Lines Matching full:csi

3  * V4L2 Capture CSI Subdev for Freescale i.MX6UL/L / i.MX7 SOC
36 /* csi control reg 1 */
91 /* csi status reg */
111 /* csi image parameter reg */
115 /* csi control reg 18 */
269 static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset) in imx7_csi_reg_read() argument
271 return readl(csi->regbase + offset); in imx7_csi_reg_read()
274 static void imx7_csi_reg_write(struct imx7_csi *csi, unsigned int value, in imx7_csi_reg_write() argument
277 writel(value, csi->regbase + offset); in imx7_csi_reg_write()
280 static u32 imx7_csi_irq_clear(struct imx7_csi *csi) in imx7_csi_irq_clear() argument
284 isr = imx7_csi_reg_read(csi, CSI_CSISR); in imx7_csi_irq_clear()
285 imx7_csi_reg_write(csi, isr, CSI_CSISR); in imx7_csi_irq_clear()
290 static void imx7_csi_init_default(struct imx7_csi *csi) in imx7_csi_init_default() argument
292 imx7_csi_reg_write(csi, BIT_SOF_POL | BIT_REDGE | BIT_GCLK_MODE | in imx7_csi_init_default()
295 imx7_csi_reg_write(csi, 0, CSI_CSICR2); in imx7_csi_init_default()
296 imx7_csi_reg_write(csi, BIT_FRMCNT_RST, CSI_CSICR3); in imx7_csi_init_default()
298 imx7_csi_reg_write(csi, BIT_IMAGE_WIDTH(IMX7_CSI_DEF_PIX_WIDTH) | in imx7_csi_init_default()
302 imx7_csi_reg_write(csi, BIT_DMA_REFLASH_RFF, CSI_CSICR3); in imx7_csi_init_default()
305 static void imx7_csi_hw_enable_irq(struct imx7_csi *csi) in imx7_csi_hw_enable_irq() argument
307 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1); in imx7_csi_hw_enable_irq()
313 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_hw_enable_irq()
316 static void imx7_csi_hw_disable_irq(struct imx7_csi *csi) in imx7_csi_hw_disable_irq() argument
318 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1); in imx7_csi_hw_disable_irq()
324 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_hw_disable_irq()
327 static void imx7_csi_hw_enable(struct imx7_csi *csi) in imx7_csi_hw_enable() argument
329 u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_hw_enable()
333 imx7_csi_reg_write(csi, cr, CSI_CSICR18); in imx7_csi_hw_enable()
336 static void imx7_csi_hw_disable(struct imx7_csi *csi) in imx7_csi_hw_disable() argument
338 u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_hw_disable()
342 imx7_csi_reg_write(csi, cr, CSI_CSICR18); in imx7_csi_hw_disable()
345 static void imx7_csi_dma_reflash(struct imx7_csi *csi) in imx7_csi_dma_reflash() argument
349 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3); in imx7_csi_dma_reflash()
351 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_dma_reflash()
354 static void imx7_csi_rx_fifo_clear(struct imx7_csi *csi) in imx7_csi_rx_fifo_clear() argument
356 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1) & ~BIT_FCC; in imx7_csi_rx_fifo_clear()
358 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_rx_fifo_clear()
359 imx7_csi_reg_write(csi, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1); in imx7_csi_rx_fifo_clear()
360 imx7_csi_reg_write(csi, cr1 | BIT_FCC, CSI_CSICR1); in imx7_csi_rx_fifo_clear()
363 static void imx7_csi_dmareq_rff_enable(struct imx7_csi *csi) in imx7_csi_dmareq_rff_enable() argument
365 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3); in imx7_csi_dmareq_rff_enable()
372 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_dmareq_rff_enable()
375 static void imx7_csi_dmareq_rff_disable(struct imx7_csi *csi) in imx7_csi_dmareq_rff_disable() argument
377 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3); in imx7_csi_dmareq_rff_disable()
381 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_dmareq_rff_disable()
384 static void imx7_csi_update_buf(struct imx7_csi *csi, dma_addr_t dma_addr, in imx7_csi_update_buf() argument
388 imx7_csi_reg_write(csi, dma_addr, CSI_CSIDMASA_FB2); in imx7_csi_update_buf()
390 imx7_csi_reg_write(csi, dma_addr, CSI_CSIDMASA_FB1); in imx7_csi_update_buf()
393 static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi);
395 static void imx7_csi_setup_vb2_buf(struct imx7_csi *csi) in imx7_csi_setup_vb2_buf() argument
404 buf = imx7_csi_video_next_buf(csi); in imx7_csi_setup_vb2_buf()
406 csi->active_vb2_buf[i] = buf; in imx7_csi_setup_vb2_buf()
410 csi->active_vb2_buf[i] = NULL; in imx7_csi_setup_vb2_buf()
411 dma_addr = csi->underrun_buf.dma_addr; in imx7_csi_setup_vb2_buf()
414 imx7_csi_update_buf(csi, dma_addr, i); in imx7_csi_setup_vb2_buf()
418 static void imx7_csi_dma_unsetup_vb2_buf(struct imx7_csi *csi, in imx7_csi_dma_unsetup_vb2_buf() argument
426 buf = csi->active_vb2_buf[i]; in imx7_csi_dma_unsetup_vb2_buf()
432 csi->active_vb2_buf[i] = NULL; in imx7_csi_dma_unsetup_vb2_buf()
437 static void imx7_csi_free_dma_buf(struct imx7_csi *csi, in imx7_csi_free_dma_buf() argument
441 dma_free_coherent(csi->dev, buf->len, buf->virt, buf->dma_addr); in imx7_csi_free_dma_buf()
447 static int imx7_csi_alloc_dma_buf(struct imx7_csi *csi, in imx7_csi_alloc_dma_buf() argument
450 imx7_csi_free_dma_buf(csi, buf); in imx7_csi_alloc_dma_buf()
453 buf->virt = dma_alloc_coherent(csi->dev, buf->len, &buf->dma_addr, in imx7_csi_alloc_dma_buf()
461 static int imx7_csi_dma_setup(struct imx7_csi *csi) in imx7_csi_dma_setup() argument
465 ret = imx7_csi_alloc_dma_buf(csi, &csi->underrun_buf, in imx7_csi_dma_setup()
466 csi->vdev_fmt.sizeimage); in imx7_csi_dma_setup()
468 v4l2_warn(&csi->sd, "consider increasing the CMA area\n"); in imx7_csi_dma_setup()
472 csi->frame_sequence = 0; in imx7_csi_dma_setup()
473 csi->last_eof = false; in imx7_csi_dma_setup()
474 init_completion(&csi->last_eof_completion); in imx7_csi_dma_setup()
476 imx7_csi_setup_vb2_buf(csi); in imx7_csi_dma_setup()
481 static void imx7_csi_dma_cleanup(struct imx7_csi *csi, in imx7_csi_dma_cleanup() argument
484 imx7_csi_dma_unsetup_vb2_buf(csi, return_status); in imx7_csi_dma_cleanup()
485 imx7_csi_free_dma_buf(csi, &csi->underrun_buf); in imx7_csi_dma_cleanup()
488 static void imx7_csi_dma_stop(struct imx7_csi *csi) in imx7_csi_dma_stop() argument
495 spin_lock_irqsave(&csi->irqlock, flags); in imx7_csi_dma_stop()
496 csi->last_eof = true; in imx7_csi_dma_stop()
497 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_dma_stop()
503 ret = wait_for_completion_timeout(&csi->last_eof_completion, in imx7_csi_dma_stop()
506 v4l2_warn(&csi->sd, "wait last EOF timeout\n"); in imx7_csi_dma_stop()
508 imx7_csi_hw_disable_irq(csi); in imx7_csi_dma_stop()
511 static void imx7_csi_configure(struct imx7_csi *csi, in imx7_csi_configure() argument
514 struct v4l2_pix_format *out_pix = &csi->vdev_fmt; in imx7_csi_configure()
520 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_configure()
532 if (!csi->is_csi2) { in imx7_csi_configure()
545 sink_fmt = v4l2_subdev_get_pad_format(&csi->sd, sd_state, in imx7_csi_configure()
587 * The CSI bridge has a 16-bit input bus. Depending on the in imx7_csi_configure()
602 * The field controls the gasket between the CSI-2 receiver and in imx7_csi_configure()
603 * the CSI bridge. On i.MX7 and i.MX8MM, the field must be set in imx7_csi_configure()
622 imx7_csi_reg_write(csi, cr1, CSI_CSICR1); in imx7_csi_configure()
623 imx7_csi_reg_write(csi, BIT_DMA_BURST_TYPE_RFF_INCR16, CSI_CSICR2); in imx7_csi_configure()
624 imx7_csi_reg_write(csi, cr3, CSI_CSICR3); in imx7_csi_configure()
625 imx7_csi_reg_write(csi, cr18, CSI_CSICR18); in imx7_csi_configure()
627 imx7_csi_reg_write(csi, (width * out_pix->height) >> 2, CSI_CSIRXCNT); in imx7_csi_configure()
628 imx7_csi_reg_write(csi, BIT_IMAGE_WIDTH(width) | in imx7_csi_configure()
631 imx7_csi_reg_write(csi, stride, CSI_CSIFBUF_PARA); in imx7_csi_configure()
634 static int imx7_csi_init(struct imx7_csi *csi, in imx7_csi_init() argument
639 ret = clk_prepare_enable(csi->mclk); in imx7_csi_init()
643 imx7_csi_configure(csi, sd_state); in imx7_csi_init()
645 ret = imx7_csi_dma_setup(csi); in imx7_csi_init()
647 clk_disable_unprepare(csi->mclk); in imx7_csi_init()
654 static void imx7_csi_deinit(struct imx7_csi *csi, in imx7_csi_deinit() argument
657 imx7_csi_dma_cleanup(csi, return_status); in imx7_csi_deinit()
658 imx7_csi_init_default(csi); in imx7_csi_deinit()
659 imx7_csi_dmareq_rff_disable(csi); in imx7_csi_deinit()
660 clk_disable_unprepare(csi->mclk); in imx7_csi_deinit()
663 static void imx7_csi_baseaddr_switch_on_second_frame(struct imx7_csi *csi) in imx7_csi_baseaddr_switch_on_second_frame() argument
665 u32 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18); in imx7_csi_baseaddr_switch_on_second_frame()
670 imx7_csi_reg_write(csi, cr18, CSI_CSICR18); in imx7_csi_baseaddr_switch_on_second_frame()
673 static void imx7_csi_enable(struct imx7_csi *csi) in imx7_csi_enable() argument
676 imx7_csi_rx_fifo_clear(csi); in imx7_csi_enable()
677 imx7_csi_dma_reflash(csi); in imx7_csi_enable()
682 imx7_csi_irq_clear(csi); in imx7_csi_enable()
683 imx7_csi_hw_enable_irq(csi); in imx7_csi_enable()
685 /* Enable the RxFIFO DMA and the CSI. */ in imx7_csi_enable()
686 imx7_csi_dmareq_rff_enable(csi); in imx7_csi_enable()
687 imx7_csi_hw_enable(csi); in imx7_csi_enable()
689 if (csi->model == IMX7_CSI_IMX8MQ) in imx7_csi_enable()
690 imx7_csi_baseaddr_switch_on_second_frame(csi); in imx7_csi_enable()
693 static void imx7_csi_disable(struct imx7_csi *csi) in imx7_csi_disable() argument
695 imx7_csi_dma_stop(csi); in imx7_csi_disable()
697 imx7_csi_dmareq_rff_disable(csi); in imx7_csi_disable()
699 imx7_csi_hw_disable_irq(csi); in imx7_csi_disable()
701 imx7_csi_hw_disable(csi); in imx7_csi_disable()
708 static void imx7_csi_error_recovery(struct imx7_csi *csi) in imx7_csi_error_recovery() argument
710 imx7_csi_hw_disable(csi); in imx7_csi_error_recovery()
712 imx7_csi_rx_fifo_clear(csi); in imx7_csi_error_recovery()
714 imx7_csi_dma_reflash(csi); in imx7_csi_error_recovery()
716 imx7_csi_hw_enable(csi); in imx7_csi_error_recovery()
719 static void imx7_csi_vb2_buf_done(struct imx7_csi *csi) in imx7_csi_vb2_buf_done() argument
725 done = csi->active_vb2_buf[csi->buf_num]; in imx7_csi_vb2_buf_done()
727 done->vbuf.field = csi->vdev_fmt.field; in imx7_csi_vb2_buf_done()
728 done->vbuf.sequence = csi->frame_sequence; in imx7_csi_vb2_buf_done()
733 csi->frame_sequence++; in imx7_csi_vb2_buf_done()
736 next = imx7_csi_video_next_buf(csi); in imx7_csi_vb2_buf_done()
739 csi->active_vb2_buf[csi->buf_num] = next; in imx7_csi_vb2_buf_done()
741 dma_addr = csi->underrun_buf.dma_addr; in imx7_csi_vb2_buf_done()
742 csi->active_vb2_buf[csi->buf_num] = NULL; in imx7_csi_vb2_buf_done()
745 imx7_csi_update_buf(csi, dma_addr, csi->buf_num); in imx7_csi_vb2_buf_done()
750 struct imx7_csi *csi = data; in imx7_csi_irq_handler() local
753 spin_lock(&csi->irqlock); in imx7_csi_irq_handler()
755 status = imx7_csi_irq_clear(csi); in imx7_csi_irq_handler()
758 dev_warn(csi->dev, "Rx fifo overflow\n"); in imx7_csi_irq_handler()
759 imx7_csi_error_recovery(csi); in imx7_csi_irq_handler()
763 dev_warn(csi->dev, "Hresponse error detected\n"); in imx7_csi_irq_handler()
764 imx7_csi_error_recovery(csi); in imx7_csi_irq_handler()
768 imx7_csi_hw_disable(csi); in imx7_csi_irq_handler()
770 imx7_csi_dma_reflash(csi); in imx7_csi_irq_handler()
772 imx7_csi_hw_enable(csi); in imx7_csi_irq_handler()
779 * CSI DMA is work in one of FB1 and FB2 buffer, in imx7_csi_irq_handler()
782 * when csi work in field0 and field1 will write to in imx7_csi_irq_handler()
786 csi->buf_num = 0; in imx7_csi_irq_handler()
788 csi->buf_num = 1; in imx7_csi_irq_handler()
793 imx7_csi_vb2_buf_done(csi); in imx7_csi_irq_handler()
795 if (csi->last_eof) { in imx7_csi_irq_handler()
796 complete(&csi->last_eof_completion); in imx7_csi_irq_handler()
797 csi->last_eof = false; in imx7_csi_irq_handler()
801 spin_unlock(&csi->irqlock); in imx7_csi_irq_handler()
819 * The CSI bridge can be configured to sample pixel components from the Rx queue
825 * As the CSI bridge can be interfaced with different IP blocks depending on the
831 * Example: i.MX8MM SoC integrates the CSI bridge with the Samsung CSIS CSI-2
832 * receiver which operates in dual pixel sampling mode. The CSI bridge should
834 * pixel sampling mode. When the CSI bridge is instead integrated on an i.MX7,
1026 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_querycap() local
1031 "platform:%s", dev_name(csi->dev)); in imx7_csi_video_querycap()
1108 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_g_fmt_vid_cap() local
1110 f->fmt.pix = csi->vdev_fmt; in imx7_csi_video_g_fmt_vid_cap()
1165 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_s_fmt_vid_cap() local
1168 if (vb2_is_busy(&csi->q)) { in imx7_csi_video_s_fmt_vid_cap()
1169 dev_err(csi->dev, "%s queue busy\n", __func__); in imx7_csi_video_s_fmt_vid_cap()
1173 cc = __imx7_csi_video_try_fmt(&f->fmt.pix, &csi->vdev_compose); in imx7_csi_video_s_fmt_vid_cap()
1175 csi->vdev_cc = cc; in imx7_csi_video_s_fmt_vid_cap()
1176 csi->vdev_fmt = f->fmt.pix; in imx7_csi_video_s_fmt_vid_cap()
1184 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_g_selection() local
1194 s->r = csi->vdev_compose; in imx7_csi_video_g_selection()
1204 s->r.width = csi->vdev_fmt.width; in imx7_csi_video_g_selection()
1205 s->r.height = csi->vdev_fmt.height; in imx7_csi_video_g_selection()
1247 struct imx7_csi *csi = vb2_get_drv_priv(vq); in imx7_csi_video_queue_setup() local
1248 struct v4l2_pix_format *pix = &csi->vdev_fmt; in imx7_csi_video_queue_setup()
1285 struct imx7_csi *csi = vb2_get_drv_priv(vb->vb2_queue); in imx7_csi_video_buf_prepare() local
1286 struct v4l2_pix_format *pix = &csi->vdev_fmt; in imx7_csi_video_buf_prepare()
1289 dev_err(csi->dev, in imx7_csi_video_buf_prepare()
1300 static bool imx7_csi_fast_track_buffer(struct imx7_csi *csi, in imx7_csi_fast_track_buffer() argument
1308 if (!csi->is_streaming) in imx7_csi_fast_track_buffer()
1342 spin_lock_irqsave(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1344 buf_num = csi->buf_num; in imx7_csi_fast_track_buffer()
1345 if (csi->active_vb2_buf[buf_num]) { in imx7_csi_fast_track_buffer()
1346 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1350 imx7_csi_update_buf(csi, dma_addr, buf_num); in imx7_csi_fast_track_buffer()
1352 isr = imx7_csi_reg_read(csi, CSI_CSISR); in imx7_csi_fast_track_buffer()
1363 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1367 csi->active_vb2_buf[buf_num] = buf; in imx7_csi_fast_track_buffer()
1369 spin_unlock_irqrestore(&csi->irqlock, flags); in imx7_csi_fast_track_buffer()
1375 struct imx7_csi *csi = vb2_get_drv_priv(vb->vb2_queue); in imx7_csi_video_buf_queue() local
1379 if (imx7_csi_fast_track_buffer(csi, buf)) in imx7_csi_video_buf_queue()
1382 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_buf_queue()
1384 list_add_tail(&buf->list, &csi->ready_q); in imx7_csi_video_buf_queue()
1386 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_buf_queue()
1389 static int imx7_csi_video_validate_fmt(struct imx7_csi *csi) in imx7_csi_video_validate_fmt() argument
1399 ret = v4l2_subdev_call_state_active(&csi->sd, pad, get_fmt, &fmt_src); in imx7_csi_video_validate_fmt()
1410 if (csi->vdev_compose.width != fmt_src.format.width || in imx7_csi_video_validate_fmt()
1411 csi->vdev_compose.height != fmt_src.format.height) in imx7_csi_video_validate_fmt()
1419 if (!cc || csi->vdev_cc->yuv != cc->yuv) in imx7_csi_video_validate_fmt()
1428 struct imx7_csi *csi = vb2_get_drv_priv(vq); in imx7_csi_video_start_streaming() local
1433 ret = imx7_csi_video_validate_fmt(csi); in imx7_csi_video_start_streaming()
1435 dev_err(csi->dev, "capture format not valid\n"); in imx7_csi_video_start_streaming()
1439 mutex_lock(&csi->mdev.graph_mutex); in imx7_csi_video_start_streaming()
1441 ret = __video_device_pipeline_start(csi->vdev, &csi->pipe); in imx7_csi_video_start_streaming()
1445 ret = v4l2_subdev_call(&csi->sd, video, s_stream, 1); in imx7_csi_video_start_streaming()
1449 mutex_unlock(&csi->mdev.graph_mutex); in imx7_csi_video_start_streaming()
1454 __video_device_pipeline_stop(csi->vdev); in imx7_csi_video_start_streaming()
1456 mutex_unlock(&csi->mdev.graph_mutex); in imx7_csi_video_start_streaming()
1457 dev_err(csi->dev, "pipeline start failed with %d\n", ret); in imx7_csi_video_start_streaming()
1459 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_start_streaming()
1460 list_for_each_entry_safe(buf, tmp, &csi->ready_q, list) { in imx7_csi_video_start_streaming()
1464 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_start_streaming()
1470 struct imx7_csi *csi = vb2_get_drv_priv(vq); in imx7_csi_video_stop_streaming() local
1475 mutex_lock(&csi->mdev.graph_mutex); in imx7_csi_video_stop_streaming()
1476 v4l2_subdev_call(&csi->sd, video, s_stream, 0); in imx7_csi_video_stop_streaming()
1477 __video_device_pipeline_stop(csi->vdev); in imx7_csi_video_stop_streaming()
1478 mutex_unlock(&csi->mdev.graph_mutex); in imx7_csi_video_stop_streaming()
1481 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_stop_streaming()
1482 list_for_each_entry_safe(frame, tmp, &csi->ready_q, list) { in imx7_csi_video_stop_streaming()
1486 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_stop_streaming()
1506 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_open() local
1509 if (mutex_lock_interruptible(&csi->vdev_mutex)) in imx7_csi_video_open()
1514 dev_err(csi->dev, "v4l2_fh_open failed\n"); in imx7_csi_video_open()
1518 ret = v4l2_pipeline_pm_get(&csi->vdev->entity); in imx7_csi_video_open()
1523 mutex_unlock(&csi->vdev_mutex); in imx7_csi_video_open()
1529 struct imx7_csi *csi = video_drvdata(file); in imx7_csi_video_release() local
1530 struct vb2_queue *vq = &csi->q; in imx7_csi_video_release()
1532 mutex_lock(&csi->vdev_mutex); in imx7_csi_video_release()
1539 v4l2_pipeline_pm_put(&csi->vdev->entity); in imx7_csi_video_release()
1542 mutex_unlock(&csi->vdev_mutex); in imx7_csi_video_release()
1559 static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi) in imx7_csi_video_next_buf() argument
1564 spin_lock_irqsave(&csi->q_lock, flags); in imx7_csi_video_next_buf()
1567 if (!list_empty(&csi->ready_q)) { in imx7_csi_video_next_buf()
1568 buf = list_entry(csi->ready_q.next, struct imx7_csi_vb2_buffer, in imx7_csi_video_next_buf()
1573 spin_unlock_irqrestore(&csi->q_lock, flags); in imx7_csi_video_next_buf()
1578 static void imx7_csi_video_init_format(struct imx7_csi *csi) in imx7_csi_video_init_format() argument
1580 struct v4l2_pix_format *pixfmt = &csi->vdev_fmt; in imx7_csi_video_init_format()
1585 csi->vdev_cc = __imx7_csi_video_try_fmt(pixfmt, &csi->vdev_compose); in imx7_csi_video_init_format()
1588 static int imx7_csi_video_register(struct imx7_csi *csi) in imx7_csi_video_register() argument
1590 struct v4l2_subdev *sd = &csi->sd; in imx7_csi_video_register()
1592 struct video_device *vdev = csi->vdev; in imx7_csi_video_register()
1598 imx7_csi_video_init_format(csi); in imx7_csi_video_register()
1603 dev_err(csi->dev, "Failed to register video device\n"); in imx7_csi_video_register()
1607 dev_info(csi->dev, "Registered %s as /dev/%s\n", vdev->name, in imx7_csi_video_register()
1610 /* Create the link from the CSI subdev to the video device. */ in imx7_csi_video_register()
1615 dev_err(csi->dev, "failed to create link to device node\n"); in imx7_csi_video_register()
1623 static void imx7_csi_video_unregister(struct imx7_csi *csi) in imx7_csi_video_unregister() argument
1625 media_entity_cleanup(&csi->vdev->entity); in imx7_csi_video_unregister()
1626 video_unregister_device(csi->vdev); in imx7_csi_video_unregister()
1629 static int imx7_csi_video_init(struct imx7_csi *csi) in imx7_csi_video_init() argument
1635 mutex_init(&csi->vdev_mutex); in imx7_csi_video_init()
1636 INIT_LIST_HEAD(&csi->ready_q); in imx7_csi_video_init()
1637 spin_lock_init(&csi->q_lock); in imx7_csi_video_init()
1652 vdev->lock = &csi->vdev_mutex; in imx7_csi_video_init()
1653 vdev->queue = &csi->q; in imx7_csi_video_init()
1655 snprintf(vdev->name, sizeof(vdev->name), "%s capture", csi->sd.name); in imx7_csi_video_init()
1657 video_set_drvdata(vdev, csi); in imx7_csi_video_init()
1658 csi->vdev = vdev; in imx7_csi_video_init()
1661 csi->vdev_pad.flags = MEDIA_PAD_FL_SINK; in imx7_csi_video_init()
1662 ret = media_entity_pads_init(&vdev->entity, 1, &csi->vdev_pad); in imx7_csi_video_init()
1669 vq = &csi->q; in imx7_csi_video_init()
1672 vq->drv_priv = csi; in imx7_csi_video_init()
1677 vq->lock = &csi->vdev_mutex; in imx7_csi_video_init()
1679 vq->dev = csi->dev; in imx7_csi_video_init()
1683 dev_err(csi->dev, "vb2_queue_init failed\n"); in imx7_csi_video_init()
1697 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_s_stream() local
1704 ret = imx7_csi_init(csi, sd_state); in imx7_csi_s_stream()
1708 ret = v4l2_subdev_call(csi->src_sd, video, s_stream, 1); in imx7_csi_s_stream()
1710 imx7_csi_deinit(csi, VB2_BUF_STATE_QUEUED); in imx7_csi_s_stream()
1714 imx7_csi_enable(csi); in imx7_csi_s_stream()
1716 imx7_csi_disable(csi); in imx7_csi_s_stream()
1718 v4l2_subdev_call(csi->src_sd, video, s_stream, 0); in imx7_csi_s_stream()
1720 imx7_csi_deinit(csi, VB2_BUF_STATE_ERROR); in imx7_csi_s_stream()
1723 csi->is_streaming = !!enable; in imx7_csi_s_stream()
1882 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_set_fmt() local
1889 if (csi->is_streaming) in imx7_csi_set_fmt()
1918 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_pad_link_validate() local
1925 * parallel input or the CSI-2 receiver. in imx7_csi_pad_link_validate()
1931 switch (csi->src_sd->entity.function) { in imx7_csi_pad_link_validate()
1933 /* The input is the CSI-2 receiver. */ in imx7_csi_pad_link_validate()
1934 csi->is_csi2 = true; in imx7_csi_pad_link_validate()
1939 for (i = 0; i < csi->src_sd->entity.num_pads; i++) { in imx7_csi_pad_link_validate()
1940 struct media_pad *spad = &csi->src_sd->entity.pads[i]; in imx7_csi_pad_link_validate()
1953 csi->is_csi2 = pad->entity->function == MEDIA_ENT_F_VID_IF_BRIDGE; in imx7_csi_pad_link_validate()
1961 csi->is_csi2 = false; in imx7_csi_pad_link_validate()
1970 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_registered() local
1973 ret = imx7_csi_video_init(csi); in imx7_csi_registered()
1977 ret = imx7_csi_video_register(csi); in imx7_csi_registered()
1981 ret = v4l2_device_register_subdev_nodes(&csi->v4l2_dev); in imx7_csi_registered()
1985 ret = media_device_register(&csi->mdev); in imx7_csi_registered()
1992 imx7_csi_video_unregister(csi); in imx7_csi_registered()
1998 struct imx7_csi *csi = v4l2_get_subdevdata(sd); in imx7_csi_unregistered() local
2000 imx7_csi_video_unregister(csi); in imx7_csi_unregistered()
2042 struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); in imx7_csi_notify_bound() local
2043 struct media_pad *sink = &csi->sd.entity.pads[IMX7_CSI_PAD_SINK]; in imx7_csi_notify_bound()
2045 csi->src_sd = sd; in imx7_csi_notify_bound()
2053 struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); in imx7_csi_notify_complete() local
2055 return v4l2_device_register_subdev_nodes(&csi->v4l2_dev); in imx7_csi_notify_complete()
2063 static int imx7_csi_async_register(struct imx7_csi *csi) in imx7_csi_async_register() argument
2069 v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); in imx7_csi_async_register()
2071 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, in imx7_csi_async_register()
2074 ret = dev_err_probe(csi->dev, -ENOTCONN, in imx7_csi_async_register()
2079 asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep, in imx7_csi_async_register()
2085 ret = dev_err_probe(csi->dev, PTR_ERR(asd), in imx7_csi_async_register()
2090 csi->notifier.ops = &imx7_csi_notify_ops; in imx7_csi_async_register()
2092 ret = v4l2_async_nf_register(&csi->notifier); in imx7_csi_async_register()
2099 v4l2_async_nf_cleanup(&csi->notifier); in imx7_csi_async_register()
2103 static void imx7_csi_media_cleanup(struct imx7_csi *csi) in imx7_csi_media_cleanup() argument
2105 v4l2_device_unregister(&csi->v4l2_dev); in imx7_csi_media_cleanup()
2106 media_device_unregister(&csi->mdev); in imx7_csi_media_cleanup()
2107 v4l2_subdev_cleanup(&csi->sd); in imx7_csi_media_cleanup()
2108 media_device_cleanup(&csi->mdev); in imx7_csi_media_cleanup()
2115 static int imx7_csi_media_dev_init(struct imx7_csi *csi) in imx7_csi_media_dev_init() argument
2119 strscpy(csi->mdev.model, "imx-media", sizeof(csi->mdev.model)); in imx7_csi_media_dev_init()
2120 csi->mdev.ops = &imx7_csi_media_ops; in imx7_csi_media_dev_init()
2121 csi->mdev.dev = csi->dev; in imx7_csi_media_dev_init()
2123 csi->v4l2_dev.mdev = &csi->mdev; in imx7_csi_media_dev_init()
2124 strscpy(csi->v4l2_dev.name, "imx-media", in imx7_csi_media_dev_init()
2125 sizeof(csi->v4l2_dev.name)); in imx7_csi_media_dev_init()
2126 snprintf(csi->mdev.bus_info, sizeof(csi->mdev.bus_info), in imx7_csi_media_dev_init()
2127 "platform:%s", dev_name(csi->mdev.dev)); in imx7_csi_media_dev_init()
2129 media_device_init(&csi->mdev); in imx7_csi_media_dev_init()
2131 ret = v4l2_device_register(csi->dev, &csi->v4l2_dev); in imx7_csi_media_dev_init()
2133 v4l2_err(&csi->v4l2_dev, in imx7_csi_media_dev_init()
2141 media_device_cleanup(&csi->mdev); in imx7_csi_media_dev_init()
2146 static int imx7_csi_media_init(struct imx7_csi *csi) in imx7_csi_media_init() argument
2152 ret = imx7_csi_media_dev_init(csi); in imx7_csi_media_init()
2156 v4l2_subdev_init(&csi->sd, &imx7_csi_subdev_ops); in imx7_csi_media_init()
2157 v4l2_set_subdevdata(&csi->sd, csi); in imx7_csi_media_init()
2158 csi->sd.internal_ops = &imx7_csi_internal_ops; in imx7_csi_media_init()
2159 csi->sd.entity.ops = &imx7_csi_entity_ops; in imx7_csi_media_init()
2160 csi->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in imx7_csi_media_init()
2161 csi->sd.dev = csi->dev; in imx7_csi_media_init()
2162 csi->sd.owner = THIS_MODULE; in imx7_csi_media_init()
2163 csi->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; in imx7_csi_media_init()
2164 snprintf(csi->sd.name, sizeof(csi->sd.name), "csi"); in imx7_csi_media_init()
2167 csi->pad[i].flags = (i == IMX7_CSI_PAD_SINK) ? in imx7_csi_media_init()
2170 ret = media_entity_pads_init(&csi->sd.entity, IMX7_CSI_PADS_NUM, in imx7_csi_media_init()
2171 csi->pad); in imx7_csi_media_init()
2175 ret = v4l2_subdev_init_finalize(&csi->sd); in imx7_csi_media_init()
2179 ret = v4l2_device_register_subdev(&csi->v4l2_dev, &csi->sd); in imx7_csi_media_init()
2186 imx7_csi_media_cleanup(csi); in imx7_csi_media_init()
2193 struct imx7_csi *csi; in imx7_csi_probe() local
2196 csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL); in imx7_csi_probe()
2197 if (!csi) in imx7_csi_probe()
2200 csi->dev = dev; in imx7_csi_probe()
2201 platform_set_drvdata(pdev, csi); in imx7_csi_probe()
2203 spin_lock_init(&csi->irqlock); in imx7_csi_probe()
2206 csi->mclk = devm_clk_get(&pdev->dev, "mclk"); in imx7_csi_probe()
2207 if (IS_ERR(csi->mclk)) { in imx7_csi_probe()
2208 ret = PTR_ERR(csi->mclk); in imx7_csi_probe()
2213 csi->irq = platform_get_irq(pdev, 0); in imx7_csi_probe()
2214 if (csi->irq < 0) in imx7_csi_probe()
2215 return csi->irq; in imx7_csi_probe()
2217 csi->regbase = devm_platform_ioremap_resource(pdev, 0); in imx7_csi_probe()
2218 if (IS_ERR(csi->regbase)) in imx7_csi_probe()
2219 return PTR_ERR(csi->regbase); in imx7_csi_probe()
2221 csi->model = (enum imx_csi_model)(uintptr_t)of_device_get_match_data(&pdev->dev); in imx7_csi_probe()
2223 ret = devm_request_irq(dev, csi->irq, imx7_csi_irq_handler, 0, "csi", in imx7_csi_probe()
2224 (void *)csi); in imx7_csi_probe()
2226 dev_err(dev, "Request CSI IRQ failed.\n"); in imx7_csi_probe()
2231 ret = imx7_csi_media_init(csi); in imx7_csi_probe()
2235 ret = imx7_csi_async_register(csi); in imx7_csi_probe()
2242 imx7_csi_media_cleanup(csi); in imx7_csi_probe()
2249 struct imx7_csi *csi = platform_get_drvdata(pdev); in imx7_csi_remove() local
2251 imx7_csi_media_cleanup(csi); in imx7_csi_remove()
2253 v4l2_async_nf_unregister(&csi->notifier); in imx7_csi_remove()
2254 v4l2_async_nf_cleanup(&csi->notifier); in imx7_csi_remove()
2255 v4l2_async_unregister_subdev(&csi->sd); in imx7_csi_remove()
2259 { .compatible = "fsl,imx8mq-csi", .data = (void *)IMX7_CSI_IMX8MQ },
2260 { .compatible = "fsl,imx7-csi", .data = (void *)IMX7_CSI_IMX7 },
2261 { .compatible = "fsl,imx6ul-csi", .data = (void *)IMX7_CSI_IMX7 },
2271 .name = "imx7-csi",
2276 MODULE_DESCRIPTION("i.MX7 CSI subdev driver");
2279 MODULE_ALIAS("platform:imx7-csi");