summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPing Li <pingli@codeaurora.org>2014-12-30 17:16:53 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:37:20 -0700
commitc29be55aa3ae563d64890596b38b276c208bfe10 (patch)
tree9bea859a2b8b7df95d29548f7820b1d9d571d778
parent5a4feccb481a065d8c36924d82e0902f96bb4115 (diff)
msm: mdss: Add SSPP histogram support on thulium
Histogram support is added back on source surface processing pipes on thulium. This change adds the support for driver side support to enable histogram on VIG pipes. Change-Id: I7d480a22de3bbbc11ebcd85b7e725f0404077350 Signed-off-by: Ping Li <pingli@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c127
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c53
3 files changed, 147 insertions, 36 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index e846cdf622e1..07e132100a55 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -1503,7 +1503,8 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix)
goto error;
}
kick_base = MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
- } else if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG && is_hist_v1) {
+ } else if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG &&
+ (is_hist_v1 || pp_driver_ops.get_hist_offset)) {
pipe = mdss_mdp_pipe_get(mdata, BIT(PP_BLOCK(block)));
if (IS_ERR_OR_NULL(pipe)) {
pr_debug("pipe DNE (%d)\n",
@@ -1512,7 +1513,10 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix)
goto error;
}
/* HIST_EN & AUTO_CLEAR */
- op_flags = BIT(8) + BIT(9);
+ if (is_hist_v1)
+ op_flags = BIT(8) + BIT(9);
+ else
+ op_flags = BIT(8);
hist_info = &pipe->pp_res.hist;
base = pipe->base;
kick_base = MDSS_MDP_REG_VIG_HIST_CTL_BASE;
@@ -2241,6 +2245,7 @@ int mdss_mdp_pp_init(struct device *dev)
struct mdss_mdp_pipe *vig;
struct pp_hist_col_info *hist;
void *ret_ptr = NULL;
+ u32 ctl_off = 0;
if (!mdata)
return -EPERM;
@@ -2256,6 +2261,17 @@ int mdss_mdp_pp_init(struct device *dev)
if (mdss_mdp_pp_dt_parse(dev))
pr_info("No PP info in device tree\n");
+ ret_ptr = pp_get_driver_ops(&pp_driver_ops);
+ if (IS_ERR(ret_ptr)) {
+ pr_err("pp_get_driver_ops failed, ret=%d\n",
+ (int) PTR_ERR(ret_ptr));
+ ret = PTR_ERR(ret_ptr);
+ goto pp_exit;
+ } else {
+ mdss_pp_res->pp_data_res = ret_ptr;
+ pp_ops = pp_driver_ops.pp_ops;
+ }
+
hist = devm_kzalloc(dev,
sizeof(struct pp_hist_col_info) *
mdata->ndspp,
@@ -2263,33 +2279,37 @@ int mdss_mdp_pp_init(struct device *dev)
if (hist == NULL) {
pr_err("dspp histogram allocation failed!\n");
ret = -ENOMEM;
- devm_kfree(dev, mdss_pp_res);
- } else {
- for (i = 0; i < mdata->ndspp; i++) {
- mutex_init(&hist[i].hist_mutex);
- spin_lock_init(&hist[i].hist_lock);
- hist[i].intr_shift = (i * 4) + 12;
+ goto pp_exit;
+ }
+ for (i = 0; i < mdata->ndspp; i++) {
+ mutex_init(&hist[i].hist_mutex);
+ spin_lock_init(&hist[i].hist_lock);
+ hist[i].intr_shift = (i * 4) + 12;
+ if (pp_driver_ops.get_hist_offset) {
+ ret = pp_driver_ops.get_hist_offset(
+ DSPP, &ctl_off);
+ if (ret) {
+ pr_err("get_hist_offset ret %d\n",
+ ret);
+ goto hist_exit;
+ }
+ hist[i].base =
+ i < mdata->ndspp ?
+ mdss_mdp_get_dspp_addr_off(i) +
+ ctl_off : NULL;
+ } else {
hist[i].base = i < mdata->ndspp ?
mdss_mdp_get_dspp_addr_off(i) +
MDSS_MDP_REG_DSPP_HIST_CTL_BASE
: NULL;
- init_completion(&hist[i].comp);
- init_completion(&hist[i].first_kick);
}
- if (mdata->ndspp == 4)
- hist[3].intr_shift = 22;
-
- mdss_pp_res->dspp_hist = hist;
- }
- ret_ptr = pp_get_driver_ops(&pp_driver_ops);
- if (IS_ERR(ret_ptr)) {
- pr_err("pp_get_driver_ops failed, ret=%d\n",
- (int) PTR_ERR(ret_ptr));
- ret = PTR_ERR(ret_ptr);
- } else {
- mdss_pp_res->pp_data_res = ret_ptr;
- pp_ops = pp_driver_ops.pp_ops;
+ init_completion(&hist[i].comp);
+ init_completion(&hist[i].first_kick);
}
+ if (mdata->ndspp == 4)
+ hist[3].intr_shift = 22;
+
+ mdss_pp_res->dspp_hist = hist;
}
}
if (mdata && mdata->vig_pipes) {
@@ -2298,14 +2318,34 @@ int mdss_mdp_pp_init(struct device *dev)
mutex_init(&vig[i].pp_res.hist.hist_mutex);
spin_lock_init(&vig[i].pp_res.hist.hist_lock);
vig[i].pp_res.hist.intr_shift = (vig[i].num * 4);
- vig[i].pp_res.hist.base = vig[i].base +
- MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ if (i == 3)
+ vig[i].pp_res.hist.intr_shift = 10;
+ if (pp_driver_ops.get_hist_offset) {
+ ret = pp_driver_ops.get_hist_offset(
+ DSPP, &ctl_off);
+ if (ret) {
+ pr_err("get_hist_offset ret %d\n",
+ ret);
+ goto hist_exit;
+ }
+ vig[i].pp_res.hist.base = vig[i].base +
+ ctl_off;
+ } else {
+ vig[i].pp_res.hist.base = vig[i].base +
+ MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ }
init_completion(&vig[i].pp_res.hist.comp);
init_completion(&vig[i].pp_res.hist.first_kick);
}
}
mutex_unlock(&mdss_pp_mutex);
return ret;
+hist_exit:
+ devm_kfree(dev, hist);
+pp_exit:
+ devm_kfree(dev, mdss_pp_res);
+ mutex_unlock(&mdss_pp_mutex);
+ return ret;
}
void mdss_mdp_pp_term(struct device *dev)
@@ -3846,12 +3886,18 @@ int mdss_mdp_hist_start(struct mdp_histogram_start_req *req)
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_ctl *ctl;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- bool is_hist_v2 = mdata->mdp_rev >= MDSS_MDP_HW_REV_103;
+ bool sspp_hist_supp;
if (!mdss_is_ready())
return -EPROBE_DEFER;
- if (is_hist_v2 && (PP_LOCAT(req->block) == MDSS_PP_SSPP_CFG)) {
+ if (pp_driver_ops.is_sspp_hist_supp)
+ sspp_hist_supp = pp_driver_ops.is_sspp_hist_supp();
+ else
+ sspp_hist_supp = (mdata->mdp_rev < MDSS_MDP_HW_REV_103);
+
+ if (!sspp_hist_supp &&
+ (PP_LOCAT(req->block) == MDSS_PP_SSPP_CFG)) {
pr_warn("No histogram on SSPP\n");
ret = -EINVAL;
goto hist_exit;
@@ -3873,7 +3919,8 @@ int mdss_mdp_hist_start(struct mdp_histogram_start_req *req)
pipe = mdss_mdp_pipe_get(mdata, BIT(i));
if (IS_ERR_OR_NULL(pipe))
continue;
- if (pipe->num > MDSS_MDP_SSPP_VIG2) {
+ if ((pipe->num > MDSS_MDP_SSPP_VIG2) &&
+ (pipe->num != MDSS_MDP_SSPP_VIG3)) {
ret = -EINVAL;
pr_warn("Invalid Hist pipe (%d)\n", i);
mdss_mdp_pipe_unmap(pipe);
@@ -3996,9 +4043,11 @@ int mdss_mdp_hist_stop(u32 block)
if (IS_ERR_OR_NULL(pipe)) {
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
- } else if (pipe->num > MDSS_MDP_SSPP_VIG2) {
+ } else if ((pipe->num > MDSS_MDP_SSPP_VIG2) &&
+ (pipe->num != MDSS_MDP_SSPP_VIG3)) {
mdss_mdp_pipe_unmap(pipe);
- pr_warn("Invalid Hist pipe (%d)\n", i);
+ pr_warn("Invalid Hist pipe (%d) pipe->num (%d)\n",
+ i, pipe->num);
continue;
}
hist_info = &pipe->pp_res.hist;
@@ -4453,7 +4502,8 @@ int mdss_mdp_hist_collect(struct mdp_histogram_data *hist)
if (IS_ERR_OR_NULL(pipe)) {
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
- } else if (pipe->num > MDSS_MDP_SSPP_VIG2) {
+ } else if ((pipe->num > MDSS_MDP_SSPP_VIG2) &&
+ (pipe->num != MDSS_MDP_SSPP_VIG3)) {
mdss_mdp_pipe_unmap(pipe);
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
@@ -4472,7 +4522,8 @@ int mdss_mdp_hist_collect(struct mdp_histogram_data *hist)
if (IS_ERR_OR_NULL(pipe)) {
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
- } else if (pipe->num > MDSS_MDP_SSPP_VIG2) {
+ } else if ((pipe->num > MDSS_MDP_SSPP_VIG2) &&
+ (pipe->num != MDSS_MDP_SSPP_VIG3)) {
mdss_mdp_pipe_unmap(pipe);
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
@@ -4497,7 +4548,8 @@ int mdss_mdp_hist_collect(struct mdp_histogram_data *hist)
if (IS_ERR_OR_NULL(pipe)) {
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
- } else if (pipe->num > MDSS_MDP_SSPP_VIG2) {
+ } else if ((pipe->num > MDSS_MDP_SSPP_VIG2) &&
+ (pipe->num != MDSS_MDP_SSPP_VIG3)) {
mdss_mdp_pipe_unmap(pipe);
pr_warn("Invalid Hist pipe (%d)\n", i);
continue;
@@ -4603,10 +4655,15 @@ static inline struct pp_hist_col_info *get_hist_info_from_isr(u32 *isr)
blk_idx = MDSS_MDP_SSPP_VIG1;
*isr &= ~(MDSS_MDP_HIST_INTR_VIG_1_DONE |
MDSS_MDP_HIST_INTR_VIG_1_RESET_DONE);
- } else {
+ } else if (*isr & (MDSS_MDP_HIST_INTR_VIG_2_DONE |
+ MDSS_MDP_HIST_INTR_VIG_2_RESET_DONE)) {
blk_idx = MDSS_MDP_SSPP_VIG2;
*isr &= ~(MDSS_MDP_HIST_INTR_VIG_2_DONE |
MDSS_MDP_HIST_INTR_VIG_2_RESET_DONE);
+ } else {
+ blk_idx = MDSS_MDP_SSPP_VIG3;
+ *isr &= ~(MDSS_MDP_HIST_INTR_VIG_3_DONE |
+ MDSS_MDP_HIST_INTR_VIG_3_RESET_DONE);
}
pipe = mdss_mdp_pipe_search(mdata, BIT(blk_idx));
if (IS_ERR_OR_NULL(pipe)) {
@@ -4637,6 +4694,8 @@ void mdss_mdp_hist_intr_done(u32 isr)
bool need_complete = false;
u32 isr_mask = (is_hist_v2) ? HIST_V2_INTR_BIT_MASK :
HIST_V1_INTR_BIT_MASK;
+ if (pp_driver_ops.get_hist_isr_info)
+ pp_driver_ops.get_hist_isr_info(&isr_mask);
isr &= isr_mask;
while (isr != 0) {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.h b/drivers/video/fbdev/msm/mdss_mdp_pp.h
index 0815f3d7d28a..29e4db17b760 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.h
@@ -97,6 +97,9 @@ struct mdp_pp_driver_ops {
struct mdp_pp_feature_ops pp_ops[PP_FEATURE_MAX];
void (*pp_opmode_config)(int location, struct pp_sts_type *pp_sts,
u32 *opmode, int side);
+ int (*get_hist_offset)(u32 block, u32 *ctl_off);
+ int (*get_hist_isr_info)(u32 *isr_mask);
+ bool (*is_sspp_hist_supp)(void);
};
struct mdss_pp_res_type_v1_7 {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c
index 984db404ad62..5213bbdfde46 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c
@@ -83,7 +83,11 @@
#define PGC_8B_ROUND BIT(1)
#define PGC_ENABLE BIT(0)
+#define HIST_V3_INTR_BIT_MASK 0xF33333
+#define HIST_CTL_OFF_DSPP_V1_7 0x210
+#define HIST_CTL_OFF_SSPP_V1_7 0x2C4
#define HIST_DATA_OFF_DSPP_V1_7 0x1000
+#define HIST_DATA_OFF_SSPP_V1_7 0xA00
#define HIST_DATA_MASK 0xFFFFFF
#define DITHER_MATRIX_OFF 0x14
#define DITHER_MATRIX_INDEX 16
@@ -183,6 +187,9 @@ static int pp_dither_set_config(char __iomem *base_addr,
/* histogram prototypes */
static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data,
u32 block_type, u32 disp_num);
+static int pp_get_hist_offset(u32 block, u32 *ctl_off);
+static int pp_get_hist_isr(u32 *isr_mask);
+static bool pp_is_sspp_hist_supp(void);
static void pp_opmode_config(int location, struct pp_sts_type *pp_sts,
u32 *opmode, int side);
@@ -285,6 +292,10 @@ void *pp_get_driver_ops(struct mdp_pp_driver_ops *ops)
/* Set opmode pointers */
ops->pp_opmode_config = pp_opmode_config;
+ ops->get_hist_offset = pp_get_hist_offset;
+ ops->get_hist_isr_info = pp_get_hist_isr;
+ ops->is_sspp_hist_supp = pp_is_sspp_hist_supp;
+
return &config_data;
}
@@ -579,8 +590,7 @@ static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data,
switch (block_type) {
case SSPP_VIG:
- pr_err("No hist support in SSPP VIG yet %d\n", block_type);
- ret = -ENOTSUPP;
+ base_addr += HIST_DATA_OFF_SSPP_V1_7;
break;
case DSPP:
base_addr += HIST_DATA_OFF_DSPP_V1_7;
@@ -604,6 +614,45 @@ static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data,
return sum;
}
+static int pp_get_hist_offset(u32 block, u32 *ctl_off)
+{
+ int ret = 0;
+
+ if (!ctl_off) {
+ pr_err("invalid params ctl_off %p\n", ctl_off);
+ return -EINVAL;
+ }
+ switch (block) {
+ case SSPP_VIG:
+ *ctl_off = HIST_CTL_OFF_SSPP_V1_7;
+ break;
+ case DSPP:
+ *ctl_off = HIST_CTL_OFF_DSPP_V1_7;
+ break;
+ default:
+ pr_err("Invalid block type %d\n", block);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int pp_get_hist_isr(u32 *isr_mask)
+{
+ if (!isr_mask) {
+ pr_err("invalid params isr_mask %p\n", isr_mask);
+ return -EINVAL;
+ }
+
+ *isr_mask = HIST_V3_INTR_BIT_MASK;
+ return 0;
+}
+
+static bool pp_is_sspp_hist_supp(void)
+{
+ return true;
+}
+
static int pp_gamut_get_config(char __iomem *base_addr, void *cfg_data,
u32 block_type, u32 disp_num)
{