riscv:driver:drm:DC8200
authorkeith.zhao <keith.zhao@starfivetech.com>
Fri, 24 Jun 2022 13:51:16 +0000 (21:51 +0800)
committerkeith.zhao <keith.zhao@starfivetech.com>
Mon, 27 Jun 2022 08:41:45 +0000 (16:41 +0800)
1、support 1080P 720P 480P display mode
2、replace some FW interface by using system api

Signed-off-by:keith.zhao <keith.zhao@statfivetech.com>

drivers/gpu/drm/verisilicon/inno_hdmi.c [changed mode: 0644->0755]
drivers/gpu/drm/verisilicon/inno_hdmi.h [changed mode: 0644->0755]
drivers/gpu/drm/verisilicon/vs_dc.c [changed mode: 0644->0755]
drivers/gpu/drm/verisilicon/vs_dc.h [changed mode: 0644->0755]
drivers/gpu/drm/verisilicon/vs_drv.c [changed mode: 0644->0755]
drivers/gpu/drm/verisilicon/vs_simple_enc.c [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 40fe808..9544c8a
@@ -17,6 +17,7 @@
 #include <linux/component.h>
 #include<linux/reset.h>
 
+#include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
@@ -77,6 +78,8 @@ struct inno_hdmi {
        struct drm_display_mode previous_mode;
        struct regulator *hdmi_1p8;
        struct regulator *hdmi_0p9;
+       struct pre_pll_config   *pre_cfg;
+       struct post_pll_config  *post_cfg;
 };
 
 enum {
@@ -88,6 +91,59 @@ enum {
        CSC_RGB_0_255_TO_RGB_16_235_8BIT,
 };
 
+static const struct pre_pll_config pre_pll_cfg_table[] = {
+       { 25200000,  25200000, 1,  100, 2, 3, 3, 12, 3, 3, 4, 0, 0},
+       { 27000000,  27000000, 1,  90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
+       { 27000000,  33750000, 1,  90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
+       { 40000000,  40000000, 1,  80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
+       { 59341000,  59341000, 1,  98, 3, 1, 2,  1, 3, 3, 4, 0, 0xE6AE6B},
+       { 59400000,  59400000, 1,  99, 3, 1, 1,  1, 3, 3, 4, 0, 0},
+       { 59341000,  74176250, 1,  98, 0, 3, 3,  1, 3, 3, 4, 0, 0xE6AE6B},
+       { 59400000,  74250000, 1,  99, 1, 2, 2,  1, 3, 3, 4, 0, 0},
+       { 74176000,  74176000, 1,  98, 1, 2, 2,  1, 2, 3, 4, 0, 0xE6AE6B},
+       { 74250000,  74250000, 1,  99, 1, 2, 2,  1, 2, 3, 4, 0, 0},
+       { 74176000,  92720000, 4, 494, 1, 2, 2,  1, 3, 3, 4, 0, 0x816817},
+       { 74250000,  92812500, 4, 495, 1, 2, 2,  1, 3, 3, 4, 0, 0},
+       {148352000, 148352000, 1,  98, 1, 1, 1,  1, 2, 2, 2, 0, 0xE6AE6B},
+       {148500000, 148500000, 1,  99, 1, 1, 1,  1, 2, 2, 2, 0, 0},
+       {148352000, 185440000, 4, 494, 0, 2, 2,  1, 3, 2, 2, 0, 0x816817},
+       {148500000, 185625000, 4, 495, 0, 2, 2,  1, 3, 2, 2, 0, 0},
+       {296703000, 296703000, 1,  98, 0, 1, 1,  1, 0, 2, 2, 0, 0xE6AE6B},
+       {297000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2, 2, 0, 0},
+       {296703000, 370878750, 4, 494, 1, 2, 0,  1, 3, 1, 1, 0, 0x816817},
+       {297000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1, 1, 0, 0},
+       {593407000, 296703500, 1,  98, 0, 1, 1,  1, 0, 2, 1, 0, 0xE6AE6B},
+       {594000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2, 1, 0, 0},
+       {593407000, 370879375, 4, 494, 1, 2, 0,  1, 3, 1, 1, 1, 0x816817},
+       {594000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1, 1, 1, 0},
+       {593407000, 593407000, 1,  98, 0, 2, 0,  1, 0, 1, 1, 0, 0xE6AE6B},
+       {594000000, 594000000, 1,  99, 0, 2, 0,  1, 0, 1, 1, 0, 0},
+       { /* sentinel */ }
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+       {25200000,      1, 80, 7, 0,1},
+       {27000000,      1, 40, 3, 0,1},
+       {33750000,      1, 40, 8, 3,1},
+       //{33750000,    1, 80, 8, 2},
+       {74250000,      1, 20, 1, 3,1},
+       //{74250000, 18, 80, 8, 2},
+       {148500000, 1, 20, 1, 3,3},
+       {297000000, 2, 20, 0, 3,3},
+       {594000000, 4, 20, 0, 0,0},//postpll_postdiv_en = 0
+       { /* sentinel */ }
+};
+/*
+static const struct post_pll_config post_pll_cfg_table[] = {
+       {33750000,  1, 40, 8, 1},
+       {33750000,  1, 80, 8, 2},
+       {74250000,  1, 40, 8, 1},
+       {74250000, 18, 80, 8, 2},
+       {148500000, 2, 40, 4, 3},
+       {297000000, 4, 40, 2, 3},
+       {594000000, 8, 40, 1, 3},
+};
+*/
 static const char coeff_csc[][24] = {
        /*
         * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
@@ -202,9 +258,6 @@ static void inno_hdmi_power_up(struct inno_hdmi *hdmi)
        val &= ~(0x1);
        writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04);
 
-       /*wait for pre-PLL and post-PLL lock*/
-       //while(!(hdmi_read(word_align(0x1a9)) & 0x1));
-       //while(!(hdmi_read(word_align(0x1af)) & 0x1));
        while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1))
        ;
        while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1))
@@ -222,42 +275,43 @@ static void inno_hdmi_tx_phy_power_down(struct inno_hdmi *hdmi)
        writel_relaxed(0x63, hdmi->regs + (0x00) * 0x04);
 }
 
-typedef struct register_value {
-       u16 reg;
-       u8 value;
-} reg_value_t;
-
-#if 0
-static void inno_hdmi_config_640x480p60(struct inno_hdmi *hdmi)
+static void inno_hdmi_config_pll(struct inno_hdmi *hdmi)
 {
+       u8 reg_1ad_value = hdmi->post_cfg->post_div_en ?
+                hdmi->post_cfg->postdiv : 0x0d;
        const reg_value_t cfg_pll_data[] = {
-               /* config pll: 640x480p, 60hz*/
                {0x1a0, 0x01},
-               //{0x1aa, 0x0f},
-               {0x1a1, 0x01},
-               {0x1a2, 0xf0},
-               {0x1a3, 0x64},
-               {0x1a4, 0x2f},
-               //{0x1a4, 0x2a},
-               {0x1a5, 0x6c},
-               {0x1a6, 0x64},
-               {0x1ab, 0x01},
-               {0x1ac, 0x50},
-               //{0x1ad, 0x07},
-               {0x1ad, 0x0d},
+               {0x1aa, 0x0f},
+               {0x1a1, hdmi->pre_cfg->prediv},
+               {0x1a2, 0xf0 | hdmi->pre_cfg->fbdiv>>8},
+               {0x1a3, hdmi->pre_cfg->fbdiv},
+               {0x1a4, ((hdmi->pre_cfg->tmds_div_a << 4) | (hdmi->pre_cfg->tmds_div_b << 2) | (hdmi->pre_cfg->tmds_div_c))},
+               {0x1a5, (hdmi->pre_cfg->pclk_div_b << 5) | hdmi->pre_cfg->pclk_div_a},
+               {0x1a6, (hdmi->pre_cfg->pclk_div_c << 5) | hdmi->pre_cfg->pclk_div_d},
+               {0x1ab, hdmi->post_cfg->prediv},
+               {0x1ac, hdmi->post_cfg->fbdiv & 0xff},
+               {0x1ad, reg_1ad_value},
                {0x1aa, 0x0e},
                {0x1a0, 0x00},
        };
 
        int i;
-
-       for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++) {
-               //hdmi_write(cfg_pll_data[i].value, word_align(cfg_pll_data[i].reg));
+       for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++)
+       {
+               /*
+               if(0x1ad == cfg_pll_data[i].reg)
+               {
+                       if(0 == hdmi->post_cfg->post_div_en)
+                       {
+                               writel_relaxed(0x0d, hdmi->regs + (cfg_pll_data[i].reg) * 0x04);
+                               continue;
+                       }
+               }*/
+               dev_info(hdmi->dev, "%s %d reg[%02x],val[%02x]\n",__func__, __LINE__,cfg_pll_data[i].reg,cfg_pll_data[i].value);
                writel_relaxed(cfg_pll_data[i].value, hdmi->regs + (cfg_pll_data[i].reg) * 0x04);
        }
        return;
 }
