Exemplo n.º 1
0
/*
 * isp_csi2_isr - CSI2 interrupt handling.
 *
 * Return -EIO on Transmission error
 */
int isp_csi2_isr(struct isp_csi2_device *csi2)
{
	u32 csi2_irqstatus, cpxio1_irqstatus;
	struct isp_device *isp = csi2->isp;
	int retval = 0;

	if (!csi2->available)
		return -ENODEV;

	csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
	isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);

	/* Failure Cases */
	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
		cpxio1_irqstatus = isp_reg_readl(isp, csi2->regs1,
						 ISPCSI2_PHY_IRQSTATUS);
		isp_reg_writel(isp, cpxio1_irqstatus,
			       csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
		dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
			"%x\n", cpxio1_irqstatus);
		retval = -EIO;
	}

	if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
			      ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
			      ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
			      ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
			      ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)) {
		dev_dbg(isp->dev, "CSI2 Err:"
			" OCP:%d,"
			" Short_pack:%d,"
			" ECC:%d,"
			" CPXIO2:%d,"
			" FIFO_OVF:%d,"
			"\n",
			(csi2_irqstatus &
			 ISPCSI2_IRQSTATUS_OCP_ERR_IRQ) ? 1 : 0,
			(csi2_irqstatus &
			 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ) ? 1 : 0,
			(csi2_irqstatus &
			 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ) ? 1 : 0,
			(csi2_irqstatus &
			 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
			(csi2_irqstatus &
			 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
		retval = -EIO;
	}

	if (isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
		return 0;

	/* Successful cases */
	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
		isp_csi2_isr_ctx(csi2, &csi2->contexts[0]);

	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
		dev_dbg(isp->dev, "CSI2: ECC correction done\n");

	return retval;
}
Exemplo n.º 2
0
/**
 * isph3a_aewb_update_regs - Helper function to update h3a registers.
 **/
void isph3a_aewb_config_registers(struct isp_h3a_device *isp_h3a)
{
	struct device *dev = to_device(isp_h3a);
	unsigned long irqflags;

	if (!isp_h3a->aewb_config_local.aewb_enable)
		return;

	spin_lock_irqsave(isp_h3a->lock, irqflags);

	isp_reg_writel(dev, isp_h3a->buf_next->iommu_addr,
		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);

	if (!isp_h3a->update) {
		spin_unlock_irqrestore(isp_h3a->lock, irqflags);
		return;
	}

	isp_reg_writel(dev, isp_h3a->regs.win1, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWWIN1);
	isp_reg_writel(dev, isp_h3a->regs.start, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWINSTART);
	isp_reg_writel(dev, isp_h3a->regs.blk, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWINBLK);
	isp_reg_writel(dev, isp_h3a->regs.subwin, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWSUBWIN);
	isp_reg_and_or(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
		       ~ISPH3A_PCR_AEW_MASK, isp_h3a->regs.pcr);

	isp_h3a->update = 0;

	spin_unlock_irqrestore(isp_h3a->lock, irqflags);
}
Exemplo n.º 3
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);
	}
}
Exemplo n.º 4
0
/*
 * csi2_set_outaddr - Set memory address to save output image
 * @csi2: Pointer to ISP CSI2a device.
 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
 *
 * Sets the memory address where the output will be saved.
 *
 * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
 * boundary.
 */
