]> Git Repo - J-linux.git/blob - drivers/gpu/drm/tegra/plane.c
Merge tag 'tpmdd-next-v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko...
[J-linux.git] / drivers / gpu / drm / tegra / plane.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2017 NVIDIA CORPORATION.  All rights reserved.
4  */
5
6 #include <linux/dma-mapping.h>
7 #include <linux/iommu.h>
8 #include <linux/interconnect.h>
9
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <drm/drm_fourcc.h>
13 #include <drm/drm_framebuffer.h>
14 #include <drm/drm_gem_atomic_helper.h>
15 #include <drm/drm_plane_helper.h>
16
17 #include "dc.h"
18 #include "plane.h"
19
20 static void tegra_plane_destroy(struct drm_plane *plane)
21 {
22         struct tegra_plane *p = to_tegra_plane(plane);
23
24         drm_plane_cleanup(plane);
25         kfree(p);
26 }
27
28 static void tegra_plane_reset(struct drm_plane *plane)
29 {
30         struct tegra_plane *p = to_tegra_plane(plane);
31         struct tegra_plane_state *state;
32         unsigned int i;
33
34         if (plane->state)
35                 __drm_atomic_helper_plane_destroy_state(plane->state);
36
37         kfree(plane->state);
38         plane->state = NULL;
39
40         state = kzalloc(sizeof(*state), GFP_KERNEL);
41         if (state) {
42                 plane->state = &state->base;
43                 plane->state->plane = plane;
44                 plane->state->zpos = p->index;
45                 plane->state->normalized_zpos = p->index;
46
47                 for (i = 0; i < 3; i++)
48                         state->iova[i] = DMA_MAPPING_ERROR;
49         }
50 }
51
52 static struct drm_plane_state *
53 tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
54 {
55         struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
56         struct tegra_plane_state *copy;
57         unsigned int i;
58
59         copy = kmalloc(sizeof(*copy), GFP_KERNEL);
60         if (!copy)
61                 return NULL;
62
63         __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
64         copy->tiling = state->tiling;
65         copy->format = state->format;
66         copy->swap = state->swap;
67         copy->reflect_x = state->reflect_x;
68         copy->reflect_y = state->reflect_y;
69         copy->opaque = state->opaque;
70         copy->total_peak_memory_bandwidth = state->total_peak_memory_bandwidth;
71         copy->peak_memory_bandwidth = state->peak_memory_bandwidth;
72         copy->avg_memory_bandwidth = state->avg_memory_bandwidth;
73
74         for (i = 0; i < 2; i++)
75                 copy->blending[i] = state->blending[i];
76
77         for (i = 0; i < 3; i++) {
78                 copy->iova[i] = DMA_MAPPING_ERROR;
79                 copy->map[i] = NULL;
80         }
81
82         return &copy->base;
83 }
84
85 static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
86                                              struct drm_plane_state *state)
87 {
88         __drm_atomic_helper_plane_destroy_state(state);
89         kfree(state);
90 }
91
92 static bool tegra_plane_supports_sector_layout(struct drm_plane *plane)
93 {
94         struct drm_crtc *crtc;
95
96         drm_for_each_crtc(crtc, plane->dev) {
97                 if (plane->possible_crtcs & drm_crtc_mask(crtc)) {
98                         struct tegra_dc *dc = to_tegra_dc(crtc);
99
100                         if (!dc->soc->supports_sector_layout)
101                                 return false;
102                 }
103         }
104
105         return true;
106 }
107
108 static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
109                                              uint32_t format,
110                                              uint64_t modifier)
111 {
112         const struct drm_format_info *info = drm_format_info(format);
113
114         if (modifier == DRM_FORMAT_MOD_LINEAR)
115                 return true;
116
117         /* check for the sector layout bit */
118         if (fourcc_mod_is_vendor(modifier, NVIDIA)) {
119                 if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) {
120                         if (!tegra_plane_supports_sector_layout(plane))
121                                 return false;
122                 }
123         }
124
125         if (info->num_planes == 1)
126                 return true;
127
128         return false;
129 }
130
131 const struct drm_plane_funcs tegra_plane_funcs = {
132         .update_plane = drm_atomic_helper_update_plane,
133         .disable_plane = drm_atomic_helper_disable_plane,
134         .destroy = tegra_plane_destroy,
135         .reset = tegra_plane_reset,
136         .atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
137         .atomic_destroy_state = tegra_plane_atomic_destroy_state,
138         .format_mod_supported = tegra_plane_format_mod_supported,
139 };
140
141 static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state)
142 {
143         unsigned int i;
144         int err;
145
146         for (i = 0; i < state->base.fb->format->num_planes; i++) {
147                 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
148                 struct host1x_bo_mapping *map;
149
150                 map = host1x_bo_pin(dc->dev, &bo->base, DMA_TO_DEVICE, &dc->client.cache);
151                 if (IS_ERR(map)) {
152                         err = PTR_ERR(map);
153                         goto unpin;
154                 }
155
156                 if (!dc->client.group) {
157                         /*
158                          * The display controller needs contiguous memory, so
159                          * fail if the buffer is discontiguous and we fail to
160                          * map its SG table to a single contiguous chunk of
161                          * I/O virtual memory.
162                          */
163                         if (map->chunks > 1) {
164                                 err = -EINVAL;
165                                 goto unpin;
166                         }
167
168                         state->iova[i] = map->phys;
169                 } else {
170                         state->iova[i] = bo->iova;
171                 }
172
173                 state->map[i] = map;
174         }
175
176         return 0;
177
178 unpin:
179         dev_err(dc->dev, "failed to map plane %u: %d\n", i, err);
180
181         while (i--) {
182                 host1x_bo_unpin(state->map[i]);
183                 state->iova[i] = DMA_MAPPING_ERROR;
184                 state->map[i] = NULL;
185         }
186
187         return err;
188 }
189
190 static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state)
191 {
192         unsigned int i;
193
194         for (i = 0; i < state->base.fb->format->num_planes; i++) {
195                 host1x_bo_unpin(state->map[i]);
196                 state->iova[i] = DMA_MAPPING_ERROR;
197                 state->map[i] = NULL;
198         }
199 }
200
201 int tegra_plane_prepare_fb(struct drm_plane *plane,
202                            struct drm_plane_state *state)
203 {
204         struct tegra_dc *dc = to_tegra_dc(state->crtc);
205         int err;
206
207         if (!state->fb)
208                 return 0;
209
210         err = drm_gem_plane_helper_prepare_fb(plane, state);
211         if (err < 0)
212                 return err;
213
214         return tegra_dc_pin(dc, to_tegra_plane_state(state));
215 }
216
217 void tegra_plane_cleanup_fb(struct drm_plane *plane,
218                             struct drm_plane_state *state)
219 {
220         struct tegra_dc *dc = to_tegra_dc(state->crtc);
221
222         if (dc)
223                 tegra_dc_unpin(dc, to_tegra_plane_state(state));
224 }
225
226 static int tegra_plane_calculate_memory_bandwidth(struct drm_plane_state *state)
227 {
228         struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
229         unsigned int i, bpp, dst_w, dst_h, src_w, src_h, mul;
230         const struct tegra_dc_soc_info *soc;
231         const struct drm_format_info *fmt;
232         struct drm_crtc_state *crtc_state;
233         u64 avg_bandwidth, peak_bandwidth;
234
235         if (!state->visible)
236                 return 0;
237
238         crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
239         if (!crtc_state)
240                 return -EINVAL;
241
242         src_w = drm_rect_width(&state->src) >> 16;
243         src_h = drm_rect_height(&state->src) >> 16;
244         dst_w = drm_rect_width(&state->dst);
245         dst_h = drm_rect_height(&state->dst);
246
247         fmt = state->fb->format;
248         soc = to_tegra_dc(state->crtc)->soc;
249
250         /*
251          * Note that real memory bandwidth vary depending on format and
252          * memory layout, we are not taking that into account because small
253          * estimation error isn't important since bandwidth is rounded up
254          * anyway.
255          */
256         for (i = 0, bpp = 0; i < fmt->num_planes; i++) {
257                 unsigned int bpp_plane = fmt->cpp[i] * 8;
258
259                 /*
260                  * Sub-sampling is relevant for chroma planes only and vertical
261                  * readouts are not cached, hence only horizontal sub-sampling
262                  * matters.
263                  */
264                 if (i > 0)
265                         bpp_plane /= fmt->hsub;
266
267                 bpp += bpp_plane;
268         }
269
270         /* average bandwidth in kbytes/sec */
271         avg_bandwidth  = min(src_w, dst_w) * min(src_h, dst_h);
272         avg_bandwidth *= drm_mode_vrefresh(&crtc_state->adjusted_mode);
273         avg_bandwidth  = DIV_ROUND_UP(avg_bandwidth * bpp, 8) + 999;
274         do_div(avg_bandwidth, 1000);
275
276         /* mode.clock in kHz, peak bandwidth in kbytes/sec */
277         peak_bandwidth = DIV_ROUND_UP(crtc_state->adjusted_mode.clock * bpp, 8);
278
279         /*
280          * Tegra30/114 Memory Controller can't interleave DC memory requests
281          * for the tiled windows because DC uses 16-bytes atom, while DDR3
282          * uses 32-bytes atom.  Hence there is x2 memory overfetch for tiled
283          * framebuffer and DDR3 on these SoCs.
284          */
285         if (soc->plane_tiled_memory_bandwidth_x2 &&
286             tegra_state->tiling.mode == TEGRA_BO_TILING_MODE_TILED)
287                 mul = 2;
288         else
289                 mul = 1;
290
291         /* ICC bandwidth in kbytes/sec */
292         tegra_state->peak_memory_bandwidth = kBps_to_icc(peak_bandwidth) * mul;
293         tegra_state->avg_memory_bandwidth  = kBps_to_icc(avg_bandwidth)  * mul;
294
295         return 0;
296 }
297
298 int tegra_plane_state_add(struct tegra_plane *plane,
299                           struct drm_plane_state *state)
300 {
301         struct drm_crtc_state *crtc_state;
302         struct tegra_dc_state *tegra;
303         int err;
304
305         /* Propagate errors from allocation or locking failures. */
306         crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
307         if (IS_ERR(crtc_state))
308                 return PTR_ERR(crtc_state);
309
310         /* Check plane state for visibility and calculate clipping bounds */
311         err = drm_atomic_helper_check_plane_state(state, crtc_state,
312                                                   0, INT_MAX, true, true);
313         if (err < 0)
314                 return err;
315
316         err = tegra_plane_calculate_memory_bandwidth(state);
317         if (err < 0)
318                 return err;
319
320         tegra = to_dc_state(crtc_state);
321
322         tegra->planes |= WIN_A_ACT_REQ << plane->index;
323
324         return 0;
325 }
326
327 int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
328 {
329         /* assume no swapping of fetched data */
330         if (swap)
331                 *swap = BYTE_SWAP_NOSWAP;
332
333         switch (fourcc) {
334         case DRM_FORMAT_ARGB4444:
335                 *format = WIN_COLOR_DEPTH_B4G4R4A4;
336                 break;
337
338         case DRM_FORMAT_ARGB1555:
339                 *format = WIN_COLOR_DEPTH_B5G5R5A1;
340                 break;
341
342         case DRM_FORMAT_RGB565:
343                 *format = WIN_COLOR_DEPTH_B5G6R5;
344                 break;
345
346         case DRM_FORMAT_RGBA5551:
347                 *format = WIN_COLOR_DEPTH_A1B5G5R5;
348                 break;
349
350         case DRM_FORMAT_ARGB8888:
351                 *format = WIN_COLOR_DEPTH_B8G8R8A8;
352                 break;
353
354         case DRM_FORMAT_ABGR8888:
355                 *format = WIN_COLOR_DEPTH_R8G8B8A8;
356                 break;
357
358         case DRM_FORMAT_ABGR4444:
359                 *format = WIN_COLOR_DEPTH_R4G4B4A4;
360                 break;
361
362         case DRM_FORMAT_ABGR1555:
363                 *format = WIN_COLOR_DEPTH_R5G5B5A;
364                 break;
365
366         case DRM_FORMAT_BGRA5551:
367                 *format = WIN_COLOR_DEPTH_AR5G5B5;
368                 break;
369
370         case DRM_FORMAT_XRGB1555:
371                 *format = WIN_COLOR_DEPTH_B5G5R5X1;
372                 break;
373
374         case DRM_FORMAT_RGBX5551:
375                 *format = WIN_COLOR_DEPTH_X1B5G5R5;
376                 break;
377
378         case DRM_FORMAT_XBGR1555:
379                 *format = WIN_COLOR_DEPTH_R5G5B5X1;
380                 break;
381
382         case DRM_FORMAT_BGRX5551:
383                 *format = WIN_COLOR_DEPTH_X1R5G5B5;
384                 break;
385
386         case DRM_FORMAT_BGR565:
387                 *format = WIN_COLOR_DEPTH_R5G6B5;
388                 break;
389
390         case DRM_FORMAT_BGRA8888:
391                 *format = WIN_COLOR_DEPTH_A8R8G8B8;
392                 break;
393
394         case DRM_FORMAT_RGBA8888:
395                 *format = WIN_COLOR_DEPTH_A8B8G8R8;
396                 break;
397
398         case DRM_FORMAT_XRGB8888:
399                 *format = WIN_COLOR_DEPTH_B8G8R8X8;
400                 break;
401
402         case DRM_FORMAT_XBGR8888:
403                 *format = WIN_COLOR_DEPTH_R8G8B8X8;
404                 break;
405
406         case DRM_FORMAT_UYVY:
407                 *format = WIN_COLOR_DEPTH_YCbCr422;
408                 break;
409
410         case DRM_FORMAT_YUYV:
411                 if (!swap)
412                         return -EINVAL;
413
414                 *format = WIN_COLOR_DEPTH_YCbCr422;
415                 *swap = BYTE_SWAP_SWAP2;
416                 break;
417
418         case DRM_FORMAT_YVYU:
419                 if (!swap)
420                         return -EINVAL;
421
422                 *format = WIN_COLOR_DEPTH_YCbCr422;
423                 *swap = BYTE_SWAP_SWAP4;
424                 break;
425
426         case DRM_FORMAT_VYUY:
427                 if (!swap)
428                         return -EINVAL;
429
430                 *format = WIN_COLOR_DEPTH_YCbCr422;
431                 *swap = BYTE_SWAP_SWAP4HW;
432                 break;
433
434         case DRM_FORMAT_YUV420:
435                 *format = WIN_COLOR_DEPTH_YCbCr420P;
436                 break;
437
438         case DRM_FORMAT_YUV422:
439                 *format = WIN_COLOR_DEPTH_YCbCr422P;
440                 break;
441
442         case DRM_FORMAT_YUV444:
443                 *format = WIN_COLOR_DEPTH_YCbCr444P;
444                 break;
445
446         case DRM_FORMAT_NV12:
447                 *format = WIN_COLOR_DEPTH_YCbCr420SP;
448                 break;
449
450         case DRM_FORMAT_NV21:
451                 *format = WIN_COLOR_DEPTH_YCrCb420SP;
452                 break;
453
454         case DRM_FORMAT_NV16:
455                 *format = WIN_COLOR_DEPTH_YCbCr422SP;
456                 break;
457
458         case DRM_FORMAT_NV61:
459                 *format = WIN_COLOR_DEPTH_YCrCb422SP;
460                 break;
461
462         case DRM_FORMAT_NV24:
463                 *format = WIN_COLOR_DEPTH_YCbCr444SP;
464                 break;
465
466         case DRM_FORMAT_NV42:
467                 *format = WIN_COLOR_DEPTH_YCrCb444SP;
468                 break;
469
470         default:
471                 return -EINVAL;
472         }
473
474         return 0;
475 }
476
477 bool tegra_plane_format_is_indexed(unsigned int format)
478 {
479         switch (format) {
480         case WIN_COLOR_DEPTH_P1:
481         case WIN_COLOR_DEPTH_P2:
482         case WIN_COLOR_DEPTH_P4:
483         case WIN_COLOR_DEPTH_P8:
484                 return true;
485         }
486
487         return false;
488 }
489
490 bool tegra_plane_format_is_yuv(unsigned int format, unsigned int *planes, unsigned int *bpc)
491 {
492         switch (format) {
493         case WIN_COLOR_DEPTH_YCbCr422:
494         case WIN_COLOR_DEPTH_YUV422:
495                 if (planes)
496                         *planes = 1;
497
498                 if (bpc)
499                         *bpc = 8;
500
501                 return true;
502
503         case WIN_COLOR_DEPTH_YCbCr420P:
504         case WIN_COLOR_DEPTH_YUV420P:
505         case WIN_COLOR_DEPTH_YCbCr422P:
506         case WIN_COLOR_DEPTH_YUV422P:
507         case WIN_COLOR_DEPTH_YCbCr422R:
508         case WIN_COLOR_DEPTH_YUV422R:
509         case WIN_COLOR_DEPTH_YCbCr422RA:
510         case WIN_COLOR_DEPTH_YUV422RA:
511         case WIN_COLOR_DEPTH_YCbCr444P:
512                 if (planes)
513                         *planes = 3;
514
515                 if (bpc)
516                         *bpc = 8;
517
518                 return true;
519
520         case WIN_COLOR_DEPTH_YCrCb420SP:
521         case WIN_COLOR_DEPTH_YCbCr420SP:
522         case WIN_COLOR_DEPTH_YCrCb422SP:
523         case WIN_COLOR_DEPTH_YCbCr422SP:
524         case WIN_COLOR_DEPTH_YCrCb444SP:
525         case WIN_COLOR_DEPTH_YCbCr444SP:
526                 if (planes)
527                         *planes = 2;
528
529                 if (bpc)
530                         *bpc = 8;
531
532                 return true;
533         }
534
535         if (planes)
536                 *planes = 1;
537
538         return false;
539 }
540
541 static bool __drm_format_has_alpha(u32 format)
542 {
543         switch (format) {
544         case DRM_FORMAT_ARGB1555:
545         case DRM_FORMAT_RGBA5551:
546         case DRM_FORMAT_ABGR8888:
547         case DRM_FORMAT_ARGB8888:
548                 return true;
549         }
550
551         return false;
552 }
553
554 static int tegra_plane_format_get_alpha(unsigned int opaque,
555                                         unsigned int *alpha)
556 {
557         if (tegra_plane_format_is_yuv(opaque, NULL, NULL)) {
558                 *alpha = opaque;
559                 return 0;
560         }
561
562         switch (opaque) {
563         case WIN_COLOR_DEPTH_B5G5R5X1:
564                 *alpha = WIN_COLOR_DEPTH_B5G5R5A1;
565                 return 0;
566
567         case WIN_COLOR_DEPTH_X1B5G5R5:
568                 *alpha = WIN_COLOR_DEPTH_A1B5G5R5;
569                 return 0;
570
571         case WIN_COLOR_DEPTH_R8G8B8X8:
572                 *alpha = WIN_COLOR_DEPTH_R8G8B8A8;
573                 return 0;
574
575         case WIN_COLOR_DEPTH_B8G8R8X8:
576                 *alpha = WIN_COLOR_DEPTH_B8G8R8A8;
577                 return 0;
578
579         case WIN_COLOR_DEPTH_B5G6R5:
580                 *alpha = opaque;
581                 return 0;
582         }
583
584         return -EINVAL;
585 }
586
587 /*
588  * This is applicable to Tegra20 and Tegra30 only where the opaque formats can
589  * be emulated using the alpha formats and alpha blending disabled.
590  */
591 static int tegra_plane_setup_opacity(struct tegra_plane *tegra,
592                                      struct tegra_plane_state *state)
593 {
594         unsigned int format;
595         int err;
596
597         switch (state->format) {
598         case WIN_COLOR_DEPTH_B5G5R5A1:
599         case WIN_COLOR_DEPTH_A1B5G5R5:
600         case WIN_COLOR_DEPTH_R8G8B8A8:
601         case WIN_COLOR_DEPTH_B8G8R8A8:
602                 state->opaque = false;
603                 break;
604
605         default:
606                 err = tegra_plane_format_get_alpha(state->format, &format);
607                 if (err < 0)
608                         return err;
609
610                 state->format = format;
611                 state->opaque = true;
612                 break;
613         }
614
615         return 0;
616 }
617
618 static int tegra_plane_check_transparency(struct tegra_plane *tegra,
619                                           struct tegra_plane_state *state)
620 {
621         struct drm_plane_state *old, *plane_state;
622         struct drm_plane *plane;
623
624         old = drm_atomic_get_old_plane_state(state->base.state, &tegra->base);
625
626         /* check if zpos / transparency changed */
627         if (old->normalized_zpos == state->base.normalized_zpos &&
628             to_tegra_plane_state(old)->opaque == state->opaque)
629                 return 0;
630
631         /* include all sibling planes into this commit */
632         drm_for_each_plane(plane, tegra->base.dev) {
633                 struct tegra_plane *p = to_tegra_plane(plane);
634
635                 /* skip this plane and planes on different CRTCs */
636                 if (p == tegra || p->dc != tegra->dc)
637                         continue;
638
639                 plane_state = drm_atomic_get_plane_state(state->base.state,
640                                                          plane);
641                 if (IS_ERR(plane_state))
642                         return PTR_ERR(plane_state);
643         }
644
645         return 1;
646 }
647
648 static unsigned int tegra_plane_get_overlap_index(struct tegra_plane *plane,
649                                                   struct tegra_plane *other)
650 {
651         unsigned int index = 0, i;
652
653         WARN_ON(plane == other);
654
655         for (i = 0; i < 3; i++) {
656                 if (i == plane->index)
657                         continue;
658
659                 if (i == other->index)
660                         break;
661
662                 index++;
663         }
664
665         return index;
666 }
667
668 static void tegra_plane_update_transparency(struct tegra_plane *tegra,
669                                             struct tegra_plane_state *state)
670 {
671         struct drm_plane_state *new;
672         struct drm_plane *plane;
673         unsigned int i;
674
675         for_each_new_plane_in_state(state->base.state, plane, new, i) {
676                 struct tegra_plane *p = to_tegra_plane(plane);
677                 unsigned index;
678
679                 /* skip this plane and planes on different CRTCs */
680                 if (p == tegra || p->dc != tegra->dc)
681                         continue;
682
683                 index = tegra_plane_get_overlap_index(tegra, p);
684
685                 if (new->fb && __drm_format_has_alpha(new->fb->format->format))
686                         state->blending[index].alpha = true;
687                 else
688                         state->blending[index].alpha = false;
689
690                 if (new->normalized_zpos > state->base.normalized_zpos)
691                         state->blending[index].top = true;
692                 else
693                         state->blending[index].top = false;
694
695                 /*
696                  * Missing framebuffer means that plane is disabled, in this
697                  * case mark B / C window as top to be able to differentiate
698                  * windows indices order in regards to zPos for the middle
699                  * window X / Y registers programming.
700                  */
701                 if (!new->fb)
702                         state->blending[index].top = (index == 1);
703         }
704 }
705
706 static int tegra_plane_setup_transparency(struct tegra_plane *tegra,
707                                           struct tegra_plane_state *state)
708 {
709         struct tegra_plane_state *tegra_state;
710         struct drm_plane_state *new;
711         struct drm_plane *plane;
712         int err;
713
714         /*
715          * If planes zpos / transparency changed, sibling planes blending
716          * state may require adjustment and in this case they will be included
717          * into this atom commit, otherwise blending state is unchanged.
718          */
719         err = tegra_plane_check_transparency(tegra, state);
720         if (err <= 0)
721                 return err;
722
723         /*
724          * All planes are now in the atomic state, walk them up and update
725          * transparency state for each plane.
726          */
727         drm_for_each_plane(plane, tegra->base.dev) {
728                 struct tegra_plane *p = to_tegra_plane(plane);
729
730                 /* skip planes on different CRTCs */
731                 if (p->dc != tegra->dc)
732                         continue;
733
734                 new = drm_atomic_get_new_plane_state(state->base.state, plane);
735                 tegra_state = to_tegra_plane_state(new);
736
737                 /*
738                  * There is no need to update blending state for the disabled
739                  * plane.
740                  */
741                 if (new->fb)
742                         tegra_plane_update_transparency(p, tegra_state);
743         }
744
745         return 0;
746 }
747
748 int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
749                                    struct tegra_plane_state *state)
750 {
751         int err;
752
753         err = tegra_plane_setup_opacity(tegra, state);
754         if (err < 0)
755                 return err;
756
757         err = tegra_plane_setup_transparency(tegra, state);
758         if (err < 0)
759                 return err;
760
761         return 0;
762 }
763
764 static const char * const tegra_plane_icc_names[TEGRA_DC_LEGACY_PLANES_NUM] = {
765         "wina", "winb", "winc", NULL, NULL, NULL, "cursor",
766 };
767
768 int tegra_plane_interconnect_init(struct tegra_plane *plane)
769 {
770         const char *icc_name = tegra_plane_icc_names[plane->index];
771         struct device *dev = plane->dc->dev;
772         struct tegra_dc *dc = plane->dc;
773         int err;
774
775         if (WARN_ON(plane->index >= TEGRA_DC_LEGACY_PLANES_NUM) ||
776             WARN_ON(!tegra_plane_icc_names[plane->index]))
777                 return -EINVAL;
778
779         plane->icc_mem = devm_of_icc_get(dev, icc_name);
780         err = PTR_ERR_OR_ZERO(plane->icc_mem);
781         if (err) {
782                 dev_err_probe(dev, err, "failed to get %s interconnect\n",
783                               icc_name);
784                 return err;
785         }
786
787         /* plane B on T20/30 has a dedicated memory client for a 6-tap vertical filter */
788         if (plane->index == 1 && dc->soc->has_win_b_vfilter_mem_client) {
789                 plane->icc_mem_vfilter = devm_of_icc_get(dev, "winb-vfilter");
790                 err = PTR_ERR_OR_ZERO(plane->icc_mem_vfilter);
791                 if (err) {
792                         dev_err_probe(dev, err, "failed to get %s interconnect\n",
793                                       "winb-vfilter");
794                         return err;
795                 }
796         }
797
798         return 0;
799 }
This page took 0.078082 seconds and 4 git commands to generate.