#include "armada_plane.h"
#include "armada_trace.h"
+#define DEFAULT_BRIGHTNESS 0
+#define DEFAULT_CONTRAST 0x4000
+#define DEFAULT_SATURATION 0x4000
+
struct armada_ovl_plane_properties {
uint32_t colorkey_yr;
uint32_t colorkey_ug;
#define K2R(val) (((val) >> 0) & 0xff)
#define K2G(val) (((val) >> 8) & 0xff)
#define K2B(val) (((val) >> 16) & 0xff)
- int16_t brightness;
- uint16_t contrast;
- uint16_t saturation;
uint32_t colorkey_mode;
uint32_t colorkey_enable;
};
#define drm_to_armada_ovl_plane(p) \
container_of(p, struct armada_ovl_plane, base.base)
+struct armada_overlay_state {
+ struct drm_plane_state base;
+ s16 brightness;
+ u16 contrast;
+ u16 saturation;
+};
+#define drm_to_overlay_state(s) \
+ container_of(s, struct armada_overlay_state, base)
+
+static inline u32 armada_spu_contrast(struct drm_plane_state *state)
+{
+ return drm_to_overlay_state(state)->brightness << 16 |
+ drm_to_overlay_state(state)->contrast;
+}
+
+static inline u32 armada_spu_saturation(struct drm_plane_state *state)
+{
+ /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
+ return drm_to_overlay_state(state)->saturation << 16;
+}
static void
armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U);
writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V);
- writel_relaxed(prop->brightness << 16 | prop->contrast,
- dcrtc->base + LCD_SPU_CONTRAST);
- /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
- writel_relaxed(prop->saturation << 16,
- dcrtc->base + LCD_SPU_SATURATION);
- writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE);
-
spin_lock_irq(&dcrtc->irq_lock);
armada_updatel(prop->colorkey_mode,
CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
LCD_SPU_DMA_CTRL0);
+ val = armada_spu_contrast(state);
+ if ((!old_state->visible && state->visible) ||
+ armada_spu_contrast(old_state) != val)
+ armada_reg_queue_set(regs, idx, val, LCD_SPU_CONTRAST);
+ val = armada_spu_saturation(state);
+ if ((!old_state->visible && state->visible) ||
+ armada_spu_saturation(old_state) != val)
+ armada_reg_queue_set(regs, idx, val, LCD_SPU_SATURATION);
+ if (!old_state->visible && state->visible)
+ armada_reg_queue_set(regs, idx, 0x00002000, LCD_SPU_CBSH_HUE);
+
dcrtc->regs_idx += idx;
}
/* Point of no return */
swap(plane->state, state);
+ /* No CRTC, can't update */
+ if (!plane->state->crtc)
+ goto put_state;
+
dcrtc->regs_idx = 0;
dcrtc->regs = work->regs;
dplane->next_work = !dplane->next_work;
put_state:
- drm_atomic_helper_plane_destroy_state(plane, state);
+ plane->funcs->atomic_destroy_state(plane, state);
return ret;
}
src_x, src_y, src_w, src_h);
/* Construct new state for the overlay plane */
- state = drm_atomic_helper_plane_duplicate_state(plane);
+ state = plane->funcs->atomic_duplicate_state(plane);
if (!state)
return -ENOMEM;
dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
}
update_attr = true;
- } else if (property == priv->brightness_prop) {
- dplane->prop.brightness = val - 256;
- update_attr = true;
- } else if (property == priv->contrast_prop) {
- dplane->prop.contrast = val;
- update_attr = true;
- } else if (property == priv->saturation_prop) {
- dplane->prop.saturation = val;
- update_attr = true;
+ } else {
+ struct drm_plane_state *state;
+ int ret;
+
+ state = plane->funcs->atomic_duplicate_state(plane);
+ if (!state)
+ return -ENOMEM;
+
+ ret = plane->funcs->atomic_set_property(plane, state, property,
+ val);
+ if (ret) {
+ plane->funcs->atomic_destroy_state(plane, state);
+ return ret;
+ }
+
+ return armada_overlay_commit(plane, state);
}
if (update_attr && dplane->base.base.crtc)
return 0;
}
+static void armada_overlay_reset(struct drm_plane *plane)
+{
+ struct armada_overlay_state *state;
+
+ if (plane->state)
+ __drm_atomic_helper_plane_destroy_state(plane->state);
+ kfree(plane->state);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state) {
+ state->base.plane = plane;
+ state->base.rotation = DRM_MODE_ROTATE_0;
+ state->brightness = DEFAULT_BRIGHTNESS;
+ state->contrast = DEFAULT_CONTRAST;
+ state->saturation = DEFAULT_SATURATION;
+ }
+ plane->state = &state->base;
+}
+
+struct drm_plane_state *
+armada_overlay_duplicate_state(struct drm_plane *plane)
+{
+ struct armada_overlay_state *state;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
+ if (state)
+ __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
+ return &state->base;
+}
+
+static int armada_overlay_set_property(struct drm_plane *plane,
+ struct drm_plane_state *state, struct drm_property *property,
+ uint64_t val)
+{
+ struct armada_private *priv = plane->dev->dev_private;
+
+ if (property == priv->brightness_prop) {
+ drm_to_overlay_state(state)->brightness = val - 256;
+ } else if (property == priv->contrast_prop) {
+ drm_to_overlay_state(state)->contrast = val;
+ } else if (property == priv->saturation_prop) {
+ drm_to_overlay_state(state)->saturation = val;
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int armada_overlay_get_property(struct drm_plane *plane,
+ const struct drm_plane_state *state, struct drm_property *property,
+ uint64_t *val)
+{
+ struct armada_private *priv = plane->dev->dev_private;
+
+ if (property == priv->brightness_prop) {
+ *val = drm_to_overlay_state(state)->brightness + 256;
+ } else if (property == priv->contrast_prop) {
+ *val = drm_to_overlay_state(state)->contrast;
+ } else if (property == priv->saturation_prop) {
+ *val = drm_to_overlay_state(state)->saturation;
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+}
+
static const struct drm_plane_funcs armada_ovl_plane_funcs = {
.update_plane = armada_ovl_plane_update,
.disable_plane = drm_plane_helper_disable,
.destroy = armada_ovl_plane_destroy,
.set_property = armada_ovl_plane_set_property,
- .reset = drm_atomic_helper_plane_reset,
+ .reset = armada_overlay_reset,
+ .atomic_duplicate_state = armada_overlay_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+ .atomic_set_property = armada_overlay_set_property,
+ .atomic_get_property = armada_overlay_get_property,
};
static const uint32_t armada_ovl_formats[] = {
dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
CFG_ALPHAM_GRA | CFG_ALPHA(0);
dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
- dplane->prop.brightness = 0;
- dplane->prop.contrast = 0x4000;
- dplane->prop.saturation = 0x4000;
mobj = &dplane->base.base.base;
drm_object_attach_property(mobj, priv->colorkey_prop,
0x000000);
drm_object_attach_property(mobj, priv->colorkey_mode_prop,
CKMODE_RGB);
- drm_object_attach_property(mobj, priv->brightness_prop, 256);
+ drm_object_attach_property(mobj, priv->brightness_prop,
+ 256 + DEFAULT_BRIGHTNESS);
drm_object_attach_property(mobj, priv->contrast_prop,
- dplane->prop.contrast);
+ DEFAULT_CONTRAST);
drm_object_attach_property(mobj, priv->saturation_prop,
- dplane->prop.saturation);
+ DEFAULT_SATURATION);
return 0;
}