/* * ispccp2_if_enable - Enable CCP2 interface. * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ static void ispccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); int i; if (enable && ccp2->vdds_csib) regulator_enable(ccp2->vdds_csib); /* Enable/Disable all the LCx channels */ for (i = 0; i < CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), ISPCCP2_LCx_CTRL_CHAN_EN, enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0); /* Enable/Disable ccp2 interface in ccp2 mode */ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL, ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN, enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0); /* For frame count propagation */ if (pipe->do_propagation) { /* We may want the Frame Start IRQ from LC0 */ if (enable) isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); else isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); } if (!enable && ccp2->vdds_csib) regulator_disable(ccp2->vdds_csib); }
/* * ispccp2_phyif_config - Initialize CCP2 phy interface config * @ccp2: Pointer to ISP CCP2 device * @config: CCP2 platform data * * Configure the CCP2 physical interface module from platform data. * * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success. */ static int ispccp2_phyif_config(struct isp_ccp2_device *ccp2, const struct isp_ccp2_platform_data *pdata) { struct isp_device *isp = to_isp_device(ccp2); u32 val; /* CCP2B mode */ val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) | ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE; /* Data/strobe physical layer */ BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK, pdata->phy_layer); BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK, pdata->strobe_clk_pol); isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL); val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL); if (!(val & ISPCCP2_CTRL_MODE)) { if (pdata->ccp2_mode) dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n"); if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE) /* Strobe mode requires CCP2 */ return -EIO; } return 0; }
/* * ccp2_if_enable - Enable CCP2 interface. * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ static int ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); int ret; int i; if (enable && ccp2->vdds_csib) { ret = regulator_enable(ccp2->vdds_csib); if (ret < 0) return ret; } /* Enable/Disable all the LCx channels */ for (i = 0; i < CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), ISPCCP2_LCx_CTRL_CHAN_EN, enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0); /* Enable/Disable ccp2 interface in ccp2 mode */ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL, ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN, enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0); if (!enable && ccp2->vdds_csib) regulator_disable(ccp2->vdds_csib); return 0; }
int isp_af_busy(struct isp_af_device *af) { struct isp_device *isp = to_isp_device(af); return isp_reg_readl(isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR) & ISPH3A_PCR_BUSYAF; }
/* * ispresizer_set_src_offs - Setup the memory offset for the input lines * @isp_res: Device context. * @offset: Memory offset. * * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte * boundary; the 5 LSBs are read-only. This field must be programmed to be * 0x0 if the resizer input is from preview engine/CCDC. */ static void ispresizer_set_input_offset(struct isp_res_device *res, u32 offset) { struct isp_device *isp = to_isp_device(res); isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF); }
/* * This API allows the user to update White Balance gains, as well as * exposure time and analog gain. It is also used to request frame * statistics. */ int isp_af_request_statistics(struct isp_af_device *af, struct isp_af_data *afdata) { struct isp_device *isp = to_isp_device(af); struct ispstat_buffer *buf; if (!af->config.af_config) { dev_dbg(isp->dev, "af: statistics requested while af engine" " is not configured\n"); return -EINVAL; } if (afdata->update & REQUEST_STATISTICS) { buf = ispstat_buf_get(&af->stat, (__force void __user *)afdata->af_statistics_buf, afdata->frame_number); if (IS_ERR(buf)) return PTR_ERR(buf); afdata->xtrastats.ts = buf->ts; afdata->config_counter = buf->config_counter; afdata->frame_number = buf->frame_number; ispstat_buf_release(&af->stat); } afdata->curr_frame = af->stat.frame_number; return 0; }
/* * ispresizer_adjust_bandwidth - Reduces read bandwidth when scaling up. * Otherwise there will be SBL overflows. * * The ISP read speed is 256.0 / max(256, 1024 * ISPSBL_SDR_REQ_EXP). This * formula is correct, no matter what the TRM says. Thus, the first * step to use is 0.25 (REQ_EXP=1). * * Ratios: * 0 = 1.0 * 1 = 0.25 * 2 = 0.125 * 3 = 0.083333... * 4 = 0.0625 * 5 = 0.05 and so on... * * TRM says that read bandwidth should be no more than 83MB/s, half * of the maximum of 166MB/s. * * HOWEVER, the read speed must be chosen so that the resizer always * has time to process the frame before the next frame comes in. * Failure to do so will result in a pile-up and endless "resizer busy!" * messages. * * Zoom ratio must not exceed 4.0. This is checked in * ispresizer_check_crop_boundaries(). */ static void ispresizer_adjust_bandwidth(struct isp_res_device *res, int input_width, int input_height, int output_width, int output_height) { struct isp_device *isp = to_isp_device(res); /* Table for dividers. This allows hand tuning. */ static const unsigned char area_to_divider[] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5 /* 1........2...........3.......................4 Zoom level */ }; unsigned int input_area = input_width * input_height; unsigned int output_area = output_width * output_height; if (input_area < output_area && input_area > 0) { u32 val = area_to_divider[output_area / input_area - 1]; dev_dbg(isp->dev, "%s: area factor = %i, val = %i\n", __func__, output_area / input_area, val); isp_reg_writel(isp, val << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP); } else { /* Required input bandwidth greater than output, no limit. */ dev_dbg(isp->dev, "%s: resetting\n", __func__); isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP); } }
/* * ispresizer_set_ratio - Setup horizontal and vertical resizing value * @isp_res: Device context. * @ratio: Structure for ratio parameters. * * Resizing range from 64 to 1024 */ static void ispresizer_set_ratio(struct isp_res_device *res, const struct resizer_ratio *ratio) { struct isp_device *isp = to_isp_device(res); const u16 *h_filter, *v_filter; u32 rgval = 0; rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) & ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK); rgval |= ((ratio->horz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) & ISPRSZ_CNT_HRSZ_MASK; rgval |= ((ratio->vert - 1) << ISPRSZ_CNT_VRSZ_SHIFT) & ISPRSZ_CNT_VRSZ_MASK; isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT); /* prepare horizontal filter coefficients */ if (ratio->horz > MID_RESIZE_VALUE) h_filter = &filter_coefs.h_filter_coef_7tap[0]; else h_filter = &filter_coefs.h_filter_coef_4tap[0]; /* prepare vertical filter coefficients */ if (ratio->vert > MID_RESIZE_VALUE) v_filter = &filter_coefs.v_filter_coef_7tap[0]; else v_filter = &filter_coefs.v_filter_coef_4tap[0]; ispresizer_set_filters(res, h_filter, v_filter); }
/* * ispresizer_busy - Checks if ISP resizer is busy. * * Returns busy field from ISPRSZ_PCR register. */ int ispresizer_busy(struct isp_res_device *res) { struct isp_device *isp = to_isp_device(res); return isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & ISPRSZ_PCR_BUSY; }
/* * ispccp2_pwr_cfg - Configure the power mode settings * @ccp2: pointer to ISP CCP2 device */ static void ispccp2_pwr_cfg(struct isp_ccp2_device *ccp2) { struct isp_device *isp = to_isp_device(ccp2); isp_reg_writel(isp, ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART | ((isp->revision == ISP_REVISION_15_0 && isp->autoidle) ? ISPCCP2_SYSCONFIG_AUTO_IDLE : 0), OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG); }
/* * Configures the memory address to which the output frame is written. * @addr: 32bit memory address aligned on 32byte boundary. * Note: For SBL efficiency reasons the address should be on a 256-byte * boundary. */ static void ispresizer_set_outaddr(struct isp_res_device *res, u32 addr) { struct isp_device *isp = to_isp_device(res); /* * Set output address. This needs to be in its own function * because it changes often. */ isp_reg_writel(isp, addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD); }
/* * ispresizer_set_bilinear - Chrominance horizontal algorithm select * @isp_res: Device context. * @type: Filtering interpolation type. * * Filtering that is same as luminance processing is * intended only for downsampling, and bilinear interpolation * is intended only for upsampling. */ static void ispresizer_set_bilinear(struct isp_res_device *res, enum resizer_chroma_algo type) { struct isp_device *isp = to_isp_device(res); if (type == RSZ_BILINEAR) isp_reg_or(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ISPRSZ_CNT_CBILIN); else isp_reg_and(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_CBILIN); }
/* * ispresizer_set_source - Input source select * @isp_res: Device context. * @source: Input source type * * If this field is set to RESIZER_INPUT_VP, the resizer input is fed from * Preview/CCDC engine, otherwise from memory. */ static void ispresizer_set_source(struct isp_res_device *res, enum resizer_input_entity source) { struct isp_device *isp = to_isp_device(res); if (source == RESIZER_INPUT_MEMORY) isp_reg_or(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ISPRSZ_CNT_INPSRC); else isp_reg_and(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_INPSRC); }
/* * ispresizer_set_intype - Input type select * @isp_res: Device context. * @type: Pixel format type. */ static void ispresizer_set_intype(struct isp_res_device *res, enum resizer_colors_type type) { struct isp_device *isp = to_isp_device(res); if (type == RSZ_COLOR8) isp_reg_or(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ISPRSZ_CNT_INPTYP); else isp_reg_and(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_INPTYP); }
/** * isph3a_update_wb - Updates WB parameters. * * Needs to be called when no ISP Preview processing is taking place. **/ void isph3a_update_wb(struct isp_h3a_device *isp_h3a) { struct isp_device *isp = to_isp_device(isp_h3a); if (isp_h3a->wb_update) { /* FIXME: Get the preview crap out of here!!! */ isppreview_config_whitebalance(&isp->isp_prev, isp_h3a->h3awb_update); isp_h3a->wb_update = 0; } return; }
/* * ispresizer_set_dst_size - Setup the output height and width * @isp_res: Device context. * @width: Output width. * @height: Output height. * * Width : * The value must be EVEN. * * Height: * The number of bytes written to SDRAM must be * a multiple of 16-bytes if the vertical resizing factor * is greater than 1x (upsizing) */ static void ispresizer_set_output_size(struct isp_res_device *res, u32 width, u32 height) { struct isp_device *isp = to_isp_device(res); u32 rgval = 0; dev_dbg(isp->dev, "Output size[w/h]: %dx%d\n", width, height); rgval = (width << ISPRSZ_OUT_SIZE_HORZ_SHIFT) & ISPRSZ_OUT_SIZE_HORZ_MASK; rgval |= (height << ISPRSZ_OUT_SIZE_VERT_SHIFT) & ISPRSZ_OUT_SIZE_VERT_MASK; isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE); }
/* * ispresizer_set_phase - Setup horizontal and vertical starting phase * @isp_res: Device context. * @h_phase: horizontal phase parameters. * @v_phase: vertical phase parameters. * * Horizontal and vertical phase range is 0 to 7 */ static void ispresizer_set_phase(struct isp_res_device *res, u32 h_phase, u32 v_phase) { struct isp_device *isp = to_isp_device(res); u32 rgval = 0; rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) & ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK); rgval |= (h_phase << ISPRSZ_CNT_HSTPH_SHIFT) & ISPRSZ_CNT_HSTPH_MASK; rgval |= (v_phase << ISPRSZ_CNT_VSTPH_SHIFT) & ISPRSZ_CNT_VSTPH_MASK; isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT); }
/* * ispresizer_set_start - Setup vertical and horizontal start position * @isp_res: Device context. * @left: Horizontal start position. * @top: Vertical start position. * * Vertical start line: * This field makes sense only when the resizer obtains its input * from the preview engine/CCDC * * Horizontal start pixel: * Pixels are coded on 16 bits for YUV and 8 bits for color separate data. * When the resizer gets its input from SDRAM, this field must be set * to <= 15 for YUV 16-bit data and <= 31 for 8-bit color separate data */ static void ispresizer_set_start(struct isp_res_device *res, u32 left, u32 top) { struct isp_device *isp = to_isp_device(res); u32 rgval = 0; rgval = (left << ISPRSZ_IN_START_HORZ_ST_SHIFT) & ISPRSZ_IN_START_HORZ_ST_MASK; rgval |= (top << ISPRSZ_IN_START_VERT_ST_SHIFT) & ISPRSZ_IN_START_VERT_ST_MASK; isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START); }
/* * ispresizer_set_inaddr - Sets the memory address of the input frame. * @addr: 32bit memory address aligned on 32byte boundary. */ static void ispresizer_set_inaddr(struct isp_res_device *res, u32 addr) { struct isp_device *isp = to_isp_device(res); dev_dbg(isp->dev, "%s: addr = 0x%08x\n", __func__, addr); res->addr_base = addr; /* This will handle crop settings in stream off state */ if (res->crop_offset) addr += res->crop_offset & ~0x1f; __ispresizer_set_inaddr(res, addr); }
/* * ispccp2_mem_enable - Enable CCP2 memory interface. * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ static void ispccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); if (enable) ispccp2_if_enable(ccp2, 0); /* Enable/Disable ccp2 interface in ccp2 mode */ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL, ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0); isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL, ISPCCP2_LCM_CTRL_CHAN_EN, enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0); }
static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); if (enable) ccp2_if_enable(ccp2, 0); isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL, ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0); isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL, ISPCCP2_LCM_CTRL_CHAN_EN, enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0); }
static void __isp_af_enable(struct isp_af_device *af, int enable) { struct isp_device *isp = to_isp_device(af); unsigned int pcr; pcr = isp_reg_readl(isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); /* Set AF_EN bit in PCR Register */ if (enable) pcr |= AF_EN; else pcr &= ~AF_EN; isp_reg_writel(isp, pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); }
/* * ispccp2_vp_config - Initialize CCP2 video port interface. * @ccp2: Pointer to ISP CCP2 device * @vpclk_div: Video port divisor * * Configure the CCP2 video port with the given clock divisor. The valid divisor * values depend on the ISP revision: * * - revision 1.0 and 2.0 1 to 4 * - revision 15.0 1 to 65536 * * The exact divisor value used might differ from the requested value, as ISP * revision 15.0 represent the divisor by 65536 divided by an integer. */ static void ispccp2_vp_config(struct isp_ccp2_device *ccp2, unsigned int vpclk_div) { struct isp_device *isp = to_isp_device(ccp2); u32 val; /* ISPCCP2_CTRL Video port */ val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL); val |= ISPCCP2_CTRL_VP_ONLY_EN; /* Disable the memory write port */ if (isp->revision == ISP_REVISION_15_0) { vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536); vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U); BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT, ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div); } else {
void __isph3a_aewb_enable(struct isp_h3a_device *isp_h3a, u8 enable) { struct device *dev = to_device(isp_h3a); u32 pcr = isp_reg_readl(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); if (enable) { #ifdef CONFIG_VIDEO_OMAP34XX_ISP_DEBUG_FS struct isp_device *isp = to_isp_device(isp_h3a); if (isp->dfs_h3a) isph3a_dfs_dump(isp); #endif pcr |= ISPH3A_PCR_AEW_EN; } else { pcr &= ~ISPH3A_PCR_AEW_EN; } isp_reg_writel(dev, pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); }
/* * ispresizer_set_luma - Setup luminance enhancer parameters * @isp_res: Device context. * @luma: Structure for luminance enhancer parameters. * * Algorithm select: * 0x0: Disable * 0x1: [-1 2 -1]/2 high-pass filter * 0x2: [-1 -2 6 -2 -1]/4 high-pass filter * * Maximum gain: * The data is coded in U4Q4 representation. * * Slope: * The data is coded in U4Q4 representation. * * Coring offset: * The data is coded in U8Q0 representation. * * The new luminance value is computed as: * Y += HPF(Y) x max(GAIN, (HPF(Y) - CORE) x SLOP + 8) >> 4. */ static void ispresizer_set_luma(struct isp_res_device *res, struct resizer_luma_yenh *luma) { struct isp_device *isp = to_isp_device(res); u32 rgval = 0; rgval = (luma->algo << ISPRSZ_YENH_ALGO_SHIFT) & ISPRSZ_YENH_ALGO_MASK; rgval |= (luma->gain << ISPRSZ_YENH_GAIN_SHIFT) & ISPRSZ_YENH_GAIN_MASK; rgval |= (luma->slope << ISPRSZ_YENH_SLOP_SHIFT) & ISPRSZ_YENH_SLOP_MASK; rgval |= (luma->core << ISPRSZ_YENH_CORE_SHIFT) & ISPRSZ_YENH_CORE_MASK; isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH); }
static void ccp2_reset(struct isp_ccp2_device *ccp2) { struct isp_device *isp = to_isp_device(ccp2); int i = 0; isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG, ISPCCP2_SYSCONFIG_SOFT_RESET); while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) & ISPCCP2_SYSSTATUS_RESET_DONE)) { udelay(10); if (i++ > 10) { dev_warn(isp->dev, "omap3_isp: timeout waiting for ccp2 reset\n"); break; } } }
/* * ispccp2_reset - Reset the CCP2 * @ccp2: pointer to ISP CCP2 device */ static void ispccp2_reset(struct isp_ccp2_device *ccp2) { struct isp_device *isp = to_isp_device(ccp2); int i = 0; /* Reset the CSI1/CCP2B and wait for reset to complete */ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG, ISPCCP2_SYSCONFIG_SOFT_RESET); while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) & ISPCCP2_SYSSTATUS_RESET_DONE)) { udelay(10); if (i++ > 10) { /* try read 10 times */ dev_warn(isp->dev, "omap3_isp: timeout waiting for ccp2 reset\n"); break; } } }
/* * ispresizer_set_ycpos - Luminance and chrominance order * @isp_res: Device context. * @order: order type. */ static void ispresizer_set_ycpos(struct isp_res_device *res, enum v4l2_mbus_pixelcode pixelcode) { struct isp_device *isp = to_isp_device(res); switch (pixelcode) { case V4L2_MBUS_FMT_YUYV16_1X16: isp_reg_or(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ISPRSZ_CNT_YCPOS); break; case V4L2_MBUS_FMT_UYVY16_1X16: isp_reg_and(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_YCPOS); break; default: return; } }
/** * ispresizer_applycrop - Apply crop to input image. **/ void ispresizer_applycrop(struct isp_res_device *isp_res) { struct isp_device *isp = to_isp_device(isp_res); struct isp_node *pipe = &isp->pipeline.rsz; int bpp = ISP_BYTES_PER_PIXEL; if (!isp_res->applycrop) return; ispresizer_set_ratio(isp->dev, isp_res->h_resz, isp_res->v_resz); ispresizer_set_coeffs(isp->dev, NULL, isp_res->h_resz, isp_res->v_resz); /* Switch filter, releated to up/down scale */ if (ispresizer_is_upscale(pipe)) ispresizer_enable_cbilin(isp_res, 1); else ispresizer_enable_cbilin(isp_res, 0); /* Set input and output size */ ispresizer_set_input_size(isp->dev, isp_res->phy_rect.width, isp_res->phy_rect.height); ispresizer_set_output_size(isp->dev, pipe->out.image.width, pipe->out.image.height); /* Set input address and line offset address */ if (pipe->in.path != RSZ_OTFLY_YUV) { /* Set the input address, plus calculated crop offset */ ispresizer_set_inaddr(isp_res, isp_res->in_buff_addr, pipe); /* Set the input line offset/length */ ispresizer_set_in_offset(isp_res, pipe->in.image.bytesperline); } else { /* Set the input address.*/ ispresizer_set_inaddr(isp_res, 0, NULL); /* Set the starting pixel offset */ ispresizer_set_start(isp->dev, isp_res->phy_rect.left * bpp, isp_res->phy_rect.top); ispresizer_set_in_offset(isp_res, 0); } /* Set output line offset */ ispresizer_set_out_offset(isp_res, pipe->out.image.bytesperline); isp_res->applycrop = 0; }
/** * isp_af_validate_errata_i421 - Check errata i421 from AF perspective **/ int isp_af_validate_errata_i421(struct isp_af_device *isp_af, struct af_configuration *afconfig) { struct isp_device *isp = to_isp_device(isp_af); struct isp_h3a_device *isp_h3a = &isp->isp_h3a; struct isph3a_aewb_config *ae_cfg = &isp_h3a->aewb_config_local; struct af_paxel *af_paxel_cfg = &afconfig->paxel_config; int i = 0; if (!isp_h3a->enabled) return 0; if (af_paxel_cfg->hz_cnt < ae_cfg->hor_win_count) { for (i = 2; i <= af_paxel_cfg->hz_cnt; i++) { int num_cycles = ((i - 1) * af_paxel_cfg->width) + 2; if (num_cycles % ae_cfg->win_width == 0) { if (num_cycles / ae_cfg->win_width < ae_cfg->hor_win_count) { dev_err(isp->dev, "Preventing errata" " i421... Invalid" " AF paxel size\n"); return -EINVAL; } } } } else if (af_paxel_cfg->hz_cnt > ae_cfg->hor_win_count) { for (i = 2; i <= ae_cfg->hor_win_count; i++) { int num_cycles = ((i - 1) * ae_cfg->win_width) - 2; if (num_cycles % af_paxel_cfg->width == 0) { if (num_cycles / af_paxel_cfg->width < af_paxel_cfg->hz_cnt) { dev_err(isp->dev, "Preventing errata" " i421... Invalid" " AF paxel size\n"); return -EINVAL; } } } } return 0; }