cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

armada_overlay.c (20821B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2012 Russell King
      4 *  Rewritten from the dovefb driver, and Armada510 manuals.
      5 */
      6
      7#include <drm/armada_drm.h>
      8#include <drm/drm_atomic.h>
      9#include <drm/drm_atomic_helper.h>
     10#include <drm/drm_atomic_uapi.h>
     11#include <drm/drm_fourcc.h>
     12#include <drm/drm_plane_helper.h>
     13
     14#include "armada_crtc.h"
     15#include "armada_drm.h"
     16#include "armada_fb.h"
     17#include "armada_gem.h"
     18#include "armada_hw.h"
     19#include "armada_ioctlP.h"
     20#include "armada_plane.h"
     21#include "armada_trace.h"
     22
     23#define DEFAULT_BRIGHTNESS	0
     24#define DEFAULT_CONTRAST	0x4000
     25#define DEFAULT_SATURATION	0x4000
     26#define DEFAULT_ENCODING	DRM_COLOR_YCBCR_BT601
     27
     28struct armada_overlay_state {
     29	struct armada_plane_state base;
     30	u32 colorkey_yr;
     31	u32 colorkey_ug;
     32	u32 colorkey_vb;
     33	u32 colorkey_mode;
     34	u32 colorkey_enable;
     35	s16 brightness;
     36	u16 contrast;
     37	u16 saturation;
     38};
     39#define drm_to_overlay_state(s) \
     40	container_of(s, struct armada_overlay_state, base.base)
     41
     42static inline u32 armada_spu_contrast(struct drm_plane_state *state)
     43{
     44	return drm_to_overlay_state(state)->brightness << 16 |
     45	       drm_to_overlay_state(state)->contrast;
     46}
     47
     48static inline u32 armada_spu_saturation(struct drm_plane_state *state)
     49{
     50	/* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
     51	return drm_to_overlay_state(state)->saturation << 16;
     52}
     53
     54static inline u32 armada_csc(struct drm_plane_state *state)
     55{
     56	/*
     57	 * The CFG_CSC_RGB_* settings control the output of the colour space
     58	 * converter, setting the range of output values it produces.  Since
     59	 * we will be blending with the full-range graphics, we need to
     60	 * produce full-range RGB output from the conversion.
     61	 */
     62	return CFG_CSC_RGB_COMPUTER |
     63	       (state->color_encoding == DRM_COLOR_YCBCR_BT709 ?
     64			CFG_CSC_YUV_CCIR709 : CFG_CSC_YUV_CCIR601);
     65}
     66
     67/* === Plane support === */
     68static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
     69	struct drm_atomic_state *state)
     70{
     71	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
     72									   plane);
     73	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
     74									   plane);
     75	struct armada_crtc *dcrtc;
     76	struct armada_regs *regs;
     77	unsigned int idx;
     78	u32 cfg, cfg_mask, val;
     79
     80	DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
     81
     82	if (!new_state->fb || WARN_ON(!new_state->crtc))
     83		return;
     84
     85	DRM_DEBUG_KMS("[PLANE:%d:%s] is on [CRTC:%d:%s] with [FB:%d] visible %u->%u\n",
     86		plane->base.id, plane->name,
     87		new_state->crtc->base.id, new_state->crtc->name,
     88		new_state->fb->base.id,
     89		old_state->visible, new_state->visible);
     90
     91	dcrtc = drm_to_armada_crtc(new_state->crtc);
     92	regs = dcrtc->regs + dcrtc->regs_idx;
     93
     94	idx = 0;
     95	if (!old_state->visible && new_state->visible)
     96		armada_reg_queue_mod(regs, idx,
     97				     0, CFG_PDWN16x66 | CFG_PDWN32x66,
     98				     LCD_SPU_SRAM_PARA1);
     99	val = armada_src_hw(new_state);
    100	if (armada_src_hw(old_state) != val)
    101		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_HPXL_VLN);
    102	val = armada_dst_yx(new_state);
    103	if (armada_dst_yx(old_state) != val)
    104		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN);
    105	val = armada_dst_hw(new_state);
    106	if (armada_dst_hw(old_state) != val)
    107		armada_reg_queue_set(regs, idx, val, LCD_SPU_DZM_HPXL_VLN);
    108	/* FIXME: overlay on an interlaced display */
    109	if (old_state->src.x1 != new_state->src.x1 ||
    110	    old_state->src.y1 != new_state->src.y1 ||
    111	    old_state->fb != new_state->fb ||
    112	    new_state->crtc->state->mode_changed) {
    113		const struct drm_format_info *format;
    114		u16 src_x;
    115
    116		armada_reg_queue_set(regs, idx, armada_addr(new_state, 0, 0),
    117				     LCD_SPU_DMA_START_ADDR_Y0);
    118		armada_reg_queue_set(regs, idx, armada_addr(new_state, 0, 1),
    119				     LCD_SPU_DMA_START_ADDR_U0);
    120		armada_reg_queue_set(regs, idx, armada_addr(new_state, 0, 2),
    121				     LCD_SPU_DMA_START_ADDR_V0);
    122		armada_reg_queue_set(regs, idx, armada_addr(new_state, 1, 0),
    123				     LCD_SPU_DMA_START_ADDR_Y1);
    124		armada_reg_queue_set(regs, idx, armada_addr(new_state, 1, 1),
    125				     LCD_SPU_DMA_START_ADDR_U1);
    126		armada_reg_queue_set(regs, idx, armada_addr(new_state, 1, 2),
    127				     LCD_SPU_DMA_START_ADDR_V1);
    128
    129		val = armada_pitch(new_state, 0) << 16 | armada_pitch(new_state,
    130								      0);
    131		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_YC);
    132		val = armada_pitch(new_state, 1) << 16 | armada_pitch(new_state,
    133								      2);
    134		armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_UV);
    135
    136		cfg = CFG_DMA_FMT(drm_fb_to_armada_fb(new_state->fb)->fmt) |
    137		      CFG_DMA_MOD(drm_fb_to_armada_fb(new_state->fb)->mod) |
    138		      CFG_CBSH_ENA;
    139		if (new_state->visible)
    140			cfg |= CFG_DMA_ENA;
    141
    142		/*
    143		 * Shifting a YUV packed format image by one pixel causes the
    144		 * U/V planes to swap.  Compensate for it by also toggling
    145		 * the UV swap.
    146		 */
    147		format = new_state->fb->format;
    148		src_x = new_state->src.x1 >> 16;
    149		if (format->num_planes == 1 && src_x & (format->hsub - 1))
    150			cfg ^= CFG_DMA_MOD(CFG_SWAPUV);
    151		if (to_armada_plane_state(new_state)->interlace)
    152			cfg |= CFG_DMA_FTOGGLE;
    153		cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT |
    154			   CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV |
    155				       CFG_SWAPYU | CFG_YUV2RGB) |
    156			   CFG_DMA_FTOGGLE | CFG_DMA_TSTMODE |
    157			   CFG_DMA_ENA;
    158	} else if (old_state->visible != new_state->visible) {
    159		cfg = new_state->visible ? CFG_DMA_ENA : 0;
    160		cfg_mask = CFG_DMA_ENA;
    161	} else {
    162		cfg = cfg_mask = 0;
    163	}
    164	if (drm_rect_width(&old_state->src) != drm_rect_width(&new_state->src) ||
    165	    drm_rect_width(&old_state->dst) != drm_rect_width(&new_state->dst)) {
    166		cfg_mask |= CFG_DMA_HSMOOTH;
    167		if (drm_rect_width(&new_state->src) >> 16 !=
    168		    drm_rect_width(&new_state->dst))
    169			cfg |= CFG_DMA_HSMOOTH;
    170	}
    171
    172	if (cfg_mask)
    173		armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
    174				     LCD_SPU_DMA_CTRL0);
    175
    176	val = armada_spu_contrast(new_state);
    177	if ((!old_state->visible && new_state->visible) ||
    178	    armada_spu_contrast(old_state) != val)
    179		armada_reg_queue_set(regs, idx, val, LCD_SPU_CONTRAST);
    180	val = armada_spu_saturation(new_state);
    181	if ((!old_state->visible && new_state->visible) ||
    182	    armada_spu_saturation(old_state) != val)
    183		armada_reg_queue_set(regs, idx, val, LCD_SPU_SATURATION);
    184	if (!old_state->visible && new_state->visible)
    185		armada_reg_queue_set(regs, idx, 0x00002000, LCD_SPU_CBSH_HUE);
    186	val = armada_csc(new_state);
    187	if ((!old_state->visible && new_state->visible) ||
    188	    armada_csc(old_state) != val)
    189		armada_reg_queue_mod(regs, idx, val, CFG_CSC_MASK,
    190				     LCD_SPU_IOPAD_CONTROL);
    191	val = drm_to_overlay_state(new_state)->colorkey_yr;
    192	if ((!old_state->visible && new_state->visible) ||
    193	    drm_to_overlay_state(old_state)->colorkey_yr != val)
    194		armada_reg_queue_set(regs, idx, val, LCD_SPU_COLORKEY_Y);
    195	val = drm_to_overlay_state(new_state)->colorkey_ug;
    196	if ((!old_state->visible && new_state->visible) ||
    197	    drm_to_overlay_state(old_state)->colorkey_ug != val)
    198		armada_reg_queue_set(regs, idx, val, LCD_SPU_COLORKEY_U);
    199	val = drm_to_overlay_state(new_state)->colorkey_vb;
    200	if ((!old_state->visible && new_state->visible) ||
    201	    drm_to_overlay_state(old_state)->colorkey_vb != val)
    202		armada_reg_queue_set(regs, idx, val, LCD_SPU_COLORKEY_V);
    203	val = drm_to_overlay_state(new_state)->colorkey_mode;
    204	if ((!old_state->visible && new_state->visible) ||
    205	    drm_to_overlay_state(old_state)->colorkey_mode != val)
    206		armada_reg_queue_mod(regs, idx, val, CFG_CKMODE_MASK |
    207				     CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
    208				     LCD_SPU_DMA_CTRL1);
    209	val = drm_to_overlay_state(new_state)->colorkey_enable;
    210	if (((!old_state->visible && new_state->visible) ||
    211	     drm_to_overlay_state(old_state)->colorkey_enable != val) &&
    212	    dcrtc->variant->has_spu_adv_reg)
    213		armada_reg_queue_mod(regs, idx, val, ADV_GRACOLORKEY |
    214				     ADV_VIDCOLORKEY, LCD_SPU_ADV_REG);
    215
    216	dcrtc->regs_idx += idx;
    217}
    218
    219static void armada_drm_overlay_plane_atomic_disable(struct drm_plane *plane,
    220	struct drm_atomic_state *state)
    221{
    222	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
    223									   plane);
    224	struct armada_crtc *dcrtc;
    225	struct armada_regs *regs;
    226	unsigned int idx = 0;
    227
    228	DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
    229
    230	if (!old_state->crtc)
    231		return;
    232
    233	DRM_DEBUG_KMS("[PLANE:%d:%s] was on [CRTC:%d:%s] with [FB:%d]\n",
    234		plane->base.id, plane->name,
    235		old_state->crtc->base.id, old_state->crtc->name,
    236		old_state->fb->base.id);
    237
    238	dcrtc = drm_to_armada_crtc(old_state->crtc);
    239	regs = dcrtc->regs + dcrtc->regs_idx;
    240
    241	/* Disable plane and power down the YUV FIFOs */
    242	armada_reg_queue_mod(regs, idx, 0, CFG_DMA_ENA, LCD_SPU_DMA_CTRL0);
    243	armada_reg_queue_mod(regs, idx, CFG_PDWN16x66 | CFG_PDWN32x66, 0,
    244			     LCD_SPU_SRAM_PARA1);
    245
    246	dcrtc->regs_idx += idx;
    247}
    248
    249static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = {
    250	.atomic_check	= armada_drm_plane_atomic_check,
    251	.atomic_update	= armada_drm_overlay_plane_atomic_update,
    252	.atomic_disable	= armada_drm_overlay_plane_atomic_disable,
    253};
    254
    255static int
    256armada_overlay_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
    257	struct drm_framebuffer *fb,
    258	int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
    259	uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
    260	struct drm_modeset_acquire_ctx *ctx)
    261{
    262	struct drm_atomic_state *state;
    263	struct drm_plane_state *plane_state;
    264	int ret = 0;
    265
    266	trace_armada_ovl_plane_update(plane, crtc, fb,
    267				 crtc_x, crtc_y, crtc_w, crtc_h,
    268				 src_x, src_y, src_w, src_h);
    269
    270	state = drm_atomic_state_alloc(plane->dev);
    271	if (!state)
    272		return -ENOMEM;
    273
    274	state->acquire_ctx = ctx;
    275	plane_state = drm_atomic_get_plane_state(state, plane);
    276	if (IS_ERR(plane_state)) {
    277		ret = PTR_ERR(plane_state);
    278		goto fail;
    279	}
    280
    281	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
    282	if (ret != 0)
    283		goto fail;
    284
    285	drm_atomic_set_fb_for_plane(plane_state, fb);
    286	plane_state->crtc_x = crtc_x;
    287	plane_state->crtc_y = crtc_y;
    288	plane_state->crtc_h = crtc_h;
    289	plane_state->crtc_w = crtc_w;
    290	plane_state->src_x = src_x;
    291	plane_state->src_y = src_y;
    292	plane_state->src_h = src_h;
    293	plane_state->src_w = src_w;
    294
    295	ret = drm_atomic_nonblocking_commit(state);
    296fail:
    297	drm_atomic_state_put(state);
    298	return ret;
    299}
    300
    301static void armada_ovl_plane_destroy(struct drm_plane *plane)
    302{
    303	drm_plane_cleanup(plane);
    304	kfree(plane);
    305}
    306
    307static void armada_overlay_reset(struct drm_plane *plane)
    308{
    309	struct armada_overlay_state *state;
    310
    311	if (plane->state)
    312		__drm_atomic_helper_plane_destroy_state(plane->state);
    313	kfree(plane->state);
    314	plane->state = NULL;
    315
    316	state = kzalloc(sizeof(*state), GFP_KERNEL);
    317	if (state) {
    318		state->colorkey_yr = 0xfefefe00;
    319		state->colorkey_ug = 0x01010100;
    320		state->colorkey_vb = 0x01010100;
    321		state->colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
    322				       CFG_ALPHAM_GRA | CFG_ALPHA(0);
    323		state->colorkey_enable = ADV_GRACOLORKEY;
    324		state->brightness = DEFAULT_BRIGHTNESS;
    325		state->contrast = DEFAULT_CONTRAST;
    326		state->saturation = DEFAULT_SATURATION;
    327		__drm_atomic_helper_plane_reset(plane, &state->base.base);
    328		state->base.base.color_encoding = DEFAULT_ENCODING;
    329		state->base.base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
    330	}
    331}
    332
    333static struct drm_plane_state *
    334armada_overlay_duplicate_state(struct drm_plane *plane)
    335{
    336	struct armada_overlay_state *state;
    337
    338	if (WARN_ON(!plane->state))
    339		return NULL;
    340
    341	state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
    342	if (state)
    343		__drm_atomic_helper_plane_duplicate_state(plane,
    344							  &state->base.base);
    345	return &state->base.base;
    346}
    347
    348static int armada_overlay_set_property(struct drm_plane *plane,
    349	struct drm_plane_state *state, struct drm_property *property,
    350	uint64_t val)
    351{
    352	struct armada_private *priv = drm_to_armada_dev(plane->dev);
    353
    354#define K2R(val) (((val) >> 0) & 0xff)
    355#define K2G(val) (((val) >> 8) & 0xff)
    356#define K2B(val) (((val) >> 16) & 0xff)
    357	if (property == priv->colorkey_prop) {
    358#define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8)
    359		drm_to_overlay_state(state)->colorkey_yr = CCC(K2R(val));
    360		drm_to_overlay_state(state)->colorkey_ug = CCC(K2G(val));
    361		drm_to_overlay_state(state)->colorkey_vb = CCC(K2B(val));
    362#undef CCC
    363	} else if (property == priv->colorkey_min_prop) {
    364		drm_to_overlay_state(state)->colorkey_yr &= ~0x00ff0000;
    365		drm_to_overlay_state(state)->colorkey_yr |= K2R(val) << 16;
    366		drm_to_overlay_state(state)->colorkey_ug &= ~0x00ff0000;
    367		drm_to_overlay_state(state)->colorkey_ug |= K2G(val) << 16;
    368		drm_to_overlay_state(state)->colorkey_vb &= ~0x00ff0000;
    369		drm_to_overlay_state(state)->colorkey_vb |= K2B(val) << 16;
    370	} else if (property == priv->colorkey_max_prop) {
    371		drm_to_overlay_state(state)->colorkey_yr &= ~0xff000000;
    372		drm_to_overlay_state(state)->colorkey_yr |= K2R(val) << 24;
    373		drm_to_overlay_state(state)->colorkey_ug &= ~0xff000000;
    374		drm_to_overlay_state(state)->colorkey_ug |= K2G(val) << 24;
    375		drm_to_overlay_state(state)->colorkey_vb &= ~0xff000000;
    376		drm_to_overlay_state(state)->colorkey_vb |= K2B(val) << 24;
    377	} else if (property == priv->colorkey_val_prop) {
    378		drm_to_overlay_state(state)->colorkey_yr &= ~0x0000ff00;
    379		drm_to_overlay_state(state)->colorkey_yr |= K2R(val) << 8;
    380		drm_to_overlay_state(state)->colorkey_ug &= ~0x0000ff00;
    381		drm_to_overlay_state(state)->colorkey_ug |= K2G(val) << 8;
    382		drm_to_overlay_state(state)->colorkey_vb &= ~0x0000ff00;
    383		drm_to_overlay_state(state)->colorkey_vb |= K2B(val) << 8;
    384	} else if (property == priv->colorkey_alpha_prop) {
    385		drm_to_overlay_state(state)->colorkey_yr &= ~0x000000ff;
    386		drm_to_overlay_state(state)->colorkey_yr |= K2R(val);
    387		drm_to_overlay_state(state)->colorkey_ug &= ~0x000000ff;
    388		drm_to_overlay_state(state)->colorkey_ug |= K2G(val);
    389		drm_to_overlay_state(state)->colorkey_vb &= ~0x000000ff;
    390		drm_to_overlay_state(state)->colorkey_vb |= K2B(val);
    391	} else if (property == priv->colorkey_mode_prop) {
    392		if (val == CKMODE_DISABLE) {
    393			drm_to_overlay_state(state)->colorkey_mode =
    394				CFG_CKMODE(CKMODE_DISABLE) |
    395				CFG_ALPHAM_CFG | CFG_ALPHA(255);
    396			drm_to_overlay_state(state)->colorkey_enable = 0;
    397		} else {
    398			drm_to_overlay_state(state)->colorkey_mode =
    399				CFG_CKMODE(val) |
    400				CFG_ALPHAM_GRA | CFG_ALPHA(0);
    401			drm_to_overlay_state(state)->colorkey_enable =
    402				ADV_GRACOLORKEY;
    403		}
    404	} else if (property == priv->brightness_prop) {
    405		drm_to_overlay_state(state)->brightness = val - 256;
    406	} else if (property == priv->contrast_prop) {
    407		drm_to_overlay_state(state)->contrast = val;
    408	} else if (property == priv->saturation_prop) {
    409		drm_to_overlay_state(state)->saturation = val;
    410	} else {
    411		return -EINVAL;
    412	}
    413	return 0;
    414}
    415
    416static int armada_overlay_get_property(struct drm_plane *plane,
    417	const struct drm_plane_state *state, struct drm_property *property,
    418	uint64_t *val)
    419{
    420	struct armada_private *priv = drm_to_armada_dev(plane->dev);
    421
    422#define C2K(c,s)	(((c) >> (s)) & 0xff)
    423#define R2BGR(r,g,b,s)	(C2K(r,s) << 0 | C2K(g,s) << 8 | C2K(b,s) << 16)
    424	if (property == priv->colorkey_prop) {
    425		/* Do best-efforts here for this property */
    426		*val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    427			     drm_to_overlay_state(state)->colorkey_ug,
    428			     drm_to_overlay_state(state)->colorkey_vb, 16);
    429		/* If min != max, or min != val, error out */
    430		if (*val != R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    431				  drm_to_overlay_state(state)->colorkey_ug,
    432				  drm_to_overlay_state(state)->colorkey_vb, 24) ||
    433		    *val != R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    434				  drm_to_overlay_state(state)->colorkey_ug,
    435				  drm_to_overlay_state(state)->colorkey_vb, 8))
    436			return -EINVAL;
    437	} else if (property == priv->colorkey_min_prop) {
    438		*val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    439			     drm_to_overlay_state(state)->colorkey_ug,
    440			     drm_to_overlay_state(state)->colorkey_vb, 16);
    441	} else if (property == priv->colorkey_max_prop) {
    442		*val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    443			     drm_to_overlay_state(state)->colorkey_ug,
    444			     drm_to_overlay_state(state)->colorkey_vb, 24);
    445	} else if (property == priv->colorkey_val_prop) {
    446		*val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    447			     drm_to_overlay_state(state)->colorkey_ug,
    448			     drm_to_overlay_state(state)->colorkey_vb, 8);
    449	} else if (property == priv->colorkey_alpha_prop) {
    450		*val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
    451			     drm_to_overlay_state(state)->colorkey_ug,
    452			     drm_to_overlay_state(state)->colorkey_vb, 0);
    453	} else if (property == priv->colorkey_mode_prop) {
    454		*val = (drm_to_overlay_state(state)->colorkey_mode &
    455			CFG_CKMODE_MASK) >> ffs(CFG_CKMODE_MASK);
    456	} else if (property == priv->brightness_prop) {
    457		*val = drm_to_overlay_state(state)->brightness + 256;
    458	} else if (property == priv->contrast_prop) {
    459		*val = drm_to_overlay_state(state)->contrast;
    460	} else if (property == priv->saturation_prop) {
    461		*val = drm_to_overlay_state(state)->saturation;
    462	} else {
    463		return -EINVAL;
    464	}
    465	return 0;
    466}
    467
    468static const struct drm_plane_funcs armada_ovl_plane_funcs = {
    469	.update_plane	= armada_overlay_plane_update,
    470	.disable_plane	= drm_atomic_helper_disable_plane,
    471	.destroy	= armada_ovl_plane_destroy,
    472	.reset		= armada_overlay_reset,
    473	.atomic_duplicate_state = armada_overlay_duplicate_state,
    474	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
    475	.atomic_set_property = armada_overlay_set_property,
    476	.atomic_get_property = armada_overlay_get_property,
    477};
    478
    479static const uint32_t armada_ovl_formats[] = {
    480	DRM_FORMAT_UYVY,
    481	DRM_FORMAT_YUYV,
    482	DRM_FORMAT_YUV420,
    483	DRM_FORMAT_YVU420,
    484	DRM_FORMAT_YUV422,
    485	DRM_FORMAT_YVU422,
    486	DRM_FORMAT_VYUY,
    487	DRM_FORMAT_YVYU,
    488	DRM_FORMAT_ARGB8888,
    489	DRM_FORMAT_ABGR8888,
    490	DRM_FORMAT_XRGB8888,
    491	DRM_FORMAT_XBGR8888,
    492	DRM_FORMAT_RGB888,
    493	DRM_FORMAT_BGR888,
    494	DRM_FORMAT_ARGB1555,
    495	DRM_FORMAT_ABGR1555,
    496	DRM_FORMAT_RGB565,
    497	DRM_FORMAT_BGR565,
    498};
    499
    500static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = {
    501	{ CKMODE_DISABLE, "disabled" },
    502	{ CKMODE_Y,       "Y component" },
    503	{ CKMODE_U,       "U component" },
    504	{ CKMODE_V,       "V component" },
    505	{ CKMODE_RGB,     "RGB" },
    506	{ CKMODE_R,       "R component" },
    507	{ CKMODE_G,       "G component" },
    508	{ CKMODE_B,       "B component" },
    509};
    510
    511static int armada_overlay_create_properties(struct drm_device *dev)
    512{
    513	struct armada_private *priv = drm_to_armada_dev(dev);
    514
    515	if (priv->colorkey_prop)
    516		return 0;
    517
    518	priv->colorkey_prop = drm_property_create_range(dev, 0,
    519				"colorkey", 0, 0xffffff);
    520	priv->colorkey_min_prop = drm_property_create_range(dev, 0,
    521				"colorkey_min", 0, 0xffffff);
    522	priv->colorkey_max_prop = drm_property_create_range(dev, 0,
    523				"colorkey_max", 0, 0xffffff);
    524	priv->colorkey_val_prop = drm_property_create_range(dev, 0,
    525				"colorkey_val", 0, 0xffffff);
    526	priv->colorkey_alpha_prop = drm_property_create_range(dev, 0,
    527				"colorkey_alpha", 0, 0xffffff);
    528	priv->colorkey_mode_prop = drm_property_create_enum(dev, 0,
    529				"colorkey_mode",
    530				armada_drm_colorkey_enum_list,
    531				ARRAY_SIZE(armada_drm_colorkey_enum_list));
    532	priv->brightness_prop = drm_property_create_range(dev, 0,
    533				"brightness", 0, 256 + 255);
    534	priv->contrast_prop = drm_property_create_range(dev, 0,
    535				"contrast", 0, 0x7fff);
    536	priv->saturation_prop = drm_property_create_range(dev, 0,
    537				"saturation", 0, 0x7fff);
    538
    539	if (!priv->colorkey_prop)
    540		return -ENOMEM;
    541
    542	return 0;
    543}
    544
    545int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
    546{
    547	struct armada_private *priv = drm_to_armada_dev(dev);
    548	struct drm_mode_object *mobj;
    549	struct drm_plane *overlay;
    550	int ret;
    551
    552	ret = armada_overlay_create_properties(dev);
    553	if (ret)
    554		return ret;
    555
    556	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
    557	if (!overlay)
    558		return -ENOMEM;
    559
    560	drm_plane_helper_add(overlay, &armada_overlay_plane_helper_funcs);
    561
    562	ret = drm_universal_plane_init(dev, overlay, crtcs,
    563				       &armada_ovl_plane_funcs,
    564				       armada_ovl_formats,
    565				       ARRAY_SIZE(armada_ovl_formats),
    566				       NULL,
    567				       DRM_PLANE_TYPE_OVERLAY, NULL);
    568	if (ret) {
    569		kfree(overlay);
    570		return ret;
    571	}
    572
    573	mobj = &overlay->base;
    574	drm_object_attach_property(mobj, priv->colorkey_prop,
    575				   0x0101fe);
    576	drm_object_attach_property(mobj, priv->colorkey_min_prop,
    577				   0x0101fe);
    578	drm_object_attach_property(mobj, priv->colorkey_max_prop,
    579				   0x0101fe);
    580	drm_object_attach_property(mobj, priv->colorkey_val_prop,
    581				   0x0101fe);
    582	drm_object_attach_property(mobj, priv->colorkey_alpha_prop,
    583				   0x000000);
    584	drm_object_attach_property(mobj, priv->colorkey_mode_prop,
    585				   CKMODE_RGB);
    586	drm_object_attach_property(mobj, priv->brightness_prop,
    587				   256 + DEFAULT_BRIGHTNESS);
    588	drm_object_attach_property(mobj, priv->contrast_prop,
    589				   DEFAULT_CONTRAST);
    590	drm_object_attach_property(mobj, priv->saturation_prop,
    591				   DEFAULT_SATURATION);
    592
    593	ret = drm_plane_create_color_properties(overlay,
    594						BIT(DRM_COLOR_YCBCR_BT601) |
    595						BIT(DRM_COLOR_YCBCR_BT709),
    596						BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
    597						DEFAULT_ENCODING,
    598						DRM_COLOR_YCBCR_LIMITED_RANGE);
    599
    600	return ret;
    601}