• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 Allwinnertech Co.Ltd
3  * Authors: zhengwanyu
4  *
5  * This program is free software; you can redistribute  it and/or modify it
6  * under  the terms of  the GNU General  Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  *
10  */
11 #include <drm/drm_crtc_helper.h>
12 #include <drm/drm_fb_helper.h>
13 #include <drm/drm_plane_helper.h>
14 #include <drm/drm_atomic_helper.h>
15 #include <drm/drm_fourcc.h>
16 
17 #include "sunxi_drm_drv.h"
18 #include "sunxi_drm_plane.h"
19 #include "sunxi_drm_crtc.h"
20 #include "sunxi_drm_connector.h"
21 #include "sunxi_drm_fb.h"
22 #include "sunxi_drm_gem.h"
23 #include "sunxi_device/sunxi_de.h"
24 
25 /*void sunxi_plane_dump(struct drm_plane *plane, bool dump_fb)
26 {
27     struct sunxi_drm_plane *sunxi_plane = to_sunxi_plane(plane);
28 
29     DRM_INFO("Plane info:\n");
30     DRM_INFO("Plane ID:%u  sunxi plane id:%u  drm_plane index:%u\n",
31         plane->base.id, sunxi_plane->plane_id, plane->index);
32     DRM_INFO("name:%s\n", plane->name);
33     DRM_INFO("type:%s\n", (plane->type == DRM_PLANE_TYPE_PRIMARY) ?
34         "primary" : ((plane->type == DRM_PLANE_TYPE_OVERLAY) ?
35                         "overlay" : "cursor"));
36     DRM_INFO("possible_crtcs:%u\n", plane->possible_crtcs);
37 
38     if (plane->crtc)
39         DRM_INFO("Attached crtc index:%d\n", plane->crtc->index);
40     else
41         DRM_INFO("WARN:No attached crtc\n");
42 
43     if (plane->fb && dump_fb) {
44         sunxi_fb_dump(plane->fb);
45     } else if (plane->fb) {
46         DRM_INFO("Has fb, obj ID:%u", plane->fb->base.id);
47     } else {
48         DRM_INFO("WARN:Has NOT fb\n");
49     }
50 
51     DRM_INFO("\n");
52 }*/
53 
drm_to_disp_format(uint32_t format)54 static int drm_to_disp_format(uint32_t format)
55 {
56     switch (format) {
57     case DRM_FORMAT_ARGB8888:
58         return DISP_FORMAT_ARGB_8888;
59 
60     case DRM_FORMAT_ABGR8888:
61         return DISP_FORMAT_ABGR_8888;
62 
63     case DRM_FORMAT_RGBA8888:
64         return DISP_FORMAT_RGBA_8888;
65 
66     case DRM_FORMAT_BGRA8888:
67         return DISP_FORMAT_BGRA_8888;
68 
69     case DRM_FORMAT_XRGB8888:
70         return DISP_FORMAT_XRGB_8888;
71 
72     case DRM_FORMAT_XBGR8888:
73         return DISP_FORMAT_XBGR_8888;
74 
75     case DRM_FORMAT_RGBX8888:
76         return DISP_FORMAT_RGBX_8888;
77 
78     case DRM_FORMAT_BGRX8888:
79         return DISP_FORMAT_BGRX_8888;
80 
81     case DRM_FORMAT_RGB888:
82         return DISP_FORMAT_RGB_888;
83 
84     case DISP_FORMAT_BGR_888:
85         return DRM_FORMAT_BGR888;
86 
87     case DRM_FORMAT_RGB565:
88         return DISP_FORMAT_RGB_565;
89 
90     case DRM_FORMAT_BGR565:
91         return DISP_FORMAT_BGR_565;
92 
93     case DRM_FORMAT_ARGB4444:
94         return DISP_FORMAT_ARGB_4444;
95 
96     case DRM_FORMAT_ABGR4444:
97         return DISP_FORMAT_ABGR_4444;
98 
99     case DRM_FORMAT_RGBA4444:
100         return DISP_FORMAT_RGBA_4444;
101 
102     case DRM_FORMAT_BGRA4444:
103         return DISP_FORMAT_BGRA_4444;
104 
105     case DRM_FORMAT_ARGB1555:
106         return DISP_FORMAT_ARGB_1555;
107 
108     case DRM_FORMAT_ABGR1555:
109         return DISP_FORMAT_ABGR_1555;
110 
111     case DRM_FORMAT_RGBA5551:
112         return DISP_FORMAT_RGBA_5551;
113 
114     case DRM_FORMAT_BGRA5551:
115         return DISP_FORMAT_BGRA_5551;
116 
117     /* SP: semi-planar, P:planar, I:interleaved
118     * UVUV: U in the LSBs;     VUVU: V in the LSBs */
119     case DRM_FORMAT_AYUV:
120         return DISP_FORMAT_YUV444_I_AYUV;
121 
122     case DRM_FORMAT_YUV444:
123         return DISP_FORMAT_YUV444_P;
124 
125     case DRM_FORMAT_YUV422:
126         return DISP_FORMAT_YUV422_P;
127 
128     case DRM_FORMAT_YUV420:
129         return DISP_FORMAT_YUV420_P;
130 
131     case DRM_FORMAT_YUV411:
132         return DISP_FORMAT_YUV411_P;
133 
134     case DRM_FORMAT_NV61:
135         return DISP_FORMAT_YUV422_SP_UVUV;
136 
137     case DRM_FORMAT_NV16:
138         return DISP_FORMAT_YUV422_SP_VUVU;
139 
140     case DRM_FORMAT_NV21:
141         return DISP_FORMAT_YUV420_SP_UVUV;
142 
143     case DRM_FORMAT_NV12:
144         return DISP_FORMAT_YUV420_SP_VUVU;
145     }
146 
147     DRM_ERROR("get a err drm format.\n");
148     return -1;
149 }
150 
151 /*void sunxi_plane_state_dump(struct drm_plane_state *state)
152 {
153     DRM_INFO("drm_plane_state info:\n");
154     DRM_INFO("CRTC:%d\n", drm_crtc_index(state->crtc));
155     DRM_INFO("crtc_x:%d crtc_y:%d crtc_w:%d crtc_h:%d\n",
156                 state->crtc_x, state->crtc_y,
157                 state->crtc_w, state->crtc_h);
158     DRM_INFO("src_x:%d src_y:%d src_w:%d src_h:%d\n",
159                 state->src_x, state->src_y,
160                 state->src_w, state->src_h);
161     DRM_INFO("Rotation:%u\n", state->rotation);
162     DRM_INFO("Zops:%u normalized_zpos:%u\n", state->zpos,
163                     state->normalized_zpos);
164     DRM_INFO("Rect-src: x1:%d y1:%d x2:%d y2:%d\n", state->src.x1,
165                 state->src.y1, state->src.x2, state->src.y2);
166     DRM_INFO("Rect-dst: x1:%d y1:%d x2:%d y2:%d\n", state->dst.x1,
167                 state->dst.y1, state->dst.x2, state->dst.y2);
168     DRM_INFO("visible:%u\n", state->visible);
169     DRM_INFO("\n");
170 
171     sunxi_plane_dump(state->plane, false);
172 
173     if (state->fb)
174         sunxi_fb_dump(state->fb);
175 
176 }*/
177 
sunxi_plane_state_show(char * buf,struct drm_plane_state * state)178 ssize_t sunxi_plane_state_show(char *buf, struct drm_plane_state *state)
179 {
180     ssize_t n = 0;
181 
182     n += sprintf(buf + n, "attaching CRTC:%d\n", drm_crtc_index(state->crtc));
183     n += sprintf(buf + n, "crtc_x:%d crtc_y:%d crtc_w:%d crtc_h:%d\n",
184                 state->crtc_x, state->crtc_y,
185                 state->crtc_w, state->crtc_h);
186     n += sprintf(buf + n, "src_x:%d src_y:%d src_w:%d src_h:%d\n",
187                 state->src_x, state->src_y,
188                 state->src_w, state->src_h);
189     n += sprintf(buf + n, "Rotation:%u\n", state->rotation);
190     n += sprintf(buf + n, "Zops:%u normalized_zpos:%u\n", state->zpos,
191                     state->normalized_zpos);
192     n += sprintf(buf + n, "Rect-src: x1:%d y1:%d x2:%d y2:%d\n", state->src.x1,
193                 state->src.y1, state->src.x2, state->src.y2);
194     n += sprintf(buf + n, "Rect-dst: x1:%d y1:%d x2:%d y2:%d\n", state->dst.x1,
195                 state->dst.y1, state->dst.x2, state->dst.y2);
196     n += sprintf(buf + n, "visible:%u\n", state->visible);
197 
198     if (state->fb)
199         n += sprintf(buf + n, "fb drm_mode_object id:%u\n", state->fb->base.id);
200     n += sprintf(buf + n, "\n");
201 
202     return n;
203 }
204 
205 /*ssize_t sunxi_drm_planes_show(char *buf, struct drm_device *dev,
206                         struct drm_crtc *crtc)
207 {
208     ssize_t n = 0;
209     struct drm_plane *plane;
210     struct sunxi_drm_plane *sunxi_plane;
211 
212     drm_for_each_plane(plane, dev) {
213         if (crtc && !((plane->possible_crtcs >> drm_crtc_index(crtc)) & 0x1))
214             continue;
215 
216         if (crtc && (!plane->crtc || !plane->fb))
217             continue;
218 
219         sunxi_plane = to_sunxi_plane(plane);
220 
221         if (!crtc && (!plane->crtc || !plane->fb)) {
222             n += sprintf(buf + n, "drm_plane index:%u  sunxi plane id:%u NOT enabled!!!\n",
223                         plane->index, sunxi_plane->plane_id);
224             continue;
225         }
226 
227         n += sprintf(buf + n, "sunxi plane id:%u  drm_plane index:%u\n",
228                         sunxi_plane->plane_id, plane->index);
229         n += sprintf(buf + n, "drm_mode_object id:%u\n", plane->base.id);
230         n += sprintf(buf + n, "name:%s\n", plane->name);
231         n += sprintf(buf + n, "type:%s\n", (plane->type == DRM_PLANE_TYPE_PRIMARY) ?
232                 "primary" : ((plane->type == DRM_PLANE_TYPE_OVERLAY) ?
233                                 "overlay" : "cursor"));
234         n += sprintf(buf + n, "possible_crtcs:%u\n", plane->possible_crtcs);
235         n += sprintf(buf + n, "Attached crtc index:%d\n", plane->crtc->index);
236 
237         n += sprintf(buf + n, "alpha_mode:%lld\n", sunxi_plane->alpha_mode);
238         n += sprintf(buf + n, "galpha_value:%lld\n", sunxi_plane->galpha_value);
239 
240         if (plane->state) {
241             n += sprintf(buf + n, "[sunxi plane id:%u sate]:\n",
242                         sunxi_plane->plane_id);
243             n += sunxi_plane_state_show(buf + n, plane->state);
244         }
245 
246         if (plane->fb) {
247             n += sprintf(buf + n, "[sunxi plane id:%u attached fb(obj_id:%u) info]:\n",
248                         sunxi_plane->plane_id, plane->fb->base.id);
249             n += sunxi_drm_fb_show(buf + n, plane->fb);
250         }
251 
252         n += sprintf(buf + n, "\n");
253     }
254 
255     return n;
256 }*/
257 
258 
259 /*
260  *@pixel_format: fourcc format
261  *@return: 0:pixel alpha  1:global alpha 2:mixed alpha
262  */
sunxi_plane_get_alpha_mode(unsigned int pixel_format,unsigned int alpha)263 static int sunxi_plane_get_alpha_mode(unsigned int pixel_format, unsigned int alpha)
264 {
265     switch (pixel_format) {
266     case DRM_FORMAT_ARGB4444:
267     case DRM_FORMAT_ABGR4444:
268     case DRM_FORMAT_RGBA4444:
269     case DRM_FORMAT_BGRA4444:
270 
271     case DRM_FORMAT_ARGB1555:
272     case DRM_FORMAT_ABGR1555:
273     case DRM_FORMAT_RGBA5551:
274     case DRM_FORMAT_BGRA5551:
275 
276     case DRM_FORMAT_ARGB8888:
277     case DRM_FORMAT_ABGR8888:
278     case DRM_FORMAT_RGBA8888:
279     case DRM_FORMAT_BGRA8888:
280 
281     case DRM_FORMAT_ARGB2101010:
282     case DRM_FORMAT_ABGR2101010:
283     case DRM_FORMAT_RGBA1010102:
284     case DRM_FORMAT_BGRA1010102:
285         if (alpha)
286             return MIXED_ALPHA;
287         else
288             return PIXEL_ALPHA;
289 
290     case DRM_FORMAT_C8:
291     case DRM_FORMAT_R8:
292     case DRM_FORMAT_RG88:
293     case DRM_FORMAT_GR88:
294     case DRM_FORMAT_RGB332:
295     case DRM_FORMAT_BGR233:
296     case DRM_FORMAT_XRGB4444:
297     case DRM_FORMAT_XBGR4444:
298     case DRM_FORMAT_RGBX4444:
299     case DRM_FORMAT_BGRX4444:
300     case DRM_FORMAT_XRGB1555:
301     case DRM_FORMAT_XBGR1555:
302     case DRM_FORMAT_RGBX5551:
303     case DRM_FORMAT_BGRX5551:
304     case DRM_FORMAT_RGB565:
305     case DRM_FORMAT_BGR565:
306 
307 /* 24 bpp RGB */
308     case DRM_FORMAT_RGB888:
309     case DRM_FORMAT_BGR888:
310 
311 /* 32 bpp RGB */
312     case DRM_FORMAT_XRGB8888:
313     case DRM_FORMAT_XBGR8888:
314     case DRM_FORMAT_RGBX8888:
315     case DRM_FORMAT_BGRX8888:
316 
317     case DRM_FORMAT_XRGB2101010:
318     case DRM_FORMAT_XBGR2101010:
319     case DRM_FORMAT_RGBX1010102:
320     case DRM_FORMAT_BGRX1010102:
321 
322 /* packed YCbCr */
323     case DRM_FORMAT_YUYV:
324     case DRM_FORMAT_YVYU:
325     case DRM_FORMAT_UYVY:
326     case DRM_FORMAT_VYUY:
327 
328     case DRM_FORMAT_AYUV:
329 
330 /* 2 plane YCbCr */
331     case DRM_FORMAT_NV12:
332     case DRM_FORMAT_NV21:
333     case DRM_FORMAT_NV16:
334     case DRM_FORMAT_NV61:
335     case DRM_FORMAT_NV24:
336     case DRM_FORMAT_NV42:
337 
338     case DRM_FORMAT_YUV410:
339     case DRM_FORMAT_YVU410:
340     case DRM_FORMAT_YUV411:
341     case DRM_FORMAT_YVU411:
342     case DRM_FORMAT_YUV420:
343     case DRM_FORMAT_YVU420:
344     case DRM_FORMAT_YUV422:
345     case DRM_FORMAT_YVU422:
346     case DRM_FORMAT_YUV444:
347     case DRM_FORMAT_YVU444:
348 
349         return GLOBAL_ALPHA;
350     }
351 
352     DRM_ERROR("wrong pixel_format input\n");
353     return GLOBAL_ALPHA;
354 }
355 
356 /*
357  * group index is actually layer chanel index of SUNXI DE
358  */
sunxi_plane_create_group_index_property(struct sunxi_drm_plane * sunxi_plane,unsigned int crtc_id)359 static int sunxi_plane_create_group_index_property(
360         struct sunxi_drm_plane *sunxi_plane, unsigned int crtc_id)
361 {
362     struct drm_property *prop;
363     unsigned int group_index;
364     struct sunxi_drm_crtc *scrtc = sunxi_drm_crtc_get_crtc(crtc_id);
365 
366     /* Here we make group_index's range from 0 to 6,
367      * but actually, in general, SUNXI DE has 4 groups(channels) at most
368      * for layers
369      */
370     prop = drm_property_create_range(sunxi_plane->plane.dev,
371         DRM_MODE_PROP_IMMUTABLE, "group_index", 0, 6);
372     if (!prop) {
373         DRM_ERROR("Create group_index property for plane:%d failed!",
374             sunxi_plane->plane_id);
375         return -ENOMEM;
376     }
377 
378     group_index = scrtc->hw_funcs->get_layer_channel_id(crtc_id,
379                     sunxi_plane->plane_id);
380 
381     drm_object_attach_property(&sunxi_plane->plane.base,
382                     prop, group_index);
383 
384     return 0;
385 }
386 
387 /*
388  * the sub_index is a plane sub index within a plane group(chanel)
389  */
sunxi_plane_create_sub_index_property(struct sunxi_drm_plane * sunxi_plane,unsigned int crtc_id)390 static int sunxi_plane_create_sub_index_property(
391         struct sunxi_drm_plane *sunxi_plane, unsigned int crtc_id)
392 {
393     struct drm_property *prop;
394     unsigned int sub_index;
395     struct sunxi_drm_crtc *scrtc = sunxi_drm_crtc_get_crtc(crtc_id);
396 
397     /* Here we make sub_index's range from 0 to 6,
398      * but actually, in general, SUNXI DE has 4 sub layers at most
399      * within a layer channel
400      */
401     prop = drm_property_create_range(sunxi_plane->plane.dev,
402         DRM_MODE_PROP_IMMUTABLE, "sub_index", 0, 6);
403     if (!prop) {
404         DRM_ERROR("Create sub_index property for plane:%d failed!",
405             sunxi_plane->plane_id);
406         return -ENOMEM;
407     }
408 
409     sub_index = scrtc->hw_funcs->get_layer_id_within_chanel(crtc_id,
410                     sunxi_plane->plane_id);
411 
412     drm_object_attach_property(&sunxi_plane->plane.base,
413                     prop, sub_index);
414 
415     return 0;
416 }
417 
sunxi_plane_create_alpha_mode_property(struct sunxi_drm_plane * sunxi_plane,unsigned int alpha_mode,unsigned int min,unsigned int max)418 static int sunxi_plane_create_alpha_mode_property(
419             struct sunxi_drm_plane *sunxi_plane,
420                    unsigned int alpha_mode,
421                    unsigned int min, unsigned int max)
422 {
423     struct drm_property *prop;
424 
425     prop = drm_property_create_range(sunxi_plane->plane.dev, 0,
426             "alpha_mode", min, max);
427     if (!prop)
428         return -ENOMEM;
429 
430     drm_object_attach_property(&sunxi_plane->plane.base,
431                     prop, alpha_mode);
432 
433     sunxi_plane->alpha_mode_property = prop;
434 
435     sunxi_plane->alpha_mode = alpha_mode;
436 
437     return 0;
438 }
439 
sunxi_plane_create_galpha_value_property(struct sunxi_drm_plane * sunxi_plane,unsigned int galpha_value,unsigned int min,unsigned int max)440 static int sunxi_plane_create_galpha_value_property(
441             struct sunxi_drm_plane *sunxi_plane,
442                    unsigned int galpha_value,
443                    unsigned int min, unsigned int max)
444 {
445     struct drm_property *prop;
446 
447     prop = drm_property_create_range(sunxi_plane->plane.dev, 0,
448             "alpha", min, max);
449     if (!prop)
450         return -ENOMEM;
451 
452     drm_object_attach_property(&sunxi_plane->plane.base,
453                     prop, galpha_value);
454 
455     sunxi_plane->galpha_value_property = prop;
456 
457     sunxi_plane->galpha_value = galpha_value;
458 
459     return 0;
460 }
461 
462 
sunxi_plane_reset(struct drm_plane * plane)463 static void sunxi_plane_reset(struct drm_plane *plane)
464 {
465     drm_atomic_helper_plane_reset(plane);
466 }
467 
sunxi_plane_atomic_get_property(struct drm_plane * plane,const struct drm_plane_state * state,struct drm_property * property,uint64_t * val)468 static int sunxi_plane_atomic_get_property(struct drm_plane *plane,
469                const struct drm_plane_state *state,
470                struct drm_property *property,
471                uint64_t *val)
472 {
473     struct sunxi_drm_plane *sunxi_plane = to_sunxi_plane(plane);
474 
475     if (property == sunxi_plane->alpha_mode_property) {
476         *val = sunxi_plane->alpha_mode;
477         return 0;
478     } else if (property == sunxi_plane->galpha_value_property) {
479         *val = sunxi_plane->galpha_value;
480         return 0;
481     }
482 
483     return -1;
484 }
485 
sunxi_plane_atomic_set_property(struct drm_plane * plane,struct drm_plane_state * state,struct drm_property * property,uint64_t val)486 static int sunxi_plane_atomic_set_property(struct drm_plane *plane,
487                struct drm_plane_state *state,
488                struct drm_property *property,
489                uint64_t val)
490 {
491     struct sunxi_drm_plane *sunxi_plane = to_sunxi_plane(plane);
492 
493     if (property == sunxi_plane->alpha_mode_property) {
494         sunxi_plane->alpha_mode = val;
495         return 0;
496     } else if (property == sunxi_plane->galpha_value_property) {
497         sunxi_plane->galpha_value = val;
498         return 0;
499     }
500 
501     return -1;
502 }
503 
504 /**
505  * update a certain plane except disable it
506  * all that want to set/change plane configs will call function finally.
507  *
508  * NOTE: drm disable or suspend will also call this function, instead of calling
509  * sunxi_plane_atomic_disable
510  */
sunxi_plane_atomic_update(struct drm_plane * plane,struct drm_plane_state * old_state)511 static void sunxi_plane_atomic_update(struct drm_plane *plane,
512                 struct drm_plane_state *old_state)
513 {
514     int i;
515 
516     struct drm_plane_state *new_state = NULL;
517     struct drm_crtc_state *crtc_state = NULL;
518     struct sunxi_drm_plane *sunxi_plane = to_sunxi_plane(plane);
519 
520     struct drm_framebuffer *fb;
521     struct sunxi_drm_fb *sunxi_fb;
522     struct sunxi_drm_gem_object    *sunxi_gem_obj;
523     struct sunxi_drm_crtc *scrtc;
524     struct drm_crtc_helper_funcs *crtc_helper_funcs;
525     struct sunxi_drm_connector *sconn;
526 
527     struct disp_layer_config_data *layer_config = &sunxi_plane->config;
528     struct disp_layer_config_inner *layer_config_inner = &layer_config->config;
529     struct disp_layer_info_inner *layer_inner = &layer_config_inner->info;
530     struct disp_fb_info_inner *fb_inner = &layer_inner->fb;
531 
532 #ifdef CONFIG_VIDEO_SUNXI_CAR_REVERSE
533     if (sunxi_drm_get_force_plane_en())
534         return;
535 #endif
536 
537     DRM_DEBUG_DRIVER("[SUNXI-PLANE]%s\n", __func__);
538     new_state = plane->state;
539     if (!new_state) {
540         DRM_ERROR("drm_plane state is NULL\n");
541         return;
542     }
543 
544     if (!new_state->crtc) {
545         DRM_ERROR("plane state has NO crtc\n");
546         return;
547     }
548 
549     if (!new_state->fb) {
550         DRM_ERROR("plane state has NO fb\n");
551         return;
552     }
553 
554 /*get fb that is going to attach with*/
555     sunxi_fb = to_sunxi_fb(new_state->fb);
556     fb = &sunxi_fb->fb;
557 
558 /*get crtc that is going to attach with*/
559     scrtc = to_sunxi_crtc(new_state->crtc);
560     crtc_state = new_state->crtc->state;
561 
562 /*get connector that is going to set*/
563     for (i = 0; i < sunxi_drm_connector_get_count(); i++) {
564         if ((crtc_state->connector_mask >> i) & 0x1)
565             break;
566     }
567 
568     sconn = sunxi_drm_connector_get_connector(i);
569     if (!sconn) {
570         DRM_ERROR("sunxi_drm_connector_get_connector:%d failed\n", i);
571         return;
572     }
573 
574 /*ensure that manager_enable who's belongs to lowlevel hw layer is set.
575  * because we reference layer/de setting from sunxi_display, so we need to
576  * keep the setting sequence same with sunxi_display
577  */
578     if (!scrtc->enabled) {
579         crtc_helper_funcs = (struct drm_crtc_helper_funcs *)
580                     new_state->crtc->helper_private;
581         crtc_helper_funcs->atomic_enable(new_state->crtc, NULL);
582     }
583 
584 
585     //sunxi_plane_state_dump(new_state);
586 
587     mutex_lock(&scrtc->update_reg_lock);
588     layer_config->flag |= LAYER_ALL_DIRTY;
589 
590     /* do NOT make layer_config_inner->enable = new_state->visible,
591      * layer_config_inner->enable always be true in this function,
592      * when layer disable, DRM_CORE will call ->atomic_disable() instead
593      */
594     /*layers rely upon de to work, so de must be active, or layers can NOT be work*/
595     layer_config_inner->enable = crtc_state->active;
596 
597     layer_config_inner->channel =
598         scrtc->hw_funcs->get_layer_channel_id(
599         scrtc->crtc_id, sunxi_plane->plane_id);
600     layer_config_inner->layer_id =
601         scrtc->hw_funcs->get_layer_id_within_chanel(
602         scrtc->crtc_id, sunxi_plane->plane_id);
603 
604     layer_inner->mode = LAYER_MODE_BUFFER;
605 
606     /*blending setting*/
607     layer_inner->zorder = new_state->zpos;
608     if (sunxi_plane->alpha_mode == NONE_ALPHA_MODE) {
609         layer_inner->alpha_mode = sunxi_plane_get_alpha_mode(
610                         new_state->fb->format->format,
611                         sunxi_plane->galpha_value);
612             layer_inner->alpha_value = sunxi_plane->galpha_value;
613     } else {
614         layer_inner->alpha_mode = sunxi_plane->alpha_mode;
615         layer_inner->alpha_value = sunxi_plane->galpha_value;
616     }
617 
618     if (!layer_inner->alpha_value)
619         layer_inner->alpha_value = 0xff;
620 
621     /*screen display setting(scale)*/
622     layer_inner->screen_win.x = new_state->crtc_x;
623     layer_inner->screen_win.y = new_state->crtc_y;
624     layer_inner->screen_win.width = new_state->crtc_w;
625     layer_inner->screen_win.height = new_state->crtc_h;
626 
627     /*framebuffer information setting
628      * NOTE:
629      * (1)fb_inner->size[i].width means how many pixels a line has
630      */
631     for (i = 0; i < 3; i++) {
632         if (!sunxi_fb->obj[i]) {
633             fb_inner->size[i].width = 0; /*have NOT been test*/
634             fb_inner->size[i].height = 0; /*have NOT been test*/
635             fb_inner->align[i] = 0;
636             continue;
637         }
638 
639         sunxi_gem_obj = sunxi_fb->obj[i];
640         fb_inner->addr[i] = (unsigned long long)sunxi_gem_obj->dma_addr
641                             + fb->offsets[i];
642 
643         switch (fb->format->num_planes) {
644         case 1:
645             fb_inner->size[i].width =  new_state->fb->width;
646             break;
647 
648         case 2:
649             if (i == 0)
650                 fb_inner->size[i].width =  new_state->fb->pitches[i];
651             else if (i == 1)
652                 fb_inner->size[i].width =  new_state->fb->pitches[i] / 2;
653             break;
654 
655         case 3:
656             fb_inner->size[i].width =  new_state->fb->pitches[i];
657             break;
658         }
659 
660         fb_inner->size[i].height = new_state->fb->height;
661         fb_inner->align[i] = 0;
662     }
663     fb_inner->format = drm_to_disp_format(new_state->fb->format->format);
664 
665     if ((new_state->fb->height >= 720) && (new_state->fb->width >= 720))
666         fb_inner->color_space = DISP_BT709;
667     else
668         fb_inner->color_space = DISP_BT601;
669 
670     if (layer_inner->alpha_mode == 2)
671         fb_inner->pre_multiply = true;
672 
673     /*framebuffer crop setting*/
674     fb_inner->crop.x = (((unsigned long long)new_state->src_x) >> 16) << 32;
675     fb_inner->crop.y = (((unsigned long long)new_state->src_y) >> 16) << 32;
676     fb_inner->crop.width = (((unsigned long long)new_state->src_w) >> 16) << 32;
677     fb_inner->crop.height = (((unsigned long long)new_state->src_h) >> 16) << 32;
678 
679     fb_inner->eotf = DISP_EOTF_UNDEF;
680 
681     DRM_DEBUG_DRIVER("[SUNXI-PLANE] CH:%d  layer_id:%d plane_id:%d\n",
682                 layer_config_inner->channel, layer_config_inner->layer_id,
683                 sunxi_plane->plane_id);
684     DRM_DEBUG_DRIVER("[SUNXI-PLANE]zorder:%d alpha_mode:%d alpha_value%d\n",
685         layer_inner->zorder, layer_inner->alpha_mode,
686         layer_inner->alpha_value);
687     DRM_DEBUG_DRIVER("[SUNXI-PLANE]x-y:%d-%d width:%d height:%d\n",
688         layer_inner->screen_win.x, layer_inner->screen_win.y,
689         layer_inner->screen_win.width, layer_inner->screen_win.height);
690     DRM_DEBUG_DRIVER("[SUNXI-PLANE]addr:0x%llx 0x%llx 0x%llx\n", fb_inner->addr[0],
691         fb_inner->addr[1], fb_inner->addr[2]);
692     DRM_DEBUG_DRIVER("[SUNXI-PLANE]width:%u %u %u\n", fb_inner->size[0].width,
693         fb_inner->size[1].width, fb_inner->size[2].width);
694     DRM_DEBUG_DRIVER("[SUNXI-PLANE]height:%u %u %u\n", fb_inner->size[0].height,
695         fb_inner->size[1].height, fb_inner->size[2].height);
696     DRM_DEBUG_DRIVER("[SUNXI-PLANE]format:%d\n", fb_inner->format);
697 
698     DRM_DEBUG_DRIVER("[SUNXI-PLANE]crop x:%lld y:%lld w:%lld h:%lld\n",
699             fb_inner->crop.x, fb_inner->crop.y,
700             fb_inner->crop.width, fb_inner->crop.height);
701     DRM_DEBUG_DRIVER("[SUNXI-PLANE]depth:%d\n", fb_inner->depth);
702 
703     if (scrtc->hw_funcs->single_layer_apply(drm_crtc_index(new_state->crtc),
704                     layer_config) < 0) {
705         DRM_ERROR("sunxi_de single layer_apply failed\n");
706     } else {
707         DRM_DEBUG_DRIVER("[SUNXI-PLANE]%s success\n", __func__);
708     }
709 
710     mutex_unlock(&scrtc->update_reg_lock);
711     return;
712 }
713 
714 /*
715  * disable a certain plane
716  * when libdrm API drmModeSetPlane has NO param of fb_id, it means that user want to disable this plane.
717  * in this case, sunxi_plane_atomic_disable will be call.
718  */
sunxi_plane_atomic_disable(struct drm_plane * plane,struct drm_plane_state * old_state)719 static void sunxi_plane_atomic_disable(struct drm_plane *plane,
720                struct drm_plane_state *old_state)
721 {
722     struct sunxi_drm_crtc *scrtc;
723     struct sunxi_drm_plane *sunxi_plane = to_sunxi_plane(plane);
724     struct disp_layer_config_data *layer_config = &sunxi_plane->config;
725     struct disp_layer_config_inner *layer_config_inner = &layer_config->config;
726     struct disp_layer_info_inner *layer_inner = &layer_config_inner->info;
727 
728     DRM_DEBUG_DRIVER("[SUNXI-PLANE]%s plane:%d\n", __func__, plane->index);
729     scrtc = to_sunxi_crtc(old_state->crtc);
730 
731     mutex_lock(&scrtc->update_reg_lock);
732     layer_config->flag = LAYER_ALL_DIRTY;
733     memset(layer_inner, 0, sizeof(struct disp_layer_info_inner));
734 
735     layer_config_inner->enable = false;
736 
737     layer_config->config.channel =
738         scrtc->hw_funcs->get_layer_channel_id(
739                 scrtc->crtc_id, plane->index);
740     layer_config->config.layer_id =
741         scrtc->hw_funcs->get_layer_id_within_chanel(
742                 scrtc->crtc_id, plane->index);
743 
744     if (scrtc->hw_funcs->single_layer_apply(drm_crtc_index(old_state->crtc),
745                 layer_config) < 0) {
746         DRM_ERROR("sunxi_de single layer_apply failed\n");
747     } else {
748         DRM_DEBUG_DRIVER("%s success\n", __func__);
749     }
750 
751     mutex_unlock(&scrtc->update_reg_lock);
752     return;
753 }
754 
755 static const struct drm_plane_funcs sunxi_plane_funcs = {
756     .update_plane = drm_atomic_helper_update_plane,
757     .disable_plane = drm_atomic_helper_disable_plane,
758     .destroy = drm_plane_cleanup,
759     .reset = drm_atomic_helper_plane_reset,
760     .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
761     .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
762     .atomic_get_property = sunxi_plane_atomic_get_property,
763     .atomic_set_property = sunxi_plane_atomic_set_property,
764 };
765 
766 static const struct drm_plane_helper_funcs sunxi_plane_helper_funcs = {
767 #ifndef CONFIG_AW_DRM_PANFROST /* @TODO: fix this */
768     .prepare_fb = sunxi_drm_fb_prepare_fb,
769 //    .atomic_check = sunxi_plane_atomic_check,
770 #endif
771     .atomic_update = sunxi_plane_atomic_update,
772     .atomic_disable = sunxi_plane_atomic_disable,
773 };
774 
sunxi_drm_plane_init(struct drm_device * dev,struct sunxi_drm_plane * plane,int crtc_id,int plane_id,int type)775 int sunxi_drm_plane_init(struct drm_device *dev,
776             struct sunxi_drm_plane *plane,
777             int crtc_id, int plane_id, int type)
778 {
779     const uint32_t *formats;
780     unsigned int format_count;
781     struct sunxi_drm_crtc *scrtc = sunxi_drm_crtc_get_crtc(crtc_id);
782 
783     if (type == DRM_PLANE_TYPE_CURSOR) {
784         DRM_ERROR("sunxi hw do NOT support cursor plane\n");
785         return -1;
786     }
787 
788     plane->plane_id = plane_id;
789 
790     if (scrtc->hw_funcs->get_layer_formats(crtc_id, plane_id,
791             &formats, &format_count) < 0) {
792         DRM_ERROR("sunxi_de_get_layer_format failed\n");
793         return -1;
794     }
795 
796     if (drm_universal_plane_init(dev, &plane->plane, 1 << crtc_id,
797                  &sunxi_plane_funcs,
798                  formats, format_count,
799                  NULL,
800                  type,
801                  "crtc%d-plane%d", crtc_id, plane_id)) {
802         DRM_ERROR("drm_universal_plane_init failed\n");
803         return -1;
804     }
805 
806     if (drm_plane_create_zpos_property(&plane->plane, 0, 0,
807             scrtc->hw_funcs->get_layer_count(crtc_id)) < 0) {
808         DRM_ERROR("drm_plane_create_zpos_property Failed\n");
809         return -1;
810     }
811 
812     if (sunxi_plane_create_alpha_mode_property(plane, NONE_ALPHA_MODE,
813                 0, ALPHA_MODE_NUM) < 0) {
814         DRM_ERROR("sunxi_plane_create_alpha_mode_property Failed\n");
815         return -1;
816     }
817 
818     if (sunxi_plane_create_galpha_value_property(plane, 0xff, 0, 0xff) < 0) {
819         DRM_ERROR("sunxi_plane_create_galpha_value_property Failed\n");
820         return -1;
821     }
822 
823     if (sunxi_plane_create_group_index_property(plane, crtc_id) < 0) {
824         DRM_ERROR("sunxi_plane_create_group_index_property Failed\n");
825         return -1;
826     }
827 
828 
829     if (sunxi_plane_create_sub_index_property(plane, crtc_id) < 0) {
830         DRM_ERROR("sunxi_plane_create_sub_index_property Failed\n");
831         return -1;
832     }
833 
834     drm_plane_helper_add(&plane->plane, &sunxi_plane_helper_funcs);
835 
836     sunxi_plane_reset(&plane->plane);
837     return 0;
838 }
839