static void csi2_set_outaddr(struct isp_csi2_device *csi2, u32 addr)
{
	struct isp_device *isp = csi2->isp;
	struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[0];

	ctx->ping_addr = ctx->pong_addr = addr;
	isp_reg_writel(isp, ctx->ping_addr,
		       csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
	isp_reg_writel(isp, ctx->pong_addr,
		       csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
}
Exemplo n.º 5
0
/**
 * ispresizer_set_luma_enhance - Set luminance enhancer parameters.
 * @yenh: Pointer to structure containing desired values or NULL
 * to user default values for core, slope, gain and algo parameters.
 **/
void ispresizer_set_luma_enhance(struct device *dev, struct isprsz_yenh *yenh)
{
	if (yenh != NULL) {
		isp_reg_writel(dev, (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);
	} else {
		isp_reg_writel(dev, 0, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH);
	}
}
Exemplo n.º 6
0
Arquivo: isp.c Projeto: Antyks/linux
/*
 * isp_power_settings - Sysconfig settings, for Power Management.
 * @isp: OMAP3 ISP device
 * @idle: Consider idle state.
 *
 * Sets the power settings for the ISP, and SBL bus.
 */
static void isp_power_settings(struct isp_device *isp, int idle)
{
	isp_reg_writel(isp,
		       ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY :
				ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY) <<
			ISP_SYSCONFIG_MIDLEMODE_SHIFT) |
			((isp->revision == ISP_REVISION_15_0) ?
			  ISP_SYSCONFIG_AUTOIDLE : 0),
		       OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);

	if (isp->autoidle)
		isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
			       ISP_CTRL);
}
Exemplo n.º 7
0
/**
 * ispresizer_set_coeffs - Setup default coefficents for polyphase filter.
 * @dst: Target registers map structure.
 * @coeffs: filter coefficients structure or NULL for default values
 * @h_ratio: Horizontal resizing value.
 * @v_ratio: Vertical resizing value.
 */
void ispresizer_set_coeffs(struct device *dev, struct isprsz_coef *coeffs,
			   unsigned h_ratio, unsigned v_ratio)
{
	const u16 *cf_ptr;
	int ix;
	u32 rval;

	/* Init horizontal filter coefficients */
	if (h_ratio > MID_RESIZE_VALUE) {
		if (coeffs != NULL)
			cf_ptr = coeffs->h_filter_coef_7tap;
		else
			cf_ptr = ispreszdefcoef.h_filter_coef_7tap;
	} else {
		if (coeffs != NULL)
			cf_ptr = coeffs->h_filter_coef_4tap;
		else
			cf_ptr = ispreszdefcoef.h_filter_coef_4tap;
	}

	for (ix = ISPRSZ_HFILT10; ix <= ISPRSZ_HFILT3130; ix += sizeof(u32)) {
		rval  = (*cf_ptr++ & ISPRSZ_HFILT_COEF0_MASK) <<
			ISPRSZ_HFILT_COEF0_SHIFT;
		rval |= (*cf_ptr++ & ISPRSZ_HFILT_COEF1_MASK) <<
			ISPRSZ_HFILT_COEF1_SHIFT;
		isp_reg_writel(dev, rval, OMAP3_ISP_IOMEM_RESZ, ix);
	}

	/* Init vertical filter coefficients */
	if (v_ratio > MID_RESIZE_VALUE) {
		if (coeffs != NULL)
			cf_ptr = coeffs->v_filter_coef_7tap;
		else
			cf_ptr = ispreszdefcoef.v_filter_coef_7tap;
	} else {
		if (coeffs != NULL)
			cf_ptr = coeffs->v_filter_coef_4tap;
		else
			cf_ptr = ispreszdefcoef.v_filter_coef_4tap;
	}

	for (ix = ISPRSZ_VFILT10; ix <= ISPRSZ_VFILT3130; ix += sizeof(u32)) {
		rval  = (*cf_ptr++ & ISPRSZ_VFILT_COEF0_MASK) <<
			ISPRSZ_VFILT_COEF0_SHIFT;
		rval |= (*cf_ptr++ & ISPRSZ_VFILT_COEF1_MASK) <<
			ISPRSZ_VFILT_COEF1_SHIFT;
		isp_reg_writel(dev, rval, OMAP3_ISP_IOMEM_RESZ, ix);
	}
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
void isp_reg_and_or(enum isp_mem_resources mmio_range, u32 reg,
				  u32 and_bits, u32 or_bits)
{
	u32 v = isp_reg_readl(mmio_range, reg);

	isp_reg_writel((v & and_bits) | or_bits, mmio_range, reg);
}
Exemplo n.º 11
0
Arquivo: isphist.c Projeto: 7799/linux
/*
 * hist_reset_mem - clear Histogram memory before start stats engine.
 */
static void hist_reset_mem(struct ispstat *hist)
{
	struct isp_device *isp = hist->isp;
	struct omap3isp_hist_config *conf = hist->priv;
	unsigned int i;

	isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);

	/*
	 * By setting it, the histogram internal buffer is being cleared at the
	 * same time it's being read. This bit must be cleared afterwards.
	 */
	isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);

	/*
	 * We'll clear 4 words at each iteration for optimization. It avoids
	 * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4.
	 */
	for (i = OMAP3ISP_HIST_MEM_SIZE / 4; i > 0; i--) {
		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
	}
	isp_reg_clr(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);

	hist->wait_acc_frames = conf->num_acc_frames;
}
Exemplo n.º 12
0
/*
 * csi2_recv_config - CSI2 receiver module configuration.
 * @currctrl: isp_csi2_ctrl_cfg structure
 *
 */
