0001
0002
0003
0004
0005
0006
0007 #include <drm/armada_drm.h>
0008 #include <drm/drm_atomic.h>
0009 #include <drm/drm_atomic_helper.h>
0010 #include <drm/drm_atomic_uapi.h>
0011 #include <drm/drm_fourcc.h>
0012 #include <drm/drm_plane_helper.h>
0013
0014 #include "armada_crtc.h"
0015 #include "armada_drm.h"
0016 #include "armada_fb.h"
0017 #include "armada_gem.h"
0018 #include "armada_hw.h"
0019 #include "armada_ioctlP.h"
0020 #include "armada_plane.h"
0021 #include "armada_trace.h"
0022
0023 #define DEFAULT_BRIGHTNESS 0
0024 #define DEFAULT_CONTRAST 0x4000
0025 #define DEFAULT_SATURATION 0x4000
0026 #define DEFAULT_ENCODING DRM_COLOR_YCBCR_BT601
0027
0028 struct armada_overlay_state {
0029 struct armada_plane_state base;
0030 u32 colorkey_yr;
0031 u32 colorkey_ug;
0032 u32 colorkey_vb;
0033 u32 colorkey_mode;
0034 u32 colorkey_enable;
0035 s16 brightness;
0036 u16 contrast;
0037 u16 saturation;
0038 };
0039 #define drm_to_overlay_state(s) \
0040 container_of(s, struct armada_overlay_state, base.base)
0041
0042 static inline u32 armada_spu_contrast(struct drm_plane_state *state)
0043 {
0044 return drm_to_overlay_state(state)->brightness << 16 |
0045 drm_to_overlay_state(state)->contrast;
0046 }
0047
0048 static inline u32 armada_spu_saturation(struct drm_plane_state *state)
0049 {
0050
0051 return drm_to_overlay_state(state)->saturation << 16;
0052 }
0053
0054 static inline u32 armada_csc(struct drm_plane_state *state)
0055 {
0056
0057
0058
0059
0060
0061
0062 return CFG_CSC_RGB_COMPUTER |
0063 (state->color_encoding == DRM_COLOR_YCBCR_BT709 ?
0064 CFG_CSC_YUV_CCIR709 : CFG_CSC_YUV_CCIR601);
0065 }
0066
0067
0068 static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
0069 struct drm_atomic_state *state)
0070 {
0071 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
0072 plane);
0073 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0074 plane);
0075 struct armada_crtc *dcrtc;
0076 struct armada_regs *regs;
0077 unsigned int idx;
0078 u32 cfg, cfg_mask, val;
0079
0080 DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
0081
0082 if (!new_state->fb || WARN_ON(!new_state->crtc))
0083 return;
0084
0085 DRM_DEBUG_KMS("[PLANE:%d:%s] is on [CRTC:%d:%s] with [FB:%d] visible %u->%u\n",
0086 plane->base.id, plane->name,
0087 new_state->crtc->base.id, new_state->crtc->name,
0088 new_state->fb->base.id,
0089 old_state->visible, new_state->visible);
0090
0091 dcrtc = drm_to_armada_crtc(new_state->crtc);
0092 regs = dcrtc->regs + dcrtc->regs_idx;
0093
0094 idx = 0;
0095 if (!old_state->visible && new_state->visible)
0096 armada_reg_queue_mod(regs, idx,
0097 0, CFG_PDWN16x66 | CFG_PDWN32x66,
0098 LCD_SPU_SRAM_PARA1);
0099 val = armada_src_hw(new_state);
0100 if (armada_src_hw(old_state) != val)
0101 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_HPXL_VLN);
0102 val = armada_dst_yx(new_state);
0103 if (armada_dst_yx(old_state) != val)
0104 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN);
0105 val = armada_dst_hw(new_state);
0106 if (armada_dst_hw(old_state) != val)
0107 armada_reg_queue_set(regs, idx, val, LCD_SPU_DZM_HPXL_VLN);
0108
0109 if (old_state->src.x1 != new_state->src.x1 ||
0110 old_state->src.y1 != new_state->src.y1 ||
0111 old_state->fb != new_state->fb ||
0112 new_state->crtc->state->mode_changed) {
0113 const struct drm_format_info *format;
0114 u16 src_x;
0115
0116 armada_reg_queue_set(regs, idx, armada_addr(new_state, 0, 0),
0117 LCD_SPU_DMA_START_ADDR_Y0);
0118 armada_reg_queue_set(regs, idx, armada_addr(new_state, 0, 1),
0119 LCD_SPU_DMA_START_ADDR_U0);
0120 armada_reg_queue_set(regs, idx, armada_addr(new_state, 0, 2),
0121 LCD_SPU_DMA_START_ADDR_V0);
0122 armada_reg_queue_set(regs, idx, armada_addr(new_state, 1, 0),
0123 LCD_SPU_DMA_START_ADDR_Y1);
0124 armada_reg_queue_set(regs, idx, armada_addr(new_state, 1, 1),
0125 LCD_SPU_DMA_START_ADDR_U1);
0126 armada_reg_queue_set(regs, idx, armada_addr(new_state, 1, 2),
0127 LCD_SPU_DMA_START_ADDR_V1);
0128
0129 val = armada_pitch(new_state, 0) << 16 | armada_pitch(new_state,
0130 0);
0131 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_YC);
0132 val = armada_pitch(new_state, 1) << 16 | armada_pitch(new_state,
0133 2);
0134 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_UV);
0135
0136 cfg = CFG_DMA_FMT(drm_fb_to_armada_fb(new_state->fb)->fmt) |
0137 CFG_DMA_MOD(drm_fb_to_armada_fb(new_state->fb)->mod) |
0138 CFG_CBSH_ENA;
0139 if (new_state->visible)
0140 cfg |= CFG_DMA_ENA;
0141
0142
0143
0144
0145
0146
0147 format = new_state->fb->format;
0148 src_x = new_state->src.x1 >> 16;
0149 if (format->num_planes == 1 && src_x & (format->hsub - 1))
0150 cfg ^= CFG_DMA_MOD(CFG_SWAPUV);
0151 if (to_armada_plane_state(new_state)->interlace)
0152 cfg |= CFG_DMA_FTOGGLE;
0153 cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT |
0154 CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV |
0155 CFG_SWAPYU | CFG_YUV2RGB) |
0156 CFG_DMA_FTOGGLE | CFG_DMA_TSTMODE |
0157 CFG_DMA_ENA;
0158 } else if (old_state->visible != new_state->visible) {
0159 cfg = new_state->visible ? CFG_DMA_ENA : 0;
0160 cfg_mask = CFG_DMA_ENA;
0161 } else {
0162 cfg = cfg_mask = 0;
0163 }
0164 if (drm_rect_width(&old_state->src) != drm_rect_width(&new_state->src) ||
0165 drm_rect_width(&old_state->dst) != drm_rect_width(&new_state->dst)) {
0166 cfg_mask |= CFG_DMA_HSMOOTH;
0167 if (drm_rect_width(&new_state->src) >> 16 !=
0168 drm_rect_width(&new_state->dst))
0169 cfg |= CFG_DMA_HSMOOTH;
0170 }
0171
0172 if (cfg_mask)
0173 armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
0174 LCD_SPU_DMA_CTRL0);
0175
0176 val = armada_spu_contrast(new_state);
0177 if ((!old_state->visible && new_state->visible) ||
0178 armada_spu_contrast(old_state) != val)
0179 armada_reg_queue_set(regs, idx, val, LCD_SPU_CONTRAST);
0180 val = armada_spu_saturation(new_state);
0181 if ((!old_state->visible && new_state->visible) ||
0182 armada_spu_saturation(old_state) != val)
0183 armada_reg_queue_set(regs, idx, val, LCD_SPU_SATURATION);
0184 if (!old_state->visible && new_state->visible)
0185 armada_reg_queue_set(regs, idx, 0x00002000, LCD_SPU_CBSH_HUE);
0186 val = armada_csc(new_state);
0187 if ((!old_state->visible && new_state->visible) ||
0188 armada_csc(old_state) != val)
0189 armada_reg_queue_mod(regs, idx, val, CFG_CSC_MASK,
0190 LCD_SPU_IOPAD_CONTROL);
0191 val = drm_to_overlay_state(new_state)->colorkey_yr;
0192 if ((!old_state->visible && new_state->visible) ||
0193 drm_to_overlay_state(old_state)->colorkey_yr != val)
0194 armada_reg_queue_set(regs, idx, val, LCD_SPU_COLORKEY_Y);
0195 val = drm_to_overlay_state(new_state)->colorkey_ug;
0196 if ((!old_state->visible && new_state->visible) ||
0197 drm_to_overlay_state(old_state)->colorkey_ug != val)
0198 armada_reg_queue_set(regs, idx, val, LCD_SPU_COLORKEY_U);
0199 val = drm_to_overlay_state(new_state)->colorkey_vb;
0200 if ((!old_state->visible && new_state->visible) ||
0201 drm_to_overlay_state(old_state)->colorkey_vb != val)
0202 armada_reg_queue_set(regs, idx, val, LCD_SPU_COLORKEY_V);
0203 val = drm_to_overlay_state(new_state)->colorkey_mode;
0204 if ((!old_state->visible && new_state->visible) ||
0205 drm_to_overlay_state(old_state)->colorkey_mode != val)
0206 armada_reg_queue_mod(regs, idx, val, CFG_CKMODE_MASK |
0207 CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
0208 LCD_SPU_DMA_CTRL1);
0209 val = drm_to_overlay_state(new_state)->colorkey_enable;
0210 if (((!old_state->visible && new_state->visible) ||
0211 drm_to_overlay_state(old_state)->colorkey_enable != val) &&
0212 dcrtc->variant->has_spu_adv_reg)
0213 armada_reg_queue_mod(regs, idx, val, ADV_GRACOLORKEY |
0214 ADV_VIDCOLORKEY, LCD_SPU_ADV_REG);
0215
0216 dcrtc->regs_idx += idx;
0217 }
0218
0219 static void armada_drm_overlay_plane_atomic_disable(struct drm_plane *plane,
0220 struct drm_atomic_state *state)
0221 {
0222 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
0223 plane);
0224 struct armada_crtc *dcrtc;
0225 struct armada_regs *regs;
0226 unsigned int idx = 0;
0227
0228 DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
0229
0230 if (!old_state->crtc)
0231 return;
0232
0233 DRM_DEBUG_KMS("[PLANE:%d:%s] was on [CRTC:%d:%s] with [FB:%d]\n",
0234 plane->base.id, plane->name,
0235 old_state->crtc->base.id, old_state->crtc->name,
0236 old_state->fb->base.id);
0237
0238 dcrtc = drm_to_armada_crtc(old_state->crtc);
0239 regs = dcrtc->regs + dcrtc->regs_idx;
0240
0241
0242 armada_reg_queue_mod(regs, idx, 0, CFG_DMA_ENA, LCD_SPU_DMA_CTRL0);
0243 armada_reg_queue_mod(regs, idx, CFG_PDWN16x66 | CFG_PDWN32x66, 0,
0244 LCD_SPU_SRAM_PARA1);
0245
0246 dcrtc->regs_idx += idx;
0247 }
0248
0249 static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = {
0250 .atomic_check = armada_drm_plane_atomic_check,
0251 .atomic_update = armada_drm_overlay_plane_atomic_update,
0252 .atomic_disable = armada_drm_overlay_plane_atomic_disable,
0253 };
0254
0255 static int
0256 armada_overlay_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
0257 struct drm_framebuffer *fb,
0258 int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
0259 uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
0260 struct drm_modeset_acquire_ctx *ctx)
0261 {
0262 struct drm_atomic_state *state;
0263 struct drm_plane_state *plane_state;
0264 int ret = 0;
0265
0266 trace_armada_ovl_plane_update(plane, crtc, fb,
0267 crtc_x, crtc_y, crtc_w, crtc_h,
0268 src_x, src_y, src_w, src_h);
0269
0270 state = drm_atomic_state_alloc(plane->dev);
0271 if (!state)
0272 return -ENOMEM;
0273
0274 state->acquire_ctx = ctx;
0275 plane_state = drm_atomic_get_plane_state(state, plane);
0276 if (IS_ERR(plane_state)) {
0277 ret = PTR_ERR(plane_state);
0278 goto fail;
0279 }
0280
0281 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
0282 if (ret != 0)
0283 goto fail;
0284
0285 drm_atomic_set_fb_for_plane(plane_state, fb);
0286 plane_state->crtc_x = crtc_x;
0287 plane_state->crtc_y = crtc_y;
0288 plane_state->crtc_h = crtc_h;
0289 plane_state->crtc_w = crtc_w;
0290 plane_state->src_x = src_x;
0291 plane_state->src_y = src_y;
0292 plane_state->src_h = src_h;
0293 plane_state->src_w = src_w;
0294
0295 ret = drm_atomic_nonblocking_commit(state);
0296 fail:
0297 drm_atomic_state_put(state);
0298 return ret;
0299 }
0300
0301 static void armada_ovl_plane_destroy(struct drm_plane *plane)
0302 {
0303 drm_plane_cleanup(plane);
0304 kfree(plane);
0305 }
0306
0307 static void armada_overlay_reset(struct drm_plane *plane)
0308 {
0309 struct armada_overlay_state *state;
0310
0311 if (plane->state)
0312 __drm_atomic_helper_plane_destroy_state(plane->state);
0313 kfree(plane->state);
0314 plane->state = NULL;
0315
0316 state = kzalloc(sizeof(*state), GFP_KERNEL);
0317 if (state) {
0318 state->colorkey_yr = 0xfefefe00;
0319 state->colorkey_ug = 0x01010100;
0320 state->colorkey_vb = 0x01010100;
0321 state->colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
0322 CFG_ALPHAM_GRA | CFG_ALPHA(0);
0323 state->colorkey_enable = ADV_GRACOLORKEY;
0324 state->brightness = DEFAULT_BRIGHTNESS;
0325 state->contrast = DEFAULT_CONTRAST;
0326 state->saturation = DEFAULT_SATURATION;
0327 __drm_atomic_helper_plane_reset(plane, &state->base.base);
0328 state->base.base.color_encoding = DEFAULT_ENCODING;
0329 state->base.base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
0330 }
0331 }
0332
0333 static struct drm_plane_state *
0334 armada_overlay_duplicate_state(struct drm_plane *plane)
0335 {
0336 struct armada_overlay_state *state;
0337
0338 if (WARN_ON(!plane->state))
0339 return NULL;
0340
0341 state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
0342 if (state)
0343 __drm_atomic_helper_plane_duplicate_state(plane,
0344 &state->base.base);
0345 return &state->base.base;
0346 }
0347
0348 static int armada_overlay_set_property(struct drm_plane *plane,
0349 struct drm_plane_state *state, struct drm_property *property,
0350 uint64_t val)
0351 {
0352 struct armada_private *priv = drm_to_armada_dev(plane->dev);
0353
0354 #define K2R(val) (((val) >> 0) & 0xff)
0355 #define K2G(val) (((val) >> 8) & 0xff)
0356 #define K2B(val) (((val) >> 16) & 0xff)
0357 if (property == priv->colorkey_prop) {
0358 #define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8)
0359 drm_to_overlay_state(state)->colorkey_yr = CCC(K2R(val));
0360 drm_to_overlay_state(state)->colorkey_ug = CCC(K2G(val));
0361 drm_to_overlay_state(state)->colorkey_vb = CCC(K2B(val));
0362 #undef CCC
0363 } else if (property == priv->colorkey_min_prop) {
0364 drm_to_overlay_state(state)->colorkey_yr &= ~0x00ff0000;
0365 drm_to_overlay_state(state)->colorkey_yr |= K2R(val) << 16;
0366 drm_to_overlay_state(state)->colorkey_ug &= ~0x00ff0000;
0367 drm_to_overlay_state(state)->colorkey_ug |= K2G(val) << 16;
0368 drm_to_overlay_state(state)->colorkey_vb &= ~0x00ff0000;
0369 drm_to_overlay_state(state)->colorkey_vb |= K2B(val) << 16;
0370 } else if (property == priv->colorkey_max_prop) {
0371 drm_to_overlay_state(state)->colorkey_yr &= ~0xff000000;
0372 drm_to_overlay_state(state)->colorkey_yr |= K2R(val) << 24;
0373 drm_to_overlay_state(state)->colorkey_ug &= ~0xff000000;
0374 drm_to_overlay_state(state)->colorkey_ug |= K2G(val) << 24;
0375 drm_to_overlay_state(state)->colorkey_vb &= ~0xff000000;
0376 drm_to_overlay_state(state)->colorkey_vb |= K2B(val) << 24;
0377 } else if (property == priv->colorkey_val_prop) {
0378 drm_to_overlay_state(state)->colorkey_yr &= ~0x0000ff00;
0379 drm_to_overlay_state(state)->colorkey_yr |= K2R(val) << 8;
0380 drm_to_overlay_state(state)->colorkey_ug &= ~0x0000ff00;
0381 drm_to_overlay_state(state)->colorkey_ug |= K2G(val) << 8;
0382 drm_to_overlay_state(state)->colorkey_vb &= ~0x0000ff00;
0383 drm_to_overlay_state(state)->colorkey_vb |= K2B(val) << 8;
0384 } else if (property == priv->colorkey_alpha_prop) {
0385 drm_to_overlay_state(state)->colorkey_yr &= ~0x000000ff;
0386 drm_to_overlay_state(state)->colorkey_yr |= K2R(val);
0387 drm_to_overlay_state(state)->colorkey_ug &= ~0x000000ff;
0388 drm_to_overlay_state(state)->colorkey_ug |= K2G(val);
0389 drm_to_overlay_state(state)->colorkey_vb &= ~0x000000ff;
0390 drm_to_overlay_state(state)->colorkey_vb |= K2B(val);
0391 } else if (property == priv->colorkey_mode_prop) {
0392 if (val == CKMODE_DISABLE) {
0393 drm_to_overlay_state(state)->colorkey_mode =
0394 CFG_CKMODE(CKMODE_DISABLE) |
0395 CFG_ALPHAM_CFG | CFG_ALPHA(255);
0396 drm_to_overlay_state(state)->colorkey_enable = 0;
0397 } else {
0398 drm_to_overlay_state(state)->colorkey_mode =
0399 CFG_CKMODE(val) |
0400 CFG_ALPHAM_GRA | CFG_ALPHA(0);
0401 drm_to_overlay_state(state)->colorkey_enable =
0402 ADV_GRACOLORKEY;
0403 }
0404 } else if (property == priv->brightness_prop) {
0405 drm_to_overlay_state(state)->brightness = val - 256;
0406 } else if (property == priv->contrast_prop) {
0407 drm_to_overlay_state(state)->contrast = val;
0408 } else if (property == priv->saturation_prop) {
0409 drm_to_overlay_state(state)->saturation = val;
0410 } else {
0411 return -EINVAL;
0412 }
0413 return 0;
0414 }
0415
0416 static int armada_overlay_get_property(struct drm_plane *plane,
0417 const struct drm_plane_state *state, struct drm_property *property,
0418 uint64_t *val)
0419 {
0420 struct armada_private *priv = drm_to_armada_dev(plane->dev);
0421
0422 #define C2K(c,s) (((c) >> (s)) & 0xff)
0423 #define R2BGR(r,g,b,s) (C2K(r,s) << 0 | C2K(g,s) << 8 | C2K(b,s) << 16)
0424 if (property == priv->colorkey_prop) {
0425
0426 *val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0427 drm_to_overlay_state(state)->colorkey_ug,
0428 drm_to_overlay_state(state)->colorkey_vb, 16);
0429
0430 if (*val != R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0431 drm_to_overlay_state(state)->colorkey_ug,
0432 drm_to_overlay_state(state)->colorkey_vb, 24) ||
0433 *val != R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0434 drm_to_overlay_state(state)->colorkey_ug,
0435 drm_to_overlay_state(state)->colorkey_vb, 8))
0436 return -EINVAL;
0437 } else if (property == priv->colorkey_min_prop) {
0438 *val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0439 drm_to_overlay_state(state)->colorkey_ug,
0440 drm_to_overlay_state(state)->colorkey_vb, 16);
0441 } else if (property == priv->colorkey_max_prop) {
0442 *val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0443 drm_to_overlay_state(state)->colorkey_ug,
0444 drm_to_overlay_state(state)->colorkey_vb, 24);
0445 } else if (property == priv->colorkey_val_prop) {
0446 *val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0447 drm_to_overlay_state(state)->colorkey_ug,
0448 drm_to_overlay_state(state)->colorkey_vb, 8);
0449 } else if (property == priv->colorkey_alpha_prop) {
0450 *val = R2BGR(drm_to_overlay_state(state)->colorkey_yr,
0451 drm_to_overlay_state(state)->colorkey_ug,
0452 drm_to_overlay_state(state)->colorkey_vb, 0);
0453 } else if (property == priv->colorkey_mode_prop) {
0454 *val = (drm_to_overlay_state(state)->colorkey_mode &
0455 CFG_CKMODE_MASK) >> ffs(CFG_CKMODE_MASK);
0456 } else if (property == priv->brightness_prop) {
0457 *val = drm_to_overlay_state(state)->brightness + 256;
0458 } else if (property == priv->contrast_prop) {
0459 *val = drm_to_overlay_state(state)->contrast;
0460 } else if (property == priv->saturation_prop) {
0461 *val = drm_to_overlay_state(state)->saturation;
0462 } else {
0463 return -EINVAL;
0464 }
0465 return 0;
0466 }
0467
0468 static const struct drm_plane_funcs armada_ovl_plane_funcs = {
0469 .update_plane = armada_overlay_plane_update,
0470 .disable_plane = drm_atomic_helper_disable_plane,
0471 .destroy = armada_ovl_plane_destroy,
0472 .reset = armada_overlay_reset,
0473 .atomic_duplicate_state = armada_overlay_duplicate_state,
0474 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
0475 .atomic_set_property = armada_overlay_set_property,
0476 .atomic_get_property = armada_overlay_get_property,
0477 };
0478
0479 static const uint32_t armada_ovl_formats[] = {
0480 DRM_FORMAT_UYVY,
0481 DRM_FORMAT_YUYV,
0482 DRM_FORMAT_YUV420,
0483 DRM_FORMAT_YVU420,
0484 DRM_FORMAT_YUV422,
0485 DRM_FORMAT_YVU422,
0486 DRM_FORMAT_VYUY,
0487 DRM_FORMAT_YVYU,
0488 DRM_FORMAT_ARGB8888,
0489 DRM_FORMAT_ABGR8888,
0490 DRM_FORMAT_XRGB8888,
0491 DRM_FORMAT_XBGR8888,
0492 DRM_FORMAT_RGB888,
0493 DRM_FORMAT_BGR888,
0494 DRM_FORMAT_ARGB1555,
0495 DRM_FORMAT_ABGR1555,
0496 DRM_FORMAT_RGB565,
0497 DRM_FORMAT_BGR565,
0498 };
0499
0500 static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = {
0501 { CKMODE_DISABLE, "disabled" },
0502 { CKMODE_Y, "Y component" },
0503 { CKMODE_U, "U component" },
0504 { CKMODE_V, "V component" },
0505 { CKMODE_RGB, "RGB" },
0506 { CKMODE_R, "R component" },
0507 { CKMODE_G, "G component" },
0508 { CKMODE_B, "B component" },
0509 };
0510
0511 static int armada_overlay_create_properties(struct drm_device *dev)
0512 {
0513 struct armada_private *priv = drm_to_armada_dev(dev);
0514
0515 if (priv->colorkey_prop)
0516 return 0;
0517
0518 priv->colorkey_prop = drm_property_create_range(dev, 0,
0519 "colorkey", 0, 0xffffff);
0520 priv->colorkey_min_prop = drm_property_create_range(dev, 0,
0521 "colorkey_min", 0, 0xffffff);
0522 priv->colorkey_max_prop = drm_property_create_range(dev, 0,
0523 "colorkey_max", 0, 0xffffff);
0524 priv->colorkey_val_prop = drm_property_create_range(dev, 0,
0525 "colorkey_val", 0, 0xffffff);
0526 priv->colorkey_alpha_prop = drm_property_create_range(dev, 0,
0527 "colorkey_alpha", 0, 0xffffff);
0528 priv->colorkey_mode_prop = drm_property_create_enum(dev, 0,
0529 "colorkey_mode",
0530 armada_drm_colorkey_enum_list,
0531 ARRAY_SIZE(armada_drm_colorkey_enum_list));
0532 priv->brightness_prop = drm_property_create_range(dev, 0,
0533 "brightness", 0, 256 + 255);
0534 priv->contrast_prop = drm_property_create_range(dev, 0,
0535 "contrast", 0, 0x7fff);
0536 priv->saturation_prop = drm_property_create_range(dev, 0,
0537 "saturation", 0, 0x7fff);
0538
0539 if (!priv->colorkey_prop)
0540 return -ENOMEM;
0541
0542 return 0;
0543 }
0544
0545 int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
0546 {
0547 struct armada_private *priv = drm_to_armada_dev(dev);
0548 struct drm_mode_object *mobj;
0549 struct drm_plane *overlay;
0550 int ret;
0551
0552 ret = armada_overlay_create_properties(dev);
0553 if (ret)
0554 return ret;
0555
0556 overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
0557 if (!overlay)
0558 return -ENOMEM;
0559
0560 drm_plane_helper_add(overlay, &armada_overlay_plane_helper_funcs);
0561
0562 ret = drm_universal_plane_init(dev, overlay, crtcs,
0563 &armada_ovl_plane_funcs,
0564 armada_ovl_formats,
0565 ARRAY_SIZE(armada_ovl_formats),
0566 NULL,
0567 DRM_PLANE_TYPE_OVERLAY, NULL);
0568 if (ret) {
0569 kfree(overlay);
0570 return ret;
0571 }
0572
0573 mobj = &overlay->base;
0574 drm_object_attach_property(mobj, priv->colorkey_prop,
0575 0x0101fe);
0576 drm_object_attach_property(mobj, priv->colorkey_min_prop,
0577 0x0101fe);
0578 drm_object_attach_property(mobj, priv->colorkey_max_prop,
0579 0x0101fe);
0580 drm_object_attach_property(mobj, priv->colorkey_val_prop,
0581 0x0101fe);
0582 drm_object_attach_property(mobj, priv->colorkey_alpha_prop,
0583 0x000000);
0584 drm_object_attach_property(mobj, priv->colorkey_mode_prop,
0585 CKMODE_RGB);
0586 drm_object_attach_property(mobj, priv->brightness_prop,
0587 256 + DEFAULT_BRIGHTNESS);
0588 drm_object_attach_property(mobj, priv->contrast_prop,
0589 DEFAULT_CONTRAST);
0590 drm_object_attach_property(mobj, priv->saturation_prop,
0591 DEFAULT_SATURATION);
0592
0593 ret = drm_plane_create_color_properties(overlay,
0594 BIT(DRM_COLOR_YCBCR_BT601) |
0595 BIT(DRM_COLOR_YCBCR_BT709),
0596 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
0597 DEFAULT_ENCODING,
0598 DRM_COLOR_YCBCR_LIMITED_RANGE);
0599
0600 return ret;
0601 }