riscv:linux:drm:
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / verisilicon / vs_dc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 VeriSilicon Holdings Co., Ltd.
4  */
5
6 #include <linux/component.h>
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/media-bus-format.h>
10
11 #include <drm/drm_framebuffer.h>
12 #include <drm/drm_atomic.h>
13 #include <drm/drm_atomic_helper.h>
14 #include <drm/vs_drm.h>
15 #include <linux/reset.h>
16 #include <linux/pm_runtime.h>
17
18 #include "vs_type.h"
19 #include "vs_dc_hw.h"
20 #include "vs_dc.h"
21 #include "vs_crtc.h"
22 #include "vs_drv.h"
23
24 #include <soc/starfive/vic7100.h>
25
26 #if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
27 #include <drm/drm_fourcc.h>
28 #include <drm/drm_vblank.h>
29 #endif
30
31 //syscon panel
32 #include <linux/regmap.h>
33 #include <linux/mfd/syscon.h>
34 //syscon panel
35
36 static inline void update_format(u32 format, u64 mod, struct dc_hw_fb *fb)
37 {
38         u8 f = FORMAT_A8R8G8B8;
39
40         switch (format) {
41         case DRM_FORMAT_XRGB4444:
42         case DRM_FORMAT_RGBX4444:
43         case DRM_FORMAT_XBGR4444:
44         case DRM_FORMAT_BGRX4444:
45                 f = FORMAT_X4R4G4B4;
46                 break;
47         case DRM_FORMAT_ARGB4444:
48         case DRM_FORMAT_RGBA4444:
49         case DRM_FORMAT_ABGR4444:
50         case DRM_FORMAT_BGRA4444:
51                 f = FORMAT_A4R4G4B4;
52                 break;
53         case DRM_FORMAT_XRGB1555:
54         case DRM_FORMAT_RGBX5551:
55         case DRM_FORMAT_XBGR1555:
56         case DRM_FORMAT_BGRX5551:
57                 f = FORMAT_X1R5G5B5;
58                 break;
59         case DRM_FORMAT_ARGB1555:
60         case DRM_FORMAT_RGBA5551:
61         case DRM_FORMAT_ABGR1555:
62         case DRM_FORMAT_BGRA5551:
63                 f = FORMAT_A1R5G5B5;
64                 break;
65         case DRM_FORMAT_RGB565:
66         case DRM_FORMAT_BGR565:
67                 f = FORMAT_R5G6B5;
68                 break;
69         case DRM_FORMAT_XRGB8888:
70         case DRM_FORMAT_RGBX8888:
71         case DRM_FORMAT_XBGR8888:
72         case DRM_FORMAT_BGRX8888:
73                 f = FORMAT_X8R8G8B8;
74                 break;
75         case DRM_FORMAT_ARGB8888:
76         case DRM_FORMAT_RGBA8888:
77         case DRM_FORMAT_ABGR8888:
78         case DRM_FORMAT_BGRA8888:
79                 f = FORMAT_A8R8G8B8;
80                 break;
81         case DRM_FORMAT_YUYV:
82         case DRM_FORMAT_YVYU:
83                 f = FORMAT_YUY2;
84                 break;
85         case DRM_FORMAT_UYVY:
86         case DRM_FORMAT_VYUY:
87                 f = FORMAT_UYVY;
88                 break;
89         case DRM_FORMAT_YUV420:
90         case DRM_FORMAT_YVU420:
91                 f = FORMAT_YV12;
92                 break;
93         case DRM_FORMAT_NV21:
94                 f = FORMAT_NV12;
95                 break;
96         case DRM_FORMAT_NV16:
97         case DRM_FORMAT_NV61:
98                 f = FORMAT_NV16;
99                 break;
100         case DRM_FORMAT_P010:
101                 f = FORMAT_P010;
102                 break;
103         case DRM_FORMAT_ARGB2101010:
104         case DRM_FORMAT_RGBA1010102:
105         case DRM_FORMAT_ABGR2101010:
106         case DRM_FORMAT_BGRA1010102:
107                 f = FORMAT_A2R10G10B10;
108                 break;
109         case DRM_FORMAT_NV12:
110                 if (fourcc_mod_vs_get_type(mod) ==
111                         DRM_FORMAT_MOD_VS_TYPE_CUSTOM_10BIT)
112                         f = FORMAT_NV12_10BIT;
113                 else
114                         f = FORMAT_NV12;
115                 break;
116         case DRM_FORMAT_YUV444:
117                 if (fourcc_mod_vs_get_type(mod) ==
118                         DRM_FORMAT_MOD_VS_TYPE_CUSTOM_10BIT)
119                         f = FORMAT_YUV444_10BIT;
120                 else
121                         f = FORMAT_YUV444;
122                 break;
123         default:
124                 break;
125         }
126
127         fb->format = f;
128 }
129
130 static inline void update_swizzle(u32 format, struct dc_hw_fb *fb)
131 {
132         fb->swizzle = SWIZZLE_ARGB;
133         fb->uv_swizzle = 0;
134
135         switch (format) {
136         case DRM_FORMAT_RGBX4444:
137         case DRM_FORMAT_RGBA4444:
138         case DRM_FORMAT_RGBX5551:
139         case DRM_FORMAT_RGBA5551:
140         case DRM_FORMAT_RGBX8888:
141         case DRM_FORMAT_RGBA8888:
142         case DRM_FORMAT_RGBA1010102:
143                 fb->swizzle = SWIZZLE_RGBA;
144                 break;
145         case DRM_FORMAT_XBGR4444:
146         case DRM_FORMAT_ABGR4444:
147         case DRM_FORMAT_XBGR1555:
148         case DRM_FORMAT_ABGR1555:
149         case DRM_FORMAT_BGR565:
150         case DRM_FORMAT_XBGR8888:
151         case DRM_FORMAT_ABGR8888:
152         case DRM_FORMAT_ABGR2101010:
153                 fb->swizzle = SWIZZLE_ABGR;
154                 break;
155         case DRM_FORMAT_BGRX4444:
156         case DRM_FORMAT_BGRA4444:
157         case DRM_FORMAT_BGRX5551:
158         case DRM_FORMAT_BGRA5551:
159         case DRM_FORMAT_BGRX8888:
160         case DRM_FORMAT_BGRA8888:
161         case DRM_FORMAT_BGRA1010102:
162                 fb->swizzle = SWIZZLE_BGRA;
163                 break;
164         case DRM_FORMAT_YVYU:
165         case DRM_FORMAT_VYUY:
166         case DRM_FORMAT_NV21:
167         case DRM_FORMAT_NV61:
168                 fb->uv_swizzle = 1;
169                 break;
170         default:
171                 break;
172         }
173 }
174
175 static inline void update_watermark(struct drm_property_blob *watermark,
176                                                                         struct dc_hw_fb *fb)
177 {
178         struct drm_vs_watermark *data;
179
180         fb->water_mark = 0;
181
182         if (watermark) {
183                 data = watermark->data;
184                 fb->water_mark = data->watermark & 0xFFFFF;
185         }
186 }
187
188 static inline u8 to_vs_rotation(unsigned int rotation)
189 {
190         u8 rot;
191
192         switch (rotation & DRM_MODE_REFLECT_MASK) {
193         case DRM_MODE_REFLECT_X:
194                 rot = FLIP_X;
195                 return rot;
196         case DRM_MODE_REFLECT_Y:
197                 rot = FLIP_Y;
198                 return rot;
199         case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
200                 rot = FLIP_XY;
201                 return rot;
202         default:
203                 break;
204         }
205
206         switch (rotation & DRM_MODE_ROTATE_MASK) {
207         case DRM_MODE_ROTATE_0:
208                 rot = ROT_0;
209                 break;
210         case DRM_MODE_ROTATE_90:
211                 rot = ROT_90;
212                 break;
213         case DRM_MODE_ROTATE_180:
214                 rot = ROT_180;
215                 break;
216         case DRM_MODE_ROTATE_270:
217                 rot = ROT_270;
218                 break;
219         default:
220                 rot = ROT_0;
221                 break;
222         }
223
224         return rot;
225 }
226
227 static inline u8 to_vs_yuv_color_space(u32 color_space)
228 {
229         u8 cs;
230
231         switch (color_space) {
232         case DRM_COLOR_YCBCR_BT601:
233                 cs = COLOR_SPACE_601;
234                 break;
235         case DRM_COLOR_YCBCR_BT709:
236                 cs = COLOR_SPACE_709;
237                 break;
238         case DRM_COLOR_YCBCR_BT2020:
239                 cs = COLOR_SPACE_2020;
240                 break;
241         default:
242                 cs = COLOR_SPACE_601;
243                 break;
244         }
245
246         return cs;
247 }
248
249 static inline u8 to_vs_tile_mode(u64 modifier)
250 {
251         return (u8)(modifier & DRM_FORMAT_MOD_VS_NORM_MODE_MASK);
252 }
253
254 static inline u8 to_vs_display_id(struct vs_dc *dc, struct drm_crtc *crtc)
255 {
256         u8 panel_num = dc->hw.info->panel_num;
257         u32 index = drm_crtc_index(crtc);
258         int i;
259
260         for (i = 0; i < panel_num; i++) {
261                 if (index == dc->crtc[i]->base.index)
262                         return i;
263         }
264
265         return 0;
266 }
267 #if 0
268 static int plda_clk_rst_init(struct device *dev)
269 {
270         int ret;
271         struct vs_dc *dc = dev_get_drvdata(dev);
272
273         dc->num_clks = devm_clk_bulk_get_all(dev, &dc->clks);
274         if (dc->num_clks < 0) {
275                 dev_err(dev, "failed to get vout clocks\n");
276                 ret = -ENODEV;
277                 goto exit;
278         }
279         ret = clk_bulk_prepare_enable(dc->num_clks, dc->clks);
280         if (ret) {
281                 dev_err(dev, "failed to enable clocks\n");
282                 goto exit;
283         }
284
285         dc->resets = devm_reset_control_array_get_exclusive(dev);
286         if (IS_ERR(dc->resets)) {
287                 ret = PTR_ERR(dc->resets);
288                 dev_err(dev, "failed to get pcie resets");
289                 goto err_clk_init;
290         }
291         ret = reset_control_deassert(dc->resets);
292         goto exit;
293
294 err_clk_init:
295         clk_bulk_disable_unprepare(dc->num_clks, dc->clks);
296 exit:
297         return ret;
298 }
299
300 static void plda_clk_rst_deinit(struct device *dev)
301 {
302         struct vs_dc *dc = dev_get_drvdata(dev);
303
304         reset_control_assert(dc->resets);
305         clk_bulk_disable_unprepare(dc->num_clks, dc->clks);
306 }
307 #endif
308
309
310 static int vs_dc_get_clock(struct device *dev, struct vs_dc *dc)
311 {
312         dc->cpu_axi = devm_clk_get(dev, "noc_cpu");
313         if (IS_ERR(dc->cpu_axi)) {
314                 dev_err(dev, "---cpu_axi get error\n");
315                 return PTR_ERR(dc->cpu_axi);
316         }
317
318         dc->axicfg0_axi = devm_clk_get(dev, "noc_cfg0");
319         if (IS_ERR(dc->axicfg0_axi)) {
320                 dev_err(dev, "---axicfg0_axi get error\n");
321                 return PTR_ERR(dc->axicfg0_axi);
322         }
323
324         dc->disp_axi = devm_clk_get(dev, "noc_disp");
325         if (IS_ERR(dc->disp_axi)) {
326                 dev_err(dev, "---disp_axi get error\n");
327                 return PTR_ERR(dc->disp_axi);
328         }
329
330         dc->stg_axi = devm_clk_get(dev, "noc_stg");
331         if (IS_ERR(dc->stg_axi)) {
332                 dev_err(dev, "---stg_axi get error\n");
333                 return PTR_ERR(dc->stg_axi);
334         }
335         return 0;
336 }
337
338 static int  vs_dc_clock_enable(struct device *dev, struct vs_dc *dc)
339 {
340         int ret;
341         /*clk_prepare_enable(dc->sys_clk);*/
342         ret = clk_prepare_enable(dc->cpu_axi);
343         if (ret) {
344                 dev_err(dev, "failed to prepare/enable cpu_axi\n");
345                 return ret;
346         }
347         ret = clk_prepare_enable(dc->axicfg0_axi);
348         if (ret) {
349                 dev_err(dev, "failed to prepare/enable axicfg0_axi\n");
350                 return ret;
351         }
352         ret = clk_prepare_enable(dc->disp_axi);
353         if (ret) {
354                 dev_err(dev, "failed to prepare/enable disp_axi\n");
355                 return ret;
356         }
357         ret = clk_prepare_enable(dc->stg_axi);
358         if (ret) {
359                 dev_err(dev, "failed to prepare/enable stg_axi\n");
360                 return ret;
361         }
362
363         return ret;
364 }
365
366 static void  vs_dc_clock_disable(struct vs_dc *dc)
367 {
368         clk_disable_unprepare(dc->cpu_axi);
369         clk_disable_unprepare(dc->axicfg0_axi);
370         clk_disable_unprepare(dc->disp_axi);
371         clk_disable_unprepare(dc->stg_axi);
372 }
373
374 static int vs_dc_vouttop_get_clock(struct device *dev, struct vs_dc *dc)
375 {
376         dc->vout_src = devm_clk_get(dev, "vout_src");
377         if (IS_ERR(dc->vout_src)) {
378                 dev_err(dev, "failed to get vout_src\n");
379                 return PTR_ERR(dc->vout_src);
380         }
381
382         dc->vout_axi = devm_clk_get(dev, "top_vout_axi");
383         if (IS_ERR(dc->vout_axi)) {
384                 dev_err(dev, "failed to get vout_axi\n");
385                 return PTR_ERR(dc->vout_axi);
386         }
387
388         dc->ahb1 = devm_clk_get(dev, "ahb1");
389         if (IS_ERR(dc->ahb1)) {
390                 dev_err(dev, "failed to get ahb1\n");
391                 return PTR_ERR(dc->ahb1);
392         }
393
394         dc->vout_ahb = devm_clk_get(dev, "top_vout_ahb");
395         if (IS_ERR(dc->vout_ahb)) {
396                 dev_err(dev, "failed to get vout_ahb\n");
397                 return PTR_ERR(dc->vout_ahb);
398         }
399
400         dc->hdmitx0_mclk = devm_clk_get(dev, "top_vout_hdmiTX0");
401         if (IS_ERR(dc->hdmitx0_mclk)) {
402                 dev_err(dev, "failed to get hdmitx0_mclk\n");
403                 return PTR_ERR(dc->hdmitx0_mclk);
404         }
405
406         dc->bclk_mst = devm_clk_get(dev, "i2stx");
407         if (IS_ERR(dc->bclk_mst)) {
408                 dev_err(dev, "failed to get bclk_mst\n");
409                 return PTR_ERR(dc->bclk_mst);
410         }
411
412         return 0;
413 }
414
415 static int  vs_dc_vouttop_clock_enable(struct device *dev, struct vs_dc *dc)
416 {
417         int ret;
418         /*clk_prepare_enable(dc->sys_clk);*/
419         ret = clk_prepare_enable(dc->vout_src);
420         if (ret) {
421                 dev_err(dev, "failed to prepare/enable vout_src\n");
422                 return ret;
423         }
424         ret = clk_prepare_enable(dc->vout_axi);
425         if (ret) {
426                 dev_err(dev, "failed to prepare/enable vout_axi\n");
427                 return ret;
428         }
429         ret = clk_prepare_enable(dc->ahb1);
430         if (ret) {
431                 dev_err(dev, "failed to prepare/enable ahb1\n");
432                 return ret;
433         }
434         ret = clk_prepare_enable(dc->hdmitx0_mclk);
435         if (ret) {
436                 dev_err(dev, "failed to prepare/enable hdmitx0_mclk\n");
437                 return ret;
438         }
439         ret = clk_prepare_enable(dc->bclk_mst);
440         if (ret) {
441                 dev_err(dev, "failed to prepare/enable bclk_mst\n");
442                 return ret;
443         }
444         return ret;
445 }
446
447 static void  vs_dc_vouttop_clock_disable(struct vs_dc *dc)
448 {
449         clk_disable_unprepare(dc->vout_src);
450         clk_disable_unprepare(dc->vout_axi);
451         clk_disable_unprepare(dc->ahb1);
452         clk_disable_unprepare(dc->hdmitx0_mclk);
453         clk_disable_unprepare(dc->bclk_mst);
454 }
455
456 static int vs_dc_dc8200_get_clock(struct device *dev, struct vs_dc *dc)
457 {
458         dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk");
459         if (IS_ERR(dc->dc8200_clk_pix0)) {
460                 dev_err(dev, "---dc8200_clk_pix0 get error\n");
461                 return PTR_ERR(dc->dc8200_clk_pix0);
462         }
463
464         dc->dc8200_clk_pix1 = devm_clk_get(dev, "vout_pix1");
465         if (IS_ERR(dc->dc8200_clk_pix1)) {
466                 dev_err(dev, "---dc8200_clk_pix1 get error\n");
467                 return PTR_ERR(dc->dc8200_clk_pix1);
468         }
469
470         dc->dc8200_axi = devm_clk_get(dev, "axi_clk");
471         if (IS_ERR(dc->dc8200_axi)) {
472                 dev_err(dev, "---dc8200_axi get error\n");
473                 return PTR_ERR(dc->dc8200_axi);
474         }
475
476         dc->dc8200_core = devm_clk_get(dev, "core_clk");
477         if (IS_ERR(dc->dc8200_core)) {
478                 dev_err(dev, "---dc8200_core get error\n");
479                 return PTR_ERR(dc->dc8200_core);
480         }
481
482         dc->dc8200_ahb = devm_clk_get(dev, "vout_ahb");
483         if (IS_ERR(dc->dc8200_ahb)) {
484                 dev_err(dev, "---dc8200_ahb get error\n");
485                 return PTR_ERR(dc->dc8200_ahb);
486         }
487         return 0;
488 }
489
490 static int  vs_dc_dc8200_clock_enable(struct device *dev, struct vs_dc *dc)
491 {
492         int ret;
493         /*clk_prepare_enable(dc->sys_clk);*/
494         ret = clk_prepare_enable(dc->dc8200_clk_pix0);
495         if (ret) {
496                 dev_err(dev, "failed to prepare/enable dc8200_clk_pix0\n");
497                 return ret;
498         }
499         ret = clk_prepare_enable(dc->dc8200_clk_pix1);
500         if (ret) {
501                 dev_err(dev, "failed to prepare/enable dc8200_clk_pix1\n");
502                 return ret;
503         }
504         ret = clk_prepare_enable(dc->dc8200_axi);
505         if (ret) {
506                 dev_err(dev, "failed to prepare/enable dc8200_axi\n");
507                 return ret;
508         }
509         ret = clk_prepare_enable(dc->dc8200_core);
510         if (ret) {
511                 dev_err(dev, "failed to prepare/enable dc8200_core\n");
512                 return ret;
513         }
514         ret = clk_prepare_enable(dc->dc8200_ahb);
515         if (ret) {
516                 dev_err(dev, "failed to prepare/enable dc8200_ahb\n");
517                 return ret;
518         }
519
520         return ret;
521 }
522
523 static void  vs_dc_dc8200_clock_disable(struct vs_dc *dc)
524 {
525         clk_disable_unprepare(dc->dc8200_clk_pix0);
526         clk_disable_unprepare(dc->dc8200_clk_pix1);
527         clk_disable_unprepare(dc->dc8200_axi);
528         clk_disable_unprepare(dc->dc8200_core);
529         clk_disable_unprepare(dc->dc8200_ahb);
530 }
531
532 static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc)
533 {
534         int ret;
535         ret = vs_dc_get_clock(dev, dc);
536         if (ret) {
537                 dev_err(dev, "failed to get clock\n");
538                 return ret;
539         }
540
541         ret = vs_dc_clock_enable(dev, dc);
542         if (ret) {
543                 dev_err(dev, "failed to enable clock\n");
544                 return ret;
545         }
546
547         ret = vs_dc_vouttop_get_clock(dev, dc);
548         if (ret) {
549                 dev_err(dev, "failed to get clock\n");
550                 return ret;
551         }
552
553         ret = vs_dc_vouttop_clock_enable(dev, dc);
554         if (ret) {
555                 dev_err(dev, "failed to enable clock\n");
556                 return ret;
557         }
558
559         ret = vs_dc_dc8200_get_clock(dev, dc);
560         if (ret) {
561                 dev_err(dev, "failed to get clock\n");
562                 return ret;
563         }
564
565         ret = vs_dc_dc8200_clock_enable(dev, dc);
566         if (ret) {
567                 dev_err(dev, "failed to enable clock\n");
568                 return ret;
569         }
570
571         dc->vout_resets = devm_reset_control_array_get_exclusive(dev);
572         if (IS_ERR(dc->vout_resets)) {
573                 ret = PTR_ERR(dc->vout_resets);
574                 dev_err(dev, "faied to get vout resets controls\n");
575         }
576
577         ret = reset_control_deassert(dc->vout_resets);
578         if (ret){
579                 dev_err(dev, "deassert error.\n");
580                 return ret;
581         }
582
583         return ret;
584 }
585
586
587 static int syscon_panel_parse_dt(struct device *dev)
588 {
589         struct vs_dc *dc = dev_get_drvdata(dev);
590         int ret = 0;
591
592         dc->dss_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
593                                                 "verisilicon,dss-syscon");
594
595         if (IS_ERR(dc->dss_regmap)) {
596                 if (PTR_ERR(dc->dss_regmap) != -ENODEV) {
597                         dev_err(dev, "failed to get dss-syscon\n");
598                         ret = PTR_ERR(dc->dss_regmap);
599                         goto err;
600                 }
601                 dc->dss_regmap = NULL;
602                 goto err;
603         }
604
605 err:
606         return ret;
607 }
608
609 int sys_dispctrl_clk_standard(struct vs_dc *dc, struct device *dev)
610 {
611         dc->dc8200_clk_pix1 = devm_clk_get(dev, "vout_pix1");
612         if (IS_ERR(dc->dc8200_clk_pix1)) {
613                 dev_err(dev, "---dc8200_clk_pix1 get error\n");
614                 return PTR_ERR(dc->dc8200_clk_pix1);
615         }
616
617         dc->hdmitx0_pixelclk = devm_clk_get(dev, "hdmitx0_pixelclk");
618         if (IS_ERR(dc->hdmitx0_pixelclk)) {
619                 dev_err(dev, "---hdmitx0_pixelclk get error\n");
620                 return PTR_ERR(dc->hdmitx0_pixelclk);
621         }
622
623         dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk");
624         if (IS_ERR(dc->dc8200_clk_pix0)) {
625                 dev_err(dev, "---dc8200_clk_pix0 get error\n");
626                 return PTR_ERR(dc->dc8200_clk_pix0);
627         }
628
629         dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk");     //dc8200_clk_pix0
630         if (IS_ERR(dc->dc8200_clk_pix0)) {
631                 dev_err(dev, "---dc8200_clk_pix0 get error\n");
632                 return PTR_ERR(dc->dc8200_clk_pix0);
633         }
634
635         dc->hdmitx0_pixelclk = devm_clk_get(dev, "hdmitx0_pixelclk");//hdmitx0_pixelclk
636         if (IS_ERR(dc->hdmitx0_pixelclk)) {
637                 dev_err(dev, "---hdmitx0_pixelclk get error\n");
638                 return PTR_ERR(dc->hdmitx0_pixelclk);
639         }
640
641         dc->vout_src = devm_clk_get(dev, "vout_src");
642         if (IS_ERR(dc->vout_src)){
643                 dev_err(dev,"failed to get dc->vout_src\n");
644                 return PTR_ERR(dc->vout_src);
645         }
646
647         dc->vout_top_lcd = devm_clk_get(dev, "vout_top_lcd");
648         if (IS_ERR(dc->vout_top_lcd)){
649                 dev_err(dev,"failed to get dc->vout_top_lcd\n");
650                 return PTR_ERR(dc->vout_top_lcd);
651         }
652
653         dc->dc8200_pix0 = devm_clk_get(dev, "dc8200_pix0");     //dc8200_pix0
654         if (IS_ERR(dc->dc8200_pix0)) {
655                 dev_err(dev, "---dc8200_pix0 get error\n");
656                 return PTR_ERR(dc->dc8200_pix0);
657         }
658
659     return 0;
660 }
661
662 static void dc_deinit(struct device *dev)
663 {
664         struct vs_dc *dc = dev_get_drvdata(dev);
665         struct platform_device *pdev = to_platform_device(dev);
666         int ret;
667         dc_hw_enable_interrupt(&dc->hw, 0);
668         dc_hw_deinit(&dc->hw);
669         vs_dc_dc8200_clock_disable(dc);
670         vs_dc_vouttop_clock_disable(dc);
671         vs_dc_clock_disable(dc);
672         ret = reset_control_assert(dc->vout_resets);
673         if (ret)
674                 dev_err(dev, "assert vout resets error.\n");
675
676         pm_runtime_put_sync(&pdev->dev);
677         pm_runtime_disable(&pdev->dev);
678 }
679
680
681 ///////////////////////////////////////////////////////////
682 static int dc_init(struct device *dev)
683 {
684         struct vs_dc *dc = dev_get_drvdata(dev);
685         struct platform_device *pdev = to_platform_device(dev);
686         int ret;
687
688         dc->first_frame = true;
689
690         ret = syscon_panel_parse_dt(dev);
691         if (ret){
692                 dev_err(dev,"syscon_panel_parse_dt failed\n");
693                 return ret;
694         }
695
696         pm_runtime_enable(&pdev->dev);
697         ret = pm_runtime_get_sync(&pdev->dev);
698         if (ret < 0) {
699                 dev_err(&pdev->dev, "dc_init: failed to get pm runtime: %d\n", ret);
700                 return ret;
701         }
702
703         ret = dc_vout_clk_rst_init(dev, dc);
704
705         ret = sys_dispctrl_clk_standard(dc, dev);
706
707 #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi
708         regmap_update_bits(dc->dss_regmap, 0x4, BIT(20), 1<<20);
709 #endif
710
711 #ifdef CONFIG_STARFIVE_DSI
712         regmap_update_bits(dc->dss_regmap, 0x8, BIT(3), 1<<3);
713 #endif
714
715         dc->dc8200_clk_pix0_out = devm_clk_get(dev, "dc8200_pix0_out");
716         if (IS_ERR(dc->dc8200_clk_pix0_out)){
717                 dev_err(dev,"failed to get dc->dc8200_clk_pix0_out\n");
718                 return PTR_ERR(dc->dc8200_clk_pix0_out);
719         }
720
721         dc->dc8200_clk_pix1_out = devm_clk_get(dev, "dc8200_pix1_out");
722         if (IS_ERR(dc->dc8200_clk_pix0_out)){
723                 dev_err(dev,"failed to get dc->dc8200_clk_pix0_out\n");
724                 return PTR_ERR(dc->dc8200_clk_pix0_out);
725         }
726
727         dc->vout_top_lcd = devm_clk_get(dev, "vout_top_lcd");
728         if (IS_ERR(dc->vout_top_lcd)){
729                 dev_err(dev,"failed to get dc->vout_top_lcd\n");
730                 return PTR_ERR(dc->vout_top_lcd);
731         }
732
733         ret = clk_set_parent(dc->vout_top_lcd, dc->dc8200_clk_pix1_out);
734
735         ret = clk_prepare_enable(dc->vout_top_lcd);
736         if (ret) {
737                 dev_err(dev, "failed to prepare/enable vout_top_lcd\n");
738                 return ret;
739         }
740
741         ret = dc_hw_init(&dc->hw);
742         if (ret) {
743                 dev_err(dev, "failed to init DC HW\n");
744                 return ret;
745         }
746
747         return 0;
748
749 }
750
751 static void vs_dc_dump_enable(struct device *dev, dma_addr_t addr,
752                                    unsigned int pitch)
753 {
754         struct vs_dc *dc = dev_get_drvdata(dev);
755
756         dc_hw_enable_dump(&dc->hw, addr, pitch);
757 }
758
759 static void vs_dc_dump_disable(struct device *dev)
760 {
761         struct vs_dc *dc = dev_get_drvdata(dev);
762
763         dc_hw_disable_dump(&dc->hw);
764 }
765
766 static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc)
767 {
768         struct vs_dc *dc = dev_get_drvdata(dev);
769         struct vs_crtc_state *crtc_state = to_vs_crtc_state(crtc->state);
770         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
771         struct dc_hw_display display;
772
773         display.bus_format = crtc_state->output_fmt;
774         display.h_active = mode->hdisplay;
775         display.h_total = mode->htotal;
776         display.h_sync_start = mode->hsync_start;
777         display.h_sync_end = mode->hsync_end;
778         if (mode->flags & DRM_MODE_FLAG_PHSYNC)
779                 display.h_sync_polarity = true;
780         else
781                 display.h_sync_polarity = false;
782
783         display.v_active = mode->vdisplay;
784         display.v_total = mode->vtotal;
785
786         if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI){
787                 display.v_sync_start = mode->vsync_start + 1;
788                 display.v_sync_end = mode->vsync_end - 1;
789         }else{
790                 display.v_sync_start = mode->vsync_start;
791                 display.v_sync_end = mode->vsync_end;
792         }
793
794         if (mode->flags & DRM_MODE_FLAG_PVSYNC)
795                 display.v_sync_polarity = true;
796         else
797                 display.v_sync_polarity = false;
798
799         display.sync_mode = crtc_state->sync_mode;
800         display.bg_color = crtc_state->bg_color;
801
802         display.id = to_vs_display_id(dc, crtc);
803         display.sync_enable = crtc_state->sync_enable;
804         display.dither_enable = crtc_state->dither_enable;
805
806         display.enable = true;
807
808         if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI){
809                 if (dc->pix_clk_rate != mode->clock) {
810                         clk_set_rate(dc->dc8200_pix0, mode->clock * 1000);
811                         dc->pix_clk_rate = mode->clock;
812                 }
813
814                 clk_set_parent(dc->dc8200_clk_pix1, dc->dc8200_pix0 );//child,parent
815                 udelay(1000);
816                 dc_hw_set_out(&dc->hw, OUT_DPI, display.id);
817         } else {
818                 if (dc->pix_clk_rate != mode->clock) {
819                         clk_set_rate(dc->dc8200_pix0, mode->clock * 1000);
820                         dc->pix_clk_rate = mode->clock;
821                 }
822
823                 clk_set_parent(dc->dc8200_clk_pix1, dc->dc8200_pix0);
824                 clk_set_parent(dc->dc8200_clk_pix0, dc->hdmitx0_pixelclk);
825                 dc_hw_set_out(&dc->hw, OUT_DP, display.id);
826         }
827
828 #ifdef CONFIG_VERISILICON_MMU
829         if (crtc_state->mmu_prefetch == VS_MMU_PREFETCH_ENABLE)
830                 dc_hw_enable_mmu_prefetch(&dc->hw, true);
831         else
832                 dc_hw_enable_mmu_prefetch(&dc->hw, false);
833 #endif
834
835         dc_hw_setup_display(&dc->hw, &display);
836 }
837
838 static void vs_dc_disable(struct device *dev, struct drm_crtc *crtc)
839 {
840         struct vs_dc *dc = dev_get_drvdata(dev);
841         struct dc_hw_display display;
842
843         display.id = to_vs_display_id(dc, crtc);
844         display.enable = false;
845
846         dc_hw_setup_display(&dc->hw, &display);
847 }
848
849 static bool vs_dc_mode_fixup(struct device *dev,
850                                   const struct drm_display_mode *mode,
851                                   struct drm_display_mode *adjusted_mode)
852 {
853
854 #if 1
855         ;//printk("====> %s, %d--pix_clk.\n", __func__, __LINE__);
856 #else
857         struct vs_dc *dc = dev_get_drvdata(dev);
858
859         long clk_rate;
860         if (dc->pix_clk) {
861                 clk_rate = clk_round_rate(dc->pix_clk,
862                                           adjusted_mode->clock * 1000);
863                 adjusted_mode->clock = DIV_ROUND_UP(clk_rate, 1000);
864         }
865 #endif
866
867         return true;
868 }
869
870 static void vs_dc_set_gamma(struct device *dev, struct drm_crtc *crtc,
871                                  struct drm_color_lut *lut, unsigned int size)
872 {
873         struct vs_dc *dc = dev_get_drvdata(dev);
874         u16 i, r, g, b;
875         u8 bits, id;
876
877         if (size != dc->hw.info->gamma_size) {
878                 dev_err(dev, "gamma size does not match!\n");
879                 return;
880         }
881
882         id = to_vs_display_id(dc, crtc);
883
884         bits = dc->hw.info->gamma_bits;
885         for (i = 0; i < size; i++) {
886                 r = drm_color_lut_extract(lut[i].red, bits);
887                 g = drm_color_lut_extract(lut[i].green, bits);
888                 b = drm_color_lut_extract(lut[i].blue, bits);
889                 dc_hw_update_gamma(&dc->hw, id, i, r, g, b);
890         }
891 }
892
893 static void vs_dc_enable_gamma(struct device *dev, struct drm_crtc *crtc,
894                                  bool enable)
895 {
896         struct vs_dc *dc = dev_get_drvdata(dev);
897         u8 id;
898
899         id = to_vs_display_id(dc, crtc);
900         dc_hw_enable_gamma(&dc->hw, id, enable);
901 }
902
903 static void vs_dc_enable_vblank(struct device *dev, bool enable)
904 {
905         struct vs_dc *dc = dev_get_drvdata(dev);
906
907         dc_hw_enable_interrupt(&dc->hw, enable);
908 }
909
910 static u32 calc_factor(u32 src, u32 dest)
911 {
912         u32 factor = 1 << 16;
913
914         if ((src > 1) && (dest > 1))
915                 factor = ((src - 1) << 16) / (dest - 1);
916
917         return factor;
918 }
919
920 static void update_scale(struct drm_plane_state *state, struct dc_hw_roi *roi,
921                                                  struct dc_hw_scale *scale)
922 {
923         int dst_w = drm_rect_width(&state->dst);
924         int dst_h = drm_rect_height(&state->dst);
925         int src_w, src_h, temp;
926
927         scale->enable = false;
928
929         if (roi->enable) {
930                 src_w = roi->width;
931                 src_h = roi->height;
932         } else {
933                 src_w = drm_rect_width(&state->src) >> 16;
934                 src_h = drm_rect_height(&state->src) >> 16;
935         }
936
937         if (drm_rotation_90_or_270(state->rotation)) {
938                 temp = src_w;
939                 src_w = src_h;
940                 src_h = temp;
941         }
942
943         if (src_w != dst_w) {
944                 scale->scale_factor_x = calc_factor(src_w, dst_w);
945                 scale->enable = true;
946         } else {
947                 scale->scale_factor_x = 1 << 16;
948         }
949         if (src_h != dst_h) {
950                 scale->scale_factor_y = calc_factor(src_h, dst_h);
951                 scale->enable = true;
952         } else {
953                 scale->scale_factor_y = 1 << 16;
954         }
955 }
956
957 static void update_fb(struct vs_plane *plane, u8 display_id,
958                                           struct dc_hw_fb *fb, struct drm_plane_state *state)
959 {
960         //struct drm_plane_state *state = plane->base.state;
961         struct vs_plane_state *plane_state = to_vs_plane_state(state);
962         struct drm_framebuffer *drm_fb = state->fb;
963         struct drm_rect *src = &state->src;
964
965         fb->display_id = display_id;
966         fb->y_address = plane->dma_addr[0];
967         fb->y_stride = drm_fb->pitches[0];
968         if (drm_fb->format->format == DRM_FORMAT_YVU420) {
969                 fb->u_address = plane->dma_addr[2];
970                 fb->v_address = plane->dma_addr[1];
971                 fb->u_stride = drm_fb->pitches[2];
972                 fb->v_stride = drm_fb->pitches[1];
973         } else {
974                 fb->u_address = plane->dma_addr[1];
975                 fb->v_address = plane->dma_addr[2];
976                 fb->u_stride = drm_fb->pitches[1];
977                 fb->v_stride = drm_fb->pitches[2];
978         }
979         fb->width = drm_rect_width(src) >> 16;
980         fb->height = drm_rect_height(src) >> 16;
981         fb->tile_mode = to_vs_tile_mode(drm_fb->modifier);
982         //fb->tile_mode = 0x04;
983         fb->rotation = to_vs_rotation(state->rotation);
984         fb->yuv_color_space = to_vs_yuv_color_space(state->color_encoding);
985         fb->zpos = state->zpos;
986         fb->enable = state->visible;
987         update_format(drm_fb->format->format, drm_fb->modifier, fb);
988         update_swizzle(drm_fb->format->format, fb);
989         update_watermark(plane_state->watermark, fb);
990
991         starfive_flush_dcache(fb->y_address, fb->height * fb->y_stride);
992         if (fb->u_address)
993                 starfive_flush_dcache(fb->u_address, fb->height * fb->u_stride);
994         if (fb->v_address)
995                 starfive_flush_dcache(fb->v_address, fb->height * fb->v_stride);
996
997         plane_state->status.tile_mode = fb->tile_mode;
998 }
999
1000 #ifdef CONFIG_VERISILICON_DEC
1001 static u8 get_stream_base(u8 id)
1002 {
1003         u8 stream_base = 0;
1004
1005         switch (id) {
1006         case OVERLAY_PLANE_0:
1007                 stream_base = 3;
1008                 break;
1009         case OVERLAY_PLANE_1:
1010                 stream_base = 6;
1011                 break;
1012         case PRIMARY_PLANE_1:
1013                 stream_base = 16;
1014                 break;
1015         case OVERLAY_PLANE_2:
1016                 stream_base = 19;
1017                 break;
1018         case OVERLAY_PLANE_3:
1019                 stream_base = 22;
1020                 break;
1021         default:
1022                 break;
1023         }
1024
1025         return stream_base;
1026 }
1027
1028 static void update_fbc(struct vs_dc *dc, struct vs_plane *plane, bool *enable,
1029                                                 struct drm_plane_state *state)
1030 {
1031         struct dc_dec_fb dec_fb;
1032         //struct drm_plane_state *state = plane->base.state;
1033         struct drm_framebuffer *drm_fb = state->fb;
1034         struct vs_dc_plane *dc_plane = &dc->planes[plane->id];
1035         u8 i, stream_id;
1036
1037         if (!dc->hw.info->cap_dec) {
1038                 *enable = false;
1039                 return;
1040         }
1041
1042         stream_id = get_stream_base(dc_plane->id);
1043         memset(&dec_fb, 0, sizeof(struct dc_dec_fb));
1044         dec_fb.fb = drm_fb;
1045
1046         if (fourcc_mod_vs_get_type(drm_fb->modifier) !=
1047                                         DRM_FORMAT_MOD_VS_TYPE_COMPRESSED) {
1048                 *enable = false;
1049         } else {
1050                 *enable = true;
1051
1052                 for (i = 0; i < DEC_PLANE_MAX; i++) {
1053                         dec_fb.addr[i] = plane->dma_addr[i];
1054                         dec_fb.stride[i] = drm_fb->pitches[i];
1055                 }
1056         }
1057
1058         dc_dec_config(&dc->dec400l, &dec_fb, stream_id);
1059 }
1060
1061 static void disable_fbc(struct vs_dc *dc, struct vs_plane *plane)
1062 {
1063         struct vs_dc_plane *dc_plane = &dc->planes[plane->id];
1064         u8 stream_id;
1065
1066         if (!dc->hw.info->cap_dec)
1067                 return;
1068
1069         stream_id = get_stream_base(dc_plane->id);
1070         dc_dec_config(&dc->dec400l, NULL, stream_id);
1071 }
1072 #endif
1073
1074 static void update_degamma(struct vs_dc *dc, struct vs_plane *plane,
1075                            struct vs_plane_state *plane_state)
1076 {
1077         dc_hw_update_degamma(&dc->hw, plane->id, plane_state->degamma);
1078         plane_state->degamma_changed = false;
1079 }
1080
1081 static void update_roi(struct vs_dc *dc, u8 id,
1082                                            struct vs_plane_state *plane_state,
1083                                            struct dc_hw_roi *roi,
1084                                            struct drm_plane_state *state)
1085 {
1086         struct drm_vs_roi *data;
1087         //struct drm_rect *src = &plane_state->base.src;
1088         struct drm_rect *src = &state->src;
1089         u16 src_w = drm_rect_width(src) >> 16;
1090         u16 src_h = drm_rect_height(src) >> 16;
1091
1092         if (plane_state->roi) {
1093                 data = plane_state->roi->data;
1094
1095                 if (data->enable) {
1096                         roi->x = data->roi_x;
1097                         roi->y = data->roi_y;
1098                         roi->width = (data->roi_x + data->roi_w > src_w) ?
1099                                                  (src_w - data->roi_x) : data->roi_w;
1100                         roi->height = (data->roi_y + data->roi_h > src_h) ?
1101                                                   (src_h - data->roi_y) : data->roi_h;
1102                         roi->enable = true;
1103                 } else {
1104                         roi->enable = false;
1105                 }
1106
1107                 dc_hw_update_roi(&dc->hw, id, roi);
1108         } else {
1109                 roi->enable = false;
1110         }
1111 }
1112
1113 static void update_color_mgmt(struct vs_dc *dc, u8 id,
1114                                                         struct dc_hw_fb *fb,
1115                                                         struct vs_plane_state *plane_state)
1116 {
1117         struct drm_vs_color_mgmt *data;
1118         struct dc_hw_colorkey colorkey;
1119
1120         if (plane_state->color_mgmt) {
1121                 data = plane_state->color_mgmt->data;
1122
1123                 fb->clear_enable = data->clear_enable;
1124                 fb->clear_value = data->clear_value;
1125
1126                 if (data->colorkey > data->colorkey_high)
1127                         data->colorkey = data->colorkey_high;
1128
1129                 colorkey.colorkey = data->colorkey;
1130                 colorkey.colorkey_high = data->colorkey_high;
1131                 colorkey.transparency = (data->transparency) ?
1132                                 DC_TRANSPARENCY_KEY : DC_TRANSPARENCY_OPAQUE;
1133                 dc_hw_update_colorkey(&dc->hw, id, &colorkey);
1134         }
1135 }
1136
1137 static void update_plane(struct vs_dc *dc, struct vs_plane *plane, struct drm_plane *drm_plane,
1138                                                 struct drm_atomic_state *drm_state)
1139 {
1140         struct dc_hw_fb fb = {0};
1141         struct dc_hw_scale scale;
1142         struct dc_hw_position pos;
1143         struct dc_hw_blend blend;
1144         struct dc_hw_roi roi;
1145         //struct drm_plane_state *state = plane->base.state;
1146         struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state,
1147                                                                            drm_plane);
1148         struct vs_plane_state *plane_state = to_vs_plane_state(state);
1149         struct drm_rect *dest = &state->dst;
1150         bool dec_enable = false;
1151         u8 display_id = 0;
1152
1153 #ifdef CONFIG_VERISILICON_DEC
1154         update_fbc(dc, plane, &dec_enable, state);
1155 #endif
1156
1157         display_id = to_vs_display_id(dc, state->crtc);
1158         update_fb(plane, display_id, &fb, state);
1159         fb.dec_enable = dec_enable;
1160
1161
1162         update_roi(dc, plane->id, plane_state, &roi, state);
1163
1164         update_scale(state, &roi, &scale);
1165
1166         if (plane_state->degamma_changed)
1167                 update_degamma(dc, plane, plane_state);
1168
1169         pos.start_x = dest->x1;
1170         pos.start_y = dest->y1;
1171         pos.end_x = dest->x2;
1172         pos.end_y = dest->y2;
1173
1174         blend.alpha = (u8)(state->alpha >> 8);
1175         blend.blend_mode = (u8)(state->pixel_blend_mode);
1176
1177         update_color_mgmt(dc, plane->id, &fb, plane_state);
1178
1179         dc_hw_update_plane(&dc->hw, plane->id, &fb, &scale, &pos, &blend);
1180 }
1181
1182 static void update_qos(struct vs_dc *dc, struct vs_plane *plane, struct drm_plane *drm_plane,
1183                                                 struct drm_atomic_state *drm_state)
1184 {
1185         //struct drm_plane_state *state = plane->base.state;
1186         struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state,
1187                                                                            drm_plane);
1188         struct vs_plane_state *plane_state = to_vs_plane_state(state);
1189         struct drm_vs_watermark *data;
1190         struct dc_hw_qos qos;
1191
1192         if (plane_state->watermark) {
1193                 data = plane_state->watermark->data;
1194
1195                 if (data->qos_high) {
1196                         if (data->qos_low > data->qos_high)
1197                                 data->qos_low = data->qos_high;
1198
1199                         qos.low_value = data->qos_low & 0x0F;
1200                         qos.high_value = data->qos_high & 0x0F;
1201                         dc_hw_update_qos(&dc->hw, &qos);
1202                 }
1203         }
1204 }
1205
1206 static void update_cursor_size(struct drm_plane_state *state, struct dc_hw_cursor *cursor)
1207 {
1208         u8 size_type;
1209
1210         switch (state->crtc_w) {
1211         case 32:
1212                 size_type = CURSOR_SIZE_32X32;
1213                 break;
1214         case 64:
1215                 size_type = CURSOR_SIZE_64X64;
1216                 break;
1217         default:
1218                 size_type = CURSOR_SIZE_32X32;
1219                 break;
1220         }
1221
1222         cursor->size = size_type;
1223 }
1224
1225 static void update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, struct drm_plane *drm_plane,
1226                                                                         struct drm_atomic_state *drm_state)
1227 {
1228         //struct drm_plane_state *state = plane->base.state;
1229         struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state,
1230                                                                            drm_plane);
1231         struct drm_framebuffer *drm_fb = state->fb;
1232         struct dc_hw_cursor cursor;
1233
1234         cursor.address = plane->dma_addr[0];
1235         cursor.x = state->crtc_x;
1236         cursor.y = state->crtc_y;
1237         cursor.hot_x = drm_fb->hot_x;
1238         cursor.hot_y = drm_fb->hot_y;
1239         cursor.display_id = to_vs_display_id(dc, state->crtc);
1240         update_cursor_size(state, &cursor);
1241         cursor.enable = true;
1242
1243         dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor);
1244 }
1245
1246 static void vs_dc_update_plane(struct device *dev, struct vs_plane *plane, struct drm_plane *drm_plane,
1247                                                                 struct drm_atomic_state *drm_state)
1248 {
1249         struct vs_dc *dc = dev_get_drvdata(dev);
1250         enum drm_plane_type type = plane->base.type;
1251
1252         switch (type) {
1253         case DRM_PLANE_TYPE_PRIMARY:
1254         case DRM_PLANE_TYPE_OVERLAY:
1255                 update_plane(dc, plane, drm_plane, drm_state);
1256                 update_qos(dc, plane, drm_plane, drm_state);
1257                 break;
1258         case DRM_PLANE_TYPE_CURSOR:
1259                 update_cursor_plane(dc, plane, drm_plane, drm_state);
1260                 break;
1261         default:
1262                 break;
1263         }
1264 }
1265
1266 static void vs_dc_disable_plane(struct device *dev, struct vs_plane *plane,
1267                                                                 struct drm_plane_state *old_state)
1268 {
1269         struct vs_dc *dc = dev_get_drvdata(dev);
1270         enum drm_plane_type type = plane->base.type;
1271         struct dc_hw_fb fb = {0};
1272         struct dc_hw_cursor cursor = {0};
1273
1274         switch (type) {
1275         case DRM_PLANE_TYPE_PRIMARY:
1276         case DRM_PLANE_TYPE_OVERLAY:
1277                 fb.enable = false;
1278                 dc_hw_update_plane(&dc->hw, plane->id, &fb, NULL, NULL, NULL);
1279 #ifdef CONFIG_VERISILICON_DEC
1280                 disable_fbc(dc, plane);
1281 #endif
1282                 break;
1283         case DRM_PLANE_TYPE_CURSOR:
1284                 cursor.enable = false;
1285                 cursor.display_id = to_vs_display_id(dc, old_state->crtc);
1286                 dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor);
1287                 break;
1288         default:
1289                 break;
1290         }
1291 }
1292
1293 static bool vs_dc_mod_supported(const struct vs_plane_info *plane_info,
1294                                                                 u64 modifier)
1295 {
1296         const u64 *mods;
1297
1298         if (plane_info->modifiers == NULL)
1299                 return false;
1300
1301         for (mods = plane_info->modifiers; *mods != DRM_FORMAT_MOD_INVALID; mods++) {
1302                 if (*mods == modifier)
1303                         return true;
1304         }
1305
1306         return false;
1307 }
1308
1309 static int vs_dc_check_plane(struct device *dev, struct drm_plane *plane,
1310                                   struct drm_atomic_state *state)
1311 {
1312         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
1313                                                                                          plane);
1314         struct vs_dc *dc = dev_get_drvdata(dev);
1315         struct drm_framebuffer *fb = new_plane_state->fb;
1316         const struct vs_plane_info *plane_info;
1317         struct drm_crtc *crtc = new_plane_state->crtc;
1318         struct drm_crtc_state *crtc_state;
1319         struct vs_plane *vs_plane = to_vs_plane(plane);
1320
1321         plane_info = &dc->hw.info->planes[vs_plane->id];
1322         if (plane_info == NULL)
1323                 return -EINVAL;
1324
1325         if (fb->width < plane_info->min_width ||
1326                 fb->width > plane_info->max_width ||
1327                 fb->height < plane_info->min_height ||
1328                 fb->height > plane_info->max_height)
1329                 dev_err_once(dev, "buffer size may not support on plane%d.\n",
1330                                  vs_plane->id);
1331
1332         if ((vs_plane->base.type != DRM_PLANE_TYPE_CURSOR) &&
1333                 (!vs_dc_mod_supported(plane_info, fb->modifier))) {
1334                 dev_err(dev, "unsupported modifier on plane%d.\n", vs_plane->id);
1335                 return -EINVAL;
1336         }
1337
1338         crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
1339         if (IS_ERR(crtc_state))
1340                 return -EINVAL;
1341
1342         return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
1343                                                   plane_info->min_scale,
1344                                                   plane_info->max_scale,
1345                                                   true, true);
1346 }
1347
1348 static irqreturn_t dc_isr(int irq, void *data)
1349 {
1350         struct vs_dc *dc = data;
1351         struct vs_dc_info *dc_info = dc->hw.info;
1352         u32 i, ret;
1353
1354         ret = dc_hw_get_interrupt(&dc->hw);
1355
1356         for (i = 0; i < dc_info->panel_num; i++)
1357                 vs_crtc_handle_vblank(&dc->crtc[i]->base, dc_hw_check_underflow(&dc->hw));
1358
1359         return IRQ_HANDLED;
1360 }
1361
1362 static void vs_dc_commit(struct device *dev)
1363 {
1364         struct vs_dc *dc = dev_get_drvdata(dev);
1365
1366 #ifdef CONFIG_VERISILICON_DEC
1367         if (dc->hw.info->cap_dec)
1368                 dc_dec_commit(&dc->dec400l, &dc->hw);
1369 #endif
1370
1371         dc_hw_enable_shadow_register(&dc->hw, false);
1372
1373         dc_hw_commit(&dc->hw);
1374
1375         if (dc->first_frame)
1376                 dc->first_frame = false;
1377
1378         dc_hw_enable_shadow_register(&dc->hw, true);
1379 }
1380
1381 static const struct vs_crtc_funcs dc_crtc_funcs = {
1382         .enable                 = vs_dc_enable,
1383         .disable                = vs_dc_disable,
1384         .mode_fixup             = vs_dc_mode_fixup,
1385         .set_gamma              = vs_dc_set_gamma,
1386         .enable_gamma   = vs_dc_enable_gamma,
1387         .enable_vblank  = vs_dc_enable_vblank,
1388         .commit                 = vs_dc_commit,
1389 };
1390
1391 static const struct vs_plane_funcs dc_plane_funcs = {
1392         .update                 = vs_dc_update_plane,
1393         .disable                = vs_dc_disable_plane,
1394         .check                  = vs_dc_check_plane,
1395 };
1396
1397 static const struct vs_dc_funcs dc_funcs = {
1398         .dump_enable            = vs_dc_dump_enable,
1399         .dump_disable           = vs_dc_dump_disable,
1400 };
1401
1402 static int dc_bind(struct device *dev, struct device *master, void *data)
1403 {
1404         struct drm_device *drm_dev = data;
1405 #ifdef CONFIG_VERISILICON_MMU
1406         struct vs_drm_private *priv = drm_dev->dev_private;
1407 #endif
1408         struct vs_dc *dc = dev_get_drvdata(dev);
1409         struct device_node *port;
1410         struct vs_crtc *crtc;
1411         struct drm_crtc *drm_crtc;
1412         struct vs_dc_info *dc_info;
1413         struct vs_plane *plane;
1414         struct drm_plane *drm_plane, *tmp;
1415         struct vs_plane_info *plane_info;
1416         int i, ret;
1417         u32 ctrc_mask = 0;
1418
1419         if (!drm_dev || !dc) {
1420                 dev_err(dev, "devices are not created.\n");
1421                 return -ENODEV;
1422         }
1423
1424         ret = dc_init(dev);
1425         if (ret < 0) {
1426                 dev_err(dev, "Failed to initialize DC hardware.\n");
1427                 return ret;
1428         }
1429
1430 #ifdef CONFIG_VERISILICON_MMU
1431         ret = dc_mmu_construct(priv->dma_dev, &priv->mmu);
1432         if (ret) {
1433                 dev_err(dev, "failed to construct DC MMU\n");
1434                 goto err_clean_dc;
1435         }
1436
1437         ret = dc_hw_mmu_init(&dc->hw, priv->mmu);
1438         if (ret) {
1439                 dev_err(dev, "failed to init DC MMU\n");
1440                 goto err_clean_dc;
1441         }
1442 #endif
1443
1444         ret = vs_drm_iommu_attach_device(drm_dev, dev);
1445         if (ret < 0) {
1446                 dev_err(dev, "Failed to attached iommu device.\n");
1447                 goto err_clean_dc;
1448         }
1449
1450         port = of_get_child_by_name(dev->of_node, "port");
1451         if (!port) {
1452                 dev_err(dev, "no port node found\n");
1453                 goto err_detach_dev;
1454         }
1455         of_node_put(port);
1456
1457         dc_info = dc->hw.info;
1458
1459         for (i = 0; i < dc_info->panel_num; i++) {
1460                 crtc = vs_crtc_create(drm_dev, dc_info);
1461                 if (!crtc) {
1462                         dev_err(dev, "Failed to create CRTC.\n");
1463                         ret = -ENOMEM;
1464                         goto err_detach_dev;
1465                 }
1466
1467                 crtc->base.port = port;
1468                 crtc->dev = dev;
1469                 crtc->funcs = &dc_crtc_funcs;
1470                 dc->crtc[i] = crtc;
1471                 ctrc_mask |= drm_crtc_mask(&crtc->base);
1472         }
1473
1474         for (i = 0; i < dc_info->plane_num; i++) {
1475                 plane_info = (struct vs_plane_info *)&dc_info->planes[i];
1476
1477                 if (!strcmp(plane_info->name, "Primary") || !strcmp(plane_info->name, "Cursor")) {
1478                         plane = vs_plane_create(drm_dev, plane_info, dc_info->layer_num,
1479                                         drm_crtc_mask(&dc->crtc[0]->base));
1480                 } else if (!strcmp(plane_info->name, "Primary_1") ||
1481                                  !strcmp(plane_info->name, "Cursor_1")) {
1482                         plane = vs_plane_create(drm_dev, plane_info, dc_info->layer_num,
1483                                         drm_crtc_mask(&dc->crtc[1]->base));
1484                 } else {
1485                         plane = vs_plane_create(drm_dev, plane_info,
1486                                         dc_info->layer_num, ctrc_mask);
1487                 }
1488
1489                 if (!plane)
1490                         goto err_cleanup_planes;
1491
1492                 plane->id = i;
1493                 dc->planes[i].id = plane_info->id;
1494
1495                 plane->funcs = &dc_plane_funcs;
1496
1497                 if (plane_info->type == DRM_PLANE_TYPE_PRIMARY) {
1498                         if (!strcmp(plane_info->name, "Primary"))
1499                                 dc->crtc[0]->base.primary = &plane->base;
1500                         else
1501                                 dc->crtc[1]->base.primary = &plane->base;
1502                         drm_dev->mode_config.min_width = plane_info->min_width;
1503                         drm_dev->mode_config.min_height =
1504                                                         plane_info->min_height;
1505                         drm_dev->mode_config.max_width = plane_info->max_width;
1506                         drm_dev->mode_config.max_height =
1507                                                         plane_info->max_height;
1508                 }
1509
1510                 if (plane_info->type == DRM_PLANE_TYPE_CURSOR) {
1511                         if (!strcmp(plane_info->name, "Cursor"))
1512                                 dc->crtc[0]->base.cursor = &plane->base;
1513                         else
1514                                 dc->crtc[1]->base.cursor = &plane->base;
1515                         drm_dev->mode_config.cursor_width =
1516                                                         plane_info->max_width;
1517                         drm_dev->mode_config.cursor_height =
1518                                                         plane_info->max_height;
1519                 }
1520         }
1521
1522         dc->funcs = &dc_funcs;
1523
1524         vs_drm_update_pitch_alignment(drm_dev, dc_info->pitch_alignment);
1525
1526         return 0;
1527
1528 err_cleanup_planes:
1529         list_for_each_entry_safe(drm_plane, tmp,
1530                                  &drm_dev->mode_config.plane_list, head)
1531                 if (drm_plane->possible_crtcs & ctrc_mask)
1532                         vs_plane_destory(drm_plane);
1533
1534         drm_for_each_crtc(drm_crtc, drm_dev)
1535                 vs_crtc_destroy(drm_crtc);
1536 err_detach_dev:
1537         vs_drm_iommu_detach_device(drm_dev, dev);
1538 err_clean_dc:
1539         dc_deinit(dev);
1540         return ret;
1541 }
1542
1543 static void dc_unbind(struct device *dev, struct device *master, void *data)
1544 {
1545         struct drm_device *drm_dev = data;
1546
1547         dc_deinit(dev);
1548
1549         vs_drm_iommu_detach_device(drm_dev, dev);
1550 }
1551
1552 const struct component_ops dc_component_ops = {
1553         .bind = dc_bind,
1554         .unbind = dc_unbind,
1555 };
1556
1557 static const struct of_device_id dc_driver_dt_match[] = {
1558         { .compatible = "verisilicon,dc8200", },
1559         {},
1560 };
1561 MODULE_DEVICE_TABLE(of, dc_driver_dt_match);
1562
1563 static int dc_probe(struct platform_device *pdev)
1564 {
1565         struct device *dev = &pdev->dev;
1566         struct vs_dc *dc;
1567         int irq, ret;
1568
1569         dc = devm_kzalloc(dev, sizeof(*dc), GFP_KERNEL);
1570         if (!dc)
1571                 return -ENOMEM;
1572
1573
1574         dc->hw.hi_base = devm_platform_ioremap_resource(pdev, 0);
1575         if (IS_ERR(dc->hw.hi_base))
1576                 return PTR_ERR(dc->hw.hi_base);
1577
1578         dc->hw.reg_base = devm_platform_ioremap_resource(pdev, 1);
1579         if (IS_ERR(dc->hw.reg_base))
1580                 return PTR_ERR(dc->hw.reg_base);
1581
1582         dc->pmu_base = ioremap(0x17030000, 0x10000);
1583         if (IS_ERR(dc->pmu_base))
1584                 return PTR_ERR(dc->pmu_base);
1585
1586 #ifdef CONFIG_VERISILICON_MMU
1587         dc->hw.mmu_base = devm_platform_ioremap_resource(pdev, 2);
1588         if (IS_ERR(dc->hw.mmu_base))
1589                 return PTR_ERR(dc->hw.mmu_base);
1590 #endif
1591
1592         irq = platform_get_irq(pdev, 0);
1593         ret = devm_request_irq(dev, irq, dc_isr, 0, dev_name(dev), dc);
1594         if (ret < 0) {
1595                 dev_err(dev, "Failed to install irq:%u.\n", irq);
1596                 return ret;
1597         }
1598
1599         dev_set_drvdata(dev, dc);
1600
1601         return component_add(dev, &dc_component_ops);
1602 }
1603
1604 static int dc_remove(struct platform_device *pdev)
1605 {
1606         struct device *dev = &pdev->dev;
1607
1608         component_del(dev, &dc_component_ops);
1609
1610         dev_set_drvdata(dev, NULL);
1611
1612         return 0;
1613 }
1614
1615 struct platform_driver dc_platform_driver = {
1616         .probe = dc_probe,
1617         .remove = dc_remove,
1618         .driver = {
1619                 .name = "vs-dc",
1620                 .of_match_table = of_match_ptr(dc_driver_dt_match),
1621         },
1622 };
1623
1624 MODULE_DESCRIPTION("VeriSilicon DC Driver");
1625 MODULE_LICENSE("GPL v2");