blob: aa2a12aec3cc58661a4a1e214238bc805a8b0bd7 [file] [log] [blame]
Russell King96f60e32012-08-15 13:59:49 +01001/*
2 * Copyright (C) 2012 Russell King
3 * Rewritten from the dovefb driver, and Armada510 manuals.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9#include <drm/drmP.h>
Russell King47dc4132018-07-30 11:52:34 +010010#include <drm/drm_atomic.h>
Dave Airliebcd21a42018-01-05 09:43:46 +100011#include <drm/drm_atomic_helper.h>
Russell King47dc4132018-07-30 11:52:34 +010012#include <drm/drm_plane_helper.h>
Russell King96f60e32012-08-15 13:59:49 +010013#include "armada_crtc.h"
14#include "armada_drm.h"
15#include "armada_fb.h"
16#include "armada_gem.h"
17#include "armada_hw.h"
18#include <drm/armada_drm.h>
19#include "armada_ioctlP.h"
Russell Kingc8a220c2016-05-17 13:51:08 +010020#include "armada_trace.h"
Russell King96f60e32012-08-15 13:59:49 +010021
Russell King28a2aeb2015-07-15 18:11:23 +010022struct armada_ovl_plane_properties {
Russell King96f60e32012-08-15 13:59:49 +010023 uint32_t colorkey_yr;
24 uint32_t colorkey_ug;
25 uint32_t colorkey_vb;
26#define K2R(val) (((val) >> 0) & 0xff)
27#define K2G(val) (((val) >> 8) & 0xff)
28#define K2B(val) (((val) >> 16) & 0xff)
29 int16_t brightness;
30 uint16_t contrast;
31 uint16_t saturation;
32 uint32_t colorkey_mode;
Russell Kingd3788592018-06-24 14:35:10 +010033 uint32_t colorkey_enable;
Russell King96f60e32012-08-15 13:59:49 +010034};
35
Russell King28a2aeb2015-07-15 18:11:23 +010036struct armada_ovl_plane {
Russell King561f60b2015-07-15 18:11:24 +010037 struct armada_plane base;
Russell King3acea7b2018-07-30 11:52:34 +010038 bool wait_vblank;
Russell King28a2aeb2015-07-15 18:11:23 +010039 struct armada_ovl_plane_properties prop;
Russell King96f60e32012-08-15 13:59:49 +010040};
Russell King561f60b2015-07-15 18:11:24 +010041#define drm_to_armada_ovl_plane(p) \
42 container_of(p, struct armada_ovl_plane, base.base)
Russell King96f60e32012-08-15 13:59:49 +010043
44
45static void
Russell King28a2aeb2015-07-15 18:11:23 +010046armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
Russell King96f60e32012-08-15 13:59:49 +010047 struct armada_crtc *dcrtc)
48{
49 writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y);
50 writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U);
51 writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V);
52
53 writel_relaxed(prop->brightness << 16 | prop->contrast,
54 dcrtc->base + LCD_SPU_CONTRAST);
55 /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
56 writel_relaxed(prop->saturation << 16,
57 dcrtc->base + LCD_SPU_SATURATION);
58 writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE);
59
60 spin_lock_irq(&dcrtc->irq_lock);
Russell Kingd3788592018-06-24 14:35:10 +010061 armada_updatel(prop->colorkey_mode,
62 CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
63 dcrtc->base + LCD_SPU_DMA_CTRL1);
64 if (dcrtc->variant->has_spu_adv_reg)
65 armada_updatel(prop->colorkey_enable,
66 ADV_GRACOLORKEY | ADV_VIDCOLORKEY,
67 dcrtc->base + LCD_SPU_ADV_REG);
Russell King96f60e32012-08-15 13:59:49 +010068 spin_unlock_irq(&dcrtc->irq_lock);
69}
70
71/* === Plane support === */
Russell King4a8506d2015-08-07 09:33:05 +010072static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
Russell Kingeaab0132017-07-07 15:55:53 +010073 struct armada_plane_work *work)
Russell King96f60e32012-08-15 13:59:49 +010074{
Russell Kinga3f6a182017-07-08 10:16:48 +010075 unsigned long flags;
Russell King96f60e32012-08-15 13:59:49 +010076
Russell Kingeaab0132017-07-07 15:55:53 +010077 trace_armada_ovl_plane_work(&dcrtc->crtc, work->plane);
Russell Kingc8a220c2016-05-17 13:51:08 +010078
Russell Kinga3f6a182017-07-08 10:16:48 +010079 spin_lock_irqsave(&dcrtc->irq_lock, flags);
Russell Kingeaa66272017-07-08 10:22:10 +010080 armada_drm_crtc_update_regs(dcrtc, work->regs);
Russell Kinga3f6a182017-07-08 10:16:48 +010081 spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
Russell King96f60e32012-08-15 13:59:49 +010082}
83
Russell King47dc4132018-07-30 11:52:34 +010084static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
85 struct drm_plane_state *old_state)
86{
87 struct drm_plane_state *state = plane->state;
88 struct armada_crtc *dcrtc;
89 struct armada_regs *regs;
Russell King3acea7b2018-07-30 11:52:34 +010090 unsigned int idx;
91 u32 cfg, cfg_mask, val;
Russell King47dc4132018-07-30 11:52:34 +010092
93 DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
94
95 if (!state->fb || WARN_ON(!state->crtc))
96 return;
97
98 DRM_DEBUG_KMS("[PLANE:%d:%s] is on [CRTC:%d:%s] with [FB:%d] visible %u->%u\n",
99 plane->base.id, plane->name,
100 state->crtc->base.id, state->crtc->name,
101 state->fb->base.id,
102 old_state->visible, state->visible);
103
104 dcrtc = drm_to_armada_crtc(state->crtc);
105 regs = dcrtc->regs + dcrtc->regs_idx;
106
Russell King3acea7b2018-07-30 11:52:34 +0100107 drm_to_armada_ovl_plane(plane)->wait_vblank = false;
108
109 idx = 0;
110 if (!old_state->visible && state->visible)
111 armada_reg_queue_mod(regs, idx,
112 0, CFG_PDWN16x66 | CFG_PDWN32x66,
113 LCD_SPU_SRAM_PARA1);
114 val = armada_rect_hw_fp(&state->src);
115 if (armada_rect_hw_fp(&old_state->src) != val)
116 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_HPXL_VLN);
117 val = armada_rect_yx(&state->dst);
118 if (armada_rect_yx(&old_state->dst) != val)
119 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN);
120 val = armada_rect_hw(&state->dst);
121 if (armada_rect_hw(&old_state->dst) != val)
122 armada_reg_queue_set(regs, idx, val, LCD_SPU_DZM_HPXL_VLN);
123 /* FIXME: overlay on an interlaced display */
124 if (old_state->src.x1 != state->src.x1 ||
125 old_state->src.y1 != state->src.y1 ||
126 old_state->fb != state->fb) {
127 const struct drm_format_info *format;
128 u16 src_x = state->src.x1 >> 16;
129 u16 src_y = state->src.y1 >> 16;
130 u32 addrs[3];
131
132 armada_drm_plane_calc_addrs(addrs, state->fb, src_x, src_y);
133
134 armada_reg_queue_set(regs, idx, addrs[0],
135 LCD_SPU_DMA_START_ADDR_Y0);
136 armada_reg_queue_set(regs, idx, addrs[1],
137 LCD_SPU_DMA_START_ADDR_U0);
138 armada_reg_queue_set(regs, idx, addrs[2],
139 LCD_SPU_DMA_START_ADDR_V0);
140 armada_reg_queue_set(regs, idx, addrs[0],
141 LCD_SPU_DMA_START_ADDR_Y1);
142 armada_reg_queue_set(regs, idx, addrs[1],
143 LCD_SPU_DMA_START_ADDR_U1);
144 armada_reg_queue_set(regs, idx, addrs[2],
145 LCD_SPU_DMA_START_ADDR_V1);
146
147 val = state->fb->pitches[0] << 16 | state->fb->pitches[0];
148 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_YC);
149 val = state->fb->pitches[1] << 16 | state->fb->pitches[2];
150 armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_UV);
151
152 cfg = CFG_DMA_FMT(drm_fb_to_armada_fb(state->fb)->fmt) |
153 CFG_DMA_MOD(drm_fb_to_armada_fb(state->fb)->mod) |
154 CFG_CBSH_ENA;
155 if (state->visible)
156 cfg |= CFG_DMA_ENA;
157
158 /*
159 * Shifting a YUV packed format image by one pixel causes the
160 * U/V planes to swap. Compensate for it by also toggling
161 * the UV swap.
162 */
163 format = state->fb->format;
164 if (format->num_planes == 1 && src_x & (format->hsub - 1))
165 cfg ^= CFG_DMA_MOD(CFG_SWAPUV);
166 cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT |
167 CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV |
168 CFG_SWAPYU | CFG_YUV2RGB) |
169 CFG_DMA_FTOGGLE | CFG_DMA_TSTMODE |
170 CFG_DMA_ENA;
171
172 drm_to_armada_ovl_plane(plane)->wait_vblank = true;
173 } else if (old_state->visible != state->visible) {
174 cfg = state->visible ? CFG_DMA_ENA : 0;
175 cfg_mask = CFG_DMA_ENA;
176 } else {
177 cfg = cfg_mask = 0;
178 }
179 if (drm_rect_width(&old_state->src) != drm_rect_width(&state->src) ||
180 drm_rect_width(&old_state->dst) != drm_rect_width(&state->dst)) {
181 cfg_mask |= CFG_DMA_HSMOOTH;
182 if (drm_rect_width(&state->src) >> 16 !=
183 drm_rect_width(&state->dst))
184 cfg |= CFG_DMA_HSMOOTH;
185 }
186
187 if (cfg_mask)
188 armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
189 LCD_SPU_DMA_CTRL0);
190
191 dcrtc->regs_idx += idx;
Russell King47dc4132018-07-30 11:52:34 +0100192}
193
194static void armada_drm_overlay_plane_atomic_disable(struct drm_plane *plane,
195 struct drm_plane_state *old_state)
196{
Russell King47dc4132018-07-30 11:52:34 +0100197 struct armada_crtc *dcrtc;
198 struct armada_regs *regs;
199 unsigned int idx = 0;
200
201 DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
202
203 if (!old_state->crtc)
204 return;
205
206 DRM_DEBUG_KMS("[PLANE:%d:%s] was on [CRTC:%d:%s] with [FB:%d]\n",
207 plane->base.id, plane->name,
208 old_state->crtc->base.id, old_state->crtc->name,
209 old_state->fb->base.id);
210
Russell King47dc4132018-07-30 11:52:34 +0100211 dcrtc = drm_to_armada_crtc(old_state->crtc);
212 regs = dcrtc->regs + dcrtc->regs_idx;
213
214 /* Disable plane and power down the YUV FIFOs */
215 armada_reg_queue_mod(regs, idx, 0, CFG_DMA_ENA, LCD_SPU_DMA_CTRL0);
216 armada_reg_queue_mod(regs, idx, CFG_PDWN16x66 | CFG_PDWN32x66, 0,
217 LCD_SPU_SRAM_PARA1);
218
219 dcrtc->regs_idx += idx;
220
221 if (dcrtc->plane == plane)
222 dcrtc->plane = NULL;
223}
224
225static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = {
226 .prepare_fb = armada_drm_plane_prepare_fb,
227 .cleanup_fb = armada_drm_plane_cleanup_fb,
228 .atomic_check = armada_drm_plane_atomic_check,
229 .atomic_update = armada_drm_overlay_plane_atomic_update,
230 .atomic_disable = armada_drm_overlay_plane_atomic_disable,
231};
232
233static int armada_overlay_commit(struct drm_plane *plane,
234 struct drm_plane_state *state)
Russell King96f60e32012-08-15 13:59:49 +0100235{
Russell King28a2aeb2015-07-15 18:11:23 +0100236 struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
Russell King47dc4132018-07-30 11:52:34 +0100237 const struct drm_plane_helper_funcs *plane_funcs;
238 struct armada_crtc *dcrtc = drm_to_armada_crtc(state->crtc);
Russell Kingd9241552017-07-08 10:22:25 +0100239 struct armada_plane_work *work;
Russell King96f60e32012-08-15 13:59:49 +0100240 int ret;
241
Russell King47dc4132018-07-30 11:52:34 +0100242 plane_funcs = plane->helper_private;
243 ret = plane_funcs->atomic_check(plane, state);
Russell King98fb74f2015-06-15 10:17:57 +0100244 if (ret)
Russell King47dc4132018-07-30 11:52:34 +0100245 goto put_state;
Russell King98fb74f2015-06-15 10:17:57 +0100246
Russell Kingd9241552017-07-08 10:22:25 +0100247 work = &dplane->base.works[dplane->base.next_work];
Russell King96f60e32012-08-15 13:59:49 +0100248
Russell King47dc4132018-07-30 11:52:34 +0100249 if (plane->state->fb != state->fb) {
Russell King96f60e32012-08-15 13:59:49 +0100250 /*
251 * Take a reference on the new framebuffer - we want to
252 * hold on to it while the hardware is displaying it.
253 */
Russell King47dc4132018-07-30 11:52:34 +0100254 drm_framebuffer_reference(state->fb);
Russell King96f60e32012-08-15 13:59:49 +0100255
Russell King47dc4132018-07-30 11:52:34 +0100256 work->old_fb = plane->state->fb;
Russell Kingb972a802017-07-08 10:16:52 +0100257 } else {
Russell Kingeaa66272017-07-08 10:22:10 +0100258 work->old_fb = NULL;
Russell King96f60e32012-08-15 13:59:49 +0100259 }
260
Russell King47dc4132018-07-30 11:52:34 +0100261 /* Point of no return */
262 swap(plane->state, state);
Russell King98fb74f2015-06-15 10:17:57 +0100263
Russell King47dc4132018-07-30 11:52:34 +0100264 dcrtc->regs_idx = 0;
265 dcrtc->regs = work->regs;
266
267 plane_funcs->atomic_update(plane, state);
268
269 /* If nothing was updated, short-circuit */
Russell King3acea7b2018-07-30 11:52:34 +0100270 if (dcrtc->regs_idx == 0)
Russell King47dc4132018-07-30 11:52:34 +0100271 goto put_state;
272
273 armada_reg_queue_end(dcrtc->regs, dcrtc->regs_idx);
Russell Kingd19f6ee2017-07-08 10:22:31 +0100274
Russell King07da3c72017-07-08 10:22:34 +0100275 /* Wait for pending work to complete */
276 if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0)
277 armada_drm_plane_work_cancel(dcrtc, &dplane->base);
278
Russell Kingd19f6ee2017-07-08 10:22:31 +0100279 /* Just updating the position/size? */
Russell King3acea7b2018-07-30 11:52:34 +0100280 if (!dplane->wait_vblank) {
Russell Kingd19f6ee2017-07-08 10:22:31 +0100281 armada_ovl_plane_work(dcrtc, work);
Russell King47dc4132018-07-30 11:52:34 +0100282 goto put_state;
Russell Kingd19f6ee2017-07-08 10:22:31 +0100283 }
Russell King96f60e32012-08-15 13:59:49 +0100284
285 if (!dcrtc->plane) {
286 dcrtc->plane = plane;
287 armada_ovl_update_attr(&dplane->prop, dcrtc);
288 }
289
Russell King65843e9a2017-07-08 10:22:33 +0100290 /* Queue it for update on the next interrupt if we are enabled */
291 ret = armada_drm_plane_work_queue(dcrtc, work);
Russell King47dc4132018-07-30 11:52:34 +0100292 if (ret) {
Russell King65843e9a2017-07-08 10:22:33 +0100293 DRM_ERROR("failed to queue plane work: %d\n", ret);
Russell King47dc4132018-07-30 11:52:34 +0100294 ret = 0;
295 }
Russell King96f60e32012-08-15 13:59:49 +0100296
Russell King65843e9a2017-07-08 10:22:33 +0100297 dplane->base.next_work = !dplane->base.next_work;
Russell King96f60e32012-08-15 13:59:49 +0100298
Russell King47dc4132018-07-30 11:52:34 +0100299put_state:
300 drm_atomic_helper_plane_destroy_state(plane, state);
301 return ret;
302}
303
304static int
305armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
306 struct drm_framebuffer *fb,
307 int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
308 uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
309 struct drm_modeset_acquire_ctx *ctx)
310{
311 struct drm_plane_state *state;
312
313 trace_armada_ovl_plane_update(plane, crtc, fb,
314 crtc_x, crtc_y, crtc_w, crtc_h,
315 src_x, src_y, src_w, src_h);
316
317 /* Construct new state for the overlay plane */
318 state = drm_atomic_helper_plane_duplicate_state(plane);
319 if (!state)
320 return -ENOMEM;
321
322 state->crtc = crtc;
323 drm_atomic_set_fb_for_plane(state, fb);
324 state->crtc_x = crtc_x;
325 state->crtc_y = crtc_y;
326 state->crtc_h = crtc_h;
327 state->crtc_w = crtc_w;
328 state->src_x = src_x;
329 state->src_y = src_y;
330 state->src_h = src_h;
331 state->src_w = src_w;
332
333 return armada_overlay_commit(plane, state);
Russell King96f60e32012-08-15 13:59:49 +0100334}
335
Russell King28a2aeb2015-07-15 18:11:23 +0100336static void armada_ovl_plane_destroy(struct drm_plane *plane)
Russell King96f60e32012-08-15 13:59:49 +0100337{
Russell King28a2aeb2015-07-15 18:11:23 +0100338 struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
Russell King41dbb2d2015-06-15 10:13:30 +0100339
340 drm_plane_cleanup(plane);
341
342 kfree(dplane);
Russell King96f60e32012-08-15 13:59:49 +0100343}
344
Russell King28a2aeb2015-07-15 18:11:23 +0100345static int armada_ovl_plane_set_property(struct drm_plane *plane,
Russell King96f60e32012-08-15 13:59:49 +0100346 struct drm_property *property, uint64_t val)
347{
348 struct armada_private *priv = plane->dev->dev_private;
Russell King28a2aeb2015-07-15 18:11:23 +0100349 struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
Russell King96f60e32012-08-15 13:59:49 +0100350 bool update_attr = false;
351
352 if (property == priv->colorkey_prop) {
353#define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8)
354 dplane->prop.colorkey_yr = CCC(K2R(val));
355 dplane->prop.colorkey_ug = CCC(K2G(val));
356 dplane->prop.colorkey_vb = CCC(K2B(val));
357#undef CCC
358 update_attr = true;
359 } else if (property == priv->colorkey_min_prop) {
360 dplane->prop.colorkey_yr &= ~0x00ff0000;
361 dplane->prop.colorkey_yr |= K2R(val) << 16;
362 dplane->prop.colorkey_ug &= ~0x00ff0000;
363 dplane->prop.colorkey_ug |= K2G(val) << 16;
364 dplane->prop.colorkey_vb &= ~0x00ff0000;
365 dplane->prop.colorkey_vb |= K2B(val) << 16;
366 update_attr = true;
367 } else if (property == priv->colorkey_max_prop) {
368 dplane->prop.colorkey_yr &= ~0xff000000;
369 dplane->prop.colorkey_yr |= K2R(val) << 24;
370 dplane->prop.colorkey_ug &= ~0xff000000;
371 dplane->prop.colorkey_ug |= K2G(val) << 24;
372 dplane->prop.colorkey_vb &= ~0xff000000;
373 dplane->prop.colorkey_vb |= K2B(val) << 24;
374 update_attr = true;
375 } else if (property == priv->colorkey_val_prop) {
376 dplane->prop.colorkey_yr &= ~0x0000ff00;
377 dplane->prop.colorkey_yr |= K2R(val) << 8;
378 dplane->prop.colorkey_ug &= ~0x0000ff00;
379 dplane->prop.colorkey_ug |= K2G(val) << 8;
380 dplane->prop.colorkey_vb &= ~0x0000ff00;
381 dplane->prop.colorkey_vb |= K2B(val) << 8;
382 update_attr = true;
383 } else if (property == priv->colorkey_alpha_prop) {
384 dplane->prop.colorkey_yr &= ~0x000000ff;
385 dplane->prop.colorkey_yr |= K2R(val);
386 dplane->prop.colorkey_ug &= ~0x000000ff;
387 dplane->prop.colorkey_ug |= K2G(val);
388 dplane->prop.colorkey_vb &= ~0x000000ff;
389 dplane->prop.colorkey_vb |= K2B(val);
390 update_attr = true;
391 } else if (property == priv->colorkey_mode_prop) {
Russell Kingd3788592018-06-24 14:35:10 +0100392 if (val == CKMODE_DISABLE) {
393 dplane->prop.colorkey_mode =
394 CFG_CKMODE(CKMODE_DISABLE) |
395 CFG_ALPHAM_CFG | CFG_ALPHA(255);
396 dplane->prop.colorkey_enable = 0;
397 } else {
398 dplane->prop.colorkey_mode =
399 CFG_CKMODE(val) |
400 CFG_ALPHAM_GRA | CFG_ALPHA(0);
401 dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
402 }
Russell King96f60e32012-08-15 13:59:49 +0100403 update_attr = true;
404 } else if (property == priv->brightness_prop) {
405 dplane->prop.brightness = val - 256;
406 update_attr = true;
407 } else if (property == priv->contrast_prop) {
408 dplane->prop.contrast = val;
409 update_attr = true;
410 } else if (property == priv->saturation_prop) {
411 dplane->prop.saturation = val;
412 update_attr = true;
413 }
414
Russell King561f60b2015-07-15 18:11:24 +0100415 if (update_attr && dplane->base.base.crtc)
Russell King96f60e32012-08-15 13:59:49 +0100416 armada_ovl_update_attr(&dplane->prop,
Russell King561f60b2015-07-15 18:11:24 +0100417 drm_to_armada_crtc(dplane->base.base.crtc));
Russell King96f60e32012-08-15 13:59:49 +0100418
419 return 0;
420}
421
Russell King28a2aeb2015-07-15 18:11:23 +0100422static const struct drm_plane_funcs armada_ovl_plane_funcs = {
423 .update_plane = armada_ovl_plane_update,
Russell King47dc4132018-07-30 11:52:34 +0100424 .disable_plane = drm_plane_helper_disable,
Russell King28a2aeb2015-07-15 18:11:23 +0100425 .destroy = armada_ovl_plane_destroy,
426 .set_property = armada_ovl_plane_set_property,
Russell King47dc4132018-07-30 11:52:34 +0100427 .reset = drm_atomic_helper_plane_reset,
Russell King96f60e32012-08-15 13:59:49 +0100428};
429
Russell King28a2aeb2015-07-15 18:11:23 +0100430static const uint32_t armada_ovl_formats[] = {
Russell King96f60e32012-08-15 13:59:49 +0100431 DRM_FORMAT_UYVY,
432 DRM_FORMAT_YUYV,
433 DRM_FORMAT_YUV420,
434 DRM_FORMAT_YVU420,
435 DRM_FORMAT_YUV422,
436 DRM_FORMAT_YVU422,
437 DRM_FORMAT_VYUY,
438 DRM_FORMAT_YVYU,
439 DRM_FORMAT_ARGB8888,
440 DRM_FORMAT_ABGR8888,
441 DRM_FORMAT_XRGB8888,
442 DRM_FORMAT_XBGR8888,
443 DRM_FORMAT_RGB888,
444 DRM_FORMAT_BGR888,
445 DRM_FORMAT_ARGB1555,
446 DRM_FORMAT_ABGR1555,
447 DRM_FORMAT_RGB565,
448 DRM_FORMAT_BGR565,
449};
450
Arvind Yadav8a63ca52017-07-01 16:24:42 +0530451static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = {
Russell King96f60e32012-08-15 13:59:49 +0100452 { CKMODE_DISABLE, "disabled" },
453 { CKMODE_Y, "Y component" },
454 { CKMODE_U, "U component" },
455 { CKMODE_V, "V component" },
456 { CKMODE_RGB, "RGB" },
457 { CKMODE_R, "R component" },
458 { CKMODE_G, "G component" },
459 { CKMODE_B, "B component" },
460};
461
462static int armada_overlay_create_properties(struct drm_device *dev)
463{
464 struct armada_private *priv = dev->dev_private;
465
466 if (priv->colorkey_prop)
467 return 0;
468
469 priv->colorkey_prop = drm_property_create_range(dev, 0,
470 "colorkey", 0, 0xffffff);
471 priv->colorkey_min_prop = drm_property_create_range(dev, 0,
472 "colorkey_min", 0, 0xffffff);
473 priv->colorkey_max_prop = drm_property_create_range(dev, 0,
474 "colorkey_max", 0, 0xffffff);
475 priv->colorkey_val_prop = drm_property_create_range(dev, 0,
476 "colorkey_val", 0, 0xffffff);
477 priv->colorkey_alpha_prop = drm_property_create_range(dev, 0,
478 "colorkey_alpha", 0, 0xffffff);
479 priv->colorkey_mode_prop = drm_property_create_enum(dev, 0,
480 "colorkey_mode",
481 armada_drm_colorkey_enum_list,
482 ARRAY_SIZE(armada_drm_colorkey_enum_list));
483 priv->brightness_prop = drm_property_create_range(dev, 0,
484 "brightness", 0, 256 + 255);
485 priv->contrast_prop = drm_property_create_range(dev, 0,
486 "contrast", 0, 0x7fff);
487 priv->saturation_prop = drm_property_create_range(dev, 0,
488 "saturation", 0, 0x7fff);
489
490 if (!priv->colorkey_prop)
491 return -ENOMEM;
492
493 return 0;
494}
495
496int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
497{
498 struct armada_private *priv = dev->dev_private;
499 struct drm_mode_object *mobj;
Russell King28a2aeb2015-07-15 18:11:23 +0100500 struct armada_ovl_plane *dplane;
Russell King96f60e32012-08-15 13:59:49 +0100501 int ret;
502
503 ret = armada_overlay_create_properties(dev);
504 if (ret)
505 return ret;
506
507 dplane = kzalloc(sizeof(*dplane), GFP_KERNEL);
508 if (!dplane)
509 return -ENOMEM;
510
Russell King5740d272015-07-15 18:11:25 +0100511 ret = armada_drm_plane_init(&dplane->base);
512 if (ret) {
513 kfree(dplane);
514 return ret;
515 }
516
Russell Kingd9241552017-07-08 10:22:25 +0100517 dplane->base.works[0].fn = armada_ovl_plane_work;
518 dplane->base.works[1].fn = armada_ovl_plane_work;
Russell King96f60e32012-08-15 13:59:49 +0100519
Russell King47dc4132018-07-30 11:52:34 +0100520 drm_plane_helper_add(&dplane->base.base,
521 &armada_overlay_plane_helper_funcs);
522
Russell King561f60b2015-07-15 18:11:24 +0100523 ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs,
Russell Kingd563c242015-07-15 18:11:24 +0100524 &armada_ovl_plane_funcs,
525 armada_ovl_formats,
526 ARRAY_SIZE(armada_ovl_formats),
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700527 NULL,
Ville Syrjäläb0b3b792015-12-09 16:19:55 +0200528 DRM_PLANE_TYPE_OVERLAY, NULL);
Russell King28a2aeb2015-07-15 18:11:23 +0100529 if (ret) {
530 kfree(dplane);
531 return ret;
532 }
Russell King96f60e32012-08-15 13:59:49 +0100533
534 dplane->prop.colorkey_yr = 0xfefefe00;
535 dplane->prop.colorkey_ug = 0x01010100;
536 dplane->prop.colorkey_vb = 0x01010100;
Russell Kingd3788592018-06-24 14:35:10 +0100537 dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
538 CFG_ALPHAM_GRA | CFG_ALPHA(0);
539 dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
Russell King96f60e32012-08-15 13:59:49 +0100540 dplane->prop.brightness = 0;
541 dplane->prop.contrast = 0x4000;
542 dplane->prop.saturation = 0x4000;
543
Russell King561f60b2015-07-15 18:11:24 +0100544 mobj = &dplane->base.base.base;
Russell King96f60e32012-08-15 13:59:49 +0100545 drm_object_attach_property(mobj, priv->colorkey_prop,
546 0x0101fe);
547 drm_object_attach_property(mobj, priv->colorkey_min_prop,
548 0x0101fe);
549 drm_object_attach_property(mobj, priv->colorkey_max_prop,
550 0x0101fe);
551 drm_object_attach_property(mobj, priv->colorkey_val_prop,
552 0x0101fe);
553 drm_object_attach_property(mobj, priv->colorkey_alpha_prop,
554 0x000000);
555 drm_object_attach_property(mobj, priv->colorkey_mode_prop,
556 CKMODE_RGB);
557 drm_object_attach_property(mobj, priv->brightness_prop, 256);
558 drm_object_attach_property(mobj, priv->contrast_prop,
559 dplane->prop.contrast);
560 drm_object_attach_property(mobj, priv->saturation_prop,
561 dplane->prop.saturation);
562
563 return 0;
564}