-#endif
 
 static void inno_hdmi_config_1920x1080p60(struct inno_hdmi *hdmi)
 {
@@ -599,11 +653,244 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
        return 0;
 }
 
+ static const
+ struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi *hdmi,
+                                                         unsigned long rate)
+ {
+        const struct pre_pll_config *cfg = pre_pll_cfg_table;
+        //unsigned long tmdsclock = 148500000;
+       rate = (rate / 1000) * 1000;
+
+        for (; cfg->pixclock != 0; cfg++)
+                if (cfg->pixclock == rate)
+                        break;
+
+        if (cfg->pixclock == 0)
+                return ERR_PTR(-EINVAL);
+
+        return cfg;
+ }
+
+#define PRE_PLL_POWER_DOWN                     BIT(0)
+
+ /* phy tuning values for an undocumented set of registers */
+ static const struct phy_config inno_phy_cfg[] = {
+        {       165000000, {
+                        0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
+                        0x00, 0xac, 0xcc, 0xcc, 0xcc,
+                },
+        }, {
+                340000000, {
+                        0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
+                        0x3f, 0xac, 0xcc, 0xcd, 0xdd,
+                },
+        }, {
+                594000000, {
+                        0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
+                        0x00, 0xac, 0xcc, 0xcc, 0xcc,
+                },
+        }, { /* sentinel */ },
+ };
+
+ static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi *hdmi,unsigned long rate)
+ {
+       hdmi->post_cfg = post_pll_cfg_table;
+       unsigned long tmdsclock = hdmi->tmds_rate;
+       u32 v;
+       int ret;
+
+       dev_info(hdmi->dev, "%s rate %lu tmdsclk %lu\n",__func__, rate, tmdsclock);
+
+       hdmi->pre_cfg = inno_hdmi_phy_get_pre_pll_cfg(hdmi, tmdsclock);
+       if (IS_ERR(hdmi->pre_cfg))
+       return PTR_ERR(hdmi->pre_cfg);
+
+       for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++)
+               if (tmdsclock <= hdmi->post_cfg->tmdsclock && hdmi->post_cfg->version)
+                       break;
+
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->pixclock = %lu\n",__func__, hdmi->pre_cfg->pixclock);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmdsclock = %lu\n",__func__, hdmi->pre_cfg->tmdsclock);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->prediv = %d\n",__func__, hdmi->pre_cfg->prediv);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->fbdiv = %d\n",__func__, hdmi->pre_cfg->fbdiv);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_a = %d\n",__func__, hdmi->pre_cfg->tmds_div_a);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_b = %d\n",__func__, hdmi->pre_cfg->tmds_div_b);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_c = %d\n",__func__, hdmi->pre_cfg->tmds_div_c);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_a = %d\n",__func__, hdmi->pre_cfg->pclk_div_a);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_b = %d\n",__func__, hdmi->pre_cfg->pclk_div_b);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_c = %d\n",__func__, hdmi->pre_cfg->pclk_div_c);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_d = %d\n",__func__, hdmi->pre_cfg->pclk_div_d);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->vco_div_5_en = %d\n",__func__, hdmi->pre_cfg->vco_div_5_en);
+       dev_info(hdmi->dev, "%s hdmi->pre_cfg->fracdiv = %d\n",__func__, hdmi->pre_cfg->fracdiv);
+
+
+       dev_info(hdmi->dev, "*******************************************************\n");
+
+       dev_info(hdmi->dev, "%s hdmi->post_cfg->tmdsclock = %lu\n",__func__, hdmi->post_cfg->tmdsclock);
+       dev_info(hdmi->dev, "%s hdmi->post_cfg->prediv = %d\n",__func__, hdmi->post_cfg->prediv);
+       dev_info(hdmi->dev, "%s hdmi->post_cfg->fbdiv = %d\n",__func__, hdmi->post_cfg->fbdiv);
+       dev_info(hdmi->dev, "%s hdmi->post_cfg->postdiv = %d\n",__func__, hdmi->post_cfg->postdiv);
+       dev_info(hdmi->dev, "%s hdmi->post_cfg->post_div_en = %d\n",__func__, hdmi->post_cfg->post_div_en);
+       dev_info(hdmi->dev, "%s hdmi->post_cfg->version = %d\n",__func__, hdmi->post_cfg->version);
+
+       inno_hdmi_config_pll(hdmi);
+       //1920x1080p60
+       //inno_hdmi_tx_ctrl(hdmi);
+
+#if 0 //pre pll + post pll configire
+
+       /*pre-pll power down*/
+       hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, INNO_PRE_PLL_POWER_DOWN);
+
+       /* Configure pre-pll */
+       hdmi_modb(hdmi, 0x1a0, INNO_PCLK_VCO_DIV_5_MASK, INNO_PCLK_VCO_DIV_5(hdmi->pre_cfg->vco_div_5_en));
+       hdmi_writeb(hdmi, 0x1a1, INNO_PRE_PLL_PRE_DIV(hdmi->pre_cfg->prediv));
+
+       u32 val;
+       val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
+       if (!hdmi->pre_cfg->fracdiv)
+               val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
+       hdmi_writeb(hdmi, 0x1a2, INNO_PRE_PLL_FB_DIV_11_8(hdmi->pre_cfg->fbdiv | val));
+
+       hdmi_writeb(hdmi, 0x1a3, INNO_PRE_PLL_FB_DIV_7_0(hdmi->pre_cfg->fbdiv));
+
+       hdmi_writeb(hdmi, 0x1a5, INNO_PRE_PLL_PCLK_DIV_A(hdmi->pre_cfg->pclk_div_a) |
+                       INNO_PRE_PLL_PCLK_DIV_B(hdmi->pre_cfg->pclk_div_b));
+
+       hdmi_writeb(hdmi, 0x1a6, INNO_PRE_PLL_PCLK_DIV_C(hdmi->pre_cfg->pclk_div_c) |
+                       INNO_PRE_PLL_PCLK_DIV_D(hdmi->pre_cfg->pclk_div_d));
+
+       hdmi_writeb(hdmi, 0x1a4, INNO_PRE_PLL_TMDSCLK_DIV_C(hdmi->pre_cfg->tmds_div_c) |
+                       INNO_PRE_PLL_TMDSCLK_DIV_A(hdmi->pre_cfg->tmds_div_a) |
+                       INNO_PRE_PLL_TMDSCLK_DIV_B(hdmi->pre_cfg->tmds_div_b));
+
+       hdmi_writeb(hdmi, 0x1d3, INNO_PRE_PLL_FRAC_DIV_7_0(hdmi->pre_cfg->fracdiv));
+       hdmi_writeb(hdmi, 0x1d2, INNO_PRE_PLL_FRAC_DIV_15_8(hdmi->pre_cfg->fracdiv));
+       hdmi_writeb(hdmi, 0x1d1, INNO_PRE_PLL_FRAC_DIV_23_16(hdmi->pre_cfg->fracdiv));
+
+       /*pre-pll power down*/
+       hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, 0);
+
+       const struct phy_config *phy_cfg = inno_phy_cfg;
+
+       for (; phy_cfg->tmdsclock != 0; phy_cfg++)
+               if (tmdsclock <= phy_cfg->tmdsclock)
+                       break;
+
+       hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, INNO_POST_PLL_POWER_DOWN);
+
+       hdmi_writeb(hdmi, 0x1ac, INNO_POST_PLL_FB_DIV_7_0(hdmi->post_cfg->fbdiv));
+
+       if (hdmi->post_cfg->postdiv == 1) {
+               hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS);
+               hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv));
+               hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
+       } else {
+               v = (hdmi->post_cfg->postdiv / 2) - 1;
+               v &= INNO_POST_PLL_POST_DIV_MASK;
+               hdmi_modb(hdmi, 0x1ad, INNO_POST_PLL_POST_DIV_MASK, v);
+               hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv));
+               hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
+               hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS);
+               hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POST_DIV_ENABLE, INNO_POST_PLL_POST_DIV_ENABLE);
+       }
+
+       for (v = 0; v < 14; v++){
+               hdmi_writeb(hdmi, 0x1b5 + v, phy_cfg->regs[v]);
+       }
+
+       if (phy_cfg->tmdsclock > 340000000) {
+               /* Set termination resistor to 100ohm */
+               v = clk_get_rate(hdmi->sys_clk) / 100000;
+       
+               hdmi_writeb(hdmi, 0x1c5, INNO_TERM_RESISTOR_CALIB_SPEED_14_8(v)
+                          | INNO_BYPASS_TERM_RESISTOR_CALIB);
+       
+               hdmi_writeb(hdmi, 0x1c6, INNO_TERM_RESISTOR_CALIB_SPEED_7_0(v));
+               hdmi_writeb(hdmi, 0x1c7, INNO_TERM_RESISTOR_100);               
+               hdmi_modb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB, 0);
+       } else {
+               hdmi_writeb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB);
+
+               /* clk termination resistor is 50ohm (parallel resistors) */
+               if (phy_cfg->tmdsclock > 165000000){
+                       hdmi_modb(hdmi, 0x1c8,
+                                        INNO_ESD_DETECT_MASK,
+                                        INNO_TERM_RESISTOR_200);
+               }
+               /* data termination resistor for D2, D1 and D0 is 150ohm */
+               for (v = 0; v < 3; v++){
+                       hdmi_modb(hdmi, 0x1c9 + v,
+                                        INNO_ESD_DETECT_MASK,
+                                        INNO_TERM_RESISTOR_200);
+               }
+       }
+
+       hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, 0);
+
+
+#endif
+        return 0;
+ }
+
 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
                           struct drm_display_mode *mode)
 {
        hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
 
+       dev_info(hdmi->dev, "%s %d,hdmi->hdmi_data.vic = %d\n",__func__, __LINE__,hdmi->hdmi_data.vic);
+       
+
+       int val;
+
+       val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
+       val |= 0x4;
+       writel_relaxed(val, hdmi->regs + (0x1b0) * 0x04);
+       writel_relaxed(0xf, hdmi->regs + (0x1cc) * 0x04);
+
+       /*turn on pre-PLL*/
+       val = readl_relaxed(hdmi->regs + (0x1a0) * 0x04);
+       val &= ~(0x1);
+       writel_relaxed(val, hdmi->regs + (0x1a0) * 0x04);
+       /*turn on post-PLL*/
+       val = readl_relaxed(hdmi->regs + (0x1aa) * 0x04);
+       val &= ~(0x1);
+       writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04);
+
+       hdmi->tmds_rate = mode->clock * 1000;
+       inno_hdmi_phy_clk_set_rate(hdmi,hdmi->tmds_rate);
+
+       dev_info(hdmi->dev, "%s %d\n",__func__, __LINE__);
+
+       while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1))
+       ;
+       while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1))
+       ;
+
+       /*turn on LDO*/
+       writel_relaxed(0x7, hdmi->regs + (0x1b4) * 0x04);
+       /*turn on serializer*/
+       writel_relaxed(0x70, hdmi->regs + (0x1be) * 0x04);
+       inno_hdmi_tx_phy_power_down(hdmi);
+       /* Set HDMI Mode */
+       hdmi_writeb(hdmi, 0x100,0x3);
+       //hdmi_writeb(hdmi, 0x8,0x00);
+       int value;
+
+       /* Set detail external video timing polarity and interlace mode */
+       value = v_EXTERANL_VIDEO(0);
+       value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
+                v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
+       value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
+                v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
+       value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
+                v_INETLACE(1) : v_INETLACE(0);
+       hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
+
+       dev_info(hdmi->dev, "%s %d\n",__func__, __LINE__);
+       hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
+       dev_info(hdmi->dev, "%s %d,hdmi->hdmi_data.vic = %d\n",__func__, __LINE__,hdmi->hdmi_data.vic);
+
        hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
        hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
 
@@ -615,35 +902,30 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
        else
                hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
 
-       /* Mute video and audio output */
-       hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
-                 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+       /* Mute audio output */
+       hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE ,
+                 v_AUDIO_MUTE(1));
 
-       /* Set HDMI Mode */
-       hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
-                   v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
 
-       inno_hdmi_config_video_timing(hdmi, mode);
+    if(0 == hdmi->hdmi_data.vic)
+       {
+               inno_hdmi_config_video_timing(hdmi, mode);
 
-       inno_hdmi_config_video_csc(hdmi);
+               inno_hdmi_config_video_csc(hdmi);
+    }
+       dev_info(hdmi->dev, "%s %d,hdmi->hdmi_data.sink_is_hdmi = %d\n",__func__, __LINE__,hdmi->hdmi_data.sink_is_hdmi);
 
        if (hdmi->hdmi_data.sink_is_hdmi) {
                inno_hdmi_config_video_avi(hdmi, mode);
                inno_hdmi_config_video_vsi(hdmi, mode);
        }
 
-       /*
-        * When IP controller have configured to an accurate video
-        * timing, then the TMDS clock source would be switched to
-        * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
-        * clock rate, and reconfigure the DDC clock.
-        */
-       hdmi->tmds_rate = mode->clock * 1000;
-       inno_hdmi_i2c_init(hdmi);
+       inno_hdmi_tx_phy_power_on(hdmi);
+       inno_hdmi_tmds_driver_on(hdmi);
 
-       /* Unmute video and audio output */
-       hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
-                 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
+       writel_relaxed(0x0, hdmi->regs + (0xce) * 0x04);
+       writel_relaxed(0x1, hdmi->regs + (0xce) * 0x04);
+       dev_info(hdmi->dev, "%s %d\n",__func__, __LINE__);
 
        return 0;
 }
@@ -672,6 +954,14 @@ static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
        struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 
+       hdmi_modb(hdmi, 0x1b2, 0xf, 0);
+       hdmi_modb(hdmi, 0x1be, 0xf, 0);
+       hdmi_modb(hdmi, 0x1b4, 0xf, 0);
+       hdmi_modb(hdmi, 0x1a0, 1, 1);
+       hdmi_modb(hdmi, 0x1aa, 1, 1);
+       hdmi_modb(hdmi, 0x1cc, 0x0f, 0);
+       hdmi_modb(hdmi, 0x1b0, 1<<2, 0);
+
        inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
 }
 
@@ -733,11 +1023,119 @@ static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
        return ret;
 }
 
+static const struct dw_hdmi_mpll_config starfive_mpll_cfg[] = {
+       {
+               25200000, {
+                       { 0x00b3, 0x0000},
+                       { 0x2153, 0x0000},
+                       { 0x40f3, 0x0000}
+               },
+       }, {
+               27000000, {
+                       { 0x00b3, 0x0000},
+                       { 0x2153, 0x0000},
+                       { 0x40f3, 0x0000}
+               },
+       }, {
+               36000000, {
+                       { 0x00b3, 0x0000},
+                       { 0x2153, 0x0000},
+                       { 0x40f3, 0x0000}
+               },
+       }, {
+               40000000, {
+                       { 0x00b3, 0x0000},
+                       { 0x2153, 0x0000},
+                       { 0x40f3, 0x0000}
+               },
+       }, {
+               54000000, {
+                       { 0x0072, 0x0001},
+                       { 0x2142, 0x0001},
+                       { 0x40a2, 0x0001},
+               },
+       }, {
+               65000000, {
+                       { 0x0072, 0x0001},
+                       { 0x2142, 0x0001},
+                       { 0x40a2, 0x0001},
+               },
+       }, {
+               66000000, {
+                       { 0x013e, 0x0003},
+                       { 0x217e, 0x0002},
+                       { 0x4061, 0x0002}
+               },
+       }, {
+               74250000, {
+                       { 0x0072, 0x0001},
+                       { 0x2145, 0x0002},
+                       { 0x4061, 0x0002}
+               },
+       }, {
+               83500000, {
+                       { 0x0072, 0x0001},
+               },
+       }, {
+               108000000, {
+                       { 0x0051, 0x0002},
+                       { 0x2145, 0x0002},
+                       { 0x4061, 0x0002}
+               },
+       }, {
+               106500000, {
+                       { 0x0051, 0x0002},
+                       { 0x2145, 0x0002},
+                       { 0x4061, 0x0002}
+               },
+       }, {
+               146250000, {
+                       { 0x0051, 0x0002},
+                       { 0x2145, 0x0002},
+                       { 0x4061, 0x0002}
+               },
+       }, {
+               148500000, {
+                       { 0x0051, 0x0003},
+                       { 0x214c, 0x0003},
+                       { 0x4064, 0x0003}
+               },
+       }, {
+               ~0UL, {
+                       { 0x00a0, 0x000a },
+                       { 0x2001, 0x000f },
+                       { 0x4002, 0x000f },
+               },
+       }
+};
+
 static enum drm_mode_status
 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
                               struct drm_display_mode *mode)
 {
-       return MODE_OK;
+#if 0
+       const struct dw_hdmi_mpll_config *mpll_cfg = starfive_mpll_cfg;
+       int pclk = mode->clock * 1000;
+       bool valid = false;
+       int i;
+
+       for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
+               if (pclk == mpll_cfg[i].mpixelclock) {
+                       valid = true;
+                       break;
+               }
+       }
+
+       return (valid) ? MODE_OK : MODE_BAD;
+#endif
+       u32 vic = drm_match_cea_mode(mode);
+
+       if (vic >= 1)
+               return MODE_OK;
+       else
+               return MODE_BAD;
+
+       //return MODE_OK;
 }
 
 static int
@@ -1131,21 +1529,8 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
        }
        udelay(100);
 
-//20220531 clk rst interface support
-#if 1
        ret = inno_hdmi_get_clk_rst(dev, hdmi);
-       //if (ret) {
-       //      dev_err(dev, "failed to get clock or reset\n");
-       //      return ret;
-       //}
        ret = inno_hdmi_en_clk_deas_rst(dev, hdmi);
-       //if (ret) {
-       //      dev_err(dev, "failed to enable clock or deassert reset\n");
-       //      return ret;
-       //}
-#endif
-//20220531 clk rst interface support
-
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -1218,15 +1603,9 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master,
        clk_disable_unprepare(hdmi->mclk);
        clk_disable_unprepare(hdmi->bclk);
 
-       //pmic turn off
-       #if 1
        regulator_disable(hdmi->hdmi_1p8);
        udelay(100);
        regulator_disable(hdmi->hdmi_0p9);
-       #endif
-       //pmic turn off
-
-//     clk_disable_unprepare(hdmi->pclk);
 }
 
 static const struct component_ops inno_hdmi_ops = {
old mode 100644 (file)
new mode 100755 (executable)
index d463f13..1799553
@@ -374,4 +374,175 @@ typedef enum {
 } vic_code_t;
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define UPDATE(x, h, l)                (((x) << (l)) & GENMASK((h), (l)))
+
+       /* REG: 0x1a0 */
+#define INNO_PCLK_VCO_DIV_5_MASK                       BIT(1)
+#define INNO_PCLK_VCO_DIV_5(x)                         UPDATE(x, 1, 1)
+#define INNO_PRE_PLL_POWER_DOWN                                BIT(0)
+
+       /* REG: 0x1a1 */
+#define INNO_PRE_PLL_PRE_DIV_MASK                      GENMASK(5, 0)
+#define INNO_PRE_PLL_PRE_DIV(x)                                UPDATE(x, 5, 0)
+
+
+       /* REG: 0xa2 */
+       /* unset means center spread */
+#define INNO_SPREAD_SPECTRUM_MOD_DOWN                  BIT(7)
+#define INNO_SPREAD_SPECTRUM_MOD_DISABLE               BIT(6)
+#define INNO_PRE_PLL_FRAC_DIV_DISABLE                  UPDATE(3, 5, 4)
+#define INNO_PRE_PLL_FB_DIV_11_8_MASK                  GENMASK(3, 0)
+#define INNO_PRE_PLL_FB_DIV_11_8(x)                            UPDATE((x) >> 8, 3, 0)
+
+       /* REG: 0xa3 */
+#define INNO_PRE_PLL_FB_DIV_7_0(x)                             UPDATE(x, 7, 0)
+
+       /* REG: 0xa4*/
+#define INNO_PRE_PLL_TMDSCLK_DIV_C_MASK                        GENMASK(1, 0)
+#define INNO_PRE_PLL_TMDSCLK_DIV_C(x)                  UPDATE(x, 1, 0)
+#define INNO_PRE_PLL_TMDSCLK_DIV_B_MASK                        GENMASK(3, 2)
+#define INNO_PRE_PLL_TMDSCLK_DIV_B(x)                  UPDATE(x, 3, 2)
+#define INNO_PRE_PLL_TMDSCLK_DIV_A_MASK                        GENMASK(5, 4)
+#define INNO_PRE_PLL_TMDSCLK_DIV_A(x)                  UPDATE(x, 5, 4)
+       /* REG: 0xa5 */
+#define INNO_PRE_PLL_PCLK_DIV_B_SHIFT                  5
+#define INNO_PRE_PLL_PCLK_DIV_B_MASK                   GENMASK(6, 5)
+#define INNO_PRE_PLL_PCLK_DIV_B(x)                             UPDATE(x, 6, 5)
+#define INNO_PRE_PLL_PCLK_DIV_A_MASK                   GENMASK(4, 0)
+#define INNO_PRE_PLL_PCLK_DIV_A(x)                             UPDATE(x, 4, 0)
+
+       /* REG: 0xa6 */
+#define INNO_PRE_PLL_PCLK_DIV_C_SHIFT                  5
+#define INNO_PRE_PLL_PCLK_DIV_C_MASK                   GENMASK(6, 5)
+#define INNO_PRE_PLL_PCLK_DIV_C(x)                             UPDATE(x, 6, 5)
+#define INNO_PRE_PLL_PCLK_DIV_D_MASK                   GENMASK(4, 0)
+#define INNO_PRE_PLL_PCLK_DIV_D(x)                             UPDATE(x, 4, 0)
+
+                       /* REG: 0xd1 */
+#define INNO_PRE_PLL_FRAC_DIV_23_16(x)                 UPDATE((x) >> 16, 7, 0)
+                       /* REG: 0xd2 */
+#define INNO_PRE_PLL_FRAC_DIV_15_8(x)                  UPDATE((x) >> 8, 7, 0)
+                       /* REG: 0xd3 */
+#define INNO_PRE_PLL_FRAC_DIV_7_0(x)                   UPDATE(x, 7, 0)
+
+       /* REG: 0x1aa */
+#define INNO_POST_PLL_POST_DIV_ENABLE                  GENMASK(3, 2)
+#define INNO_POST_PLL_REFCLK_SEL_TMDS                  BIT(1)
+#define INNO_POST_PLL_POWER_DOWN                               BIT(0)
+#define INNO_POST_PLL_FB_DIV_8(x)                      UPDATE(((x) >> 8) <<4 , 4, 4)
+
+       /* REG:0x1ab */
+#define INNO_POST_PLL_Pre_DIV_MASK                     GENMASK(5, 0)
+#define INNO_POST_PLL_PRE_DIV(x)                       UPDATE(x, 5, 0)
+       /* REG: 0x1ac */
+#define INNO_POST_PLL_FB_DIV_7_0(x)                    UPDATE(x, 7, 0)
+       /* REG: 0x1ad */
+#define INNO_POST_PLL_POST_DIV_MASK                    GENMASK(2, 0)
+#define INNO_POST_PLL_POST_DIV_2                       0x0
+#define INNO_POST_PLL_POST_DIV_4                       0x1
+#define INNO_POST_PLL_POST_DIV_8                       0x3
+       /* REG: 0x1af */
+#define INNO_POST_PLL_LOCK_STATUS                      BIT(0)
+       /* REG: 0x1b0 */
+#define INNO_BANDGAP_ENABLE                            BIT(2)
+       /* REG: 0x1b2 */
+#define INNO_TMDS_CLK_DRIVER_EN                        BIT(3)
+#define INNO_TMDS_D2_DRIVER_EN                 BIT(2)
+#define INNO_TMDS_D1_DRIVER_EN                 BIT(1)
+#define INNO_TMDS_D0_DRIVER_EN                 BIT(0)
+#define INNO_TMDS_DRIVER_ENABLE                (INNO_TMDS_CLK_DRIVER_EN | \
+                                                       INNO_TMDS_D2_DRIVER_EN | \
+                                                       INNO_TMDS_D1_DRIVER_EN | \
+                                                       INNO_TMDS_D0_DRIVER_EN)
+       /* REG:0x1c5 */
+#define INNO_BYPASS_TERM_RESISTOR_CALIB                BIT(7)
+#define INNO_TERM_RESISTOR_CALIB_SPEED_14_8(x) UPDATE((x) >> 8, 6, 0)
+       /* REG:0x1c6 */
+#define INNO_TERM_RESISTOR_CALIB_SPEED_7_0(x)          UPDATE(x, 7, 0)
+       /* REG:0x1c7 */
+#define INNO_TERM_RESISTOR_100                         UPDATE(0, 2, 1)
+#define INNO_TERM_RESISTOR_125                         UPDATE(1, 2, 1)
+#define INNO_TERM_RESISTOR_150                         UPDATE(2, 2, 1)
+#define INNO_TERM_RESISTOR_200                         UPDATE(3, 2, 1)
+       /* REG 0x1c8 - 0x1cb */
+#define INNO_ESD_DETECT_MASK                           GENMASK(5, 0)
+#define INNO_ESD_DETECT_340MV                          (0x0 << 6)
+#define INNO_ESD_DETECT_280MV                          (0x1 << 6)
+#define INNO_ESD_DETECT_260MV                          (0x2 << 6)
+#define INNO_ESD_DETECT_240MV                          (0x3 << 6)
+       /* resistors can be used in parallel */
+#define INNO_TMDS_TERM_RESIST_MASK                     GENMASK(5, 0)
+#define INNO_TMDS_TERM_RESIST_125                      BIT(5)
+#define INNO_TMDS_TERM_RESIST_250                      BIT(4)
+#define INNO_TMDS_TERM_RESIST_500                      BIT(3)
+#define INNO_TMDS_TERM_RESIST_1000                     BIT(2)
+#define INNO_TMDS_TERM_RESIST_2000                     BIT(1)
+#define INNO_TMDS_TERM_RESIST_4000                     BIT(0)
+
+struct pre_pll_config {
+       unsigned long pixclock;
+       unsigned long tmdsclock;
+       u8 prediv;
+       u16 fbdiv;
+       u8 tmds_div_a;
+       u8 tmds_div_b;
+       u8 tmds_div_c;
+       u8 pclk_div_a;
+       u8 pclk_div_b;
+       u8 pclk_div_c;
+       u8 pclk_div_d;
+       u8 vco_div_5_en;
+       u32 fracdiv;
+};
+
+struct post_pll_config {
+       unsigned long tmdsclock;
+       u8 prediv;
+       u16 fbdiv;
+       u8 postdiv;
+       u8 post_div_en;
+       u8 version;
+};
+
+struct phy_config {
+       unsigned long   tmdsclock;
+       u8              regs[14];
+};
+
+typedef struct register_value {
+       u16 reg;
+       u8 value;
+} reg_value_t;
+
 #endif /* __INNO_HDMI_H__ */
