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 <linux/dma-mapping.h>
12 #include <uapi/drm/drm_fourcc.h>
13 #include <linux/clk.h>
14
15 #include "sunxi_de.h"
16
17 #ifdef CONFIG_AW_DRM_DE_V33X
18 #include "disp_al_de.h"
19 #include "de330/de_rtmx.h"
20 #include "de330/de_enhance.h"
21 #include "de330/de_smbl.h"
22 #include "de330/de_wb.h"
23 #include "de330/de_bld.h"
24 #include "de330/de_ccsc.h"
25
26 #include "tcon/de_lcd.h"
27 #include "tcon/de_dsi.h"
28 #else
29 #include "de_feat.h"
30 #include "de_hal.h"
31 #include "de_clock.h"
32 #include "disp_al.h"
33 #include "de_lcd.h"
34 #include "de_dsi.h"
35 #endif
36
37 #include "sunxi_common.h"
38 #include "sunxi_tcon.h"
39
40 static struct sunxi_de_drv *de_drv;
41
42 #if defined(CONFIG_AW_IOMMU)
43 #define DE_MASTOR_ID 0
44 extern void sunxi_enable_device_iommu(unsigned int mastor_id, bool flag);
45 #endif
46
47 static const unsigned int ui_layer_formats[] = {
48 DRM_FORMAT_RGB888,
49 DRM_FORMAT_BGR888,
50
51 DRM_FORMAT_ARGB8888,
52 DRM_FORMAT_ABGR8888,
53 DRM_FORMAT_RGBA8888,
54 DRM_FORMAT_BGRA8888,
55
56 DRM_FORMAT_XRGB8888,
57 DRM_FORMAT_XBGR8888,
58 DRM_FORMAT_RGBX8888,
59 DRM_FORMAT_BGRX8888,
60
61 DRM_FORMAT_RGB565,
62 DRM_FORMAT_BGR565,
63
64 DRM_FORMAT_ARGB4444,
65 DRM_FORMAT_ABGR4444,
66 DRM_FORMAT_RGBA4444,
67 DRM_FORMAT_BGRA4444,
68
69 DRM_FORMAT_ARGB1555,
70 DRM_FORMAT_ABGR1555,
71 DRM_FORMAT_RGBA5551,
72 DRM_FORMAT_BGRA5551,
73 };
74
75 static const unsigned int vi_layer_formats[] = {
76 DRM_FORMAT_RGB888,
77 DRM_FORMAT_BGR888,
78
79 DRM_FORMAT_ARGB8888,
80 DRM_FORMAT_ABGR8888,
81 DRM_FORMAT_RGBA8888,
82 DRM_FORMAT_BGRA8888,
83
84 DRM_FORMAT_XRGB8888,
85 DRM_FORMAT_XBGR8888,
86 DRM_FORMAT_RGBX8888,
87 DRM_FORMAT_BGRX8888,
88
89 DRM_FORMAT_RGB565,
90 DRM_FORMAT_BGR565,
91
92 DRM_FORMAT_ARGB4444,
93 DRM_FORMAT_ABGR4444,
94 DRM_FORMAT_RGBA4444,
95 DRM_FORMAT_BGRA4444,
96
97 DRM_FORMAT_ARGB1555,
98 DRM_FORMAT_ABGR1555,
99 DRM_FORMAT_RGBA5551,
100 DRM_FORMAT_BGRA5551,
101
102 DRM_FORMAT_AYUV,
103 DRM_FORMAT_YUV444,
104 DRM_FORMAT_YUV422,
105 DRM_FORMAT_YUV420,
106 DRM_FORMAT_YUV411,
107
108 DRM_FORMAT_NV61,
109 DRM_FORMAT_NV16,
110 DRM_FORMAT_NV21,
111 DRM_FORMAT_NV12,
112 };
113
sunxi_de_get_de(int nr)114 static struct sunxi_de *sunxi_de_get_de(int nr)
115 {
116 return &de_drv->hwde[nr];
117 }
118
119 /*get crtc count*/
sunxi_de_get_count(void)120 int sunxi_de_get_count(void)
121 {
122 /* return the DE count */
123 return de_drv->de_cnt;
124 }
125
sunxi_de_get_funcs(int nr)126 struct sunxi_de_funcs *sunxi_de_get_funcs(int nr)
127 {
128 struct sunxi_de *hwde = sunxi_de_get_de(nr);
129
130 return (struct sunxi_de_funcs *)hwde->funcs;
131 }
132
sunxi_de_clk_enable(void)133 static int sunxi_de_clk_enable(void)
134 {
135 int ret;
136
137 ret = clk_prepare_enable(de_drv->mclk);
138 if (ret < 0) {
139 DRM_ERROR("Enable de clk failed\n");
140 return ret;
141 }
142
143 ret = clk_prepare_enable(de_drv->mclk_bus);
144 if (ret < 0) {
145 DRM_ERROR("Enable de bus clk failed\n");
146 return ret;
147 }
148
149 return 0;
150 }
151
sunxi_de_clk_disable(void)152 static void sunxi_de_clk_disable(void)
153 {
154 clk_disable_unprepare(de_drv->mclk);
155 }
156
disp_feat_is_using_rcq(unsigned int disp)157 int disp_feat_is_using_rcq(unsigned int disp)
158 {
159 #if defined(DE_VERSION_V33X)
160 return de_feat_is_using_rcq(disp);
161 #endif
162 return 0;
163 }
164
disp_feat_is_using_wb_rcq(unsigned int wb)165 int disp_feat_is_using_wb_rcq(unsigned int wb)
166 {
167 #if defined(DE_VERSION_V33X)
168 return de_feat_is_using_wb_rcq(wb);
169 #endif
170 return 0;
171 }
172
sunxi_de_get_freq(int nr)173 static unsigned long sunxi_de_get_freq(int nr)
174 {
175 return clk_get_rate(de_drv->mclk);
176 }
177
sunxi_de_get_layer_count(int nr)178 static int sunxi_de_get_layer_count(int nr)
179 {
180 struct sunxi_de *hwde = sunxi_de_get_de(nr);
181
182 return ((hwde->vichannel_cnt * hwde->layers_per_vichannel)
183 + (hwde->uichannel_cnt * hwde->layers_per_uichannel));
184 }
185
sunxi_de_get_vi_layer_count(int nr)186 static int sunxi_de_get_vi_layer_count(int nr)
187 {
188 struct sunxi_de *hwde = sunxi_de_get_de(nr);
189
190 return (hwde->vichannel_cnt * hwde->layers_per_vichannel);
191 }
192
sunxi_de_get_ui_layer_count(int nr)193 static int sunxi_de_get_ui_layer_count(int nr)
194 {
195 struct sunxi_de *hwde = sunxi_de_get_de(nr);
196
197 return (hwde->uichannel_cnt * hwde->layers_per_uichannel);
198 }
199
sunxi_de_layer_is_video(int nr,int layer_id)200 static int sunxi_de_layer_is_video(int nr, int layer_id)
201 {
202 struct sunxi_de *hwde = sunxi_de_get_de(nr);
203
204 if (layer_id >= sunxi_de_get_layer_count(nr)) {
205 DRM_ERROR("layer:%d if is out of range\n", layer_id);
206 return -1;
207 }
208
209 if (layer_id < (hwde->vichannel_cnt * hwde->layers_per_vichannel))
210 return 1;
211 return 0;
212 }
213
sunxi_de_get_layer_channel_id(int nr,int layer_id)214 static int sunxi_de_get_layer_channel_id(int nr, int layer_id)
215 {
216 struct sunxi_de *hwde = sunxi_de_get_de(nr);
217
218 if (sunxi_de_layer_is_video(nr, layer_id))
219 return layer_id / hwde->layers_per_vichannel;
220
221 return hwde->vichannel_cnt +
222 ((layer_id - sunxi_de_get_vi_layer_count(nr)) / hwde->layers_per_uichannel);
223 }
224
sunxi_de_get_layer_id_within_chanel(int nr,int top_layer_id)225 static int sunxi_de_get_layer_id_within_chanel(int nr, int top_layer_id)
226 {
227 struct sunxi_de *hwde = sunxi_de_get_de(nr);
228
229 if (top_layer_id < sunxi_de_get_vi_layer_count(nr))
230 return top_layer_id % hwde->layers_per_vichannel;
231
232 return top_layer_id % hwde->layers_per_uichannel;
233 }
234
sunxi_de_get_layer_formats(int nr,unsigned int layer_id,const unsigned int ** formats,unsigned int * count)235 static int sunxi_de_get_layer_formats(int nr, unsigned int layer_id,
236 const unsigned int **formats,
237 unsigned int *count)
238 {
239 int is_video;
240
241 is_video = sunxi_de_layer_is_video(nr, layer_id);
242 if (is_video < 0) {
243 DRM_ERROR("judge layer_is_video failed\n");
244 return -1;
245 }
246
247 if (is_video) {
248 *formats = vi_layer_formats;
249 *count = ARRAY_SIZE(vi_layer_formats);
250 } else {
251 *formats = ui_layer_formats;
252 *count = ARRAY_SIZE(ui_layer_formats);
253 }
254
255 return 0;
256 }
257
sunxi_de_is_support_tcon(int nr,int tcon_id)258 static bool sunxi_de_is_support_tcon(int nr, int tcon_id)
259 {
260 return true;
261 }
262
sunxi_de_get_attached_tcon_id(int nr)263 static int sunxi_de_get_attached_tcon_id(int nr)
264 {
265 struct sunxi_de *hwde = sunxi_de_get_de(nr);
266
267 if (!hwde->enable) {
268 DRM_ERROR("DE%d is NOT be set to enable\n", hwde->id);
269 return -1;
270 }
271
272 return hwde->info.hwdev_index;
273 }
274
sunxi_de_is_enable(int nr)275 static bool sunxi_de_is_enable(int nr)
276 {
277 struct sunxi_de *hwde = sunxi_de_get_de(nr);
278
279 return hwde->enable;
280 }
281
282 #if defined(CONFIG_AW_DRM_DE_V33X)
sunxi_de_layer_enhance_apply(unsigned int disp,struct disp_layer_config_data * data,unsigned int layer_num)283 static int sunxi_de_layer_enhance_apply(unsigned int disp,
284 struct disp_layer_config_data *data,
285 unsigned int layer_num)
286 {
287 struct disp_enhance_chn_info *ehs_info;
288 struct de_rtmx_context *ctx = de_rtmx_get_context(disp);
289 struct de_chn_info *chn_info = ctx->chn_info;
290 u32 vi_chn_num = de_feat_get_num_vi_chns(disp);
291 u32 i;
292
293 ehs_info = kmalloc(sizeof(struct disp_enhance_chn_info) * vi_chn_num,
294 GFP_KERNEL | __GFP_ZERO);
295 if (ehs_info == NULL) {
296 pr_warn("%s failed to kmalloc!\n", __func__);
297 return -1;
298 }
299 memset((void *)ehs_info, 0, sizeof(struct disp_enhance_chn_info)
300 * vi_chn_num);
301 for (i = 0; i < layer_num; ++i, ++data) {
302 if (data->config.enable
303 && (data->config.channel < vi_chn_num)) {
304 struct disp_enhance_layer_info *ehs_layer_info =
305 &ehs_info[data->config.channel]
306 .layer_info[data->config.layer_id];
307
308 ehs_layer_info->fb_size.width =
309 data->config.info.fb.size[0].width;
310 ehs_layer_info->fb_size.height =
311 data->config.info.fb.size[0].height;
312 ehs_layer_info->fb_crop.x =
313 data->config.info.fb.crop.x >> 32;
314 ehs_layer_info->fb_crop.y =
315 data->config.info.fb.crop.y >> 32;
316 ehs_layer_info->en = 1;
317 ehs_layer_info->format = data->config.info.fb.format;
318 }
319 }
320 for (i = 0; i < vi_chn_num; i++) {
321 ehs_info[i].ovl_size.width = chn_info->ovl_out_win.width;
322 ehs_info[i].ovl_size.height = chn_info->ovl_out_win.height;
323 ehs_info[i].bld_size.width = chn_info->scn_win.width;
324 ehs_info[i].bld_size.height = chn_info->scn_win.height;
325
326 }
327 /* set enhance size */
328 de_enhance_layer_apply(disp, ehs_info);
329 kfree(ehs_info);
330 return 0;
331 }
332
333 #endif
334
sunxi_de_single_layer_apply(int nr,struct disp_layer_config_data * data)335 static int sunxi_de_single_layer_apply(
336 int nr, struct disp_layer_config_data *data)
337 {
338 int ret = 0, layer_id;
339 struct disp_csc_config csc_cfg;
340 struct disp_layer_config_data *data_tmp = NULL;
341 struct sunxi_de *hwde = sunxi_de_get_de(nr);
342
343 csc_cfg.out_fmt =
344 (hwde->info.cs == DISP_CSC_TYPE_RGB) ? DE_RGB : DE_YUV;
345 if ((data->config.info.screen_win.height < 1280)
346 && (data->config.info.screen_win.height < 720))
347 csc_cfg.out_mode = DE_BT601;
348 else
349 csc_cfg.out_mode = DE_BT709;
350 csc_cfg.out_color_range = hwde->info.color_range;
351
352 #if defined(CONFIG_AW_DRM_DE_V33X)
353 #elif defined(CONFIG_AW_DRM_DE_V2X)
354 de_al_mgr_apply_color(nr, &csc_cfg);
355 #elif defined(CONFIG_AW_DRM_DE_SUN50IW1)
356 #else
357 "de_al_mgr_apply_color has NOT been implemented!"
358 #endif
359
360 layer_id = data->config.channel * 4 + data->config.layer_id;
361 data_tmp = &hwde->layer_config_data[layer_id];
362 memcpy(data_tmp, data,
363 sizeof(struct disp_layer_config_data));
364
365 #ifdef CONFIG_AW_DRM_DE_V33X
366 de_rtmx_layer_apply(nr, hwde->layer_config_data,
367 sunxi_de_get_layer_count(nr));
368 sunxi_de_layer_enhance_apply(nr, hwde->layer_config_data,
369 sunxi_de_get_layer_count(nr));
370 #else
371 ret = de_al_lyr_apply(nr, hwde->layer_config_data,
372 sunxi_de_get_layer_count(nr), false);
373 if (ret) {
374 DRM_ERROR("de_al_lyr_apply failed\n");
375 return ret;
376 }
377 #endif
378
379 //de_al_mgr_update_regs(nr);
380
381 hwde->layer_enabled[data->config.channel][data->config.layer_id]
382 = data->config.enable;
383
384 return 0;
385 }
386
sunxi_de_multi_layers_apply(int nr,struct disp_layer_config_data * data,unsigned int layer_num)387 int sunxi_de_multi_layers_apply(int nr, struct disp_layer_config_data *data,
388 unsigned int layer_num)
389 {
390 int i, layer_id, ret;
391 struct disp_csc_config csc_cfg;
392 struct disp_layer_config_data *data_tmp = NULL;
393 struct sunxi_de *hwde = sunxi_de_get_de(nr);
394
395 csc_cfg.out_fmt =
396 (hwde->info.cs == DISP_CSC_TYPE_RGB) ? DE_RGB : DE_YUV;
397 if ((data->config.info.screen_win.height < 1280)
398 && (data->config.info.screen_win.height < 720))
399 csc_cfg.out_mode = DE_BT601;
400 else
401 csc_cfg.out_mode = DE_BT709;
402 csc_cfg.out_color_range = hwde->info.color_range;
403 #if defined(CONFIG_AW_DRM_DE_V33X)
404
405 #elif defined(CONFIG_AW_DRM_DE_V2X)
406 de_al_mgr_apply_color(nr, &csc_cfg);
407 #elif defined(CONFIG_AW_DRM_DE_SUN50IW1)
408 #else
409 "de_al_mgr_apply_color has NOT been implemented!"
410 #endif
411
412 for (i = 0; i < layer_num; i++) {
413 layer_id = data[i].config.channel * 4 + data[i].config.layer_id;
414 data_tmp = &hwde->layer_config_data[layer_id];
415 memcpy(data_tmp, &data[i],
416 sizeof(struct disp_layer_config_data));
417 hwde->layer_enabled[data[i].config.channel][data[i].config.layer_id]
418 = data[i].config.enable;
419 }
420
421 #ifdef CONFIG_AW_DRM_DE_V33X
422 de_rtmx_layer_apply(nr, hwde->layer_config_data,
423 sunxi_de_get_layer_count(nr));
424 sunxi_de_layer_enhance_apply(nr, hwde->layer_config_data,
425 sunxi_de_get_layer_count(nr));
426 #else
427 ret = de_al_lyr_apply(nr, hwde->layer_config_data,
428 sunxi_de_get_layer_count(nr), false);
429 if (ret) {
430 DRM_ERROR("de_al_lyr_apply failed\n");
431 return ret;
432 }
433 #endif
434
435 return 0;
436 }
437
438 /*enhance*/
sunxi_de_enhance_apply(int nr,struct disp_enhance_config * config)439 static int sunxi_de_enhance_apply(int nr,
440 struct disp_enhance_config *config)
441 {
442 #ifndef CONFIG_AW_DRM_DE_V33X
443 struct disp_csc_config csc_config;
444
445 if (config->flags & ENH_MODE_DIRTY) {
446 de_dcsc_get_config(nr, &csc_config);
447 csc_config.enhance_mode = (config->info.mode >> 16) & 0xffff;
448 de_dcsc_apply(nr, &csc_config);
449 }
450 #endif
451
452 return de_enhance_apply(nr, config);
453 }
454
sunxi_de_enhance_sync(int nr)455 static void sunxi_de_enhance_sync(int nr)
456 {
457 //struct sunxi_de *hwde = sunxi_de_get_de(nr);
458
459 de_enhance_update_regs(nr);
460 de_enhance_sync(nr);
461 de_enhance_tasklet(nr);
462 }
463
sunxi_de_smbl_sync(int nr)464 static void sunxi_de_smbl_sync(int nr)
465 {
466 de_smbl_update_regs(nr);
467 de_smbl_tasklet(nr);
468 }
469
470
sunxi_de_enable(int nr,struct disp_manager_data * data)471 static int sunxi_de_enable(int nr, struct disp_manager_data *data)
472 {
473 int ret = 0;
474 struct sunxi_de *hwde = sunxi_de_get_de(nr);
475
476 if (hwde->enable) {
477 DRM_INFO("[SUNXI-DE]WARN:sunxi has been enable,"
478 "do NOT enable it again\n");
479 return 0;
480 }
481
482 hwde->enable = true;
483 memcpy(&hwde->info, &data->config,
484 sizeof(struct disp_manager_info));
485 #ifdef CONFIG_AW_DRM_DE_V33X
486 de_rtmx_start(nr);
487 de_rtmx_mgr_apply(nr, data);
488 de_rtmx_update_reg_ahb(nr);
489 #else
490
491 sunxi_de_clk_enable();
492 de_clk_enable(DE_CLK_CORE0 + nr);
493
494 #ifndef CONFIG_AW_DRM_DE_SUN50IW1
495 de_update_clk_rate(data->config.de_freq);
496 #endif
497 de_update_device_fps(nr, data->config.device_fps);
498
499 ret = de_al_mgr_apply(nr, data);
500 if (ret) {
501 DRM_ERROR("de_al_mgr_apply failed\n");
502 return ret;
503 }
504
505 de_al_mgr_update_regs(nr);
506
507 #if IS_ENABLED(CONFIG_AW_IOMMU)
508 sunxi_enable_device_iommu(DE_MASTOR_ID, true);
509 #endif
510 /*de_rtmx_set_dbuff_rdy(nr);*/
511 #endif
512
513 /*enhance*/
514 ret = sunxi_de_enhance_apply(nr,
515 &hwde->enhance_config);
516 if (ret) {
517 DRM_ERROR("sunxi_de_enhance_apply failed\n");
518 return ret;
519 }
520
521 /*smbl*/
522 ret = de_smbl_apply(nr, &hwde->smbl_info);
523 if (ret) {
524 DRM_ERROR("de_smbl_apply failed\n");
525 return ret;
526 }
527
528 return 0;
529 }
530
531 /*int sunxi_de_sw_enable(int nr)
532 {
533 struct sunxi_de *hwde = sunxi_de_get_de(nr);
534
535 hwde->is_assigned = true;
536 sunxi_de_clk_enable();
537 return 0;
538 }*/
539
sunxi_de_disable(int nr,struct disp_manager_data * data)540 static void sunxi_de_disable(int nr, struct disp_manager_data *data)
541 {
542 int ret = 0;
543 struct sunxi_de *hwde = sunxi_de_get_de(nr);
544
545 if (!hwde->enable) {
546 DRM_INFO("[SUNXI-DE]WARN:sunxi has NOT been enable,"
547 "can NOT enable it\n");
548 return;
549 }
550
551 hwde->enable = false;
552 memcpy(&hwde->info, &data->config,
553 sizeof(struct disp_manager_info));
554 #ifdef CONFIG_AW_DRM_DE_V33X
555 de_rtmx_stop(nr);
556 #else
557 ret = de_al_mgr_apply(nr, data);
558 if (ret) {
559 DRM_ERROR("de_al_mgr_apply failed\n");
560 return;
561 }
562
563 de_al_mgr_update_regs(nr);
564 de_rtmx_set_dbuff_rdy(nr);
565 #if !defined(CONFIG_AW_DRM_DE_V33X)
566 de_clk_disable(DE_CLK_CORE0 + nr);
567 #endif
568
569 sunxi_de_clk_disable();
570 #endif
571 return;
572 }
573
574
sunxi_de_is_use_irq(int nr)575 static bool sunxi_de_is_use_irq(int nr)
576 {
577 return false;
578 }
579
sunxi_de_get_irq_no(int nr)580 static unsigned int sunxi_de_get_irq_no(int nr)
581 {
582 return 0;
583 }
584
sunxi_de_query_irq(int nr)585 static int sunxi_de_query_irq(int nr)
586 {
587 int tcon_id, irq_query;
588
589 tcon_id = sunxi_de_get_attached_tcon_id(nr);
590 if (tcon_id < 0) {
591 DRM_ERROR("DE%d has No atteched tcon\n", nr);
592 return -1;
593 }
594
595 irq_query = sunxi_tcon_query_irq(tcon_id);
596 if (!irq_query) {
597 DRM_ERROR("irq_query result: No IRQ\n");
598 return -1;
599 }
600
601 return 0;
602 }
603
604
605 /*
606 * The main task during de vsync is to update de registers and make it effective
607 */
sunxi_de_event_proc(int nr,bool update)608 static int sunxi_de_event_proc(int nr, bool update)
609 {
610 int tcon_id;
611 //struct sunxi_de *hwde = sunxi_de_get_de(nr);
612
613 if (!update)
614 return 0;
615
616 #if defined(CONFIG_AW_DRM_DE_V33X)
617 de_rtmx_update_reg_ahb(nr);
618 #else
619 tcon_id = sunxi_de_get_attached_tcon_id(nr);
620 if (tcon_id < 0) {
621 DRM_ERROR("DE%d has No atteched tcon\n", nr);
622 return -1;
623 }
624
625 if (!sunxi_tcon_sync_time_is_enough(tcon_id)) {
626 de_al_mgr_update_regs(nr);
627 DRM_INFO("WARNING: NO enough time left to sync reg\n");
628 return -1;
629 }
630
631 de_rtmx_set_dbuff_rdy(nr);
632 de_al_mgr_update_regs(nr);
633 #endif
634
635 /*enhance*/
636 sunxi_de_enhance_sync(nr);
637
638 /*smbl*/
639 sunxi_de_smbl_sync(nr);
640
641 return 0;
642 }
643
sunxi_updata_crtc_freq(unsigned long rate)644 void sunxi_updata_crtc_freq(unsigned long rate)
645 {
646 #ifdef CONFIG_AW_DRM_DE_V2X
647 de_update_clk_rate(rate);
648 #endif
649 #ifdef CONFIG_AW_DRM_DE_SUN50IW1
650 de_update_de_frequency(rate);
651 #endif
652 }
653
654 /*enhance*/
sunxi_de_set_enhance(int nr,int mode,bool enable,int width,int height,int conn_type)655 static int sunxi_de_set_enhance(int nr,
656 int mode, bool enable, int width, int height, int conn_type)
657 {
658 struct sunxi_de *hwde = sunxi_de_get_de(nr);
659 struct disp_enhance_config *config = &hwde->enhance_config;
660
661 if (!enable) {
662 config->info.enable = 0;
663 config->flags |= ENH_ENABLE_DIRTY;
664 goto out;
665 }
666
667 config->info.mode =
668 (config->info.mode & 0xffff) | (mode << 16);
669 config->flags |= ENH_MODE_DIRTY;
670
671 if (!width || !height) {
672 DRM_ERROR("invalid crtc size, width:%d height:%d\n",
673 width, height);
674 return -1;
675 }
676
677 config->info.size.width = width;
678 config->info.size.height = height;
679 config->flags |= ENH_SIZE_DIRTY;
680
681 if (conn_type == DISP_OUTPUT_TYPE_HDMI)
682 config->info.mode = (config->info.mode & 0xffff0000) | 1;
683 else
684 config->info.mode = (config->info.mode & 0xffff0000) | 0;
685
686 config->info.enable = 1;
687 config->flags |= ENH_ENABLE_DIRTY;
688
689 out:
690 return sunxi_de_enhance_apply(nr, config);
691
692 }
693
sunxi_de_get_enhance(int nr,int * mode,bool * enable,int * width,int * height)694 static void sunxi_de_get_enhance(int nr,
695 int *mode, bool *enable, int *width, int *height)
696 {
697 struct sunxi_de *hwde = sunxi_de_get_de(nr);
698 struct disp_enhance_config *config = &hwde->enhance_config;
699
700 if (mode)
701 *mode = config->info.mode;
702 if (enable)
703 *enable = config->info.enable;
704 if (width)
705 *width = config->info.size.width;
706 if (height)
707 *height = config->info.size.height;
708 }
709
710 /*smbl*/
sunxi_de_is_support_smbl(int nr)711 static bool sunxi_de_is_support_smbl(int nr)
712 {
713 bool ret;
714
715 ret = de_feat_is_support_smbl(nr) ? true : false;
716
717 return ret;
718 }
719
sunxi_de_set_smbl(int nr,bool enable,struct disp_rect * rect)720 static int sunxi_de_set_smbl(int nr, bool enable,
721 struct disp_rect *rect)
722 {
723 struct sunxi_de *hwde = sunxi_de_get_de(nr);
724 struct disp_smbl_info *info = &hwde->smbl_info;
725
726 memcpy(&info->window, rect, sizeof(struct disp_rect));
727 info->flags |= SMBL_DIRTY_WINDOW;
728
729 info->enable = enable;
730 info->flags |= SMBL_DIRTY_ENABLE;
731
732 return de_smbl_apply(nr, info);
733 }
734
sunxi_de_get_smbl(int nr,bool * enable,struct disp_rect * rect)735 static void sunxi_de_get_smbl(int nr, bool *enable,
736 struct disp_rect *rect)
737 {
738 struct sunxi_de *hwde = sunxi_de_get_de(nr);
739 struct disp_smbl_info *info = &hwde->smbl_info;
740
741 if (rect)
742 memcpy(rect, &info->window, sizeof(struct disp_rect));
743
744 if (enable)
745 *enable = info->enable;
746 }
747
748 static const struct sunxi_de_funcs de_funcs = {
749 .is_support_tcon = sunxi_de_is_support_tcon,
750 .get_freq = sunxi_de_get_freq,
751
752 .get_layer_count = sunxi_de_get_layer_count,
753 .get_vi_layer_count = sunxi_de_get_vi_layer_count,
754 .get_ui_layer_count = sunxi_de_get_ui_layer_count,
755 .get_layer_channel_id = sunxi_de_get_layer_channel_id,
756 .get_layer_id_within_chanel = sunxi_de_get_layer_id_within_chanel,
757 .get_layer_formats = sunxi_de_get_layer_formats,
758 .single_layer_apply = sunxi_de_single_layer_apply,
759 .multi_layers_apply = sunxi_de_multi_layers_apply,
760
761 .is_enable = sunxi_de_is_enable,
762 .enable = sunxi_de_enable,
763 .disable = sunxi_de_disable,
764
765 .is_use_irq = sunxi_de_is_use_irq,
766 .get_irq_no = sunxi_de_get_irq_no,
767 .query_irq = sunxi_de_query_irq,
768 .event_proc = sunxi_de_event_proc,
769
770 /*enhance*/
771 .set_enhance = sunxi_de_set_enhance,
772 .get_enhance = sunxi_de_get_enhance,
773
774 /*smbl*/
775 .is_support_smbl = sunxi_de_is_support_smbl,
776 .set_smbl = sunxi_de_set_smbl,
777 .get_smbl = sunxi_de_get_smbl,
778 };
779
sunxi_de_reg_dump(char * buf,unsigned int start,unsigned int end)780 static ssize_t sunxi_de_reg_dump(char *buf, unsigned int start,
781 unsigned int end)
782 {
783 ssize_t n = 0;
784 unsigned int *reg, i;
785
786 for (i = start; i <= end; i += 4) {
787 /*print address info*/
788 if (i == start)
789 n += sprintf(buf + n, "0x%06x:", i);
790 if ((i % 16 == 0) && (i != start)) {
791 n += sprintf(buf + n, "%s", "\n");
792 n += sprintf(buf + n, "0x%06x:", i);
793 }
794
795 /*print reg value*/
796 reg = (unsigned int *)(de_drv->reg_base + i);
797 n += sprintf(buf + n, "0x%08x ", *reg);
798 }
799
800 n += sprintf(buf + n, "\n");
801
802 return n;
803 }
804
805
806 /**print sunxi-de info*/
de_info_show(struct device * dev,struct device_attribute * attr,char * buf)807 static ssize_t de_info_show(struct device *dev,
808 struct device_attribute *attr, char *buf)
809 {
810 ssize_t i, n = 0;
811 struct sunxi_de *hwde;
812
813 n += sprintf(buf + n, "%s\n", "sunxi-de info:");
814 n += sprintf(buf + n, "virt_reg_base: 0x%lx\n", de_drv->reg_base);
815 n += sprintf(buf + n, "de count: %u\n", de_drv->de_cnt);
816 n += sprintf(buf + n, "clk_name:%s clk_rate: %lu enable count:%d\n\n",
817 __clk_get_name(de_drv->mclk),
818 clk_get_rate(de_drv->mclk),
819 __clk_get_enable_count(de_drv->mclk));
820
821 for (i = 0; i < de_drv->de_cnt; i++) {
822 hwde = &de_drv->hwde[i];
823 n += sprintf(buf + n, "id: %d\n", hwde->id);
824 n += sprintf(buf + n, "vi channel count: %u\n",
825 hwde->vichannel_cnt);
826 n += sprintf(buf + n, "ui channel count: %u\n",
827 hwde->uichannel_cnt);
828 n += sprintf(buf + n, "vi layers per channel: %u\n",
829 hwde->layers_per_vichannel);
830 n += sprintf(buf + n, "ui layers per channel: %u\n",
831 hwde->layers_per_uichannel);
832 if (!hwde->irq_used) {
833 n += sprintf(buf + n, "%s\n", "de irq is NOT used");
834 } else {
835 n += sprintf(buf + n, "%s\n", "de irq is used");
836 n += sprintf(buf + n, "irq no: %u\n", hwde->irq_no);
837 n += sprintf(buf + n, "irq enable: %d\n",
838 hwde->irq_enable);
839 }
840
841 if (hwde->enable)
842 n += sprintf(buf + n, "%s\n", "Has been enable");
843 else
844 n += sprintf(buf + n, "%s\n", "Has NOT been enable");
845 n += sprintf(buf + n, "%s", "\n");
846 }
847
848 return n;
849 }
850
de_info_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)851 static ssize_t de_info_store(struct device *dev,
852 struct device_attribute *attr,
853 const char *buf, size_t count)
854 {
855 return count;
856 }
857
858 static DEVICE_ATTR(info, 0660, de_info_show, de_info_store);
859
de_top_reg_show(struct device * dev,struct device_attribute * attr,char * buf)860 static ssize_t de_top_reg_show(struct device *dev,
861 struct device_attribute *attr, char *buf)
862 {
863 ssize_t n = 0;
864
865 if (!__clk_is_enabled(de_drv->mclk)) {
866 n += sprintf(buf + n, "%s\n",
867 "ERROR:de clk is NOT enabled, can NOT dump reg");
868 return n;
869 }
870
871 n += sprintf(buf + n, "TOP DE reg:\n");
872 n += sunxi_de_reg_dump(n + buf, 0, 0x1c);
873 return n;
874 }
875
de_top_reg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)876 static ssize_t de_top_reg_store(struct device *dev,
877 struct device_attribute *attr,
878 const char *buf, size_t count)
879 {
880 return count;
881 }
882
883 static DEVICE_ATTR(top_reg, 0660, de_top_reg_show, de_top_reg_store);
884
de_rtmx_reg_show(struct device * dev,struct device_attribute * attr,char * buf)885 static ssize_t de_rtmx_reg_show(struct device *dev,
886 struct device_attribute *attr, char *buf)
887 {
888 ssize_t n = 0;
889 int i, j;
890 bool vi_en = 0, ui_en = 0;
891 unsigned int start_addr, end_addr;
892 struct sunxi_de *hwde = &de_drv->hwde[0];
893
894 n += sprintf(buf + n, "RT-Mix0-glb reg:\n");
895 n += sunxi_de_reg_dump(n + buf, 0x100000, 0x10000c);
896
897 n += sprintf(buf + n, "RT-Mix0-bld reg:\n");
898 start_addr = 0x101000;
899 end_addr = start_addr + 0xfc;
900 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
901
902 n += sprintf(buf + n, "vichannel status:\n");
903 for (i = 0; i < hwde->vichannel_cnt; i++) {
904 vi_en = 0;
905 for (j = 0; j < hwde->layers_per_vichannel; j++) {
906 if (!hwde->layer_enabled[i][j]) {
907 n += sprintf(buf + n, "CH%d-LAYER%d NOT enabled\n", i, j);
908 continue;
909 }
910 n += sprintf(buf + n, "CH%d-LAYER%d IS enabled\n", i, j);
911
912 n += sprintf(buf + n, "CH%d-LAYER%d reg:\n", i, j);
913 n += sprintf(buf + n, "VI General control reg:\n");
914 start_addr = 0x102000 + (i * 0x1000) + j * 0x30;
915 end_addr = start_addr + 0x2c;
916 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
917 n += sprintf(buf + n, "%s", "\n");
918
919 n += sprintf(buf + n, "VI fill color reg:\n");
920 start_addr = 0x102000 + (i * 0x1000) + j * 0x4;
921 end_addr = start_addr + 0;
922 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
923 n += sprintf(buf + n, "%s", "\n");
924 vi_en = 1;
925 }
926
927 /*No layer in this channel is enabled*/
928 if (!vi_en)
929 continue;
930
931 n += sprintf(buf + n, "VI TOP reg:\n");
932 start_addr = 0x102000 + (i * 0x1000) + 0xd0;
933 end_addr = 0x102000 + (i * 0x1000) + 0xfc;
934 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
935 n += sprintf(buf + n, "%s", "\n\n");
936 }
937
938 n += sprintf(buf + n, "uichannel status:\n");
939 for (i = 0; i < hwde->uichannel_cnt; i++) {
940 ui_en = 0;
941 for (j = 0; j < hwde->layers_per_uichannel; j++) {
942 if (!hwde->layer_enabled[i + hwde->vichannel_cnt][j]) {
943 n += sprintf(buf + n, "CH%d-LAYER%d NOT enabled\n",
944 i + hwde->vichannel_cnt, j);
945 continue;
946 }
947 n += sprintf(buf + n, "CH%d-LAYER%d reg:\n",
948 i + hwde->vichannel_cnt, j);
949 n += sprintf(buf + n, "UI General control reg:\n");
950 start_addr = 0x102000 + (0x1000 * hwde->vichannel_cnt)
951 + (i * 0x1000) + j * 0x20;
952 end_addr = start_addr + 0x18;
953 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
954 n += sprintf(buf + n, "%s", "\n");
955 ui_en = 1;
956 }
957
958 /*No layer in this channel is enabled*/
959 if (!ui_en)
960 continue;
961
962 n += sprintf(buf + n, "CH%d UI TOP reg:\n", i + hwde->vichannel_cnt);
963 start_addr = 0x102000 + (0x1000 * hwde->vichannel_cnt)
964 + (i * 0x1000) + 0x80;
965 end_addr = 0x102000 + (0x1000 * hwde->vichannel_cnt)
966 + (i * 0x1000) + 0x88;
967 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
968 n += sprintf(buf + n, "%s", "\n\n");
969 }
970
971 n += sprintf(buf + n, "%s", "\n");
972 return n;
973 }
974
de_rtmx_reg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)975 static ssize_t de_rtmx_reg_store(struct device *dev,
976 struct device_attribute *attr,
977 const char *buf, size_t count)
978 {
979 return count;
980 }
981
982 static DEVICE_ATTR(rtmx_reg, 0660, de_rtmx_reg_show, de_rtmx_reg_store);
983
984
de_vsu_reg_show(struct device * dev,struct device_attribute * attr,char * buf)985 static ssize_t de_vsu_reg_show(struct device *dev,
986 struct device_attribute *attr, char *buf)
987 {
988 ssize_t n = 0;
989 int i, j, vi_chn_cnt;
990 unsigned int start_addr, end_addr;
991 struct sunxi_de *hwde = &de_drv->hwde[0];
992
993 if (!__clk_is_enabled(de_drv->mclk)) {
994 n += sprintf(buf + n, "%s\n",
995 "ERROR:de clk is NOT enabled, can NOT dump reg");
996 return n;
997 }
998
999 vi_chn_cnt = hwde->vichannel_cnt;
1000 for (i = 0; i < vi_chn_cnt; i++) {
1001 for (j = 0; j < hwde->layers_per_vichannel; j++) {
1002 if (hwde->layer_enabled[i][j])
1003 break;
1004 }
1005
1006 if (j >= hwde->layers_per_vichannel) {
1007 n += sprintf(buf + n, "Video CH%d is NOT enabled\n", i);
1008 continue;
1009 }
1010
1011 n += sprintf(buf + n, "CH%d VSU reg:\n", i);
1012 start_addr = 0x00100000 + ((i + 1) * 0x20000);
1013 end_addr = start_addr + 0xdc;
1014 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1015 }
1016
1017 return n;
1018 }
1019
de_vsu_reg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1020 static ssize_t de_vsu_reg_store(struct device *dev,
1021 struct device_attribute *attr,
1022 const char *buf, size_t count)
1023 {
1024 return count;
1025 }
1026
1027 static DEVICE_ATTR(vsu_reg, 0660, de_vsu_reg_show, de_vsu_reg_store);
1028
de_gsu_reg_show(struct device * dev,struct device_attribute * attr,char * buf)1029 static ssize_t de_gsu_reg_show(struct device *dev,
1030 struct device_attribute *attr, char *buf)
1031 {
1032 ssize_t n = 0;
1033 int i, j, vi_chn_cnt, ui_chn_cnt;
1034 unsigned int start_addr, end_addr;
1035 struct sunxi_de *hwde = &de_drv->hwde[0];
1036
1037 if (!__clk_is_enabled(de_drv->mclk)) {
1038 n += sprintf(buf + n, "%s\n",
1039 "ERROR:de clk is NOT enabled, can NOT dump reg");
1040 return n;
1041 }
1042
1043 vi_chn_cnt = hwde->vichannel_cnt;
1044 ui_chn_cnt = hwde->uichannel_cnt;
1045 for (i = 0; i < ui_chn_cnt; i++) {
1046 for (j = 0; j < hwde->layers_per_uichannel; j++) {
1047 if (hwde->layer_enabled[i + vi_chn_cnt][j])
1048 break;
1049 }
1050
1051 if (j >= hwde->layers_per_uichannel) {
1052 n += sprintf(buf + n, "UI CHANNEL, CH%d is NOT enabled\n",
1053 i + vi_chn_cnt);
1054 continue;
1055 }
1056
1057 n += sprintf(buf + n, "CH%d GSU reg:\n", i + vi_chn_cnt);
1058 start_addr = 0x00100000 + (vi_chn_cnt * 0x20000) + (i * 0x10000);
1059 end_addr = start_addr + 0x9c;
1060 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1061 }
1062
1063 return n;
1064 }
1065
de_gsu_reg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1066 static ssize_t de_gsu_reg_store(struct device *dev,
1067 struct device_attribute *attr,
1068 const char *buf, size_t count)
1069 {
1070 return count;
1071 }
1072
1073 static DEVICE_ATTR(gsu_reg, 0660, de_gsu_reg_show, de_gsu_reg_store);
1074
1075
1076 /*enhance is belongs to POST-PROCESS1,
1077 * Only use in video chanel
1078 */
de_enhance_reg_show(struct device * dev,struct device_attribute * attr,char * buf)1079 static ssize_t de_enhance_reg_show(struct device *dev,
1080 struct device_attribute *attr, char *buf)
1081 {
1082 ssize_t n = 0;
1083 unsigned int start_addr, end_addr;
1084
1085 if (!__clk_is_enabled(de_drv->mclk)) {
1086 n += sprintf(buf + n, "%s\n",
1087 "ERROR:de clk is NOT enabled, can NOT dump reg");
1088 return n;
1089 }
1090
1091 n += sprintf(buf + n, "FCE reg:\n");
1092 start_addr = 0x00100000 + 0xa0000;
1093 end_addr = start_addr + 0x40;
1094 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1095
1096 n += sprintf(buf + n, "LTI reg:\n");
1097 start_addr = 0x00100000 + 0xa4000;
1098 end_addr = start_addr + 0xcc;
1099 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1100
1101 n += sprintf(buf + n, "PEAK reg:\n");
1102 start_addr = 0x00100000 + 0xa6000;
1103 end_addr = start_addr + 0xcc;
1104 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1105
1106 n += sprintf(buf + n, "ASE reg:\n");
1107 start_addr = 0x00100000 + 0xa8000;
1108 end_addr = start_addr + 0x10;
1109 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1110
1111 n += sprintf(buf + n, "FCC reg:\n");
1112 start_addr = 0x00100000 + 0xaa000;
1113 end_addr = start_addr + 0x90;
1114 n += sunxi_de_reg_dump(n + buf, start_addr, end_addr);
1115
1116 return n;
1117 }
1118
de_enhance_reg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1119 static ssize_t de_enhance_reg_store(struct device *dev,
1120 struct device_attribute *attr,
1121 const char *buf, size_t count)
1122 {
1123 return count;
1124 }
1125
1126 static DEVICE_ATTR(enhance_reg, 0660, de_enhance_reg_show, de_enhance_reg_store);
1127
sunxi_disp_hal_debug_show(struct device * device,struct device_attribute * attr,char * buf)1128 static ssize_t sunxi_disp_hal_debug_show(struct device *device,
1129 struct device_attribute *attr,
1130 char *buf)
1131 {
1132 ssize_t n = 0;
1133 #if !defined(CONFIG_AW_DRM_DE_V33X)
1134 /*n += sprintf(buf + n, "hal_debug_level=%d\n",
1135 de_get_hal_debug_level());*/
1136 #endif
1137 return n;
1138 }
1139
sunxi_disp_hal_debug_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1140 static ssize_t sunxi_disp_hal_debug_store(struct device *device,
1141 struct device_attribute *attr,
1142 const char *buf, size_t count)
1143 {
1144 unsigned int level;
1145
1146 if (kstrtoul(buf, 0, (unsigned long *)&level) < 0) {
1147 DRM_ERROR("ERROR input\n");
1148 return 0;
1149 }
1150 #if !defined(CONFIG_AW_DRM_DE_V33X)
1151 /*de_set_hal_debug_level(level);*/
1152 #endif
1153 return count;
1154 }
1155
1156 static DEVICE_ATTR(disp_hal_debug, 0660,
1157 sunxi_disp_hal_debug_show, sunxi_disp_hal_debug_store);
1158
sunxi_disp_debug_show(struct device * device,struct device_attribute * attr,char * buf)1159 static ssize_t sunxi_disp_debug_show(struct device *device,
1160 struct device_attribute *attr,
1161 char *buf)
1162 {
1163 ssize_t n = 0;
1164
1165 n += sprintf(buf + n, "disp_debug=%d\n",
1166 bsp_disp_get_print_level());
1167
1168 return n;
1169 }
1170
sunxi_disp_debug_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1171 static ssize_t sunxi_disp_debug_store(struct device *device,
1172 struct device_attribute *attr,
1173 const char *buf, size_t count)
1174 {
1175 unsigned int debug;
1176
1177 if (kstrtoul(buf, 0, (unsigned long *)&debug) < 0) {
1178 DRM_ERROR("ERROR input\n");
1179 return 0;
1180 }
1181
1182 bsp_disp_set_print_level(debug);
1183
1184 return count;
1185 }
1186
1187 static DEVICE_ATTR(disp_debug, 0660, sunxi_disp_debug_show, sunxi_disp_debug_store);
1188
1189 static struct attribute *de_attributes[] = {
1190 &dev_attr_info.attr,
1191 &dev_attr_top_reg.attr,
1192 &dev_attr_rtmx_reg.attr,
1193 &dev_attr_vsu_reg.attr,
1194 &dev_attr_gsu_reg.attr,
1195 &dev_attr_enhance_reg.attr,
1196 &dev_attr_disp_debug.attr,
1197 &dev_attr_disp_hal_debug.attr,
1198 NULL
1199 };
1200
1201 static struct attribute_group de_attribute_group = {
1202 .name = "attr",
1203 .attrs = de_attributes,
1204 };
1205
1206
1207 #if defined(CONFIG_AW_DRM_DE_V33X)
sunxi_de_v33x_al_init(struct disp_bsp_init_para * para)1208 static int sunxi_de_v33x_al_init(struct disp_bsp_init_para *para)
1209 {
1210 if (de_top_mem_pool_alloc())
1211 return -1;
1212
1213 de_enhance_init(para);
1214 de_smbl_init(para->reg_base[DISP_MOD_DE]);
1215 de_rtmx_init(para);
1216 de_wb_init(para);
1217
1218 return 0;
1219 }
1220 #elif defined(CONFIG_AW_DRM_DE_V33X)
sunxi_de_v3x_al_init(struct disp_bsp_init_para * para)1221 static int sunxi_de_v3x_al_init(struct disp_bsp_init_para *para)
1222 {
1223 return 0;
1224 }
1225 #elif defined(CONFIG_AW_DRM_DE_V2X)
sunxi_de_v2x_al_init(struct disp_bsp_init_para * para)1226 static int sunxi_de_v2x_al_init(struct disp_bsp_init_para *para)
1227 {
1228 int i;
1229 de_al_init(para);
1230
1231 de_enhance_init(para);
1232 de_ccsc_init(para);
1233 de_dcsc_init(para);
1234
1235 #ifndef CONFIG_EINK_PANEL_USED
1236 wb_ebios_init(para);
1237 #endif
1238 de_clk_set_reg_base(para->reg_base[DISP_MOD_DE]);
1239 for (i = 0; i < DE_NUM; i++) {
1240 if (de_feat_is_support_smbl(i))
1241 de_smbl_init(i, para->reg_base[DISP_MOD_DE]);
1242 }
1243
1244 return 0;
1245 }
1246 #elif defined(CONFIG_AW_DRM_DE_SUN50IW1)
sunxi_de_sun50iw1_al_init(struct disp_bsp_init_para * para)1247 static int sunxi_de_sun50iw1_al_init(struct disp_bsp_init_para *para)
1248 {
1249 int i;
1250 de_al_init(para);
1251
1252 de_enhance_init(para);
1253 de_ccsc_init(para);
1254 de_dcsc_init(para);
1255 WB_EBIOS_Init(para);
1256
1257 de_clk_set_reg_base(para->reg_base[DISP_MOD_DE]);
1258 for (i = 0; i < DE_NUM; i++) {
1259 if (de_feat_is_support_smbl(i))
1260 de_smbl_init(i, para->reg_base[DISP_MOD_DE]);
1261 }
1262
1263 return 0;
1264 }
1265 #else
1266 "compile error!"
1267 #endif
1268
1269 #if defined(CONFIG_AW_DRM_DE_V33X)
1270 static int sunxi_de_v33x_al_exit(void)
1271 {
1272 return disp_exit_al();
1273 }
1274 #elif defined(CONFIG_AW_DRM_DE_V33X)
1275 static int sunxi_de_v3x_al_exit(void)
1276 {
1277 return 0;
1278 }
1279 #elif defined(CONFIG_AW_DRM_DE_V2X)
1280 static int sunxi_de_v2x_al_exit(void)
1281 {
1282 de_al_exit();
1283
1284 de_enhance_exit();
1285 de_ccsc_exit();
1286 de_dcsc_exit();
1287
1288 wb_ebios_exit();
1289
1290 for (i = 0; i < DE_NUM; i++) {
1291 #if defined(SUPPORT_SMBL)
1292 if (de_feat_is_support_smbl(i))
1293 de_smbl_exit(i);
1294 #endif
1295 kfree(de_drv->hwde[i].layer_config_data);
1296 }
1297 return 0;
1298 }
1299 #elif defined(CONFIG_AW_DRM_DE_SUN50IW1)
1300 static int sunxi_de_sun50iw1_al_exit(void)
1301 {
1302 return 0;
1303 }
1304 #else
1305 "compile error!"
1306 #endif
1307
1308
sunxi_de_init_al(void)1309 static int sunxi_de_init_al(void)
1310 {
1311 struct disp_bsp_init_para *para;
1312
1313 para = sunxi_disp_get_bsp_init_para();
1314 if (!para) {
1315 DRM_ERROR("[sunxi-de] sunxi_disp_get_bsp_init_para failed\n");
1316 return -1;
1317 }
1318
1319 para->reg_base[DISP_MOD_DE] = de_drv->reg_base;
1320 para->mclk[DISP_MOD_DE] = de_drv->mclk;
1321
1322 #if defined(CONFIG_AW_DRM_DE_V33X)
1323 return sunxi_de_v33x_al_init(para);
1324 #elif defined(CONFIG_AW_DRM_DE_V33X)
1325 return sunxi_de_v3x_al_init(para);
1326 #elif defined(CONFIG_AW_DRM_DE_V2X)
1327 return sunxi_de_v2x_al_init(para);
1328 #elif defined(CONFIG_AW_DRM_DE_SUN50IW1)
1329 return sunxi_de_sun50iw1_al_init(para);
1330 #else
1331 "ERROR Compile!"
1332 #endif
1333 return 0;
1334 }
1335
1336 /*parse de dts info: reg_base/clk*/
sunxi_de_parse_dts(struct platform_device * pdev)1337 static int sunxi_de_parse_dts(struct platform_device *pdev)
1338 {
1339 struct device_node *node;
1340
1341 node = pdev->dev.of_node;
1342 if (!node) {
1343 DRM_ERROR("get sunxi-de node err.\n ");
1344 return -EINVAL;
1345 }
1346
1347 /*parse de reg_base*/
1348 de_drv->reg_base = (uintptr_t __force)of_iomap(node, 0);
1349 if (!de_drv->reg_base) {
1350 DRM_ERROR("unable to map de registers\n");
1351 return -EINVAL;
1352 }
1353 DRM_DEBUG_DRIVER("[SUNXI-DE]get de reg_base:0x%lx\n", de_drv->reg_base);
1354
1355 /*get clk of de*/
1356 de_drv->mclk = devm_clk_get(&pdev->dev, "clk_de0");
1357 if (IS_ERR(de_drv->mclk)) {
1358 DRM_ERROR("fail to get clk for de\n");
1359 return -EINVAL;
1360 }
1361
1362 de_drv->mclk_bus = devm_clk_get(&pdev->dev, "clk_bus_de0");
1363 if (IS_ERR(de_drv->mclk)) {
1364 DRM_ERROR("fail to get bus clk for de\n");
1365 return -EINVAL;
1366 }
1367
1368 de_drv->irq_no = irq_of_parse_and_map(node, 0);
1369 if (!de_drv->irq_no) {
1370 DRM_ERROR("irq_of_parse_and_map de irq fail\n");
1371 return -EINVAL;
1372 }
1373
1374 #if defined(CONFIG_AW_DRM_DE_V33X)
1375 if (of_property_read_u32(node, "chn_cfg_mode",
1376 &de_drv->chn_cfg_mode) < 0) {
1377 DRM_ERROR("failed to read chn_cfg_mode\n");
1378 return -EINVAL;
1379 }
1380 #endif
1381
1382 return 0;
1383 }
1384
sunxi_de_probe(struct platform_device * pdev)1385 static int sunxi_de_probe(struct platform_device *pdev)
1386 {
1387 int ret, i, lay_num;
1388 #if defined(CONFIG_AW_DRM_DE_V33X)
1389 struct de_feat_init de_feat;
1390 #endif
1391
1392
1393 DRM_INFO("[SUNXI-DE] sunxi_de_probe start\n");
1394
1395 de_drv->pdev = pdev;
1396
1397 ret = sunxi_de_parse_dts(pdev);
1398 if (ret < 0) {
1399 DRM_ERROR("Parse de dts failed!\n");
1400 goto de_err;
1401 }
1402
1403 #if defined(CONFIG_AW_DRM_DE_V33X)
1404 de_feat.chn_cfg_mode = de_drv->chn_cfg_mode;
1405 de_feat_init_config(&de_feat);
1406 #else
1407 if (de_feat_init()) {
1408 DRM_ERROR("de_feat_init failed\n");
1409 goto de_err;
1410 }
1411 #endif
1412
1413 de_drv->de_cnt = de_feat_get_num_screens();
1414 if ((de_drv->de_cnt <= 0) || (de_drv->de_cnt > DE_NUM_MAX)) {
1415 DRM_ERROR("get wrong de count");
1416 goto de_err;
1417 }
1418
1419
1420 for (i = 0; i < de_drv->de_cnt; i++) {
1421 de_drv->hwde[i].id = i;
1422
1423 de_drv->hwde[i].vichannel_cnt = de_feat_get_num_vi_chns(i);
1424 de_drv->hwde[i].uichannel_cnt = de_feat_get_num_ui_chns(i);
1425 de_drv->hwde[i].layers_per_vichannel = 4;
1426 de_drv->hwde[i].layers_per_uichannel = 4;
1427 }
1428
1429 for (i = 0; i < de_drv->de_cnt; i++) {
1430 lay_num = sunxi_de_get_layer_count(i);
1431 de_drv->hwde[i].layer_config_data =
1432 kzalloc(lay_num * sizeof(struct disp_layer_config_data),
1433 GFP_KERNEL);
1434 if (!de_drv->hwde[i].layer_config_data) {
1435 DRM_ERROR("KZALLOC for disp_layer_config_data failed\n");
1436 return -1;
1437 }
1438
1439 de_drv->hwde[i].funcs = &de_funcs;
1440 }
1441
1442
1443 if (sunxi_de_init_al() < 0) {
1444 DRM_ERROR("sunxi_de_init_al failed!\n");
1445 goto de_err;
1446 }
1447
1448 DRM_INFO("[SUNXI-DE] sunxi_de_probe end\n");
1449 return 0;
1450
1451 de_err:
1452 DRM_ERROR("sunxi_de_probe FAILED\n");
1453 return -EINVAL;
1454 }
1455
sunxi_de_remove(struct platform_device * pdev)1456 static int sunxi_de_remove(struct platform_device *pdev)
1457 {
1458 #if defined(CONFIG_AW_DRM_DE_V33X)
1459 return sunxi_de_v33x_al_exit();
1460 #elif defined(CONFIG_AW_DRM_DE_V3X)
1461 return sunxi_de_v3x_al_exit();
1462 #elif defined(CONFIG_AW_DRM_DE_V2X)
1463 return sunxi_de_v2x_al_exit();
1464 #elif defined(CONFIG_AW_DRM_DE_SUN50IW1)
1465 return sunxi_de_sun50iw1_al_exit();
1466 #else
1467 "ERROR Compile!"
1468 #endif
1469
1470 return 0;
1471 }
1472
1473 static const struct of_device_id sunxi_de_match[] = {
1474 { .compatible = "allwinner,sunxi-de", },
1475 {},
1476 };
1477
1478 struct platform_driver sunxi_de_platform_driver = {
1479 .probe = sunxi_de_probe,
1480 .remove = sunxi_de_remove,
1481 .driver = {
1482 .name = "de",
1483 .owner = THIS_MODULE,
1484 .of_match_table = sunxi_de_match,
1485 },
1486 };
1487
sunxi_de_module_init(void)1488 int sunxi_de_module_init(void)
1489 {
1490 int ret = 0, err;
1491 struct drv_model_info *drv_model;
1492
1493 DRM_INFO("[SUNXI-DE]sunxi_de_module_init\n");
1494
1495 de_drv = kzalloc(sizeof(struct sunxi_de_drv), GFP_KERNEL);
1496 if (!de_drv) {
1497 DRM_ERROR("can NOT allocate memory for de_drv\n");
1498 goto de_err;
1499 }
1500
1501 drv_model = &de_drv->drv_model;
1502 if (alloc_chrdev_region(&drv_model->devid, 0, 1, "de") < 0) {
1503 DRM_ERROR("alloc_chrdev_region failed\n");
1504 goto de_err;
1505 }
1506
1507 drv_model->cdev = cdev_alloc();
1508 if (!drv_model->cdev) {
1509 DRM_ERROR("cdev_alloc failed\n");
1510 goto de_err;
1511 }
1512
1513 cdev_init(drv_model->cdev, NULL);
1514 drv_model->cdev->owner = THIS_MODULE;
1515 err = cdev_add(drv_model->cdev, drv_model->devid, 1);
1516 if (err) {
1517 DRM_ERROR("cdev_add major number:%d failed\n",
1518 MAJOR(drv_model->devid));
1519 goto de_err;
1520 }
1521
1522 drv_model->sysclass = class_create(THIS_MODULE, "de");
1523 if (IS_ERR(drv_model->sysclass)) {
1524 DRM_ERROR("create class error\n");
1525 goto de_err;
1526 }
1527
1528 drv_model->dev = device_create(drv_model->sysclass, NULL,
1529 drv_model->devid, NULL, "de");
1530 if (!drv_model->dev) {
1531 DRM_ERROR("device_create failed\n");
1532 goto de_err;
1533 }
1534
1535 ret = platform_driver_register(&sunxi_de_platform_driver);
1536 if (ret) {
1537 DRM_ERROR("platform_driver_register failed\n");
1538 goto de_err;
1539 }
1540
1541 ret = sysfs_create_group(&drv_model->dev->kobj, &de_attribute_group);
1542 if (ret < 0) {
1543 DRM_ERROR("sysfs_create_file fail!\n");
1544 goto de_err;
1545 }
1546
1547 DRM_INFO("[SUNXI-DE]sunxi_de_module_init end\n\n");
1548 return 0;
1549 de_err:
1550 kfree(de_drv);
1551 DRM_ERROR("sunxi_de_module_init FAILED\n");
1552 return -EINVAL;
1553 }
1554
sunxi_de_module_exit(void)1555 void sunxi_de_module_exit(void)
1556 {
1557 struct drv_model_info *drv_model;
1558
1559 DRM_INFO("[SUNXI-DE]sunxi_de_module_exit\n");
1560
1561 drv_model = &de_drv->drv_model;
1562 platform_driver_unregister(&sunxi_de_platform_driver);
1563 device_destroy(drv_model->sysclass, drv_model->devid);
1564 class_destroy(drv_model->sysclass);
1565
1566 cdev_del(drv_model->cdev);
1567 kfree(de_drv);
1568 }
1569
1570