Skip to content

Commit

Permalink
drm: exynos: hdmi: add support to disable video processor in mixer
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
  • Loading branch information
Rahul Sharma authored and Inki Dae committed Oct 5, 2012
1 parent 1e12344 commit 1b8e574
Showing 1 changed file with 98 additions and 53 deletions.
151 changes: 98 additions & 53 deletions drivers/gpu/drm/exynos/exynos_mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct mixer_context {
int pipe;
bool interlace;
bool powered;
bool vp_enabled;
u32 int_en;

struct mutex mixer_mutex;
Expand All @@ -93,6 +94,7 @@ struct mixer_context {

struct mixer_drv_data {
enum mixer_version_id version;
bool is_vp_enabled;
};

static const u8 filter_y_horiz_tap8[] = {
Expand Down Expand Up @@ -261,7 +263,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);
}

Expand Down Expand Up @@ -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);
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;
}
}
Expand Down Expand Up @@ -602,7 +608,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 */
Expand All @@ -625,14 +632,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);
Expand All @@ -655,8 +665,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);
Expand All @@ -676,8 +688,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);

Expand Down Expand Up @@ -810,7 +824,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);
Expand Down Expand Up @@ -946,39 +960,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) {
Expand All @@ -987,54 +982,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[] = {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 1b8e574

Please sign in to comment.