diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-08-15 08:59:49 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-10-12 05:13:40 -0400 |
commit | 96f60e37dc66091bde8d5de136ff6fda09f2d799 (patch) | |
tree | 2c2cc30a5ac7339730430369e27d33d4a8dd21ef /drivers/gpu/drm/armada/armada_overlay.c | |
parent | 15c03dd4859ab16f9212238f29dd315654aa94f6 (diff) |
DRM: Armada: Add Armada DRM driver
This patch adds support for the pair of LCD controllers on the Marvell
Armada 510 SoCs. This driver supports:
- multiple contiguous scanout buffers for video and graphics
- shm backed cacheable buffer objects for X pixmaps for Vivante GPU
acceleration
- dual lcd0 and lcd1 crt operation
- video overlay on each LCD crt via DRM planes
- page flipping of the main scanout buffers
- DRM prime for buffer export/import
This driver is trivial to extend to other Armada SoCs.
Included in this commit is the core driver with no output support; output
support is platform and encoder driver dependent.
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/armada/armada_overlay.c')
-rw-r--r-- | drivers/gpu/drm/armada/armada_overlay.c | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c new file mode 100644 index 000000000000..c5b06fdb459c --- /dev/null +++ b/drivers/gpu/drm/armada/armada_overlay.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
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> | ||
10 | #include "armada_crtc.h" | ||
11 | #include "armada_drm.h" | ||
12 | #include "armada_fb.h" | ||
13 | #include "armada_gem.h" | ||
14 | #include "armada_hw.h" | ||
15 | #include <drm/armada_drm.h> | ||
16 | #include "armada_ioctlP.h" | ||
17 | |||
18 | struct armada_plane_properties { | ||
19 | uint32_t colorkey_yr; | ||
20 | uint32_t colorkey_ug; | ||
21 | uint32_t colorkey_vb; | ||
22 | #define K2R(val) (((val) >> 0) & 0xff) | ||
23 | #define K2G(val) (((val) >> 8) & 0xff) | ||
24 | #define K2B(val) (((val) >> 16) & 0xff) | ||
25 | int16_t brightness; | ||
26 | uint16_t contrast; | ||
27 | uint16_t saturation; | ||
28 | uint32_t colorkey_mode; | ||
29 | }; | ||
30 | |||
31 | struct armada_plane { | ||
32 | struct drm_plane base; | ||
33 | spinlock_t lock; | ||
34 | struct drm_framebuffer *old_fb; | ||
35 | uint32_t src_hw; | ||
36 | uint32_t dst_hw; | ||
37 | uint32_t dst_yx; | ||
38 | uint32_t ctrl0; | ||
39 | struct { | ||
40 | struct armada_vbl_event update; | ||
41 | struct armada_regs regs[13]; | ||
42 | wait_queue_head_t wait; | ||
43 | } vbl; | ||
44 | struct armada_plane_properties prop; | ||
45 | }; | ||
46 | #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) | ||
47 | |||
48 | |||
49 | static void | ||
50 | armada_ovl_update_attr(struct armada_plane_properties *prop, | ||
51 | struct armada_crtc *dcrtc) | ||
52 | { | ||
53 | writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y); | ||
54 | writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U); | ||
55 | writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V); | ||
56 | |||
57 | writel_relaxed(prop->brightness << 16 | prop->contrast, | ||
58 | dcrtc->base + LCD_SPU_CONTRAST); | ||
59 | /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */ | ||
60 | writel_relaxed(prop->saturation << 16, | ||
61 | dcrtc->base + LCD_SPU_SATURATION); | ||
62 | writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); | ||
63 | |||
64 | spin_lock_irq(&dcrtc->irq_lock); | ||
65 | armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA, | ||
66 | CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, | ||
67 | dcrtc->base + LCD_SPU_DMA_CTRL1); | ||
68 | |||
69 | armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG); | ||
70 | spin_unlock_irq(&dcrtc->irq_lock); | ||
71 | } | ||
72 | |||
73 | /* === Plane support === */ | ||
74 | static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) | ||
75 | { | ||
76 | struct armada_plane *dplane = data; | ||
77 | struct drm_framebuffer *fb; | ||
78 | |||
79 | armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); | ||
80 | |||
81 | spin_lock(&dplane->lock); | ||
82 | fb = dplane->old_fb; | ||
83 | dplane->old_fb = NULL; | ||
84 | spin_unlock(&dplane->lock); | ||
85 | |||
86 | if (fb) | ||
87 | armada_drm_queue_unref_work(dcrtc->crtc.dev, fb); | ||
88 | } | ||
89 | |||
90 | static unsigned armada_limit(int start, unsigned size, unsigned max) | ||
91 | { | ||
92 | int end = start + size; | ||
93 | if (end < 0) | ||
94 | return 0; | ||
95 | if (start < 0) | ||
96 | start = 0; | ||
97 | return (unsigned)end > max ? max - start : end - start; | ||
98 | } | ||
99 | |||
100 | static int | ||
101 | armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | ||
102 | struct drm_framebuffer *fb, | ||
103 | int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, | ||
104 | uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) | ||
105 | { | ||
106 | struct armada_plane *dplane = drm_to_armada_plane(plane); | ||
107 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | ||
108 | uint32_t val, ctrl0; | ||
109 | unsigned idx = 0; | ||
110 | int ret; | ||
111 | |||
112 | crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay); | ||
113 | crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay); | ||
114 | ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | | ||
115 | CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | | ||
116 | CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; | ||
117 | |||
118 | /* Does the position/size result in nothing to display? */ | ||
119 | if (crtc_w == 0 || crtc_h == 0) { | ||
120 | ctrl0 &= ~CFG_DMA_ENA; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * FIXME: if the starting point is off screen, we need to | ||
125 | * adjust src_x, src_y, src_w, src_h appropriately, and | ||
126 | * according to the scale. | ||
127 | */ | ||
128 | |||
129 | if (!dcrtc->plane) { | ||
130 | dcrtc->plane = plane; | ||
131 | armada_ovl_update_attr(&dplane->prop, dcrtc); | ||
132 | } | ||
133 | |||
134 | /* FIXME: overlay on an interlaced display */ | ||
135 | /* Just updating the position/size? */ | ||
136 | if (plane->fb == fb && dplane->ctrl0 == ctrl0) { | ||
137 | val = (src_h & 0xffff0000) | src_w >> 16; | ||
138 | dplane->src_hw = val; | ||
139 | writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); | ||
140 | val = crtc_h << 16 | crtc_w; | ||
141 | dplane->dst_hw = val; | ||
142 | writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); | ||
143 | val = crtc_y << 16 | crtc_x; | ||
144 | dplane->dst_yx = val; | ||
145 | writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); | ||
146 | return 0; | ||
147 | } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { | ||
148 | /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ | ||
149 | armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, | ||
150 | dcrtc->base + LCD_SPU_SRAM_PARA1); | ||
151 | } | ||
152 | |||
153 | ret = wait_event_timeout(dplane->vbl.wait, | ||
154 | list_empty(&dplane->vbl.update.node), | ||
155 | HZ/25); | ||
156 | if (ret < 0) | ||
157 | return ret; | ||
158 | |||
159 | if (plane->fb != fb) { | ||
160 | struct armada_gem_object *obj = drm_fb_obj(fb); | ||
161 | uint32_t sy, su, sv; | ||
162 | |||
163 | /* | ||
164 | * Take a reference on the new framebuffer - we want to | ||
165 | * hold on to it while the hardware is displaying it. | ||
166 | */ | ||
167 | drm_framebuffer_reference(fb); | ||
168 | |||
169 | if (plane->fb) { | ||
170 | struct drm_framebuffer *older_fb; | ||
171 | |||
172 | spin_lock_irq(&dplane->lock); | ||
173 | older_fb = dplane->old_fb; | ||
174 | dplane->old_fb = plane->fb; | ||
175 | spin_unlock_irq(&dplane->lock); | ||
176 | if (older_fb) | ||
177 | armada_drm_queue_unref_work(dcrtc->crtc.dev, | ||
178 | older_fb); | ||
179 | } | ||
180 | |||
181 | src_y >>= 16; | ||
182 | src_x >>= 16; | ||
183 | sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] + | ||
184 | src_x * fb->bits_per_pixel / 8; | ||
185 | su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] + | ||
186 | src_x; | ||
187 | sv = obj->dev_addr + fb->offsets[2] + src_y * fb->pitches[2] + | ||
188 | src_x; | ||
189 | |||
190 | armada_reg_queue_set(dplane->vbl.regs, idx, sy, | ||
191 | LCD_SPU_DMA_START_ADDR_Y0); | ||
192 | armada_reg_queue_set(dplane->vbl.regs, idx, su, | ||
193 | LCD_SPU_DMA_START_ADDR_U0); | ||
194 | armada_reg_queue_set(dplane->vbl.regs, idx, sv, | ||
195 | LCD_SPU_DMA_START_ADDR_V0); | ||
196 | armada_reg_queue_set(dplane->vbl.regs, idx, sy, | ||
197 | LCD_SPU_DMA_START_ADDR_Y1); | ||
198 | armada_reg_queue_set(dplane->vbl.regs, idx, su, | ||
199 | LCD_SPU_DMA_START_ADDR_U1); | ||
200 | armada_reg_queue_set(dplane->vbl.regs, idx, sv, | ||
201 | LCD_SPU_DMA_START_ADDR_V1); | ||
202 | |||
203 | val = fb->pitches[0] << 16 | fb->pitches[0]; | ||
204 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | ||
205 | LCD_SPU_DMA_PITCH_YC); | ||
206 | val = fb->pitches[1] << 16 | fb->pitches[2]; | ||
207 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | ||
208 | LCD_SPU_DMA_PITCH_UV); | ||
209 | } | ||
210 | |||
211 | val = (src_h & 0xffff0000) | src_w >> 16; | ||
212 | if (dplane->src_hw != val) { | ||
213 | dplane->src_hw = val; | ||
214 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | ||
215 | LCD_SPU_DMA_HPXL_VLN); | ||
216 | } | ||
217 | val = crtc_h << 16 | crtc_w; | ||
218 | if (dplane->dst_hw != val) { | ||
219 | dplane->dst_hw = val; | ||
220 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | ||
221 | LCD_SPU_DZM_HPXL_VLN); | ||
222 | } | ||
223 | val = crtc_y << 16 | crtc_x; | ||
224 | if (dplane->dst_yx != val) { | ||
225 | dplane->dst_yx = val; | ||
226 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | ||
227 | LCD_SPU_DMA_OVSA_HPXL_VLN); | ||
228 | } | ||
229 | if (dplane->ctrl0 != ctrl0) { | ||
230 | dplane->ctrl0 = ctrl0; | ||
231 | armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, | ||
232 | CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | | ||
233 | CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | | ||
234 | CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | | ||
235 | CFG_YUV2RGB) | CFG_DMA_ENA, | ||
236 | LCD_SPU_DMA_CTRL0); | ||
237 | } | ||
238 | if (idx) { | ||
239 | armada_reg_queue_end(dplane->vbl.regs, idx); | ||
240 | armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update); | ||
241 | } | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int armada_plane_disable(struct drm_plane *plane) | ||
246 | { | ||
247 | struct armada_plane *dplane = drm_to_armada_plane(plane); | ||
248 | struct drm_framebuffer *fb; | ||
249 | struct armada_crtc *dcrtc; | ||
250 | |||
251 | if (!dplane->base.crtc) | ||
252 | return 0; | ||
253 | |||
254 | dcrtc = drm_to_armada_crtc(dplane->base.crtc); | ||
255 | dcrtc->plane = NULL; | ||
256 | |||
257 | spin_lock_irq(&dcrtc->irq_lock); | ||
258 | armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); | ||
259 | armada_updatel(0, CFG_DMA_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0); | ||
260 | dplane->ctrl0 = 0; | ||
261 | spin_unlock_irq(&dcrtc->irq_lock); | ||
262 | |||
263 | /* Power down the Y/U/V FIFOs */ | ||
264 | armada_updatel(CFG_PDWN16x66 | CFG_PDWN32x66, 0, | ||
265 | dcrtc->base + LCD_SPU_SRAM_PARA1); | ||
266 | |||
267 | if (plane->fb) | ||
268 | drm_framebuffer_unreference(plane->fb); | ||
269 | |||
270 | spin_lock_irq(&dplane->lock); | ||
271 | fb = dplane->old_fb; | ||
272 | dplane->old_fb = NULL; | ||
273 | spin_unlock_irq(&dplane->lock); | ||
274 | if (fb) | ||
275 | drm_framebuffer_unreference(fb); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static void armada_plane_destroy(struct drm_plane *plane) | ||
281 | { | ||
282 | kfree(plane); | ||
283 | } | ||
284 | |||
285 | static int armada_plane_set_property(struct drm_plane *plane, | ||
286 | struct drm_property *property, uint64_t val) | ||
287 | { | ||
288 | struct armada_private *priv = plane->dev->dev_private; | ||
289 | struct armada_plane *dplane = drm_to_armada_plane(plane); | ||
290 | bool update_attr = false; | ||
291 | |||
292 | if (property == priv->colorkey_prop) { | ||
293 | #define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8) | ||
294 | dplane->prop.colorkey_yr = CCC(K2R(val)); | ||
295 | dplane->prop.colorkey_ug = CCC(K2G(val)); | ||
296 | dplane->prop.colorkey_vb = CCC(K2B(val)); | ||
297 | #undef CCC | ||
298 | update_attr = true; | ||
299 | } else if (property == priv->colorkey_min_prop) { | ||
300 | dplane->prop.colorkey_yr &= ~0x00ff0000; | ||
301 | dplane->prop.colorkey_yr |= K2R(val) << 16; | ||
302 | dplane->prop.colorkey_ug &= ~0x00ff0000; | ||
303 | dplane->prop.colorkey_ug |= K2G(val) << 16; | ||
304 | dplane->prop.colorkey_vb &= ~0x00ff0000; | ||
305 | dplane->prop.colorkey_vb |= K2B(val) << 16; | ||
306 | update_attr = true; | ||
307 | } else if (property == priv->colorkey_max_prop) { | ||
308 | dplane->prop.colorkey_yr &= ~0xff000000; | ||
309 | dplane->prop.colorkey_yr |= K2R(val) << 24; | ||
310 | dplane->prop.colorkey_ug &= ~0xff000000; | ||
311 | dplane->prop.colorkey_ug |= K2G(val) << 24; | ||
312 | dplane->prop.colorkey_vb &= ~0xff000000; | ||
313 | dplane->prop.colorkey_vb |= K2B(val) << 24; | ||
314 | update_attr = true; | ||
315 | } else if (property == priv->colorkey_val_prop) { | ||
316 | dplane->prop.colorkey_yr &= ~0x0000ff00; | ||
317 | dplane->prop.colorkey_yr |= K2R(val) << 8; | ||
318 | dplane->prop.colorkey_ug &= ~0x0000ff00; | ||
319 | dplane->prop.colorkey_ug |= K2G(val) << 8; | ||
320 | dplane->prop.colorkey_vb &= ~0x0000ff00; | ||
321 | dplane->prop.colorkey_vb |= K2B(val) << 8; | ||
322 | update_attr = true; | ||
323 | } else if (property == priv->colorkey_alpha_prop) { | ||
324 | dplane->prop.colorkey_yr &= ~0x000000ff; | ||
325 | dplane->prop.colorkey_yr |= K2R(val); | ||
326 | dplane->prop.colorkey_ug &= ~0x000000ff; | ||
327 | dplane->prop.colorkey_ug |= K2G(val); | ||
328 | dplane->prop.colorkey_vb &= ~0x000000ff; | ||
329 | dplane->prop.colorkey_vb |= K2B(val); | ||
330 | update_attr = true; | ||
331 | } else if (property == priv->colorkey_mode_prop) { | ||
332 | dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; | ||
333 | dplane->prop.colorkey_mode |= CFG_CKMODE(val); | ||
334 | update_attr = true; | ||
335 | } else if (property == priv->brightness_prop) { | ||
336 | dplane->prop.brightness = val - 256; | ||
337 | update_attr = true; | ||
338 | } else if (property == priv->contrast_prop) { | ||
339 | dplane->prop.contrast = val; | ||
340 | update_attr = true; | ||
341 | } else if (property == priv->saturation_prop) { | ||
342 | dplane->prop.saturation = val; | ||
343 | update_attr = true; | ||
344 | } | ||
345 | |||
346 | if (update_attr && dplane->base.crtc) | ||
347 | armada_ovl_update_attr(&dplane->prop, | ||
348 | drm_to_armada_crtc(dplane->base.crtc)); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static const struct drm_plane_funcs armada_plane_funcs = { | ||
354 | .update_plane = armada_plane_update, | ||
355 | .disable_plane = armada_plane_disable, | ||
356 | .destroy = armada_plane_destroy, | ||
357 | .set_property = armada_plane_set_property, | ||
358 | }; | ||
359 | |||
360 | static const uint32_t armada_formats[] = { | ||
361 | DRM_FORMAT_UYVY, | ||
362 | DRM_FORMAT_YUYV, | ||
363 | DRM_FORMAT_YUV420, | ||
364 | DRM_FORMAT_YVU420, | ||
365 | DRM_FORMAT_YUV422, | ||
366 | DRM_FORMAT_YVU422, | ||
367 | DRM_FORMAT_VYUY, | ||
368 | DRM_FORMAT_YVYU, | ||
369 | DRM_FORMAT_ARGB8888, | ||
370 | DRM_FORMAT_ABGR8888, | ||
371 | DRM_FORMAT_XRGB8888, | ||
372 | DRM_FORMAT_XBGR8888, | ||
373 | DRM_FORMAT_RGB888, | ||
374 | DRM_FORMAT_BGR888, | ||
375 | DRM_FORMAT_ARGB1555, | ||
376 | DRM_FORMAT_ABGR1555, | ||
377 | DRM_FORMAT_RGB565, | ||
378 | DRM_FORMAT_BGR565, | ||
379 | }; | ||
380 | |||
381 | static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { | ||
382 | { CKMODE_DISABLE, "disabled" }, | ||
383 | { CKMODE_Y, "Y component" }, | ||
384 | { CKMODE_U, "U component" }, | ||
385 | { CKMODE_V, "V component" }, | ||
386 | { CKMODE_RGB, "RGB" }, | ||
387 | { CKMODE_R, "R component" }, | ||
388 | { CKMODE_G, "G component" }, | ||
389 | { CKMODE_B, "B component" }, | ||
390 | }; | ||
391 | |||
392 | static int armada_overlay_create_properties(struct drm_device *dev) | ||
393 | { | ||
394 | struct armada_private *priv = dev->dev_private; | ||
395 | |||
396 | if (priv->colorkey_prop) | ||
397 | return 0; | ||
398 | |||
399 | priv->colorkey_prop = drm_property_create_range(dev, 0, | ||
400 | "colorkey", 0, 0xffffff); | ||
401 | priv->colorkey_min_prop = drm_property_create_range(dev, 0, | ||
402 | "colorkey_min", 0, 0xffffff); | ||
403 | priv->colorkey_max_prop = drm_property_create_range(dev, 0, | ||
404 | "colorkey_max", 0, 0xffffff); | ||
405 | priv->colorkey_val_prop = drm_property_create_range(dev, 0, | ||
406 | "colorkey_val", 0, 0xffffff); | ||
407 | priv->colorkey_alpha_prop = drm_property_create_range(dev, 0, | ||
408 | "colorkey_alpha", 0, 0xffffff); | ||
409 | priv->colorkey_mode_prop = drm_property_create_enum(dev, 0, | ||
410 | "colorkey_mode", | ||
411 | armada_drm_colorkey_enum_list, | ||
412 | ARRAY_SIZE(armada_drm_colorkey_enum_list)); | ||
413 | priv->brightness_prop = drm_property_create_range(dev, 0, | ||
414 | "brightness", 0, 256 + 255); | ||
415 | priv->contrast_prop = drm_property_create_range(dev, 0, | ||
416 | "contrast", 0, 0x7fff); | ||
417 | priv->saturation_prop = drm_property_create_range(dev, 0, | ||
418 | "saturation", 0, 0x7fff); | ||
419 | |||
420 | if (!priv->colorkey_prop) | ||
421 | return -ENOMEM; | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) | ||
427 | { | ||
428 | struct armada_private *priv = dev->dev_private; | ||
429 | struct drm_mode_object *mobj; | ||
430 | struct armada_plane *dplane; | ||
431 | int ret; | ||
432 | |||
433 | ret = armada_overlay_create_properties(dev); | ||
434 | if (ret) | ||
435 | return ret; | ||
436 | |||
437 | dplane = kzalloc(sizeof(*dplane), GFP_KERNEL); | ||
438 | if (!dplane) | ||
439 | return -ENOMEM; | ||
440 | |||
441 | spin_lock_init(&dplane->lock); | ||
442 | init_waitqueue_head(&dplane->vbl.wait); | ||
443 | armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl, | ||
444 | dplane); | ||
445 | |||
446 | drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs, | ||
447 | armada_formats, ARRAY_SIZE(armada_formats), false); | ||
448 | |||
449 | dplane->prop.colorkey_yr = 0xfefefe00; | ||
450 | dplane->prop.colorkey_ug = 0x01010100; | ||
451 | dplane->prop.colorkey_vb = 0x01010100; | ||
452 | dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); | ||
453 | dplane->prop.brightness = 0; | ||
454 | dplane->prop.contrast = 0x4000; | ||
455 | dplane->prop.saturation = 0x4000; | ||
456 | |||
457 | mobj = &dplane->base.base; | ||
458 | drm_object_attach_property(mobj, priv->colorkey_prop, | ||
459 | 0x0101fe); | ||
460 | drm_object_attach_property(mobj, priv->colorkey_min_prop, | ||
461 | 0x0101fe); | ||
462 | drm_object_attach_property(mobj, priv->colorkey_max_prop, | ||
463 | 0x0101fe); | ||
464 | drm_object_attach_property(mobj, priv->colorkey_val_prop, | ||
465 | 0x0101fe); | ||
466 | drm_object_attach_property(mobj, priv->colorkey_alpha_prop, | ||
467 | 0x000000); | ||
468 | drm_object_attach_property(mobj, priv->colorkey_mode_prop, | ||
469 | CKMODE_RGB); | ||
470 | drm_object_attach_property(mobj, priv->brightness_prop, 256); | ||
471 | drm_object_attach_property(mobj, priv->contrast_prop, | ||
472 | dplane->prop.contrast); | ||
473 | drm_object_attach_property(mobj, priv->saturation_prop, | ||
474 | dplane->prop.saturation); | ||
475 | |||
476 | return 0; | ||
477 | } | ||