[RFC PATCH 05/18] drm/i915: Adjusting the pclk for dual link and burst mode

Ramalingam C
2015-06-26T14:00:01Z

dsi_clk is calculated for the clock of passed drm_display_mode
and pclk is adjusted considering dual link and the burst mode.

This change is required to make the drrs to co-exist with dual link
and Burst mode.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
drivers/gpu/drm/i915/intel_dsi_pll.c | 77 ++++++++++++++++++++++++++++++----
1 file changed, 68 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index c58eb02..ce5949f 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -128,13 +128,11 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,

#else

-/* Get DSI clock from pixel clock */
-static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
+static u32 intel_get_bits_per_pixel(struct intel_dsi *intel_dsi)
{
- u32 dsi_clk_khz;
u32 bpp;

- switch (pixel_format) {
+ switch (intel_dsi->pixel_format) {
default:
case VID_MODE_FORMAT_RGB888:
case VID_MODE_FORMAT_RGB666_LOOSE:
@@ -147,10 +145,70 @@ static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
bpp = 16;
break;
}
+ return bpp;
+}
+
+void adjust_pclk_for_dual_link(struct intel_dsi *intel_dsi,
+ struct drm_display_mode *mode, u32 *pclk)
+{
+ /* In dual link mode each port needs half of pixel clock */
+ *pclk = *pclk / 2;
+
+ /*
+ * If pixel_overlap needed by panel, we need to increase the pixel
+ * clock for extra pixels.
+ */
+ if (intel_dsi->dual_link & DSI_DUAL_LINK_FRONT_BACK)
+ *pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap *
+ mode->vrefresh, 1000);
+}
+
+void adjust_pclk_for_burst_mode(u32 *pclk, u16 burst_mode_ratio)
+{
+ *pclk = DIV_ROUND_UP(*pclk * burst_mode_ratio, 100);
+}
+
+
+/* To recalculate the pclk considering dual link and Burst mode */
+static u32 intel_drrs_calc_pclk(struct intel_dsi *intel_dsi,
+ struct drm_display_mode *mode)
+{
+ u32 pclk;
+ int pkt_pixel_size; /* in bits */

- /* DSI data rate = pixel clock * bits per pixel / lane count
- pixel clock is converted from KHz to Hz */
- dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count);
+ pclk = mode->clock;
+
+ pkt_pixel_size = intel_get_bits_per_pixel(intel_dsi);
+
+ /* In dual link mode each port needs half of pixel clock */
+ if (intel_dsi->dual_link)
+ adjust_pclk_for_dual_link(intel_dsi, mode, &pclk);
+
+ /* Retaining the same Burst mode ratio for DRRS. Need to be tested */
+ if (intel_dsi->burst_mode_ratio > 100)
+ adjust_pclk_for_burst_mode(&pclk, intel_dsi->burst_mode_ratio);
+
+ DRM_DEBUG_KMS("mode->clock : %d, pclk : %d\n", mode->clock, pclk);
+ return pclk;
+}
+
+/* Get DSI clock from pixel clock */
+static u32 dsi_clk_from_pclk(struct intel_dsi *intel_dsi,
+ struct drm_display_mode *mode)
+{
+ u32 dsi_clk_khz;
+ u32 bpp;
+ u32 pclk;
+
+ bpp = intel_get_bits_per_pixel(intel_dsi);
+
+ pclk = intel_drrs_calc_pclk(intel_dsi, mode);
+
+ /*
+ * DSI data rate = pixel clock * bits per pixel / lane count
+ * pixel clock is converted from KHz to Hz
+ */
+ dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, intel_dsi->lane_count);

return dsi_clk_khz;
}
@@ -205,12 +263,13 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ struct intel_connector *intel_connector = intel_dsi->attached_connector;
int ret;
struct dsi_mnp dsi_mnp;
u32 dsi_clk;

- dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
- intel_dsi->lane_count);
+ dsi_clk = dsi_clk_from_pclk(intel_dsi,
+ intel_connector->panel.fixed_mode);

ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
if (ret) {