diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2019-06-29 08:59:31 -0400 |
---|---|---|
committer | Rob Clark <robdclark@chromium.org> | 2019-09-03 19:16:58 -0400 |
commit | a44769b407ecd9df2dd86d8b855412e3aff8b41b (patch) | |
tree | e226dd7911d21884f3929a99d5eaba86864e364a | |
parent | 86fe3f546eb36d3a2eb252046dd2381ef02aa70c (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.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 42 |
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 | ||
428 | static 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; | |||
22 | struct hdmi_platform_config; | 23 | struct hdmi_platform_config; |
23 | 24 | ||
24 | struct hdmi_gpio_data { | 25 | struct 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 | ||
31 | struct hdmi_audio { | 31 | struct 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 | ||
70 | static int gpio_config(struct hdmi *hdmi, bool on) | 70 | static 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; |
121 | err: | ||
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 | ||
130 | static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) | 112 | static 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 { |