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