1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 VeriSilicon Holdings Co., Ltd.
6 #include <linux/component.h>
8 #include <linux/delay.h>
9 #include <linux/media-bus-format.h>
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>
24 #include <soc/starfive/vic7100.h>
26 #if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
27 #include <drm/drm_fourcc.h>
28 #include <drm/drm_vblank.h>
32 #include <linux/regmap.h>
33 #include <linux/mfd/syscon.h>
36 static inline void update_format(u32 format, u64 mod, struct dc_hw_fb *fb)
38 u8 f = FORMAT_A8R8G8B8;
41 case DRM_FORMAT_XRGB4444:
42 case DRM_FORMAT_RGBX4444:
43 case DRM_FORMAT_XBGR4444:
44 case DRM_FORMAT_BGRX4444:
47 case DRM_FORMAT_ARGB4444:
48 case DRM_FORMAT_RGBA4444:
49 case DRM_FORMAT_ABGR4444:
50 case DRM_FORMAT_BGRA4444:
53 case DRM_FORMAT_XRGB1555:
54 case DRM_FORMAT_RGBX5551:
55 case DRM_FORMAT_XBGR1555:
56 case DRM_FORMAT_BGRX5551:
59 case DRM_FORMAT_ARGB1555:
60 case DRM_FORMAT_RGBA5551:
61 case DRM_FORMAT_ABGR1555:
62 case DRM_FORMAT_BGRA5551:
65 case DRM_FORMAT_RGB565:
66 case DRM_FORMAT_BGR565:
69 case DRM_FORMAT_XRGB8888:
70 case DRM_FORMAT_RGBX8888:
71 case DRM_FORMAT_XBGR8888:
72 case DRM_FORMAT_BGRX8888:
75 case DRM_FORMAT_ARGB8888:
76 case DRM_FORMAT_RGBA8888:
77 case DRM_FORMAT_ABGR8888:
78 case DRM_FORMAT_BGRA8888:
89 case DRM_FORMAT_YUV420:
90 case DRM_FORMAT_YVU420:
100 case DRM_FORMAT_P010:
103 case DRM_FORMAT_ARGB2101010:
104 case DRM_FORMAT_RGBA1010102:
105 case DRM_FORMAT_ABGR2101010:
106 case DRM_FORMAT_BGRA1010102:
107 f = FORMAT_A2R10G10B10;
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;
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;
130 static inline void update_swizzle(u32 format, struct dc_hw_fb *fb)
132 fb->swizzle = SWIZZLE_ARGB;
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;
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;
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;
164 case DRM_FORMAT_YVYU:
165 case DRM_FORMAT_VYUY:
166 case DRM_FORMAT_NV21:
167 case DRM_FORMAT_NV61:
175 static inline void update_watermark(struct drm_property_blob *watermark,
178 struct drm_vs_watermark *data;
183 data = watermark->data;
184 fb->water_mark = data->watermark & 0xFFFFF;
188 static inline u8 to_vs_rotation(unsigned int rotation)
192 switch (rotation & DRM_MODE_REFLECT_MASK) {
193 case DRM_MODE_REFLECT_X:
196 case DRM_MODE_REFLECT_Y:
199 case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
206 switch (rotation & DRM_MODE_ROTATE_MASK) {
207 case DRM_MODE_ROTATE_0:
210 case DRM_MODE_ROTATE_90:
213 case DRM_MODE_ROTATE_180:
216 case DRM_MODE_ROTATE_270:
227 static inline u8 to_vs_yuv_color_space(u32 color_space)
231 switch (color_space) {
232 case DRM_COLOR_YCBCR_BT601:
233 cs = COLOR_SPACE_601;
235 case DRM_COLOR_YCBCR_BT709:
236 cs = COLOR_SPACE_709;
238 case DRM_COLOR_YCBCR_BT2020:
239 cs = COLOR_SPACE_2020;
242 cs = COLOR_SPACE_601;
249 static inline u8 to_vs_tile_mode(u64 modifier)
251 return (u8)(modifier & DRM_FORMAT_MOD_VS_NORM_MODE_MASK);
254 static inline u8 to_vs_display_id(struct vs_dc *dc, struct drm_crtc *crtc)
256 u8 panel_num = dc->hw.info->panel_num;
257 u32 index = drm_crtc_index(crtc);
260 for (i = 0; i < panel_num; i++) {
261 if (index == dc->crtc[i]->base.index)
268 static int plda_clk_rst_init(struct device *dev)
271 struct vs_dc *dc = dev_get_drvdata(dev);
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");
279 ret = clk_bulk_prepare_enable(dc->num_clks, dc->clks);
281 dev_err(dev, "failed to enable clocks\n");
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");
291 ret = reset_control_deassert(dc->resets);
295 clk_bulk_disable_unprepare(dc->num_clks, dc->clks);
300 static void plda_clk_rst_deinit(struct device *dev)
302 struct vs_dc *dc = dev_get_drvdata(dev);
304 reset_control_assert(dc->resets);
305 clk_bulk_disable_unprepare(dc->num_clks, dc->clks);
310 static int vs_dc_get_clock(struct device *dev, struct vs_dc *dc)
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);
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);
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);
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);
338 static int vs_dc_clock_enable(struct device *dev, struct vs_dc *dc)
341 /*clk_prepare_enable(dc->sys_clk);*/
342 ret = clk_prepare_enable(dc->cpu_axi);
344 dev_err(dev, "failed to prepare/enable cpu_axi\n");
347 ret = clk_prepare_enable(dc->axicfg0_axi);
349 dev_err(dev, "failed to prepare/enable axicfg0_axi\n");
352 ret = clk_prepare_enable(dc->disp_axi);
354 dev_err(dev, "failed to prepare/enable disp_axi\n");
357 ret = clk_prepare_enable(dc->stg_axi);
359 dev_err(dev, "failed to prepare/enable stg_axi\n");
366 static void vs_dc_clock_disable(struct vs_dc *dc)
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);
374 static int vs_dc_vouttop_get_clock(struct device *dev, struct vs_dc *dc)
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);
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);
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);
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);
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);
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);
415 static int vs_dc_vouttop_clock_enable(struct device *dev, struct vs_dc *dc)
418 /*clk_prepare_enable(dc->sys_clk);*/
419 ret = clk_prepare_enable(dc->vout_src);
421 dev_err(dev, "failed to prepare/enable vout_src\n");
424 ret = clk_prepare_enable(dc->vout_axi);
426 dev_err(dev, "failed to prepare/enable vout_axi\n");
429 ret = clk_prepare_enable(dc->ahb1);
431 dev_err(dev, "failed to prepare/enable ahb1\n");
434 ret = clk_prepare_enable(dc->hdmitx0_mclk);
436 dev_err(dev, "failed to prepare/enable hdmitx0_mclk\n");
439 ret = clk_prepare_enable(dc->bclk_mst);
441 dev_err(dev, "failed to prepare/enable bclk_mst\n");
447 static void vs_dc_vouttop_clock_disable(struct vs_dc *dc)
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);
456 static int vs_dc_dc8200_get_clock(struct device *dev, struct vs_dc *dc)
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);
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);
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);
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);
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);
490 static int vs_dc_dc8200_clock_enable(struct device *dev, struct vs_dc *dc)
493 /*clk_prepare_enable(dc->sys_clk);*/
494 ret = clk_prepare_enable(dc->dc8200_clk_pix0);
496 dev_err(dev, "failed to prepare/enable dc8200_clk_pix0\n");
499 ret = clk_prepare_enable(dc->dc8200_clk_pix1);
501 dev_err(dev, "failed to prepare/enable dc8200_clk_pix1\n");
504 ret = clk_prepare_enable(dc->dc8200_axi);
506 dev_err(dev, "failed to prepare/enable dc8200_axi\n");
509 ret = clk_prepare_enable(dc->dc8200_core);
511 dev_err(dev, "failed to prepare/enable dc8200_core\n");
514 ret = clk_prepare_enable(dc->dc8200_ahb);
516 dev_err(dev, "failed to prepare/enable dc8200_ahb\n");
523 static void vs_dc_dc8200_clock_disable(struct vs_dc *dc)
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);
532 static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc)
535 ret = vs_dc_get_clock(dev, dc);
537 dev_err(dev, "failed to get clock\n");
541 ret = vs_dc_clock_enable(dev, dc);
543 dev_err(dev, "failed to enable clock\n");
547 ret = vs_dc_vouttop_get_clock(dev, dc);
549 dev_err(dev, "failed to get clock\n");
553 ret = vs_dc_vouttop_clock_enable(dev, dc);
555 dev_err(dev, "failed to enable clock\n");
559 ret = vs_dc_dc8200_get_clock(dev, dc);
561 dev_err(dev, "failed to get clock\n");
565 ret = vs_dc_dc8200_clock_enable(dev, dc);
567 dev_err(dev, "failed to enable clock\n");
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");
577 ret = reset_control_deassert(dc->vout_resets);
579 dev_err(dev, "deassert error.\n");
587 static int syscon_panel_parse_dt(struct device *dev)
589 struct vs_dc *dc = dev_get_drvdata(dev);
592 dc->dss_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
593 "verisilicon,dss-syscon");
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);
601 dc->dss_regmap = NULL;
609 int sys_dispctrl_clk_standard(struct vs_dc *dc, struct device *dev)
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);
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);
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);
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);
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);
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);
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);
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);
662 static void dc_deinit(struct device *dev)
664 struct vs_dc *dc = dev_get_drvdata(dev);
665 struct platform_device *pdev = to_platform_device(dev);
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);
674 dev_err(dev, "assert vout resets error.\n");
676 pm_runtime_put_sync(&pdev->dev);
677 pm_runtime_disable(&pdev->dev);
681 ///////////////////////////////////////////////////////////
682 static int dc_init(struct device *dev)
684 struct vs_dc *dc = dev_get_drvdata(dev);
685 struct platform_device *pdev = to_platform_device(dev);
688 dc->first_frame = true;
690 ret = syscon_panel_parse_dt(dev);
692 dev_err(dev,"syscon_panel_parse_dt failed\n");
696 pm_runtime_enable(&pdev->dev);
697 ret = pm_runtime_get_sync(&pdev->dev);
699 dev_err(&pdev->dev, "dc_init: failed to get pm runtime: %d\n", ret);
703 ret = dc_vout_clk_rst_init(dev, dc);
705 ret = sys_dispctrl_clk_standard(dc, dev);
707 #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi
708 regmap_update_bits(dc->dss_regmap, 0x4, BIT(20), 1<<20);
711 #ifdef CONFIG_STARFIVE_DSI
712 regmap_update_bits(dc->dss_regmap, 0x8, BIT(3), 1<<3);
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);
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);
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);
733 ret = clk_set_parent(dc->vout_top_lcd, dc->dc8200_clk_pix1_out);
735 ret = clk_prepare_enable(dc->vout_top_lcd);
737 dev_err(dev, "failed to prepare/enable vout_top_lcd\n");
741 ret = dc_hw_init(&dc->hw);
743 dev_err(dev, "failed to init DC HW\n");
751 static void vs_dc_dump_enable(struct device *dev, dma_addr_t addr,
754 struct vs_dc *dc = dev_get_drvdata(dev);
756 dc_hw_enable_dump(&dc->hw, addr, pitch);
759 static void vs_dc_dump_disable(struct device *dev)
761 struct vs_dc *dc = dev_get_drvdata(dev);
763 dc_hw_disable_dump(&dc->hw);
766 static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc)
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;
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;
781 display.h_sync_polarity = false;
783 display.v_active = mode->vdisplay;
784 display.v_total = mode->vtotal;
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;
790 display.v_sync_start = mode->vsync_start;
791 display.v_sync_end = mode->vsync_end;
794 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
795 display.v_sync_polarity = true;
797 display.v_sync_polarity = false;
799 display.sync_mode = crtc_state->sync_mode;
800 display.bg_color = crtc_state->bg_color;
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;
806 display.enable = true;
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;
814 clk_set_parent(dc->dc8200_clk_pix1, dc->dc8200_pix0 );//child,parent
816 dc_hw_set_out(&dc->hw, OUT_DPI, display.id);
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;
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);
828 #ifdef CONFIG_VERISILICON_MMU
829 if (crtc_state->mmu_prefetch == VS_MMU_PREFETCH_ENABLE)
830 dc_hw_enable_mmu_prefetch(&dc->hw, true);
832 dc_hw_enable_mmu_prefetch(&dc->hw, false);
835 dc_hw_setup_display(&dc->hw, &display);
838 static void vs_dc_disable(struct device *dev, struct drm_crtc *crtc)
840 struct vs_dc *dc = dev_get_drvdata(dev);
841 struct dc_hw_display display;
843 display.id = to_vs_display_id(dc, crtc);
844 display.enable = false;
846 dc_hw_setup_display(&dc->hw, &display);
849 static bool vs_dc_mode_fixup(struct device *dev,
850 const struct drm_display_mode *mode,
851 struct drm_display_mode *adjusted_mode)
855 ;//printk("====> %s, %d--pix_clk.\n", __func__, __LINE__);
857 struct vs_dc *dc = dev_get_drvdata(dev);
861 clk_rate = clk_round_rate(dc->pix_clk,
862 adjusted_mode->clock * 1000);
863 adjusted_mode->clock = DIV_ROUND_UP(clk_rate, 1000);
870 static void vs_dc_set_gamma(struct device *dev, struct drm_crtc *crtc,
871 struct drm_color_lut *lut, unsigned int size)
873 struct vs_dc *dc = dev_get_drvdata(dev);
877 if (size != dc->hw.info->gamma_size) {
878 dev_err(dev, "gamma size does not match!\n");
882 id = to_vs_display_id(dc, crtc);
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);
893 static void vs_dc_enable_gamma(struct device *dev, struct drm_crtc *crtc,
896 struct vs_dc *dc = dev_get_drvdata(dev);
899 id = to_vs_display_id(dc, crtc);
900 dc_hw_enable_gamma(&dc->hw, id, enable);
903 static void vs_dc_enable_vblank(struct device *dev, bool enable)
905 struct vs_dc *dc = dev_get_drvdata(dev);
907 dc_hw_enable_interrupt(&dc->hw, enable);
910 static u32 calc_factor(u32 src, u32 dest)
912 u32 factor = 1 << 16;
914 if ((src > 1) && (dest > 1))
915 factor = ((src - 1) << 16) / (dest - 1);
920 static void update_scale(struct drm_plane_state *state, struct dc_hw_roi *roi,
921 struct dc_hw_scale *scale)
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;
927 scale->enable = false;
933 src_w = drm_rect_width(&state->src) >> 16;
934 src_h = drm_rect_height(&state->src) >> 16;
937 if (drm_rotation_90_or_270(state->rotation)) {
943 if (src_w != dst_w) {
944 scale->scale_factor_x = calc_factor(src_w, dst_w);
945 scale->enable = true;
947 scale->scale_factor_x = 1 << 16;
949 if (src_h != dst_h) {
950 scale->scale_factor_y = calc_factor(src_h, dst_h);
951 scale->enable = true;
953 scale->scale_factor_y = 1 << 16;
957 static void update_fb(struct vs_plane *plane, u8 display_id,
958 struct dc_hw_fb *fb, struct drm_plane_state *state)
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;
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];
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];
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);
991 starfive_flush_dcache(fb->y_address, fb->height * fb->y_stride);
993 starfive_flush_dcache(fb->u_address, fb->height * fb->u_stride);
995 starfive_flush_dcache(fb->v_address, fb->height * fb->v_stride);
997 plane_state->status.tile_mode = fb->tile_mode;
1000 #ifdef CONFIG_VERISILICON_DEC
1001 static u8 get_stream_base(u8 id)
1006 case OVERLAY_PLANE_0:
1009 case OVERLAY_PLANE_1:
1012 case PRIMARY_PLANE_1:
1015 case OVERLAY_PLANE_2:
1018 case OVERLAY_PLANE_3:
1028 static void update_fbc(struct vs_dc *dc, struct vs_plane *plane, bool *enable,
1029 struct drm_plane_state *state)
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];
1037 if (!dc->hw.info->cap_dec) {
1042 stream_id = get_stream_base(dc_plane->id);
1043 memset(&dec_fb, 0, sizeof(struct dc_dec_fb));
1046 if (fourcc_mod_vs_get_type(drm_fb->modifier) !=
1047 DRM_FORMAT_MOD_VS_TYPE_COMPRESSED) {
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];
1058 dc_dec_config(&dc->dec400l, &dec_fb, stream_id);
1061 static void disable_fbc(struct vs_dc *dc, struct vs_plane *plane)
1063 struct vs_dc_plane *dc_plane = &dc->planes[plane->id];
1066 if (!dc->hw.info->cap_dec)
1069 stream_id = get_stream_base(dc_plane->id);
1070 dc_dec_config(&dc->dec400l, NULL, stream_id);
1074 static void update_degamma(struct vs_dc *dc, struct vs_plane *plane,
1075 struct vs_plane_state *plane_state)
1077 dc_hw_update_degamma(&dc->hw, plane->id, plane_state->degamma);
1078 plane_state->degamma_changed = false;
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)
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;
1092 if (plane_state->roi) {
1093 data = plane_state->roi->data;
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;
1104 roi->enable = false;
1107 dc_hw_update_roi(&dc->hw, id, roi);
1109 roi->enable = false;
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)
1117 struct drm_vs_color_mgmt *data;
1118 struct dc_hw_colorkey colorkey;
1120 if (plane_state->color_mgmt) {
1121 data = plane_state->color_mgmt->data;
1123 fb->clear_enable = data->clear_enable;
1124 fb->clear_value = data->clear_value;
1126 if (data->colorkey > data->colorkey_high)
1127 data->colorkey = data->colorkey_high;
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);
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)
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,
1148 struct vs_plane_state *plane_state = to_vs_plane_state(state);
1149 struct drm_rect *dest = &state->dst;
1150 bool dec_enable = false;
1153 #ifdef CONFIG_VERISILICON_DEC
1154 update_fbc(dc, plane, &dec_enable, state);
1157 display_id = to_vs_display_id(dc, state->crtc);
1158 update_fb(plane, display_id, &fb, state);
1159 fb.dec_enable = dec_enable;
1162 update_roi(dc, plane->id, plane_state, &roi, state);
1164 update_scale(state, &roi, &scale);
1166 if (plane_state->degamma_changed)
1167 update_degamma(dc, plane, plane_state);
1169 pos.start_x = dest->x1;
1170 pos.start_y = dest->y1;
1171 pos.end_x = dest->x2;
1172 pos.end_y = dest->y2;
1174 blend.alpha = (u8)(state->alpha >> 8);
1175 blend.blend_mode = (u8)(state->pixel_blend_mode);
1177 update_color_mgmt(dc, plane->id, &fb, plane_state);
1179 dc_hw_update_plane(&dc->hw, plane->id, &fb, &scale, &pos, &blend);
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)
1185 //struct drm_plane_state *state = plane->base.state;
1186 struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state,
1188 struct vs_plane_state *plane_state = to_vs_plane_state(state);
1189 struct drm_vs_watermark *data;
1190 struct dc_hw_qos qos;
1192 if (plane_state->watermark) {
1193 data = plane_state->watermark->data;
1195 if (data->qos_high) {
1196 if (data->qos_low > data->qos_high)
1197 data->qos_low = data->qos_high;
1199 qos.low_value = data->qos_low & 0x0F;
1200 qos.high_value = data->qos_high & 0x0F;
1201 dc_hw_update_qos(&dc->hw, &qos);
1206 static void update_cursor_size(struct drm_plane_state *state, struct dc_hw_cursor *cursor)
1210 switch (state->crtc_w) {
1212 size_type = CURSOR_SIZE_32X32;
1215 size_type = CURSOR_SIZE_64X64;
1218 size_type = CURSOR_SIZE_32X32;
1222 cursor->size = size_type;
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)
1228 //struct drm_plane_state *state = plane->base.state;
1229 struct drm_plane_state *state = drm_atomic_get_new_plane_state(drm_state,
1231 struct drm_framebuffer *drm_fb = state->fb;
1232 struct dc_hw_cursor cursor;
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;
1243 dc_hw_update_cursor(&dc->hw, cursor.display_id, &cursor);
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)
1249 struct vs_dc *dc = dev_get_drvdata(dev);
1250 enum drm_plane_type type = plane->base.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);
1258 case DRM_PLANE_TYPE_CURSOR:
1259 update_cursor_plane(dc, plane, drm_plane, drm_state);
1266 static void vs_dc_disable_plane(struct device *dev, struct vs_plane *plane,
1267 struct drm_plane_state *old_state)
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};
1275 case DRM_PLANE_TYPE_PRIMARY:
1276 case DRM_PLANE_TYPE_OVERLAY:
1278 dc_hw_update_plane(&dc->hw, plane->id, &fb, NULL, NULL, NULL);
1279 #ifdef CONFIG_VERISILICON_DEC
1280 disable_fbc(dc, plane);
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);
1293 static bool vs_dc_mod_supported(const struct vs_plane_info *plane_info,
1298 if (plane_info->modifiers == NULL)
1301 for (mods = plane_info->modifiers; *mods != DRM_FORMAT_MOD_INVALID; mods++) {
1302 if (*mods == modifier)
1309 static int vs_dc_check_plane(struct device *dev, struct drm_plane *plane,
1310 struct drm_atomic_state *state)
1312 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
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);
1321 plane_info = &dc->hw.info->planes[vs_plane->id];
1322 if (plane_info == NULL)
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",
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);
1338 crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
1339 if (IS_ERR(crtc_state))
1342 return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
1343 plane_info->min_scale,
1344 plane_info->max_scale,
1348 static irqreturn_t dc_isr(int irq, void *data)
1350 struct vs_dc *dc = data;
1351 struct vs_dc_info *dc_info = dc->hw.info;
1354 ret = dc_hw_get_interrupt(&dc->hw);
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));
1362 static void vs_dc_commit(struct device *dev)
1364 struct vs_dc *dc = dev_get_drvdata(dev);
1366 #ifdef CONFIG_VERISILICON_DEC
1367 if (dc->hw.info->cap_dec)
1368 dc_dec_commit(&dc->dec400l, &dc->hw);
1371 dc_hw_enable_shadow_register(&dc->hw, false);
1373 dc_hw_commit(&dc->hw);
1375 if (dc->first_frame)
1376 dc->first_frame = false;
1378 dc_hw_enable_shadow_register(&dc->hw, true);
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,
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,
1397 static const struct vs_dc_funcs dc_funcs = {
1398 .dump_enable = vs_dc_dump_enable,
1399 .dump_disable = vs_dc_dump_disable,
1402 static int dc_bind(struct device *dev, struct device *master, void *data)
1404 struct drm_device *drm_dev = data;
1405 #ifdef CONFIG_VERISILICON_MMU
1406 struct vs_drm_private *priv = drm_dev->dev_private;
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;
1419 if (!drm_dev || !dc) {
1420 dev_err(dev, "devices are not created.\n");
1426 dev_err(dev, "Failed to initialize DC hardware.\n");
1430 #ifdef CONFIG_VERISILICON_MMU
1431 ret = dc_mmu_construct(priv->dma_dev, &priv->mmu);
1433 dev_err(dev, "failed to construct DC MMU\n");
1437 ret = dc_hw_mmu_init(&dc->hw, priv->mmu);
1439 dev_err(dev, "failed to init DC MMU\n");
1444 ret = vs_drm_iommu_attach_device(drm_dev, dev);
1446 dev_err(dev, "Failed to attached iommu device.\n");
1450 port = of_get_child_by_name(dev->of_node, "port");
1452 dev_err(dev, "no port node found\n");
1453 goto err_detach_dev;
1457 dc_info = dc->hw.info;
1459 for (i = 0; i < dc_info->panel_num; i++) {
1460 crtc = vs_crtc_create(drm_dev, dc_info);
1462 dev_err(dev, "Failed to create CRTC.\n");
1464 goto err_detach_dev;
1467 crtc->base.port = port;
1469 crtc->funcs = &dc_crtc_funcs;
1471 ctrc_mask |= drm_crtc_mask(&crtc->base);
1474 for (i = 0; i < dc_info->plane_num; i++) {
1475 plane_info = (struct vs_plane_info *)&dc_info->planes[i];
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));
1485 plane = vs_plane_create(drm_dev, plane_info,
1486 dc_info->layer_num, ctrc_mask);
1490 goto err_cleanup_planes;
1493 dc->planes[i].id = plane_info->id;
1495 plane->funcs = &dc_plane_funcs;
1497 if (plane_info->type == DRM_PLANE_TYPE_PRIMARY) {
1498 if (!strcmp(plane_info->name, "Primary"))
1499 dc->crtc[0]->base.primary = &plane->base;
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;
1510 if (plane_info->type == DRM_PLANE_TYPE_CURSOR) {
1511 if (!strcmp(plane_info->name, "Cursor"))
1512 dc->crtc[0]->base.cursor = &plane->base;
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;
1522 dc->funcs = &dc_funcs;
1524 vs_drm_update_pitch_alignment(drm_dev, dc_info->pitch_alignment);
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);
1534 drm_for_each_crtc(drm_crtc, drm_dev)
1535 vs_crtc_destroy(drm_crtc);
1537 vs_drm_iommu_detach_device(drm_dev, dev);
1543 static void dc_unbind(struct device *dev, struct device *master, void *data)
1545 struct drm_device *drm_dev = data;
1549 vs_drm_iommu_detach_device(drm_dev, dev);
1552 const struct component_ops dc_component_ops = {
1554 .unbind = dc_unbind,
1557 static const struct of_device_id dc_driver_dt_match[] = {
1558 { .compatible = "verisilicon,dc8200", },
1561 MODULE_DEVICE_TABLE(of, dc_driver_dt_match);
1563 static int dc_probe(struct platform_device *pdev)
1565 struct device *dev = &pdev->dev;
1569 dc = devm_kzalloc(dev, sizeof(*dc), GFP_KERNEL);
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);
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);
1582 dc->pmu_base = ioremap(0x17030000, 0x10000);
1583 if (IS_ERR(dc->pmu_base))
1584 return PTR_ERR(dc->pmu_base);
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);
1592 irq = platform_get_irq(pdev, 0);
1593 ret = devm_request_irq(dev, irq, dc_isr, 0, dev_name(dev), dc);
1595 dev_err(dev, "Failed to install irq:%u.\n", irq);
1599 dev_set_drvdata(dev, dc);
1601 return component_add(dev, &dc_component_ops);
1604 static int dc_remove(struct platform_device *pdev)
1606 struct device *dev = &pdev->dev;
1608 component_del(dev, &dc_component_ops);
1610 dev_set_drvdata(dev, NULL);
1615 struct platform_driver dc_platform_driver = {
1617 .remove = dc_remove,
1620 .of_match_table = of_match_ptr(dc_driver_dt_match),
1624 MODULE_DESCRIPTION("VeriSilicon DC Driver");
1625 MODULE_LICENSE("GPL v2");