|
@@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = {
|
|
|
71, 35 /* 91 - 92 */
|
|
|
};
|
|
|
|
|
|
+#ifdef DSI_CLK_FROM_RR
|
|
|
+
|
|
|
static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
|
|
int pixel_format, int video_mode_format,
|
|
|
int lane_count, bool eotp)
|
|
@@ -121,7 +123,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
|
|
|
|
|
/* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */
|
|
|
dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8;
|
|
|
- dsi_clk = dsi_bit_clock_hz / (1000 * 1000);
|
|
|
+ dsi_clk = dsi_bit_clock_hz / 1000;
|
|
|
|
|
|
if (eotp && video_mode_format == VIDEO_MODE_BURST)
|
|
|
dsi_clk *= 2;
|
|
@@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
|
|
return dsi_clk;
|
|
|
}
|
|
|
|
|
|
-#ifdef MNP_FROM_TABLE
|
|
|
-
|
|
|
-struct dsi_clock_table {
|
|
|
- u32 freq;
|
|
|
- u8 m;
|
|
|
- u8 p;
|
|
|
-};
|
|
|
-
|
|
|
-static const struct dsi_clock_table dsi_clk_tbl[] = {
|
|
|
- {300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6},
|
|
|
- {343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6},
|
|
|
- {383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5},
|
|
|
- {401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5},
|
|
|
- {405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5},
|
|
|
- {409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5},
|
|
|
- {413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5},
|
|
|
- {417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5},
|
|
|
- {430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5},
|
|
|
- {470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4},
|
|
|
- {510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4},
|
|
|
- {550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3},
|
|
|
- {590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3},
|
|
|
- {630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3},
|
|
|
- {670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3},
|
|
|
- {710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3},
|
|
|
- {750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2},
|
|
|
- {790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2},
|
|
|
- {1000, 80, 2}, /* dsi clock frequency in Mhz*/
|
|
|
-};
|
|
|
+#else
|
|
|
|
|
|
-static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|
|
+/* Get DSI clock from pixel clock */
|
|
|
+static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
|
|
|
+ int pixel_format, int lane_count)
|
|
|
{
|
|
|
- unsigned int i;
|
|
|
- u8 m;
|
|
|
- u8 n;
|
|
|
- u8 p;
|
|
|
- u32 m_seed;
|
|
|
-
|
|
|
- if (dsi_clk < 300 || dsi_clk > 1000)
|
|
|
- return -ECHRNG;
|
|
|
+ u32 dsi_clk_khz;
|
|
|
+ u32 bpp;
|
|
|
|
|
|
- for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
|
|
|
- if (dsi_clk_tbl[i].freq > dsi_clk)
|
|
|
- break;
|
|
|
+ switch (pixel_format) {
|
|
|
+ default:
|
|
|
+ case VID_MODE_FORMAT_RGB888:
|
|
|
+ case VID_MODE_FORMAT_RGB666_LOOSE:
|
|
|
+ bpp = 24;
|
|
|
+ break;
|
|
|
+ case VID_MODE_FORMAT_RGB666:
|
|
|
+ bpp = 18;
|
|
|
+ break;
|
|
|
+ case VID_MODE_FORMAT_RGB565:
|
|
|
+ bpp = 16;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- m = dsi_clk_tbl[i].m;
|
|
|
- p = dsi_clk_tbl[i].p;
|
|
|
- m_seed = lfsr_converts[m - 62];
|
|
|
- n = 1;
|
|
|
- dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2);
|
|
|
- dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT |
|
|
|
- m_seed << DSI_PLL_M1_DIV_SHIFT;
|
|
|
+ /* DSI data rate = pixel clock * bits per pixel / lane count
|
|
|
+ pixel clock is converted from KHz to Hz */
|
|
|
+ dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count);
|
|
|
|
|
|
- return 0;
|
|
|
+ return dsi_clk_khz;
|
|
|
}
|
|
|
|
|
|
-#else
|
|
|
+#endif
|
|
|
|
|
|
static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|
|
{
|
|
@@ -200,13 +175,14 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|
|
u32 calc_p;
|
|
|
u32 m_seed;
|
|
|
|
|
|
- if (dsi_clk < 300 || dsi_clk > 1150) {
|
|
|
+ /* dsi_clk is expected in KHZ */
|
|
|
+ if (dsi_clk < 300000 || dsi_clk > 1150000) {
|
|
|
DRM_ERROR("DSI CLK Out of Range\n");
|
|
|
return -ECHRNG;
|
|
|
}
|
|
|
|
|
|
ref_clk = 25000;
|
|
|
- target_dsi_clk = dsi_clk * 1000;
|
|
|
+ target_dsi_clk = dsi_clk;
|
|
|
error = 0xFFFFFFFF;
|
|
|
calc_m = 0;
|
|
|
calc_p = 0;
|
|
@@ -235,8 +211,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* XXX: The muxing and gating is hard coded for now. Need to add support for
|
|
|
* sharing PLLs with two DSI outputs.
|
|
@@ -251,9 +225,8 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
|
|
|
struct dsi_mnp dsi_mnp;
|
|
|
u32 dsi_clk;
|
|
|
|
|
|
- dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format,
|
|
|
- intel_dsi->video_mode_format,
|
|
|
- intel_dsi->lane_count, !intel_dsi->eot_disable);
|
|
|
+ dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
|
|
|
+ intel_dsi->lane_count);
|
|
|
|
|
|
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
|
|
|
if (ret) {
|