phy: rockchip-inno-mipi-dphy: Add fixed timing param table
authorWeiYong Bi <bivvy.bi@rock-chips.com>
Tue, 11 Apr 2017 10:10:46 +0000 (18:10 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 17 Apr 2017 03:07:11 +0000 (11:07 +0800)
Change-Id: Ia6a92833f4b597ac5f9af694644714a7b71b3375
Signed-off-by: WeiYong Bi <bivvy.bi@rock-chips.com>
drivers/phy/phy-rockchip-inno-mipi-dphy.c

index 1e82afe6ec11e1eec7bd161c506ebe44509e1807..a0eda5d12336b5614eabe974b68cd3d23912178a 100644 (file)
 #define DATA_LANE_2_EN         BIT(4)
 #define DATA_LANE_1_EN         BIT(3)
 #define DATA_LANE_0_EN         BIT(2)
 #define DATA_LANE_2_EN         BIT(4)
 #define DATA_LANE_1_EN         BIT(3)
 #define DATA_LANE_0_EN         BIT(2)
+#define FBDIV_8_MASK           BIT(5)
+#define PREDIV_MASK            (0x1f << 0)
+#define FBDIV_7_0_MASK         (0xff << 0)
 #define FBDIV_8(x)             (((x) & 0x1) << 5)
 #define PREDIV(x)              (((x) & 0x1f) << 0)
 #define FBDIV_7_0(x)           (((x) & 0xff) << 0)
 #define FBDIV_8(x)             (((x) & 0x1) << 5)
 #define PREDIV(x)              (((x) & 0x1f) << 0)
 #define FBDIV_7_0(x)           (((x) & 0xff) << 0)
+#define T_LPX_MASK             (0x3f << 0)
+#define T_HS_PREPARE_MASK      (0x7f << 0)
+#define T_HS_ZERO_MASK         (0x3f << 0)
+#define T_HS_TRAIL_MASK                (0x7f << 0)
+#define T_HS_EXIT_MASK         (0x1f << 0)
+#define T_CLK_POST_MASK                (0xf << 0)
+#define T_WAKUP_H_MASK         (0x3 << 0)
+#define T_WAKUP_L_MASK         (0xff << 0)
+#define T_CLK_PRE_MASK         (0xf << 0)
+#define T_TA_GO_MASK           (0x3f << 0)
+#define T_TA_SURE_MASK         (0x3f << 0)
+#define T_TA_WAIT_MASK         (0x3f << 0)
 #define T_LPX(x)               (((x) & 0x3f) << 0)
 #define T_HS_PREPARE(x)                (((x) & 0x7f) << 0)
 #define T_HS_ZERO(x)           (((x) & 0x3f) << 0)
 #define T_LPX(x)               (((x) & 0x3f) << 0)
 #define T_HS_PREPARE(x)                (((x) & 0x7f) << 0)
 #define T_HS_ZERO(x)           (((x) & 0x3f) << 0)
@@ -90,82 +105,12 @@ enum lane_type {
        DATA_LANE_3,
 };
 
        DATA_LANE_3,
 };
 