static void csi2_recv_config(struct isp_device *isp,
                             struct isp_csi2_device *csi2,
                             struct isp_csi2_ctrl_cfg *currctrl)
{
    u32 reg;

    reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTRL);

    if (currctrl->frame_mode)
        reg |= ISPCSI2_CTRL_FRAME;
    else
        reg &= ~ISPCSI2_CTRL_FRAME;

    if (currctrl->vp_clk_enable)
        reg |= ISPCSI2_CTRL_VP_CLK_EN;
    else
        reg &= ~ISPCSI2_CTRL_VP_CLK_EN;

    if (currctrl->vp_only_enable)
        reg |= ISPCSI2_CTRL_VP_ONLY_EN;
    else
        reg &= ~ISPCSI2_CTRL_VP_ONLY_EN;

    reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
    reg |= currctrl->vp_out_ctrl << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;

    if (currctrl->ecc_enable)
        reg |= ISPCSI2_CTRL_ECC_EN;
    else
        reg &= ~ISPCSI2_CTRL_ECC_EN;

    isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTRL);
}
Exemplo n.º 13
0
/*
 * csi2_ctx_enable - Enable specified CSI2 context
 * @ctxnum: Context number, valid between 0 and 7 values.
 * @enable: enable
 *
 */
static void csi2_ctx_enable(struct isp_device *isp,
                            struct isp_csi2_device *csi2, u8 ctxnum, u8 enable)
{
    struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
    unsigned int skip = 0;
    u32 reg;

    reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));

    if (enable) {
        if (csi2->frame_skip)
            skip = csi2->frame_skip;
        else if (csi2->output & CSI2_OUTPUT_MEMORY)
            skip = 1;

        reg &= ~ISPCSI2_CTX_CTRL1_COUNT_MASK;
        reg |= ISPCSI2_CTX_CTRL1_COUNT_UNLOCK
               |  (skip << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
               |  ISPCSI2_CTX_CTRL1_CTX_EN;
    } else {
        reg &= ~ISPCSI2_CTX_CTRL1_CTX_EN;
    }

    isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
    ctx->enabled = enable;
}
Exemplo n.º 14
0
/**
 * ispresizer_set_inaddr - Sets the memory address of the input frame.
 * @addr: 32bit memory address aligned on 32byte boundary.
 * @offset: Starting offset.
 *
 * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
 **/
int ispresizer_set_inaddr(struct isp_res_device *isp_res, u32 addr,
			  struct isp_node *pipe)
{
	struct device *dev = to_device(isp_res);
	u32 in_buf_plus_offs = 0;

	if (addr % 32)
		return -EINVAL;

	isp_res->in_buff_addr = addr;
	if (pipe != NULL) {
		dev_dbg(dev, "%s: In crop top: %d[%d] left: %d[%d]\n", __func__,
			isp_res->phy_rect.top, pipe->in.crop.top,
			isp_res->phy_rect.left, pipe->in.crop.left);
		/* Calculate additional part to prepare crop offsets */
		in_buf_plus_offs = ((isp_res->phy_rect.top *
				     (pipe->in.image.bytesperline / 2) +
				     (isp_res->phy_rect.left & ~0xf)) *
				    ISP_BYTES_PER_PIXEL);

		/* Set the fractional part of the crop */
		ispresizer_set_start(dev, isp_res->phy_rect.left & 0xf, 0);

		dev_dbg(dev, "%s: In address offs: 0x%08X\n", __func__,
			in_buf_plus_offs);
	}

	isp_reg_writel(dev, isp_res->in_buff_addr + in_buf_plus_offs,
		       OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);

	dev_dbg(dev, "%s: In address base: 0x%08X\n", __func__, addr);

