From: Yogesh Mohan Marimuthu <[email protected]>

The GPIO configuration and register offsets are different from
baytrail for cherrytrail. Port the gpio programming accordingly
for cherrytrail in this patch.

v2: Rebase

Signed-off-by: Yogesh Mohan Marimuthu <[email protected]>
---
 drivers/gpu/drm/i915/i915_reg.h            |   23 ++++++
 drivers/gpu/drm/i915/intel_dsi_panel_vbt.c |  117 +++++++++++++++++++++++-----
 2 files changed, 122 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5bef50c..c5bea41 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -568,11 +568,21 @@
 #define   IOSF_PORT_DPIO                       0x12
 #define   IOSF_PORT_DPIO_2                     0x1a
 #define   IOSF_PORT_GPIO_NC                    0x13
+#define   CHV_IOSF_PORT_GPIO_N                 0x13
 #define   IOSF_PORT_GPIO_SC                    0x48
+#define   CHV_IOSF_PORT_GPIO_SE                        0x48
+#define   CHV_IOSF_PORT_GPIO_SW                        0xB2
 #define   IOSF_PORT_GPIO_SUS                   0xA8
+#define   CHV_IOSF_PORT_GPIO_E                 0xA8
 #define   MAX_GPIO_NUM_NC                      26
 #define   MAX_GPIO_NUM_SC                      128
 #define   MAX_GPIO_NUM                         172
+#define   CHV_MAX_GPIO_NUM_N                   72
+#define   CHV_MAX_GPIO_NUM_SE                  99
+#define   CHV_MAX_GPIO_NUM_SW                  197
+#define   CHV_MIN_GPIO_NUM_SE                  73
+#define   CHV_MIN_GPIO_NUM_SW                  100
+#define   CHV_MIN_GPIO_NUM_E                   198
 #define   IOSF_PORT_CCK                                0x14
 #define   IOSF_PORT_CCU                                0xA9
 #define   IOSF_PORT_GPS_CORE                   0x48
@@ -580,6 +590,19 @@
 #define VLV_IOSF_DATA                          (VLV_DISPLAY_BASE + 0x2104)
 #define VLV_IOSF_ADDR                          (VLV_DISPLAY_BASE + 0x2108)
 
+#define VLV_GPIO_CFG                           0x2000CC00
+#define VLV_GPIO_INPUT_DIS                     0x04
+
+#define CHV_PAD_FMLY_BASE                      0x4400
+#define CHV_PAD_FMLY_SIZE                      0x400
+#define CHV_PAD_CFG_0_1_REG_SIZE               0x8
+#define CHV_PAD_CFG_REG_SIZE                   0x4
+#define CHV_VBT_MAX_PINS_PER_FMLY              15
+
+#define CHV_GPIO_CFG_UNLOCK                    0x00000000
+#define CHV_GPIO_CFG_HiZ                       0x00008100
+#define CHV_GPIO_CFG_TX_STATE_SHIFT            1
+
 /* See configdb bunit SB addr map */
 #define BUNIT_REG_BISOC                                0x11
 
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c 
b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
index 1aa5b19..b0d09f6 100644
--- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
@@ -418,17 +418,75 @@ static const u8 *mipi_exec_delay(struct intel_dsi 
*intel_dsi, const u8 *data)
 
        return data;
 }