old mode 100644 (file)
new mode 100755 (executable)
index 3e26baa..8c6a7a7
 #include <drm/drm_vblank.h>
 #endif
 
+//syscon panel
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+//syscon panel
+
 static inline void update_format(u32 format, u64 mod, struct dc_hw_fb *fb)
 {
        u8 f = FORMAT_A8R8G8B8;
@@ -332,10 +337,7 @@ static int vs_dc_get_clock(struct device *dev, struct vs_dc *dc)
        }
        return ret;
 }
-//noc bus clk get
-
 
-//noc bus clk enable
 static int  vs_dc_clock_enable(struct device *dev, struct vs_dc *dc)
 {
        int ret;
@@ -590,16 +592,16 @@ static int vs_dc_vouttop_resets_assert(struct device *dev, struct vs_dc *dc)
 static int vs_dc_dc8200_get_clock(struct device *dev, struct vs_dc *dc)
 {
        int ret;
-       dc->dc8200_pix0 = devm_clk_get(dev, "pix_clk");
-       if (IS_ERR(dc->dc8200_pix0)) {
-               dev_err(dev, "---dc8200_pix0 get error\n");
-               return PTR_ERR(dc->dc8200_pix0);
+       dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk");
+       if (IS_ERR(dc->dc8200_clk_pix0)) {
+               dev_err(dev, "---dc8200_clk_pix0 get error\n");
+               return PTR_ERR(dc->dc8200_clk_pix0);
        }
 
-       dc->dc8200_pix1 = devm_clk_get(dev, "vout_pix1");
-       if (IS_ERR(dc->dc8200_pix1)) {
-               dev_err(dev, "---dc8200_pix1 get error\n");
-               return PTR_ERR(dc->dc8200_pix1);
+       dc->dc8200_clk_pix1 = devm_clk_get(dev, "vout_pix1");
+       if (IS_ERR(dc->dc8200_clk_pix1)) {
+               dev_err(dev, "---dc8200_clk_pix1 get error\n");
+               return PTR_ERR(dc->dc8200_clk_pix1);
        }
 
        dc->dc8200_axi = devm_clk_get(dev, "axi_clk");
@@ -626,14 +628,14 @@ static int  vs_dc_dc8200_clock_enable(struct device *dev, struct vs_dc *dc)
 {
        int ret;
        /*clk_prepare_enable(dc->sys_clk);*/
-       ret = clk_prepare_enable(dc->dc8200_pix0);
+       ret = clk_prepare_enable(dc->dc8200_clk_pix0);
        if (ret) {
-               dev_err(dev, "failed to prepare/enable dc8200_pix0\n");
+               dev_err(dev, "failed to prepare/enable dc8200_clk_pix0\n");
                return ret;
        }
-       ret = clk_prepare_enable(dc->dc8200_pix1);
+       ret = clk_prepare_enable(dc->dc8200_clk_pix1);
        if (ret) {
-               dev_err(dev, "failed to prepare/enable dc8200_pix1\n");
+               dev_err(dev, "failed to prepare/enable dc8200_clk_pix1\n");
                return ret;
        }
        ret = clk_prepare_enable(dc->dc8200_axi);
@@ -657,8 +659,8 @@ static int  vs_dc_dc8200_clock_enable(struct device *dev, struct vs_dc *dc)
 
 static void  vs_dc_dc8200_clock_disable(struct vs_dc *dc)
 {
-       clk_disable_unprepare(dc->dc8200_pix0);
-       clk_disable_unprepare(dc->dc8200_pix1);
+       clk_disable_unprepare(dc->dc8200_clk_pix0);
+       clk_disable_unprepare(dc->dc8200_clk_pix1);
        clk_disable_unprepare(dc->dc8200_axi);
        clk_disable_unprepare(dc->dc8200_core);
        clk_disable_unprepare(dc->dc8200_ahb);
@@ -731,7 +733,6 @@ static int vs_dc_dc8200_resets_assert(struct device *dev, struct vs_dc *dc)
 static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc)
 {
        int ret;
-       #if 1   //noc bus
        ret = vs_dc_get_clock(dev, dc);
        if (ret) {
                dev_err(dev, "failed to get clock\n");
@@ -752,9 +753,7 @@ static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc)
                dev_err(dev, "failed to deassert reset\n");
                return ret;
        }
-       #endif
 
-       #if 1   //vout top
        ret = vs_dc_vouttop_get_clock(dev, dc);
        if (ret) {
                dev_err(dev, "failed to get clock\n");
@@ -775,9 +774,7 @@ static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc)
                dev_err(dev, "failed to deassert reset\n");
                return ret;
        }
-       #endif
 
-       #if 1   //dc8200
        ret = vs_dc_dc8200_get_clock(dev, dc);
        if (ret) {
                dev_err(dev, "failed to get clock\n");
@@ -798,40 +795,73 @@ static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc)
                dev_err(dev, "failed to deassert reset\n");
                return ret;
        }
-       #endif
 
        return ret;
 }
 
-int sys_vout_mux_config(void)
+
+static int syscon_panel_parse_dt(struct device *dev)
 {
-       #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi
-               SET_U0_LCD_DATA_MAPPING_DPI_DP_SEL(0);//DC8200_INTERFACE_DPI
-               SET_U0_LCD_DATA_MAPPING_DP_RGB_FMT(0);//0-RGB888
-               SET_U0_DISPLAY_PANEL_MUX_PANEL_SEL(0);//panel 0
-       #else
-    if(1){
-               SET_U0_HDMI_DATA_MAPPING_DPI_DP_SEL(0);
-               SET_U0_HDMI_DATA_MAPPING_DPI_BIT_DEPTH(0);
-               SET_U0_HDMI_DATA_MAPPING_DP_BIT_DEPTH(0);
-               SET_U0_HDMI_DATA_MAPPING_DP_YUV_MODE(0);
-               SET_U2_DISPLAY_PANEL_MUX_PANEL_SEL(0);
-
-    }
-       #endif
-    return 0;
+       struct vs_dc *dc = dev_get_drvdata(dev);
+       int ret = 0;
+
+       dc->dss_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                               "verisilicon,dss-syscon");
+
+       if (IS_ERR(dc->dss_regmap)) {
+               if (PTR_ERR(dc->dss_regmap) != -ENODEV) {
+                       dev_err(dev, "failed to get dss-syscon\n");
+                       ret = PTR_ERR(dc->dss_regmap);
+                       goto err;
+               }
+               dc->dss_regmap = NULL;
+               goto err;
+       }
+
+err:
+       return ret;
 }
 
-int sys_dispctrl_clk(void)
+int sys_dispctrl_clk_standard(struct vs_dc *dc, struct device *dev)
 {
-       #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi
-               _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX1_SOURCE_CLK_HDMITX0_PIXELCLK_;
-               _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_HDMITX0_PIXELCLK_;
-               //_ENABLE_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_;//disabled standard
-       #else
-               _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_HDMITX0_PIXELCLK_;
-               //_SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_;
-       #endif
+#ifdef CONFIG_DRM_I2C_NXP_TDA998X
+       dc->dc8200_clk_pix1 = devm_clk_get(dev, "vout_pix1");
+       if (IS_ERR(dc->dc8200_clk_pix1)) {
+               dev_err(dev, "---dc8200_clk_pix1 get error\n");
+               return PTR_ERR(dc->dc8200_clk_pix1);
+       }
+
+       dc->hdmitx0_pixelclk = devm_clk_get(dev, "hdmitx0_pixelclk");
+       if (IS_ERR(dc->hdmitx0_pixelclk)) {
+               dev_err(dev, "---hdmitx0_pixelclk get error\n");
+               return PTR_ERR(dc->hdmitx0_pixelclk);
+       }
+
+       dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk");
+       if (IS_ERR(dc->dc8200_clk_pix0)) {
+               dev_err(dev, "---dc8200_clk_pix0 get error\n");
+               return PTR_ERR(dc->dc8200_clk_pix0);
+       }
+
+       clk_set_parent( dc->dc8200_clk_pix1, dc->hdmitx0_pixelclk );
+       clk_set_parent( dc->dc8200_clk_pix0, dc->hdmitx0_pixelclk );
+
+#else
+       //_SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_HDMITX0_PIXELCLK_;
+       dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk");     //dc8200_clk_pix0
+       if (IS_ERR(dc->dc8200_clk_pix0)) {
+               dev_err(dev, "---dc8200_clk_pix0 get error\n");
+               return PTR_ERR(dc->dc8200_clk_pix0);
+       }
+
+       dc->hdmitx0_pixelclk = devm_clk_get(dev, "hdmitx0_pixelclk");//hdmitx0_pixelclk
+       if (IS_ERR(dc->hdmitx0_pixelclk)) {
+               dev_err(dev, "---hdmitx0_pixelclk get error\n");
+               return PTR_ERR(dc->hdmitx0_pixelclk);
+       }
+       clk_set_parent( dc->dc8200_clk_pix0, dc->hdmitx0_pixelclk );//parent,child
+
+#endif
 
     return 0;
 }
@@ -841,11 +871,7 @@ int drv_config_dc_4_dsi(struct vs_dc *dc, struct device *dev)//for dc_dsi config
        int ret;
 
        dev_info(dev, "====> %s, %d.\n", __func__, __LINE__);
-       /*---------------------mux config------------*/
-       SET_U0_DSITX_DATA_MAPPING_DPI_DP_SEL(0);
-       //SET_U0_DSITX_DATA_MAPPING_DP_MODE(vout_sys->vout_dsitx.dp_color_mode);
-       SET_U1_DISPLAY_PANEL_MUX_PANEL_SEL(0);
-       //_ENABLE_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_;
+
        ret = clk_prepare_enable(dc->vout_top_lcd);
        if (ret) {
                dev_err(dev, "failed to prepare/enable vout_top_lcd\n");
@@ -856,15 +882,6 @@ int drv_config_dc_4_dsi(struct vs_dc *dc, struct device *dev)//for dc_dsi config
        return 0;
 }
 
-int sys_dispctrl_init(void)
-{
-    sys_vout_mux_config();
-    sys_dispctrl_clk();
-
-       mdelay(1);    
-    return 0;
-}
-
 static void dc_deinit(struct device *dev)
 {
        struct vs_dc *dc = dev_get_drvdata(dev);
@@ -890,20 +907,26 @@ static int dc_init(struct device *dev)
 
        dc->first_frame = true;
 
-       //power_set(dev, 1);
+       ret = syscon_panel_parse_dt(dev);
+       if (ret){
+               dev_err(dev,"syscon_panel_parse_dt failed\n");
+               return ret;
+       }
 
        starfive_power_domain_set(POWER_DOMAIN_VOUT, 1);
 
        //ret = plda_clk_rst_init(dev);
        ret = dc_vout_clk_rst_init(dev, dc);
 
-       ret = sys_dispctrl_init();
-       if (ret < 0) {
-               dev_err(dev, "failed to init vout clk reset: %d\n", ret);
-               return ret;
-       }
+       #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi
+                       regmap_update_bits(dc->dss_regmap, 0x4, BIT(20), 1<<20);
+       #endif
+
+       ret = sys_dispctrl_clk_standard(dc, dev);
+
        #ifdef CONFIG_STARFIVE_DSI
        dev_info(dev, "dc mipi channel\n");
+       regmap_update_bits(dc->dss_regmap, 0x8, BIT(3), 1<<3);
        dc->vout_src = devm_clk_get(dev, "vout_src");
        if (IS_ERR(dc->vout_src)){
                dev_err(dev,"failed to get dc->vout_src\n");
@@ -914,6 +937,15 @@ static int dc_init(struct device *dev)
                dev_err(dev,"failed to get dc->vout_top_lcd\n");
                return PTR_ERR(dc->vout_top_lcd);
        }
+       #if 1   //parent for dc8200_clk_pix0 !!
+       dc->dc8200_pix0 = devm_clk_get(dev, "dc8200_pix0");     //dc8200_pix0
+       if (IS_ERR(dc->dc8200_pix0)) {
+               dev_err(dev, "---dc8200_pix0 get error\n");
+               return PTR_ERR(dc->dc8200_pix0);
+       }
+       #endif
+       //_SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_;
+       clk_set_parent( dc->dc8200_clk_pix0, dc->dc8200_pix0 );//child,parent
        ret = drv_config_dc_4_dsi(dc,dev);
        if (ret < 0) {
                dev_err(dev, "failed to drv_config_dc_4_dsi: %d\n", ret);
@@ -923,19 +955,22 @@ static int dc_init(struct device *dev)
 
        #ifdef CONFIG_DRM_I2C_NXP_TDA998X
        _ENABLE_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_;
-       /*
+       #if 0 //to do fix
        dev_info(dev, "dc rgb2hdmi channel\n");
        dc->vout_top_lcd = devm_clk_get(dev, "vout_top_lcd");
        if (IS_ERR(dc->vout_top_lcd)){
                dev_err(dev,"failed to get dc->vout_top_lcd\n");
                return PTR_ERR(dc->vout_top_lcd);
        }
+
+       clk_set_parent( dc->vout_top_lcd, dc->dc8200_clk_pix1);
+
        ret = clk_prepare_enable(dc->vout_top_lcd);
        if (ret) {
                dev_err(dev, "failed to prepare/enable vout_top_lcd\n");
                return ret;
        }
-       */
+       #endif
        #endif
        printk("====> %s, %d.\n", __func__, __LINE__);
 
@@ -970,10 +1005,14 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc)
        struct vs_crtc_state *crtc_state = to_vs_crtc_state(crtc->state);
        struct drm_display_mode *mode = &crtc->state->adjusted_mode;
        struct dc_hw_display display;
+#ifdef CONFIG_STARFIVE_DSI//7110 mipi
+       #if 0
        uint32_t vout_clock;
        uint32_t div;
        uint32_t div_new;
        const uint32_t wanted_pxclk = mode->clock * 1000;
+       #endif
+#endif
 
        display.bus_format = crtc_state->output_fmt;
        display.h_active = mode->hdisplay;
@@ -1003,47 +1042,8 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc)
 
        display.enable = true;
 
-#if 1
-       ;//printk("====> %s, %d--pix_clk.\n", __func__, __LINE__);
-#else
-       //used for div clock
-       if (dc->pix_clk_rate != mode->clock) {
-               printk("====> %s, %d--pix_clk.mode->clock = %d\n", __func__, __LINE__,mode->clock);
-               u32 div = _GET_CLOCK_DIVIDE_STATUS_CLK_DC8200_PIX0_;
-       printk("====> %s, %d--pix_clk.div = %d\n", __func__, __LINE__,div);
-
-       //148500
-         div = 1228800/mode->clock;
-               //148500
-               printk("====> %s, %d--pix_clk.div = %d\n", __func__, __LINE__,div);
-
-               _DIVIDE_CLOCK_CLK_DC8200_PIX0_(div);
-               _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_;
-               _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX1_SOURCE_CLK_DC8200_PIX0_;
-
-               _SWITCH_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_SOURCE_CLK_U0_DC8200_CLK_PIX0_OUT_;
-
-               //clk_set_rate(dc->pix_clk, mode->clock * 1000);
-               dc->pix_clk_rate = mode->clock;
-       }
-#endif
-
-#ifdef CONFIG_STARFIVE_DSI//7110 mipi
-       /*-----------------div freq clk  sys_dispctrl_clk()----------*/
-       //const uint32_t wanted_pxclk = 20144262;//dpi->pixelclock;
-       //wanted_pxclk = mode->clock * 1000;
-       dev_info(dev, "wanted_pxclk = %d\n",wanted_pxclk);
-    //uint32_t vout_clock = 614400000;
-       vout_clock = clk_get_rate(dc->vout_src);
-       dev_info(dev, "vout_clock = %d\n", vout_clock); 
-       div = _GET_CLOCK_DIVIDE_STATUS_CLK_DC8200_PIX0_;
-       div_new = vout_clock / wanted_pxclk;
-       if (div != div_new) {
-               div = div_new;
-               _DIVIDE_CLOCK_CLK_DC8200_PIX0_(div);
-               _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_;
-       }
-       /*-----------------div freq clk  sys_dispctrl_clk()----------*/
+#ifdef CONFIG_STARFIVE_DSI//
+       clk_set_rate(dc->dc8200_pix0, 20144263);//round up, 20144262+1
 #endif
 
        if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI)
