]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00272541 IPUv3 IC: Split Downsizing overflow for size greater than 1024
authorOliver Brown <oliver.brown@freescale.com>
Tue, 19 Nov 2013 15:49:53 +0000 (09:49 -0600)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 20 Aug 2014 08:06:45 +0000 (10:06 +0200)
For downscaling, it is possible that downscaler output is greater
than 1024. Added a function, calc_split_resize_coeffs, based upon
_calc_resize_coeffs to calculate resizing and downscaling coefficients.

In ipu_ic.c, checks for the range of *_resize_ratio are no longer needed.
 Non split cases will always have  *_resize_ratio of zero.

In ipu_device, additional checks are needed to check for an error from
ipu_calc_stripes_sizes if calc_split_resize_coeffs fails.

Signed-off-by: Oliver Brown <oliver.brown@freescale.com>
drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
drivers/mxc/ipu3/ipu_device.c
drivers/mxc/ipu3/ipu_ic.c

index 4458996c603eca980dc09e3206fa78f704883d5f..7c4181dd572f15a65ec26de343b1dc8391689dbe 100644 (file)
@@ -125,6 +125,57 @@ static unsigned int m_calc(unsigned int pfs)
        return m_calculated;
 }
 
+static int calc_split_resize_coeffs(unsigned int inSize, unsigned int outSize,
+                                   unsigned int *resizeCoeff,
+                                   unsigned int *downsizeCoeff)
+{
+       uint32_t tempSize;
+       uint32_t tempDownsize;
+
+       if (inSize > 4096) {
+               pr_debug("IC input size(%d) cannot exceed 4096\n",
+                       inSize);
+               return -EINVAL;
+       }
+
+       if (outSize > 1024) {
+               pr_debug("IC output size(%d) cannot exceed 1024\n",
+                       outSize);
+               return -EINVAL;
+       }
+
+       if ((outSize << 3) < inSize) {
+               pr_debug("IC cannot downsize more than 8:1\n");
+               return -EINVAL;
+       }
+
+       /* Compute downsizing coefficient */
+       /* Output of downsizing unit cannot be more than 1024 */
+       tempDownsize = 0;
+       tempSize = inSize;
+       while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
+              (tempDownsize < 2)) {
+               tempSize >>= 1;
+               tempDownsize++;
+       }
+       *downsizeCoeff = tempDownsize;
+
+       /* compute resizing coefficient using the following equation:
+          resizeCoeff = M*(SI -1)/(SO - 1)
+          where M = 2^13, SI - input size, SO - output size    */
+       *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
+       if (*resizeCoeff >= 16384L) {
+               pr_debug("Overflow on IC resize coefficient.\n");
+               return -EINVAL;
+       }
+
+       pr_debug("resizing from %u -> %u pixels, "
+               "downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
+               *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
+               ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
+
+       return 0;
+}
 
 /* Stripe parameters calculator */
 /**************************************************************************
@@ -202,6 +253,8 @@ int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
        u64 div; /* result of division */
 
        unsigned int input_m, input_f, output_m, output_f; /* parameters for upsizing by stripes */
+       unsigned int resize_coeff;
+       unsigned int downsize_coeff;
 
        status = 0;
 
@@ -292,7 +345,16 @@ int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
                        left->output_column = 0;
                        right->output_column = onw;
                }
-       } else { /* independent stripes */
+               if (left->input_width > left->output_width) {
+                       if (calc_split_resize_coeffs(left->input_width,
+                                                    left->output_width,
+                                                    &resize_coeff,
+                                                    &downsize_coeff) < 0)
+                               return -EINVAL;
+                       left->irr = right->irr =
+                               (downsize_coeff << 14) | resize_coeff;
+               }
+               } else { /* independent stripes */
                onw_min = output_frame_width - maximal_stripe_width;
                /* onw is a multiple of output_f, in the range */
                /* [max(output_f,output_frame_width-maximal_stripe_width),*/
@@ -363,6 +425,22 @@ int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
                right->input_column = left->input_column + inw;
                left->output_column = 0;
                right->output_column = onw;
+               if (left->input_width > left->output_width) {
+                       if (calc_split_resize_coeffs(left->input_width,
+                                                    left->output_width,
+                                                    &resize_coeff,
+                                                    &downsize_coeff) < 0)
+                               return -EINVAL;
+                       left->irr = (downsize_coeff << 14) | resize_coeff;
+               }
+               if (right->input_width > right->output_width) {
+                       if (calc_split_resize_coeffs(right->input_width,
+                                                    right->output_width,
+                                                    &resize_coeff,
+                                                    &downsize_coeff) < 0)
+                               return -EINVAL;
+                       right->irr = (downsize_coeff << 14) | resize_coeff;
+               }
        }
        return status;
 }
