Commit 61ba2527 authored by Russell King's avatar Russell King

drm/armada: move CBSH properties into overlay plane state

Move the contrast, brightness, and saturation properties to the overlay
plane state structure, and call our overlay commit function to update
the hardware via the planes atomic_update() method.
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
parent 63b93c08
...@@ -42,7 +42,7 @@ struct armada_plane_work { ...@@ -42,7 +42,7 @@ struct armada_plane_work {
struct drm_plane *plane; struct drm_plane *plane;
struct drm_framebuffer *old_fb; struct drm_framebuffer *old_fb;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
struct armada_regs regs[14]; struct armada_regs regs[24];
}; };
struct armada_plane { struct armada_plane {
......
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
#include "armada_plane.h" #include "armada_plane.h"
#include "armada_trace.h" #include "armada_trace.h"
#define DEFAULT_BRIGHTNESS 0
#define DEFAULT_CONTRAST 0x4000
#define DEFAULT_SATURATION 0x4000
struct armada_ovl_plane_properties { struct armada_ovl_plane_properties {
uint32_t colorkey_yr; uint32_t colorkey_yr;
uint32_t colorkey_ug; uint32_t colorkey_ug;
...@@ -27,9 +31,6 @@ struct armada_ovl_plane_properties { ...@@ -27,9 +31,6 @@ struct armada_ovl_plane_properties {
#define K2R(val) (((val) >> 0) & 0xff) #define K2R(val) (((val) >> 0) & 0xff)
#define K2G(val) (((val) >> 8) & 0xff) #define K2G(val) (((val) >> 8) & 0xff)
#define K2B(val) (((val) >> 16) & 0xff) #define K2B(val) (((val) >> 16) & 0xff)
int16_t brightness;
uint16_t contrast;
uint16_t saturation;
uint32_t colorkey_mode; uint32_t colorkey_mode;
uint32_t colorkey_enable; uint32_t colorkey_enable;
}; };
...@@ -44,6 +45,26 @@ struct armada_ovl_plane { ...@@ -44,6 +45,26 @@ struct armada_ovl_plane {
#define drm_to_armada_ovl_plane(p) \ #define drm_to_armada_ovl_plane(p) \
container_of(p, struct armada_ovl_plane, base.base) 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 static void
armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
...@@ -53,13 +74,6 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, ...@@ -53,13 +74,6 @@ 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_ug, dcrtc->base + LCD_SPU_COLORKEY_U);
writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V); 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); spin_lock_irq(&dcrtc->irq_lock);
armada_updatel(prop->colorkey_mode, armada_updatel(prop->colorkey_mode,
CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
...@@ -191,6 +205,17 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane, ...@@ -191,6 +205,17 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
armada_reg_queue_mod(regs, idx, cfg, cfg_mask, armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
LCD_SPU_DMA_CTRL0); 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; dcrtc->regs_idx += idx;
} }
...@@ -264,6 +289,10 @@ static int armada_overlay_commit(struct drm_plane *plane, ...@@ -264,6 +289,10 @@ static int armada_overlay_commit(struct drm_plane *plane,
/* Point of no return */ /* Point of no return */
swap(plane->state, state); swap(plane->state, state);
/* No CRTC, can't update */
if (!plane->state->crtc)
goto put_state;
dcrtc->regs_idx = 0; dcrtc->regs_idx = 0;
dcrtc->regs = work->regs; dcrtc->regs = work->regs;
...@@ -300,7 +329,7 @@ static int armada_overlay_commit(struct drm_plane *plane, ...@@ -300,7 +329,7 @@ static int armada_overlay_commit(struct drm_plane *plane,
dplane->next_work = !dplane->next_work; dplane->next_work = !dplane->next_work;
put_state: put_state:
drm_atomic_helper_plane_destroy_state(plane, state); plane->funcs->atomic_destroy_state(plane, state);
return ret; return ret;
} }
...@@ -318,7 +347,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -318,7 +347,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
src_x, src_y, src_w, src_h); src_x, src_y, src_w, src_h);
/* Construct new state for the overlay plane */ /* Construct new state for the overlay plane */
state = drm_atomic_helper_plane_duplicate_state(plane); state = plane->funcs->atomic_duplicate_state(plane);
if (!state) if (!state)
return -ENOMEM; return -ENOMEM;
...@@ -404,15 +433,22 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane, ...@@ -404,15 +433,22 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane,
dplane->prop.colorkey_enable = ADV_GRACOLORKEY; dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
} }
update_attr = true; update_attr = true;
} else if (property == priv->brightness_prop) { } else {
dplane->prop.brightness = val - 256; struct drm_plane_state *state;
update_attr = true; int ret;
} else if (property == priv->contrast_prop) {
dplane->prop.contrast = val; state = plane->funcs->atomic_duplicate_state(plane);
update_attr = true; if (!state)
} else if (property == priv->saturation_prop) { return -ENOMEM;
dplane->prop.saturation = val;
update_attr = true; 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) if (update_attr && dplane->base.base.crtc)
...@@ -422,12 +458,85 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane, ...@@ -422,12 +458,85 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane,
return 0; 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 = { static const struct drm_plane_funcs armada_ovl_plane_funcs = {
.update_plane = armada_ovl_plane_update, .update_plane = armada_ovl_plane_update,
.disable_plane = drm_plane_helper_disable, .disable_plane = drm_plane_helper_disable,
.destroy = armada_ovl_plane_destroy, .destroy = armada_ovl_plane_destroy,
.set_property = armada_ovl_plane_set_property, .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[] = { static const uint32_t armada_ovl_formats[] = {
...@@ -542,9 +651,6 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) ...@@ -542,9 +651,6 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) | dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
CFG_ALPHAM_GRA | CFG_ALPHA(0); CFG_ALPHAM_GRA | CFG_ALPHA(0);
dplane->prop.colorkey_enable = ADV_GRACOLORKEY; dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
dplane->prop.brightness = 0;
dplane->prop.contrast = 0x4000;
dplane->prop.saturation = 0x4000;
mobj = &dplane->base.base.base; mobj = &dplane->base.base.base;
drm_object_attach_property(mobj, priv->colorkey_prop, drm_object_attach_property(mobj, priv->colorkey_prop,
...@@ -559,11 +665,12 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) ...@@ -559,11 +665,12 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
0x000000); 0x000000);
drm_object_attach_property(mobj, priv->colorkey_mode_prop, drm_object_attach_property(mobj, priv->colorkey_mode_prop,
CKMODE_RGB); 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, drm_object_attach_property(mobj, priv->contrast_prop,
dplane->prop.contrast); DEFAULT_CONTRAST);
drm_object_attach_property(mobj, priv->saturation_prop, drm_object_attach_property(mobj, priv->saturation_prop,
dplane->prop.saturation); DEFAULT_SATURATION);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment