This patch set adds the DT based support for Samsung's Exynos5250 in DRM-HDMI. It includes disabling of hdmi internal interrupt, suppport for platform variants for hdmi and mixer, support to disable video processor based on platform type and removal of drm common platform data.
Rahul Sharma (9): drm: exynos: remove drm hdmi platform data struct drm: exynos: hdmi: add support for exynos5 ddc drm: exynos: hdmi: add support for exynos5 hdmiphy drm: exynos: hdmi: add support for platform variants for mixer drm: exynos: hdmi: add support to disable video processor in mixer drm: exynos: hdmi: add support for exynos5 mixer drm: exynos: hdmi: replace is_v13 with version check in hdmi drm: exynos: hdmi: add support for exynos5 hdmi drm: exynos: hdmi: remove drm common hdmi platform data struct
Tomasz Stanislawski (5): media: s5p-hdmi: add HPD GPIO to platform data drm: exynos: hdmi: support for platform variants drm: exynos: hdmi: fix interrupt handling drm: exynos: hdmi: use s5p-hdmi platform data drm: exynos: hdmi: turn off HPD interrupt in HDMI chip
drivers/gpu/drm/exynos/exynos_ddc.c | 22 +++- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 51 ++++---- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 2 + drivers/gpu/drm/exynos/exynos_hdmi.c | 196 ++++++++++++++++++++------- drivers/gpu/drm/exynos/exynos_hdmiphy.c | 12 ++- drivers/gpu/drm/exynos/exynos_mixer.c | 219 ++++++++++++++++++++++-------- drivers/gpu/drm/exynos/regs-mixer.h | 2 + include/drm/exynos_drm.h | 27 ---- include/media/s5p_hdmi.h | 2 + 9 files changed, 369 insertions(+), 164 deletions(-)
From: Tomasz Stanislawski t.stanislaws@samsung.com
This patch extends s5p-hdmi platform data by a GPIO identifier for Hot-Plug-Detection pin.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- include/media/s5p_hdmi.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/media/s5p_hdmi.h b/include/media/s5p_hdmi.h index 361a751..181642b 100644 --- a/include/media/s5p_hdmi.h +++ b/include/media/s5p_hdmi.h @@ -20,6 +20,7 @@ struct i2c_board_info; * @hdmiphy_info: template for HDMIPHY I2C device * @mhl_bus: controller id for MHL control bus * @mhl_info: template for MHL I2C device + * @hpd_gpio: GPIO for Hot-Plug-Detect pin * * NULL pointer for *_info fields indicates that * the corresponding chip is not present @@ -29,6 +30,7 @@ struct s5p_hdmi_platform_data { struct i2c_board_info *hdmiphy_info; int mhl_bus; struct i2c_board_info *mhl_info; + int hpd_gpio; };
#endif /* S5P_HDMI_H */
From: Tomasz Stanislawski t.stanislaws@samsung.com
This patch implements check if HDMI is version 1.3 by using a driver variant instead of platform data.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 25 ++++++++++++++++++++++++- 1 files changed, 24 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index a6aea6f..b3a802b 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2262,6 +2262,26 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) hdmi_hdmiphy = hdmiphy; }
+enum hdmi_type { + HDMI_TYPE13, + HDMI_TYPE14, +}; + +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, + }, { + /* end node */ + } +}; + static int __devinit hdmi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -2270,6 +2290,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev) struct exynos_drm_hdmi_pdata *pdata; struct resource *res; int ret; + enum hdmi_type hdmi_type;
DRM_DEBUG_KMS("[%d]\n", __LINE__);
@@ -2300,7 +2321,8 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drm_hdmi_ctx);
- hdata->is_v13 = pdata->is_v13; + hdmi_type = platform_get_device_id(pdev)->driver_data; + hdata->is_v13 = (hdmi_type == HDMI_TYPE13); hdata->cfg_hpd = pdata->cfg_hpd; hdata->get_hpd = pdata->get_hpd; hdata->dev = dev; @@ -2447,6 +2469,7 @@ static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume); struct platform_driver hdmi_driver = { .probe = hdmi_probe, .remove = __devexit_p(hdmi_remove), + .id_table = hdmi_driver_types, .driver = { .name = "exynos4-hdmi", .owner = THIS_MODULE,
From: Tomasz Stanislawski t.stanislaws@samsung.com
This patch fixes 'unsigned < 0' check in probe. Moreover it releases an interrupt at remove.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index b3a802b..3902917 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -64,8 +64,8 @@ struct hdmi_context { struct mutex hdmi_mutex;
void __iomem *regs; - unsigned int external_irq; - unsigned int internal_irq; + int external_irq; + int internal_irq;
struct i2c_client *ddc_port; struct i2c_client *hdmiphy_port; @@ -2424,6 +2424,7 @@ static int __devexit hdmi_remove(struct platform_device *pdev) pm_runtime_disable(dev);
free_irq(hdata->internal_irq, hdata); + free_irq(hdata->external_irq, hdata);
hdmi_resources_cleanup(hdata);
From: Tomasz Stanislawski t.stanislaws@samsung.com
The 'exynos-drm-hdmi' driver makes use of s5p-tv platform devices. Therefore the driver should use the same platform data to prevent crashes caused by dereferencing incorrect types. This patch corrects the exynos-drm-hdmi driver to the platform data from s5p-hdmi.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Joonyoung Shim jy0922.shim@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 55 +++++++++++++++------------------- 1 files changed, 24 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 3902917..90dce8c 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -40,6 +40,9 @@
#include "exynos_hdmi.h"
+#include <linux/gpio.h> +#include <media/s5p_hdmi.h> + #define MAX_WIDTH 1920 #define MAX_HEIGHT 1080 #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) @@ -76,8 +79,7 @@ struct hdmi_context { struct hdmi_resources res; void *parent_ctx;
- void (*cfg_hpd)(bool external); - int (*get_hpd)(void); + int hpd_gpio; };
/* HDMI Version 1.3 */ @@ -2024,8 +2026,6 @@ static void hdmi_poweron(struct hdmi_context *hdata)
hdata->powered = true;
- if (hdata->cfg_hpd) - hdata->cfg_hpd(true); mutex_unlock(&hdata->hdmi_mutex);
pm_runtime_get_sync(hdata->dev); @@ -2061,8 +2061,6 @@ static void hdmi_poweroff(struct hdmi_context *hdata) pm_runtime_put_sync(hdata->dev);
mutex_lock(&hdata->hdmi_mutex); - if (hdata->cfg_hpd) - hdata->cfg_hpd(false);
hdata->powered = false;
@@ -2110,17 +2108,13 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) struct exynos_drm_hdmi_context *ctx = arg; struct hdmi_context *hdata = ctx->ctx;
- if (!hdata->get_hpd) - goto out; - mutex_lock(&hdata->hdmi_mutex); - hdata->hpd = hdata->get_hpd(); + hdata->hpd = gpio_get_value(hdata->hpd_gpio); mutex_unlock(&hdata->hdmi_mutex);
if (ctx->drm_dev) drm_helper_hpd_irq_event(ctx->drm_dev);
-out: return IRQ_HANDLED; }
@@ -2143,18 +2137,9 @@ static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg) HDMI_INTC_FLAG_HPD_PLUG); }
- mutex_lock(&hdata->hdmi_mutex); - hdata->hpd = hdmi_reg_read(hdata, HDMI_HPD_STATUS); - if (hdata->powered && hdata->hpd) { - mutex_unlock(&hdata->hdmi_mutex); - goto out; - } - mutex_unlock(&hdata->hdmi_mutex); - if (ctx->drm_dev) drm_helper_hpd_irq_event(ctx->drm_dev);
-out: return IRQ_HANDLED; }
@@ -2287,7 +2272,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct exynos_drm_hdmi_context *drm_hdmi_ctx; struct hdmi_context *hdata; - struct exynos_drm_hdmi_pdata *pdata; + struct s5p_hdmi_platform_data *pdata; struct resource *res; int ret; enum hdmi_type hdmi_type; @@ -2323,8 +2308,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
hdmi_type = platform_get_device_id(pdev)->driver_data; hdata->is_v13 = (hdmi_type == HDMI_TYPE13); - hdata->cfg_hpd = pdata->cfg_hpd; - hdata->get_hpd = pdata->get_hpd; + hdata->hpd_gpio = pdata->hpd_gpio; hdata->dev = dev;
ret = hdmi_resources_init(hdata); @@ -2342,11 +2326,17 @@ static int __devinit hdmi_probe(struct platform_device *pdev) goto err_resource; }
+ ret = gpio_request(hdata->hpd_gpio, "HPD"); + if (ret) { + DRM_ERROR("failed to request HPD gpio\n"); + goto err_resource; + } + /* DDC i2c driver */ if (i2c_add_driver(&ddc_driver)) { DRM_ERROR("failed to register ddc i2c driver\n"); ret = -ENOENT; - goto err_resource; + goto err_gpio; }
hdata->ddc_port = hdmi_ddc; @@ -2360,32 +2350,31 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
hdata->hdmiphy_port = hdmi_hdmiphy;
- hdata->external_irq = platform_get_irq_byname(pdev, "external_irq"); + hdata->external_irq = gpio_to_irq(hdata->hpd_gpio); if (hdata->external_irq < 0) { - DRM_ERROR("failed to get platform irq\n"); + DRM_ERROR("failed to get GPIO external irq\n"); ret = hdata->external_irq; goto err_hdmiphy; }
- hdata->internal_irq = platform_get_irq_byname(pdev, "internal_irq"); + hdata->internal_irq = platform_get_irq(pdev, 0); if (hdata->internal_irq < 0) { DRM_ERROR("failed to get platform internal irq\n"); ret = hdata->internal_irq; goto err_hdmiphy; }
+ hdata->hpd = gpio_get_value(hdata->hpd_gpio); + ret = request_threaded_irq(hdata->external_irq, NULL, hdmi_external_irq_thread, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "hdmi_external", drm_hdmi_ctx); if (ret) { - DRM_ERROR("failed to register hdmi internal interrupt\n"); + DRM_ERROR("failed to register hdmi external interrupt\n"); goto err_hdmiphy; }
- if (hdata->cfg_hpd) - hdata->cfg_hpd(false); - ret = request_threaded_irq(hdata->internal_irq, NULL, hdmi_internal_irq_thread, IRQF_ONESHOT, "hdmi_internal", drm_hdmi_ctx); @@ -2407,6 +2396,8 @@ err_hdmiphy: i2c_del_driver(&hdmiphy_driver); err_ddc: i2c_del_driver(&ddc_driver); +err_gpio: + gpio_free(hdata->hpd_gpio); err_resource: hdmi_resources_cleanup(hdata); err_data: @@ -2426,6 +2417,8 @@ static int __devexit hdmi_remove(struct platform_device *pdev) free_irq(hdata->internal_irq, hdata); free_irq(hdata->external_irq, hdata);
+ gpio_free(hdata->hpd_gpio); + hdmi_resources_cleanup(hdata);
/* hdmiphy i2c driver */
From: Tomasz Stanislawski t.stanislaws@samsung.com
The plug/unplug interrupt are handled by a separate interrupt. So there is no need to replicate this mechanism in HDMI core.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 90dce8c..e3ab840 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1532,12 +1532,9 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
static void hdmi_conf_init(struct hdmi_context *hdata) { - /* enable HPD interrupts */ + /* disable HPD interrupts */ hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); - mdelay(10); - hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL | - HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
/* choose HDMI mode */ hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
This patch removes the drm hdmi platform data structure which is no longer in use by drm hdmi driver after this patch set get merged. s5p hdmi platform data structure is used instead.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- include/drm/exynos_drm.h | 13 ------------- 1 files changed, 0 insertions(+), 13 deletions(-)
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 0d1c503..8bdd49a 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -254,18 +254,5 @@ struct exynos_drm_common_hdmi_pd { struct device *mixer_dev; };
-/** - * Platform Specific Structure for DRM based HDMI core. - * - * @is_v13: set if hdmi version 13 is. - * @cfg_hpd: function pointer to configure hdmi hotplug detection pin - * @get_hpd: function pointer to get value of hdmi hotplug detection pin - */ -struct exynos_drm_hdmi_pdata { - bool is_v13; - void (*cfg_hpd)(bool external); - int (*get_hpd)(void); -}; - #endif /* __KERNEL__ */ #endif /* _EXYNOS_DRM_H_ */
This patch adds support for exynos5 ddc with device tree enabled.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_ddc.c | 22 +++++++++++++++++----- 1 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_ddc.c b/drivers/gpu/drm/exynos/exynos_ddc.c index 7e1051d..ef28779 100644 --- a/drivers/gpu/drm/exynos/exynos_ddc.c +++ b/drivers/gpu/drm/exynos/exynos_ddc.c @@ -26,29 +26,41 @@ static int s5p_ddc_probe(struct i2c_client *client, { hdmi_attach_ddc_client(client);
- dev_info(&client->adapter->dev, "attached s5p_ddc " - "into i2c adapter successfully\n"); + dev_info(&client->adapter->dev, + "attached %s into i2c adapter successfully\n", + client->name);
return 0; }
static int s5p_ddc_remove(struct i2c_client *client) { - dev_info(&client->adapter->dev, "detached s5p_ddc " - "from i2c adapter successfully\n"); + dev_info(&client->adapter->dev, + "detached %s from i2c adapter successfully\n", + client->name);
return 0; }
static struct i2c_device_id ddc_idtable[] = { {"s5p_ddc", 0}, + {"exynos5-hdmiddc", 0}, { }, };
+static struct of_device_id hdmiddc_match_types[] = { + { + .compatible = "samsung,exynos5-hdmiddc", + }, { + /* end node */ + } +}; + struct i2c_driver ddc_driver = { .driver = { - .name = "s5p_ddc", + .name = "exynos-hdmiddc", .owner = THIS_MODULE, + .of_match_table = hdmiddc_match_types, }, .id_table = ddc_idtable, .probe = s5p_ddc_probe,
This patch adds support for exynos5 hdmi phy with device tree enabled.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmiphy.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c index 9fe2995..a33073b 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmiphy.c +++ b/drivers/gpu/drm/exynos/exynos_hdmiphy.c @@ -42,13 +42,23 @@ static int hdmiphy_remove(struct i2c_client *client)
static const struct i2c_device_id hdmiphy_id[] = { { "s5p_hdmiphy", 0 }, + { "exynos5-hdmiphy", 0 }, { }, };
+static struct of_device_id hdmiphy_match_types[] = { + { + .compatible = "samsung,exynos5-hdmiphy", + }, { + /* end node */ + } +}; + struct i2c_driver hdmiphy_driver = { .driver = { - .name = "s5p-hdmiphy", + .name = "exynos-hdmiphy", .owner = THIS_MODULE, + .of_match_table = hdmiphy_match_types, }, .id_table = hdmiphy_id, .probe = hdmiphy_probe,
This patch adds the support for multiple mixer versions avaialble in various platform variants. Version is passed as a driver data field instead of paltform data.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_mixer.c | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 8a43ee1..30233a3 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -73,6 +73,12 @@ struct mixer_resources { struct clk *sclk_dac; };
+enum mixer_version_id { + MXR_VER_INVALID = -1, + MXR_VER_0_0_0_16, + MXR_VER_16_0_33_0, +}; + struct mixer_context { struct device *dev; int pipe; @@ -83,6 +89,11 @@ struct mixer_context { struct mutex mixer_mutex; struct mixer_resources mixer_res; struct hdmi_win_data win_data[MIXER_WIN_NR]; + enum mixer_version_id mxr_ver; +}; + +struct mixer_drv_data { + enum mixer_version_id version; };
static const u8 filter_y_horiz_tap8[] = { @@ -1023,11 +1034,24 @@ fail: return ret; }
+static struct mixer_drv_data exynos4_mxr_drv_data = { + .version = MXR_VER_0_0_0_16, +}; +static struct platform_device_id mixer_driver_types[] = { + { + .name = "s5p-mixer", + .driver_data = (unsigned long)&exynos4_mxr_drv_data, + }, { + /* end node */ + } +}; + static int __devinit mixer_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct exynos_drm_hdmi_context *drm_hdmi_ctx; struct mixer_context *ctx; + struct mixer_drv_data *drv; int ret;
dev_info(dev, "probe start\n"); @@ -1047,8 +1071,11 @@ static int __devinit mixer_probe(struct platform_device *pdev)
mutex_init(&ctx->mixer_mutex);
+ drv = (struct mixer_drv_data *)platform_get_device_id( + pdev)->driver_data; ctx->dev = &pdev->dev; drm_hdmi_ctx->ctx = (void *)ctx; + ctx->mxr_ver = drv->version;
platform_set_drvdata(pdev, drm_hdmi_ctx);
@@ -1101,4 +1128,5 @@ struct platform_driver mixer_driver = { }, .probe = mixer_probe, .remove = __devexit_p(mixer_remove), + .id_table = mixer_driver_types, };
On 09/28/2012 11:25 PM, Rahul Sharma wrote:
This patch adds the support for multiple mixer versions avaialble in various platform variants. Version is passed as a driver data field instead of paltform data.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com
drivers/gpu/drm/exynos/exynos_mixer.c | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 8a43ee1..30233a3 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -73,6 +73,12 @@ struct mixer_resources { struct clk *sclk_dac; };
+enum mixer_version_id {
- MXR_VER_INVALID = -1,
Does MXR_VER_INVALID enum need really?
- MXR_VER_0_0_0_16,
- MXR_VER_16_0_33_0,
+};
- struct mixer_context { struct device *dev; int pipe;
@@ -83,6 +89,11 @@ struct mixer_context { struct mutex mixer_mutex; struct mixer_resources mixer_res; struct hdmi_win_data win_data[MIXER_WIN_NR];
- enum mixer_version_id mxr_ver;
+};
+struct mixer_drv_data {
enum mixer_version_id version; };
static const u8 filter_y_horiz_tap8[] = {
@@ -1023,11 +1034,24 @@ fail: return ret; }
+static struct mixer_drv_data exynos4_mxr_drv_data = {
- .version = MXR_VER_0_0_0_16,
+};
Add one empty line.
+static struct platform_device_id mixer_driver_types[] = {
- {
.name = "s5p-mixer",
.driver_data = (unsigned long)&exynos4_mxr_drv_data,
- }, {
/* end node */
- }
+};
static int __devinit mixer_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct exynos_drm_hdmi_context *drm_hdmi_ctx; struct mixer_context *ctx;
struct mixer_drv_data *drv; int ret;
dev_info(dev, "probe start\n");
@@ -1047,8 +1071,11 @@ static int __devinit mixer_probe(struct platform_device *pdev)
mutex_init(&ctx->mixer_mutex);
drv = (struct mixer_drv_data *)platform_get_device_id(
pdev)->driver_data;
ctx->dev = &pdev->dev; drm_hdmi_ctx->ctx = (void *)ctx;
ctx->mxr_ver = drv->version;
platform_set_drvdata(pdev, drm_hdmi_ctx);
@@ -1101,4 +1128,5 @@ struct platform_driver mixer_driver = { }, .probe = mixer_probe, .remove = __devexit_p(mixer_remove),
- .id_table = mixer_driver_types, };
This patch adds support for disabling the video processor code based on the platform type. This is done based on a field in the mixer driver data which changes with the platform variant.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_mixer.c | 151 +++++++++++++++++++++------------ 1 files changed, 98 insertions(+), 53 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 30233a3..ff2a45d 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -84,6 +84,7 @@ struct mixer_context { int pipe; bool interlace; bool powered; + bool vp_enabled; u32 int_en;
struct mutex mixer_mutex; @@ -94,6 +95,7 @@ struct mixer_context {
struct mixer_drv_data { enum mixer_version_id version; + bool is_vp_enabled; };
static const u8 filter_y_horiz_tap8[] = { @@ -262,7 +264,8 @@ static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) mixer_reg_writemask(res, MXR_STATUS, enable ? MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
- vp_reg_write(res, VP_SHADOW_UPDATE, enable ? + if (ctx->vp_enabled) + vp_reg_write(res, VP_SHADOW_UPDATE, enable ? VP_SHADOW_UPDATE_ENABLE : 0); }
@@ -344,8 +347,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); break; case 2: - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); + if (ctx->vp_enabled) { + vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); + mixer_reg_writemask(res, MXR_CFG, val, + MXR_CFG_VP_ENABLE); + } break; } } @@ -603,7 +609,8 @@ static void mixer_win_reset(struct mixer_context *ctx) */ val = MXR_LAYER_CFG_GRP1_VAL(3); val |= MXR_LAYER_CFG_GRP0_VAL(2); - val |= MXR_LAYER_CFG_VP_VAL(1); + if (ctx->vp_enabled) + val |= MXR_LAYER_CFG_VP_VAL(1); mixer_reg_write(res, MXR_LAYER_CFG, val);
/* setting background color */ @@ -626,14 +633,17 @@ static void mixer_win_reset(struct mixer_context *ctx) val = MXR_GRP_CFG_ALPHA_VAL(0); mixer_reg_write(res, MXR_VIDEO_CFG, val);
- /* configuration of Video Processor Registers */ - vp_win_reset(ctx); - vp_default_filter(res); + if (ctx->vp_enabled) { + /* configuration of Video Processor Registers */ + vp_win_reset(ctx); + vp_default_filter(res); + }
/* disable all layers */ mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); + if (ctx->vp_enabled) + mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
mixer_vsync_set_update(ctx, true); spin_unlock_irqrestore(&res->reg_slock, flags); @@ -656,8 +666,10 @@ static void mixer_poweron(struct mixer_context *ctx) pm_runtime_get_sync(ctx->dev);
clk_enable(res->mixer); - clk_enable(res->vp); - clk_enable(res->sclk_mixer); + if (ctx->vp_enabled) { + clk_enable(res->vp); + clk_enable(res->sclk_mixer); + }
mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_win_reset(ctx); @@ -677,8 +689,10 @@ static void mixer_poweroff(struct mixer_context *ctx) ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
clk_disable(res->mixer); - clk_disable(res->vp); - clk_disable(res->sclk_mixer); + if (ctx->vp_enabled) { + clk_disable(res->vp); + clk_disable(res->sclk_mixer); + }
pm_runtime_put_sync(ctx->dev);
@@ -811,7 +825,7 @@ static void mixer_win_commit(void *ctx, int win)
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
- if (win > 1) + if (win > 1 && mixer_ctx->vp_enabled) vp_video_buffer(mixer_ctx, win); else mixer_graph_buffer(mixer_ctx, win); @@ -947,39 +961,20 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, ret = -ENODEV; goto fail; } - mixer_res->vp = clk_get(dev, "vp"); - if (IS_ERR_OR_NULL(mixer_res->vp)) { - dev_err(dev, "failed to get clock 'vp'\n"); - ret = -ENODEV; - goto fail; - } - mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); - if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { - dev_err(dev, "failed to get clock 'sclk_mixer'\n"); - ret = -ENODEV; - goto fail; - } + mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); ret = -ENODEV; goto fail; } - mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); - if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { - dev_err(dev, "failed to get clock 'sclk_dac'\n"); - ret = -ENODEV; - goto fail; - } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(dev, "get memory resource failed.\n"); ret = -ENXIO; goto fail; }
- clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); - mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (mixer_res->mixer_regs == NULL) { @@ -988,54 +983,92 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, goto fail; }
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { - dev_err(dev, "get memory resource failed.\n"); + dev_err(dev, "get interrupt resource failed.\n"); ret = -ENXIO; goto fail; }
- mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (mixer_res->vp_regs == NULL) { - dev_err(dev, "register mapping failed.\n"); - ret = -ENXIO; + ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, + 0, "drm_mixer", ctx); + if (ret) { + dev_err(dev, "request interrupt failed.\n"); goto fail; } + mixer_res->irq = res->start;
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); + return 0; + +fail: + if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) + clk_put(mixer_res->sclk_hdmi); + if (!IS_ERR_OR_NULL(mixer_res->mixer)) + clk_put(mixer_res->mixer); + return ret; +} + +static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx, + struct platform_device *pdev) +{ + struct mixer_context *mixer_ctx = ctx->ctx; + struct device *dev = &pdev->dev; + struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; + struct resource *res; + int ret; + + mixer_res->vp = clk_get(dev, "vp"); + if (IS_ERR_OR_NULL(mixer_res->vp)) { + dev_err(dev, "failed to get clock 'vp'\n"); + ret = -ENODEV; + goto fail; + } + mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); + if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { + dev_err(dev, "failed to get clock 'sclk_mixer'\n"); + ret = -ENODEV; + goto fail; + } + mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); + if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { + dev_err(dev, "failed to get clock 'sclk_dac'\n"); + ret = -ENODEV; + goto fail; + } + + if (mixer_res->sclk_hdmi) + clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res == NULL) { - dev_err(dev, "get interrupt resource failed.\n"); + dev_err(dev, "get memory resource failed.\n"); ret = -ENXIO; goto fail; }
- ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, - 0, "drm_mixer", ctx); - if (ret) { - dev_err(dev, "request interrupt failed.\n"); + mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (mixer_res->vp_regs == NULL) { + dev_err(dev, "register mapping failed.\n"); + ret = -ENXIO; goto fail; } - mixer_res->irq = res->start;
return 0;
fail: if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) clk_put(mixer_res->sclk_dac); - if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) - clk_put(mixer_res->sclk_hdmi); if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer)) clk_put(mixer_res->sclk_mixer); if (!IS_ERR_OR_NULL(mixer_res->vp)) clk_put(mixer_res->vp); - if (!IS_ERR_OR_NULL(mixer_res->mixer)) - clk_put(mixer_res->mixer); return ret; }
static struct mixer_drv_data exynos4_mxr_drv_data = { .version = MXR_VER_0_0_0_16, + .is_vp_enabled = 1, }; static struct platform_device_id mixer_driver_types[] = { { @@ -1075,14 +1108,26 @@ static int __devinit mixer_probe(struct platform_device *pdev) pdev)->driver_data; ctx->dev = &pdev->dev; drm_hdmi_ctx->ctx = (void *)ctx; + ctx->vp_enabled = drv->is_vp_enabled; ctx->mxr_ver = drv->version;
platform_set_drvdata(pdev, drm_hdmi_ctx);
/* acquire resources: regs, irqs, clocks */ ret = mixer_resources_init(drm_hdmi_ctx, pdev); - if (ret) + if (ret) { + DRM_ERROR("mixer_resources_init failed\n"); goto fail; + } + + if (ctx->vp_enabled) { + /* acquire vp resources: regs, irqs, clocks */ + ret = vp_resources_init(drm_hdmi_ctx, pdev); + if (ret) { + DRM_ERROR("vp_resources_init failed\n"); + goto fail; + } + }
/* register specific callback point to common hdmi. */ exynos_mixer_ops_register(&mixer_ops);
This patch adds support for exynos5 mixer with device tree enabled.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com Signed-off-by: Fahad Kunnathadi fahad.k@samsung.com --- drivers/gpu/drm/exynos/exynos_mixer.c | 41 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ff2a45d..d34562a 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -645,6 +645,10 @@ static void mixer_win_reset(struct mixer_context *ctx) if (ctx->vp_enabled) mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
+ /* enable vsync interrupt after mixer reset*/ + mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, + MXR_INT_EN_VSYNC); + mixer_vsync_set_update(ctx, true); spin_unlock_irqrestore(&res->reg_slock, flags); } @@ -913,6 +917,11 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
/* handling VSYNC */ if (val & MXR_INT_STATUS_VSYNC) { + if (ctx->mxr_ver == MXR_VER_16_0_33_0) { + /* layer update mandatory for mixer 16.0.33.0 */ + mixer_reg_writemask(res, MXR_CFG, ~0, + MXR_CFG_LAYER_UPDATE); + } /* interlace scan need to check shadow register */ if (ctx->interlace) { base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); @@ -1066,6 +1075,11 @@ fail: return ret; }
+static struct mixer_drv_data exynos5_mxr_drv_data = { + .version = MXR_VER_16_0_33_0, + .is_vp_enabled = 0, +}; + static struct mixer_drv_data exynos4_mxr_drv_data = { .version = MXR_VER_0_0_0_16, .is_vp_enabled = 1, @@ -1075,6 +1089,18 @@ static struct platform_device_id mixer_driver_types[] = { .name = "s5p-mixer", .driver_data = (unsigned long)&exynos4_mxr_drv_data, }, { + .name = "exynos5-mixer", + .driver_data = (unsigned long)&exynos5_mxr_drv_data, + }, { + /* end node */ + } +}; + +static struct of_device_id mixer_match_types[] = { + { + .compatible = "samsung,exynos5-mixer", + .data = &exynos5_mxr_drv_data, + }, { /* end node */ } }; @@ -1104,8 +1130,16 @@ static int __devinit mixer_probe(struct platform_device *pdev)
mutex_init(&ctx->mixer_mutex);
- drv = (struct mixer_drv_data *)platform_get_device_id( - pdev)->driver_data; + if (dev->of_node) { + const struct of_device_id *match; + match = of_match_node(of_match_ptr(mixer_match_types), + pdev->dev.of_node); + drv = match->data; + } else { + drv = (struct mixer_drv_data *) + platform_get_device_id(pdev)->driver_data; + } + ctx->dev = &pdev->dev; drm_hdmi_ctx->ctx = (void *)ctx; ctx->vp_enabled = drv->is_vp_enabled; @@ -1167,9 +1201,10 @@ static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
struct platform_driver mixer_driver = { .driver = { - .name = "s5p-mixer", + .name = "exynos-mixer", .owner = THIS_MODULE, .pm = &mixer_pm_ops, + .of_match_table = mixer_match_types, }, .probe = mixer_probe, .remove = __devexit_p(mixer_remove), diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index fd2f4d1..6ee60be 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -69,6 +69,7 @@ (((val) << (low_bit)) & MXR_MASK(high_bit, low_bit))
/* bits for MXR_STATUS */ +#define MXR_STATUS_SOFT_RESET (1 << 8) #define MXR_STATUS_16_BURST (1 << 7) #define MXR_STATUS_BURST_MASK (1 << 7) #define MXR_STATUS_BIG_ENDIAN (1 << 3) @@ -77,6 +78,7 @@ #define MXR_STATUS_REG_RUN (1 << 0)
/* bits for MXR_CFG */ +#define MXR_CFG_LAYER_UPDATE (1 << 31) #define MXR_CFG_RGB601_0_255 (0 << 9) #define MXR_CFG_RGB601_16_235 (1 << 9) #define MXR_CFG_RGB709_0_255 (2 << 9)
On 09/28/2012 11:25 PM, Rahul Sharma wrote:
This patch adds support for exynos5 mixer with device tree enabled.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com Signed-off-by: Fahad Kunnathadi fahad.k@samsung.com
drivers/gpu/drm/exynos/exynos_mixer.c | 41 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ff2a45d..d34562a 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -645,6 +645,10 @@ static void mixer_win_reset(struct mixer_context *ctx) if (ctx->vp_enabled) mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
- /* enable vsync interrupt after mixer reset*/
- mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
MXR_INT_EN_VSYNC);
The vsync interrupt is controlled by mixer_enable_vblank() and mixer_disable_vblank(). After mixer reset, need to check whether it is requested to enable vblank.
mixer_vsync_set_update(ctx, true); spin_unlock_irqrestore(&res->reg_slock, flags); } @@ -913,6 +917,11 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
/* handling VSYNC */ if (val & MXR_INT_STATUS_VSYNC) {
if (ctx->mxr_ver == MXR_VER_16_0_33_0) {
/* layer update mandatory for mixer 16.0.33.0 */
mixer_reg_writemask(res, MXR_CFG, ~0,
MXR_CFG_LAYER_UPDATE);
/* interlace scan need to check shadow register */ if (ctx->interlace) { base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));}
@@ -1066,6 +1075,11 @@ fail: return ret; }
+static struct mixer_drv_data exynos5_mxr_drv_data = {
- .version = MXR_VER_16_0_33_0,
- .is_vp_enabled = 0,
+};
- static struct mixer_drv_data exynos4_mxr_drv_data = { .version = MXR_VER_0_0_0_16, .is_vp_enabled = 1,
@@ -1075,6 +1089,18 @@ static struct platform_device_id mixer_driver_types[] = { .name = "s5p-mixer", .driver_data = (unsigned long)&exynos4_mxr_drv_data, }, {
.name = "exynos5-mixer",
.driver_data = (unsigned long)&exynos5_mxr_drv_data,
- }, {
/* end node */
- }
+};
+static struct of_device_id mixer_match_types[] = {
- {
.compatible = "samsung,exynos5-mixer",
.data = &exynos5_mxr_drv_data,
- }, { /* end node */ } };
@@ -1104,8 +1130,16 @@ static int __devinit mixer_probe(struct platform_device *pdev)
mutex_init(&ctx->mixer_mutex);
- drv = (struct mixer_drv_data *)platform_get_device_id(
pdev)->driver_data;
- if (dev->of_node) {
const struct of_device_id *match;
match = of_match_node(of_match_ptr(mixer_match_types),
pdev->dev.of_node);
drv = match->data;
- } else {
drv = (struct mixer_drv_data *)
platform_get_device_id(pdev)->driver_data;
- }
- ctx->dev = &pdev->dev; drm_hdmi_ctx->ctx = (void *)ctx; ctx->vp_enabled = drv->is_vp_enabled;
@@ -1167,9 +1201,10 @@ static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
struct platform_driver mixer_driver = { .driver = {
.name = "s5p-mixer",
.owner = THIS_MODULE, .pm = &mixer_pm_ops,.name = "exynos-mixer",
}, .probe = mixer_probe, .remove = __devexit_p(mixer_remove),.of_match_table = mixer_match_types,
diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index fd2f4d1..6ee60be 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -69,6 +69,7 @@ (((val) << (low_bit)) & MXR_MASK(high_bit, low_bit))
/* bits for MXR_STATUS */ +#define MXR_STATUS_SOFT_RESET (1 << 8) #define MXR_STATUS_16_BURST (1 << 7) #define MXR_STATUS_BURST_MASK (1 << 7) #define MXR_STATUS_BIG_ENDIAN (1 << 3) @@ -77,6 +78,7 @@ #define MXR_STATUS_REG_RUN (1 << 0)
/* bits for MXR_CFG */ +#define MXR_CFG_LAYER_UPDATE (1 << 31) #define MXR_CFG_RGB601_0_255 (0 << 9) #define MXR_CFG_RGB601_16_235 (1 << 9) #define MXR_CFG_RGB709_0_255 (2 << 9)
This patch removed the is_v13 variable from the hdmi driver context. It is replaced with condition check for the hdmi version. This cleans the way for handling further hdmi versions.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 40 +++++++++++++++++----------------- 1 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index e3ab840..89e798b 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -47,6 +47,11 @@ #define MAX_HEIGHT 1080 #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
+enum hdmi_type { + HDMI_TYPE13, + HDMI_TYPE14, +}; + struct hdmi_resources { struct clk *hdmi; struct clk *sclk_hdmi; @@ -62,7 +67,6 @@ struct hdmi_context { struct drm_device *drm_dev; bool hpd; bool powered; - bool is_v13; bool dvi_mode; struct mutex hdmi_mutex;
@@ -80,6 +84,8 @@ struct hdmi_context { void *parent_ctx;
int hpd_gpio; + + enum hdmi_type type; };
/* HDMI Version 1.3 */ @@ -1211,7 +1217,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->is_v13) + if (hdata->type == HDMI_TYPE13) hdmi_v13_regs_dump(hdata, prefix); else hdmi_v14_regs_dump(hdata, prefix); @@ -1252,7 +1258,7 @@ static int hdmi_v14_conf_index(struct drm_display_mode *mode) static int hdmi_conf_index(struct hdmi_context *hdata, struct drm_display_mode *mode) { - if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) return hdmi_v13_conf_index(mode);
return hdmi_v14_conf_index(mode); @@ -1348,7 +1354,7 @@ static int hdmi_check_timing(void *ctx, void *timing) check_timing->yres, check_timing->refresh, check_timing->vmode);
- if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) return hdmi_v13_check_timing(check_timing); else return hdmi_v14_check_timing(check_timing); @@ -1414,7 +1420,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->is_v13) + if (hdata->type == HDMI_TYPE13) hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4); else hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); @@ -1518,7 +1524,7 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) { u32 reg;
- if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) reg = HDMI_V13_CORE_RSTOUT; else reg = HDMI_CORE_RSTOUT; @@ -1550,7 +1556,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata) HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS); }
- if (hdata->is_v13) { + if (hdata->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); @@ -1832,7 +1838,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
static void hdmi_timing_apply(struct hdmi_context *hdata) { - if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) hdmi_v13_timing_apply(hdata); else hdmi_v14_timing_apply(hdata); @@ -1854,7 +1860,7 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) if (hdata->hdmiphy_port) i2c_master_send(hdata->hdmiphy_port, buffer, 2);
- if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) reg = HDMI_V13_PHY_RSTOUT; else reg = HDMI_PHY_RSTOUT; @@ -1881,7 +1887,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) }
/* pixel clock */ - if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; else hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data; @@ -1949,7 +1955,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
drm_mode_set_crtcinfo(adjusted_mode, 0);
- if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) index = hdmi_v13_conf_index(adjusted_mode); else index = hdmi_v14_conf_index(adjusted_mode); @@ -1963,7 +1969,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, * to adjusted_mode. */ list_for_each_entry(m, &connector->modes, head) { - if (hdata->is_v13) + if (hdata->type == HDMI_TYPE13) index = hdmi_v13_conf_index(m); else index = hdmi_v14_conf_index(m); @@ -2244,11 +2250,6 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) hdmi_hdmiphy = hdmiphy; }
-enum hdmi_type { - HDMI_TYPE13, - HDMI_TYPE14, -}; - static struct platform_device_id hdmi_driver_types[] = { { .name = "s5pv210-hdmi", @@ -2272,7 +2273,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev) struct s5p_hdmi_platform_data *pdata; struct resource *res; int ret; - enum hdmi_type hdmi_type;
DRM_DEBUG_KMS("[%d]\n", __LINE__);
@@ -2303,8 +2303,8 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drm_hdmi_ctx);
- hdmi_type = platform_get_device_id(pdev)->driver_data; - hdata->is_v13 = (hdmi_type == HDMI_TYPE13); + hdata->type = (enum hdmi_type)platform_get_device_id + (pdev)->driver_data; hdata->hpd_gpio = pdata->hpd_gpio; hdata->dev = dev;
This patch adds support for exynos5 hdmi with device tree enabled.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 83 ++++++++++++++++++++++++++++++++-- 1 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 89e798b..5caf49f 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -32,6 +32,9 @@ #include <linux/pm_runtime.h> #include <linux/clk.h> #include <linux/regulator/consumer.h> +#include <linux/io.h> +#include <linux/of_gpio.h> +#include <plat/gpio-cfg.h>
#include <drm/exynos_drm.h>
@@ -2250,6 +2253,41 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) hdmi_hdmiphy = hdmiphy; }
+#ifdef CONFIG_OF +static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata + (struct device *dev) +{ + struct device_node *np = dev->of_node; + struct s5p_hdmi_platform_data *pd; + enum of_gpio_flags flags; + u32 value; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) { + DRM_ERROR("memory allocation for pdata failed\n"); + goto err_data; + } + + if (!of_find_property(np, "hpd-gpio", &value)) { + DRM_ERROR("no hpd gpio property found\n"); + goto err_data; + } + + pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags); + + return pd; + +err_data: + return NULL; +} +#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", @@ -2259,7 +2297,19 @@ static struct platform_device_id hdmi_driver_types[] = { .driver_data = HDMI_TYPE13, }, { .name = "exynos4-hdmi14", - .driver_data = HDMI_TYPE14, + .driver_data = HDMI_TYPE14, + }, { + .name = "exynos5-hdmi", + .driver_data = HDMI_TYPE14, + }, { + /* end node */ + } +}; + +static struct of_device_id hdmi_match_types[] = { + { + .compatible = "samsung,exynos5-hdmi", + .data = (void *)HDMI_TYPE14, }, { /* end node */ } @@ -2276,7 +2326,16 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
DRM_DEBUG_KMS("[%d]\n", __LINE__);
- pdata = pdev->dev.platform_data; + if (pdev->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 = pdev->dev.platform_data; + } + if (!pdata) { DRM_ERROR("no platform data specified\n"); return -EINVAL; @@ -2303,18 +2362,33 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drm_hdmi_ctx);
- hdata->type = (enum hdmi_type)platform_get_device_id + if (dev->of_node) { + const struct of_device_id *match; + match = of_match_node(of_match_ptr(hdmi_match_types), + pdev->dev.of_node); + hdata->type = (enum hdmi_type)match->data; + } else { + hdata->type = (enum hdmi_type)platform_get_device_id (pdev)->driver_data; + } + hdata->hpd_gpio = pdata->hpd_gpio; hdata->dev = dev;
ret = hdmi_resources_init(hdata); + if (ret) { ret = -EINVAL; + DRM_ERROR("hdmi_resources_init failed\n"); goto err_data; }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DRM_ERROR("failed to find registers\n"); + ret = -ENOENT; + goto err_resource; + }
hdata->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hdata->regs) { @@ -2462,8 +2536,9 @@ struct platform_driver hdmi_driver = { .remove = __devexit_p(hdmi_remove), .id_table = hdmi_driver_types, .driver = { - .name = "exynos4-hdmi", + .name = "exynos-hdmi", .owner = THIS_MODULE, .pm = &hdmi_pm_ops, + .of_match_table = hdmi_match_types, }, };
exynos-drm-hdmi need context pointers from hdmi and mixer. These pointers were expected from the plf data. Cleaned this dependency by exporting i/f which are called by hdmi, mixer driver probes for setting their context.
Signed-off-by: Rahul Sharma rahul.sharma@samsung.com --- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 51 +++++++++++++++-------------- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 2 + drivers/gpu/drm/exynos/exynos_hdmi.c | 3 ++ drivers/gpu/drm/exynos/exynos_mixer.c | 3 ++ include/drm/exynos_drm.h | 14 -------- 5 files changed, 34 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 0584132..85304c4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -29,6 +29,11 @@ #define get_ctx_from_subdrv(subdrv) container_of(subdrv,\ struct drm_hdmi_context, subdrv);
+/* Common hdmi subdrv needs to access the hdmi and mixer though context. +* These should be initialied by the repective drivers */ +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_hdmi_ops *hdmi_ops; static struct exynos_mixer_ops *mixer_ops; @@ -41,6 +46,18 @@ struct drm_hdmi_context { bool enabled[MIXER_WIN_NR]; };
+void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx) +{ + if (ctx) + hdmi_ctx = ctx; +} + +void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx) +{ + if (ctx) + mixer_ctx = ctx; +} + void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) { DRM_DEBUG_KMS("%s\n", __FILE__); @@ -303,46 +320,30 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev, { struct exynos_drm_subdrv *subdrv = to_subdrv(dev); struct drm_hdmi_context *ctx; - struct platform_device *pdev = to_platform_device(dev); - struct exynos_drm_common_hdmi_pd *pd;
DRM_DEBUG_KMS("%s\n", __FILE__);
- pd = pdev->dev.platform_data; - - if (!pd) { - DRM_DEBUG_KMS("platform data is null.\n"); + if (!hdmi_ctx) { + DRM_ERROR("hdmi context not initialized.\n"); return -EFAULT; }
- if (!pd->hdmi_dev) { - DRM_DEBUG_KMS("hdmi device is null.\n"); - return -EFAULT; - } - - if (!pd->mixer_dev) { - DRM_DEBUG_KMS("mixer device is null.\n"); + if (!mixer_ctx) { + DRM_ERROR("mixer context not initialized.\n"); return -EFAULT; }
ctx = get_ctx_from_subdrv(subdrv);
- ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *) - to_context(pd->hdmi_dev); - if (!ctx->hdmi_ctx) { - DRM_DEBUG_KMS("hdmi context is null.\n"); + if (!ctx) { + DRM_ERROR("no drm hdmi context.\n"); return -EFAULT; }
- ctx->hdmi_ctx->drm_dev = drm_dev; - - ctx->mixer_ctx = (struct exynos_drm_hdmi_context *) - to_context(pd->mixer_dev); - if (!ctx->mixer_ctx) { - DRM_DEBUG_KMS("mixer context is null.\n"); - return -EFAULT; - } + ctx->hdmi_ctx = hdmi_ctx; + ctx->mixer_ctx = mixer_ctx;
+ ctx->hdmi_ctx->drm_dev = drm_dev; ctx->mixer_ctx->drm_dev = drm_dev;
return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index d9f9e9f..2da5ffd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -73,6 +73,8 @@ struct exynos_mixer_ops { void (*win_disable)(void *ctx, int zpos); };
+void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx); +void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx); 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 5caf49f..e6b784d 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2454,6 +2454,9 @@ static int __devinit hdmi_probe(struct platform_device *pdev) goto err_free_irq; }
+ /* Attach HDMI Driver to common hdmi. */ + exynos_hdmi_drv_attach(drm_hdmi_ctx); + /* register specific callbacks to common hdmi. */ exynos_hdmi_ops_register(&hdmi_ops);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index d34562a..672e6f7 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1163,6 +1163,9 @@ static int __devinit mixer_probe(struct platform_device *pdev) } }
+ /* attach mixer driver to common hdmi. */ + exynos_mixer_drv_attach(drm_hdmi_ctx); + /* register specific callback point to common hdmi. */ exynos_mixer_ops_register(&mixer_ops);
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 8bdd49a..8ac4079 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -240,19 +240,5 @@ struct exynos_drm_fimd_pdata { unsigned int bpp; };
-/** - * Platform Specific Structure for DRM based HDMI. - * - * @hdmi_dev: device point to specific hdmi driver. - * @mixer_dev: device point to specific mixer driver. - * - * this structure is used for common hdmi driver and each device object - * would be used to access specific device driver(hdmi or mixer driver) - */ -struct exynos_drm_common_hdmi_pd { - struct device *hdmi_dev; - struct device *mixer_dev; -}; - #endif /* __KERNEL__ */ #endif /* _EXYNOS_DRM_H_ */
To Mr. Shim,
Can you check these patch series?
Thank you, Kyungmin Park
On 9/28/12, Rahul Sharma rahul.sharma@samsung.com wrote:
This patch set adds the DT based support for Samsung's Exynos5250 in DRM-HDMI. It includes disabling of hdmi internal interrupt, suppport for platform variants for hdmi and mixer, support to disable video processor based on platform type and removal of drm common platform data.
Rahul Sharma (9): drm: exynos: remove drm hdmi platform data struct drm: exynos: hdmi: add support for exynos5 ddc drm: exynos: hdmi: add support for exynos5 hdmiphy drm: exynos: hdmi: add support for platform variants for mixer drm: exynos: hdmi: add support to disable video processor in mixer drm: exynos: hdmi: add support for exynos5 mixer drm: exynos: hdmi: replace is_v13 with version check in hdmi drm: exynos: hdmi: add support for exynos5 hdmi drm: exynos: hdmi: remove drm common hdmi platform data struct
Tomasz Stanislawski (5): media: s5p-hdmi: add HPD GPIO to platform data drm: exynos: hdmi: support for platform variants drm: exynos: hdmi: fix interrupt handling drm: exynos: hdmi: use s5p-hdmi platform data drm: exynos: hdmi: turn off HPD interrupt in HDMI chip
drivers/gpu/drm/exynos/exynos_ddc.c | 22 +++- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 51 ++++---- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 2 + drivers/gpu/drm/exynos/exynos_hdmi.c | 196 ++++++++++++++++++++------- drivers/gpu/drm/exynos/exynos_hdmiphy.c | 12 ++- drivers/gpu/drm/exynos/exynos_mixer.c | 219 ++++++++++++++++++++++-------- drivers/gpu/drm/exynos/regs-mixer.h | 2 + include/drm/exynos_drm.h | 27 ---- include/media/s5p_hdmi.h | 2 + 9 files changed, 369 insertions(+), 164 deletions(-)
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi,
On 09/28/2012 11:25 PM, Rahul Sharma wrote:
This patch set adds the DT based support for Samsung's Exynos5250 in DRM-HDMI. It includes disabling of hdmi internal interrupt, suppport for platform variants for hdmi and mixer, support to disable video processor based on platform type and removal of drm common platform data.
Looks good to me overall, i commented a bit.
Thanks.
Rahul Sharma (9): drm: exynos: remove drm hdmi platform data struct drm: exynos: hdmi: add support for exynos5 ddc drm: exynos: hdmi: add support for exynos5 hdmiphy drm: exynos: hdmi: add support for platform variants for mixer drm: exynos: hdmi: add support to disable video processor in mixer drm: exynos: hdmi: add support for exynos5 mixer drm: exynos: hdmi: replace is_v13 with version check in hdmi drm: exynos: hdmi: add support for exynos5 hdmi drm: exynos: hdmi: remove drm common hdmi platform data struct
Tomasz Stanislawski (5): media: s5p-hdmi: add HPD GPIO to platform data drm: exynos: hdmi: support for platform variants drm: exynos: hdmi: fix interrupt handling drm: exynos: hdmi: use s5p-hdmi platform data drm: exynos: hdmi: turn off HPD interrupt in HDMI chip
drivers/gpu/drm/exynos/exynos_ddc.c | 22 +++- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 51 ++++---- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 2 + drivers/gpu/drm/exynos/exynos_hdmi.c | 196 ++++++++++++++++++++------- drivers/gpu/drm/exynos/exynos_hdmiphy.c | 12 ++- drivers/gpu/drm/exynos/exynos_mixer.c | 219 ++++++++++++++++++++++-------- drivers/gpu/drm/exynos/regs-mixer.h | 2 + include/drm/exynos_drm.h | 27 ---- include/media/s5p_hdmi.h | 2 + 9 files changed, 369 insertions(+), 164 deletions(-)
dri-devel@lists.freedesktop.org