diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c')
-rw-r--r-- | kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 140 |
1 files changed, 106 insertions, 34 deletions
diff --git a/kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index b62cdb968..a3b05ae52 100644 --- a/kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/kernel/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -16,6 +16,7 @@ */ #include <linux/gpio.h> +#include <linux/pinctrl/consumer.h> #include "msm_kms.h" #include "hdmi.h" @@ -27,32 +28,85 @@ struct hdmi_connector { }; #define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base) +static void hdmi_phy_reset(struct hdmi *hdmi) +{ + unsigned int val; + + val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL); + + if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { + /* pull low */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val & ~HDMI_PHY_CTRL_SW_RESET); + } else { + /* pull high */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val | HDMI_PHY_CTRL_SW_RESET); + } + + if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) { + /* pull low */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val & ~HDMI_PHY_CTRL_SW_RESET_PLL); + } else { + /* pull high */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val | HDMI_PHY_CTRL_SW_RESET_PLL); + } + + msleep(100); + + if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { + /* pull high */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val | HDMI_PHY_CTRL_SW_RESET); + } else { + /* pull low */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val & ~HDMI_PHY_CTRL_SW_RESET); + } + + if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) { + /* pull high */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val | HDMI_PHY_CTRL_SW_RESET_PLL); + } else { + /* pull low */ + hdmi_write(hdmi, REG_HDMI_PHY_CTRL, + val & ~HDMI_PHY_CTRL_SW_RESET_PLL); + } +} + static int gpio_config(struct hdmi *hdmi, bool on) { - struct drm_device *dev = hdmi->dev; + struct device *dev = &hdmi->pdev->dev; const struct hdmi_platform_config *config = hdmi->config; int ret; if (on) { - ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK"); - if (ret) { - dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", - "HDMI_DDC_CLK", config->ddc_clk_gpio, ret); - goto error1; + if (config->ddc_clk_gpio != -1) { + ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK"); + if (ret) { + dev_err(dev, "'%s'(%d) gpio_request failed: %d\n", + "HDMI_DDC_CLK", config->ddc_clk_gpio, ret); + goto error1; + } + gpio_set_value_cansleep(config->ddc_clk_gpio, 1); } - gpio_set_value_cansleep(config->ddc_clk_gpio, 1); - ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA"); - if (ret) { - dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", - "HDMI_DDC_DATA", config->ddc_data_gpio, ret); - goto error2; + 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); } - gpio_set_value_cansleep(config->ddc_data_gpio, 1); ret = gpio_request(config->hpd_gpio, "HDMI_HPD"); if (ret) { - dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", + dev_err(dev, "'%s'(%d) gpio_request failed: %d\n", "HDMI_HPD", config->hpd_gpio, ret); goto error3; } @@ -62,7 +116,7 @@ static int gpio_config(struct hdmi *hdmi, bool on) if (config->mux_en_gpio != -1) { ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN"); if (ret) { - dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", + dev_err(dev, "'%s'(%d) gpio_request failed: %d\n", "HDMI_MUX_EN", config->mux_en_gpio, ret); goto error4; } @@ -72,7 +126,7 @@ static int gpio_config(struct hdmi *hdmi, bool on) if (config->mux_sel_gpio != -1) { ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL"); if (ret) { - dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n", + dev_err(dev, "'%s'(%d) gpio_request failed: %d\n", "HDMI_MUX_SEL", config->mux_sel_gpio, ret); goto error5; } @@ -83,7 +137,7 @@ static int gpio_config(struct hdmi *hdmi, bool on) ret = gpio_request(config->mux_lpm_gpio, "HDMI_MUX_LPM"); if (ret) { - dev_err(dev->dev, + dev_err(dev, "'%s'(%d) gpio_request failed: %d\n", "HDMI_MUX_LPM", config->mux_lpm_gpio, ret); @@ -93,8 +147,12 @@ static int gpio_config(struct hdmi *hdmi, bool on) } DBG("gpio on"); } else { - gpio_free(config->ddc_clk_gpio); - gpio_free(config->ddc_data_gpio); + if (config->ddc_clk_gpio != -1) + gpio_free(config->ddc_clk_gpio); + + if (config->ddc_data_gpio != -1) + gpio_free(config->ddc_data_gpio); + gpio_free(config->hpd_gpio); if (config->mux_en_gpio != -1) { @@ -125,9 +183,11 @@ error5: error4: gpio_free(config->hpd_gpio); error3: - gpio_free(config->ddc_data_gpio); + if (config->ddc_data_gpio != -1) + gpio_free(config->ddc_data_gpio); error2: - gpio_free(config->ddc_clk_gpio); + if (config->ddc_clk_gpio != -1) + gpio_free(config->ddc_clk_gpio); error1: return ret; } @@ -136,23 +196,29 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; const struct hdmi_platform_config *config = hdmi->config; - struct drm_device *dev = hdmi_connector->base.dev; - struct hdmi_phy *phy = hdmi->phy; + struct device *dev = &hdmi->pdev->dev; uint32_t hpd_ctrl; int i, ret; + unsigned long flags; for (i = 0; i < config->hpd_reg_cnt; i++) { ret = regulator_enable(hdmi->hpd_regs[i]); if (ret) { - dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", + dev_err(dev, "failed to enable hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } } + ret = pinctrl_pm_select_default_state(dev); + if (ret) { + dev_err(dev, "pinctrl state chg failed: %d\n", ret); + goto fail; + } + ret = gpio_config(hdmi, true); if (ret) { - dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); + dev_err(dev, "failed to configure GPIOs: %d\n", ret); goto fail; } @@ -161,20 +227,20 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) ret = clk_set_rate(hdmi->hpd_clks[i], config->hpd_freq[i]); if (ret) - dev_warn(dev->dev, "failed to set clk %s (%d)\n", + dev_warn(dev, "failed to set clk %s (%d)\n", config->hpd_clk_names[i], ret); } ret = clk_prepare_enable(hdmi->hpd_clks[i]); if (ret) { - dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n", + dev_err(dev, "failed to enable hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } } hdmi_set_mode(hdmi, false); - phy->funcs->reset(phy); + hdmi_phy_reset(hdmi); hdmi_set_mode(hdmi, true); hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); @@ -185,6 +251,7 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) HDMI_HPD_INT_CTRL_INT_EN); /* set timeout to 4.1ms (max) for hardware debounce */ + spin_lock_irqsave(&hdmi->reg_lock, flags); hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff); @@ -193,6 +260,7 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl); hdmi_write(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE | hpd_ctrl); + spin_unlock_irqrestore(&hdmi->reg_lock, flags); return 0; @@ -204,7 +272,7 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; const struct hdmi_platform_config *config = hdmi->config; - struct drm_device *dev = hdmi_connector->base.dev; + struct device *dev = &hdmi->pdev->dev; int i, ret = 0; /* Disable HPD interrupt */ @@ -217,12 +285,16 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector) ret = gpio_config(hdmi, false); if (ret) - dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); + dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret); + + ret = pinctrl_pm_select_sleep_state(dev); + if (ret) + dev_warn(dev, "pinctrl state chg failed: %d\n", ret); for (i = 0; i < config->hpd_reg_cnt; i++) { ret = regulator_disable(hdmi->hpd_regs[i]); if (ret) - dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n", + dev_warn(dev, "failed to disable hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); } } @@ -239,7 +311,6 @@ hotplug_work(struct work_struct *work) void hdmi_connector_irq(struct drm_connector *connector) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); - struct msm_drm_private *priv = connector->dev->dev_private; struct hdmi *hdmi = hdmi_connector->hdmi; uint32_t hpd_int_status, hpd_int_ctrl; @@ -263,7 +334,7 @@ void hdmi_connector_irq(struct drm_connector *connector) hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT; hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl); - queue_work(priv->wq, &hdmi_connector->hpd_work); + queue_work(hdmi->workq, &hdmi_connector->hpd_work); } } @@ -339,6 +410,7 @@ static int hdmi_connector_get_modes(struct drm_connector *connector) hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl); + hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid); drm_mode_connector_update_edid_property(connector, edid); if (edid) { @@ -433,7 +505,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi) ret = hpd_enable(hdmi_connector); if (ret) { - dev_err(hdmi->dev->dev, "failed to enable HPD: %d\n", ret); + dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret); goto fail; } |