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 <carlv@codeaurora.org>
This commit is contained in:
Carl Vanderlip 2012-07-23 12:34:47 -07:00 committed by Stephen Boyd
parent 90bf348a06
commit a2f86cc692
4 changed files with 103 additions and 49 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;