old mode 100644 (file)
new mode 100755 (executable)
index a645c3e..e07bcfc
@@ -54,54 +54,47 @@ struct vs_dc {
 
        const struct vs_dc_funcs *funcs;
 
-//noc bus clk
        struct clk *cpu_axi;
        struct clk *axicfg0_axi;
        struct clk *disp_axi;
        struct clk *stg_axi;
-//noc bus clk
-//noc bus rst
+
        struct reset_control *cpu_axi_n;
        struct reset_control *axicfg0_axi_n;
        struct reset_control *apb_bus_n;
        struct reset_control *disp_axi_n;
        struct reset_control *stg_axi_n;
-//noc bus rst
 
-//vout top clk
        struct clk *vout_src;
        struct clk *vout_axi;
        struct clk *ahb1;
        struct clk *vout_ahb;
        struct clk *hdmitx0_mclk;
        struct clk *bclk_mst;
-//vout top clk
-//vout top rst
+
        struct reset_control *rstn_vout_src;
-//vout top rst
 
-//dc8200 clk
-       struct clk *dc8200_pix0;
-       struct clk *dc8200_pix1;
+       struct clk *dc8200_clk_pix0;
+       struct clk *dc8200_clk_pix1;
        struct clk *dc8200_axi;
        struct clk *dc8200_core;
        struct clk *dc8200_ahb;
-//dc8200 clk
-//dc8200 rst
+
        struct reset_control *rstn_dc8200_axi;
        struct reset_control *rstn_dc8200_core;
        struct reset_control *rstn_dc8200_ahb;
-//dc8200 rst
 
-//7110 mp
-struct clk *vout_top_axi;
-struct clk *vout_top_lcd;
-//7110 mp
+       struct clk *vout_top_axi;
+       struct clk *vout_top_lcd;
+
+       struct clk *hdmitx0_pixelclk;
+       struct clk *dc8200_pix0;
+
+       struct regmap *dss_regmap;
 
 };
 
 extern struct platform_driver dc_platform_driver;
