From a2f86cc69270beea22205966b463220d6abaf5e2 Mon Sep 17 00:00:00 2001 From: Carl Vanderlip Date: Mon, 23 Jul 2012 12:34:47 -0700 Subject: [PATCH] video: msm: Add CSC and QSEED support to Overlay API Add support for CSC and QSEED configuration through MSMFB_OVERLAY_SET and MSMFB_OVERLAY_PLAY ioctls. Provide better integration than previous attempt with the existing Overlay and PostProcessing APIs. CRs-Fixed: 380750 Change-Id: If895391074ef1e7d7a6824d289e1ed9da6a52180 Signed-off-by: Carl Vanderlip --- drivers/video/msm/mdp4.h | 4 ++ drivers/video/msm/mdp4_overlay.c | 29 ++++++++++++ drivers/video/msm/mdp4_util.c | 44 +++++++++++-------- include/linux/msm_mdp.h | 75 +++++++++++++++++++------------- 4 files changed, 103 insertions(+), 49 deletions(-) diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h index 247bb485694d..9482bf760907 100644 --- a/drivers/video/msm/mdp4.h +++ b/drivers/video/msm/mdp4.h @@ -34,6 +34,7 @@ extern spinlock_t dsi_clk_lock; #define MDP4_VIDEO_BASE 0x20000 #define MDP4_VIDEO_OFF 0x10000 +#define MDP4_VIDEO_CSC_OFF 0x4000 #define MDP4_RGB_BASE 0x40000 #define MDP4_RGB_OFF 0x10000 @@ -219,6 +220,7 @@ enum { #define MDP4_OP_FLIP_UD BIT(14) #define MDP4_OP_FLIP_LR BIT(13) #define MDP4_OP_CSC_EN BIT(11) +#define MDP4_OP_DST_DATA_YCBCR BIT(10) #define MDP4_OP_SRC_DATA_YCBCR BIT(9) #define MDP4_OP_SCALEY_FIR (0 << 4) #define MDP4_OP_SCALEY_MN_PHASE (1 << 4) @@ -348,6 +350,7 @@ struct mdp4_overlay_pipe { uint32 dmae_cnt; uint32 blt_end; uint32 luma_align_size; + struct mdp_overlay_pp_params pp_cfg; struct completion dmas_comp; struct mdp_overlay req_data; }; @@ -814,6 +817,7 @@ int mdp4_csc_enable(struct mdp_csc_cfg_data *config); int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr); int mdp4_argc_cfg(struct mdp_pgc_lut_data *pgc_ptr); int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg); +int mdp4_qseed_access_cfg(struct mdp_qseed_cfg *cfg, uint32_t base); u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num); void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num); void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num); diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c index 90020da7292a..096fdeb2c9ad 100644 --- a/drivers/video/msm/mdp4_overlay.c +++ b/drivers/video/msm/mdp4_overlay.c @@ -701,6 +701,26 @@ void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe) format = mdp4_overlay_format(pipe); pattern = mdp4_overlay_unpack_pattern(pipe); + /* CSC Post Processing enabled? */ + if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) { + if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_CSC_CFG) { + if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_ENABLE) + pipe->op_mode |= MDP4_OP_CSC_EN; + if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_YUV_IN) + pipe->op_mode |= MDP4_OP_SRC_DATA_YCBCR; + if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_YUV_OUT) + pipe->op_mode |= MDP4_OP_DST_DATA_YCBCR; + + mdp4_csc_write(&pipe->pp_cfg.csc_cfg, + (uint32_t) (vg_base + MDP4_VIDEO_CSC_OFF)); + } + if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_QSEED_CFG) { + mdp4_qseed_access_cfg(&pipe->pp_cfg.qseed_cfg[0], + (uint32_t) vg_base); + mdp4_qseed_access_cfg(&pipe->pp_cfg.qseed_cfg[1], + (uint32_t) vg_base); + } + } /* not RGB use VG pipe, pure VG pipe */ if (ptype != OVERLAY_TYPE_RGB) pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR); @@ -2687,6 +2707,15 @@ int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req) mdp4_stat.overlay_set[pipe->mixer_num]++; + if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) { + if (pipe->pipe_num <= OVERLAY_PIPE_VG2) + memcpy(&pipe->pp_cfg, &req->overlay_pp_cfg, + sizeof(struct mdp_overlay_pp_params)); + else + pr_debug("%s: RGB Pipes don't support CSC/QSEED\n", + __func__); + } + if (ctrl->panel_mode & MDP4_PANEL_DTV && pipe->mixer_num == MDP4_MIXER1) { u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level); diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c index 645d5a85f85e..adf3bb9972ea 100644 --- a/drivers/video/msm/mdp4_util.c +++ b/drivers/video/msm/mdp4_util.c @@ -3276,56 +3276,60 @@ static uint32_t mdp4_pp_block2qseed(uint32_t block) return valid; } -static int mdp4_qseed_access_cfg(struct mdp_qseed_cfg_data *cfg) +int mdp4_qseed_access_cfg(struct mdp_qseed_cfg *config, uint32_t base) { int i, ret = 0; - uint32_t base = (uint32_t) (MDP_BASE + mdp_block2base(cfg->block)); uint32_t *values; - if ((cfg->table_num != 1) && (cfg->table_num != 2)) { + if ((config->table_num != 1) && (config->table_num != 2)) { ret = -ENOTTY; goto error; } - if (((cfg->table_num == 1) && (cfg->len != QSEED_TABLE_1_COUNT)) || - ((cfg->table_num == 2) && (cfg->len != QSEED_TABLE_2_COUNT))) { + if (((config->table_num == 1) && (config->len != QSEED_TABLE_1_COUNT)) + || ((config->table_num == 2) && + (config->len != QSEED_TABLE_2_COUNT))) { ret = -EINVAL; goto error; } - values = kmalloc(cfg->len * sizeof(uint32_t), GFP_KERNEL); + values = kmalloc(config->len * sizeof(uint32_t), GFP_KERNEL); if (!values) { ret = -ENOMEM; goto error; } - base += (cfg->table_num == 1) ? MDP4_QSEED_TABLE1_OFF : + base += (config->table_num == 1) ? MDP4_QSEED_TABLE1_OFF : MDP4_QSEED_TABLE2_OFF; - if (cfg->ops & MDP_PP_OPS_WRITE) { - ret = copy_from_user(values, cfg->data, - sizeof(uint32_t) * cfg->len); + if (config->ops & MDP_PP_OPS_WRITE) { + ret = copy_from_user(values, config->data, + sizeof(uint32_t) * config->len); if (ret) { pr_warn("%s: Error copying from user, %d", __func__, ret); ret = -EINVAL; goto err_mem; } - for (i = 0; i < cfg->len; i++) { + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + for (i = 0; i < config->len; i++) { if (!(base & 0x3FF)) wmb(); MDP_OUTP(base , values[i]); base += sizeof(uint32_t); } - } else if (cfg->ops & MDP_PP_OPS_READ) { - for (i = 0; i < cfg->len; i++) { + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + } else if (config->ops & MDP_PP_OPS_READ) { + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + for (i = 0; i < config->len; i++) { values[i] = inpdw(base); if (!(base & 0x3FF)) rmb(); base += sizeof(uint32_t); } - ret = copy_to_user(cfg->data, values, - sizeof(uint32_t) * cfg->len); + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + ret = copy_to_user(config->data, values, + sizeof(uint32_t) * config->len); if (ret) { pr_warn("%s: Error copying to user, %d", __func__, ret); ret = -EINVAL; @@ -3339,11 +3343,13 @@ error: return ret; } -int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg) +int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *config) { int ret = 0; + struct mdp_qseed_cfg *cfg = &config->qseed_data; + uint32_t base; - if (!mdp4_pp_block2qseed(cfg->block)) { + if (!mdp4_pp_block2qseed(config->block)) { ret = -ENOTTY; goto error; } @@ -3354,8 +3360,8 @@ int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg) __func__); goto error; } - - ret = mdp4_qseed_access_cfg(cfg); + base = (uint32_t) (MDP_BASE + mdp_block2base(config->block)); + ret = mdp4_qseed_access_cfg(cfg, base); error: return ret; diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h index 9940d4e5902d..4850492fad30 100644 --- a/include/linux/msm_mdp.h +++ b/include/linux/msm_mdp.h @@ -148,6 +148,7 @@ enum { #define MDP_DEINTERLACE_ODD 0x00400000 #define MDP_OV_PLAY_NOWAIT 0x00200000 #define MDP_SOURCE_ROTATED_90 0x00100000 +#define MDP_OVERLAY_PP_CFG_EN 0x00080000 #define MDP_BACKEND_COMPOSITION 0x00040000 #define MDP_BORDERFILL_SUPPORTED 0x00010000 #define MDP_SECURE_OVERLAY_SESSION 0x00008000 @@ -264,6 +265,49 @@ struct msmfb_writeback_data { struct msmfb_img img; }; +#define MDP_PP_OPS_READ 0x2 +#define MDP_PP_OPS_WRITE 0x4 + +struct mdp_qseed_cfg { + uint32_t table_num; + uint32_t ops; + uint32_t len; + uint32_t *data; +}; + +struct mdp_qseed_cfg_data { + uint32_t block; + struct mdp_qseed_cfg qseed_data; +}; + +#define MDP_OVERLAY_PP_CSC_CFG 0x1 +#define MDP_OVERLAY_PP_QSEED_CFG 0x2 + +#define MDP_CSC_FLAG_ENABLE 0x1 +#define MDP_CSC_FLAG_YUV_IN 0x2 +#define MDP_CSC_FLAG_YUV_OUT 0x4 + +struct mdp_csc_cfg { + /* flags for enable CSC, toggling RGB,YUV input/output */ + uint32_t flags; + uint32_t csc_mv[9]; + uint32_t csc_pre_bv[3]; + uint32_t csc_post_bv[3]; + uint32_t csc_pre_lv[6]; + uint32_t csc_post_lv[6]; +}; + +struct mdp_csc_cfg_data { + uint32_t block; + struct mdp_csc_cfg csc_data; +}; + +struct mdp_overlay_pp_params { + uint32_t config_ops; + struct mdp_csc_cfg csc_cfg; + struct mdp_qseed_cfg qseed_cfg[2]; +}; + struct mdp_overlay { struct msmfb_img src; struct mdp_rect src_rect; @@ -275,6 +319,7 @@ struct mdp_overlay { uint32_t flags; uint32_t id; uint32_t user_data[8]; + struct mdp_overlay_pp_params overlay_pp_cfg; }; struct msmfb_overlay_3d { @@ -362,28 +407,6 @@ struct mdp_pcc_cfg_data { struct mdp_pcc_coeff r, g, b; }; -#define MDP_CSC_FLAG_ENABLE 0x1 -#define MDP_CSC_FLAG_YUV_IN 0x2 -#define MDP_CSC_FLAG_YUV_OUT 0x4 - -struct mdp_csc_cfg { - /* flags for enable CSC, toggling RGB,YUV input/output */ - uint32_t flags; - uint32_t csc_mv[9]; - uint32_t csc_pre_bv[3]; - uint32_t csc_post_bv[3]; - uint32_t csc_pre_lv[6]; - uint32_t csc_post_lv[6]; -}; - -struct mdp_csc_cfg_data { - uint32_t block; - struct mdp_csc_cfg csc_data; -}; - -#define MDP_PP_OPS_READ 0x2 -#define MDP_PP_OPS_WRITE 0x4 - enum { mdp_lut_igc, mdp_lut_pgc, @@ -432,14 +455,6 @@ struct mdp_lut_cfg_data { } data; }; -struct mdp_qseed_cfg_data { - uint32_t block; - uint32_t table_num; - uint32_t ops; - uint32_t len; - uint32_t *data; -}; - struct mdp_bl_scale_data { uint32_t min_lvl; uint32_t scale;