Commit | Line | Data |
---|---|---|
96f60e37 RK |
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> | |
98fb74f4 | 10 | #include <drm/drm_plane_helper.h> |
96f60e37 RK |
11 | #include "armada_crtc.h" |
12 | #include "armada_drm.h" | |
13 | #include "armada_fb.h" | |
14 | #include "armada_gem.h" | |
15 | #include "armada_hw.h" | |
16 | #include <drm/armada_drm.h> | |
17 | #include "armada_ioctlP.h" | |
18 | ||
28a2aebe | 19 | struct armada_ovl_plane_properties { |
96f60e37 RK |
20 | uint32_t colorkey_yr; |
21 | uint32_t colorkey_ug; | |
22 | uint32_t colorkey_vb; | |
23 | #define K2R(val) (((val) >> 0) & 0xff) | |
24 | #define K2G(val) (((val) >> 8) & 0xff) | |
25 | #define K2B(val) (((val) >> 16) & 0xff) | |
26 | int16_t brightness; | |
27 | uint16_t contrast; | |
28 | uint16_t saturation; | |
29 | uint32_t colorkey_mode; | |
30 | }; | |
31 | ||
28a2aebe | 32 | struct armada_ovl_plane { |
561f60bc | 33 | struct armada_plane base; |
96f60e37 RK |
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 { | |
4a8506d2 | 40 | struct armada_plane_work work; |
96f60e37 | 41 | struct armada_regs regs[13]; |
96f60e37 | 42 | } vbl; |
28a2aebe | 43 | struct armada_ovl_plane_properties prop; |
96f60e37 | 44 | }; |
561f60bc RK |
45 | #define drm_to_armada_ovl_plane(p) \ |
46 | container_of(p, struct armada_ovl_plane, base.base) | |
96f60e37 RK |
47 | |
48 | ||
49 | static void | |
28a2aebe | 50 | armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, |
96f60e37 RK |
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 | ||
fecfdb2d RK |
73 | static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, |
74 | struct drm_framebuffer *fb) | |
75 | { | |
76 | struct drm_framebuffer *old_fb; | |
77 | ||
66377efa | 78 | old_fb = xchg(&dplane->old_fb, fb); |
fecfdb2d RK |
79 | |
80 | if (old_fb) | |
561f60bc | 81 | armada_drm_queue_unref_work(dplane->base.base.dev, old_fb); |
fecfdb2d RK |
82 | } |
83 | ||
96f60e37 | 84 | /* === Plane support === */ |
4a8506d2 RK |
85 | static void armada_ovl_plane_work(struct armada_crtc *dcrtc, |
86 | struct armada_plane *plane, struct armada_plane_work *work) | |
96f60e37 | 87 | { |
4a8506d2 | 88 | struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base); |
96f60e37 RK |
89 | |
90 | armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); | |
fecfdb2d | 91 | armada_ovl_retire_fb(dplane, NULL); |
96f60e37 RK |
92 | } |
93 | ||
96f60e37 | 94 | static int |
28a2aebe | 95 | armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, |
96f60e37 RK |
96 | struct drm_framebuffer *fb, |
97 | int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, | |
98 | uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) | |
99 | { | |
28a2aebe | 100 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); |
96f60e37 | 101 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
98fb74f4 RK |
102 | struct drm_rect src = { |
103 | .x1 = src_x, | |
104 | .y1 = src_y, | |
105 | .x2 = src_x + src_w, | |
106 | .y2 = src_y + src_h, | |
107 | }; | |
108 | struct drm_rect dest = { | |
109 | .x1 = crtc_x, | |
110 | .y1 = crtc_y, | |
111 | .x2 = crtc_x + crtc_w, | |
112 | .y2 = crtc_y + crtc_h, | |
113 | }; | |
114 | const struct drm_rect clip = { | |
115 | .x2 = crtc->mode.hdisplay, | |
116 | .y2 = crtc->mode.vdisplay, | |
117 | }; | |
96f60e37 RK |
118 | uint32_t val, ctrl0; |
119 | unsigned idx = 0; | |
98fb74f4 | 120 | bool visible; |
96f60e37 RK |
121 | int ret; |
122 | ||
98fb74f4 RK |
123 | ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, |
124 | 0, INT_MAX, true, false, &visible); | |
125 | if (ret) | |
126 | return ret; | |
127 | ||
96f60e37 RK |
128 | ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | |
129 | CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | | |
130 | CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; | |
131 | ||
132 | /* Does the position/size result in nothing to display? */ | |
98fb74f4 | 133 | if (!visible) |
96f60e37 | 134 | ctrl0 &= ~CFG_DMA_ENA; |
96f60e37 RK |
135 | |
136 | if (!dcrtc->plane) { | |
137 | dcrtc->plane = plane; | |
138 | armada_ovl_update_attr(&dplane->prop, dcrtc); | |
139 | } | |
140 | ||
141 | /* FIXME: overlay on an interlaced display */ | |
142 | /* Just updating the position/size? */ | |
143 | if (plane->fb == fb && dplane->ctrl0 == ctrl0) { | |
98fb74f4 RK |
144 | val = (drm_rect_height(&src) & 0xffff0000) | |
145 | drm_rect_width(&src) >> 16; | |
96f60e37 RK |
146 | dplane->src_hw = val; |
147 | writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); | |
98fb74f4 RK |
148 | |
149 | val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); | |
96f60e37 RK |
150 | dplane->dst_hw = val; |
151 | writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); | |
98fb74f4 RK |
152 | |
153 | val = dest.y1 << 16 | dest.x1; | |
96f60e37 RK |
154 | dplane->dst_yx = val; |
155 | writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); | |
98fb74f4 | 156 | |
96f60e37 RK |
157 | return 0; |
158 | } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { | |
159 | /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ | |
160 | armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, | |
161 | dcrtc->base + LCD_SPU_SRAM_PARA1); | |
162 | } | |
163 | ||
4a8506d2 RK |
164 | if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0) |
165 | armada_drm_plane_work_cancel(dcrtc, &dplane->base); | |
96f60e37 RK |
166 | |
167 | if (plane->fb != fb) { | |
168 | struct armada_gem_object *obj = drm_fb_obj(fb); | |
73068ce3 RK |
169 | uint32_t addr[3], pixel_format; |
170 | int i, num_planes, hsub; | |
96f60e37 RK |
171 | |
172 | /* | |
173 | * Take a reference on the new framebuffer - we want to | |
174 | * hold on to it while the hardware is displaying it. | |
175 | */ | |
176 | drm_framebuffer_reference(fb); | |
177 | ||
fecfdb2d RK |
178 | if (plane->fb) |
179 | armada_ovl_retire_fb(dplane, plane->fb); | |
96f60e37 | 180 | |
98fb74f4 RK |
181 | src_y = src.y1 >> 16; |
182 | src_x = src.x1 >> 16; | |
73068ce3 RK |
183 | |
184 | pixel_format = fb->pixel_format; | |
185 | hsub = drm_format_horz_chroma_subsampling(pixel_format); | |
186 | num_planes = drm_format_num_planes(pixel_format); | |
187 | ||
188 | /* | |
189 | * Annoyingly, shifting a YUYV-format image by one pixel | |
190 | * causes the U/V planes to toggle. Toggle the UV swap. | |
191 | * (Unfortunately, this causes momentary colour flickering.) | |
192 | */ | |
193 | if (src_x & (hsub - 1) && num_planes == 1) | |
194 | ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); | |
195 | ||
196 | for (i = 0; i < num_planes; i++) | |
197 | addr[i] = obj->dev_addr + fb->offsets[i] + | |
198 | src_y * fb->pitches[i] + | |
199 | src_x * drm_format_plane_cpp(pixel_format, i); | |
200 | for (; i < ARRAY_SIZE(addr); i++) | |
201 | addr[i] = 0; | |
202 | ||
203 | armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], | |
96f60e37 | 204 | LCD_SPU_DMA_START_ADDR_Y0); |
73068ce3 | 205 | armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], |
96f60e37 | 206 | LCD_SPU_DMA_START_ADDR_U0); |
73068ce3 | 207 | armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], |
96f60e37 | 208 | LCD_SPU_DMA_START_ADDR_V0); |
73068ce3 | 209 | armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], |
96f60e37 | 210 | LCD_SPU_DMA_START_ADDR_Y1); |
73068ce3 | 211 | armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], |
96f60e37 | 212 | LCD_SPU_DMA_START_ADDR_U1); |
73068ce3 | 213 | armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], |
96f60e37 RK |
214 | LCD_SPU_DMA_START_ADDR_V1); |
215 | ||
216 | val = fb->pitches[0] << 16 | fb->pitches[0]; | |
217 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | |
218 | LCD_SPU_DMA_PITCH_YC); | |
219 | val = fb->pitches[1] << 16 | fb->pitches[2]; | |
220 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | |
221 | LCD_SPU_DMA_PITCH_UV); | |
222 | } | |
223 | ||
98fb74f4 | 224 | val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; |
96f60e37 RK |
225 | if (dplane->src_hw != val) { |
226 | dplane->src_hw = val; | |
227 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | |
228 | LCD_SPU_DMA_HPXL_VLN); | |
229 | } | |
98fb74f4 RK |
230 | |
231 | val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); | |
96f60e37 RK |
232 | if (dplane->dst_hw != val) { |
233 | dplane->dst_hw = val; | |
234 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | |
235 | LCD_SPU_DZM_HPXL_VLN); | |
236 | } | |
98fb74f4 RK |
237 | |
238 | val = dest.y1 << 16 | dest.x1; | |
96f60e37 RK |
239 | if (dplane->dst_yx != val) { |
240 | dplane->dst_yx = val; | |
241 | armada_reg_queue_set(dplane->vbl.regs, idx, val, | |
242 | LCD_SPU_DMA_OVSA_HPXL_VLN); | |
243 | } | |
98fb74f4 | 244 | |
96f60e37 RK |
245 | if (dplane->ctrl0 != ctrl0) { |
246 | dplane->ctrl0 = ctrl0; | |
247 | armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, | |
248 | CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | | |
249 | CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | | |
250 | CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | | |
251 | CFG_YUV2RGB) | CFG_DMA_ENA, | |
252 | LCD_SPU_DMA_CTRL0); | |
253 | } | |
254 | if (idx) { | |
255 | armada_reg_queue_end(dplane->vbl.regs, idx); | |
4a8506d2 RK |
256 | armada_drm_plane_work_queue(dcrtc, &dplane->base, |
257 | &dplane->vbl.work); | |
96f60e37 RK |
258 | } |
259 | return 0; | |
260 | } | |
261 | ||
28a2aebe | 262 | static int armada_ovl_plane_disable(struct drm_plane *plane) |
96f60e37 | 263 | { |
28a2aebe | 264 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); |
96f60e37 RK |
265 | struct drm_framebuffer *fb; |
266 | struct armada_crtc *dcrtc; | |
267 | ||
561f60bc | 268 | if (!dplane->base.base.crtc) |
96f60e37 RK |
269 | return 0; |
270 | ||
561f60bc | 271 | dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); |
96f60e37 | 272 | |
4a8506d2 RK |
273 | armada_drm_plane_work_cancel(dcrtc, &dplane->base); |
274 | armada_drm_crtc_plane_disable(dcrtc, plane); | |
96f60e37 | 275 | |
4a8506d2 | 276 | dcrtc->plane = NULL; |
5c8752c6 RK |
277 | dplane->ctrl0 = 0; |
278 | ||
66377efa | 279 | fb = xchg(&dplane->old_fb, NULL); |
96f60e37 RK |
280 | if (fb) |
281 | drm_framebuffer_unreference(fb); | |
282 | ||
283 | return 0; | |
284 | } | |
285 | ||
28a2aebe | 286 | static void armada_ovl_plane_destroy(struct drm_plane *plane) |
96f60e37 | 287 | { |
28a2aebe | 288 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); |
41dbb2db RK |
289 | |
290 | drm_plane_cleanup(plane); | |
291 | ||
292 | kfree(dplane); | |
96f60e37 RK |
293 | } |
294 | ||
28a2aebe | 295 | static int armada_ovl_plane_set_property(struct drm_plane *plane, |
96f60e37 RK |
296 | struct drm_property *property, uint64_t val) |
297 | { | |
298 | struct armada_private *priv = plane->dev->dev_private; | |
28a2aebe | 299 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); |
96f60e37 RK |
300 | bool update_attr = false; |
301 | ||
302 | if (property == priv->colorkey_prop) { | |
303 | #define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8) | |
304 | dplane->prop.colorkey_yr = CCC(K2R(val)); | |
305 | dplane->prop.colorkey_ug = CCC(K2G(val)); | |
306 | dplane->prop.colorkey_vb = CCC(K2B(val)); | |
307 | #undef CCC | |
308 | update_attr = true; | |
309 | } else if (property == priv->colorkey_min_prop) { | |
310 | dplane->prop.colorkey_yr &= ~0x00ff0000; | |
311 | dplane->prop.colorkey_yr |= K2R(val) << 16; | |
312 | dplane->prop.colorkey_ug &= ~0x00ff0000; | |
313 | dplane->prop.colorkey_ug |= K2G(val) << 16; | |
314 | dplane->prop.colorkey_vb &= ~0x00ff0000; | |
315 | dplane->prop.colorkey_vb |= K2B(val) << 16; | |
316 | update_attr = true; | |
317 | } else if (property == priv->colorkey_max_prop) { | |
318 | dplane->prop.colorkey_yr &= ~0xff000000; | |
319 | dplane->prop.colorkey_yr |= K2R(val) << 24; | |
320 | dplane->prop.colorkey_ug &= ~0xff000000; | |
321 | dplane->prop.colorkey_ug |= K2G(val) << 24; | |
322 | dplane->prop.colorkey_vb &= ~0xff000000; | |
323 | dplane->prop.colorkey_vb |= K2B(val) << 24; | |
324 | update_attr = true; | |
325 | } else if (property == priv->colorkey_val_prop) { | |
326 | dplane->prop.colorkey_yr &= ~0x0000ff00; | |
327 | dplane->prop.colorkey_yr |= K2R(val) << 8; | |
328 | dplane->prop.colorkey_ug &= ~0x0000ff00; | |
329 | dplane->prop.colorkey_ug |= K2G(val) << 8; | |
330 | dplane->prop.colorkey_vb &= ~0x0000ff00; | |
331 | dplane->prop.colorkey_vb |= K2B(val) << 8; | |
332 | update_attr = true; | |
333 | } else if (property == priv->colorkey_alpha_prop) { | |
334 | dplane->prop.colorkey_yr &= ~0x000000ff; | |
335 | dplane->prop.colorkey_yr |= K2R(val); | |
336 | dplane->prop.colorkey_ug &= ~0x000000ff; | |
337 | dplane->prop.colorkey_ug |= K2G(val); | |
338 | dplane->prop.colorkey_vb &= ~0x000000ff; | |
339 | dplane->prop.colorkey_vb |= K2B(val); | |
340 | update_attr = true; | |
341 | } else if (property == priv->colorkey_mode_prop) { | |
342 | dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; | |
343 | dplane->prop.colorkey_mode |= CFG_CKMODE(val); | |
344 | update_attr = true; | |
345 | } else if (property == priv->brightness_prop) { | |
346 | dplane->prop.brightness = val - 256; | |
347 | update_attr = true; | |
348 | } else if (property == priv->contrast_prop) { | |
349 | dplane->prop.contrast = val; | |
350 | update_attr = true; | |
351 | } else if (property == priv->saturation_prop) { | |
352 | dplane->prop.saturation = val; | |
353 | update_attr = true; | |
354 | } | |
355 | ||
561f60bc | 356 | if (update_attr && dplane->base.base.crtc) |
96f60e37 | 357 | armada_ovl_update_attr(&dplane->prop, |
561f60bc | 358 | drm_to_armada_crtc(dplane->base.base.crtc)); |
96f60e37 RK |
359 | |
360 | return 0; | |
361 | } | |
362 | ||
28a2aebe RK |
363 | static const struct drm_plane_funcs armada_ovl_plane_funcs = { |
364 | .update_plane = armada_ovl_plane_update, | |
365 | .disable_plane = armada_ovl_plane_disable, | |
366 | .destroy = armada_ovl_plane_destroy, | |
367 | .set_property = armada_ovl_plane_set_property, | |
96f60e37 RK |
368 | }; |
369 | ||
28a2aebe | 370 | static const uint32_t armada_ovl_formats[] = { |
96f60e37 RK |
371 | DRM_FORMAT_UYVY, |
372 | DRM_FORMAT_YUYV, | |
373 | DRM_FORMAT_YUV420, | |
374 | DRM_FORMAT_YVU420, | |
375 | DRM_FORMAT_YUV422, | |
376 | DRM_FORMAT_YVU422, | |
377 | DRM_FORMAT_VYUY, | |
378 | DRM_FORMAT_YVYU, | |
379 | DRM_FORMAT_ARGB8888, | |
380 | DRM_FORMAT_ABGR8888, | |
381 | DRM_FORMAT_XRGB8888, | |
382 | DRM_FORMAT_XBGR8888, | |
383 | DRM_FORMAT_RGB888, | |
384 | DRM_FORMAT_BGR888, | |
385 | DRM_FORMAT_ARGB1555, | |
386 | DRM_FORMAT_ABGR1555, | |
387 | DRM_FORMAT_RGB565, | |
388 | DRM_FORMAT_BGR565, | |
389 | }; | |
390 | ||
391 | static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { | |
392 | { CKMODE_DISABLE, "disabled" }, | |
393 | { CKMODE_Y, "Y component" }, | |
394 | { CKMODE_U, "U component" }, | |
395 | { CKMODE_V, "V component" }, | |
396 | { CKMODE_RGB, "RGB" }, | |
397 | { CKMODE_R, "R component" }, | |
398 | { CKMODE_G, "G component" }, | |
399 | { CKMODE_B, "B component" }, | |
400 | }; | |
401 | ||
402 | static int armada_overlay_create_properties(struct drm_device *dev) | |
403 | { | |
404 | struct armada_private *priv = dev->dev_private; | |
405 | ||
406 | if (priv->colorkey_prop) | |
407 | return 0; | |
408 | ||
409 | priv->colorkey_prop = drm_property_create_range(dev, 0, | |
410 | "colorkey", 0, 0xffffff); | |
411 | priv->colorkey_min_prop = drm_property_create_range(dev, 0, | |
412 | "colorkey_min", 0, 0xffffff); | |
413 | priv->colorkey_max_prop = drm_property_create_range(dev, 0, | |
414 | "colorkey_max", 0, 0xffffff); | |
415 | priv->colorkey_val_prop = drm_property_create_range(dev, 0, | |
416 | "colorkey_val", 0, 0xffffff); | |
417 | priv->colorkey_alpha_prop = drm_property_create_range(dev, 0, | |
418 | "colorkey_alpha", 0, 0xffffff); | |
419 | priv->colorkey_mode_prop = drm_property_create_enum(dev, 0, | |
420 | "colorkey_mode", | |
421 | armada_drm_colorkey_enum_list, | |
422 | ARRAY_SIZE(armada_drm_colorkey_enum_list)); | |
423 | priv->brightness_prop = drm_property_create_range(dev, 0, | |
424 | "brightness", 0, 256 + 255); | |
425 | priv->contrast_prop = drm_property_create_range(dev, 0, | |
426 | "contrast", 0, 0x7fff); | |
427 | priv->saturation_prop = drm_property_create_range(dev, 0, | |
428 | "saturation", 0, 0x7fff); | |
429 | ||
430 | if (!priv->colorkey_prop) | |
431 | return -ENOMEM; | |
432 | ||
433 | return 0; | |
434 | } | |
435 | ||
436 | int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) | |
437 | { | |
438 | struct armada_private *priv = dev->dev_private; | |
439 | struct drm_mode_object *mobj; | |
28a2aebe | 440 | struct armada_ovl_plane *dplane; |
96f60e37 RK |
441 | int ret; |
442 | ||
443 | ret = armada_overlay_create_properties(dev); | |
444 | if (ret) | |
445 | return ret; | |
446 | ||
447 | dplane = kzalloc(sizeof(*dplane), GFP_KERNEL); | |
448 | if (!dplane) | |
449 | return -ENOMEM; | |
450 | ||
5740d27f RK |
451 | ret = armada_drm_plane_init(&dplane->base); |
452 | if (ret) { | |
453 | kfree(dplane); | |
454 | return ret; | |
455 | } | |
456 | ||
4a8506d2 | 457 | dplane->vbl.work.fn = armada_ovl_plane_work; |
96f60e37 | 458 | |
561f60bc | 459 | ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, |
d563c245 RK |
460 | &armada_ovl_plane_funcs, |
461 | armada_ovl_formats, | |
462 | ARRAY_SIZE(armada_ovl_formats), | |
463 | DRM_PLANE_TYPE_OVERLAY); | |
28a2aebe RK |
464 | if (ret) { |
465 | kfree(dplane); | |
466 | return ret; | |
467 | } | |
96f60e37 RK |
468 | |
469 | dplane->prop.colorkey_yr = 0xfefefe00; | |
470 | dplane->prop.colorkey_ug = 0x01010100; | |
471 | dplane->prop.colorkey_vb = 0x01010100; | |
472 | dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); | |
473 | dplane->prop.brightness = 0; | |
474 | dplane->prop.contrast = 0x4000; | |
475 | dplane->prop.saturation = 0x4000; | |
476 | ||
561f60bc | 477 | mobj = &dplane->base.base.base; |
96f60e37 RK |
478 | drm_object_attach_property(mobj, priv->colorkey_prop, |
479 | 0x0101fe); | |
480 | drm_object_attach_property(mobj, priv->colorkey_min_prop, | |
481 | 0x0101fe); | |
482 | drm_object_attach_property(mobj, priv->colorkey_max_prop, | |
483 | 0x0101fe); | |
484 | drm_object_attach_property(mobj, priv->colorkey_val_prop, | |
485 | 0x0101fe); | |
486 | drm_object_attach_property(mobj, priv->colorkey_alpha_prop, | |
487 | 0x000000); | |
488 | drm_object_attach_property(mobj, priv->colorkey_mode_prop, | |
489 | CKMODE_RGB); | |
490 | drm_object_attach_property(mobj, priv->brightness_prop, 256); | |
491 | drm_object_attach_property(mobj, priv->contrast_prop, | |
492 | dplane->prop.contrast); | |
493 | drm_object_attach_property(mobj, priv->saturation_prop, | |
494 | dplane->prop.saturation); | |
495 | ||
496 | return 0; | |
497 | } |