summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2013-09-22 10:34:24 +0800
committerPeng Fushi <fushi.peng@freescale.com>2014-08-28 16:50:11 +0800
commit267695f5b9db21a1fcdf1145c791c1f28b444e4d (patch)
treee22f21c4b03ca541569e4c869e9cfcc430c230c2
parent584028a9549f008937d72dadfcfac9a000c38190 (diff)
ENGR00280663-1 IPUv3: improve IC scale check logic
This patch improves IPU IC task scale check logic so that we may return with error code if the calculation for scale coefficients fails. Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
-rw-r--r--drivers/mxc/ipu3/ipu_ic.c125
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h10
2 files changed, 97 insertions, 38 deletions
diff --git a/drivers/mxc/ipu3/ipu_ic.c b/drivers/mxc/ipu3/ipu_ic.c
index 4a9c24dc1115..7437c7461512 100644
--- a/drivers/mxc/ipu3/ipu_ic.c
+++ b/drivers/mxc/ipu3/ipu_ic.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2014 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -38,7 +38,8 @@ enum {
static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
ipu_color_space_t out_format, int csc_index);
-static bool _calc_resize_coeffs(struct ipu_soc *ipu,
+
+static int _calc_resize_coeffs(struct ipu_soc *ipu,
uint32_t inSize, uint32_t outSize,
uint32_t *resizeCoeff,
uint32_t *downsizeCoeff);
@@ -234,19 +235,27 @@ void _ipu_vdi_uninit(struct ipu_soc *ipu)
ipu_vdi_write(ipu, 0, VDI_C);
}
-void _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params, bool src_is_csi)
+int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi)
{
uint32_t reg, ic_conf;
uint32_t downsizeCoeff, resizeCoeff;
ipu_color_space_t in_fmt, out_fmt;
+ int ret = 0;
/* Setup vertical resizing */
if (!(params->mem_prp_vf_mem.outv_resize_ratio) ||
(params->mem_prp_vf_mem.outv_resize_ratio >=
IC_RSZ_MAX_RESIZE_RATIO)) {
- _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_height,
- params->mem_prp_vf_mem.out_height,
- &resizeCoeff, &downsizeCoeff);
+ ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_height,
+ params->mem_prp_vf_mem.out_height,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpvf height "
+ "scaling coefficients\n");
+ return ret;
+ }
+
reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
} else
reg = (params->mem_prp_vf_mem.outv_resize_ratio) << 16;
@@ -256,9 +265,15 @@ void _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params, bool
if (!(params->mem_prp_vf_mem.outh_resize_ratio) ||
(params->mem_prp_vf_mem.outh_resize_ratio >=
IC_RSZ_MAX_RESIZE_RATIO)) {
- _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_width,
- params->mem_prp_vf_mem.out_width,
- &resizeCoeff, &downsizeCoeff);
+ ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_width,
+ params->mem_prp_vf_mem.out_width,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpvf width "
+ "scaling coefficients\n");
+ return ret;
+ }
+
reg |= (downsizeCoeff << 14) | resizeCoeff;
} else
reg |= params->mem_prp_vf_mem.outh_resize_ratio;
@@ -339,6 +354,8 @@ void _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params, bool
ic_conf |= IC_CONF_RWS_EN;
ipu_ic_write(ipu, ic_conf, IC_CONF);
+
+ return ret;
}
void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu)
@@ -363,19 +380,28 @@ void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu)
ipu_ic_write(ipu, reg, IC_CONF);
}
-void _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params, bool src_is_csi)
+int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi)
{
uint32_t reg, ic_conf;
uint32_t downsizeCoeff, resizeCoeff;
ipu_color_space_t in_fmt, out_fmt;
+ int ret = 0;
/* Setup vertical resizing */
if (!(params->mem_prp_enc_mem.outv_resize_ratio) ||
(params->mem_prp_enc_mem.outv_resize_ratio >=
IC_RSZ_MAX_RESIZE_RATIO)) {
- _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_height,
- params->mem_prp_enc_mem.out_height,
- &resizeCoeff, &downsizeCoeff);
+ ret = _calc_resize_coeffs(ipu,
+ params->mem_prp_enc_mem.in_height,
+ params->mem_prp_enc_mem.out_height,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpenc height "
+ "scaling coefficients\n");
+ return ret;
+ }
+
reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
} else
reg = (params->mem_prp_enc_mem.outv_resize_ratio) << 16;
@@ -385,9 +411,15 @@ void _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params, bool
if (!(params->mem_prp_enc_mem.outh_resize_ratio) ||
(params->mem_prp_enc_mem.outh_resize_ratio >=
IC_RSZ_MAX_RESIZE_RATIO)) {
- _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_width,
- params->mem_prp_enc_mem.out_width,
- &resizeCoeff, &downsizeCoeff);
+ ret = _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_width,
+ params->mem_prp_enc_mem.out_width,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpenc width "
+ "scaling coefficients\n");
+ return ret;
+ }
+
reg |= (downsizeCoeff << 14) | resizeCoeff;
} else
reg |= params->mem_prp_enc_mem.outh_resize_ratio;
@@ -422,6 +454,8 @@ void _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params, bool
ic_conf |= IC_CONF_RWS_EN;
ipu_ic_write(ipu, ic_conf, IC_CONF);
+
+ return ret;
}
void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu)
@@ -446,19 +480,26 @@ void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu)
ipu_ic_write(ipu, reg, IC_CONF);
}
-void _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
+int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
{
uint32_t reg, ic_conf;
uint32_t downsizeCoeff, resizeCoeff;
ipu_color_space_t in_fmt, out_fmt;
+ int ret = 0;
/* Setup vertical resizing */
if (!(params->mem_pp_mem.outv_resize_ratio) ||
(params->mem_pp_mem.outv_resize_ratio >=
IC_RSZ_MAX_RESIZE_RATIO)) {
- _calc_resize_coeffs(ipu, params->mem_pp_mem.in_height,
- params->mem_pp_mem.out_height,
- &resizeCoeff, &downsizeCoeff);
+ ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_height,
+ params->mem_pp_mem.out_height,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate pp height "
+ "scaling coefficients\n");
+ return ret;
+ }
+
reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
} else {
reg = (params->mem_pp_mem.outv_resize_ratio) << 16;
@@ -469,9 +510,15 @@ void _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
if (!(params->mem_pp_mem.outh_resize_ratio) ||
(params->mem_pp_mem.outh_resize_ratio >=
IC_RSZ_MAX_RESIZE_RATIO)) {
- _calc_resize_coeffs(ipu, params->mem_pp_mem.in_width,
- params->mem_pp_mem.out_width,
- &resizeCoeff, &downsizeCoeff);
+ ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_width,
+ params->mem_pp_mem.out_width,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate pp width "
+ "scaling coefficients\n");
+ return ret;
+ }
+
reg |= (downsizeCoeff << 14) | resizeCoeff;
} else {
reg |= params->mem_pp_mem.outh_resize_ratio;
@@ -549,6 +596,8 @@ void _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
}
ipu_ic_write(ipu, ic_conf, IC_CONF);
+
+ return ret;
}
void _ipu_ic_uninit_pp(struct ipu_soc *ipu)
@@ -822,7 +871,7 @@ static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in
}
}
-static bool _calc_resize_coeffs(struct ipu_soc *ipu,
+static int _calc_resize_coeffs(struct ipu_soc *ipu,
uint32_t inSize, uint32_t outSize,
uint32_t *resizeCoeff,
uint32_t *downsizeCoeff)
@@ -830,14 +879,22 @@ static bool _calc_resize_coeffs(struct ipu_soc *ipu,
uint32_t tempSize;
uint32_t tempDownsize;
- /* Input size cannot be more than 4096 */
- /* Output size cannot be more than 1024 */
- if ((inSize > 4096) || (outSize > 1024))
- return false;
+ if (inSize > 4096) {
+ dev_err(ipu->dev, "IC input size(%d) cannot exceed 4096\n",
+ inSize);
+ return -EINVAL;
+ }
+
+ if (outSize > 1024) {
+ dev_err(ipu->dev, "IC output size(%d) cannot exceed 1024\n",
+ outSize);
+ return -EINVAL;
+ }
- /* Cannot downsize more than 8:1 */
- if ((outSize << 3) < inSize)
- return false;
+ if ((outSize << 3) < inSize) {
+ dev_err(ipu->dev, "IC cannot downsize more than 8:1\n");
+ return -EINVAL;
+ }
/* Compute downsizing coefficient */
/* Output of downsizing unit cannot be more than 1024 */
@@ -855,8 +912,8 @@ static bool _calc_resize_coeffs(struct ipu_soc *ipu,
where M = 2^13, SI - input size, SO - output size */
*resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
if (*resizeCoeff >= 16384L) {
- dev_dbg(ipu->dev, "Warning! Overflow on resize coeff.\n");
- *resizeCoeff = 0x3FFF;
+ dev_err(ipu->dev, "Overflow on IC resize coefficient.\n");
+ return -EINVAL;
}
dev_dbg(ipu->dev, "resizing from %u -> %u pixels, "
@@ -864,7 +921,7 @@ static bool _calc_resize_coeffs(struct ipu_soc *ipu,
*downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
- return true;
+ return 0;
}
void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu)
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
index a0d71dd5dad3..495cc72cfd14 100644
--- a/drivers/mxc/ipu3/ipu_prv.h
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2014 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -287,7 +287,8 @@ int _ipu_disp_chan_is_interlaced(struct ipu_soc *ipu, ipu_channel_t channel);
void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel);
void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel);
-void _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params, bool src_is_csi);
+int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi);
void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
void _ipu_vdi_uninit(struct ipu_soc *ipu);
void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu);
@@ -295,11 +296,12 @@ void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params);
void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu);
void _ipu_ic_init_csi(struct ipu_soc *ipu, ipu_channel_params_t *params);
void _ipu_ic_uninit_csi(struct ipu_soc *ipu);
-void _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params, bool src_is_csi);
+int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi);
void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu);
void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params);
void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu);
-void _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
+int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
void _ipu_ic_uninit_pp(struct ipu_soc *ipu);
void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu);