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