aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-06-29 08:59:31 -0400
committerRob Clark <robdclark@chromium.org>2019-09-03 19:16:58 -0400
commita44769b407ecd9df2dd86d8b855412e3aff8b41b (patch)
treee226dd7911d21884f3929a99d5eaba86864e364a
parent86fe3f546eb36d3a2eb252046dd2381ef02aa70c (diff)
drm/msm/hdmi: Convert to use GPIO descriptors
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>
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c66
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h4
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c42
3 files changed, 45 insertions, 67 deletions
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 0e4217be3f00..355afb936401 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -425,38 +425,6 @@ static const struct {
425 { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" }, 425 { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
426}; 426};
427 427
428static int msm_hdmi_get_gpio(struct device_node *of_node, const char *name)
429{
430 int gpio;
431
432 /* try with the gpio names as in the table (downstream bindings) */
433 gpio = of_get_named_gpio(of_node, name, 0);
434 if (gpio < 0) {
435 char name2[32];
436
437 /* try with the gpio names as in the upstream bindings */
438 snprintf(name2, sizeof(name2), "%s-gpios", name);
439 gpio = of_get_named_gpio(of_node, name2, 0);
440 if (gpio < 0) {
441 char name3[32];
442
443 /*
444 * try again after stripping out the "qcom,hdmi-tx"
445 * prefix. This is mainly to match "hpd-gpios" used
446 * in the upstream bindings
447 */
448 if (sscanf(name2, "qcom,hdmi-tx-%s", name3))
449 gpio = of_get_named_gpio(of_node, name3, 0);
450 }
451
452 if (gpio < 0) {
453 DBG("failed to get gpio: %s (%d)", name, gpio);
454 gpio = -1;
455 }
456 }
457 return gpio;
458}
459
460/* 428/*
461 * HDMI audio codec callbacks 429 * HDMI audio codec callbacks
462 */ 430 */
@@ -582,11 +550,39 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
582 hdmi_cfg->qfprom_mmio_name = "qfprom_physical"; 550 hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
583 551
584 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { 552 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
585 hdmi_cfg->gpios[i].num = msm_hdmi_get_gpio(of_node, 553 const char *name = msm_hdmi_gpio_pdata[i].name;
586 msm_hdmi_gpio_pdata[i].name); 554 struct gpio_desc *gpiod;
555
556 /*
557 * We are fetching the GPIO lines "as is" since the connector
558 * code is enabling and disabling the lines. Until that point
559 * the power-on default value will be kept.
560 */
561 gpiod = devm_gpiod_get_optional(dev, name, GPIOD_ASIS);
562 /* This will catch e.g. -PROBE_DEFER */
563 if (IS_ERR(gpiod))
564 return PTR_ERR(gpiod);
565 if (!gpiod) {
566 /* Try a second time, stripping down the name */
567 char name3[32];
568
569 /*
570 * Try again after stripping out the "qcom,hdmi-tx"
571 * prefix. This is mainly to match "hpd-gpios" used
572 * in the upstream bindings.
573 */
574 if (sscanf(name, "qcom,hdmi-tx-%s", name3))
575 gpiod = devm_gpiod_get_optional(dev, name3, GPIOD_ASIS);
576 if (IS_ERR(gpiod))
577 return PTR_ERR(gpiod);
578 if (!gpiod)
579 DBG("failed to get gpio: %s", name);
580 }
581 hdmi_cfg->gpios[i].gpiod = gpiod;
582 if (gpiod)
583 gpiod_set_consumer_name(gpiod, msm_hdmi_gpio_pdata[i].label);
587 hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output; 584 hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output;
588 hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value; 585 hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value;
589 hdmi_cfg->gpios[i].label = msm_hdmi_gpio_pdata[i].label;
590 } 586 }
591 587
592 dev->platform_data = hdmi_cfg; 588 dev->platform_data = hdmi_cfg;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 982865866a29..bdac452b00fb 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -11,6 +11,7 @@
11#include <linux/clk.h> 11#include <linux/clk.h>
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <linux/regulator/consumer.h> 13#include <linux/regulator/consumer.h>
14#include <linux/gpio/consumer.h>
14#include <linux/hdmi.h> 15#include <linux/hdmi.h>
15 16
16#include "msm_drv.h" 17#include "msm_drv.h"
@@ -22,10 +23,9 @@ struct hdmi_phy;
22struct hdmi_platform_config; 23struct hdmi_platform_config;
23 24
24struct hdmi_gpio_data { 25struct hdmi_gpio_data {
25 int num; 26 struct gpio_desc *gpiod;
26 bool output; 27 bool output;
27 int value; 28 int value;
28 const char *label;
29}; 29};
30 30
31struct hdmi_audio { 31struct hdmi_audio {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index 1976304b675e..839822d894d0 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -5,7 +5,7 @@
5 */ 5 */
6 6
7#include <linux/delay.h> 7#include <linux/delay.h>
8#include <linux/gpio.h> 8#include <linux/gpio/consumer.h>
9#include <linux/pinctrl/consumer.h> 9#include <linux/pinctrl/consumer.h>
10 10
11#include "msm_kms.h" 11#include "msm_kms.h"
@@ -69,30 +69,21 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi)
69 69
70static int gpio_config(struct hdmi *hdmi, bool on) 70static int gpio_config(struct hdmi *hdmi, bool on)
71{ 71{
72 struct device *dev = &hdmi->pdev->dev;
73 const struct hdmi_platform_config *config = hdmi->config; 72 const struct hdmi_platform_config *config = hdmi->config;
74 int ret, i; 73 int i;
75 74
76 if (on) { 75 if (on) {
77 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { 76 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
78 struct hdmi_gpio_data gpio = config->gpios[i]; 77 struct hdmi_gpio_data gpio = config->gpios[i];
79 78
80 if (gpio.num != -1) { 79 if (gpio.gpiod) {
81 ret = gpio_request(gpio.num, gpio.label);
82 if (ret) {
83 DRM_DEV_ERROR(dev,
84 "'%s'(%d) gpio_request failed: %d\n",
85 gpio.label, gpio.num, ret);
86 goto err;
87 }
88
89 if (gpio.output) { 80 if (gpio.output) {
90 gpio_direction_output(gpio.num, 81 gpiod_direction_output(gpio.gpiod,
91 gpio.value); 82 gpio.value);
92 } else { 83 } else {
93 gpio_direction_input(gpio.num); 84 gpiod_direction_input(gpio.gpiod);
94 gpio_set_value_cansleep(gpio.num, 85 gpiod_set_value_cansleep(gpio.gpiod,
95 gpio.value); 86 gpio.value);
96 } 87 }
97 } 88 }
98 } 89 }
@@ -102,29 +93,20 @@ static int gpio_config(struct hdmi *hdmi, bool on)
102 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { 93 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
103 struct hdmi_gpio_data gpio = config->gpios[i]; 94 struct hdmi_gpio_data gpio = config->gpios[i];
104 95
105 if (gpio.num == -1) 96 if (!gpio.gpiod)
106 continue; 97 continue;
107 98
108 if (gpio.output) { 99 if (gpio.output) {
109 int value = gpio.value ? 0 : 1; 100 int value = gpio.value ? 0 : 1;
110 101
111 gpio_set_value_cansleep(gpio.num, value); 102 gpiod_set_value_cansleep(gpio.gpiod, value);
112 } 103 }
113
114 gpio_free(gpio.num);
115 }; 104 };
116 105
117 DBG("gpio off"); 106 DBG("gpio off");
118 } 107 }
119 108
120 return 0; 109 return 0;
121err:
122 while (i--) {
123 if (config->gpios[i].num != -1)
124 gpio_free(config->gpios[i].num);
125 }
126
127 return ret;
128} 110}
129 111
130static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) 112static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
@@ -312,7 +294,7 @@ static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
312 const struct hdmi_platform_config *config = hdmi->config; 294 const struct hdmi_platform_config *config = hdmi->config;
313 struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX]; 295 struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
314 296
315 return gpio_get_value(hpd_gpio.num) ? 297 return gpiod_get_value(hpd_gpio.gpiod) ?
316 connector_status_connected : 298 connector_status_connected :
317 connector_status_disconnected; 299 connector_status_disconnected;
318} 300}
@@ -331,7 +313,7 @@ static enum drm_connector_status hdmi_connector_detect(
331 * some platforms may not have hpd gpio. Rely only on the status 313 * some platforms may not have hpd gpio. Rely only on the status
332 * provided by REG_HDMI_HPD_INT_STATUS in this case. 314 * provided by REG_HDMI_HPD_INT_STATUS in this case.
333 */ 315 */
334 if (hpd_gpio.num == -1) 316 if (!hpd_gpio.gpiod)
335 return detect_reg(hdmi); 317 return detect_reg(hdmi);
336 318
337 do { 319 do {