	return 0;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
static int hist_buf_pio(struct ispstat *hist)
{
    struct isp_device *isp = hist->isp;
    u32 *buf = hist->active_buf->virt_addr;
    unsigned int i;

    if (!buf) {
        dev_dbg(isp->dev, "hist: invalid PIO buffer address\n");
        hist_reset_mem(hist);
        return STAT_NO_BUF;
    }

    isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);

    isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);

    for (i = hist->buf_size / 16; i > 0; i--) {
        *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
        *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
        *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
        *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
    }
    isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
                ISPHIST_CNT_CLEAR);

    return STAT_BUF_DONE;
}
Exemplo n.º 17
0
/*
 * csi2_timing_config - CSI2 timing configuration.
 * @timing: csi2_timing_cfg structure
 */
static void csi2_timing_config(struct isp_device *isp,
                               struct isp_csi2_device *csi2,
                               struct isp_csi2_timing_cfg *timing)
{
    u32 reg;

    reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_TIMING);

    if (timing->force_rx_mode)
        reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
    else
        reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);

    if (timing->stop_state_16x)
        reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
    else
        reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);

    if (timing->stop_state_4x)
        reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
    else
        reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);

    reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(timing->ionum);
    reg |= timing->stop_state_counter <<
           ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(timing->ionum);

    isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_TIMING);
}
Exemplo n.º 18
0
/**
 * isph3a_aewb_update_regs - Helper function to update h3a registers.
 **/
static void isph3a_aewb_update_regs(struct isp_h3a_device *isp_h3a)
{
	u32 pcr;

	if (!isp_h3a->update)
		return;

	pcr = isp_reg_readl(isp_h3a->dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
	isp_reg_writel(isp_h3a->dev, (pcr & ~ISPH3A_PCR_AEW_MASK) |
				     (isp_h3a->regs.pcr & ~ISPH3A_PCR_AEW_EN),
		       OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
	if (!isp_h3a->aewb_config_local.aewb_enable)
		return;

	if (isph3a_aewb_busy(isp_h3a)) {
		isp_reg_writel(isp_h3a->dev, (pcr & ~ISPH3A_PCR_AEW_MASK) |
					     isp_h3a->regs.pcr,
			       OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
		return;
	}

	isp_reg_writel(isp_h3a->dev, isp_h3a->regs.win1, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWWIN1);
	isp_reg_writel(isp_h3a->dev, isp_h3a->regs.start, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWINSTART);
	isp_reg_writel(isp_h3a->dev, isp_h3a->regs.blk, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWINBLK);
	isp_reg_writel(isp_h3a->dev, isp_h3a->regs.subwin, OMAP3_ISP_IOMEM_H3A,
		       ISPH3A_AEWSUBWIN);
	isp_reg_writel(isp_h3a->dev, (pcr & ~ISPH3A_PCR_AEW_MASK) |
				     isp_h3a->regs.pcr,
		       OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);

	isp_h3a->update = 0;
}
Exemplo n.º 19
0
Arquivo: isp.c Projeto: Antyks/linux
/*
 * isp_enable_interrupts - Enable ISP interrupts.
 * @isp: OMAP3 ISP device
 */
static void isp_enable_interrupts(struct isp_device *isp)
{
	static const u32 irq = IRQ0ENABLE_CSIA_IRQ
			     | IRQ0ENABLE_CSIB_IRQ
			     | IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ
			     | IRQ0ENABLE_CCDC_LSC_DONE_IRQ
			     | IRQ0ENABLE_CCDC_VD0_IRQ
			     | IRQ0ENABLE_CCDC_VD1_IRQ
			     | IRQ0ENABLE_HS_VS_IRQ
			     | IRQ0ENABLE_HIST_DONE_IRQ
			     | IRQ0ENABLE_H3A_AWB_DONE_IRQ
			     | IRQ0ENABLE_H3A_AF_DONE_IRQ
			     | IRQ0ENABLE_PRV_DONE_IRQ
			     | IRQ0ENABLE_RSZ_DONE_IRQ;

	isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
	isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
}
Exemplo n.º 20
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);
}
Exemplo n.º 21
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;
}
Exemplo n.º 22
0
/**
 * 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;
}
Exemplo n.º 23
0
/**
 * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
 * @fpc: Structure containing the number of faulty pixels corrected in the
 *       frame, address of the FPC table.
 *
 * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
 * boundary.
 **/
