示例#1
0
/*
 * 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);
}
示例#2
0
/*
 * 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;
}
示例#3
0
文件: ispccp2.c 项目: 020gzh/linux
/*
 * 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;
}
示例#4
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;
}
示例#5
0
/*
 * 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);
}
示例#6
0
/*
 * 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;
}
示例#7
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);
	}
}
示例#8
0
/*
 * 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);
}
示例#9
0
/*
 * 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;
}
示例#10
0
/*
 * 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);
}
示例#11
0
/*
 * 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);
}
示例#12
0
/*
 * 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);
}
示例#13
0
/*
 * 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);
}
示例#14
0
/*
 * 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);
}
示例#15
0
/**
 * 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;
}
示例#16
0
/*
 * 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);
}
示例#17
0
/*
 * 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);
}
示例#18
0
/*
 * 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);
}
示例#19
0
/*
 * 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);
}
示例#20
0
/*
 * 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);
}
示例#22
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);
}
示例#23
0
/*
 * 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 {
示例#24
0
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);
}
示例#25
0
/*
 * 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;
        }
    }
}
示例#27
0
/*
 * 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;
		}
	}
}
示例#28
0
/*
 * 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;
	}
}
示例#29
0
/**
 * 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;
}
示例#30
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;
}