Merge tag 'topic/crc-pmic-2015-07-23' of git://anongit.freedesktop.org/drm-intel...
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / intel_dsi.c
index f4438eb5b4587d7ae0e3658392bf747d9681d044..18dd7d7360a06e58e65fb632fb7d275cc1fb05fb 100644 (file)
@@ -31,6 +31,7 @@
 #include <drm/drm_panel.h>
 #include <drm/drm_mipi_dsi.h>
 #include <linux/slab.h>
+#include <linux/gpio/consumer.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include "intel_dsi.h"
@@ -396,6 +397,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
 
                intel_dsi_port_enable(encoder);
        }
+
+       intel_panel_enable_backlight(intel_dsi->attached_connector);
 }
 
 static void intel_dsi_pre_enable(struct intel_encoder *encoder)
@@ -410,6 +413,12 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
 
+       /* Panel Enable over CRC PMIC */
+       if (intel_dsi->gpio_panel)
+               gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
+
+       msleep(intel_dsi->panel_on_delay);
+
        /* Disable DPOunit clock gating, can stall pipe
         * and we need DPLL REFA always enabled */
        tmp = I915_READ(DPLL(pipe));
@@ -427,8 +436,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
        /* put device in ready state */
        intel_dsi_device_ready(encoder);
 
-       msleep(intel_dsi->panel_on_delay);
-
        drm_panel_prepare(intel_dsi->panel);
 
        for_each_dsi_port(port, intel_dsi->ports)
@@ -456,6 +463,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
 
+       intel_panel_disable_backlight(intel_dsi->attached_connector);
+
        if (is_vid_mode(intel_dsi)) {
                /* Send Shutdown command to the panel in LP mode */
                for_each_dsi_port(port, intel_dsi->ports)
@@ -571,6 +580,10 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder)
 
        msleep(intel_dsi->panel_off_delay);
        msleep(intel_dsi->panel_pwr_cycle_delay);
+
+       /* Panel Disable over CRC PMIC */
+       if (intel_dsi->gpio_panel)
+               gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
 }
 
 static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
@@ -950,6 +963,11 @@ static void intel_dsi_encoder_destroy(struct drm_encoder *encoder)
                /* XXX: Logically this call belongs in the panel driver. */
                drm_panel_remove(intel_dsi->panel);
        }
+
+       /* dispose of the gpios */
+       if (intel_dsi->gpio_panel)
+               gpiod_put(intel_dsi->gpio_panel);
+
        intel_encoder_destroy(encoder);
 }
 
@@ -1065,6 +1083,20 @@ void intel_dsi_init(struct drm_device *dev)
                goto err;
        }
 
+       /*
+        * In case of BYT with CRC PMIC, we need to use GPIO for
+        * Panel control.
+        */
+       if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) {
+               intel_dsi->gpio_panel =
+                       gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH);
+
+               if (IS_ERR(intel_dsi->gpio_panel)) {
+                       DRM_ERROR("Failed to own gpio for panel control\n");
+                       intel_dsi->gpio_panel = NULL;
+               }
+       }
+
        intel_encoder->type = INTEL_OUTPUT_DSI;
        intel_encoder->cloneable = 0;
        drm_connector_init(dev, connector, &intel_dsi_connector_funcs,
@@ -1098,6 +1130,7 @@ void intel_dsi_init(struct drm_device *dev)
        }
 
        intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+       intel_panel_setup_backlight(connector, INVALID_PIPE);
 
        return;