]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/msm/hdmi/hdmi_connector.c
Merge tag 'pm+acpi-4.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[karo-tx-linux.git] / drivers / gpu / drm / msm / hdmi / hdmi_connector.c
index 3f345e7c341aafa072235217b3c457b0b6785e09..a3b05ae52dae636d5a1a06fcfa646bc53474ccdf 100644 (file)
@@ -28,6 +28,55 @@ struct hdmi_connector {
 };
 #define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
 
+static void hdmi_phy_reset(struct hdmi *hdmi)
+{
+       unsigned int val;
+
+       val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET);
+       } else {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET);
+       }
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
+       } else {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET_PLL);
+       }
+
+       msleep(100);
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET);
+       } else {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET);
+       }
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET_PLL);
+       } else {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
+       }
+}
+
 static int gpio_config(struct hdmi *hdmi, bool on)
 {
        struct device *dev = &hdmi->pdev->dev;
@@ -35,21 +84,25 @@ static int gpio_config(struct hdmi *hdmi, bool on)
        int ret;
 
        if (on) {
-               ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");
-               if (ret) {
-                       dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
-                               "HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
-                       goto error1;
+               if (config->ddc_clk_gpio != -1) {
+                       ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");
+                       if (ret) {
+                               dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
+                                       "HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
+                               goto error1;
+                       }
+                       gpio_set_value_cansleep(config->ddc_clk_gpio, 1);
                }
-               gpio_set_value_cansleep(config->ddc_clk_gpio, 1);
 
-               ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
-               if (ret) {
-                       dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
-                               "HDMI_DDC_DATA", config->ddc_data_gpio, ret);
-                       goto error2;
+               if (config->ddc_data_gpio != -1) {
+                       ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
+                       if (ret) {
+                               dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
+                                       "HDMI_DDC_DATA", config->ddc_data_gpio, ret);
+                               goto error2;
+                       }
+                       gpio_set_value_cansleep(config->ddc_data_gpio, 1);
                }
-               gpio_set_value_cansleep(config->ddc_data_gpio, 1);
 
                ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
                if (ret) {
@@ -94,8 +147,12 @@ static int gpio_config(struct hdmi *hdmi, bool on)
                }
                DBG("gpio on");
        } else {
-               gpio_free(config->ddc_clk_gpio);
-               gpio_free(config->ddc_data_gpio);
+               if (config->ddc_clk_gpio != -1)
+                       gpio_free(config->ddc_clk_gpio);
+
+               if (config->ddc_data_gpio != -1)
+                       gpio_free(config->ddc_data_gpio);
+
                gpio_free(config->hpd_gpio);
 
                if (config->mux_en_gpio != -1) {
@@ -126,9 +183,11 @@ error5:
 error4:
        gpio_free(config->hpd_gpio);
 error3:
-       gpio_free(config->ddc_data_gpio);
+       if (config->ddc_data_gpio != -1)
+               gpio_free(config->ddc_data_gpio);
 error2:
-       gpio_free(config->ddc_clk_gpio);
+       if (config->ddc_clk_gpio != -1)
+               gpio_free(config->ddc_clk_gpio);
 error1:
        return ret;
 }
@@ -138,7 +197,6 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
        struct hdmi *hdmi = hdmi_connector->hdmi;
        const struct hdmi_platform_config *config = hdmi->config;
        struct device *dev = &hdmi->pdev->dev;
-       struct hdmi_phy *phy = hdmi->phy;
        uint32_t hpd_ctrl;
        int i, ret;
        unsigned long flags;
@@ -182,7 +240,7 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
        }
 
        hdmi_set_mode(hdmi, false);
-       phy->funcs->reset(phy);
+       hdmi_phy_reset(hdmi);
        hdmi_set_mode(hdmi, true);
 
        hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b);