/** * ispresizer_config_datapath - Specifies which input to use in resizer module * @input: Indicates the module that gives the image to resizer. * * Sets up the default resizer configuration according to the arguments. * * Returns 0 if successful, or -1 if an unsupported input was requested. **/ int ispresizer_config_datapath(enum ispresizer_input input) { u32 cnt = 0; DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n"); ispres_obj.resinput = input; switch (input) { case RSZ_OTFLY_YUV: cnt &= ~ISPRSZ_CNT_INPTYP; cnt &= ~ISPRSZ_CNT_INPSRC; ispresizer_set_inaddr(0); ispresizer_config_inlineoffset(0); break; case RSZ_MEM_YUV: cnt |= ISPRSZ_CNT_INPSRC; cnt &= ~ISPRSZ_CNT_INPTYP; break; case RSZ_MEM_COL8: cnt |= ISPRSZ_CNT_INPSRC; cnt |= ISPRSZ_CNT_INPTYP; break; default: DPRINTK_ISPRESZ( "ISP_ERR : Wrong Input\n"); return -1; } isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt); //ispresizer_config_ycpos(0); ispresizer_config_ycpos(1); ispresizer_config_filter_coef(&ispreszdefcoef); ispresizer_enable_cbilin(0); ispresizer_config_luma_enhance(&ispreszdefaultyenh); DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n"); return 0; }
/** * ispresizer_config_startphase - Sets the horizontal and vertical start phase. * @hstartphase: horizontal start phase (0 - 7). * @vstartphase: vertical startphase (0 - 7). * * This API just updates the isp_res struct. Actual register write happens in * ispresizer_config_size. **/ void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase) { DPRINTK_ISPRESZ("ispresizer_config_startphase()+\n"); ispres_obj.h_startphase = hstartphase; ispres_obj.v_startphase = vstartphase; DPRINTK_ISPRESZ("ispresizer_config_startphase()-\n"); }
/** * ispresizer_config_ycpos - Specifies if output should be in YC or CY format. * @yc: 0 - YC format, 1 - CY format **/ void ispresizer_config_ycpos(u8 yc) { DPRINTK_ISPRESZ("ispresizer_config_ycpos()+\n"); isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_YCPOS, (yc ? ISPRSZ_CNT_YCPOS : 0)); DPRINTK_ISPRESZ("ispresizer_config_ycpos()-\n"); }
/** * Sets the chrominance algorithm * @cbilin: 0 - chrominance uses same processing as luminance, * 1 - bilinear interpolation processing **/ void ispresizer_enable_cbilin(u8 enable) { DPRINTK_ISPRESZ("ispresizer_enable_cbilin()+\n"); isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_CBILIN, (enable ? ISPRSZ_CNT_CBILIN : 0)); DPRINTK_ISPRESZ("ispresizer_enable_cbilin()-\n"); }
/** * ispresizer_config_outlineoffset - Configures the write address line offset. * @offset: Line offset for the preview output. * * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned. **/ int ispresizer_config_outlineoffset(u32 offset) { DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()+\n"); if (offset % 32) return -EINVAL; isp_reg_writel(offset << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF); DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()-\n"); return 0; }
/** * Configures the memory address to which the output frame is written. * @addr: 32bit memory address aligned on 32byte boundary. **/ int ispresizer_set_outaddr(u32 addr) { DPRINTK_ISPRESZ("ispresizer_set_outaddr()+\n"); if (addr % 32) return -EINVAL; isp_reg_writel(addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD); DPRINTK_ISPRESZ("ispresizer_set_outaddr()-\n"); return 0; }
/** * ispresizer_set_inaddr - Sets the memory address of the input frame. * @addr: 32bit memory address aligned on 32byte boundary. * * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned. **/ int ispresizer_set_inaddr(u32 addr) { DPRINTK_ISPRESZ("ispresizer_set_inaddr()+\n"); if (addr % 32) return -EINVAL; isp_reg_writel(addr << ISPRSZ_SDR_INADD_ADDR_SHIFT, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD); ispres_obj.tmp_buf = addr; DPRINTK_ISPRESZ("ispresizer_set_inaddr()-\n"); return 0; }
/** * ispresizer_config_luma_enhance - Configures luminance enhancer parameters. * @yenh: Pointer to structure containing desired values for core, slope, gain * and algo parameters. **/ void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh) { DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()+\n"); ispres_obj.algo = yenh->algo; isp_reg_writel((yenh->algo << ISPRSZ_YENH_ALGO_SHIFT) | (yenh->gain << ISPRSZ_YENH_GAIN_SHIFT) | (yenh->slope << ISPRSZ_YENH_SLOP_SHIFT) | (yenh->coreoffset << ISPRSZ_YENH_CORE_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH); DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()-\n"); }
void __ispresizer_enable(int enable) { int val; DPRINTK_ISPRESZ("+ispresizer_enable()+\n"); if (enable) { val = (isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & 0x2) | ISPRSZ_PCR_ENABLE; } else { val = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & ~ISPRSZ_PCR_ENABLE; } isp_reg_writel(val, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR); DPRINTK_ISPRESZ("+ispresizer_enable()-\n"); }
/** * ispresizer_config_filter_coef - Sets filter coefficients for 4 & 7-tap mode. * This API just updates the isp_res struct.Actual register write happens in * ispresizer_config_size. * @coef: Structure containing horizontal and vertical filter coefficients for * both 4-tap and 7-tap mode. **/ static void ispresizer_config_filter_coef(struct isprsz_coef *coef) { int i; DPRINTK_ISPRESZ("ispresizer_config_filter_coef()+\n"); for (i = 0; i < 32; i++) { ispres_obj.coeflist.h_filter_coef_4tap[i] = coef->h_filter_coef_4tap[i]; ispres_obj.coeflist.v_filter_coef_4tap[i] = coef->v_filter_coef_4tap[i]; } for (i = 0; i < 28; i++) { ispres_obj.coeflist.h_filter_coef_7tap[i] = coef->h_filter_coef_7tap[i]; ispres_obj.coeflist.v_filter_coef_7tap[i] = coef->v_filter_coef_7tap[i]; } DPRINTK_ISPRESZ("ispresizer_config_filter_coef()-\n"); }
/** * ispresizer_config_datapath - Specifies which input to use in resizer module * @input: Indicates the module that gives the image to resizer. * * Sets up the default resizer configuration according to the arguments. * * Returns 0 if successful, or -EINVAL if an unsupported input was requested. **/ int ispresizer_config_datapath(enum ispresizer_input input) { u32 cnt = 0; DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n"); ispres_obj.resinput = input; switch (input) { case RSZ_OTFLY_YUV: cnt &= ~ISPRSZ_CNT_INPTYP; cnt &= ~ISPRSZ_CNT_INPSRC; ispresizer_set_inaddr(0); ispresizer_config_inlineoffset(0); break; case RSZ_MEM_YUV: cnt |= ISPRSZ_CNT_INPSRC; cnt &= ~ISPRSZ_CNT_INPTYP; break; case RSZ_MEM_COL8: cnt |= ISPRSZ_CNT_INPSRC; cnt |= ISPRSZ_CNT_INPTYP; break; default: printk(KERN_ERR "ISP_ERR : Wrong Input\n"); return -EINVAL; } isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt); /* Use bilinear interpolation for upsampling per TRM */ if (ispres_obj.outputwidth > ispres_obj.inputwidth) ispresizer_enable_cbilin(1); else ispresizer_enable_cbilin(0); ispresizer_config_ycpos(0); ispresizer_config_filter_coef(&ispreszdefcoef); ispresizer_config_luma_enhance(&ispreszdefaultyenh); DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n"); return 0; }
/** * ispresizer_free - Makes Resizer module free. * * Returns 0 if successful, or -EINVAL if resizer module was already freed. **/ int ispresizer_free() { mutex_lock(&ispres_obj.ispres_mutex); if (ispres_obj.res_inuse) { ispres_obj.res_inuse = 0; mutex_unlock(&ispres_obj.ispres_mutex); isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ~(ISPCTRL_RSZ_CLK_EN | ISPCTRL_SBL_WR0_RAM_EN)); return 0; } else { mutex_unlock(&ispres_obj.ispres_mutex); DPRINTK_ISPRESZ("ISP_ERR : Resizer Module already freed\n"); return -EINVAL; } }
/** * ispresizer_config_filter_coef - Sets filter coefficients for 4 & 7-tap mode. * This API just updates the isp_res struct.Actual register write happens in * ispresizer_config_size. * @coef: Structure containing horizontal and vertical filter coefficients for * both 4-tap and 7-tap mode. **/ void ispresizer_config_filter_coef(struct isprsz_coef *coef) { int i; DPRINTK_ISPRESZ("ispresizer_config_filter_coef()+\n"); for (i = 0; i < 32; i++) { ispres_obj.coeflist.h_filter_coef_4tap[i] = coef->h_filter_coef_4tap[i]; ispres_obj.coeflist.v_filter_coef_4tap[i] = coef->v_filter_coef_4tap[i]; } for (i = 0; i < 28; i++) { ispres_obj.coeflist.h_filter_coef_7tap[i] = coef->h_filter_coef_7tap[i]; ispres_obj.coeflist.v_filter_coef_7tap[i] = coef->v_filter_coef_7tap[i]; } if (isp_state() == ISP_STOPPED) ispresizer_write_filter_coef(); else need_to_write_filter_coefs = 1; DPRINTK_ISPRESZ("ispresizer_config_filter_coef()-\n"); }
/** * ispresizer_print_status - Prints the values of the resizer module registers. **/ void ispresizer_print_status() { if (!is_ispresz_debug_enabled()) return; DPRINTK_ISPRESZ("###ISP_CTRL inresizer =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL)); DPRINTK_ISPRESZ("###ISP_IRQ0ENABLE in resizer =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE)); DPRINTK_ISPRESZ("###ISP_IRQ0STATUS in resizer =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS)); DPRINTK_ISPRESZ("###RSZ PCR =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR)); DPRINTK_ISPRESZ("###RSZ CNT =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT)); DPRINTK_ISPRESZ("###RSZ OUT SIZE =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE)); DPRINTK_ISPRESZ("###RSZ IN START =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START)); DPRINTK_ISPRESZ("###RSZ IN SIZE =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE)); DPRINTK_ISPRESZ("###RSZ SDR INADD =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD)); DPRINTK_ISPRESZ("###RSZ SDR INOFF =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF)); DPRINTK_ISPRESZ("###RSZ SDR OUTADD =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD)); DPRINTK_ISPRESZ("###RSZ SDR OTOFF =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF)); DPRINTK_ISPRESZ("###RSZ YENH =0x%x\n", isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH)); }
/** * ispresizer_restore_context - Restores resizer module register values. **/ void ispresizer_restore_context(void) { DPRINTK_ISPRESZ("Restoring context\n"); isp_restore_context(isprsz_reg_list); }
/** * ispresizer_save_context - Saves the values of the resizer module registers. **/ void ispresizer_save_context(void) { DPRINTK_ISPRESZ("Saving context\n"); isp_save_context(isprsz_reg_list); }
/** * ispresizer_try_size - Validates input and output images size. * @input_w: input width for the resizer in number of pixels per line * @input_h: input height for the resizer in number of lines * @output_w: output width from the resizer in number of pixels per line * resizer when writing to memory needs this to be multiple of 16. * @output_h: output height for the resizer in number of lines, must be even. * * Calculates the horizontal and vertical resize ratio, number of pixels to * be cropped in the resizer module and checks the validity of various * parameters. Formula used for calculation is:- * * 8-phase 4-tap mode :- * inputwidth = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7 * inputheight = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4 * endpahse for width = ((32 * sph + (ow - 1) * hrsz + 16) >> 5) % 8 * endphase for height = ((32 * sph + (oh - 1) * hrsz + 16) >> 5) % 8 * * 4-phase 7-tap mode :- * inputwidth = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7 * inputheight = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7 * endpahse for width = ((64 * sph + (ow - 1) * hrsz + 32) >> 6) % 4 * endphase for height = ((64 * sph + (oh - 1) * hrsz + 32) >> 6) % 4 * * Where: * sph = Start phase horizontal * spv = Start phase vertical * ow = Output width * oh = Output height * hrsz = Horizontal resize value * vrsz = Vertical resize value * * Fills up the output/input widht/height, horizontal/vertical resize ratio, * horizontal/vertical crop variables in the isp_res structure. **/ int ispresizer_try_size(u32 *input_width, u32 *input_height, u32 *output_w, u32 *output_h) { u32 rsz, rsz_7, rsz_4; u32 sph; u32 input_w, input_h; int max_in_otf, max_out_7tap; input_w = *input_width; input_h = *input_height; if (input_w < 32 || input_h < 32) { DPRINTK_ISPCCDC("ISP_ERR: RESIZER cannot handle input width" " less than 32 pixels or height less than" " 32\n"); return -EINVAL; } input_w -= 6; input_h -= 6; if (input_h > MAX_IN_HEIGHT) return -EINVAL; if (*output_w < 16) *output_w = 16; if (*output_h < 2) *output_h = 2; if (omap_rev() == OMAP3430_REV_ES1_0) { max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE; max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH; } else { max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE_ES2; max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH_ES2; } if (ispres_obj.resinput == RSZ_OTFLY_YUV) { if (input_w > max_in_otf) return -EINVAL; } else { if (input_w > MAX_IN_WIDTH_MEMORY_MODE) return -EINVAL; } *output_h &= 0xfffffffe; sph = DEFAULTSTPHASE; rsz_7 = ((input_h - 7) * 256) / (*output_h - 1); rsz_4 = ((input_h - 4) * 256) / (*output_h - 1); rsz = (input_h * 256) / *output_h; if (rsz <= MID_RESIZE_VALUE) { rsz = rsz_4; if (rsz < MINIMUM_RESIZE_VALUE) { rsz = MINIMUM_RESIZE_VALUE; *output_h = (((input_h - 4) * 256) / rsz) + 1; DPRINTK_ISPRESZ("%s: using output_h" "%d instead\n", __func__, *output_h); } } else { rsz = rsz_7; if (*output_w > max_out_7tap) *output_w = max_out_7tap; if (rsz > MAXIMUM_RESIZE_VALUE) { rsz = MAXIMUM_RESIZE_VALUE; *output_h = (((input_h - 7) * 256) / rsz) + 1; DPRINTK_ISPRESZ("%s: using output_h" "%d instead\n", __func__, *output_h); } } if (rsz > MID_RESIZE_VALUE) { input_h = (((64 * sph) + ((*output_h - 1) * rsz) + 32) / 256) + 7; } else { input_h = (((32 * sph) + ((*output_h - 1) * rsz) + 16) / 256) + 4; } ispres_obj.outputheight = *output_h; ispres_obj.v_resz = rsz; ispres_obj.inputheight = input_h; ispres_obj.ipht_crop = DEFAULTSTPIXEL; ispres_obj.v_startphase = sph; *output_w &= 0xfffffff0; sph = DEFAULTSTPHASE; rsz_7 = ((input_w - 7) * 256) / (*output_w - 1); rsz_4 = ((input_w - 4) * 256) / (*output_w - 1); rsz = (input_w * 256) / *output_w; if (rsz > MID_RESIZE_VALUE) { rsz = rsz_7; if (rsz > MAXIMUM_RESIZE_VALUE) { rsz = MAXIMUM_RESIZE_VALUE; *output_w = (((input_w - 7) * 256) / rsz) + 1; *output_w = (*output_w + 0xf) & 0xfffffff0; DPRINTK_ISPRESZ("%s: using output_w" "%d instead\n", __func__, *output_w); } } else { rsz = rsz_4; if (rsz < MINIMUM_RESIZE_VALUE) { rsz = MINIMUM_RESIZE_VALUE; *output_w = (((input_w - 4) * 256) / rsz) + 1; *output_w = (*output_w + 0xf) & 0xfffffff0; DPRINTK_ISPRESZ("%s: using output_w %d" "instead\n", __func__, *output_w); } } /* Recalculate input based on TRM equations */ if (rsz > MID_RESIZE_VALUE) { input_w = (((64 * sph) + ((*output_w - 1) * rsz) + 32) / 256) + 7; } else { input_w = (((32 * sph) + ((*output_w - 1) * rsz) + 16) / 256) + 7; } ispres_obj.outputwidth = *output_w; ispres_obj.h_resz = rsz; ispres_obj.inputwidth = input_w; ispres_obj.ipwd_crop = DEFAULTSTPIXEL; ispres_obj.h_startphase = sph; *input_height = input_h; *input_width = input_w; return 0; }
/** * ispresizer_set_filter_coef - Writes the resizer filter coefficients to the * resizer registers. **/ void ispresizer_write_filter_coef(void) { int i, j; DPRINTK_ISPRESZ("ispresizer_write_filter_coef\n"); if (ispresizer_busy() == 0) { ispresizer_enable(0); if (ispres_obj.h_resz <= MID_RESIZE_VALUE) { j = 0; for (i = 0; i < 16; i++) { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_4tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. h_filter_coef_4tap[j + 1] << ISPRSZ_HFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 2; } } else { j = 0; for (i = 0; i < 16; i++) { if ((i + 1) % 4 == 0) { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_7tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 1; } else { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_7tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. h_filter_coef_7tap[j+1] << ISPRSZ_HFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 2; } } } if (ispres_obj.v_resz <= MID_RESIZE_VALUE) { j = 0; for (i = 0; i < 16; i++) { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_4tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. v_filter_coef_4tap[j + 1] << ISPRSZ_VFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 2; } } else { j = 0; for (i = 0; i < 16; i++) { if ((i + 1) % 4 == 0) { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_7tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 1; } else { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_7tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. v_filter_coef_7tap[j+1] << ISPRSZ_VFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 2; } } } need_to_write_filter_coefs = 0; } else { DPRINTK_ISPRESZ("Resizer busy when programming filter coefs\n"); } }
/** * ispresizer_config_size - Configures input and output image size. * @input_w: input width for the resizer in number of pixels per line. * @input_h: input height for the resizer in number of lines. * @output_w: output width from the resizer in number of pixels per line. * @output_h: output height for the resizer in number of lines. * * Configures the appropriate values stored in the isp_res structure in the * resizer registers. * * Returns 0 if successful, or -EINVAL if passed values haven't been verified * with ispresizer_try_size() previously. **/ int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h) { int i, j; u32 res; DPRINTK_ISPRESZ("ispresizer_config_size()+, input_w = %d,input_h =" " %d, output_w = %d, output_h" " = %d,hresz = %d,vresz = %d," " hcrop = %d, vcrop = %d," " hstph = %d, vstph = %d\n", ispres_obj.inputwidth, ispres_obj.inputheight, ispres_obj.outputwidth, ispres_obj.outputheight, ispres_obj.h_resz, ispres_obj.v_resz, ispres_obj.ipwd_crop, ispres_obj.ipht_crop, ispres_obj.h_startphase, ispres_obj.v_startphase); if ((output_w != ispres_obj.outputwidth) || (output_h != ispres_obj.outputheight)) { printk(KERN_ERR "Output parameters passed do not match the" " values calculated by the" " trysize passed w %d, h %d" " \n", output_w , output_h); return -EINVAL; } /* Set Resizer input address and offset adderss */ ispresizer_config_inlineoffset(isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET)); res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) & ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK); isp_reg_writel(res | (ispres_obj.h_startphase << ISPRSZ_CNT_HSTPH_SHIFT) | (ispres_obj.v_startphase << ISPRSZ_CNT_VSTPH_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT); /* Set start address for cropping */ isp_reg_writel(ispres_obj.tmp_buf + isp_get_buf_offset(), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD); /* isp_reg_writel( ((ispres_obj.ipwd_crop & 15) << ISPRSZ_IN_START_HORZ_ST_SHIFT) | (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START); */ isp_reg_writel((0x00 << ISPRSZ_IN_START_HORZ_ST_SHIFT) | (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START); isp_reg_writel((ispres_obj.inputwidth << ISPRSZ_IN_SIZE_HORZ_SHIFT) | (ispres_obj.inputheight << ISPRSZ_IN_SIZE_VERT_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE); if (!ispres_obj.algo) { isp_reg_writel((output_w << ISPRSZ_OUT_SIZE_HORZ_SHIFT) | (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE); } else { isp_reg_writel(((output_w - 4) << ISPRSZ_OUT_SIZE_HORZ_SHIFT) | (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE); } res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) & ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK); isp_reg_writel(res | ((ispres_obj.h_resz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) | ((ispres_obj.v_resz - 1) << ISPRSZ_CNT_VRSZ_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT); /* write filter coefficients */ /* why not call isp_write_filter_coefs() ? */ if (ispres_obj.h_resz <= MID_RESIZE_VALUE) { j = 0; for (i = 0; i < 16; i++) { isp_reg_writel( (ispres_obj.coeflist.h_filter_coef_4tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT) | (ispres_obj.coeflist.h_filter_coef_4tap[j + 1] << ISPRSZ_HFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 2; } } else { j = 0; for (i = 0; i < 16; i++) { if ((i + 1) % 4 == 0) { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_7tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 1; } else { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_7tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. h_filter_coef_7tap[j+1] << ISPRSZ_HFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 2; } } } if (ispres_obj.v_resz <= MID_RESIZE_VALUE) { j = 0; for (i = 0; i < 16; i++) { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_4tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. v_filter_coef_4tap[j + 1] << ISPRSZ_VFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 2; } } else { j = 0; for (i = 0; i < 16; i++) { if ((i + 1) % 4 == 0) { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_7tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 1; } else { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_7tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. v_filter_coef_7tap[j+1] << ISPRSZ_VFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 2; } } } ispresizer_config_outlineoffset(output_w*2); DPRINTK_ISPRESZ("ispresizer_config_size()-\n"); return 0; }
/** * ispresizer_config_size - Configures input and output image size. * @input_w: input width for the resizer in number of pixels per line. * @input_h: input height for the resizer in number of lines. * @output_w: output width from the resizer in number of pixels per line. * @output_h: output height for the resizer in number of lines. * * Configures the appropriate values stored in the isp_res structure in the * resizer registers. * * Returns 0 if successful, or -1 if passed values haven't been verified * with ispresizer_try_size() previously. **/ int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h) { int i, j; u32 res; DPRINTK_ISPRESZ("ispresizer_config_size()+, input_w = %d,input_h =" " %d, output_w = %d, output_h" " = %d,hresz = %d,vresz = %d," " hcrop = %d, vcrop = %d," " hstph = %d, vstph = %d," "algo = %d\n", ispres_obj.inputwidth, ispres_obj.inputheight, ispres_obj.outputwidth, ispres_obj.outputheight, ispres_obj.h_resz, ispres_obj.v_resz, ispres_obj.ipwd_crop, ispres_obj.ipht_crop, ispres_obj.h_startphase, ispres_obj.v_startphase, ispres_obj.algo); if ((output_w != ispres_obj.outputwidth) || (output_h != ispres_obj.outputheight)) { DPRINTK_ISPRESZ( "Output parameters passed do not match the" " values calculated by the" " trysize passed w %d, h %d" " \n", output_w , output_h); return -1; } res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) & ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK); isp_reg_writel(res | (ispres_obj.h_startphase << ISPRSZ_CNT_HSTPH_SHIFT) | (ispres_obj.v_startphase << ISPRSZ_CNT_VSTPH_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT); isp_reg_writel(0,OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD); isp_reg_writel(0,OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF); isp_reg_writel( ((ispres_obj.ipwd_crop * 2 + 1) << ISPRSZ_IN_START_HORZ_ST_SHIFT) | (ispres_obj.ipht_crop << ISPRSZ_IN_START_VERT_ST_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START); #if 0 isp_reg_writel((0x00 << ISPRSZ_IN_START_HORZ_ST_SHIFT) | (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START); #endif isp_reg_writel((ispres_obj.inputwidth << ISPRSZ_IN_SIZE_HORZ_SHIFT) | (ispres_obj.inputheight << ISPRSZ_IN_SIZE_VERT_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE); if (!ispres_obj.algo) { isp_reg_writel((output_w << ISPRSZ_OUT_SIZE_HORZ_SHIFT) | (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE); } else { isp_reg_writel(((output_w - 4) << ISPRSZ_OUT_SIZE_HORZ_SHIFT) | (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE); } res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) & ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK); isp_reg_writel(res | ((ispres_obj.h_resz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) | ((ispres_obj.v_resz - 1) << ISPRSZ_CNT_VRSZ_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT); if (ispres_obj.h_resz <= MID_RESIZE_VALUE) { j = 0; for (i = 0; i < 16; i++) { isp_reg_writel( (ispres_obj.coeflist.h_filter_coef_4tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT) | (ispres_obj.coeflist.h_filter_coef_4tap[j + 1] << ISPRSZ_HFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 2; } } else { j = 0; for (i = 0; i < 16; i++) { if ((i + 1) % 4 == 0) { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_7tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 1; } else { isp_reg_writel((ispres_obj.coeflist. h_filter_coef_7tap[j] << ISPRSZ_HFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. h_filter_coef_7tap[j+1] << ISPRSZ_HFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10 + (i * 0x04)); j += 2; } } } if (ispres_obj.v_resz <= MID_RESIZE_VALUE) { j = 0; for (i = 0; i < 16; i++) { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_4tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. v_filter_coef_4tap[j + 1] << ISPRSZ_VFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 2; } } else { j = 0; for (i = 0; i < 16; i++) { if ((i + 1) % 4 == 0) { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_7tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 1; } else { isp_reg_writel((ispres_obj.coeflist. v_filter_coef_7tap[j] << ISPRSZ_VFILT10_COEF0_SHIFT) | (ispres_obj.coeflist. v_filter_coef_7tap[j+1] << ISPRSZ_VFILT10_COEF1_SHIFT), OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10 + (i * 0x04)); j += 2; } } } ispresizer_config_outlineoffset(output_w*2); DPRINTK_ISPRESZ("ispresizer_config_size()-\n"); return 0; }