コード例 #1
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;
}
コード例 #2
0
ファイル: isphist.c プロジェクト: zhengsjgoembed/335x-b4
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;
}
コード例 #3
0
static void hist_dma_cb(int lch, u16 ch_status, void *data)
{
    struct ispstat *hist = data;

    if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
        dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
                ch_status);
        omap_stop_dma(lch);
        hist_reset_mem(hist);
        atomic_set(&hist->buf_err, 1);
    }
    isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
                ISPHIST_CNT_CLEAR);

    omap3isp_stat_dma_isr(hist);
    if (hist->state != ISPSTAT_DISABLED)
        omap3isp_hist_dma_done(hist->isp);
}
コード例 #4
0
static int hist_buf_process(struct ispstat *hist)
{
    struct omap3isp_hist_config *user_cfg = hist->priv;
    int ret;

    if (atomic_read(&hist->buf_err) || hist->state != ISPSTAT_ENABLED) {
        hist_reset_mem(hist);
        return STAT_NO_BUF;
    }

    if (--(hist->wait_acc_frames))
        return STAT_NO_BUF;

    if (HIST_USING_DMA(hist))
        ret = hist_buf_dma(hist);
    else
        ret = hist_buf_pio(hist);

    hist->wait_acc_frames = user_cfg->num_acc_frames;

    return ret;
}
コード例 #5
0
static int hist_buf_dma(struct ispstat *hist)
{
    dma_addr_t dma_addr = hist->active_buf->dma_addr;

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

    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);
    hist->dma_config.dst_start = dma_addr;
    hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
    omap_set_dma_params(hist->dma_ch, &hist->dma_config);

    omap_start_dma(hist->dma_ch);

    return STAT_BUF_WAITING_DMA;
}
コード例 #6
0
ファイル: isphist.c プロジェクト: 7799/linux
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);

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

	/*
	 * We'll read 4 times a 4-bytes-word at each iteration for
	 * optimization. It avoids 3/4 of the jumps. We also know buf_size is
	 * divisible by 16.
	 */
	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;
}
コード例 #7
0
static void hist_setup_regs(struct ispstat *hist, void *priv)
{
    struct isp_device *isp = hist->isp;
    struct omap3isp_hist_config *conf = priv;
    int c;
    u32 cnt;
    u32 wb_gain;
    u32 reg_hor[OMAP3ISP_HIST_MAX_REGIONS];
    u32 reg_ver[OMAP3ISP_HIST_MAX_REGIONS];

    if (!hist->update || hist->state == ISPSTAT_DISABLED ||
            hist->state == ISPSTAT_DISABLING)
        return;

    cnt = conf->cfa << ISPHIST_CNT_CFA_SHIFT;

    wb_gain = conf->wg[0] << ISPHIST_WB_GAIN_WG00_SHIFT;
    wb_gain |= conf->wg[1] << ISPHIST_WB_GAIN_WG01_SHIFT;
    wb_gain |= conf->wg[2] << ISPHIST_WB_GAIN_WG02_SHIFT;
    if (conf->cfa == OMAP3ISP_HIST_CFA_BAYER)
        wb_gain |= conf->wg[3] << ISPHIST_WB_GAIN_WG03_SHIFT;


    for (c = 0; c < OMAP3ISP_HIST_MAX_REGIONS; c++) {
        if (c < conf->num_regions) {
            reg_hor[c] = conf->region[c].h_start <<
                         ISPHIST_REG_START_SHIFT;
            reg_hor[c] = conf->region[c].h_end <<
                         ISPHIST_REG_END_SHIFT;
            reg_ver[c] = conf->region[c].v_start <<
                         ISPHIST_REG_START_SHIFT;
            reg_ver[c] = conf->region[c].v_end <<
                         ISPHIST_REG_END_SHIFT;
        } else {
            reg_hor[c] = 0;
            reg_ver[c] = 0;
        }
    }

    cnt |= conf->hist_bins << ISPHIST_CNT_BINS_SHIFT;
    switch (conf->hist_bins) {
    case OMAP3ISP_HIST_BINS_256:
        cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 8) <<
               ISPHIST_CNT_SHIFT_SHIFT;
        break;
    case OMAP3ISP_HIST_BINS_128:
        cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 7) <<
               ISPHIST_CNT_SHIFT_SHIFT;
        break;
    case OMAP3ISP_HIST_BINS_64:
        cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 6) <<
               ISPHIST_CNT_SHIFT_SHIFT;
        break;
    default:
        cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 5) <<
               ISPHIST_CNT_SHIFT_SHIFT;
        break;
    }

    hist_reset_mem(hist);

    isp_reg_writel(isp, cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
    isp_reg_writel(isp, wb_gain,  OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN);
    isp_reg_writel(isp, reg_hor[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ);
    isp_reg_writel(isp, reg_ver[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT);
    isp_reg_writel(isp, reg_hor[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ);
    isp_reg_writel(isp, reg_ver[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT);
    isp_reg_writel(isp, reg_hor[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ);
    isp_reg_writel(isp, reg_ver[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT);
    isp_reg_writel(isp, reg_hor[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ);
    isp_reg_writel(isp, reg_ver[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT);

    hist->update = 0;
    hist->config_counter += hist->inc_config;
    hist->inc_config = 0;
    hist->buf_size = conf->buf_size;
}