aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRahul Sharma <rahul.sharma@samsung.com>2013-05-13 12:59:16 +0530
committerTushar Behera <tushar.behera@linaro.org>2013-05-14 11:01:08 +0530
commit9afff744fadf3c1463bf49e86269c0580f469c02 (patch)
treed31f2e8539247ba46a0ab958252b312daa0fe4eb
parentfa3822f93b42ab0dab8e00fe03ffbff6c5dfd153 (diff)
s5p-tv: add support for dt based exynos5 mixer
Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
-rw-r--r--drivers/media/platform/s5p-tv/mixer.h9
-rw-r--r--drivers/media/platform/s5p-tv/mixer_drv.c178
-rw-r--r--drivers/media/platform/s5p-tv/mixer_reg.c37
-rw-r--r--drivers/media/platform/s5p-tv/regs-mixer.h19
4 files changed, 184 insertions, 59 deletions
diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h
index 7095e0a5fc6..f3912cb34af 100644
--- a/drivers/media/platform/s5p-tv/mixer.h
+++ b/drivers/media/platform/s5p-tv/mixer.h
@@ -232,6 +232,11 @@ enum mxr_devide_flags {
MXR_EVENT_TOP = 1,
};
+enum mixer_version_id {
+ MXR_VER_0_0_0_16,
+ MXR_VER_16_0_33_0,
+};
+
/** drivers instance */
struct mxr_device {
/** master device */
@@ -267,6 +272,10 @@ struct mxr_device {
int current_output;
/** auxiliary resources used my mixer */
struct mxr_resources res;
+ /** is Video Processor is enabled */
+ bool vp_enabled;
+ /** is Video Processor is enabled */
+ enum mixer_version_id mxr_ver;
};
/** transform device structure into mixer device */
diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c
index 202c50066c6..f6a1c76b72e 100644
--- a/drivers/media/platform/s5p-tv/mixer_drv.c
+++ b/drivers/media/platform/s5p-tv/mixer_drv.c
@@ -66,10 +66,12 @@ void mxr_streamer_get(struct mxr_device *mdev)
struct mxr_resources *res = &mdev->res;
int ret;
- if (to_output(mdev)->cookie == 0)
- clk_set_parent(res->sclk_mixer, res->sclk_dac);
- else
- clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
+ if (mdev->vp_enabled) {
+ if (to_output(mdev)->cookie == 0)
+ clk_set_parent(res->sclk_mixer, res->sclk_dac);
+ else
+ clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
+ }
mxr_reg_s_output(mdev, to_output(mdev)->cookie);
ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);
@@ -171,18 +173,20 @@ static int mxr_acquire_plat_resources(struct mxr_device *mdev,
goto fail;
}
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
- if (res == NULL) {
- mxr_err(mdev, "get memory resource failed.\n");
- ret = -ENXIO;
- goto fail_mxr_regs;
- }
-
- mdev->res.vp_regs = ioremap(res->start, resource_size(res));
- if (mdev->res.vp_regs == NULL) {
- mxr_err(mdev, "register mapping failed.\n");
- ret = -ENXIO;
- goto fail_mxr_regs;
+ if (mdev->vp_enabled) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
+ if (res == NULL) {
+ mxr_err(mdev, "get memory resource failed.\n");
+ ret = -ENXIO;
+ goto fail_mxr_regs;
+ }
+
+ mdev->res.vp_regs = ioremap(res->start, resource_size(res));
+ if (mdev->res.vp_regs == NULL) {
+ mxr_err(mdev, "register mapping failed.\n");
+ ret = -ENXIO;
+ goto fail_mxr_regs;
+ }
}
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
@@ -202,7 +206,8 @@ static int mxr_acquire_plat_resources(struct mxr_device *mdev,
return 0;
fail_vp_regs:
- iounmap(mdev->res.vp_regs);
+ if (mdev->vp_enabled)
+ iounmap(mdev->res.vp_regs);
fail_mxr_regs:
iounmap(mdev->res.mxr_regs);
@@ -214,7 +219,8 @@ fail:
static void mxr_release_plat_resources(struct mxr_device *mdev)
{
free_irq(mdev->res.irq, mdev);
- iounmap(mdev->res.vp_regs);
+ if (mdev->vp_enabled)
+ iounmap(mdev->res.vp_regs);
iounmap(mdev->res.mxr_regs);
}
@@ -222,14 +228,16 @@ static void mxr_release_clocks(struct mxr_device *mdev)
{
struct mxr_resources *res = &mdev->res;
- if (!IS_ERR_OR_NULL(res->sclk_dac))
- clk_put(res->sclk_dac);
if (!IS_ERR_OR_NULL(res->sclk_hdmi))
clk_put(res->sclk_hdmi);
- if (!IS_ERR_OR_NULL(res->sclk_mixer))
- clk_put(res->sclk_mixer);
- if (!IS_ERR_OR_NULL(res->vp))
- clk_put(res->vp);
+ if (mdev->vp_enabled) {
+ if (!IS_ERR_OR_NULL(res->sclk_dac))
+ clk_put(res->sclk_dac);
+ if (!IS_ERR_OR_NULL(res->sclk_mixer))
+ clk_put(res->sclk_mixer);
+ if (!IS_ERR_OR_NULL(res->vp))
+ clk_put(res->vp);
+ }
if (!IS_ERR_OR_NULL(res->mixer))
clk_put(res->mixer);
}
@@ -244,26 +252,28 @@ static int mxr_acquire_clocks(struct mxr_device *mdev)
mxr_err(mdev, "failed to get clock 'mixer'\n");
goto fail;
}
- res->vp = clk_get(dev, "vp");
- if (IS_ERR(res->vp)) {
- mxr_err(mdev, "failed to get clock 'vp'\n");
- goto fail;
- }
- res->sclk_mixer = clk_get(dev, "sclk_mixer");
- if (IS_ERR(res->sclk_mixer)) {
- mxr_err(mdev, "failed to get clock 'sclk_mixer'\n");
- goto fail;
+ if (mdev->vp_enabled) {
+ res->vp = clk_get(dev, "vp");
+ if (IS_ERR(res->vp)) {
+ mxr_err(mdev, "failed to get clock 'vp'\n");
+ goto fail;
+ }
+ res->sclk_mixer = clk_get(dev, "sclk_mixer");
+ if (IS_ERR(res->sclk_mixer)) {
+ mxr_err(mdev, "failed to get clock 'sclk_mixer'\n");
+ goto fail;
+ }
+ res->sclk_dac = clk_get(dev, "sclk_dac");
+ if (IS_ERR(res->sclk_dac)) {
+ mxr_err(mdev, "failed to get clock 'sclk_dac'\n");
+ goto fail;
+ }
}
res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
if (IS_ERR(res->sclk_hdmi)) {
mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n");
goto fail;
}
- res->sclk_dac = clk_get(dev, "sclk_dac");
- if (IS_ERR(res->sclk_dac)) {
- mxr_err(mdev, "failed to get clock 'sclk_dac'\n");
- goto fail;
- }
return 0;
fail:
@@ -315,12 +325,18 @@ static int mxr_acquire_layers(struct mxr_device *mdev,
{
mdev->layer[0] = mxr_graph_layer_create(mdev, 0);
mdev->layer[1] = mxr_graph_layer_create(mdev, 1);
- mdev->layer[2] = mxr_vp_layer_create(mdev, 0);
- if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) {
+ if (mdev->vp_enabled)
+ mdev->layer[2] = mxr_vp_layer_create(mdev, 0);
+
+ if (!mdev->layer[0] || !mdev->layer[1]) {
mxr_err(mdev, "failed to acquire layers\n");
goto fail;
}
+ if (mdev->vp_enabled && !mdev->layer[2]) {
+ mxr_err(mdev, "failed to acquire vp layer\n");
+ goto fail;
+ }
return 0;
@@ -340,8 +356,10 @@ static int mxr_runtime_resume(struct device *dev)
mutex_lock(&mdev->mutex);
/* turn clocks on */
clk_enable(res->mixer);
- clk_enable(res->vp);
- clk_enable(res->sclk_mixer);
+ if (mdev->vp_enabled) {
+ clk_enable(res->vp);
+ clk_enable(res->sclk_mixer);
+ }
/* apply default configuration */
mxr_reg_reset(mdev);
mxr_dbg(mdev, "resume - finished\n");
@@ -357,8 +375,10 @@ static int mxr_runtime_suspend(struct device *dev)
mxr_dbg(mdev, "suspend - start\n");
mutex_lock(&mdev->mutex);
/* turn clocks off */
- clk_disable(res->sclk_mixer);
- clk_disable(res->vp);
+ if (mdev->vp_enabled) {
+ clk_disable(res->sclk_mixer);
+ clk_disable(res->vp);
+ }
clk_disable(res->mixer);
mutex_unlock(&mdev->mutex);
mxr_dbg(mdev, "suspend - finished\n");
@@ -372,11 +392,59 @@ static const struct dev_pm_ops mxr_pm_ops = {
/* --------- DRIVER INITIALIZATION ---------- */
+struct mixer_drv_data {
+ enum mixer_version_id version;
+ bool is_vp_enabled;
+};
+
+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,
+};
+
+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 */
+ }
+};
+
+#ifdef CONFIG_OF
+
+static struct of_device_id mxr_dt_match[] = {
+ {
+ .compatible = "samsung,s5pv210-tvmixer",
+ .data = &exynos4_mxr_drv_data,
+ }, {
+ .compatible = "samsung,exynos4-mixer",
+ .data = &exynos4_mxr_drv_data,
+ }, {
+ .compatible = "samsung,exynos5-mixer",
+ .data = &exynos5_mxr_drv_data,
+ }, {
+ /* end node */
+ }
+};
+
+MODULE_DEVICE_TABLE(of, mxr_dt_match);
+#endif
+
static int mxr_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mxr_platform_data *pdata = dev->platform_data;
struct mxr_device *mdev;
+ struct mixer_drv_data *drv = NULL;
int ret;
/* mdev does not exist yet so no mxr_dbg is used */
@@ -389,8 +457,21 @@ static int mxr_probe(struct platform_device *pdev)
goto fail;
}
+ if (dev->of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(of_match_ptr(mxr_dt_match),
+ pdev->dev.of_node);
+
+ drv = (struct mixer_drv_data *)match->data;
+ } else {
+ drv = (struct mixer_drv_data *)
+ platform_get_device_id(pdev)->driver_data;
+ }
+
/* setup pointer to master device */
mdev->dev = dev;
+ mdev->vp_enabled = drv->is_vp_enabled;
+ mdev->mxr_ver = drv->version;
mutex_init(&mdev->mutex);
spin_lock_init(&mdev->reg_slock);
@@ -448,17 +529,10 @@ static int mxr_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_OF
-static const struct of_device_id mxr_dt_match[] = {
- { .compatible = "samsung,s5pv210-tvmixer" },
- { },
-};
-MODULE_DEVICE_TABLE(of, mxr_dt_match);
-#endif
-
static struct platform_driver mxr_driver __refdata = {
.probe = mxr_probe,
.remove = mxr_remove,
+ .id_table = mixer_driver_types,
.driver = {
.name = MXR_DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/media/platform/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c
index b713403024e..56d9b45c3ab 100644
--- a/drivers/media/platform/s5p-tv/mixer_reg.c
+++ b/drivers/media/platform/s5p-tv/mixer_reg.c
@@ -57,12 +57,25 @@ static inline void mxr_write_mask(struct mxr_device *mdev, u32 reg_id,
writel(val, mdev->res.mxr_regs + reg_id);
}
+static void mxr_reg_layer_update(struct mxr_device *mdev)
+{
+ u32 val;
+
+ val = mxr_read(mdev, MXR_CFG);
+
+ /* allow one update per vsync only */
+ if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
+ mxr_write_mask(mdev, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
+}
+
void mxr_vsync_set_update(struct mxr_device *mdev, int en)
{
/* block update on vsync */
mxr_write_mask(mdev, MXR_STATUS, en ? MXR_STATUS_SYNC_ENABLE : 0,
MXR_STATUS_SYNC_ENABLE);
- vp_write(mdev, VP_SHADOW_UPDATE, en ? VP_SHADOW_UPDATE_ENABLE : 0);
+ if (mdev->vp_enabled)
+ vp_write(mdev, VP_SHADOW_UPDATE,
+ en ? VP_SHADOW_UPDATE_ENABLE : 0);
}
static void __mxr_reg_vp_reset(struct mxr_device *mdev)
@@ -103,8 +116,9 @@ void mxr_reg_reset(struct mxr_device *mdev)
* layer1 - OSD
*/
val = MXR_LAYER_CFG_GRP0_VAL(1);
- val |= MXR_LAYER_CFG_VP_VAL(2);
val |= MXR_LAYER_CFG_GRP1_VAL(3);
+ if (mdev->vp_enabled)
+ val |= MXR_LAYER_CFG_VP_VAL(2);
mxr_write(mdev, MXR_LAYER_CFG, val);
/* use dark gray background color */
@@ -123,8 +137,10 @@ void mxr_reg_reset(struct mxr_device *mdev)
mxr_write(mdev, MXR_GRAPHIC_CFG(1), val);
/* configuration of Video Processor Registers */
- __mxr_reg_vp_reset(mdev);
- mxr_reg_vp_default_filter(mdev);
+ if (mdev->vp_enabled) {
+ __mxr_reg_vp_reset(mdev);
+ mxr_reg_vp_default_filter(mdev);
+ }
/* enable all interrupts */
mxr_write_mask(mdev, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
@@ -225,6 +241,9 @@ void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr)
mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
mxr_write(mdev, MXR_GRAPHIC_BASE(idx), addr);
+ if (mdev->mxr_ver == MXR_VER_16_0_33_0)
+ mxr_reg_layer_update(mdev);
+
mxr_vsync_set_update(mdev, MXR_ENABLE);
spin_unlock_irqrestore(&mdev->reg_slock, flags);
}
@@ -409,8 +428,11 @@ void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
MXR_CFG_OUT_MASK);
val = (fmt->field == V4L2_FIELD_INTERLACED) ? ~0 : 0;
- vp_write_mask(mdev, VP_MODE, val,
- VP_MODE_LINE_SKIP | VP_MODE_FIELD_ID_AUTO_TOGGLING);
+
+ if (mdev->vp_enabled) {
+ vp_write_mask(mdev, VP_MODE, val,
+ VP_MODE_LINE_SKIP | VP_MODE_FIELD_ID_AUTO_TOGGLING);
+ }
mxr_vsync_set_update(mdev, MXR_ENABLE);
spin_unlock_irqrestore(&mdev->reg_slock, flags);
@@ -548,6 +570,7 @@ do { \
void mxr_reg_dump(struct mxr_device *mdev)
{
mxr_reg_mxr_dump(mdev);
- mxr_reg_vp_dump(mdev);
+ if (mdev->vp_enabled)
+ mxr_reg_vp_dump(mdev);
}
diff --git a/drivers/media/platform/s5p-tv/regs-mixer.h b/drivers/media/platform/s5p-tv/regs-mixer.h
index 158abb43d0a..b64ec73149c 100644
--- a/drivers/media/platform/s5p-tv/regs-mixer.h
+++ b/drivers/media/platform/s5p-tv/regs-mixer.h
@@ -38,6 +38,11 @@
#define MXR_BG_COLOR0 0x0064
#define MXR_BG_COLOR1 0x0068
#define MXR_BG_COLOR2 0x006C
+#define MXR_CM_COEFF_Y 0x0080
+#define MXR_CM_COEFF_CB 0x0084
+#define MXR_CM_COEFF_CR 0x0088
+#define MXR_GRAPHIC0_BASE_S 0x2024
+#define MXR_GRAPHIC1_BASE_S 0x2044
/* for parametrized access to layer registers */
#define MXR_GRAPHIC_CFG(i) (0x0020 + (i) * 0x20)
@@ -46,6 +51,8 @@
#define MXR_GRAPHIC_SXY(i) (0x002C + (i) * 0x20)
#define MXR_GRAPHIC_WH(i) (0x0030 + (i) * 0x20)
#define MXR_GRAPHIC_DXY(i) (0x0034 + (i) * 0x20)
+#define MXR_GRAPHIC_BLANK(i) (0x0038 + (i) * 0x20)
+#define MXR_GRAPHIC_BASE_S(i) (0x2024 + (i) * 0x20)
/*
* Bit definition part
@@ -59,12 +66,22 @@
(((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)
+#define MXR_STATUS_ENDIAN_MASK (1 << 3)
#define MXR_STATUS_SYNC_ENABLE (1 << 2)
#define MXR_STATUS_REG_RUN (1 << 0)
/* bits for MXR_CFG */
+#define MXR_CFG_LAYER_UPDATE (1 << 31)
+#define MXR_CFG_LAYER_UPDATE_COUNT_MASK (3 << 29)
+#define MXR_CFG_RGB601_0_255 (0 << 9)
+#define MXR_CFG_RGB601_16_235 (1 << 9)
+#define MXR_CFG_RGB709_0_255 (2 << 9)
+#define MXR_CFG_RGB709_16_235 (3 << 9)
+#define MXR_CFG_RGB_FMT_MASK 0x600
#define MXR_CFG_OUT_YUV444 (0 << 8)
#define MXR_CFG_OUT_RGB888 (1 << 8)
#define MXR_CFG_OUT_MASK (1 << 8)
@@ -87,6 +104,8 @@
/* bits for MXR_GRAPHICn_CFG */
#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21)
#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20)
+#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17)
+#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16)
#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8)
#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0)
#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0)