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