-static const u32 lane_reg_offset[] = {
-       [CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
-       [DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
-       [DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
-       [DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
-       [DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
-};
-
-enum hs_clk_range {
-       HS_CLK_RANGE_80_110_MHZ,
-       HS_CLK_RANGE_110_150_MHZ,
-       HS_CLK_RANGE_150_200_MHZ,
-       HS_CLK_RANGE_200_250_MHZ,
-       HS_CLK_RANGE_250_300_MHZ,
-       HS_CLK_RANGE_300_400_MHZ,
-       HS_CLK_RANGE_400_500_MHZ,
-       HS_CLK_RANGE_500_600_MHZ,
-       HS_CLK_RANGE_600_700_MHZ,
-       HS_CLK_RANGE_700_800_MHZ,
-       HS_CLK_RANGE_800_1000_MHZ,
-};
-
-static const u8 t_hs_prepare_val[] = {
-       [HS_CLK_RANGE_80_110_MHZ] = 0x20,
-       [HS_CLK_RANGE_110_150_MHZ] = 0x06,
-       [HS_CLK_RANGE_150_200_MHZ] = 0x18,
-       [HS_CLK_RANGE_200_250_MHZ] = 0x05,
-       [HS_CLK_RANGE_250_300_MHZ] = 0x51,
-       [HS_CLK_RANGE_300_400_MHZ] = 0x64,
-       [HS_CLK_RANGE_400_500_MHZ] = 0x20,
-       [HS_CLK_RANGE_500_600_MHZ] = 0x6a,
-       [HS_CLK_RANGE_600_700_MHZ] = 0x3e,
-       [HS_CLK_RANGE_700_800_MHZ] = 0x21,
-       [HS_CLK_RANGE_800_1000_MHZ] = 0x09,
-};
-
-static const u8 clock_lane_t_hs_zero_val[] = {
-       [HS_CLK_RANGE_80_110_MHZ] = 0x16,
-       [HS_CLK_RANGE_110_150_MHZ] = 0x16,
-       [HS_CLK_RANGE_150_200_MHZ] = 0x17,
-       [HS_CLK_RANGE_200_250_MHZ] = 0x17,
-       [HS_CLK_RANGE_250_300_MHZ] = 0x18,
-       [HS_CLK_RANGE_300_400_MHZ] = 0x19,
-       [HS_CLK_RANGE_400_500_MHZ] = 0x1b,
-       [HS_CLK_RANGE_500_600_MHZ] = 0x1d,
-       [HS_CLK_RANGE_600_700_MHZ] = 0x1e,
-       [HS_CLK_RANGE_700_800_MHZ] = 0x1f,
-       [HS_CLK_RANGE_800_1000_MHZ] = 0x20,
-};
-
-static const u8 data_lane_t_hs_zero_val[] = {
-       [HS_CLK_RANGE_80_110_MHZ] = 2,
-       [HS_CLK_RANGE_110_150_MHZ] = 3,
-       [HS_CLK_RANGE_150_200_MHZ] = 4,
-       [HS_CLK_RANGE_200_250_MHZ] = 5,
-       [HS_CLK_RANGE_250_300_MHZ] = 6,
-       [HS_CLK_RANGE_300_400_MHZ] = 7,
-       [HS_CLK_RANGE_400_500_MHZ] = 7,
-       [HS_CLK_RANGE_500_600_MHZ] = 8,
-       [HS_CLK_RANGE_600_700_MHZ] = 8,
-       [HS_CLK_RANGE_700_800_MHZ] = 9,
-       [HS_CLK_RANGE_800_1000_MHZ] = 9,
-};
-
-static const u8 t_hs_trail_val[] = {
-       [HS_CLK_RANGE_80_110_MHZ] = 0x22,
-       [HS_CLK_RANGE_110_150_MHZ] = 0x45,
-       [HS_CLK_RANGE_150_200_MHZ] = 0x0b,
-       [HS_CLK_RANGE_200_250_MHZ] = 0x16,
-       [HS_CLK_RANGE_250_300_MHZ] = 0x2c,
-       [HS_CLK_RANGE_300_400_MHZ] = 0x33,
-       [HS_CLK_RANGE_400_500_MHZ] = 0x4e,
-       [HS_CLK_RANGE_500_600_MHZ] = 0x3a,
-       [HS_CLK_RANGE_600_700_MHZ] = 0x6a,
-       [HS_CLK_RANGE_700_800_MHZ] = 0x29,
-       [HS_CLK_RANGE_800_1000_MHZ] = 0x27,
+struct t_param {
+       u32 hs_clk_rate;
+       u8 t_hs_prepare;
+       u8 clock_lane_t_hs_zero;
+       u8 data_lane_t_hs_zero;
+       u8 t_hs_trail;
 };
 
 struct mipi_dphy_timing {
 };
 
 struct mipi_dphy_timing {
@@ -226,6 +171,28 @@ struct inno_mipi_dphy {
        u32 lane_mbps;
 };
 
        u32 lane_mbps;
 };
 
+static const u32 lane_reg_offset[] = {
+       [CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
+       [DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
+       [DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
+       [DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
+       [DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
+};
+
+static const struct t_param t_fixed_param_table[] = {
+       { 110, 0x20, 0x16, 0x02, 0x22},
+       { 150, 0x06, 0x16, 0x03, 0x45},
+       { 200, 0x18, 0x17, 0x04, 0x0b},
+       { 250, 0x05, 0x17, 0x05, 0x16},
+       { 300, 0x51, 0x18, 0x06, 0x2c},
+       { 400, 0x64, 0x19, 0x07, 0x33},
+       { 500, 0x20, 0x1b, 0x07, 0x4e},
+       { 600, 0x6a, 0x1d, 0x08, 0x3a},
+       { 700, 0x3e, 0x1e, 0x08, 0x6a},
+       { 800, 0x21, 0x1f, 0x09, 0x29},
+       {1000, 0x09, 0x20, 0x09, 0x27}
+};
+
 static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
 {
        writel_relaxed(val, inno->regs + reg);
 static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
 {
        writel_relaxed(val, inno->regs + reg);
@@ -280,46 +247,85 @@ static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
                                         struct inno_mipi_dphy_timing *t)
 {
        u32 base = lane_reg_offset[lane_type];
                                         struct inno_mipi_dphy_timing *t)
 {
        u32 base = lane_reg_offset[lane_type];
+       u32 val, mask;
 
 
-       inno_write(inno, base + T_HS_PREPARE_OFFSET,
-                  T_HS_PREPARE(t->t_hs_prepare));
-       inno_write(inno, base + T_HS_ZERO_OFFSET, T_HS_ZERO(t->t_hs_zero));
-       inno_write(inno, base + T_HS_TRAIL_OFFSET, T_HS_TRAIL(t->t_hs_trail));
-       inno_write(inno, base + T_HS_EXIT_OFFSET, T_HS_EXIT(t->t_hs_exit));
-       inno_write(inno, base + T_CLK_POST_OFFSET, T_CLK_POST(t->t_clk_post));
-       inno_write(inno, base + T_CLK_PRE_OFFSET, T_CLK_PRE(t->t_clk_pre));
-       inno_write(inno, base + T_WAKUP_H_OFFSET, T_WAKUP_H(t->t_wakup_h));
-       inno_write(inno, base + T_WAKUP_L_OFFSET, T_WAKUP_L(t->t_wakup_l));
-       inno_write(inno, base + T_LPX_OFFSET, T_LPX(t->t_lpx));
-       inno_write(inno, base + T_TA_GO_OFFSET, T_TA_GO(t->t_ta_go));
-       inno_write(inno, base + T_TA_SURE_OFFSET, T_TA_SURE(t->t_ta_sure));
-       inno_write(inno, base + T_TA_WAIT_OFFSET, T_TA_WAIT(t->t_ta_wait));
+       mask = T_HS_PREPARE_MASK;
+       val = T_HS_PREPARE(t->t_hs_prepare);
+       inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, mask, val);
+
+       mask = T_HS_ZERO_MASK;
+       val = T_HS_ZERO(t->t_hs_zero);
+       inno_update_bits(inno, base + T_HS_ZERO_OFFSET, mask, val);
+
+       mask = T_HS_TRAIL_MASK;
+       val = T_HS_TRAIL(t->t_hs_trail);
+       inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, mask, val);
+
+       mask = T_HS_EXIT_MASK;
+       val = T_HS_EXIT(t->t_hs_exit);
+       inno_update_bits(inno, base + T_HS_EXIT_OFFSET, mask, val);
+
+       if (lane_type == CLOCK_LANE) {
+               mask = T_CLK_POST_MASK;
+               val = T_CLK_POST(t->t_clk_post);
+               inno_update_bits(inno, base + T_CLK_POST_OFFSET, mask, val);
+
+               mask = T_CLK_PRE_MASK;
+               val = T_CLK_PRE(t->t_clk_pre);
+               inno_update_bits(inno, base + T_CLK_PRE_OFFSET, mask, val);
+       }
+
+       mask = T_WAKUP_H_MASK;
+       val = T_WAKUP_H(t->t_wakup_h);
+       inno_update_bits(inno, base + T_WAKUP_H_OFFSET, mask, val);
+
+       mask = T_WAKUP_L_MASK;
+       val = T_WAKUP_L(t->t_wakup_l);
+       inno_update_bits(inno, base + T_WAKUP_L_OFFSET, mask, val);
+
+       mask = T_LPX_MASK;
+       val = T_LPX(t->t_lpx);
+       inno_update_bits(inno, base + T_LPX_OFFSET, mask, val);
+
+       mask = T_TA_GO_MASK;
+       val = T_TA_GO(t->t_ta_go);
+       inno_update_bits(inno, base + T_TA_GO_OFFSET, mask, val);
+
+       mask = T_TA_SURE_MASK;
+       val = T_TA_SURE(t->t_ta_sure);
+       inno_update_bits(inno, base + T_TA_SURE_OFFSET, mask, val);
+
+       mask = T_TA_WAIT_MASK;
+       val = T_TA_WAIT(t->t_ta_wait);
+       inno_update_bits(inno, base + T_TA_WAIT_OFFSET, mask, val);
 }
 
 }
 
-static enum hs_clk_range inno_mipi_dphy_get_hs_clk_range(u32 lane_mbps)
+static int inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
+                                         u32 hs_clk_rate,
+                                         enum lane_type lane_type)
 {
 {
-       if (lane_mbps < 110)
-               return HS_CLK_RANGE_80_110_MHZ;
-       else if (lane_mbps < 150)
-               return HS_CLK_RANGE_110_150_MHZ;
-       else if (lane_mbps < 200)
-               return HS_CLK_RANGE_150_200_MHZ;
-       else if (lane_mbps < 250)
-               return HS_CLK_RANGE_200_250_MHZ;
-       else if (lane_mbps < 300)
-               return HS_CLK_RANGE_250_300_MHZ;
-       else if (lane_mbps < 400)
-               return HS_CLK_RANGE_400_500_MHZ;
-       else if (lane_mbps < 500)
-               return HS_CLK_RANGE_400_500_MHZ;
-       else if (lane_mbps < 600)
-               return HS_CLK_RANGE_500_600_MHZ;
-       else if (lane_mbps < 700)
-               return HS_CLK_RANGE_600_700_MHZ;
-       else if (lane_mbps < 800)
-               return HS_CLK_RANGE_700_800_MHZ;
+       const struct t_param *param;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(t_fixed_param_table); i++) {
+               if (hs_clk_rate <= t_fixed_param_table[i].hs_clk_rate)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(t_fixed_param_table))
+               return -EINVAL;
+
+       param = &t_fixed_param_table[i];
+
+       if (lane_type == CLOCK_LANE)
+               t->t_hs_zero = param->clock_lane_t_hs_zero;
        else
        else
-               return HS_CLK_RANGE_800_1000_MHZ;
+               t->t_hs_zero = param->data_lane_t_hs_zero;
+
+       t->t_hs_prepare = param->t_hs_prepare;
+       t->t_hs_trail = param->t_hs_trail;
+
+       return 0;
 }
 
 static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
 }
 
 static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
@@ -330,22 +336,12 @@ static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
        u32 txbyteclkhs = inno->lane_mbps / 8;  /* MHz */
        u32 txclkesc = 20;      /* MHz */
        u32 UI = DIV_ROUND_CLOSEST(NSEC_PER_USEC, inno->lane_mbps);     /* ns */
        u32 txbyteclkhs = inno->lane_mbps / 8;  /* MHz */
        u32 txclkesc = 20;      /* MHz */
        u32 UI = DIV_ROUND_CLOSEST(NSEC_PER_USEC, inno->lane_mbps);     /* ns */
-       enum hs_clk_range range;
 
        memset(&timing, 0, sizeof(timing));
        memset(&data, 0, sizeof(data));
 
        mipi_dphy_timing_get_default(&timing, UI);
 
        memset(&timing, 0, sizeof(timing));
        memset(&data, 0, sizeof(data));
 
        mipi_dphy_timing_get_default(&timing, UI);
-
-       range = inno_mipi_dphy_get_hs_clk_range(inno->lane_mbps);
-
-       if (lane_type == CLOCK_LANE)
-               data.t_hs_zero = clock_lane_t_hs_zero_val[range];
-       else
-               data.t_hs_zero = data_lane_t_hs_zero_val[range];
-
-       data.t_hs_prepare = t_hs_prepare_val[range];
-       data.t_hs_trail = t_hs_trail_val[range];
+       inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps, lane_type);
 
        /* txbyteclkhs domain */
        data.t_hs_exit = DIV_ROUND_UP(txbyteclkhs * timing.hsexit,
 
        /* txbyteclkhs domain */
        data.t_hs_exit = DIV_ROUND_UP(txbyteclkhs * timing.hsexit,
@@ -374,7 +370,7 @@ static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
        unsigned int target_mbps = 1000;
        unsigned int max_mbps = 1000;
        u32 fbdiv = 1, prediv = 1;
        unsigned int target_mbps = 1000;
        unsigned int max_mbps = 1000;
        u32 fbdiv = 1, prediv = 1;
-       u32 val;
+       u32 val, mask;
 
        mpclk = DIV_ROUND_UP(panel->vm.pixelclock, USEC_PER_SEC);
        if (mpclk) {
 
        mpclk = DIV_ROUND_UP(panel->vm.pixelclock, USEC_PER_SEC);
        if (mpclk) {
@@ -390,6 +386,8 @@ static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
        tmp = pllref;
 
        for (i = 1; i < 6; i++) {
        tmp = pllref;
 
        for (i = 1; i < 6; i++) {
+               if (pllref % i)
+                       continue;
                pre = pllref / i;
                if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
                        tmp = target_mbps % pre;
                pre = pllref / i;
                if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
                        tmp = target_mbps % pre;
@@ -400,17 +398,19 @@ static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
                        break;
        }
 
                        break;
        }
 
-       inno->lane_mbps = pllref * fbdiv / prediv;
+       inno->lane_mbps = pllref / prediv * fbdiv;
        phy_set_bus_width(inno->phy, inno->lane_mbps);
 
        phy_set_bus_width(inno->phy, inno->lane_mbps);
 
+       mask = FBDIV_8_MASK | PREDIV_MASK;
        val = FBDIV_8(fbdiv >> 8) | PREDIV(prediv);
        val = FBDIV_8(fbdiv >> 8) | PREDIV(prediv);
-       inno_write(inno, INNO_PHY_PLL_CTRL_0, val);
+       inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, mask, val);
 
 
+       mask = FBDIV_7_0_MASK;
        val = FBDIV_7_0(fbdiv);
        val = FBDIV_7_0(fbdiv);
-       inno_write(inno, INNO_PHY_PLL_CTRL_1, val);
+       inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, mask, val);
 
 
-       dev_info(inno->dev, "fin=%d, fout=%d, prediv=%d, fbdiv=%d\n",
-                pllref, inno->lane_mbps, prediv, fbdiv);
+       dev_info(inno->dev, "fin=%d, target_mbps=%d, fout=%d, prediv=%d, fbdiv=%d\n",
+                pllref, target_mbps, inno->lane_mbps, prediv, fbdiv);
 }
 
 static void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)
 }
 
 static void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)