提交 1b8e5747 编写于 作者: R Rahul Sharma 提交者: Inki Dae

drm: exynos: hdmi: add support to disable video processor in mixer

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: NRahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: NKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: NInki Dae <inki.dae@samsung.com>
上级 1e123441
...@@ -83,6 +83,7 @@ struct mixer_context { ...@@ -83,6 +83,7 @@ struct mixer_context {
int pipe; int pipe;
bool interlace; bool interlace;
bool powered; bool powered;
bool vp_enabled;
u32 int_en; u32 int_en;
struct mutex mixer_mutex; struct mutex mixer_mutex;
...@@ -93,6 +94,7 @@ struct mixer_context { ...@@ -93,6 +94,7 @@ struct mixer_context {
struct mixer_drv_data { struct mixer_drv_data {
enum mixer_version_id version; enum mixer_version_id version;
bool is_vp_enabled;
}; };
static const u8 filter_y_horiz_tap8[] = { static const u8 filter_y_horiz_tap8[] = {
...@@ -261,7 +263,8 @@ static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) ...@@ -261,7 +263,8 @@ static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
mixer_reg_writemask(res, MXR_STATUS, enable ? mixer_reg_writemask(res, MXR_STATUS, enable ?
MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_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); VP_SHADOW_UPDATE_ENABLE : 0);
} }
...@@ -343,8 +346,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) ...@@ -343,8 +346,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); mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
break; break;
case 2: case 2:
vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); if (ctx->vp_enabled) {
mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
mixer_reg_writemask(res, MXR_CFG, val,
MXR_CFG_VP_ENABLE);
}
break; break;
} }
} }
...@@ -602,7 +608,8 @@ static void mixer_win_reset(struct mixer_context *ctx) ...@@ -602,7 +608,8 @@ static void mixer_win_reset(struct mixer_context *ctx)
*/ */
val = MXR_LAYER_CFG_GRP1_VAL(3); val = MXR_LAYER_CFG_GRP1_VAL(3);
val |= MXR_LAYER_CFG_GRP0_VAL(2); 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); mixer_reg_write(res, MXR_LAYER_CFG, val);
/* setting background color */ /* setting background color */
...@@ -625,14 +632,17 @@ static void mixer_win_reset(struct mixer_context *ctx) ...@@ -625,14 +632,17 @@ static void mixer_win_reset(struct mixer_context *ctx)
val = MXR_GRP_CFG_ALPHA_VAL(0); val = MXR_GRP_CFG_ALPHA_VAL(0);
mixer_reg_write(res, MXR_VIDEO_CFG, val); mixer_reg_write(res, MXR_VIDEO_CFG, val);
/* configuration of Video Processor Registers */ if (ctx->vp_enabled) {
vp_win_reset(ctx); /* configuration of Video Processor Registers */
vp_default_filter(res); vp_win_reset(ctx);
vp_default_filter(res);
}
/* disable all layers */ /* disable all layers */
mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); 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_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); mixer_vsync_set_update(ctx, true);
spin_unlock_irqrestore(&res->reg_slock, flags); spin_unlock_irqrestore(&res->reg_slock, flags);
...@@ -655,8 +665,10 @@ static void mixer_poweron(struct mixer_context *ctx) ...@@ -655,8 +665,10 @@ static void mixer_poweron(struct mixer_context *ctx)
pm_runtime_get_sync(ctx->dev); pm_runtime_get_sync(ctx->dev);
clk_enable(res->mixer); clk_enable(res->mixer);
clk_enable(res->vp); if (ctx->vp_enabled) {
clk_enable(res->sclk_mixer); clk_enable(res->vp);
clk_enable(res->sclk_mixer);
}
mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
mixer_win_reset(ctx); mixer_win_reset(ctx);
...@@ -676,8 +688,10 @@ static void mixer_poweroff(struct mixer_context *ctx) ...@@ -676,8 +688,10 @@ static void mixer_poweroff(struct mixer_context *ctx)
ctx->int_en = mixer_reg_read(res, MXR_INT_EN); ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
clk_disable(res->mixer); clk_disable(res->mixer);
clk_disable(res->vp); if (ctx->vp_enabled) {
clk_disable(res->sclk_mixer); clk_disable(res->vp);
clk_disable(res->sclk_mixer);
}
pm_runtime_put_sync(ctx->dev); pm_runtime_put_sync(ctx->dev);
...@@ -810,7 +824,7 @@ static void mixer_win_commit(void *ctx, int win) ...@@ -810,7 +824,7 @@ static void mixer_win_commit(void *ctx, int win)
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, 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); vp_video_buffer(mixer_ctx, win);
else else
mixer_graph_buffer(mixer_ctx, win); mixer_graph_buffer(mixer_ctx, win);
...@@ -946,39 +960,20 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, ...@@ -946,39 +960,20 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
ret = -ENODEV; ret = -ENODEV;
goto fail; 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"); mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
ret = -ENODEV; ret = -ENODEV;
goto fail; goto fail;
} }
mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
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");
if (res == NULL) { if (res == NULL) {
dev_err(dev, "get memory resource failed.\n"); dev_err(dev, "get memory resource failed.\n");
ret = -ENXIO; ret = -ENXIO;
goto fail; goto fail;
} }
clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
resource_size(res)); resource_size(res));
if (mixer_res->mixer_regs == NULL) { if (mixer_res->mixer_regs == NULL) {
...@@ -987,54 +982,92 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, ...@@ -987,54 +982,92 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
goto fail; goto fail;
} }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) { if (res == NULL) {
dev_err(dev, "get memory resource failed.\n"); dev_err(dev, "get interrupt resource failed.\n");
ret = -ENXIO; ret = -ENXIO;
goto fail; goto fail;
} }
mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
resource_size(res)); 0, "drm_mixer", ctx);
if (mixer_res->vp_regs == NULL) { if (ret) {
dev_err(dev, "register mapping failed.\n"); dev_err(dev, "request interrupt failed.\n");
ret = -ENXIO;
goto fail; 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) { if (res == NULL) {
dev_err(dev, "get interrupt resource failed.\n"); dev_err(dev, "get memory resource failed.\n");
ret = -ENXIO; ret = -ENXIO;
goto fail; goto fail;
} }
ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
0, "drm_mixer", ctx); resource_size(res));
if (ret) { if (mixer_res->vp_regs == NULL) {
dev_err(dev, "request interrupt failed.\n"); dev_err(dev, "register mapping failed.\n");
ret = -ENXIO;
goto fail; goto fail;
} }
mixer_res->irq = res->start;
return 0; return 0;
fail: fail:
if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
clk_put(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)) if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
clk_put(mixer_res->sclk_mixer); clk_put(mixer_res->sclk_mixer);
if (!IS_ERR_OR_NULL(mixer_res->vp)) if (!IS_ERR_OR_NULL(mixer_res->vp))
clk_put(mixer_res->vp); clk_put(mixer_res->vp);
if (!IS_ERR_OR_NULL(mixer_res->mixer))
clk_put(mixer_res->mixer);
return ret; return ret;
} }
static struct mixer_drv_data exynos4_mxr_drv_data = { static struct mixer_drv_data exynos4_mxr_drv_data = {
.version = MXR_VER_0_0_0_16, .version = MXR_VER_0_0_0_16,
.is_vp_enabled = 1,
}; };
static struct platform_device_id mixer_driver_types[] = { static struct platform_device_id mixer_driver_types[] = {
...@@ -1075,14 +1108,26 @@ static int __devinit mixer_probe(struct platform_device *pdev) ...@@ -1075,14 +1108,26 @@ static int __devinit mixer_probe(struct platform_device *pdev)
pdev)->driver_data; pdev)->driver_data;
ctx->dev = &pdev->dev; ctx->dev = &pdev->dev;
drm_hdmi_ctx->ctx = (void *)ctx; drm_hdmi_ctx->ctx = (void *)ctx;
ctx->vp_enabled = drv->is_vp_enabled;
ctx->mxr_ver = drv->version; ctx->mxr_ver = drv->version;
platform_set_drvdata(pdev, drm_hdmi_ctx); platform_set_drvdata(pdev, drm_hdmi_ctx);
/* acquire resources: regs, irqs, clocks */ /* acquire resources: regs, irqs, clocks */
ret = mixer_resources_init(drm_hdmi_ctx, pdev); ret = mixer_resources_init(drm_hdmi_ctx, pdev);
if (ret) if (ret) {
DRM_ERROR("mixer_resources_init failed\n");
goto fail; 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. */ /* register specific callback point to common hdmi. */
exynos_mixer_ops_register(&mixer_ops); exynos_mixer_ops_register(&mixer_ops);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册