index 72a9905d5beafc745d605c11215415856b8dfe0a..d0127327f1976f5eb84f896fa308f8985593b4d3 100644 (file)
@@ -859,7 +859,9 @@ static int update_split_setting(struct ipu_task_entry *t, bool vdi_split)
                                t->output.format,
                                &left_stripe,
                                &right_stripe);
-               if (ret)
+               if (ret < 0)
+                       return IPU_CHECK_ERR_W_DOWNSIZE_OVER;
+               else if (ret)
                        dev_dbg(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
                                 t->task_no, ret);
                t->set.sp_setting.iw = left_stripe.input_width;
@@ -902,7 +904,9 @@ static int update_split_setting(struct ipu_task_entry *t, bool vdi_split)
                                t->output.format,
                                &up_stripe,
                                &down_stripe);
-               if (ret)
+               if (ret < 0)
+                       return IPU_CHECK_ERR_H_DOWNSIZE_OVER;
+               else if (ret)
                        dev_err(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
                                 t->task_no, ret);
                t->set.sp_setting.ih = up_stripe.input_width;
index f2d8e537b8dbd7014b4fa6b6104f064a64e9bd1d..2da79dfed287d7e45f62daa9810bf86f042c9cee 100644 (file)
@@ -243,9 +243,7 @@ int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
        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)) {
+       if (!params->mem_prp_vf_mem.outv_resize_ratio) {
                ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_height,
                                        params->mem_prp_vf_mem.out_height,
                                        &resizeCoeff, &downsizeCoeff);
@@ -260,10 +258,7 @@ int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
                reg = (params->mem_prp_vf_mem.outv_resize_ratio) << 16;
 
        /* Setup horizontal resizing */
-       /* Upadeted for IC split case */
-       if (!(params->mem_prp_vf_mem.outh_resize_ratio) ||
-               (params->mem_prp_vf_mem.outh_resize_ratio >=
-                                               IC_RSZ_MAX_RESIZE_RATIO)) {
+       if (!params->mem_prp_vf_mem.outh_resize_ratio) {
                ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_width,
                                        params->mem_prp_vf_mem.out_width,
                                        &resizeCoeff, &downsizeCoeff);
@@ -388,9 +383,7 @@ int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
        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)) {
+       if (!params->mem_prp_enc_mem.outv_resize_ratio) {
                ret = _calc_resize_coeffs(ipu,
                                        params->mem_prp_enc_mem.in_height,
                                        params->mem_prp_enc_mem.out_height,
@@ -406,10 +399,7 @@ int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
                reg = (params->mem_prp_enc_mem.outv_resize_ratio) << 16;
 
        /* Setup horizontal resizing */
-       /* Upadeted for IC split case */
-       if (!(params->mem_prp_enc_mem.outh_resize_ratio) ||
-               (params->mem_prp_enc_mem.outh_resize_ratio >=
-                                               IC_RSZ_MAX_RESIZE_RATIO)) {
+       if (!params->mem_prp_enc_mem.outh_resize_ratio) {
                ret = _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_width,
                                        params->mem_prp_enc_mem.out_width,
                                        &resizeCoeff, &downsizeCoeff);
@@ -487,9 +477,7 @@ int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
        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)) {
+       if (!params->mem_pp_mem.outv_resize_ratio) {
                ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_height,
                                    params->mem_pp_mem.out_height,
                                    &resizeCoeff, &downsizeCoeff);
@@ -505,10 +493,7 @@ int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
        }
 
        /* Setup horizontal resizing */
-       /* Upadeted for IC split case */
-       if (!(params->mem_pp_mem.outh_resize_ratio) ||
-               (params->mem_pp_mem.outh_resize_ratio >=
-                                               IC_RSZ_MAX_RESIZE_RATIO)) {
+       if (!params->mem_pp_mem.outh_resize_ratio) {
                ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_width,
                                        params->mem_pp_mem.out_width,
                                        &resizeCoeff, &downsizeCoeff);