int ispccdc_config_fpc(struct ispccdc_fpc fpc)
{
	u32 fpc_val = 0;

	fpc_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);

	if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
		isp_reg_writel(fpc_val & (~ISPCCDC_FPC_FPCEN),
			       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
		isp_reg_writel(fpc.fpcaddr,
			       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
	} else {
		DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
		return -EINVAL;
	}
	isp_reg_writel(fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
	return 0;
}
Exemplo n.º 24
0
/**
 * ispccdc_config_culling - Configures the culling parameters.
 * @cull: Structure containing the vertical culling pattern, and horizontal
 *        culling pattern for odd and even lines.
 **/
void ispccdc_config_culling(struct ispccdc_culling cull)
{
	u32 culling_val = 0;

	culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
	culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
	culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;

	isp_reg_writel(culling_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING);
}
Exemplo n.º 25
0
static int hist_buf_dma(struct ispstat *hist)
{
	dma_addr_t dma_addr = hist->active_buf->dma_addr;
	struct dma_async_tx_descriptor *tx;
	struct dma_slave_config cfg;
	dma_cookie_t cookie;
	int ret;

	if (unlikely(!dma_addr)) {
		dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
		goto error;
	}

	isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
	isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
		    ISPHIST_CNT_CLEAR);
	omap3isp_flush(hist->isp);

	memset(&cfg, 0, sizeof(cfg));
	cfg.src_addr = hist->isp->mmio_hist_base_phys + ISPHIST_DATA;
	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	cfg.src_maxburst = hist->buf_size / 4;

	ret = dmaengine_slave_config(hist->dma_ch, &cfg);
	if (ret < 0) {
		dev_dbg(hist->isp->dev,
			"hist: DMA slave configuration failed\n");
		goto error;
	}

	tx = dmaengine_prep_slave_single(hist->dma_ch, dma_addr,
					 hist->buf_size, DMA_DEV_TO_MEM,
					 DMA_CTRL_ACK);
	if (tx == NULL) {
		dev_dbg(hist->isp->dev,
			"hist: DMA slave preparation failed\n");
		goto error;
	}

	tx->callback = hist_dma_cb;
	tx->callback_param = hist;
	cookie = tx->tx_submit(tx);
	if (dma_submit_error(cookie)) {
		dev_dbg(hist->isp->dev, "hist: DMA submission failed\n");
		goto error;
	}

	dma_async_issue_pending(hist->dma_ch);

	return STAT_BUF_WAITING_DMA;

error:
	hist_reset_mem(hist);
	return STAT_NO_BUF;
}
Exemplo n.º 26
0
/**
 * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
 * @blcomp: Structure containing the black level compensation value for RGrGbB
 *          pixels. in 2's complement.
 **/
void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp)
{
	u32 blcomp_val = 0;

	blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
	blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
	blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
	blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;

	isp_reg_writel(blcomp_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
}
Exemplo n.º 27
0
/*
 * csi2_irq_status_set - Enables CSI2 Status IRQs.
 * @enable: Enable/disable CSI2 Status interrupts
 */
static void csi2_irq_status_set(struct isp_device *isp,
                                struct isp_csi2_device *csi2, int enable)
{
    u32 reg;
    reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
          ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
          ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
          ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
          ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
          ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
          ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
          ISPCSI2_IRQSTATUS_CONTEXT(0);
    isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQSTATUS);
    if (enable)
        reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQENABLE);
    else
        reg = 0;

    isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQENABLE);
}
Exemplo n.º 28
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;
}
Exemplo n.º 29
0
static void __ispstat_pcr_enable(struct ispstat *stat, u8 pcr_enable)
{
	u32 pcr = isp_reg_readl(stat->isp, stat->pcr->base,
				stat->pcr->offset);

	if (pcr_enable)
		pcr |= stat->pcr->enable;
	else
		pcr &= ~stat->pcr->enable;
	isp_reg_writel(stat->isp, pcr, stat->pcr->base, stat->pcr->offset);
}
Exemplo n.º 30
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);
}