Lines Matching full:csi

3  * V4L2 Capture CSI Subdev for Freescale i.MX6UL/L / i.MX7 SOC
51 /* csi control reg 1 */
106 /* csi status reg */
126 /* csi image parameter reg */
130 /* csi control reg 18 */
284 static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset) in imx7_csi_reg_read() argument
286 return readl(csi->regbase + offset); in imx7_csi_reg_read()
289 static void imx7_csi_reg_write(struct imx7_csi *csi, unsigned int value, in imx7_csi_reg_write() argument
292 writel(value, csi->regbase + offset); in imx7_csi_reg_write()
295 static u32 imx7_csi_irq_clear(struct imx7_csi *csi) in imx7_csi_irq_clear() argument
299 isr = imx7_csi_reg_read(csi, CSI_CSISR); in imx7_csi_irq_clear()
300 imx7_csi_reg_write(csi, isr, CSI_CSISR); in imx7_csi_irq_clear()
305 static void imx7_csi_init_default(struct imx7_csi *csi) in imx7_csi_init_default() argument
307 imx7_csi_reg_write(csi, BIT_SOF_POL | BIT_REDGE | BIT_GCLK_MODE | in imx7_csi_init_default()
310 imx7_csi_reg_write(csi, 0, CSI_CSICR2); in imx7_csi_init_default()
311 imx7_csi_reg_write(csi, BIT_FRMCNT_RST, CSI_CSICR3); in imx7_csi_init_default()
313 imx7_csi_reg_write(csi, BIT_IMAGE_WIDTH(IMX7_CSI_DEF_PIX_WIDTH) | in imx7_csi_init_default()
317 imx7_csi_reg_write(csi, BIT_DMA_REFLASH_RFF, CSI_CSICR3); in imx7_csi_init_default()
320 static void imx7_csi_hw_enable_irq(struct imx7_csi *csi) in imx7_csi_hw_enable_irq() argument
322 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1); in imx7_csi_hw_enable_irq()
328 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_hw_enable_irq()
331 static void imx7_csi_hw_disable_irq(struct imx7_csi *csi) in imx7_csi_hw_disable_irq() argument
333 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1); in imx7_csi_hw_disable_irq()
339 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_hw_disable_irq()
342 static void imx7_csi_hw_enable(struct imx7_csi *csi) in imx7_csi_hw_enable() argument
344 u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_hw_enable()
348 imx7_csi_reg_write(csi, cr, CSI_CSICR18); in imx7_csi_hw_enable()
351 static void imx7_csi_hw_disable(struct imx7_csi *csi) in imx7_csi_hw_disable() argument
353 u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_hw_disable()
357 imx7_csi_reg_write(csi, cr, CSI_CSICR18); in imx7_csi_hw_disable()
360 static void imx7_csi_dma_reflash(struct imx7_csi *csi) in imx7_csi_dma_reflash() argument
364 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3); in imx7_csi_dma_reflash()
366 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_dma_reflash()
369 static void imx7_csi_rx_fifo_clear(struct imx7_csi *csi) in imx7_csi_rx_fifo_clear() argument
371 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1) & ~BIT_FCC; in imx7_csi_rx_fifo_clear()
373 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_rx_fifo_clear()
374 imx7_csi_reg_write(csi, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1); in imx7_csi_rx_fifo_clear()
375 imx7_csi_reg_write(csi, cr1 | BIT_FCC, CSI_CSICR1); in imx7_csi_rx_fifo_clear()
378 static void imx7_csi_dmareq_rff_enable(struct imx7_csi *csi) in imx7_csi_dmareq_rff_enable() argument
380 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3); in imx7_csi_dmareq_rff_enable()
387 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_dmareq_rff_enable()
390 static void imx7_csi_dmareq_rff_disable(struct imx7_csi *csi) in imx7_csi_dmareq_rff_disable() argument
392 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3); in imx7_csi_dmareq_rff_disable()
396 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_dmareq_rff_disable()
399 static void imx7_csi_update_buf(struct imx7_csi *csi, dma_addr_t dma_addr, in imx7_csi_update_buf() argument
403 imx7_csi_reg_write(csi, dma_addr, CSI_CSIDMASA_FB2); in imx7_csi_update_buf()
405 imx7_csi_reg_write(csi, dma_addr, CSI_CSIDMASA_FB1); in imx7_csi_update_buf()
408 static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi);
410 static void imx7_csi_setup_vb2_buf(struct imx7_csi *csi) in imx7_csi_setup_vb2_buf() argument
419 buf = imx7_csi_video_next_buf(csi); in imx7_csi_setup_vb2_buf()
421 csi->active_vb2_buf[i] = buf; in imx7_csi_setup_vb2_buf()
425 csi->active_vb2_buf[i] = NULL; in imx7_csi_setup_vb2_buf()
426 dma_addr = csi->underrun_buf.dma_addr; in imx7_csi_setup_vb2_buf()
429 imx7_csi_update_buf(csi, dma_addr, i); in imx7_csi_setup_vb2_buf()
433 static void imx7_csi_dma_unsetup_vb2_buf(struct imx7_csi *csi, in imx7_csi_dma_unsetup_vb2_buf() argument
441 buf = csi->active_vb2_buf[i]; in imx7_csi_dma_unsetup_vb2_buf()
447 csi->active_vb2_buf[i] = NULL; in imx7_csi_dma_unsetup_vb2_buf()
452 static void imx7_csi_free_dma_buf(struct imx7_csi *csi, in imx7_csi_free_dma_buf() argument
456 dma_free_coherent(csi->dev, buf->len, buf->virt, buf->dma_addr); in imx7_csi_free_dma_buf()
462 static int imx7_csi_alloc_dma_buf(struct imx7_csi *csi, in imx7_csi_alloc_dma_buf() argument
465 imx7_csi_free_dma_buf(csi, buf); in imx7_csi_alloc_dma_buf()
468 buf->virt = dma_alloc_coherent(csi->dev, buf->len, &buf->dma_addr, in imx7_csi_alloc_dma_buf()
476 static int imx7_csi_dma_setup(struct imx7_csi *csi) in imx7_csi_dma_setup() argument
480 ret = imx7_csi_alloc_dma_buf(csi, &csi->underrun_buf, in imx7_csi_dma_setup()
481 csi->vdev_fmt.sizeimage); in imx7_csi_dma_setup()
483 v4l2_warn(&csi->sd, "consider increasing the CMA area\n"); in imx7_csi_dma_setup()
487 csi->frame_sequence = 0; in imx7_csi_dma_setup()
488 csi->last_eof = false; in imx7_csi_dma_setup()
489 init_completion(&csi->last_eof_completion); in imx7_csi_dma_setup()
491 imx7_csi_setup_vb2_buf(csi); in imx7_csi_dma_setup()
496 static void imx7_csi_dma_cleanup(struct imx7_csi *csi, in imx7_csi_dma_cleanup() argument
499 imx7_csi_dma_unsetup_vb2_buf(csi, return_status); in imx7_csi_dma_cleanup()
500 imx7_csi_free_dma_buf(csi, &csi->underrun_buf); in imx7_csi_dma_cleanup()
503 static void imx7_csi_dma_stop(struct imx7_csi *csi) in imx7_csi_dma_stop() argument
510 spin_lock_irqsave(&csi->irqlock, flags); in imx7_csi_dma_stop()
511 csi->last_eof = true; in imx7_csi_dma_stop()
512 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_dma_stop()
518 ret = wait_for_completion_timeout(&csi->last_eof_completion, in imx7_csi_dma_stop()
521 v4l2_warn(&csi->sd, "wait last EOF timeout\n"); in imx7_csi_dma_stop()
523 imx7_csi_hw_disable_irq(csi); in imx7_csi_dma_stop()
526 static void imx7_csi_configure(struct imx7_csi *csi, in imx7_csi_configure() argument
529 struct v4l2_pix_format *out_pix = &csi->vdev_fmt; in imx7_csi_configure()
535 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_configure()
547 if (!csi->is_csi2) { in imx7_csi_configure()
602 * The CSI bridge has a 16-bit input bus. Depending on the in imx7_csi_configure()
617 * The field controls the gasket between the CSI-2 receiver and in imx7_csi_configure()
618 * the CSI bridge. On i.MX7 and i.MX8MM, the field must be set in imx7_csi_configure()
637 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_configure()
638 imx7_csi_reg_write(csi, BIT_DMA_BURST_TYPE_RFF_INCR16, CSI_CSICR2); in imx7_csi_configure()
639 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_configure()
640 imx7_csi_reg_write(csi, cr18, CSI_CSICR18); in imx7_csi_configure()
642 imx7_csi_reg_write(csi, (width * out_pix->height) >> 2, CSI_CSIRXCNT); in imx7_csi_configure()
643 imx7_csi_reg_write(csi, BIT_IMAGE_WIDTH(width) | in imx7_csi_configure()
646 imx7_csi_reg_write(csi, stride, CSI_CSIFBUF_PARA); in imx7_csi_configure()
649 static int imx7_csi_init(struct imx7_csi *csi, in imx7_csi_init() argument
654 ret = clk_prepare_enable(csi->mclk); in imx7_csi_init()
658 imx7_csi_configure(csi, sd_state); in imx7_csi_init()
660 ret = imx7_csi_dma_setup(csi); in imx7_csi_init()
662 clk_disable_unprepare(csi->mclk); in imx7_csi_init()
669 static void imx7_csi_deinit(struct imx7_csi *csi, in imx7_csi_deinit() argument
672 imx7_csi_dma_cleanup(csi, return_status); in imx7_csi_deinit()
673 imx7_csi_init_default(csi); in imx7_csi_deinit()
674 imx7_csi_dmareq_rff_disable(csi); in imx7_csi_deinit()
675 clk_disable_unprepare(csi->mclk); in imx7_csi_deinit()
678 static void imx7_csi_baseaddr_switch_on_second_frame(struct imx7_csi *csi) in imx7_csi_baseaddr_switch_on_second_frame() argument
680 u32 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_baseaddr_switch_on_second_frame()
685 imx7_csi_reg_write(csi, cr18, CSI_CSICR18); in imx7_csi_baseaddr_switch_on_second_frame()
688 static void imx7_csi_enable(struct imx7_csi *csi) in imx7_csi_enable() argument
691 imx7_csi_rx_fifo_clear(csi); in imx7_csi_enable()
692 imx7_csi_dma_reflash(csi); in imx7_csi_enable()
697 imx7_csi_irq_clear(csi); in imx7_csi_enable()
698 imx7_csi_hw_enable_irq(csi); in imx7_csi_enable()
700 /* Enable the RxFIFO DMA and the CSI. */ in imx7_csi_enable()
701 imx7_csi_dmareq_rff_enable(csi); in imx7_csi_enable()
702 imx7_csi_hw_enable(csi); in imx7_csi_enable()
704 if (csi->model == IMX7_CSI_IMX8MQ) in imx7_csi_enable()
705 imx7_csi_baseaddr_switch_on_second_frame(csi); in imx7_csi_enable()
708 static void imx7_csi_disable(struct imx7_csi *csi) in imx7_csi_disable() argument
710 imx7_csi_dma_stop(csi); in imx7_csi_disable()
712 imx7_csi_dmareq_rff_disable(csi); in imx7_csi_disable()
714 imx7_csi_hw_disable_irq(csi); in imx7_csi_disable()
716 imx7_csi_hw_disable(csi); in imx7_csi_disable()
723 static void imx7_csi_error_recovery(struct imx7_csi *csi) in imx7_csi_error_recovery() argument
725 imx7_csi_hw_disable(csi); in imx7_csi_error_recovery()
727 imx7_csi_rx_fifo_clear(csi); in imx7_csi_error_recovery()
729 imx7_csi_dma_reflash(csi); in imx7_csi_error_recovery()
731 imx7_csi_hw_enable(csi); in imx7_csi_error_recovery()
734 static void imx7_csi_vb2_buf_done(struct imx7_csi *csi) in imx7_csi_vb2_buf_done() argument
740 done = csi->active_vb2_buf[csi->buf_num]; in imx7_csi_vb2_buf_done()
742 done->vbuf.field = csi->vdev_fmt.field; in imx7_csi_vb2_buf_done()
743 done->vbuf.sequence = csi->frame_sequence; in imx7_csi_vb2_buf_done()
748 csi->frame_sequence++; in imx7_csi_vb2_buf_done()
751 next = imx7_csi_video_next_buf(csi); in imx7_csi_vb2_buf_done()
754 csi->active_vb2_buf[csi->buf_num] = next; in imx7_csi_vb2_buf_done()
756 dma_addr = csi->underrun_buf.dma_addr; in imx7_csi_vb2_buf_done()
757 csi->active_vb2_buf[csi->buf_num] = NULL; in imx7_csi_vb2_buf_done()
760 imx7_csi_update_buf(csi, dma_addr, csi->buf_num); in imx7_csi_vb2_buf_done()
765 struct imx7_csi *csi = data; in imx7_csi_irq_handler() local
768 spin_lock(&csi->irqlock); in imx7_csi_irq_handler()
770 status = imx7_csi_irq_clear(csi); in imx7_csi_irq_handler()
773 dev_warn(csi->dev, "Rx fifo overflow\n"); in imx7_csi_irq_handler()
774 imx7_csi_error_recovery(csi); in imx7_csi_irq_handler()
778 dev_warn(csi->dev, "Hresponse error detected\n"); in imx7_csi_irq_handler()
779 imx7_csi_error_recovery(csi); in imx7_csi_irq_handler()
783 imx7_csi_hw_disable(csi); in imx7_csi_irq_handler()
785 imx7_csi_dma_reflash(csi); in imx7_csi_irq_handler()
787 imx7_csi_hw_enable(csi); in imx7_csi_irq_handler()
794 * CSI DMA is work in one of FB1 and FB2 buffer, in imx7_csi_irq_handler()
797 * when csi work in field0 and field1 will write to in imx7_csi_irq_handler()
801 csi->buf_num = 0; in imx7_csi_irq_handler()
803 csi->buf_num = 1; in imx7_csi_irq_handler()
808 imx7_csi_vb2_buf_done(csi); in imx7_csi_irq_handler()
810 if (csi->last_eof) { in imx7_csi_irq_handler()
811 complete(&csi->last_eof_completion); in imx7_csi_irq_handler()
812 csi->last_eof = false; in imx7_csi_irq_handler()
816 spin_unlock(&csi->irqlock); in imx7_csi_irq_handler()
834 * The CSI bridge can be configured to sample pixel components from the Rx queue
840 * As the CSI bridge can be interfaced with different IP blocks depending on the
846 * Example: i.MX8MM SoC integrates the CSI bridge with the Samsung CSIS CSI-2
847 * receiver which operates in dual pixel sampling mode. The CSI bridge should
849 * pixel sampling mode. When the CSI bridge is instead integrated on an i.MX7,
1041 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_querycap() local
1046 "platform:%s", dev_name(csi->dev)); in imx7_csi_video_querycap()
1123 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_g_fmt_vid_cap() local
1125 f->fmt.pix = csi->vdev_fmt; in imx7_csi_video_g_fmt_vid_cap()
1180 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_s_fmt_vid_cap() local
1183 if (vb2_is_busy(&csi->q)) { in imx7_csi_video_s_fmt_vid_cap()
1184 dev_err(csi->dev, "%s queue busy\n", __func__); in imx7_csi_video_s_fmt_vid_cap()
1188 cc = __imx7_csi_video_try_fmt(&f->fmt.pix, &csi->vdev_compose); in imx7_csi_video_s_fmt_vid_cap()
1190 csi->vdev_cc = cc; in imx7_csi_video_s_fmt_vid_cap()
1191 csi->vdev_fmt = f->fmt.pix; in imx7_csi_video_s_fmt_vid_cap()
1199 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_g_selection() local
1209 s->r = csi->vdev_compose; in imx7_csi_video_g_selection()
1219 s->r.width = csi->vdev_fmt.width; in imx7_csi_video_g_selection()
1220 s->r.height = csi->vdev_fmt.height; in imx7_csi_video_g_selection()
1262 struct imx7_csi *csi = vb2_get_drv_priv(vq); in imx7_csi_video_queue_setup() local
1264 struct v4l2_pix_format *pix = &csi->vdev_fmt; in imx7_csi_video_queue_setup()
1301 struct imx7_csi *csi = vb2_get_drv_priv(vb->vb2_queue); in imx7_csi_video_buf_prepare() local
1302 struct v4l2_pix_format *pix = &csi->vdev_fmt; in imx7_csi_video_buf_prepare()
1305 dev_err(csi->dev, in imx7_csi_video_buf_prepare()
1316 static bool imx7_csi_fast_track_buffer(struct imx7_csi *csi, in imx7_csi_fast_track_buffer() argument
1324 if (!csi->is_streaming) in imx7_csi_fast_track_buffer()
1358 spin_lock_irqsave(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1360 buf_num = csi->buf_num; in imx7_csi_fast_track_buffer()
1361 if (csi->active_vb2_buf[buf_num]) { in imx7_csi_fast_track_buffer()
1362 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1366 imx7_csi_update_buf(csi, dma_addr, buf_num); in imx7_csi_fast_track_buffer()
1368 isr = imx7_csi_reg_read(csi, CSI_CSISR); in imx7_csi_fast_track_buffer()
1379 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1383 csi->active_vb2_buf[buf_num] = buf; in imx7_csi_fast_track_buffer()
1385 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1391 struct imx7_csi *csi = vb2_get_drv_priv(vb->vb2_queue); in imx7_csi_video_buf_queue() local
1395 if (imx7_csi_fast_track_buffer(csi, buf)) in imx7_csi_video_buf_queue()
1398 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_buf_queue()
1400 list_add_tail(&buf->list, &csi->ready_q); in imx7_csi_video_buf_queue()
1402 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_buf_queue()
1405 static int imx7_csi_video_validate_fmt(struct imx7_csi *csi) in imx7_csi_video_validate_fmt() argument
1415 ret = v4l2_subdev_call_state_active(&csi->sd, pad, get_fmt, &fmt_src); in imx7_csi_video_validate_fmt()
1426 if (csi->vdev_compose.width != fmt_src.format.width || in imx7_csi_video_validate_fmt()
1427 csi->vdev_compose.height != fmt_src.format.height) in imx7_csi_video_validate_fmt()
1435 if (!cc || csi->vdev_cc->yuv != cc->yuv) in imx7_csi_video_validate_fmt()
1444 struct imx7_csi *csi = vb2_get_drv_priv(vq); in imx7_csi_video_start_streaming() local
1449 ret = imx7_csi_video_validate_fmt(csi); in imx7_csi_video_start_streaming()
1451 dev_err(csi->dev, "capture format not valid\n"); in imx7_csi_video_start_streaming()
1455 mutex_lock(&csi->mdev.graph_mutex); in imx7_csi_video_start_streaming()
1457 ret = __video_device_pipeline_start(csi->vdev, &csi->pipe); in imx7_csi_video_start_streaming()
1461 ret = v4l2_subdev_call(&csi->sd, video, s_stream, 1); in imx7_csi_video_start_streaming()
1465 mutex_unlock(&csi->mdev.graph_mutex); in imx7_csi_video_start_streaming()
1470 __video_device_pipeline_stop(csi->vdev); in imx7_csi_video_start_streaming()
1472 mutex_unlock(&csi->mdev.graph_mutex); in imx7_csi_video_start_streaming()
1473 dev_err(csi->dev, "pipeline start failed with %d\n", ret); in imx7_csi_video_start_streaming()
1475 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_start_streaming()
1476 list_for_each_entry_safe(buf, tmp, &csi->ready_q, list) { in imx7_csi_video_start_streaming()
1480 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_start_streaming()
1486 struct imx7_csi *csi = vb2_get_drv_priv(vq); in imx7_csi_video_stop_streaming() local
1491 mutex_lock(&csi->mdev.graph_mutex); in imx7_csi_video_stop_streaming()
1492 v4l2_subdev_call(&csi->sd, video, s_stream, 0); in imx7_csi_video_stop_streaming()
1493 __video_device_pipeline_stop(csi->vdev); in imx7_csi_video_stop_streaming()
1494 mutex_unlock(&csi->mdev.graph_mutex); in imx7_csi_video_stop_streaming()
1497 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_stop_streaming()
1498 list_for_each_entry_safe(frame, tmp, &csi->ready_q, list) { in imx7_csi_video_stop_streaming()
1502 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_stop_streaming()
1522 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_open() local
1525 if (mutex_lock_interruptible(&csi->vdev_mutex)) in imx7_csi_video_open()
1530 dev_err(csi->dev, "v4l2_fh_open failed\n"); in imx7_csi_video_open()
1534 ret = v4l2_pipeline_pm_get(&csi->vdev->entity); in imx7_csi_video_open()
1539 mutex_unlock(&csi->vdev_mutex); in imx7_csi_video_open()
1545 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_release() local
1546 struct vb2_queue *vq = &csi->q; in imx7_csi_video_release()
1548 mutex_lock(&csi->vdev_mutex); in imx7_csi_video_release()
1555 v4l2_pipeline_pm_put(&csi->vdev->entity); in imx7_csi_video_release()
1558 mutex_unlock(&csi->vdev_mutex); in imx7_csi_video_release()
1575 static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi) in imx7_csi_video_next_buf() argument
1580 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_next_buf()
1583 if (!list_empty(&csi->ready_q)) { in imx7_csi_video_next_buf()
1584 buf = list_entry(csi->ready_q.next, struct imx7_csi_vb2_buffer, in imx7_csi_video_next_buf()
1589 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_next_buf()
1594 static void imx7_csi_video_init_format(struct imx7_csi *csi) in imx7_csi_video_init_format() argument
1596 struct v4l2_pix_format *pixfmt = &csi->vdev_fmt; in imx7_csi_video_init_format()
1601 csi->vdev_cc = __imx7_csi_video_try_fmt(pixfmt, &csi->vdev_compose); in imx7_csi_video_init_format()
1604 static int imx7_csi_video_register(struct imx7_csi *csi) in imx7_csi_video_register() argument
1606 struct v4l2_subdev *sd = &csi->sd; in imx7_csi_video_register()
1608 struct video_device *vdev = csi->vdev; in imx7_csi_video_register()
1614 imx7_csi_video_init_format(csi); in imx7_csi_video_register()
1619 dev_err(csi->dev, "Failed to register video device\n"); in imx7_csi_video_register()
1623 dev_info(csi->dev, "Registered %s as /dev/%s\n", vdev->name, in imx7_csi_video_register()
1626 /* Create the link from the CSI subdev to the video device. */ in imx7_csi_video_register()
1631 dev_err(csi->dev, "failed to create link to device node\n"); in imx7_csi_video_register()
1639 static void imx7_csi_video_unregister(struct imx7_csi *csi) in imx7_csi_video_unregister() argument
1641 media_entity_cleanup(&csi->vdev->entity); in imx7_csi_video_unregister()
1642 video_unregister_device(csi->vdev); in imx7_csi_video_unregister()
1645 static int imx7_csi_video_init(struct imx7_csi *csi) in imx7_csi_video_init() argument
1651 mutex_init(&csi->vdev_mutex); in imx7_csi_video_init()
1652 INIT_LIST_HEAD(&csi->ready_q); in imx7_csi_video_init()
1653 spin_lock_init(&csi->q_lock); in imx7_csi_video_init()
1668 vdev->lock = &csi->vdev_mutex; in imx7_csi_video_init()
1669 vdev->queue = &csi->q; in imx7_csi_video_init()
1671 snprintf(vdev->name, sizeof(vdev->name), "%s capture", csi->sd.name); in imx7_csi_video_init()
1673 video_set_drvdata(vdev, csi); in imx7_csi_video_init()
1674 csi->vdev = vdev; in imx7_csi_video_init()
1677 csi->vdev_pad.flags = MEDIA_PAD_FL_SINK; in imx7_csi_video_init()
1678 ret = media_entity_pads_init(&vdev->entity, 1, &csi->vdev_pad); in imx7_csi_video_init()
1685 vq = &csi->q; in imx7_csi_video_init()
1688 vq->drv_priv = csi; in imx7_csi_video_init()
1693 vq->lock = &csi->vdev_mutex; in imx7_csi_video_init()
1695 vq->dev = csi->dev; in imx7_csi_video_init()
1699 dev_err(csi->dev, "vb2_queue_init failed\n"); in imx7_csi_video_init()
1713 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_s_stream() local
1720 ret = imx7_csi_init(csi, sd_state); in imx7_csi_s_stream()
1724 ret = v4l2_subdev_call(csi->src_sd, video, s_stream, 1); in imx7_csi_s_stream()
1726 imx7_csi_deinit(csi, VB2_BUF_STATE_QUEUED); in imx7_csi_s_stream()
1730 imx7_csi_enable(csi); in imx7_csi_s_stream()
1732 imx7_csi_disable(csi); in imx7_csi_s_stream()
1734 v4l2_subdev_call(csi->src_sd, video, s_stream, 0); in imx7_csi_s_stream()
1736 imx7_csi_deinit(csi, VB2_BUF_STATE_ERROR); in imx7_csi_s_stream()
1739 csi->is_streaming = !!enable; in imx7_csi_s_stream()
1898 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_set_fmt() local
1905 if (csi->is_streaming) in imx7_csi_set_fmt()
1934 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_pad_link_validate() local
1941 * parallel input or the CSI-2 receiver. in imx7_csi_pad_link_validate()
1947 switch (csi->src_sd->entity.function) { in imx7_csi_pad_link_validate()
1949 /* The input is the CSI-2 receiver. */ in imx7_csi_pad_link_validate()
1950 csi->is_csi2 = true; in imx7_csi_pad_link_validate()
1955 for (i = 0; i < csi->src_sd->entity.num_pads; i++) { in imx7_csi_pad_link_validate()
1956 struct media_pad *spad = &csi->src_sd->entity.pads[i]; in imx7_csi_pad_link_validate()
1969 csi->is_csi2 = pad->entity->function == MEDIA_ENT_F_VID_IF_BRIDGE; in imx7_csi_pad_link_validate()
1977 csi->is_csi2 = false; in imx7_csi_pad_link_validate()
1986 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_registered() local
1989 ret = imx7_csi_video_init(csi); in imx7_csi_registered()
1993 ret = imx7_csi_video_register(csi); in imx7_csi_registered()
1997 ret = v4l2_device_register_subdev_nodes(&csi->v4l2_dev); in imx7_csi_registered()
2001 ret = media_device_register(&csi->mdev); in imx7_csi_registered()
2008 imx7_csi_video_unregister(csi); in imx7_csi_registered()
2014 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_unregistered() local
2016 imx7_csi_video_unregister(csi); in imx7_csi_unregistered()
2058 struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); in imx7_csi_notify_bound() local
2059 struct media_pad *sink = &csi->sd.entity.pads[IMX7_CSI_PAD_SINK]; in imx7_csi_notify_bound()
2061 csi->src_sd = sd; in imx7_csi_notify_bound()
2069 struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); in imx7_csi_notify_complete() local
2071 return v4l2_device_register_subdev_nodes(&csi->v4l2_dev); in imx7_csi_notify_complete()
2079 static int imx7_csi_async_register(struct imx7_csi *csi) in imx7_csi_async_register() argument
2085 v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); in imx7_csi_async_register()
2087 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, in imx7_csi_async_register()
2090 ret = dev_err_probe(csi->dev, -ENOTCONN, in imx7_csi_async_register()
2095 asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep, in imx7_csi_async_register()
2101 ret = dev_err_probe(csi->dev, PTR_ERR(asd), in imx7_csi_async_register()
2106 csi->notifier.ops = &imx7_csi_notify_ops; in imx7_csi_async_register()
2108 ret = v4l2_async_nf_register(&csi->notifier); in imx7_csi_async_register()
2115 v4l2_async_nf_cleanup(&csi->notifier); in imx7_csi_async_register()
2119 static void imx7_csi_media_cleanup(struct imx7_csi *csi) in imx7_csi_media_cleanup() argument
2121 v4l2_device_unregister(&csi->v4l2_dev); in imx7_csi_media_cleanup()
2122 media_device_unregister(&csi->mdev); in imx7_csi_media_cleanup()
2123 v4l2_subdev_cleanup(&csi->sd); in imx7_csi_media_cleanup()
2124 media_device_cleanup(&csi->mdev); in imx7_csi_media_cleanup()
2131 static int imx7_csi_media_dev_init(struct imx7_csi *csi) in imx7_csi_media_dev_init() argument
2135 strscpy(csi->mdev.model, "imx-media", sizeof(csi->mdev.model)); in imx7_csi_media_dev_init()
2136 csi->mdev.ops = &imx7_csi_media_ops; in imx7_csi_media_dev_init()
2137 csi->mdev.dev = csi->dev; in imx7_csi_media_dev_init()
2139 csi->v4l2_dev.mdev = &csi->mdev; in imx7_csi_media_dev_init()
2140 strscpy(csi->v4l2_dev.name, "imx-media", in imx7_csi_media_dev_init()
2141 sizeof(csi->v4l2_dev.name)); in imx7_csi_media_dev_init()
2142 snprintf(csi->mdev.bus_info, sizeof(csi->mdev.bus_info), in imx7_csi_media_dev_init()
2143 "platform:%s", dev_name(csi->mdev.dev)); in imx7_csi_media_dev_init()
2145 media_device_init(&csi->mdev); in imx7_csi_media_dev_init()
2147 ret = v4l2_device_register(csi->dev, &csi->v4l2_dev); in imx7_csi_media_dev_init()
2149 v4l2_err(&csi->v4l2_dev, in imx7_csi_media_dev_init()
2157 media_device_cleanup(&csi->mdev); in imx7_csi_media_dev_init()
2162 static int imx7_csi_media_init(struct imx7_csi *csi) in imx7_csi_media_init() argument
2168 ret = imx7_csi_media_dev_init(csi); in imx7_csi_media_init()
2172 v4l2_subdev_init(&csi->sd, &imx7_csi_subdev_ops); in imx7_csi_media_init()
2173 v4l2_set_subdevdata(&csi->sd, csi); in imx7_csi_media_init()
2174 csi->sd.internal_ops = &imx7_csi_internal_ops; in imx7_csi_media_init()
2175 csi->sd.entity.ops = &imx7_csi_entity_ops; in imx7_csi_media_init()
2176 csi->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in imx7_csi_media_init()
2177 csi->sd.dev = csi->dev; in imx7_csi_media_init()
2178 csi->sd.owner = THIS_MODULE; in imx7_csi_media_init()
2179 csi->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; in imx7_csi_media_init()
2180 snprintf(csi->sd.name, sizeof(csi->sd.name), "csi"); in imx7_csi_media_init()
2183 csi->pad[i].flags = (i == IMX7_CSI_PAD_SINK) ? in imx7_csi_media_init()
2186 ret = media_entity_pads_init(&csi->sd.entity, IMX7_CSI_PADS_NUM, in imx7_csi_media_init()
2187 csi->pad); in imx7_csi_media_init()
2191 ret = v4l2_subdev_init_finalize(&csi->sd); in imx7_csi_media_init()
2195 ret = v4l2_device_register_subdev(&csi->v4l2_dev, &csi->sd); in imx7_csi_media_init()
2202 imx7_csi_media_cleanup(csi); in imx7_csi_media_init()
2209 struct imx7_csi *csi; in imx7_csi_probe() local
2212 csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL); in imx7_csi_probe()
2213 if (!csi) in imx7_csi_probe()
2216 csi->dev = dev; in imx7_csi_probe()
2217 platform_set_drvdata(pdev, csi); in imx7_csi_probe()
2219 spin_lock_init(&csi->irqlock); in imx7_csi_probe()
2222 csi->mclk = devm_clk_get(&pdev->dev, "mclk"); in imx7_csi_probe()
2223 if (IS_ERR(csi->mclk)) { in imx7_csi_probe()
2224 ret = PTR_ERR(csi->mclk); in imx7_csi_probe()
2229 csi->irq = platform_get_irq(pdev, 0); in imx7_csi_probe()
2230 if (csi->irq < 0) in imx7_csi_probe()
2231 return csi->irq; in imx7_csi_probe()
2233 csi->regbase = devm_platform_ioremap_resource(pdev, 0); in imx7_csi_probe()
2234 if (IS_ERR(csi->regbase)) in imx7_csi_probe()
2235 return PTR_ERR(csi->regbase); in imx7_csi_probe()
2237 csi->model = (enum imx_csi_model)(uintptr_t)of_device_get_match_data(&pdev->dev); in imx7_csi_probe()
2239 ret = devm_request_irq(dev, csi->irq, imx7_csi_irq_handler, 0, "csi", in imx7_csi_probe()
2240 (void *)csi); in imx7_csi_probe()
2242 dev_err(dev, "Request CSI IRQ failed.\n"); in imx7_csi_probe()
2247 ret = imx7_csi_media_init(csi); in imx7_csi_probe()
2251 ret = imx7_csi_async_register(csi); in imx7_csi_probe()
2258 imx7_csi_media_cleanup(csi); in imx7_csi_probe()
2265 struct imx7_csi *csi = platform_get_drvdata(pdev); in imx7_csi_remove() local
2267 imx7_csi_media_cleanup(csi); in imx7_csi_remove()
2269 v4l2_async_nf_unregister(&csi->notifier); in imx7_csi_remove()
2270 v4l2_async_nf_cleanup(&csi->notifier); in imx7_csi_remove()
2271 v4l2_async_unregister_subdev(&csi->sd); in imx7_csi_remove()
2275 { .compatible = "fsl,imx8mq-csi", .data = (void *)IMX7_CSI_IMX8MQ },
2276 { .compatible = "fsl,imx7-csi", .data = (void *)IMX7_CSI_IMX7 },
2277 { .compatible = "fsl,imx6ul-csi", .data = (void *)IMX7_CSI_IMX7 },
2287 .name = "imx7-csi",
2292 MODULE_DESCRIPTION("i.MX7 CSI subdev driver");
2295 MODULE_ALIAS("platform:imx7-csi");