drm/msm/hdmi: Clean up connector gpio usage
Make gpio allocation and usage iterative by parsing the gpios on a given platform from a list. This gives us flexibility over what all gpios exist for a platform, whether they are input or output, and what value they should be set to. In particular, this will make HDMI on 8x96 platforms easier to integrate with the driver, as it doesn't have a HPD gpio input to them. Also, it cleans things up a bit. We still use the legacy gpio api here, as we might need to backport this driver to downstream kernels. Signed-off-by: Archit Taneja <architt@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
d2eaa59000
commit
dc50f782c9
|
@ -388,7 +388,21 @@ static struct hdmi_platform_config hdmi_tx_8996_config = {
|
||||||
.hpd_freq = hpd_clk_freq_8x74,
|
.hpd_freq = hpd_clk_freq_8x74,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int get_gpio(struct device *dev, struct device_node *of_node, const char *name)
|
static const struct {
|
||||||
|
const char *name;
|
||||||
|
const bool output;
|
||||||
|
const int value;
|
||||||
|
const char *label;
|
||||||
|
} hdmi_gpio_pdata[] = {
|
||||||
|
{ "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
|
||||||
|
{ "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
|
||||||
|
{ "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
|
||||||
|
{ "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
|
||||||
|
{ "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
|
||||||
|
{ "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_gpio(struct device_node *of_node, const char *name)
|
||||||
{
|
{
|
||||||
int gpio = of_get_named_gpio(of_node, name, 0);
|
int gpio = of_get_named_gpio(of_node, name, 0);
|
||||||
if (gpio < 0) {
|
if (gpio < 0) {
|
||||||
|
@ -410,6 +424,7 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||||
static struct hdmi_platform_config *hdmi_cfg;
|
static struct hdmi_platform_config *hdmi_cfg;
|
||||||
struct hdmi *hdmi;
|
struct hdmi *hdmi;
|
||||||
struct device_node *of_node = dev->of_node;
|
struct device_node *of_node = dev->of_node;
|
||||||
|
int i;
|
||||||
|
|
||||||
hdmi_cfg = (struct hdmi_platform_config *)
|
hdmi_cfg = (struct hdmi_platform_config *)
|
||||||
of_device_get_match_data(dev);
|
of_device_get_match_data(dev);
|
||||||
|
@ -420,12 +435,14 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||||
|
|
||||||
hdmi_cfg->mmio_name = "core_physical";
|
hdmi_cfg->mmio_name = "core_physical";
|
||||||
hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
|
hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
|
||||||
hdmi_cfg->ddc_clk_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk");
|
|
||||||
hdmi_cfg->ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data");
|
for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
|
||||||
hdmi_cfg->hpd_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd");
|
hdmi_cfg->gpios[i].num = get_gpio(of_node,
|
||||||
hdmi_cfg->mux_en_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en");
|
hdmi_gpio_pdata[i].name);
|
||||||
hdmi_cfg->mux_sel_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel");
|
hdmi_cfg->gpios[i].output = hdmi_gpio_pdata[i].output;
|
||||||
hdmi_cfg->mux_lpm_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm");
|
hdmi_cfg->gpios[i].value = hdmi_gpio_pdata[i].value;
|
||||||
|
hdmi_cfg->gpios[i].label = hdmi_gpio_pdata[i].label;
|
||||||
|
}
|
||||||
|
|
||||||
dev->platform_data = hdmi_cfg;
|
dev->platform_data = hdmi_cfg;
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,18 @@
|
||||||
#include "msm_drv.h"
|
#include "msm_drv.h"
|
||||||
#include "hdmi.xml.h"
|
#include "hdmi.xml.h"
|
||||||
|
|
||||||
|
#define HDMI_MAX_NUM_GPIO 6
|
||||||
|
|
||||||
struct hdmi_phy;
|
struct hdmi_phy;
|
||||||
struct hdmi_platform_config;
|
struct hdmi_platform_config;
|
||||||
|
|
||||||
|
struct hdmi_gpio_data {
|
||||||
|
int num;
|
||||||
|
bool output;
|
||||||
|
int value;
|
||||||
|
const char *label;
|
||||||
|
};
|
||||||
|
|
||||||
struct hdmi_audio {
|
struct hdmi_audio {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
struct hdmi_audio_infoframe infoframe;
|
struct hdmi_audio_infoframe infoframe;
|
||||||
|
@ -110,8 +118,7 @@ struct hdmi_platform_config {
|
||||||
int pwr_clk_cnt;
|
int pwr_clk_cnt;
|
||||||
|
|
||||||
/* gpio's: */
|
/* gpio's: */
|
||||||
int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
|
struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
|
||||||
int mux_lpm_gpio;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
|
void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
|
||||||
|
|
|
@ -81,114 +81,54 @@ static int gpio_config(struct hdmi *hdmi, bool on)
|
||||||
{
|
{
|
||||||
struct device *dev = &hdmi->pdev->dev;
|
struct device *dev = &hdmi->pdev->dev;
|
||||||
const struct hdmi_platform_config *config = hdmi->config;
|
const struct hdmi_platform_config *config = hdmi->config;
|
||||||
int ret;
|
int ret, i;
|
||||||
|
|
||||||
if (on) {
|
if (on) {
|
||||||
if (config->ddc_clk_gpio != -1) {
|
for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
|
||||||
ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");
|
struct hdmi_gpio_data gpio = config->gpios[i];
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
|
if (gpio.num != -1) {
|
||||||
"HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
|
ret = gpio_request(gpio.num, gpio.label);
|
||||||
goto error1;
|
if (ret) {
|
||||||
|
dev_err(dev,
|
||||||
|
"'%s'(%d) gpio_request failed: %d\n",
|
||||||
|
gpio.label, gpio.num, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpio.output) {
|
||||||
|
gpio_direction_output(gpio.num,
|
||||||
|
gpio.value);
|
||||||
|
} else {
|
||||||
|
gpio_direction_input(gpio.num);
|
||||||
|
gpio_set_value_cansleep(gpio.num,
|
||||||
|
gpio.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gpio_set_value_cansleep(config->ddc_clk_gpio, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
|
|
||||||
"HDMI_HPD", config->hpd_gpio, ret);
|
|
||||||
goto error3;
|
|
||||||
}
|
|
||||||
gpio_direction_input(config->hpd_gpio);
|
|
||||||
gpio_set_value_cansleep(config->hpd_gpio, 1);
|
|
||||||
|
|
||||||
if (config->mux_en_gpio != -1) {
|
|
||||||
ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
|
|
||||||
"HDMI_MUX_EN", config->mux_en_gpio, ret);
|
|
||||||
goto error4;
|
|
||||||
}
|
|
||||||
gpio_set_value_cansleep(config->mux_en_gpio, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->mux_sel_gpio != -1) {
|
|
||||||
ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
|
|
||||||
"HDMI_MUX_SEL", config->mux_sel_gpio, ret);
|
|
||||||
goto error5;
|
|
||||||
}
|
|
||||||
gpio_set_value_cansleep(config->mux_sel_gpio, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->mux_lpm_gpio != -1) {
|
|
||||||
ret = gpio_request(config->mux_lpm_gpio,
|
|
||||||
"HDMI_MUX_LPM");
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev,
|
|
||||||
"'%s'(%d) gpio_request failed: %d\n",
|
|
||||||
"HDMI_MUX_LPM",
|
|
||||||
config->mux_lpm_gpio, ret);
|
|
||||||
goto error6;
|
|
||||||
}
|
|
||||||
gpio_set_value_cansleep(config->mux_lpm_gpio, 1);
|
|
||||||
}
|
|
||||||
DBG("gpio on");
|
DBG("gpio on");
|
||||||
} else {
|
} else {
|
||||||
if (config->ddc_clk_gpio != -1)
|
for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
|
||||||
gpio_free(config->ddc_clk_gpio);
|
struct hdmi_gpio_data gpio = config->gpios[i];
|
||||||
|
|
||||||
if (config->ddc_data_gpio != -1)
|
if (gpio.output) {
|
||||||
gpio_free(config->ddc_data_gpio);
|
int value = gpio.value ? 0 : 1;
|
||||||
|
|
||||||
gpio_free(config->hpd_gpio);
|
gpio_set_value_cansleep(gpio.num, value);
|
||||||
|
}
|
||||||
|
|
||||||
if (config->mux_en_gpio != -1) {
|
gpio_free(gpio.num);
|
||||||
gpio_set_value_cansleep(config->mux_en_gpio, 0);
|
};
|
||||||
gpio_free(config->mux_en_gpio);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->mux_sel_gpio != -1) {
|
|
||||||
gpio_set_value_cansleep(config->mux_sel_gpio, 1);
|
|
||||||
gpio_free(config->mux_sel_gpio);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->mux_lpm_gpio != -1) {
|
|
||||||
gpio_set_value_cansleep(config->mux_lpm_gpio, 0);
|
|
||||||
gpio_free(config->mux_lpm_gpio);
|
|
||||||
}
|
|
||||||
DBG("gpio off");
|
DBG("gpio off");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
err:
|
||||||
|
while (i--)
|
||||||
|
gpio_free(config->gpios[i].num);
|
||||||
|
|
||||||
error6:
|
|
||||||
if (config->mux_sel_gpio != -1)
|
|
||||||
gpio_free(config->mux_sel_gpio);
|
|
||||||
error5:
|
|
||||||
if (config->mux_en_gpio != -1)
|
|
||||||
gpio_free(config->mux_en_gpio);
|
|
||||||
error4:
|
|
||||||
gpio_free(config->hpd_gpio);
|
|
||||||
error3:
|
|
||||||
if (config->ddc_data_gpio != -1)
|
|
||||||
gpio_free(config->ddc_data_gpio);
|
|
||||||
error2:
|
|
||||||
if (config->ddc_clk_gpio != -1)
|
|
||||||
gpio_free(config->ddc_clk_gpio);
|
|
||||||
error1:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,10 +285,13 @@ static enum drm_connector_status detect_reg(struct hdmi *hdmi)
|
||||||
connector_status_connected : connector_status_disconnected;
|
connector_status_connected : connector_status_disconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HPD_GPIO_INDEX 2
|
||||||
static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
|
static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
|
||||||
{
|
{
|
||||||
const struct hdmi_platform_config *config = hdmi->config;
|
const struct hdmi_platform_config *config = hdmi->config;
|
||||||
return gpio_get_value(config->hpd_gpio) ?
|
struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
|
||||||
|
|
||||||
|
return gpio_get_value(hpd_gpio.num) ?
|
||||||
connector_status_connected :
|
connector_status_connected :
|
||||||
connector_status_disconnected;
|
connector_status_disconnected;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue