Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a44769b4 authored by Linus Walleij's avatar Linus Walleij Committed by Rob Clark
Browse files

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
parent 86fe3f54
Loading
Loading
Loading
Loading
+31 −35
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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 {
+12 −30
Original line number Diff line number Diff line
@@ -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,29 +69,20 @@ 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,
					gpiod_direction_output(gpio.gpiod,
							       gpio.value);
				} else {
					gpio_direction_input(gpio.num);
					gpio_set_value_cansleep(gpio.num,
					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 {