-//extern struct platform_driver simple_encoder_driver;
 extern struct platform_driver starfive_dsi_platform_driver;
 extern int init_seeed_panel(void);
 extern void exit_seeed_panel(void);
old mode 100644 (file)
new mode 100755 (executable)
index 0508da6..84c2616
@@ -468,7 +468,6 @@ static int __init vs_drm_init(void)
 {
        int ret;
 
-       printk("%s:%d\n", __func__, __LINE__);
        ret = platform_register_drivers(drm_sub_drivers, NUM_DRM_DRIVERS);
        if (ret)
                return ret;
old mode 100644 (file)
new mode 100755 (executable)
index 31672b0..48654ea
@@ -38,6 +38,7 @@ static inline struct simple_encoder *to_simple_encoder(struct drm_encoder *enc)
        return container_of(enc, struct simple_encoder, encoder);
 }
 
+#if 0
 static int encoder_parse_dt(struct device *dev)
 {
        struct simple_encoder *simple = dev_get_drvdata(dev);
@@ -103,6 +104,7 @@ err_free_masks:
 err:
        return ret;
 }
+#endif
 
 #define DOM_VOUT_SYSCON_8                                                                      0x8U
 #define U0_LCD_DATA_MAPPING_DPI_DP_SEL_SHIFT                           0x2U
@@ -116,6 +118,8 @@ void encoder_atomic_enable(struct drm_encoder *encoder,
                                                struct drm_atomic_state *state)
 {
        struct simple_encoder *simple = to_simple_encoder(encoder);
+       printk("encoder_atomic_enable\n");
+       #if 0
        struct dss_data *data = simple->dss_regdatas;
        int crtc_id;
 
@@ -130,6 +134,7 @@ void encoder_atomic_enable(struct drm_encoder *encoder,
 
        regmap_update_bits(simple->dss_regmap, DOM_VOUT_SYSCON_8, U0_LCD_DATA_MAPPING_DPI_DP_SEL_MASK, 0);
        regmap_update_bits(simple->dss_regmap, DOM_VOUT_SYSCON_4, U0_DISPLAY_PANEL_MUX_PANEL_SEL_MASK, 0);
+       #endif
 }
 
 int encoder_atomic_check(struct drm_encoder *encoder,
@@ -221,6 +226,7 @@ static int encoder_bind(struct device *dev, struct device *master, void *data)
 
        encoder->possible_crtcs =
                        drm_of_find_possible_crtcs(drm_dev, dev->of_node);
+       encoder->possible_crtcs = 3;
 
        /* output port is port1*/
 
@@ -289,11 +295,11 @@ static int encoder_probe(struct platform_device *pdev)
        simple->dev = dev;
 
        dev_set_drvdata(dev, simple);
-
+#if 0
        ret = encoder_parse_dt(dev);
        if (ret)
                return ret;
-
+#endif
        return component_add(dev, &encoder_component_ops);
 }