diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 88 |
1 files changed, 70 insertions, 18 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 098182ab5df..337e4d69a38 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -76,9 +76,15 @@ enum hdmi_type { HDMI_TYPE14, }; +enum hdmi_soc_ver { + EXYNOS4, + EXYNOS5, +}; + struct hdmi_driver_data { unsigned int type; unsigned int is_apb_phy:1; + unsigned int soc_ver; }; struct hdmi_resources { @@ -207,7 +213,7 @@ struct hdmi_context { int hpd_gpio; u32 max_pixel_clock; - enum hdmi_type type; + struct hdmi_driver_data *drv_data; }; struct hdmiphy_config { @@ -217,14 +223,17 @@ struct hdmiphy_config { struct hdmi_driver_data exynos4210_hdmi_driver_data = { .type = HDMI_TYPE13, + .soc_ver = EXYNOS4, }; struct hdmi_driver_data exynos4212_hdmi_driver_data = { .type = HDMI_TYPE14, + .soc_ver = EXYNOS4, }; struct hdmi_driver_data exynos5_hdmi_driver_data = { .type = HDMI_TYPE14, + .soc_ver = EXYNOS5, }; /* list of phy config settings */ @@ -722,7 +731,7 @@ static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix) static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix) { - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) hdmi_v13_regs_dump(hdata, prefix); else hdmi_v14_regs_dump(hdata, prefix); @@ -851,10 +860,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) const struct hdmiphy_config *confs; int count, i; - if (hdata->type == HDMI_TYPE13) { + if (hdata->drv_data->type == HDMI_TYPE13) { confs = hdmiphy_v13_configs; count = ARRAY_SIZE(hdmiphy_v13_configs); - } else if (hdata->type == HDMI_TYPE14) { + } else if (hdata->drv_data->type == HDMI_TYPE14) { confs = hdmiphy_v14_configs; count = ARRAY_SIZE(hdmiphy_v14_configs); } else @@ -1039,7 +1048,7 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr) hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]); hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]); - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4); else hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); @@ -1143,7 +1152,7 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) { u32 reg; - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) reg = HDMI_V13_CORE_RSTOUT; else reg = HDMI_CORE_RSTOUT; @@ -1177,7 +1186,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata) HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS); } - if (hdata->type == HDMI_TYPE13) { + if (hdata->drv_data->type == HDMI_TYPE13) { /* choose bluescreen (fecal) color */ hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12); hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34); @@ -1466,7 +1475,7 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) static void hdmi_mode_apply(struct hdmi_context *hdata) { - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) hdmi_v13_mode_apply(hdata); else hdmi_v14_mode_apply(hdata); @@ -1488,7 +1497,7 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) if (hdata->hdmiphy_port) i2c_master_send(hdata->hdmiphy_port, buffer, 2); - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) reg = HDMI_V13_PHY_RSTOUT; else reg = HDMI_PHY_RSTOUT; @@ -1502,14 +1511,14 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) static void hdmiphy_poweron(struct hdmi_context *hdata) { - if (hdata->type == HDMI_TYPE14) + if (hdata->drv_data->type == HDMI_TYPE14) hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN); } static void hdmiphy_poweroff(struct hdmi_context *hdata) { - if (hdata->type == HDMI_TYPE14) + if (hdata->drv_data->type == HDMI_TYPE14) hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN); } @@ -1535,7 +1544,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) return; } - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) hdmiphy_data = hdmiphy_v13_configs[i].conf; else hdmiphy_data = hdmiphy_v14_configs[i].conf; @@ -1813,7 +1822,7 @@ static void hdmi_mode_set(struct exynos_drm_display *display, m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? "INTERLACED" : "PROGERESSIVE"); - if (hdata->type == HDMI_TYPE13) + if (hdata->drv_data->type == HDMI_TYPE13) hdmi_v13_mode_set(hdata, mode); else hdmi_v14_mode_set(hdata, mode); @@ -2041,6 +2050,41 @@ static struct of_device_id hdmi_match_types[] = { } }; +static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev) +{ + struct hdmi_context *ctx = hdmi_display.ctx; + const char *exynos4_compatible_str = "samsung,exynos4210-hdmiddc"; + const char *exynos5_compatible_str = "samsung,exynos5-hdmiddc"; + const char *compatible_str = NULL; + struct device_node *np; + + if (ctx->drv_data->soc_ver == EXYNOS4) + compatible_str = exynos4_compatible_str; + else + compatible_str = exynos5_compatible_str; + + np = of_find_compatible_node(NULL, NULL, compatible_str); + if (np) + return of_get_next_parent(np); + + return NULL; +} + +static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev) +{ + struct hdmi_context *ctx = hdmi_display.ctx; + const char *exynos4_compatible_str = "samsung,exynos4212-hdmiphy"; + const char *exynos5_compatible_str = "samsung,exynos5-hdmiphy"; + const char *compatible_str = NULL; + + if (ctx->drv_data->soc_ver == EXYNOS4) + compatible_str = exynos4_compatible_str; + else + compatible_str = exynos5_compatible_str; + + return of_find_compatible_node(NULL, NULL, compatible_str); +} + static int hdmi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -2049,7 +2093,6 @@ static int hdmi_probe(struct platform_device *pdev) struct resource *res; const struct of_device_id *match; struct device_node *ddc_node, *phy_node; - struct hdmi_driver_data *drv_data; int ret; if (!dev->of_node) @@ -2076,12 +2119,12 @@ static int hdmi_probe(struct platform_device *pdev) if (!match) return -ENODEV; - drv_data = (struct hdmi_driver_data *)match->data; - hdata->type = drv_data->type; + hdata->drv_data = (struct hdmi_driver_data *)match->data; hdata->hpd_gpio = pdata->hpd_gpio; hdata->max_pixel_clock = pdata->max_pixel_clock; hdata->dev = dev; + hdmi_display.ctx = hdata; ret = hdmi_resources_init(hdata); if (ret) { @@ -2100,6 +2143,10 @@ static int hdmi_probe(struct platform_device *pdev) return ret; } + ddc_node = hdmi_legacy_ddc_dt_binding(dev); + if (ddc_node) + goto out_get_ddc_adpt; + /* DDC i2c driver */ ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); if (!ddc_node) { @@ -2107,6 +2154,7 @@ static int hdmi_probe(struct platform_device *pdev) return -ENODEV; } +out_get_ddc_adpt: hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node); if (!hdata->ddc_adpt) { DRM_ERROR("Failed to get ddc i2c adapter by node\n"); @@ -2114,9 +2162,13 @@ static int hdmi_probe(struct platform_device *pdev) } /* Not support APB PHY yet. */ - if (drv_data->is_apb_phy) + if (hdata->drv_data->is_apb_phy) return -EPERM; + phy_node = hdmi_legacy_phy_dt_binding(dev); + if (phy_node) + goto out_get_phy_port; + /* hdmiphy i2c driver */ phy_node = of_parse_phandle(dev->of_node, "phy", 0); if (!phy_node) { @@ -2125,6 +2177,7 @@ static int hdmi_probe(struct platform_device *pdev) goto err_ddc; } +out_get_phy_port: hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node); if (!hdata->hdmiphy_port) { DRM_ERROR("Failed to get hdmi phy i2c client from node\n"); @@ -2152,7 +2205,6 @@ static int hdmi_probe(struct platform_device *pdev) pm_runtime_enable(dev); - hdmi_display.ctx = hdata; exynos_drm_display_register(&hdmi_display); return 0; |