Загрузка данных


int flexio_capture_hw_disable(struct imx_flexio_capture_dev *fcam)
{
	disable_irq(fcam->hw.irq);
	flexio_capture_enable_rx_dma(fcam, 0);
	dmaengine_terminate_sync(fcam->hw.dma);

	fcam->hw.ctrl.flexen = false;
	flexio_setup_ctrl(fcam->hw.base, &fcam->hw.ctrl, CTRL);

	flexio_writel(fcam->hw.base, 1UL << FLEXIO_TIMER_IDX, TIMSTAT);
	flexio_capture_clear_status_flag(fcam);

	return 0;
}

static irqreturn_t flexio_capture_vsync_irq(int irq, void *dev)
{
	struct imx_flexio_capture_dev *fcam = dev;
	struct flexio_capture_buffer *buf, *prev;
	unsigned long flags;

	/* Why is it needed?
	 * Because sensor might start not in sync with flexio (ov7670 case)
	 * and in this case we have to align them manually.
	 * Hopefully, in normal case all data already captured, so
	 * it seems safe anyway.
	 */
	dmaengine_terminate_all(fcam->hw.dma);

	flexio_capture_clear_status_flag(fcam);

	spin_lock_irqsave(&fcam->pipe.buf_lock, flags);
	prev = fcam->pipe.active;
	buf = list_first_entry_or_null(&fcam->pipe.pending,
				       struct flexio_capture_buffer, list);
	fcam->pipe.active = buf;
	if (buf)
		list_del_init(&buf->list);
	spin_unlock_irqrestore(&fcam->pipe.buf_lock, flags);

	if (prev)
		vb2_buffer_done(&prev->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE);

	flexio_capture_dma_submit(fcam);

	return IRQ_HANDLED;
}

int flexio_capture_hw_probe(struct imx_flexio_capture_dev *fcam)
{
	struct flexio_ddata *ddata = dev_get_drvdata(fcam->dev->parent);
	struct device_node *of_node = fcam->dev->of_node;
	long irqflags = IRQF_ONESHOT;
	int err, irq;

	if (IS_ERR_OR_NULL(ddata))
		return -EINVAL;

	fcam->hw.base = ddata->base;
	fcam->hw.src_addr = ddata->phy_addr;
	if (IS_ERR(fcam->hw.base))
		return PTR_ERR(fcam->hw.base);

	fcam->hw.clk = ddata->ipg_clk;
	if (IS_ERR(fcam->hw.clk)) {
		dev_err(fcam->dev, "missing imx flexio camera clock\n");
		return PTR_ERR(fcam->hw.clk);
	}

	err = of_property_read_u32(of_node, "pclk", &fcam->hw.pclk_pin);
	if (err < 0) {
		dev_err(fcam->dev, "no pclk property found\n");
		return err;
	}
	err = of_property_read_u32(of_node, "href", &fcam->hw.href_pin);
	if (err < 0) {
		dev_err(fcam->dev, "no href property found\n");
		return err;
	}

	irq = platform_get_irq(to_platform_device(fcam->dev), 0);
	if (irq < 0)
		return irq;

	fcam->hw.irq = irq;
	if (fcam->pipe.buscfg.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
		irqflags |= IRQF_TRIGGER_RISING;
	else
		irqflags |= IRQF_TRIGGER_FALLING;
	err = devm_request_irq(fcam->dev, irq, flexio_capture_vsync_irq,
			       irqflags, dev_name(fcam->dev), fcam);
	if (err < 0) {
		dev_err(fcam->dev, "failed to request IRQ (%d)\n", err);
		return err;
	}

	disable_irq(irq);

	fcam->hw.dma = dma_request_chan(fcam->dev->parent, "flexio_dma");
	if (IS_ERR(fcam->hw.dma)) {
		err = PTR_ERR(fcam->hw.dma);
		dev_err(fcam->dev, "can't get the RX FlexIO DMA channel, error %d\n", err);
		fcam->hw.dma = NULL;
		return err;
	}

	clk_set_rate(fcam->hw.clk, FLEXIO_CLK_RATE);
	clk_prepare_enable(fcam->hw.clk);

	return 0;
};

void flexio_capture_hw_remove(struct imx_flexio_capture_dev *fcam)
{
	dma_release_channel(fcam->hw.dma);
	clk_disable_unprepare(fcam->hw.clk);
}