[PATCH 2/4] drm/exynos: hdmi: register hdmiphy driver from common drm hdmi
Rahul Sharma
rahul.sharma at samsung.com
Mon Apr 29 07:50:51 PDT 2013
hdmiphy hardware block is a physically separate device. Hdmiphy driver
is glued inside hdmi driver and acessed through hdmi callbacks. With
increasing diversities in the hdmiphy mapping and configurations, hdmi
driver is expanding with un-related changes.
This patch registers hdmiphy as a independent driver, having own set
of requried callbacks which are called by common drm hdmi, parallel to
hdmi and mixer driver.
Signed-off-by: Rahul Sharma <rahul.sharma at samsung.com>
---
drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 61 +++++++++++++++++++++++++++---
drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 17 +++++++++
drivers/gpu/drm/exynos/exynos_hdmi.c | 26 ++-----------
drivers/gpu/drm/exynos/exynos_hdmi.h | 1 -
drivers/gpu/drm/exynos/exynos_hdmiphy.c | 13 ++++++-
5 files changed, 87 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 7ab5f9f..25fe012 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -32,12 +32,14 @@
/* platform device pointer for common drm hdmi device. */
static struct platform_device *exynos_drm_hdmi_pdev;
-/* Common hdmi subdrv needs to access the hdmi and mixer though context.
-* These should be initialied by the repective drivers */
+/* Common hdmi subdrv needs to access the hdmi, hdmiphy and mixer though
+* context. These should be initialied by the repective drivers */
+static struct exynos_drm_hdmi_context *hdmiphy_ctx;
static struct exynos_drm_hdmi_context *hdmi_ctx;
static struct exynos_drm_hdmi_context *mixer_ctx;
/* these callback points shoud be set by specific drivers. */
+static struct exynos_hdmiphy_ops *hdmiphy_ops;
static struct exynos_hdmi_ops *hdmi_ops;
static struct exynos_mixer_ops *mixer_ops;
@@ -45,6 +47,7 @@ struct platform_driver exynos_drm_common_hdmi_driver;
struct drm_hdmi_context {
struct exynos_drm_subdrv subdrv;
+ struct exynos_drm_hdmi_context *hdmiphy_ctx;
struct exynos_drm_hdmi_context *hdmi_ctx;
struct exynos_drm_hdmi_context *mixer_ctx;
@@ -59,6 +62,10 @@ int exynos_common_hdmi_register(void)
if (exynos_drm_hdmi_pdev)
return -EEXIST;
+ ret = exynos_hdmiphy_driver_register();
+ if (ret < 0)
+ goto out_hdmiphy;
+
ret = platform_driver_register(&hdmi_driver);
if (ret < 0)
goto out_hdmi;
@@ -88,6 +95,8 @@ out_common_hdmi:
out_mixer:
platform_driver_unregister(&hdmi_driver);
out_hdmi:
+ exynos_hdmiphy_driver_unregister();
+out_hdmiphy:
return ret;
}
@@ -99,9 +108,16 @@ void exynos_common_hdmi_unregister(void)
platform_driver_unregister(&exynos_drm_common_hdmi_driver);
platform_driver_unregister(&mixer_driver);
platform_driver_unregister(&hdmi_driver);
+ exynos_hdmiphy_driver_unregister();
exynos_drm_hdmi_pdev = NULL;
}
+void exynos_hdmiphy_drv_attach(struct exynos_drm_hdmi_context *ctx)
+{
+ if (ctx)
+ hdmiphy_ctx = ctx;
+}
+
void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx)
{
if (ctx)
@@ -114,6 +130,14 @@ void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)
mixer_ctx = ctx;
}
+void exynos_hdmiphy_ops_register(struct exynos_hdmiphy_ops *ops)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (ops)
+ hdmiphy_ops = ops;
+}
+
void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
{
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -164,8 +188,8 @@ static int drm_hdmi_check_mode(struct device *dev,
DRM_DEBUG_KMS("%s\n", __FILE__);
/*
- * Both, mixer and hdmi should be able to handle the requested mode.
- * If any of the two fails, return mode as BAD.
+ * Mixer, hdmi and hdmiphy should be able to handle the requested mode.
+ * If any of the them fails, return mode as BAD.
*/
if (mixer_ops && mixer_ops->check_mode)
@@ -175,7 +199,13 @@ static int drm_hdmi_check_mode(struct device *dev,
return ret;
if (hdmi_ops && hdmi_ops->check_mode)
- return hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
+ ret = hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
+
+ if (ret)
+ return ret;
+
+ if (hdmiphy_ops && hdmiphy_ops->check_mode)
+ return hdmiphy_ops->check_mode(ctx->hdmiphy_ctx->ctx, mode);
return 0;
}
@@ -289,6 +319,9 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
if (hdmi_ops && hdmi_ops->mode_set)
hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
+
+ if (hdmiphy_ops && hdmiphy_ops->mode_set)
+ hdmiphy_ops->mode_set(ctx->hdmiphy_ctx->ctx, mode);
}
static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
@@ -308,6 +341,15 @@ static void drm_hdmi_commit(struct device *subdrv_dev)
DRM_DEBUG_KMS("%s\n", __FILE__);
+ if (hdmiphy_ops && hdmiphy_ops->prepare)
+ hdmiphy_ops->prepare(ctx->hdmiphy_ctx->ctx);
+
+ if (hdmi_ops && hdmi_ops->prepare)
+ hdmi_ops->prepare(ctx->hdmi_ctx->ctx);
+
+ if (hdmiphy_ops && hdmiphy_ops->config_apply)
+ hdmiphy_ops->config_apply(ctx->hdmiphy_ctx->ctx);
+
if (hdmi_ops && hdmi_ops->commit)
hdmi_ops->commit(ctx->hdmi_ctx->ctx);
}
@@ -323,6 +365,9 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
if (hdmi_ops && hdmi_ops->dpms)
hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
+
+ if (hdmiphy_ops && hdmiphy_ops->dpms)
+ hdmiphy_ops->dpms(ctx->hdmiphy_ctx->ctx, mode);
}
static void drm_hdmi_apply(struct device *subdrv_dev)
@@ -428,6 +473,11 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,
return -EFAULT;
}
+ if (!hdmiphy_ctx) {
+ DRM_ERROR("hdmiphy context not initialized.\n");
+ return -EFAULT;
+ }
+
if (!mixer_ctx) {
DRM_ERROR("mixer context not initialized.\n");
return -EFAULT;
@@ -441,6 +491,7 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,
}
ctx->hdmi_ctx = hdmi_ctx;
+ ctx->hdmiphy_ctx = hdmiphy_ctx;
ctx->mixer_ctx = mixer_ctx;
ctx->hdmi_ctx->drm_dev = drm_dev;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index 8861b90..8c8974f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -39,10 +39,19 @@ struct exynos_hdmi_ops {
void (*mode_set)(void *ctx, struct drm_display_mode *mode);
void (*get_max_resol)(void *ctx, unsigned int *width,
unsigned int *height);
+ void (*prepare)(void *ctx);
void (*commit)(void *ctx);
void (*dpms)(void *ctx, int mode);
};
+struct exynos_hdmiphy_ops {
+ int (*check_mode)(void *ctx, struct drm_display_mode *mode);
+ void (*mode_set)(void *ctx, struct drm_display_mode *mode);
+ void (*prepare)(void *ctx);
+ int (*config_apply)(void *ctx);
+ void (*dpms)(void *ctx, int mode);
+};
+
struct exynos_mixer_ops {
/* manager */
int (*iommu_on)(void *ctx, bool enable);
@@ -63,8 +72,16 @@ struct exynos_mixer_ops {
extern struct platform_driver hdmi_driver;
extern struct platform_driver mixer_driver;
+/*
+ * these functions registers/unregisters exynos drm hdmiphy driver.
+ */
+extern int exynos_hdmiphy_driver_register(void);
+extern void exynos_hdmiphy_driver_unregister(void);
+
+void exynos_hdmiphy_drv_attach(struct exynos_drm_hdmi_context *ctx);
void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx);
+void exynos_hdmiphy_ops_register(struct exynos_hdmiphy_ops *ops);
void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 6bcd7fc..520c4af 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1856,7 +1856,7 @@ fail:
return -ENODEV;
}
-static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
+static struct i2c_client *hdmi_ddc;
void hdmi_attach_ddc_client(struct i2c_client *ddc)
{
@@ -1864,12 +1864,6 @@ void hdmi_attach_ddc_client(struct i2c_client *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)
@@ -2027,20 +2021,11 @@ static int hdmi_probe(struct platform_device *pdev)
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;
- goto err_ddc;
- }
-
- hdata->hdmiphy_port = hdmi_hdmiphy;
-
hdata->irq = gpio_to_irq(hdata->hpd_gpio);
if (hdata->irq < 0) {
DRM_ERROR("failed to get GPIO irq\n");
ret = hdata->irq;
- goto err_hdmiphy;
+ goto err_ddc;
}
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
@@ -2051,7 +2036,7 @@ static int hdmi_probe(struct platform_device *pdev)
"hdmi", drm_hdmi_ctx);
if (ret) {
DRM_ERROR("failed to register hdmi interrupt\n");
- goto err_hdmiphy;
+ goto err_ddc;
}
/* Attach HDMI Driver to common hdmi. */
@@ -2064,8 +2049,6 @@ static int hdmi_probe(struct platform_device *pdev)
return 0;
-err_hdmiphy:
- i2c_del_driver(&hdmiphy_driver);
err_ddc:
i2c_del_driver(&ddc_driver);
return ret;
@@ -2083,9 +2066,6 @@ static int hdmi_remove(struct platform_device *pdev)
free_irq(hdata->irq, hdata);
-
- /* hdmiphy i2c driver */
- i2c_del_driver(&hdmiphy_driver);
/* DDC i2c driver */
i2c_del_driver(&ddc_driver);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.h b/drivers/gpu/drm/exynos/exynos_hdmi.h
index 0ddf395..6595d7b 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.h
@@ -15,7 +15,6 @@
#define _EXYNOS_HDMI_H_
void hdmi_attach_ddc_client(struct i2c_client *ddc);
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy);
extern struct i2c_driver hdmiphy_driver;
extern struct i2c_driver ddc_driver;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c
index ea49d13..eee2510 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmiphy.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy.c
@@ -24,8 +24,6 @@
static int hdmiphy_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- hdmi_attach_hdmiphy_client(client);
-
dev_info(&client->adapter->dev, "attached s5p_hdmiphy "
"into i2c adapter successfully\n");
@@ -67,4 +65,15 @@ struct i2c_driver hdmiphy_driver = {
.remove = hdmiphy_remove,
.command = NULL,
};
+
+extern int exynos_hdmiphy_driver_register(void)
+{
+ return i2c_add_driver(&hdmiphy_driver);
+}
+
+extern void exynos_hdmiphy_driver_unregister(void)
+{
+ i2c_del_driver(&hdmiphy_driver);
+}
+
EXPORT_SYMBOL(hdmiphy_driver);
--
1.7.10.4
More information about the dri-devel
mailing list