-
-static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
+static int chv_program_gpio(struct intel_dsi *intel_dsi,
+                               const u8 *data, const u8 **cur_data)
 {
+       struct drm_device *dev = intel_dsi->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u8 gpio, action;
+       u16 family_num;
        u16 function, pad;
-       u32 val;
        u8 block;
+
+       /*
+        * Skipping the first byte as it is of no
+        * interest for linux kernel in new VBT version
+        */
+       if (dev_priv->vbt.dsi.seq_version >= 3)
+               data++;
+
+       gpio = *data++;
+
+       /* pull up/down */
+       action = *data++;
+
+       if (dev_priv->vbt.dsi.seq_version >= 3) {
+               if (gpio <= CHV_MAX_GPIO_NUM_N) {
+                       block = CHV_IOSF_PORT_GPIO_N;
+                       DRM_DEBUG_DRIVER("GPIO is in the north Block\n");
+               } else if (gpio <= CHV_MAX_GPIO_NUM_SE) {
+                       block = CHV_IOSF_PORT_GPIO_SE;
+                       gpio = gpio - CHV_MIN_GPIO_NUM_SE;
+                       DRM_DEBUG_DRIVER("GPIO is in the south east Block\n");
+               } else if (gpio <= CHV_MAX_GPIO_NUM_SW) {
+                       block = CHV_IOSF_PORT_GPIO_SW;
+                       gpio = gpio - CHV_MIN_GPIO_NUM_SW;
+                       DRM_DEBUG_DRIVER("GPIO is in the south west Block\n");
+               } else {
+                       block = CHV_IOSF_PORT_GPIO_E;
+                       gpio = gpio - CHV_MIN_GPIO_NUM_E;
+                       DRM_DEBUG_DRIVER("GPIO is in the east Block\n");
+               }
+       } else
+               block = IOSF_PORT_GPIO_NC;
+
+       family_num =  gpio / CHV_VBT_MAX_PINS_PER_FMLY;
+       gpio = gpio - (family_num * CHV_VBT_MAX_PINS_PER_FMLY);
+       pad = CHV_PAD_FMLY_BASE + (family_num * CHV_PAD_FMLY_SIZE) +
+                       (((u16)gpio) * CHV_PAD_CFG_0_1_REG_SIZE);
+       function = pad + CHV_PAD_CFG_REG_SIZE;
+
+       mutex_lock(&dev_priv->sb_lock);
+       vlv_gpio_write(dev_priv, block, function,
+                                       CHV_GPIO_CFG_UNLOCK);
+       vlv_gpio_write(dev_priv, block, pad, CHV_GPIO_CFG_HiZ |
+                       (action << CHV_GPIO_CFG_TX_STATE_SHIFT));
+       mutex_unlock(&dev_priv->sb_lock);
+
+       *cur_data = data;
+
+       return 0;
+}
+
+static int vlv_program_gpio(struct intel_dsi *intel_dsi,
+               const u8 *data, const u8 **cur_data)
+{
        struct drm_device *dev = intel_dsi->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-
-       DRM_DEBUG_DRIVER("MIPI: executing gpio element\n");
+       u8 gpio, action;
+       u16 function, pad;
+       u32 val;
+       u8 block;
 
        /*
         * Skipping the first byte as it is of no
@@ -444,39 +502,62 @@ static const u8 *mipi_exec_gpio(struct intel_dsi 
*intel_dsi, const u8 *data)
 
        if (dev_priv->vbt.dsi.seq_version >= 3) {
                if (gpio <= MAX_GPIO_NUM_NC) {
-                       DRM_DEBUG_DRIVER("GPIO is in the north Block\n");
                        block = IOSF_PORT_GPIO_NC;
+                       DRM_DEBUG_DRIVER("GPIO is in the north Block\n");
                } else if (gpio > MAX_GPIO_NUM_NC && gpio <= MAX_GPIO_NUM_SC) {
-                       DRM_DEBUG_DRIVER("GPIO is in the south Block\n");
                        block = IOSF_PORT_GPIO_SC;
+                       DRM_DEBUG_DRIVER("GPIO is in the south Block\n");
                } else if (gpio > MAX_GPIO_NUM_SC && gpio <= MAX_GPIO_NUM) {
-                       DRM_DEBUG_DRIVER("GPIO is in the SUS Block\n");
                        block = IOSF_PORT_GPIO_SUS;
+                       DRM_DEBUG_DRIVER("GPIO is in the SUS Block\n");
                } else {
                        DRM_ERROR("GPIO number is not present in the table\n");
-                       return NULL;
+                       return -EINVAL;
                }
-       } else {
+       } else
                block = IOSF_PORT_GPIO_NC;
-       }
 
        function = gtable[gpio].function_reg;
        pad = gtable[gpio].pad_reg;
 
        mutex_lock(&dev_priv->sb_lock);
+
        if (!gtable[gpio].init) {
-               /* program the function */
-               /* FIXME: remove constant below */
-               vlv_gpio_write(dev_priv, IOSF_PORT_GPIO_NC, function, 
0x2000CC00);
-               gtable[gpio].init = 1;
+               vlv_gpio_write(dev_priv, block, function,
+                               VLV_GPIO_CFG);
+               gtable[gpio].init = true;
        }
-
-       val = 0x4 | action;
+       val = VLV_GPIO_INPUT_DIS | action;
 
        /* pull up/down */
-       vlv_gpio_write(dev_priv, IOSF_PORT_GPIO_NC, pad, val);
+       vlv_gpio_write(dev_priv, block, pad, val);
+
        mutex_unlock(&dev_priv->sb_lock);
 
+       *cur_data = data;
+
+       return 0;
+}
+
+static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
+{
+       struct drm_device *dev = intel_dsi->base.base.dev;
+       int ret;
+
+       DRM_DEBUG_DRIVER("MIPI: executing gpio element\n");
+
+       ret = -EINVAL;
+
+       if (IS_CHERRYVIEW(dev))
+               ret = chv_program_gpio(intel_dsi, data, &data);
+       else if (IS_VALLEYVIEW(dev))
+               ret = vlv_program_gpio(intel_dsi, data, &data);
+       else
+               DRM_ERROR("GPIO programming missing for this platform.\n");
+
+       if (ret)
+               return NULL;
+
        return data;
 }
 
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to