drm/msm/hdmi: Convert to use GPIO descriptors
authorLinus Walleij <linus.walleij@linaro.org>
Sat, 29 Jun 2019 12:59:31 +0000 (14:59 +0200)
committerRob Clark <robdclark@chromium.org>
Tue, 3 Sep 2019 23:16:58 +0000 (16:16 -0700)
This switches the MSM HDMI code to use GPIO descriptors.
Normally we would fetch the GPIOs from the device with the
flags GPIOD_IN or GPIOD_OUT_[LOW|HIGH] to set up the lines
immediately, but since the code seems eager to actively
drive the lines high/low when turning HDMI on and off, we
just fetch the GPIOs as-is and keep the code explicitly
driving them.

The old code would try legacy bindings (GPIOs without any
"-gpios" suffix) but this has been moved to the gpiolib
as a quirk by the previous patch.

Cc: Rob Clark <robdclark@gmail.com>
Cc: Sean Paul <sean@poorly.run>
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi_connector.c

index 0e4217b..355afb9 100644 (file)
@@ -425,38 +425,6 @@ static const struct {
        { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
 };
 
-static int msm_hdmi_get_gpio(struct device_node *of_node, const char *name)
-{
-       int gpio;
-
-       /* try with the gpio names as in the table (downstream bindings) */
-       gpio = of_get_named_gpio(of_node, name, 0);
-       if (gpio < 0) {
-               char name2[32];
-
-               /* try with the gpio names as in the upstream bindings */
-               snprintf(name2, sizeof(name2), "%s-gpios", name);
-               gpio = of_get_named_gpio(of_node, name2, 0);
-               if (gpio < 0) {
-                       char name3[32];
-
-                       /*
-                        * try again after stripping out the "qcom,hdmi-tx"
-                        * prefix. This is mainly to match "hpd-gpios" used
-                        * in the upstream bindings
-                        */
-                       if (sscanf(name2, "qcom,hdmi-tx-%s", name3))
-                               gpio = of_get_named_gpio(of_node, name3, 0);
-               }
-
-               if (gpio < 0) {
-                       DBG("failed to get gpio: %s (%d)", name, gpio);
-                       gpio = -1;
-               }
-       }
-       return gpio;
-}
-
 /*
  * HDMI audio codec callbacks
  */
@@ -582,11 +550,39 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
        hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
 
        for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
-               hdmi_cfg->gpios[i].num = msm_hdmi_get_gpio(of_node,
-                                               msm_hdmi_gpio_pdata[i].name);
+               const char *name = msm_hdmi_gpio_pdata[i].name;
+               struct gpio_desc *gpiod;
+
+               /*
+                * We are fetching the GPIO lines "as is" since the connector
+                * code is enabling and disabling the lines. Until that point
+                * the power-on default value will be kept.
+                */
+               gpiod = devm_gpiod_get_optional(dev, name, GPIOD_ASIS);
+               /* This will catch e.g. -PROBE_DEFER */
+               if (IS_ERR(gpiod))
+                       return PTR_ERR(gpiod);
+               if (!gpiod) {
+                       /* Try a second time, stripping down the name */
+                       char name3[32];
+
+                       /*
+                        * Try again after stripping out the "qcom,hdmi-tx"
+                        * prefix. This is mainly to match "hpd-gpios" used
+                        * in the upstream bindings.
+                        */
+                       if (sscanf(name, "qcom,hdmi-tx-%s", name3))
+                               gpiod = devm_gpiod_get_optional(dev, name3, GPIOD_ASIS);
+                       if (IS_ERR(gpiod))
+                               return PTR_ERR(gpiod);
+                       if (!gpiod)
+                               DBG("failed to get gpio: %s", name);
+               }
+               hdmi_cfg->gpios[i].gpiod = gpiod;
+               if (gpiod)
+                       gpiod_set_consumer_name(gpiod, msm_hdmi_gpio_pdata[i].label);
                hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output;
                hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value;
-               hdmi_cfg->gpios[i].label = msm_hdmi_gpio_pdata[i].label;
        }
 
        dev->platform_data = hdmi_cfg;
index 9828658..bdac452 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
 #include <linux/hdmi.h>
 
 #include "msm_drv.h"
@@ -22,10 +23,9 @@ struct hdmi_phy;
 struct hdmi_platform_config;
 
 struct hdmi_gpio_data {
-       int num;
+       struct gpio_desc *gpiod;
        bool output;
        int value;
-       const char *label;
 };
 
 struct hdmi_audio {
index 1976304..839822d 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/pinctrl/consumer.h>
 
 #include "msm_kms.h"
@@ -69,30 +69,21 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi)
 
 static int gpio_config(struct hdmi *hdmi, bool on)
 {
-       struct device *dev = &hdmi->pdev->dev;
        const struct hdmi_platform_config *config = hdmi->config;
-       int ret, i;
+       int i;
 
        if (on) {
                for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
                        struct hdmi_gpio_data gpio = config->gpios[i];
 
-                       if (gpio.num != -1) {
-                               ret = gpio_request(gpio.num, gpio.label);
-                               if (ret) {
-                                       DRM_DEV_ERROR(dev,
-                                               "'%s'(%d) gpio_request failed: %d\n",
-                                               gpio.label, gpio.num, ret);
-                                       goto err;
-                               }
-
+                       if (gpio.gpiod) {
                                if (gpio.output) {
-                                       gpio_direction_output(gpio.num,
-                                                             gpio.value);
+                                       gpiod_direction_output(gpio.gpiod,
+                                                              gpio.value);
                                } else {
-                                       gpio_direction_input(gpio.num);
-                                       gpio_set_value_cansleep(gpio.num,
-                                                               gpio.value);
+                                       gpiod_direction_input(gpio.gpiod);
+                                       gpiod_set_value_cansleep(gpio.gpiod,
+                                                                gpio.value);
                                }
                        }
                }
@@ -102,29 +93,20 @@ static int gpio_config(struct hdmi *hdmi, bool on)
                for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
                        struct hdmi_gpio_data gpio = config->gpios[i];
 
-                       if (gpio.num == -1)
+                       if (!gpio.gpiod)
                                continue;
 
                        if (gpio.output) {
                                int value = gpio.value ? 0 : 1;
 
-                               gpio_set_value_cansleep(gpio.num, value);
+                               gpiod_set_value_cansleep(gpio.gpiod, value);
                        }
-
-                       gpio_free(gpio.num);
                };
 
                DBG("gpio off");
        }
 
        return 0;
-err:
-       while (i--) {
-               if (config->gpios[i].num != -1)
-                       gpio_free(config->gpios[i].num);
-       }
-
-       return ret;
 }
 
 static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
@@ -312,7 +294,7 @@ static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
        const struct hdmi_platform_config *config = hdmi->config;
        struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
 
-       return gpio_get_value(hpd_gpio.num) ?
+       return gpiod_get_value(hpd_gpio.gpiod) ?
                        connector_status_connected :
                        connector_status_disconnected;
 }
@@ -331,7 +313,7 @@ static enum drm_connector_status hdmi_connector_detect(
         * some platforms may not have hpd gpio. Rely only on the status
         * provided by REG_HDMI_HPD_INT_STATUS in this case.
         */
-       if (hpd_gpio.num == -1)
+       if (!hpd_gpio.gpiod)
                return detect_reg(hdmi);
 
        do {