1 /*sunxi_drm_drv.c
2 *
3 * Copyright (C) 2022 Allwinnertech Co., Ltd.
4 * Authors: zhengwanyu <zhengwanyu@allwinnertech.com>
5 * Authors: hongyaobin <hongyaobin@allwinnertech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13 #include <drm/drm_crtc_helper.h>
14 #include <drm/drm_drv.h>
15 #include <drm/drm_probe_helper.h>
16
17 #include "sunxi_drm_bootlogo.h"
18 #include "sunxi_drm_drv.h"
19 #include "sunxi_drm_crtc.h"
20 #include "sunxi_drm_encoder.h"
21 #include "sunxi_drm_connector.h"
22 #include "sunxi_drm_fb.h"
23 #include "sunxi_drm_gem.h"
24
25 #ifdef CONFIG_DRM_FBDEV_EMULATION
26 #include "sunxi_drm_fbdev.h"
27 #endif
28
29 #include "sunxi_drm_gem.h"
30 #include "sunxi_drm_sysfs.h"
31 #include "sunxi_drm_iommu.h"
32
33 #include "drm_internal.h"
34
35 #define DRIVER_NAME "sunxi-drm"
36 #define DRIVER_DESC "allwinnertech SoC DRM"
37 #define DRIVER_DATE "20220517"
38 #define DRIVER_MAJOR 2
39 #define DRIVER_MINOR 0
40
41 #define VBLANK_OFF_DELAY 50000
42
43 static struct sunxi_drm_private sunxi_drv_prv;
44
sunxi_drm_platform_init(struct drm_driver * ddrv,struct device * dev)45 static int sunxi_drm_platform_init(struct drm_driver *ddrv, struct device *dev)
46 {
47 struct drm_device *ddev;
48 struct platform_device *pdev = to_platform_device(dev);
49 struct device_node *node = dev->of_node;
50 int ret;
51
52 ddev = drm_dev_alloc(ddrv, dev);
53 if (IS_ERR(ddev))
54 return PTR_ERR(ddev);
55
56 ret = drm_dev_register(ddev, 0);
57 if (ret)
58 goto init_failed;
59
60 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
61 ddrv->name, ddrv->major, ddrv->minor, ddrv->patchlevel,
62 ddrv->date, ddev->primary->index);
63 return 0;
64
65 init_failed:
66 //@TODO
67 return ret;
68 }
69
sunxi_drm_get_drm_device(void)70 struct drm_device *sunxi_drm_get_drm_device(void)
71 {
72 return sunxi_drv_prv.drm_dev;
73 }
74
75 #ifdef CONFIG_VIDEO_SUNXI_CAR_REVERSE
76 static int _force_plane_en;
77 static unsigned int active_plane_mask;
78
sunxi_drm_get_force_plane_en(void)79 int sunxi_drm_get_force_plane_en(void)
80 {
81 return _force_plane_en;
82 }
83
sunxi_drm_get_num_crtc(void)84 int sunxi_drm_get_num_crtc(void)
85 {
86 return sunxi_drm_get_crtc_count();
87 }
88 EXPORT_SYMBOL(sunxi_drm_get_num_crtc);
89
sunxi_drm_crtc_find_attached_device(struct drm_crtc * crtc,struct drm_encoder ** enc,struct drm_connector ** conn)90 static int sunxi_drm_crtc_find_attached_device(struct drm_crtc *crtc,
91 struct drm_encoder **enc, struct drm_connector **conn)
92 {
93 bool find = false;
94 struct drm_encoder *encoder;
95 struct drm_connector *connector;
96 struct drm_device *dev;
97
98 dev = crtc->dev;
99
100 /*find attaching encoder for crtc*/
101 find = false;
102 drm_for_each_encoder(encoder, dev) {
103 if (encoder->crtc == crtc) {
104 find = true;
105 break;
106 }
107 }
108 if (!find) {
109 DRM_ERROR("crtc:%d has NOT attaching encoder!\n", crtc->index);
110 return -1;
111 }
112 *enc = encoder;
113
114 /*find attaching connector for encoder*/
115 find = false;
116 drm_for_each_connector(connector, dev) {
117 if (connector->encoder == encoder) {
118 find = true;
119 break;
120 }
121 }
122 if (!find) {
123 DRM_ERROR("encoder:%d has NOT attaching connector!\n",
124 encoder->index);
125 return -1;
126 }
127 *conn = connector;
128
129 return 0;
130 }
131
disp_layer_config_convert_to_inner(struct disp_layer_config_inner * layer_inner,struct disp_layer_config * config)132 static void disp_layer_config_convert_to_inner(
133 struct disp_layer_config_inner *layer_inner,
134 struct disp_layer_config *config)
135 {
136 layer_inner->enable = config->enable;
137 layer_inner->channel = config->channel;
138 layer_inner->layer_id = config->layer_id;
139 layer_inner->info.mode = config->info.mode;
140 layer_inner->info.zorder = config->info.zorder;
141 layer_inner->info.alpha_mode = config->info.alpha_mode;
142 layer_inner->info.alpha_value = config->info.alpha_value;
143 memcpy(&layer_inner->info.screen_win,
144 &config->info.screen_win, sizeof(struct disp_rect));
145 memcpy(&layer_inner->info.fb.addr, &config->info.fb.addr,
146 3 * sizeof(unsigned long long));
147 memcpy(&layer_inner->info.fb.size, &config->info.fb.size,
148 3 * sizeof(struct disp_rectsz));
149 memcpy(&layer_inner->info.fb.align, &config->info.fb.align,
150 3 * sizeof(unsigned int));
151 layer_inner->info.fb.format = config->info.fb.format;
152 layer_inner->info.fb.color_space = config->info.fb.color_space;
153 layer_inner->info.fb.pre_multiply = config->info.fb.pre_multiply;
154 memcpy(&layer_inner->info.fb.crop, &config->info.fb.crop,
155 sizeof(struct disp_rect64));
156 layer_inner->info.fb.flags = config->info.fb.flags;
157 layer_inner->info.fb.scan = config->info.fb.scan;
158 }
159
sunxi_drm_disable_all_active_plane(struct drm_crtc * crtc)160 static void sunxi_drm_disable_all_active_plane(struct drm_crtc *crtc)
161 {
162 struct drm_plane *plane;
163 struct sunxi_drm_crtc *scrtc = to_sunxi_crtc(crtc);
164
165 drm_for_each_plane(plane, crtc->dev) {
166 struct disp_layer_config_data layer_config;
167
168 if (plane->crtc != crtc)
169 continue;
170
171 if (!plane->state)
172 continue;
173
174 memset(&layer_config, 0,
175 sizeof(struct disp_layer_config_data));
176 layer_config.flag = LAYER_ALL_DIRTY;
177 layer_config.config.enable = false;
178
179 layer_config.config.channel =
180 scrtc->hw_funcs->get_layer_channel_id(
181 scrtc->crtc_id, plane->index);
182 layer_config.config.layer_id =
183 scrtc->hw_funcs->get_layer_id_within_chanel(
184 scrtc->crtc_id, plane->index);
185
186 if (scrtc->hw_funcs->single_layer_apply(scrtc->crtc_id,
187 &layer_config) < 0) {
188 DRM_ERROR("sunxi_de single layer_apply failed\n");
189 } else {
190 DRM_DEBUG_DRIVER("%s success\n", __func__);
191 }
192 }
193 }
194
sunxi_drm_force_set_plane(int crtc_id,struct disp_layer_config * config,unsigned int plane_num)195 int sunxi_drm_force_set_plane(int crtc_id, struct disp_layer_config *config,
196 unsigned int plane_num)
197 {
198 int i = 0, irq_no;
199 bool enable;
200
201 unsigned int hdisplay, vdisplay, vrefresh;
202 struct disp_video_timings *p_info = NULL;
203 unsigned int tv_mode = 0;
204
205 struct disp_manager_data data;
206 struct disp_manager_info *info = &data.config;
207 struct disp_layer_config_data layer_data[16];
208 struct disp_layer_config_inner *layer_inner;
209
210 struct drm_device *dev;
211 struct drm_encoder *encoder;
212 struct sunxi_drm_encoder *sencoder;
213 struct drm_connector *conn;
214 struct sunxi_drm_connector *sconn;
215 struct sunxi_drm_crtc *scrtc = sunxi_drm_crtc_get_crtc(crtc_id);
216 struct drm_crtc_state *crtc_state = NULL;
217
218 dev = scrtc->crtc.dev;
219 memset(&data, 0, sizeof(struct disp_manager_data));
220 memset(layer_data, 0,
221 16 * sizeof(struct disp_layer_config_data));
222
223 _force_plane_en = 1;
224
225 crtc_state = scrtc->crtc.state;
226 if (!crtc_state) {
227 DRM_ERROR("crtc:%d has NOT set!\n", crtc_id);
228 return;
229 }
230
231 mutex_lock(&dev->mode_config.mutex);
232
233 if (sunxi_drm_crtc_find_attached_device(&scrtc->crtc,
234 &encoder, &conn) < 0) {
235 DRM_INFO("[warning] crtc:%d has NOT been set\n",
236 scrtc->crtc_id);
237 return -1;
238 }
239 sencoder = to_sunxi_encoder(encoder);
240 sconn = to_sunxi_connector(conn);
241 /*attaching connector type for tcon*/
242 sencoder->hw_funcs =
243 sunxi_tcon_attach_connector_type(sencoder->encoder_id,
244 sconn->type);
245 mutex_unlock(&dev->mode_config.mutex);
246
247 enable = scrtc->hw_funcs->is_enable(crtc_id);
248 if (!enable) {
249 /*irq register*/
250 sencoder->use_irq =
251 sencoder->hw_funcs->is_use_irq(sencoder->encoder_id);
252 sencoder->irq_no =
253 sencoder->hw_funcs->get_irq_no(sencoder->encoder_id);
254
255 if (sconn->use_irq)
256 irq_no = sconn->irq_no;
257 else if (sencoder->use_irq)
258 irq_no = sencoder->irq_no;
259 else
260 DRM_INFO("WARN: NO irq for tcon%d and lcd%d\n",
261 sencoder->encoder_id, sconn->con_id);
262 if (scrtc->irq_register(scrtc, irq_no) < 0) {
263 DRM_ERROR("sunxi_drm_crtc_irq_register failed\n");
264 return -1;
265 }
266
267 /*setting params for sunxi-crtc and enable it*/
268 data.flag = MANAGER_ALL_DIRTY;
269 info->size.x = 0;
270 info->size.y = 0;
271
272 info->hwdev_index = encoder->index;
273
274 sconn->get_init_resolution(sconn,
275 &hdisplay, &vdisplay, &vrefresh);
276 info->size.width = hdisplay;
277 info->size.height = vdisplay;
278
279 info->color_space = DISP_BT601_F;
280
281 if (sconn->get_work_mode) {
282 struct sunxi_connector_work_mode conn_work_mode;
283
284 sconn->get_work_mode(sconn, &conn_work_mode);
285
286 if (conn_work_mode.color_fmt == COLOR_FMT_RGB444)
287 info->cs = DISP_CSC_TYPE_RGB;
288 else if (conn_work_mode.color_fmt == COLOR_FMT_YUV444)
289 info->cs = DISP_CSC_TYPE_YUV444;
290 else if (conn_work_mode.color_fmt == COLOR_FMT_YUV422)
291 info->cs = DISP_CSC_TYPE_YUV422;
292 else if (conn_work_mode.color_fmt == COLOR_FMT_YUV420)
293 info->cs = DISP_CSC_TYPE_YUV420;
294 else {
295 info->cs = DISP_CSC_TYPE_RGB;
296 DRM_ERROR("sunxi connector:%d working mode hasn't been set\n",
297 sconn->con_id);
298 }
299 } else {
300 info->cs = DISP_CSC_TYPE_RGB;
301 }
302
303
304 if (info->cs == DISP_CSC_TYPE_RGB)
305 info->color_range = DISP_COLOR_RANGE_0_255;
306 else
307 info->color_range = DISP_COLOR_RANGE_16_235;
308
309 info->conn_type = sconn->type;
310
311 info->enable = true;
312 info->disp_device = crtc_id;
313
314 info->blank = false;
315 info->de_freq = scrtc->hw_funcs->get_freq(crtc_id);
316 info->device_fps = vrefresh;
317 info->eotf = DISP_EOTF_GAMMA22;
318 info->data_bits = DISP_DATA_8BITS;
319
320 scrtc->hw_funcs->enable(crtc_id, &data);
321
322 /*set encoder and connector*/
323 if (kstrtou32(crtc_state->mode.name, 10, &tv_mode)) {
324 DRM_ERROR("Get tv mode fail!\n");
325 return;
326 }
327
328 if (sconn->get_video_timing)
329 sconn->get_video_timing(p_info, tv_mode);
330 sencoder->hw_funcs->set(scrtc->crtc_id,
331 sencoder->encoder_id,
332 sconn->type_id, p_info, tv_mode);
333 sconn->enable(sconn, tv_mode);
334 } else {
335 sunxi_drm_disable_all_active_plane(&scrtc->crtc);
336 }
337
338 /*set plane*/
339 for (i = 0; i < plane_num; i++) {
340 layer_data[i].flag = LAYER_ALL_DIRTY;
341
342 layer_inner = &layer_data[i].config;
343 disp_layer_config_convert_to_inner(layer_inner,
344 &config[i]);
345 active_plane_mask |=
346 1 << (layer_inner->channel * 4 + layer_inner->layer_id);
347 }
348
349 scrtc->hw_funcs->multi_layers_apply(scrtc->crtc_id,
350 layer_data, plane_num);
351
352 atomic_set(&scrtc->update, 1);
353
354 return 0;
355 }
356 EXPORT_SYMBOL(sunxi_drm_force_set_plane);
357
358 /*
359 * exit force_set_plane and restore drm setings set by user space app
360 */
sunxi_drm_force_set_plane_exit(int crtc_id)361 void sunxi_drm_force_set_plane_exit(int crtc_id)
362 {
363 struct sunxi_drm_crtc *scrtc = sunxi_drm_crtc_get_crtc(crtc_id);
364 const struct drm_crtc_helper_funcs *crtc_funcs = scrtc->crtc.helper_private;
365 struct drm_crtc_state *crtc_state = NULL;
366 struct drm_plane *plane;
367 struct drm_plane_state *plane_state = NULL;
368
369 if (!_force_plane_en)
370 return;
371 _force_plane_en = 0;
372
373 crtc_state = scrtc->crtc.state;
374 if (!crtc_state) {
375 DRM_ERROR("crtc:%d has NOT set!\n", crtc_id);
376 return;
377 }
378
379 drm_for_each_plane(plane, scrtc->crtc.dev) {
380 struct disp_layer_config_data layer_config;
381
382 if (!(active_plane_mask & (1 << plane->index)))
383 continue;
384
385 memset(&layer_config, 0,
386 sizeof(struct disp_layer_config_data));
387
388 layer_config.config.channel =
389 scrtc->hw_funcs->get_layer_channel_id(
390 crtc_id, plane->index);
391 layer_config.config.layer_id =
392 scrtc->hw_funcs->get_layer_id_within_chanel(
393 crtc_id, plane->index);
394
395 layer_config.flag = LAYER_ALL_DIRTY;
396 layer_config.config.enable = false;
397
398 if (scrtc->hw_funcs->single_layer_apply(scrtc->crtc_id,
399 &layer_config) < 0) {
400 DRM_ERROR("sunxi_de single layer_apply failed\n");
401 } else {
402 DRM_DEBUG_DRIVER("%s success\n", __func__);
403 }
404 }
405
406 drm_for_each_plane(plane, scrtc->crtc.dev) {
407 const struct drm_plane_helper_funcs *plane_funcs;
408
409 if (crtc_state->plane_mask & (1 << plane->index)) {
410 plane_state = plane->state;
411 if (!plane_state)
412 continue;
413
414 DRM_INFO("SET plane:%d\n", plane->index);
415 plane_funcs = plane->helper_private;
416 plane_funcs->atomic_update(plane, NULL);
417 }
418 }
419
420 atomic_set(&scrtc->update, 1);
421
422 crtc_funcs->enable(&scrtc->crtc);
423 }
424 EXPORT_SYMBOL(sunxi_drm_force_set_plane_exit);
425
426 #endif
427
sunxi_drm_enable_vblank(struct drm_device * dev,unsigned int pipe)428 int sunxi_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
429 {
430 return 0;
431 }
432
sunxi_drm_disable_vblank(struct drm_device * dev,unsigned int pipe)433 void sunxi_drm_disable_vblank(struct drm_device *dev, unsigned int pipe)
434 {
435 return;
436 }
437
sunxi_drm_vblank_counter(struct drm_device * dev,unsigned int pipe)438 u32 sunxi_drm_vblank_counter(struct drm_device *dev, unsigned int pipe)
439 {
440 return 0;
441 }
442
443 /*
444 * bootlogo processing for crtc/connector state:
445 * 1.create a state for connector and initial its members with booting information;
446 * 2.create a state for crtc and initial its members with booting information;
447 */
sunxi_drm_smooth_set_state(struct drm_device * dev)448 static int sunxi_drm_smooth_set_state(struct drm_device *dev)
449 {
450 struct drm_display_mode *mode;
451 struct drm_crtc *crtc;
452 struct sunxi_drm_crtc *scrtc;
453 struct sunxi_drm_connector *sconn =
454 sunxi_drm_connector_get_connector(0);
455 struct drm_connector *conn = &sconn->connector;
456
457 if (!conn->state) {
458 conn->state
459 = kzalloc(sizeof(struct drm_connector_state),
460 GFP_KERNEL);
461 if (!conn->state) {
462 DRM_ERROR("allocate mem for "
463 "drm_connector_state failed\n");
464 return -1;
465 }
466 }
467
468 /*sunxi_drm_fbdev_initial_config()
469 has been do a default attachment for crtc/encoder/connector*/
470 if (!conn->encoder) {
471 DRM_ERROR("connector has NOT attched to a encoder\n");
472 return -1;
473 }
474 if (!conn->encoder->crtc) {
475 DRM_ERROR("encoder has NOT attached to a crtc\n");
476 return -1;
477 }
478
479 conn->state->best_encoder = conn->encoder;
480 conn->state->crtc = conn->encoder->crtc;
481 conn->state->connector = conn;
482
483 crtc = conn->encoder->crtc;
484 scrtc = to_sunxi_crtc(crtc);
485
486 if (!crtc->state) {
487 crtc->state =
488 kzalloc(sizeof(struct drm_crtc_state), GFP_KERNEL);
489 if (!crtc->state) {
490 DRM_ERROR("allocate mem for drm_crtc_state "
491 "failed\n");
492 return -1;
493 }
494 }
495
496 crtc->state->crtc = crtc;
497 crtc->state->enable = 1;
498 crtc->state->active = 1;
499 crtc->state->plane_mask = 0x10000000;
500 crtc->state->connector_mask = 0x1;
501 crtc->state->encoder_mask = 1 << conn->encoder->index;
502
503 list_for_each_entry(mode, &conn->modes, head) {
504 memcpy(&crtc->state->mode, mode,
505 sizeof(struct drm_display_mode));
506 drm_mode_copy(&crtc->state->adjusted_mode, mode);
507 }
508
509 return 0;
510 }
511
512
sunxi_drm_is_need_smooth_boot(void)513 bool sunxi_drm_is_need_smooth_boot(void)
514 {
515 /*fb_base got from DTS is the judgement*/
516 return sunxi_drv_prv.boot_disp ? true : false;
517 }
518
sunxi_drm_smooth_boot(struct drm_device * dev)519 static int sunxi_drm_smooth_boot(struct drm_device *dev)
520 {
521 int ret;
522
523 struct sunxi_drm_crtc *scrtc;
524 struct drm_encoder *enc;
525 struct sunxi_drm_encoder *senc;
526 struct sunxi_drm_connector *sconn;
527
528 scrtc = sunxi_drm_crtc_get_crtc(0);
529 sconn = sunxi_drm_connector_get_connector(0);
530
531 enc = sconn->connector.encoder;
532 if (!enc) {
533 DRM_ERROR("crtc:0 has NO attached encoder\n");
534 return -1;
535 }
536 senc = to_sunxi_encoder(enc);
537
538 ret = sunxi_drm_smooth_set_state(dev);
539 if (ret < 0) {
540 DRM_ERROR("sunxi_drm_smooth_set_state failed\n");
541 return -1;
542 }
543
544 scrtc->sw_enable(scrtc);
545 senc->sw_enable(senc);
546
547 return 0;
548 }
549
550 /*this func is used to decide bpp of fbdev fb */
sunxi_drm_get_init_bpp(void)551 unsigned int sunxi_drm_get_init_bpp(void)
552 {
553 #ifdef CONFIG_DRM_FBDEV_EMULATION
554 if (sunxi_drv_prv.bootlogo.bpp)
555 return sunxi_drv_prv.bootlogo.bpp;
556 #endif
557
558 return 32;
559 }
560
561 /*this func is used to decide width of fbdev fb */
sunxi_drm_get_init_width(void)562 unsigned int sunxi_drm_get_init_width(void)
563 {
564 unsigned int w, h, f;
565 struct sunxi_drm_connector *sconn
566 = sunxi_drm_connector_get_connector(0);
567
568 #ifdef CONFIG_DRM_FBDEV_EMULATION
569 if (sunxi_drv_prv.bootlogo.width)
570 return sunxi_drv_prv.bootlogo.width;
571 #endif
572
573 sconn->get_init_resolution(sconn, &w, &h, &f);
574 return w;
575 }
576
577 /*this func is used to decide height of fbdev fb*/
sunxi_drm_get_init_height(void)578 unsigned int sunxi_drm_get_init_height(void)
579 {
580 unsigned int w, h, f;
581 struct sunxi_drm_connector *sconn
582 = sunxi_drm_connector_get_connector(0);
583
584 #ifdef CONFIG_DRM_FBDEV_EMULATION
585 if (sunxi_drv_prv.bootlogo.height)
586 return sunxi_drv_prv.bootlogo.height;
587 #endif
588
589 sconn->get_init_resolution(sconn, &w, &h, &f);
590 return h;
591 }
592
sunxi_drm_get_connector_type(int i)593 unsigned int sunxi_drm_get_connector_type(int i)
594 {
595 if (i >= sunxi_drv_prv.connector_num) {
596 DRM_ERROR("connector:%d is out of range!\n", i);
597 return 0;
598 }
599
600 return sunxi_drv_prv.connector_type[i];
601 }
602
sunxi_drm_get_connector_mode(int i)603 char *sunxi_drm_get_connector_mode(int i)
604 {
605 if (i >= sunxi_drv_prv.connector_num) {
606 DRM_ERROR("connector:%d is out of range!\n", i);
607 return NULL;
608 }
609
610 return (char *)&sunxi_drv_prv.connector_mode[i][0];
611 }
612
sunxi_drm_get_connector_count(void)613 unsigned int sunxi_drm_get_connector_count(void)
614 {
615 return sunxi_drv_prv.connector_num;
616 }
617
sunxi_drm_init(struct drm_device * dev)618 static int sunxi_drm_init(struct drm_device *dev)
619 {
620 if (sunxi_drm_crtc_init(dev) < 0) {
621 DRM_ERROR("sunxi_drm_crtc_init failed\n");
622 goto crtc_err;
623 }
624
625 if (sunxi_drm_encoder_init(dev) < 0) {
626 DRM_ERROR("sunxi_drm_encoder_init failed\n");
627 goto enc_err;
628 }
629
630 if (sunxi_drm_connector_init(dev) < 0) {
631 DRM_ERROR("sunxi_drm_connector_init failed\n");
632 goto con_err;
633 }
634
635 #ifdef CONFIG_DRM_FBDEV_EMULATION
636 if (sunxi_drm_fbdev_init(dev) < 0) {
637 DRM_ERROR("sunxi_drm_fbdev_init failed\n");
638 goto con_err;
639 }
640 #endif
641
642 return 0;
643
644 con_err:
645 sunxi_drm_connector_exit(dev);
646 enc_err:
647 sunxi_drm_encoder_exit(dev);
648 crtc_err:
649 sunxi_drm_crtc_exit(dev);
650 DRM_ERROR("sunxi drm init failed\n");
651 return -1;
652 }
653
sunxi_drm_destroy(struct drm_device * dev)654 void sunxi_drm_destroy(struct drm_device *dev)
655 {
656 #ifdef CONFIG_DRM_FBDEV_EMULATION
657 sunxi_drm_fbdev_exit(dev);
658 #endif
659 sunxi_drm_connector_exit(dev);
660 sunxi_drm_encoder_exit(dev);
661 sunxi_drm_crtc_exit(dev);
662 }
663
sunxi_drm_output_poll_changed(struct drm_device * dev)664 static void sunxi_drm_output_poll_changed(struct drm_device *dev)
665 {
666 #ifdef CONFIG_DRM_FBDEV_EMULATION
667 sunxi_drm_fbdev_output_poll_changed(dev);
668 #else
669 /*struct drm_crtc *crtc;
670 struct drm_encoder *encoder;
671 bool find = false;
672
673 drm_for_each_crtc(crtc, dev) {
674 if (!crtc->state)
675 continue;
676 if (crtc->state->active)
677 continue;
678
679 crtc->helper_private->enable(crtc);
680
681 drm_for_each_encoder(encoder, dev) {
682 if (encoder->crtc == crtc) {
683 find = true;
684 break;
685 }
686 }
687
688 if (!find) {
689 DRM_ERROR("can NOT find an \n");
690 }
691 }*/
692 #endif
693 return;
694 }
695
696 static const struct drm_mode_config_funcs sunxi_drm_mode_config_funcs = {
697 .atomic_check = drm_atomic_helper_check,
698 .atomic_commit = drm_atomic_helper_commit,
699 .output_poll_changed = sunxi_drm_output_poll_changed,
700 .fb_create = sunxi_drm_fb_create,
701 };
702
sunxi_drm_mode_config_init(struct drm_device * dev)703 void sunxi_drm_mode_config_init(struct drm_device *dev)
704 {
705 dev->mode_config.min_width = 0;
706 dev->mode_config.min_height = 0;
707
708 /* max_width be decided by the de bufferline */
709 dev->mode_config.max_width = 8192;
710 dev->mode_config.max_height = 8192;
711
712 dev->mode_config.funcs = &sunxi_drm_mode_config_funcs;
713
714 }
715
sunxi_drm_init_iommu(struct drm_device * drm_dev)716 static int sunxi_drm_init_iommu(struct drm_device *drm_dev)
717 {
718 int ret;
719 struct sunxi_drm_private *priv = drm_dev->dev_private;
720
721 if (!IS_ENABLED(CONFIG_AW_IOMMU) || !IS_ENABLED(CONFIG_DRM_AW_IOMMU))
722 return 0;
723
724 /* create common IOMMU mapping for all devices attached to SUNXI DRM */
725 ret = sunxi_drm_create_iommu_mapping(drm_dev);
726 if (ret < 0) {
727 DRM_ERROR("failed to create iommu mapping.\n");
728 return ret;
729 }
730
731 return 0;
732 }
733
sunxi_drm_load(struct drm_device * dev,unsigned long flags)734 static int sunxi_drm_load(struct drm_device *dev, unsigned long flags)
735 {
736 int ret;
737
738 DRM_INFO("[DRM-DRV]%s start\n", __func__);
739
740 dev->dev_private = (void *)&sunxi_drv_prv;
741 sunxi_drv_prv.drm_dev = dev;
742
743 if (sunxi_drm_init_iommu(dev)) {
744 DRM_ERROR("sunxi_drm_init_iommu failed!\n");
745 goto load_err;
746 }
747
748 drm_mode_config_init(dev);
749 sunxi_drm_mode_config_init(dev);
750
751 if (sunxi_drm_init(dev)) {
752 DRM_ERROR("failed to initialize sunxi drm dev.\n");
753 goto load_err;
754 }
755
756 dev->irq_enabled = 1;
757 ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
758 if (ret) {
759 DRM_ERROR("failed to init vblank.\n");
760 goto load_err;
761 }
762
763 /* init kms poll for handling hpd */
764 drm_kms_helper_poll_init(dev);
765 return 0;
766
767 load_err:
768 sunxi_drm_destroy(dev);
769 drm_mode_config_cleanup(dev);
770 sunxi_drv_prv.drm_dev = NULL;
771 DRM_ERROR("LOAD failed\n");
772 return -1;
773 }
774
sunxi_drm_unload(struct drm_device * dev)775 static void sunxi_drm_unload(struct drm_device *dev)
776 {
777 //drm_vblank_cleanup(dev);
778 sunxi_drm_destroy(dev);
779 drm_mode_config_cleanup(dev);
780 }
781
782 static struct drm_ioctl_desc sunxi_ioctls[] = {
783 DRM_IOCTL_DEF_DRV(SUNXI_GEM_CREATE, sunxi_drm_gem_create_ioctl,
784 DRM_AUTH | DRM_RENDER_ALLOW),
785 DRM_IOCTL_DEF_DRV(SUNXI_SET_ENHANCE, sunxi_drm_crtc_set_enhance_ioctl,
786 DRM_AUTH | DRM_RENDER_ALLOW),
787 DRM_IOCTL_DEF_DRV(SUNXI_GET_ENHANCE, sunxi_drm_crtc_get_enhance_ioctl,
788 DRM_AUTH | DRM_RENDER_ALLOW),
789 DRM_IOCTL_DEF_DRV(SUNXI_SET_SMBL, sunxi_drm_crtc_set_smbl_ioctl,
790 DRM_AUTH | DRM_RENDER_ALLOW),
791 DRM_IOCTL_DEF_DRV(SUNXI_GET_SMBL, sunxi_drm_crtc_get_smbl_ioctl,
792 DRM_AUTH | DRM_RENDER_ALLOW),
793 DRM_IOCTL_DEF_DRV(SUNXI_GEM_FD_TO_PHYADDR, sunxi_drm_gem_get_phyaddr_ioctl,
794 DRM_UNLOCKED),
795 };
796
797 static const struct file_operations sunxi_drm_driver_fops = {
798 .owner = THIS_MODULE,
799 .open = drm_open,
800 .mmap = sunxi_drm_gem_mmap,
801 .poll = drm_poll,
802 .read = drm_read,
803 .unlocked_ioctl = drm_ioctl,
804 #ifdef CONFIG_COMPAT
805 .compat_ioctl = drm_compat_ioctl,
806 #endif
807 .release = drm_release,
808 };
809
810 static struct drm_driver sunxi_drm_driver = {
811 .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
812 DRIVER_GEM | DRIVER_ATOMIC,
813 .ioctls = sunxi_ioctls,
814 .fops = &sunxi_drm_driver_fops,
815 .name = DRIVER_NAME,
816 .desc = DRIVER_DESC,
817 .date = DRIVER_DATE,
818 .major = DRIVER_MAJOR,
819 .minor = DRIVER_MINOR,
820 .load = sunxi_drm_load,
821 .unload = sunxi_drm_unload,
822
823 /*gem*/
824 .gem_vm_ops = &sunxi_drm_gem_vm_ops,
825 .gem_free_object_unlocked = sunxi_drm_gem_free_object,
826 .dumb_create = sunxi_drm_gem_dumb_create,
827 .dumb_map_offset = sunxi_drm_gem_dumb_map_offset,
828 .dumb_destroy = drm_gem_dumb_destroy,
829
830 /*prime*/
831 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
832 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
833 .gem_prime_export = drm_gem_prime_export,
834 .gem_prime_import = drm_gem_prime_import,
835 .gem_prime_get_sg_table = sunxi_drm_gem_prime_get_sg_table,
836 .gem_prime_import_sg_table = sunxi_drm_gem_prime_import_sg_table,
837 .gem_prime_mmap = sunxi_drm_gem_prime_mmap,
838
839 /*vblank*/
840 .enable_vblank = sunxi_drm_enable_vblank,
841 .disable_vblank = sunxi_drm_disable_vblank,
842 .get_vblank_counter = sunxi_drm_vblank_counter,
843 };
844
sunxi_drm_parse_dts(struct device_node * np)845 static int sunxi_drm_parse_dts(struct device_node *np)
846 {
847 int ret = 0, i;
848 unsigned char string[30] = { 0 };
849 #ifdef CONFIG_DRM_FBDEV_EMULATION
850 unsigned int boot_disp;
851 #endif
852
853 /*read bootlogo physical address*/
854 ret = of_property_read_u32(np, "fb_base",
855 &sunxi_drv_prv.fb_base);
856 if (ret < 0) {
857 DRM_ERROR("Parse DTS-info fb_base failed!\n");
858 return ret;
859 }
860
861 if (sunxi_drv_prv.fb_base == 0) {
862 const char *boot_fb;
863
864 ret = of_property_read_string(np, "boot_fb0",
865 &boot_fb);
866 if (ret < 0) {
867 DRM_ERROR("There is NO boot_fb0\n");
868 return ret;
869 }
870
871 strcpy(sunxi_drv_prv.boot_fb, (char *)boot_fb);
872 }
873
874 #ifdef CONFIG_DRM_FBDEV_EMULATION
875 /*read that if there is a bootlogo output during bootloader*/
876 ret = of_property_read_u32(np, "boot_disp", &boot_disp);
877 if (ret < 0) {
878 DRM_ERROR("Parse DTS-info boot_disp failed!\n");
879 return ret;
880 }
881 sunxi_drv_prv.boot_disp = boot_disp ? true : false;
882 #endif
883
884 for (i = 0; i < MAX_CONNECTOR_COUNT; i++) {
885 const char *mode_name;
886
887 sprintf(string, "connector%d_output_type", i);
888 ret = of_property_read_u32(np, string,
889 &sunxi_drv_prv.connector_type[i]);
890 if (ret < 0 || (!sunxi_drv_prv.connector_type[i])) {
891 DRM_INFO("WARN:Parse DTS-info connector%d_output_type failed!\n",
892 i);
893 break;
894 }
895
896 sprintf(string, "connector%d_output_mode", i);
897 ret = of_property_read_string(np, string, &mode_name);
898 if (ret < 0) {
899 DRM_ERROR("Parse DTS-info connector%d_output_mode failed!\n",
900 i);
901 break;
902 }
903
904 strcpy(sunxi_drv_prv.connector_mode[i], (char *)mode_name);
905 /*memcpy(sunxi_drv_prv.connector_mode[i], mode_name, 20);
906
907 DRM_INFO("Parse DTS-info:%s result:%s - %c %c %c\n",
908 string, sunxi_drv_prv.connector_mode[i],
909 mode_name[0], mode_name[1], mode_name[2]);*/
910
911 sunxi_drv_prv.connector_num++;
912 }
913
914 DRM_DEBUG_DRIVER("SUNXI DRM DTS INFO:\n");
915 DRM_DEBUG_DRIVER("fb_base:%u\n", sunxi_drv_prv.fb_base);
916 DRM_DEBUG_DRIVER("boot_disp:%d\n", sunxi_drv_prv.boot_disp);
917 DRM_DEBUG_DRIVER("connector_num:%d\n", sunxi_drv_prv.connector_num);
918 for (i = 0; i < sunxi_drv_prv.connector_num; i++) {
919 DRM_DEBUG_DRIVER("connector%d_type:%u\n",
920 i, sunxi_drv_prv.connector_type[i]);
921 DRM_DEBUG_DRIVER("connector%d_mode:%s\n",
922 i, sunxi_drv_prv.connector_mode[i]);
923 }
924
925 return 0;
926 }
927
sunxi_drm_platform_probe(struct platform_device * pdev)928 static int sunxi_drm_platform_probe(struct platform_device *pdev)
929 {
930 int ret;
931 struct device_node *np;
932
933 DRM_INFO("[DRM-DRV]%s start\n", __func__);
934
935 memset(&sunxi_drv_prv, 0, sizeof(struct sunxi_drm_private));
936 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
937 sunxi_drm_driver.num_ioctls = ARRAY_SIZE(sunxi_ioctls);
938 sunxi_drv_prv.pdev = pdev;
939 np = pdev->dev.of_node;
940
941 ret = sunxi_drm_parse_dts(np);
942 if (ret < 0) {
943 DRM_ERROR("sunxi_drm_parse_dts FAILED!\n");
944 goto drm_err;
945 }
946
947 #ifdef CONFIG_DRM_FBDEV_EMULATION
948 /*parse bootlogo bmp file*/
949 if (sunxi_drv_prv.fb_base) {
950 ret = sunxi_drm_parse_bmp_header(&sunxi_drv_prv.bootlogo_bmp_header,
951 sunxi_drv_prv.fb_base);
952 if (ret < 0) {
953 DRM_INFO("parse bmp bootlogo failed, phy_addr:0x%x\n",
954 sunxi_drv_prv.fb_base);
955 goto drm_err;
956 }
957
958 sunxi_drm_get_bootlogoinfo_from_bmp_header(
959 &sunxi_drv_prv.bootlogo,
960 &sunxi_drv_prv.bootlogo_bmp_header,
961 sunxi_drv_prv.fb_base);
962 } else {
963 sunxi_drm_get_bootlogoinfo_from_dts_info(&sunxi_drv_prv.bootlogo,
964 sunxi_drv_prv.boot_fb);
965 }
966 #endif
967
968 ret = sunxi_drm_platform_init(&sunxi_drm_driver, &pdev->dev);
969 if (ret < 0) {
970 DRM_ERROR("sunxi_drm_platform_init\n");
971 goto drm_err;
972 }
973
974 #ifdef CONFIG_DRM_FBDEV_EMULATION
975 /*if (sunxi_drv_prv.bootlogo.phy_addr) {
976 ret = sunxi_drm_fbdev_copy_bootlogo(
977 sunxi_drv_prv.drm_dev, &sunxi_drv_prv.bootlogo);
978 if (ret < 0) {
979 DRM_ERROR("fbdev copy bootlogo failed\n");
980 goto drm_err;
981 }
982 }*/
983 #endif
984
985 if (sunxi_drm_is_need_smooth_boot()) {
986 if (sunxi_drm_smooth_boot(sunxi_drv_prv.drm_dev) < 0) {
987 DRM_ERROR("sunxi_drm smooth booting failed\n");
988 goto drm_err;
989 }
990 }
991
992 DRM_INFO("[DRM-DRV]%s end\n", __func__);
993 return 0;
994
995 drm_err:
996 DRM_INFO("[DRM-DRV]%s failed\n", __func__);
997 return -1;
998 }
999
sunxi_drm_platform_remove(struct platform_device * pdev)1000 static int sunxi_drm_platform_remove(struct platform_device *pdev)
1001 {
1002 DRM_DEBUG_DRIVER("[%d]\n", __LINE__);
1003
1004 drm_put_dev(dev_get_drvdata(&pdev->dev));
1005
1006 return 0;
1007 }
1008
1009 #ifdef CONFIG_PM_RUNTIME
sunxi_runtime_suspend(struct device * dev)1010 static int sunxi_runtime_suspend(struct device *dev)
1011 {
1012 return 0;
1013 }
1014
sunxi_runtime_resume(struct device * dev)1015 static int sunxi_runtime_resume(struct device *dev)
1016 {
1017 return 0;
1018 }
1019
sunxi_runtime_idle(struct device * dev)1020 static int sunxi_runtime_idle(struct device *dev)
1021 {
1022 return 0;
1023 }
1024 #endif
1025
sunxi_drm_suspend(struct device * dev)1026 static int sunxi_drm_suspend(struct device *dev)
1027 {
1028 struct drm_device *device = sunxi_drv_prv.drm_dev;
1029 struct drm_connector *conct = NULL;
1030
1031 if ((dev != device->dev)
1032 || (device == NULL)) {
1033 DRM_ERROR("devices are different or drm_device is NULL\n");
1034 return 0;
1035 }
1036
1037 drm_modeset_lock_all(device);
1038 list_for_each_entry(conct, &device->mode_config.connector_list, head)
1039 conct->funcs->dpms(conct, DRM_MODE_DPMS_OFF);
1040 drm_modeset_unlock_all(device);
1041
1042 return 0;
1043 }
1044
sunxi_drm_resume(struct device * dev)1045 static int sunxi_drm_resume(struct device *dev)
1046 {
1047 struct drm_device *device = sunxi_drv_prv.drm_dev;
1048 struct drm_connector *conct = NULL;
1049
1050 if ((dev != device->dev)
1051 || (device == NULL)) {
1052 DRM_ERROR("devices are different or drm_device is NULL\n");
1053 return 0;
1054 }
1055
1056
1057 drm_modeset_lock_all(device);
1058 list_for_each_entry(conct, &device->mode_config.connector_list, head)
1059 conct->funcs->dpms(conct, DRM_MODE_DPMS_ON);
1060 drm_modeset_unlock_all(device);
1061
1062 return 0;
1063 }
1064
1065
1066 static const struct dev_pm_ops sunxi_drm_runtime_pm_ops = {
1067 #ifdef CONFIG_PM_RUNTIME
1068 .runtime_suspend = sunxi_runtime_suspend,
1069 .runtime_resume = sunxi_runtime_resume,
1070 .runtime_idle = sunxi_runtime_idle,
1071 #endif
1072 .suspend = sunxi_drm_suspend,
1073 .resume = sunxi_drm_resume,
1074 };
1075
1076 static const struct of_device_id sunxi_of_match[] = {
1077 { .compatible = "allwinner,sunxi-drm", },
1078 {},
1079 };
1080 MODULE_DEVICE_TABLE(of, sunxi_of_match);
1081
1082 static struct platform_driver sunxi_drm_platform_driver = {
1083 .probe = sunxi_drm_platform_probe,
1084 .remove = sunxi_drm_platform_remove,
1085 .driver = {
1086 .owner = THIS_MODULE,
1087 .name = "sunxi-drm",
1088 .of_match_table = sunxi_of_match,
1089 .pm = &sunxi_drm_runtime_pm_ops,
1090 },
1091 };
1092
1093
sunxi_drm_drv_init(void)1094 static int __init sunxi_drm_drv_init(void)
1095 {
1096 int ret;
1097
1098 DRM_INFO("[DRM-DRV]%s start\n\n", __func__);
1099 /*register sunxi-de driver*/
1100 ret = sunxi_de_module_init();
1101 if (ret < 0) {
1102 DRM_ERROR("sunxi_de_module_init failed!\n");
1103 goto de_err;
1104 }
1105
1106 /*register sunxi-tcon driver*/
1107 ret = sunxi_tcon_module_init();
1108 if (ret < 0) {
1109 DRM_ERROR("sunxi_tcon_module_init failed!\n");
1110 goto tcon_err;
1111 }
1112 /*register sunxi-lcd driver*/
1113 #ifdef CONFIG_AW_DRM_LCD
1114 ret = sunxi_lcd_module_init();
1115 if (ret < 0) {
1116 sunxi_lcd_module_exit();
1117 DRM_ERROR("sunxi_lcd_module_init failed!\n");
1118 goto drm_err;
1119 }
1120 #endif
1121
1122 #ifdef CONFIG_AW_DRM_TV
1123 ret = sunxi_tv_module_init();
1124 if (ret < 0) {
1125 DRM_ERROR("sunxi_tv_module_init failed!\n");
1126 sunxi_tv_module_exit();
1127 goto drm_err;
1128 }
1129 #endif
1130
1131 #if defined(CONFIG_AW_DRM_HDMI14)
1132 ret = sunxi_hdmi_module_init();
1133 if (ret < 0) {
1134 DRM_ERROR("sunxi_hdmi_module_init failed!\n");
1135 sunxi_hdmi_module_exit();
1136 goto drm_err;
1137 }
1138 #elif defined(CONFIG_AW_DRM_HDMI20)
1139 ret = sunxi_hdmi20_module_init();
1140 if (ret < 0) {
1141 DRM_ERROR("sunxi_hdmi_module_init failed!\n");
1142 sunxi_hdmi20_module_exit();
1143 goto drm_err;
1144 }
1145 #endif
1146
1147 /*register sunxi-drm driver*/
1148 ret = platform_driver_register(&sunxi_drm_platform_driver);
1149 if (ret < 0) {
1150 DRM_ERROR("drm platform_driver_register failed!\n");
1151 goto drm_err;
1152 }
1153
1154 /*if (sunxi_drv_prv.drm_dev) {
1155 if (sunxi_drm_sysfs_init(sunxi_drv_prv.drm_dev) < 0) {
1156 DRM_ERROR("sunxi_drm_sysfs_init failed\n");
1157 goto drm_err;
1158 }
1159 }*/
1160
1161 DRM_INFO("[DRM-DRV]%s end\n\n", __func__);
1162 return 0;
1163
1164 drm_err:
1165 platform_driver_unregister(&sunxi_drm_platform_driver);
1166
1167 tcon_err:
1168 sunxi_tcon_module_exit();
1169 de_err:
1170 sunxi_de_module_exit();
1171 DRM_INFO("[DRM-DRV]%s failed\n", __func__);
1172 return -1;
1173 }
1174
sunxi_drm_drv_exit(void)1175 static void __exit sunxi_drm_drv_exit(void)
1176 {
1177 DRM_INFO("[DRM-DRV]%s start\n", __func__);
1178
1179 //sunxi_drm_sysfs_exit(sunxi_drv_prv.drm_dev);
1180 platform_driver_unregister(&sunxi_drm_platform_driver);
1181 #ifdef CONFIG_AW_DRM_LCD
1182 sunxi_lcd_module_exit();
1183 #endif
1184
1185 #ifdef CONFIG_AW_DRM_TV
1186 sunxi_tv_module_exit();
1187 #endif
1188
1189 #if defined(CONFIG_AW_DRM_HDMI14)
1190 sunxi_hdmi_module_exit();
1191 #elif defined(CONFIG_AW_DRM_HDMI20)
1192 sunxi_hdmi20_module_exit();
1193 #endif
1194 sunxi_tcon_module_exit();
1195 sunxi_de_module_exit();
1196 }
1197
1198 module_init(sunxi_drm_drv_init);
1199 module_exit(sunxi_drm_drv_exit);
1200 MODULE_AUTHOR("zhengwanyu");
1201 MODULE_AUTHOR("hongyaobin");
1202
1203 MODULE_DESCRIPTION("Allwinnertech SoC DRM Driver");
1204 MODULE_LICENSE("GPL");
1205