]> Git Repo - linux.git/blob - drivers/gpu/drm/sun4i/sun8i_vi_layer.c
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux.git] / drivers / gpu / drm / sun4i / sun8i_vi_layer.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) Jernej Skrabec <[email protected]>
4  */
5
6 #include <drm/drm_atomic.h>
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_blend.h>
9 #include <drm/drm_crtc.h>
10 #include <drm/drm_fb_cma_helper.h>
11 #include <drm/drm_framebuffer.h>
12 #include <drm/drm_gem_atomic_helper.h>
13 #include <drm/drm_gem_cma_helper.h>
14 #include <drm/drm_plane_helper.h>
15 #include <drm/drm_probe_helper.h>
16
17 #include "sun8i_csc.h"
18 #include "sun8i_mixer.h"
19 #include "sun8i_vi_layer.h"
20 #include "sun8i_vi_scaler.h"
21
22 static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
23                                   int overlay, bool enable, unsigned int zpos,
24                                   unsigned int old_zpos)
25 {
26         u32 val, bld_base, ch_base;
27
28         bld_base = sun8i_blender_base(mixer);
29         ch_base = sun8i_channel_base(mixer, channel);
30
31         DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
32                          enable ? "En" : "Dis", channel, overlay);
33
34         if (enable)
35                 val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
36         else
37                 val = 0;
38
39         regmap_update_bits(mixer->engine.regs,
40                            SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
41                            SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
42
43         if (!enable || zpos != old_zpos) {
44                 regmap_update_bits(mixer->engine.regs,
45                                    SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
46                                    SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
47                                    0);
48
49                 regmap_update_bits(mixer->engine.regs,
50                                    SUN8I_MIXER_BLEND_ROUTE(bld_base),
51                                    SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
52                                    0);
53         }
54
55         if (enable) {
56                 val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
57
58                 regmap_update_bits(mixer->engine.regs,
59                                    SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
60                                    val, val);
61
62                 val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
63
64                 regmap_update_bits(mixer->engine.regs,
65                                    SUN8I_MIXER_BLEND_ROUTE(bld_base),
66                                    SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
67                                    val);
68         }
69 }
70
71 static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
72                                         int overlay, struct drm_plane *plane)
73 {
74         u32 mask, val, ch_base;
75
76         ch_base = sun8i_channel_base(mixer, channel);
77
78         if (mixer->cfg->is_de3) {
79                 mask = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK |
80                        SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK;
81                 val = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA
82                         (plane->state->alpha >> 8);
83
84                 val |= (plane->state->alpha == DRM_BLEND_ALPHA_OPAQUE) ?
85                         SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_PIXEL :
86                         SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_COMBINED;
87
88                 regmap_update_bits(mixer->engine.regs,
89                                    SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base,
90                                                                   overlay),
91                                    mask, val);
92         } else if (mixer->cfg->vi_num == 1) {
93                 regmap_update_bits(mixer->engine.regs,
94                                    SUN8I_MIXER_FCC_GLOBAL_ALPHA_REG,
95                                    SUN8I_MIXER_FCC_GLOBAL_ALPHA_MASK,
96                                    SUN8I_MIXER_FCC_GLOBAL_ALPHA
97                                         (plane->state->alpha >> 8));
98         }
99 }
100
101 static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
102                                        int overlay, struct drm_plane *plane,
103                                        unsigned int zpos)
104 {
105         struct drm_plane_state *state = plane->state;
106         const struct drm_format_info *format = state->fb->format;
107         u32 src_w, src_h, dst_w, dst_h;
108         u32 bld_base, ch_base;
109         u32 outsize, insize;
110         u32 hphase, vphase;
111         u32 hn = 0, hm = 0;
112         u32 vn = 0, vm = 0;
113         bool subsampled;
114
115         DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
116                          channel, overlay);
117
118         bld_base = sun8i_blender_base(mixer);
119         ch_base = sun8i_channel_base(mixer, channel);
120
121         src_w = drm_rect_width(&state->src) >> 16;
122         src_h = drm_rect_height(&state->src) >> 16;
123         dst_w = drm_rect_width(&state->dst);
124         dst_h = drm_rect_height(&state->dst);
125
126         hphase = state->src.x1 & 0xffff;
127         vphase = state->src.y1 & 0xffff;
128
129         /* make coordinates dividable by subsampling factor */
130         if (format->hsub > 1) {
131                 int mask, remainder;
132
133                 mask = format->hsub - 1;
134                 remainder = (state->src.x1 >> 16) & mask;
135                 src_w = (src_w + remainder) & ~mask;
136                 hphase += remainder << 16;
137         }
138
139         if (format->vsub > 1) {
140                 int mask, remainder;
141
142                 mask = format->vsub - 1;
143                 remainder = (state->src.y1 >> 16) & mask;
144                 src_h = (src_h + remainder) & ~mask;
145                 vphase += remainder << 16;
146         }
147
148         insize = SUN8I_MIXER_SIZE(src_w, src_h);
149         outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
150
151         /* Set height and width */
152         DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
153                          (state->src.x1 >> 16) & ~(format->hsub - 1),
154                          (state->src.y1 >> 16) & ~(format->vsub - 1));
155         DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
156         regmap_write(mixer->engine.regs,
157                      SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch_base, overlay),
158                      insize);
159         regmap_write(mixer->engine.regs,
160                      SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch_base),
161                      insize);
162
163         /*
164          * Scaler must be enabled for subsampled formats, so it scales
165          * chroma to same size as luma.
166          */
167         subsampled = format->hsub > 1 || format->vsub > 1;
168
169         if (insize != outsize || subsampled || hphase || vphase) {
170                 unsigned int scanline, required;
171                 struct drm_display_mode *mode;
172                 u32 hscale, vscale, fps;
173                 u64 ability;
174
175                 DRM_DEBUG_DRIVER("HW scaling is enabled\n");
176
177                 mode = &plane->state->crtc->state->mode;
178                 fps = (mode->clock * 1000) / (mode->vtotal * mode->htotal);
179                 ability = clk_get_rate(mixer->mod_clk);
180                 /* BSP algorithm assumes 80% efficiency of VI scaler unit */
181                 ability *= 80;
182                 do_div(ability, mode->vdisplay * fps * max(src_w, dst_w));
183
184                 required = src_h * 100 / dst_h;
185
186                 if (ability < required) {
187                         DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
188                         vm = src_h;
189                         vn = (u32)ability * dst_h / 100;
190                         src_h = vn;
191                 }
192
193                 /* it seems that every RGB scaler has buffer for 2048 pixels */
194                 scanline = subsampled ? mixer->cfg->scanline_yuv : 2048;
195
196                 if (src_w > scanline) {
197                         DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
198                         hm = src_w;
199                         hn = scanline;
200                         src_w = hn;
201                 }
202
203                 hscale = (src_w << 16) / dst_w;
204                 vscale = (src_h << 16) / dst_h;
205
206                 sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
207                                       dst_h, hscale, vscale, hphase, vphase,
208                                       format);
209                 sun8i_vi_scaler_enable(mixer, channel, true);
210         } else {
211                 DRM_DEBUG_DRIVER("HW scaling is not needed\n");
212                 sun8i_vi_scaler_enable(mixer, channel, false);
213         }
214
215         regmap_write(mixer->engine.regs,
216                      SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
217                      SUN8I_MIXER_CHAN_VI_DS_N(hn) |
218                      SUN8I_MIXER_CHAN_VI_DS_M(hm));
219         regmap_write(mixer->engine.regs,
220                      SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
221                      SUN8I_MIXER_CHAN_VI_DS_N(hn) |
222                      SUN8I_MIXER_CHAN_VI_DS_M(hm));
223         regmap_write(mixer->engine.regs,
224                      SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
225                      SUN8I_MIXER_CHAN_VI_DS_N(vn) |
226                      SUN8I_MIXER_CHAN_VI_DS_M(vm));
227         regmap_write(mixer->engine.regs,
228                      SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
229                      SUN8I_MIXER_CHAN_VI_DS_N(vn) |
230                      SUN8I_MIXER_CHAN_VI_DS_M(vm));
231
232         /* Set base coordinates */
233         DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
234                          state->dst.x1, state->dst.y1);
235         DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
236         regmap_write(mixer->engine.regs,
237                      SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
238                      SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
239         regmap_write(mixer->engine.regs,
240                      SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
241                      outsize);
242
243         return 0;
244 }
245
246 static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
247 {
248         if (!format->is_yuv)
249                 return SUN8I_CSC_MODE_OFF;
250
251         switch (format->format) {
252         case DRM_FORMAT_YVU411:
253         case DRM_FORMAT_YVU420:
254         case DRM_FORMAT_YVU422:
255         case DRM_FORMAT_YVU444:
256                 return SUN8I_CSC_MODE_YVU2RGB;
257         default:
258                 return SUN8I_CSC_MODE_YUV2RGB;
259         }
260 }
261
262 static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
263                                          int overlay, struct drm_plane *plane)
264 {
265         struct drm_plane_state *state = plane->state;
266         u32 val, ch_base, csc_mode, hw_fmt;
267         const struct drm_format_info *fmt;
268         int ret;
269
270         ch_base = sun8i_channel_base(mixer, channel);
271
272         fmt = state->fb->format;
273         ret = sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
274         if (ret) {
275                 DRM_DEBUG_DRIVER("Invalid format\n");
276                 return ret;
277         }
278
279         val = hw_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
280         regmap_update_bits(mixer->engine.regs,
281                            SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
282                            SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
283
284         csc_mode = sun8i_vi_layer_get_csc_mode(fmt);
285         if (csc_mode != SUN8I_CSC_MODE_OFF) {
286                 sun8i_csc_set_ccsc_coefficients(mixer, channel, csc_mode,
287                                                 state->color_encoding,
288                                                 state->color_range);
289                 sun8i_csc_enable_ccsc(mixer, channel, true);
290         } else {
291                 sun8i_csc_enable_ccsc(mixer, channel, false);
292         }
293
294         if (!fmt->is_yuv)
295                 val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE;
296         else
297                 val = 0;
298
299         regmap_update_bits(mixer->engine.regs,
300                            SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
301                            SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val);
302
303         return 0;
304 }
305
306 static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
307                                         int overlay, struct drm_plane *plane)
308 {
309         struct drm_plane_state *state = plane->state;
310         struct drm_framebuffer *fb = state->fb;
311         const struct drm_format_info *format = fb->format;
312         struct drm_gem_cma_object *gem;
313         u32 dx, dy, src_x, src_y;
314         dma_addr_t paddr;
315         u32 ch_base;
316         int i;
317
318         ch_base = sun8i_channel_base(mixer, channel);
319
320         /* Adjust x and y to be dividable by subsampling factor */
321         src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
322         src_y = (state->src.y1 >> 16) & ~(format->vsub - 1);
323
324         for (i = 0; i < format->num_planes; i++) {
325                 /* Get the physical address of the buffer in memory */
326                 gem = drm_fb_cma_get_gem_obj(fb, i);
327
328                 DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
329
330                 /* Compute the start of the displayed memory */
331                 paddr = gem->paddr + fb->offsets[i];
332
333                 dx = src_x;
334                 dy = src_y;
335
336                 if (i > 0) {
337                         dx /= format->hsub;
338                         dy /= format->vsub;
339                 }
340
341                 /* Fixup framebuffer address for src coordinates */
342                 paddr += dx * format->cpp[i];
343                 paddr += dy * fb->pitches[i];
344
345                 /* Set the line width */
346                 DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
347                                  i + 1, fb->pitches[i]);
348                 regmap_write(mixer->engine.regs,
349                              SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch_base,
350                                                              overlay, i),
351                              fb->pitches[i]);
352
353                 DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
354                                  i + 1, &paddr);
355
356                 regmap_write(mixer->engine.regs,
357                              SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base,
358                                                                  overlay, i),
359                              lower_32_bits(paddr));
360         }
361
362         return 0;
363 }
364
365 static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
366                                        struct drm_atomic_state *state)
367 {
368         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
369                                                                                  plane);
370         struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
371         struct drm_crtc *crtc = new_plane_state->crtc;
372         struct drm_crtc_state *crtc_state;
373         int min_scale, max_scale;
374
375         if (!crtc)
376                 return 0;
377
378         crtc_state = drm_atomic_get_existing_crtc_state(state,
379                                                         crtc);
380         if (WARN_ON(!crtc_state))
381                 return -EINVAL;
382
383         min_scale = DRM_PLANE_HELPER_NO_SCALING;
384         max_scale = DRM_PLANE_HELPER_NO_SCALING;
385
386         if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) {
387                 min_scale = SUN8I_VI_SCALER_SCALE_MIN;
388                 max_scale = SUN8I_VI_SCALER_SCALE_MAX;
389         }
390
391         return drm_atomic_helper_check_plane_state(new_plane_state,
392                                                    crtc_state,
393                                                    min_scale, max_scale,
394                                                    true, true);
395 }
396
397 static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
398                                           struct drm_atomic_state *state)
399 {
400         struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
401                                                                            plane);
402         struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
403         unsigned int old_zpos = old_state->normalized_zpos;
404         struct sun8i_mixer *mixer = layer->mixer;
405
406         sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
407                               old_zpos);
408 }
409
410 static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
411                                          struct drm_atomic_state *state)
412 {
413         struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
414                                                                            plane);
415         struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
416                                                                            plane);
417         struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
418         unsigned int zpos = new_state->normalized_zpos;
419         unsigned int old_zpos = old_state->normalized_zpos;
420         struct sun8i_mixer *mixer = layer->mixer;
421
422         if (!new_state->visible) {
423                 sun8i_vi_layer_enable(mixer, layer->channel,
424                                       layer->overlay, false, 0, old_zpos);
425                 return;
426         }
427
428         sun8i_vi_layer_update_coord(mixer, layer->channel,
429                                     layer->overlay, plane, zpos);
430         sun8i_vi_layer_update_alpha(mixer, layer->channel,
431                                     layer->overlay, plane);
432         sun8i_vi_layer_update_formats(mixer, layer->channel,
433                                       layer->overlay, plane);
434         sun8i_vi_layer_update_buffer(mixer, layer->channel,
435                                      layer->overlay, plane);
436         sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
437                               true, zpos, old_zpos);
438 }
439
440 static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
441         .atomic_check   = sun8i_vi_layer_atomic_check,
442         .atomic_disable = sun8i_vi_layer_atomic_disable,
443         .atomic_update  = sun8i_vi_layer_atomic_update,
444 };
445
446 static const struct drm_plane_funcs sun8i_vi_layer_funcs = {
447         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
448         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
449         .destroy                = drm_plane_cleanup,
450         .disable_plane          = drm_atomic_helper_disable_plane,
451         .reset                  = drm_atomic_helper_plane_reset,
452         .update_plane           = drm_atomic_helper_update_plane,
453 };
454
455 /*
456  * While DE2 VI layer supports same RGB formats as UI layer, alpha
457  * channel is ignored. This structure lists all unique variants
458  * where alpha channel is replaced with "don't care" (X) channel.
459  */
460 static const u32 sun8i_vi_layer_formats[] = {
461         DRM_FORMAT_BGR565,
462         DRM_FORMAT_BGR888,
463         DRM_FORMAT_BGRX4444,
464         DRM_FORMAT_BGRX5551,
465         DRM_FORMAT_BGRX8888,
466         DRM_FORMAT_RGB565,
467         DRM_FORMAT_RGB888,
468         DRM_FORMAT_RGBX4444,
469         DRM_FORMAT_RGBX5551,
470         DRM_FORMAT_RGBX8888,
471         DRM_FORMAT_XBGR1555,
472         DRM_FORMAT_XBGR4444,
473         DRM_FORMAT_XBGR8888,
474         DRM_FORMAT_XRGB1555,
475         DRM_FORMAT_XRGB4444,
476         DRM_FORMAT_XRGB8888,
477
478         DRM_FORMAT_NV16,
479         DRM_FORMAT_NV12,
480         DRM_FORMAT_NV21,
481         DRM_FORMAT_NV61,
482         DRM_FORMAT_UYVY,
483         DRM_FORMAT_VYUY,
484         DRM_FORMAT_YUYV,
485         DRM_FORMAT_YVYU,
486         DRM_FORMAT_YUV411,
487         DRM_FORMAT_YUV420,
488         DRM_FORMAT_YUV422,
489         DRM_FORMAT_YVU411,
490         DRM_FORMAT_YVU420,
491         DRM_FORMAT_YVU422,
492 };
493
494 static const u32 sun8i_vi_layer_de3_formats[] = {
495         DRM_FORMAT_ABGR1555,
496         DRM_FORMAT_ABGR2101010,
497         DRM_FORMAT_ABGR4444,
498         DRM_FORMAT_ABGR8888,
499         DRM_FORMAT_ARGB1555,
500         DRM_FORMAT_ARGB2101010,
501         DRM_FORMAT_ARGB4444,
502         DRM_FORMAT_ARGB8888,
503         DRM_FORMAT_BGR565,
504         DRM_FORMAT_BGR888,
505         DRM_FORMAT_BGRA1010102,
506         DRM_FORMAT_BGRA5551,
507         DRM_FORMAT_BGRA4444,
508         DRM_FORMAT_BGRA8888,
509         DRM_FORMAT_BGRX8888,
510         DRM_FORMAT_RGB565,
511         DRM_FORMAT_RGB888,
512         DRM_FORMAT_RGBA1010102,
513         DRM_FORMAT_RGBA4444,
514         DRM_FORMAT_RGBA5551,
515         DRM_FORMAT_RGBA8888,
516         DRM_FORMAT_RGBX8888,
517         DRM_FORMAT_XBGR8888,
518         DRM_FORMAT_XRGB8888,
519
520         DRM_FORMAT_NV16,
521         DRM_FORMAT_NV12,
522         DRM_FORMAT_NV21,
523         DRM_FORMAT_NV61,
524         DRM_FORMAT_P010,
525         DRM_FORMAT_P210,
526         DRM_FORMAT_UYVY,
527         DRM_FORMAT_VYUY,
528         DRM_FORMAT_YUYV,
529         DRM_FORMAT_YVYU,
530         DRM_FORMAT_YUV411,
531         DRM_FORMAT_YUV420,
532         DRM_FORMAT_YUV422,
533         DRM_FORMAT_YVU411,
534         DRM_FORMAT_YVU420,
535         DRM_FORMAT_YVU422,
536 };
537
538 static const uint64_t sun8i_layer_modifiers[] = {
539         DRM_FORMAT_MOD_LINEAR,
540         DRM_FORMAT_MOD_INVALID
541 };
542
543 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
544                                                struct sun8i_mixer *mixer,
545                                                int index)
546 {
547         enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
548         u32 supported_encodings, supported_ranges;
549         unsigned int plane_cnt, format_count;
550         struct sun8i_vi_layer *layer;
551         const u32 *formats;
552         int ret;
553
554         layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
555         if (!layer)
556                 return ERR_PTR(-ENOMEM);
557
558         if (mixer->cfg->is_de3) {
559                 formats = sun8i_vi_layer_de3_formats;
560                 format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
561         } else {
562                 formats = sun8i_vi_layer_formats;
563                 format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
564         }
565
566         if (!mixer->cfg->ui_num && index == 0)
567                 type = DRM_PLANE_TYPE_PRIMARY;
568
569         /* possible crtcs are set later */
570         ret = drm_universal_plane_init(drm, &layer->plane, 0,
571                                        &sun8i_vi_layer_funcs,
572                                        formats, format_count,
573                                        sun8i_layer_modifiers,
574                                        type, NULL);
575         if (ret) {
576                 dev_err(drm->dev, "Couldn't initialize layer\n");
577                 return ERR_PTR(ret);
578         }
579
580         plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
581
582         if (mixer->cfg->vi_num == 1 || mixer->cfg->is_de3) {
583                 ret = drm_plane_create_alpha_property(&layer->plane);
584                 if (ret) {
585                         dev_err(drm->dev, "Couldn't add alpha property\n");
586                         return ERR_PTR(ret);
587                 }
588         }
589
590         ret = drm_plane_create_zpos_property(&layer->plane, index,
591                                              0, plane_cnt - 1);
592         if (ret) {
593                 dev_err(drm->dev, "Couldn't add zpos property\n");
594                 return ERR_PTR(ret);
595         }
596
597         supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
598                               BIT(DRM_COLOR_YCBCR_BT709);
599         if (mixer->cfg->is_de3)
600                 supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020);
601
602         supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
603                            BIT(DRM_COLOR_YCBCR_FULL_RANGE);
604
605         ret = drm_plane_create_color_properties(&layer->plane,
606                                                 supported_encodings,
607                                                 supported_ranges,
608                                                 DRM_COLOR_YCBCR_BT709,
609                                                 DRM_COLOR_YCBCR_LIMITED_RANGE);
610         if (ret) {
611                 dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
612                 return ERR_PTR(ret);
613         }
614
615         drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
616         layer->mixer = mixer;
617         layer->channel = index;
618         layer->overlay = 0;
619
620         return layer;
621 }
This page took 0.0712 seconds and 4 git commands to generate.