drm/i915: Pixel Clock changes for DSI dual link
authorGaurav K Singh <gaurav.k.singh@intel.com>
Fri, 5 Dec 2014 08:43:41 +0000 (14:13 +0530)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 5 Dec 2014 14:28:20 +0000 (15:28 +0100)
For dual link MIPI Panels, each port needs half of pixel clock. Pixel overlap
can be enabled if needed by panel, then in that case, pixel clock will be
increased for extra pixels.

v2 : Address review comments by Jani
     - Removed the bit mask used for ->dual_link
     - Used DSI instead of MIPI for #define variables

v3: Added the VLV_DISPLAY_BASE to VLV_CHICKEN_3 register

Signed-off-by: Gaurav K Singh <gaurav.k.singh@intel.com>
Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c

index b4a11ab7cb632fc58393368e64e469104570f729..869e5ae1b011a0133e47a090d24077f6913b4720 100644 (file)
@@ -6030,6 +6030,10 @@ enum punit_power_well {
 #define GEN8_PMINTR_REDIRECT_TO_NON_DISP       (1<<31)
 #define VLV_PWRDWNUPCTL                                0xA294
 
+#define VLV_CHICKEN_3                          (VLV_DISPLAY_BASE + 0x7040C)
+#define  PIXEL_OVERLAP_CNT_MASK                        (3 << 30)
+#define  PIXEL_OVERLAP_CNT_SHIFT               30
+
 #define GEN6_PMISR                             0x44020
 #define GEN6_PMIMR                             0x44024 /* rps_lock */
 #define GEN6_PMIIR                             0x44028
index de01167d8a51b953663f477013214e50e943dbf4..a6a8710f665f5c8b37c28fd3b62ad7d0593a00b4 100644 (file)
@@ -818,7 +818,8 @@ struct mipi_config {
 #define DUAL_LINK_PIXEL_ALT    2
        u16 dual_link:2;
        u16 lane_cnt:2;
-       u16 rsvd3:12;
+       u16 pixel_overlap:3;
+       u16 rsvd3:9;
 
        u16 rsvd4;
 
index fd4d3972c8cda998433b2cd48efea24b9324610e..a1b93c5590256031165bf53e0168fe49094dbede 100644 (file)
@@ -111,6 +111,14 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
        enum port port;
        u32 temp;
 
+       if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
+               temp = I915_READ(VLV_CHICKEN_3);
+               temp &= ~PIXEL_OVERLAP_CNT_MASK |
+                                       intel_dsi->pixel_overlap <<
+                                       PIXEL_OVERLAP_CNT_SHIFT;
+               I915_WRITE(VLV_CHICKEN_3, temp);
+       }
+
        for_each_dsi_port(port, intel_dsi->ports) {
                temp = I915_READ(MIPI_PORT_CTRL(port));
                temp &= ~LANE_CONFIGURATION_MASK;
index f2cc2fc8c979dcecc789863903515e37145b1922..8fe2064dd8045c87d742661c2208998ba8edf515 100644 (file)
 #include <drm/drm_crtc.h>
 #include "intel_drv.h"
 
+/* Dual Link support */
+#define DSI_DUAL_LINK_NONE             0
+#define DSI_DUAL_LINK_FRONT_BACK       1
+#define DSI_DUAL_LINK_PIXEL_ALT                2
+
 struct intel_dsi_device {
        unsigned int panel_id;
        const char *name;
@@ -105,6 +110,7 @@ struct intel_dsi {
 
        u8 escape_clk_div;
        u8 dual_link;
+       u8 pixel_overlap;
        u32 port_bits;
        u32 bw_timer;
        u32 dphy_reg;
index f60146f84467fce346e52d05011d498cf347a68e..f8c2269c434ce26e641d4492c230d4a15c500e8e 100644 (file)
@@ -288,6 +288,7 @@ static bool generic_init(struct intel_dsi_device *dsi)
        intel_dsi->lane_count = mipi_config->lane_cnt + 1;
        intel_dsi->pixel_format = mipi_config->videomode_color_format << 7;
        intel_dsi->dual_link = mipi_config->dual_link;
+       intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
 
        if (intel_dsi->dual_link)
                intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C));
@@ -310,6 +311,20 @@ static bool generic_init(struct intel_dsi_device *dsi)
 
        pclk = mode->clock;
 
+       /* In dual link mode each port needs half of pixel clock */
+       if (intel_dsi->dual_link) {
+               pclk = pclk / 2;
+
+               /* we can enable pixel_overlap if needed by panel. In this
+                * case we need to increase the pixelclock for extra pixels
+                */
+               if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
+                       pclk += DIV_ROUND_UP(mode->vtotal *
+                                               intel_dsi->pixel_overlap *
+                                               60, 1000);
+               }
+       }
+
        /* Burst Mode Ratio
         * Target ddr frequency from VBT / non burst ddr freq
         * multiply by 100 to preserve remainder
@@ -504,6 +519,12 @@ static bool generic_init(struct intel_dsi_device *dsi)
        DRM_DEBUG_KMS("Clockstop %s\n", intel_dsi->clock_stop ?
                                                "disabled" : "enabled");
        DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
+       if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
+               DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
+       else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT)
+               DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n");
+       else
+               DRM_DEBUG_KMS("Dual link: NONE\n");
        DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format);
        DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div);
        DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout);