|
@@ -41,7 +41,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
|
|
|
power_on ? "Enable" : "Disable", ctrl);
|
|
|
}
|
|
|
|
|
|
-static irqreturn_t hdmi_irq(int irq, void *dev_id)
|
|
|
+irqreturn_t hdmi_irq(int irq, void *dev_id)
|
|
|
{
|
|
|
struct hdmi *hdmi = dev_id;
|
|
|
|
|
@@ -71,13 +71,13 @@ void hdmi_destroy(struct kref *kref)
|
|
|
}
|
|
|
|
|
|
/* initialize connector */
|
|
|
-int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|
|
+struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|
|
{
|
|
|
struct hdmi *hdmi = NULL;
|
|
|
struct msm_drm_private *priv = dev->dev_private;
|
|
|
struct platform_device *pdev = hdmi_pdev;
|
|
|
struct hdmi_platform_config *config;
|
|
|
- int ret;
|
|
|
+ int i, ret;
|
|
|
|
|
|
if (!pdev) {
|
|
|
dev_err(dev->dev, "no hdmi device\n");
|
|
@@ -99,6 +99,7 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|
|
|
|
|
hdmi->dev = dev;
|
|
|
hdmi->pdev = pdev;
|
|
|
+ hdmi->config = config;
|
|
|
hdmi->encoder = encoder;
|
|
|
|
|
|
/* not sure about which phy maps to which msm.. probably I miss some */
|
|
@@ -114,44 +115,70 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- hdmi->mmio = msm_ioremap(pdev, "hdmi_msm_hdmi_addr", "HDMI");
|
|
|
+ hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
|
|
|
if (IS_ERR(hdmi->mmio)) {
|
|
|
ret = PTR_ERR(hdmi->mmio);
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- hdmi->mvs = devm_regulator_get(&pdev->dev, "8901_hdmi_mvs");
|
|
|
- if (IS_ERR(hdmi->mvs))
|
|
|
- hdmi->mvs = devm_regulator_get(&pdev->dev, "8921_hdmi_mvs");
|
|
|
- if (IS_ERR(hdmi->mvs)) {
|
|
|
- ret = PTR_ERR(hdmi->mvs);
|
|
|
- dev_err(dev->dev, "failed to get mvs regulator: %d\n", ret);
|
|
|
- goto fail;
|
|
|
+ BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs));
|
|
|
+ for (i = 0; i < config->hpd_reg_cnt; i++) {
|
|
|
+ struct regulator *reg;
|
|
|
+
|
|
|
+ reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]);
|
|
|
+ if (IS_ERR(reg)) {
|
|
|
+ ret = PTR_ERR(reg);
|
|
|
+ dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
|
|
|
+ config->hpd_reg_names[i], ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ hdmi->hpd_regs[i] = reg;
|
|
|
}
|
|
|
|
|
|
- hdmi->mpp0 = devm_regulator_get(&pdev->dev, "8901_mpp0");
|
|
|
- if (IS_ERR(hdmi->mpp0))
|
|
|
- hdmi->mpp0 = NULL;
|
|
|
+ BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs));
|
|
|
+ for (i = 0; i < config->pwr_reg_cnt; i++) {
|
|
|
+ struct regulator *reg;
|
|
|
|
|
|
- hdmi->clk = devm_clk_get(&pdev->dev, "core_clk");
|
|
|
- if (IS_ERR(hdmi->clk)) {
|
|
|
- ret = PTR_ERR(hdmi->clk);
|
|
|
- dev_err(dev->dev, "failed to get 'clk': %d\n", ret);
|
|
|
- goto fail;
|
|
|
+ reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]);
|
|
|
+ if (IS_ERR(reg)) {
|
|
|
+ ret = PTR_ERR(reg);
|
|
|
+ dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
|
|
|
+ config->pwr_reg_names[i], ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ hdmi->pwr_regs[i] = reg;
|
|
|
}
|
|
|
|
|
|
- hdmi->m_pclk = devm_clk_get(&pdev->dev, "master_iface_clk");
|
|
|
- if (IS_ERR(hdmi->m_pclk)) {
|
|
|
- ret = PTR_ERR(hdmi->m_pclk);
|
|
|
- dev_err(dev->dev, "failed to get 'm_pclk': %d\n", ret);
|
|
|
- goto fail;
|
|
|
+ BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks));
|
|
|
+ for (i = 0; i < config->hpd_clk_cnt; i++) {
|
|
|
+ struct clk *clk;
|
|
|
+
|
|
|
+ clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]);
|
|
|
+ if (IS_ERR(clk)) {
|
|
|
+ ret = PTR_ERR(clk);
|
|
|
+ dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n",
|
|
|
+ config->hpd_clk_names[i], ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ hdmi->hpd_clks[i] = clk;
|
|
|
}
|
|
|
|
|
|
- hdmi->s_pclk = devm_clk_get(&pdev->dev, "slave_iface_clk");
|
|
|
- if (IS_ERR(hdmi->s_pclk)) {
|
|
|
- ret = PTR_ERR(hdmi->s_pclk);
|
|
|
- dev_err(dev->dev, "failed to get 's_pclk': %d\n", ret);
|
|
|
- goto fail;
|
|
|
+ BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks));
|
|
|
+ for (i = 0; i < config->pwr_clk_cnt; i++) {
|
|
|
+ struct clk *clk;
|
|
|
+
|
|
|
+ clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]);
|
|
|
+ if (IS_ERR(clk)) {
|
|
|
+ ret = PTR_ERR(clk);
|
|
|
+ dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n",
|
|
|
+ config->pwr_clk_names[i], ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ hdmi->pwr_clks[i] = clk;
|
|
|
}
|
|
|
|
|
|
hdmi->i2c = hdmi_i2c_init(hdmi);
|
|
@@ -178,20 +205,22 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- hdmi->irq = platform_get_irq(pdev, 0);
|
|
|
- if (hdmi->irq < 0) {
|
|
|
- ret = hdmi->irq;
|
|
|
- dev_err(dev->dev, "failed to get irq: %d\n", ret);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
+ if (!config->shared_irq) {
|
|
|
+ hdmi->irq = platform_get_irq(pdev, 0);
|
|
|
+ if (hdmi->irq < 0) {
|
|
|
+ ret = hdmi->irq;
|
|
|
+ dev_err(dev->dev, "failed to get irq: %d\n", ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
|
|
|
- ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
|
|
|
- NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
|
|
- "hdmi_isr", hdmi);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(dev->dev, "failed to request IRQ%u: %d\n",
|
|
|
- hdmi->irq, ret);
|
|
|
- goto fail;
|
|
|
+ ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
|
|
|
+ NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
|
|
+ "hdmi_isr", hdmi);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dev->dev, "failed to request IRQ%u: %d\n",
|
|
|
+ hdmi->irq, ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
encoder->bridge = hdmi->bridge;
|
|
@@ -199,7 +228,7 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|
|
priv->bridges[priv->num_bridges++] = hdmi->bridge;
|
|
|
priv->connectors[priv->num_connectors++] = hdmi->connector;
|
|
|
|
|
|
- return 0;
|
|
|
+ return hdmi;
|
|
|
|
|
|
fail:
|
|
|
if (hdmi) {
|
|
@@ -211,37 +240,100 @@ fail:
|
|
|
hdmi_destroy(&hdmi->refcount);
|
|
|
}
|
|
|
|
|
|
- return ret;
|
|
|
+ return ERR_PTR(ret);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* The hdmi device:
|
|
|
*/
|
|
|
|
|
|
+#include <linux/of_gpio.h>
|
|
|
+
|
|
|
static int hdmi_dev_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
static struct hdmi_platform_config config = {};
|
|
|
#ifdef CONFIG_OF
|
|
|
- /* TODO */
|
|
|
+ struct device_node *of_node = pdev->dev.of_node;
|
|
|
+
|
|
|
+ int get_gpio(const char *name)
|
|
|
+ {
|
|
|
+ int gpio = of_get_named_gpio(of_node, name, 0);
|
|
|
+ if (gpio < 0) {
|
|
|
+ dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n",
|
|
|
+ name, gpio);
|
|
|
+ gpio = -1;
|
|
|
+ }
|
|
|
+ return gpio;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* TODO actually use DT.. */
|
|
|
+ static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
|
|
|
+ static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
|
|
|
+ static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
|
|
|
+ static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
|
|
|
+
|
|
|
+ config.phy_init = hdmi_phy_8x74_init;
|
|
|
+ config.mmio_name = "core_physical";
|
|
|
+ config.hpd_reg_names = hpd_reg_names;
|
|
|
+ config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
|
|
|
+ config.pwr_reg_names = pwr_reg_names;
|
|
|
+ config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names);
|
|
|
+ config.hpd_clk_names = hpd_clk_names;
|
|
|
+ config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
|
|
|
+ config.pwr_clk_names = pwr_clk_names;
|
|
|
+ config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
|
|
|
+ config.ddc_clk_gpio = get_gpio("qcom,hdmi-tx-ddc-clk");
|
|
|
+ config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
|
|
|
+ config.hpd_gpio = get_gpio("qcom,hdmi-tx-hpd");
|
|
|
+ config.mux_en_gpio = get_gpio("qcom,hdmi-tx-mux-en");
|
|
|
+ config.mux_sel_gpio = get_gpio("qcom,hdmi-tx-mux-sel");
|
|
|
+ config.shared_irq = true;
|
|
|
+
|
|
|
#else
|
|
|
+ static const char *hpd_clk_names[] = {
|
|
|
+ "core_clk", "master_iface_clk", "slave_iface_clk",
|
|
|
+ };
|
|
|
if (cpu_is_apq8064()) {
|
|
|
+ static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
|
|
|
config.phy_init = hdmi_phy_8960_init;
|
|
|
+ config.mmio_name = "hdmi_msm_hdmi_addr";
|
|
|
+ config.hpd_reg_names = hpd_reg_names;
|
|
|
+ config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
|
|
|
+ config.hpd_clk_names = hpd_clk_names;
|
|
|
+ config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
|
|
|
config.ddc_clk_gpio = 70;
|
|
|
config.ddc_data_gpio = 71;
|
|
|
config.hpd_gpio = 72;
|
|
|
- config.pmic_gpio = 13 + NR_GPIO_IRQS;
|
|
|
+ config.mux_en_gpio = -1;
|
|
|
+ config.mux_sel_gpio = 13 + NR_GPIO_IRQS;
|
|
|
} else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
|
|
|
+ static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
|
|
|
config.phy_init = hdmi_phy_8960_init;
|
|
|
+ config.mmio_name = "hdmi_msm_hdmi_addr";
|
|
|
+ config.hpd_reg_names = hpd_reg_names;
|
|
|
+ config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
|
|
|
+ config.hpd_clk_names = hpd_clk_names;
|
|
|
+ config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
|
|
|
config.ddc_clk_gpio = 100;
|
|
|
config.ddc_data_gpio = 101;
|
|
|
config.hpd_gpio = 102;
|
|
|
- config.pmic_gpio = -1;
|
|
|
+ config.mux_en_gpio = -1;
|
|
|
+ config.mux_sel_gpio = -1;
|
|
|
} else if (cpu_is_msm8x60()) {
|
|
|
+ static const char *hpd_reg_names[] = {
|
|
|
+ "8901_hdmi_mvs", "8901_mpp0"
|
|
|
+ };
|
|
|
config.phy_init = hdmi_phy_8x60_init;
|
|
|
+ config.mmio_name = "hdmi_msm_hdmi_addr";
|
|
|
+ config.hpd_reg_names = hpd_reg_names;
|
|
|
+ config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
|
|
|
+ config.hpd_clk_names = hpd_clk_names;
|
|
|
+ config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
|
|
|
config.ddc_clk_gpio = 170;
|
|
|
config.ddc_data_gpio = 171;
|
|
|
config.hpd_gpio = 172;
|
|
|
- config.pmic_gpio = -1;
|
|
|
+ config.mux_en_gpio = -1;
|
|
|
+ config.mux_sel_gpio = -1;
|
|
|
}
|
|
|
#endif
|
|
|
pdev->dev.platform_data = &config;
|
|
@@ -255,10 +347,19 @@ static int hdmi_dev_remove(struct platform_device *pdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static const struct of_device_id dt_match[] = {
|
|
|
+ { .compatible = "qcom,hdmi-tx" },
|
|
|
+ {}
|
|
|
+};
|
|
|
+MODULE_DEVICE_TABLE(of, dt_match);
|
|
|
+
|
|
|
static struct platform_driver hdmi_driver = {
|
|
|
.probe = hdmi_dev_probe,
|
|
|
.remove = hdmi_dev_remove,
|
|
|
- .driver.name = "hdmi_msm",
|
|
|
+ .driver = {
|
|
|
+ .name = "hdmi_msm",
|
|
|
+ .of_match_table = dt_match,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
void __init hdmi_register(void)
|