summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kurtz <djkurtz@chromium.org>2014-04-25 14:59:42 +0900
committerInki Dae <inki.dae@samsung.com>2014-04-28 21:33:27 +0900
commit4b0d356004aa4077801f398e6fca60bcac5e9340 (patch)
tree1db98a8dadaae09e1ac60f9a2f53e337c25359a4
parentd60f61973f6cb989d6e9df3ac0ba5b197b71d400 (diff)
downloadlinux-3.10-4b0d356004aa4077801f398e6fca60bcac5e9340.tar.gz
linux-3.10-4b0d356004aa4077801f398e6fca60bcac5e9340.tar.bz2
linux-3.10-4b0d356004aa4077801f398e6fca60bcac5e9340.zip
drm/exynos: hdmi: remove the i2c drivers and use
The i2c client was previously being passed into the hdmi driver via a dedicated i2c driver, and then a global variable. This patch removes all of that and just uses the device tree to get the i2c_client. This patch also properly references the client so we don't lose it before we're done with it. Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> [seanpaul changed to phandle lookup instead of using of node name] Signed-off-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--Documentation/devicetree/bindings/video/exynos_hdmi.txt4
-rw-r--r--drivers/gpu/drm/exynos/Makefile1
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c155
3 files changed, 62 insertions, 98 deletions
diff --git a/Documentation/devicetree/bindings/video/exynos_hdmi.txt b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
index 589edee3739..a2e148d430d 100644
--- a/Documentation/devicetree/bindings/video/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
@@ -11,6 +11,8 @@ Required properties:
c) pin function mode.
d) optional flags and pull up/down.
e) drive strength.
+- ddc: phandle to the hdmi ddc node
+- phy: phandle to the hdmi phy node
Example:
@@ -19,4 +21,6 @@ Example:
reg = <0x14530000 0x100000>;
interrupts = <0 95 0>;
hpd-gpio = <&gpx3 7 0xf 1 3>;
+ ddc = <&hdmi_ddc_node>;
+ phy = <&hdmi_phy_node>;
};
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index a7c34f53212..3d71e7f8f67 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -13,7 +13,6 @@ exynosdrm-$(CONFIG_ARM_DMA_USE_IOMMU) += exynos_drm_iommu_init.o
exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \
- exynos_ddc.o exynos_hdmiphy.o \
exynos_drm_hdmi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index b0057164846..9352ab8cd1d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -41,8 +41,6 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_hdmi.h"
-#include "exynos_hdmi.h"
-
#include <linux/gpio.h>
#include <media/s5p_hdmi.h>
@@ -84,6 +82,7 @@ struct hdmi_resources {
struct clk *sclk_pixel;
struct clk *sclk_hdmiphy;
struct phy *hdmiphy;
+ struct clk *mout_hdmi;
struct regulator_bulk_data *regul_bulk;
int regul_count;
};
@@ -1692,8 +1691,8 @@ static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
struct hdmi_context *hdata = ctx;
struct drm_display_mode *m = mode;
- DRM_DEBUG_KMS("[%s]: xres=%d, yres=%d, refresh=%d, intl=%s\n",
- __func__, m->hdisplay, m->vdisplay,
+ DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
+ m->hdisplay, m->vdisplay,
m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
"INTERLACED" : "PROGERESSIVE");
@@ -1782,7 +1781,7 @@ static void hdmi_dpms(void *ctx, int mode)
{
struct hdmi_context *hdata = ctx;
- DRM_DEBUG_KMS("[%d] %s mode %d\n", __LINE__, __func__, mode);
+ DRM_DEBUG_KMS("mode %d\n", mode);
switch (mode) {
case DRM_MODE_DPMS_ON:
@@ -1872,8 +1871,13 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
DRM_ERROR("failed to get phy 'hdmiphy'\n");
goto fail;
}
+ res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
+ if (IS_ERR(res->mout_hdmi)) {
+ DRM_ERROR("failed to get clock 'mout_hdmi'\n");
+ goto fail;
+ }
- clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+ clk_set_parent(res->mout_hdmi, res->sclk_pixel);
res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
sizeof(res->regul_bulk[0]), GFP_KERNEL);
@@ -1896,21 +1900,6 @@ fail:
return -ENODEV;
}
-static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
-
-void hdmi_attach_ddc_client(struct i2c_client *ddc)
-{
- if (ddc)
- hdmi_ddc = ddc;
-}
-
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
-{
- if (hdmiphy)
- hdmi_hdmiphy = hdmiphy;
-}
-
-#ifdef CONFIG_OF
static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
(struct device *dev)
{
@@ -1921,7 +1910,7 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
if (!pd)
return NULL;
- pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, NULL);
+ pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
if (pd->hpd_gpio < 0) {
DRM_ERROR("no hpd gpio property found\n");
return NULL;
@@ -1931,45 +1920,21 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
return pd;
}
-#else
-static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
- (struct device *dev)
-{
- return NULL;
-}
-#endif
-static struct platform_device_id hdmi_driver_types[] = {
- {
- .name = "s5pv210-hdmi",
- .driver_data = HDMI_TYPE13,
- }, {
- .name = "exynos4-hdmi",
- .driver_data = HDMI_TYPE13,
- }, {
- .name = "exynos4-hdmi14",
- .driver_data = HDMI_TYPE14,
- }, {
- .name = "exynos5-hdmi",
- .driver_data = HDMI_TYPE14,
- }, {
- /* end node */
- }
-};
-
-#ifdef CONFIG_OF
static struct of_device_id hdmi_match_types[] = {
{
.compatible = "samsung,exynos4210-hdmi",
.data = (void *)HDMI_TYPE13,
}, {
+ .compatible = "samsung,exynos4212-hdmi",
+ .data = (void *)HDMI_TYPE14,
+ }, {
.compatible = "samsung,exynos5-hdmi",
.data = (void *)HDMI_TYPE14,
}, {
/* end node */
}
};
-#endif
static int hdmi_probe(struct platform_device *pdev)
{
@@ -1978,35 +1943,27 @@ static int hdmi_probe(struct platform_device *pdev)
struct hdmi_context *hdata;
struct s5p_hdmi_platform_data *pdata;
struct resource *res;
+ const struct of_device_id *match;
+ struct device_node *ddc_node, *phy_node;
int ret;
- if (dev->of_node) {
- pdata = drm_hdmi_dt_parse_pdata(dev);
- if (IS_ERR(pdata)) {
- DRM_ERROR("failed to parse dt\n");
- return PTR_ERR(pdata);
- }
- } else {
- pdata = dev->platform_data;
- }
+ if (!dev->of_node)
+ return -ENODEV;
- if (!pdata) {
- DRM_ERROR("no platform data specified\n");
+ pdata = drm_hdmi_dt_parse_pdata(dev);
+ if (!pdata)
return -EINVAL;
- }
if (!pdata->max_pixel_clock) {
DRM_LOG("max-pixel-clock is zero, using INF\n");
pdata->max_pixel_clock = ULONG_MAX;
}
- drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
- GFP_KERNEL);
+ drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
if (!drm_hdmi_ctx)
return -ENOMEM;
- hdata = devm_kzalloc(dev, sizeof(struct hdmi_context),
- GFP_KERNEL);
+ hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
if (!hdata)
return -ENOMEM;
@@ -2017,24 +1974,16 @@ static int hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drm_hdmi_ctx);
- if (dev->of_node) {
- const struct of_device_id *match;
- match = of_match_node(of_match_ptr(hdmi_match_types),
- dev->of_node);
- if (match == NULL)
- return -ENODEV;
- hdata->type = (enum hdmi_type)match->data;
- } else {
- hdata->type = (enum hdmi_type)platform_get_device_id
- (pdev)->driver_data;
- }
+ match = of_match_node(hdmi_match_types, dev->of_node);
+ if (!match)
+ return -ENODEV;
+ hdata->type = (enum hdmi_type)match->data;
hdata->hpd_gpio = pdata->hpd_gpio;
hdata->max_pixel_clock = pdata->max_pixel_clock;
hdata->dev = dev;
ret = hdmi_resources_init(hdata);
-
if (ret) {
DRM_ERROR("hdmi_resources_init failed\n");
return -EINVAL;
@@ -2052,21 +2001,34 @@ static int hdmi_probe(struct platform_device *pdev)
}
/* DDC i2c driver */
- if (i2c_add_driver(&ddc_driver)) {
- DRM_ERROR("failed to register ddc i2c driver\n");
- return -ENOENT;
+ ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
+ if (!ddc_node) {
+ DRM_ERROR("Failed to find ddc node in device tree\n");
+ return -ENODEV;
+ }
+#if 0 /* FIXME */
+ hdata->ddc_port = of_find_i2c_device_by_node(ddc_node);
+#endif
+ if (!hdata->ddc_port) {
+ DRM_ERROR("Failed to get ddc i2c client by node\n");
+ return -ENODEV;
}
-
- hdata->ddc_port = hdmi_ddc;
/* hdmiphy i2c driver */
- if (i2c_add_driver(&hdmiphy_driver)) {
- DRM_ERROR("failed to register hdmiphy i2c driver\n");
- ret = -ENOENT;
+ phy_node = of_parse_phandle(dev->of_node, "phy", 0);
+ if (!phy_node) {
+ DRM_ERROR("Failed to find hdmiphy node in device tree\n");
+ ret = -ENODEV;
+ goto err_ddc;
+ }
+#if 0 /* FIXME */
+ hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
+#endif
+ if (!hdata->hdmiphy_port) {
+ DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
+ ret = -ENODEV;
goto err_ddc;
}
-
- hdata->hdmiphy_port = hdmi_hdmiphy;
hdata->irq = gpio_to_irq(hdata->hpd_gpio);
if (hdata->irq < 0) {
@@ -2097,22 +2059,22 @@ static int hdmi_probe(struct platform_device *pdev)
return 0;
err_hdmiphy:
- i2c_del_driver(&hdmiphy_driver);
+ put_device(&hdata->hdmiphy_port->dev);
err_ddc:
- i2c_del_driver(&ddc_driver);
+ put_device(&hdata->ddc_port->dev);
return ret;
}
static int hdmi_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
+ struct hdmi_context *hdata = ctx->ctx;
pm_runtime_disable(dev);
- /* hdmiphy i2c driver */
- i2c_del_driver(&hdmiphy_driver);
- /* DDC i2c driver */
- i2c_del_driver(&ddc_driver);
+ put_device(&hdata->hdmiphy_port->dev);
+ put_device(&hdata->ddc_port->dev);
return 0;
}
@@ -2130,7 +2092,7 @@ static int hdmi_suspend(struct device *dev)
drm_helper_hpd_irq_event(hdata->drm_dev);
if (pm_runtime_suspended(dev)) {
- DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
+ DRM_DEBUG_KMS("Already suspended\n");
return 0;
}
@@ -2149,7 +2111,7 @@ static int hdmi_resume(struct device *dev)
enable_irq(hdata->irq);
if (!pm_runtime_suspended(dev)) {
- DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
+ DRM_DEBUG_KMS("Already resumed\n");
return 0;
}
@@ -2189,11 +2151,10 @@ static const struct dev_pm_ops hdmi_pm_ops = {
struct platform_driver hdmi_driver = {
.probe = hdmi_probe,
.remove = hdmi_remove,
- .id_table = hdmi_driver_types,
.driver = {
.name = "exynos-hdmi",
.owner = THIS_MODULE,
.pm = &hdmi_pm_ops,
- .of_match_table = of_match_ptr(hdmi_match_types),
+ .of_match_table = hdmi_match_types,
},
};