Lines Matching full:csi

36 static void sun4i_csi_capture_start(struct sun4i_csi *csi)  in sun4i_csi_capture_start()  argument
38 writel(CSI_CPT_CTRL_VIDEO_START, csi->regs + CSI_CPT_CTRL_REG); in sun4i_csi_capture_start()
41 static void sun4i_csi_capture_stop(struct sun4i_csi *csi) in sun4i_csi_capture_stop() argument
43 writel(0, csi->regs + CSI_CPT_CTRL_REG); in sun4i_csi_capture_stop()
52 struct sun4i_csi *csi = vb2_get_drv_priv(vq); in sun4i_csi_queue_setup() local
53 unsigned int num_planes = csi->fmt.num_planes; in sun4i_csi_queue_setup()
61 if (sizes[i] < csi->fmt.plane_fmt[i].sizeimage) in sun4i_csi_queue_setup()
68 sizes[i] = csi->fmt.plane_fmt[i].sizeimage; in sun4i_csi_queue_setup()
75 struct sun4i_csi *csi = vb2_get_drv_priv(vb->vb2_queue); in sun4i_csi_buffer_prepare() local
78 for (i = 0; i < csi->fmt.num_planes; i++) { in sun4i_csi_buffer_prepare()
79 unsigned long size = csi->fmt.plane_fmt[i].sizeimage; in sun4i_csi_buffer_prepare()
82 dev_err(csi->dev, "buffer too small (%lu < %lu)\n", in sun4i_csi_buffer_prepare()
93 static int sun4i_csi_setup_scratch_buffer(struct sun4i_csi *csi, in sun4i_csi_setup_scratch_buffer() argument
96 dma_addr_t addr = csi->scratch.paddr; in sun4i_csi_setup_scratch_buffer()
99 dev_dbg(csi->dev, in sun4i_csi_setup_scratch_buffer()
102 for (plane = 0; plane < csi->fmt.num_planes; plane++) { in sun4i_csi_setup_scratch_buffer()
103 writel(addr, csi->regs + CSI_BUF_ADDR_REG(plane, slot)); in sun4i_csi_setup_scratch_buffer()
104 addr += csi->fmt.plane_fmt[plane].sizeimage; in sun4i_csi_setup_scratch_buffer()
107 csi->current_buf[slot] = NULL; in sun4i_csi_setup_scratch_buffer()
111 static int sun4i_csi_buffer_fill_slot(struct sun4i_csi *csi, unsigned int slot) in sun4i_csi_buffer_fill_slot() argument
121 if (WARN_ON(csi->current_buf[slot])) in sun4i_csi_buffer_fill_slot()
124 if (list_empty(&csi->buf_list)) in sun4i_csi_buffer_fill_slot()
125 return sun4i_csi_setup_scratch_buffer(csi, slot); in sun4i_csi_buffer_fill_slot()
127 c_buf = list_first_entry(&csi->buf_list, struct sun4i_csi_buffer, list); in sun4i_csi_buffer_fill_slot()
131 csi->current_buf[slot] = v_buf; in sun4i_csi_buffer_fill_slot()
133 for (plane = 0; plane < csi->fmt.num_planes; plane++) { in sun4i_csi_buffer_fill_slot()
138 writel(buf_addr, csi->regs + CSI_BUF_ADDR_REG(plane, slot)); in sun4i_csi_buffer_fill_slot()
144 static int sun4i_csi_buffer_fill_all(struct sun4i_csi *csi) in sun4i_csi_buffer_fill_all() argument
150 ret = sun4i_csi_buffer_fill_slot(csi, slot); in sun4i_csi_buffer_fill_all()
158 static void sun4i_csi_buffer_mark_done(struct sun4i_csi *csi, in sun4i_csi_buffer_mark_done() argument
164 if (!csi->current_buf[slot]) { in sun4i_csi_buffer_mark_done()
165 dev_dbg(csi->dev, "Scratch buffer was used, ignoring..\n"); in sun4i_csi_buffer_mark_done()
169 v_buf = csi->current_buf[slot]; in sun4i_csi_buffer_mark_done()
170 v_buf->field = csi->fmt.field; in sun4i_csi_buffer_mark_done()
175 csi->current_buf[slot] = NULL; in sun4i_csi_buffer_mark_done()
178 static int sun4i_csi_buffer_flip(struct sun4i_csi *csi, unsigned int sequence) in sun4i_csi_buffer_flip() argument
180 u32 reg = readl(csi->regs + CSI_BUF_CTRL_REG); in sun4i_csi_buffer_flip()
187 sun4i_csi_buffer_mark_done(csi, next, sequence); in sun4i_csi_buffer_flip()
190 return sun4i_csi_buffer_fill_slot(csi, next); in sun4i_csi_buffer_flip()
195 struct sun4i_csi *csi = vb2_get_drv_priv(vb->vb2_queue); in sun4i_csi_buffer_queue() local
199 spin_lock_irqsave(&csi->qlock, flags); in sun4i_csi_buffer_queue()
200 list_add_tail(&buf->list, &csi->buf_list); in sun4i_csi_buffer_queue()
201 spin_unlock_irqrestore(&csi->qlock, flags); in sun4i_csi_buffer_queue()
204 static void return_all_buffers(struct sun4i_csi *csi, in return_all_buffers() argument
210 list_for_each_entry_safe(buf, node, &csi->buf_list, list) { in return_all_buffers()
216 struct vb2_v4l2_buffer *v_buf = csi->current_buf[slot]; in return_all_buffers()
222 csi->current_buf[slot] = NULL; in return_all_buffers()
228 struct sun4i_csi *csi = vb2_get_drv_priv(vq); in sun4i_csi_start_streaming() local
229 struct v4l2_mbus_config_parallel *bus = &csi->bus; in sun4i_csi_start_streaming()
236 csi_fmt = sun4i_csi_find_format(&csi->fmt.pixelformat, NULL); in sun4i_csi_start_streaming()
240 dev_dbg(csi->dev, "Starting capture\n"); in sun4i_csi_start_streaming()
242 csi->sequence = 0; in sun4i_csi_start_streaming()
255 csi->scratch.size = 0; in sun4i_csi_start_streaming()
256 for (i = 0; i < csi->fmt.num_planes; i++) in sun4i_csi_start_streaming()
257 csi->scratch.size += csi->fmt.plane_fmt[i].sizeimage; in sun4i_csi_start_streaming()
259 csi->scratch.vaddr = dma_alloc_coherent(csi->dev, in sun4i_csi_start_streaming()
260 csi->scratch.size, in sun4i_csi_start_streaming()
261 &csi->scratch.paddr, in sun4i_csi_start_streaming()
263 if (!csi->scratch.vaddr) { in sun4i_csi_start_streaming()
264 dev_err(csi->dev, "Failed to allocate scratch buffer\n"); in sun4i_csi_start_streaming()
269 ret = video_device_pipeline_alloc_start(&csi->vdev); in sun4i_csi_start_streaming()
273 spin_lock_irqsave(&csi->qlock, flags); in sun4i_csi_start_streaming()
276 writel(CSI_WIN_CTRL_W_ACTIVE(csi->fmt.width * 2), in sun4i_csi_start_streaming()
277 csi->regs + CSI_WIN_CTRL_W_REG); in sun4i_csi_start_streaming()
278 writel(CSI_WIN_CTRL_H_ACTIVE(csi->fmt.height), in sun4i_csi_start_streaming()
279 csi->regs + CSI_WIN_CTRL_H_REG); in sun4i_csi_start_streaming()
297 csi->regs + CSI_CFG_REG); in sun4i_csi_start_streaming()
300 writel(csi->fmt.plane_fmt[0].bytesperline, in sun4i_csi_start_streaming()
301 csi->regs + CSI_BUF_LEN_REG); in sun4i_csi_start_streaming()
304 ret = sun4i_csi_buffer_fill_all(csi); in sun4i_csi_start_streaming()
306 spin_unlock_irqrestore(&csi->qlock, flags); in sun4i_csi_start_streaming()
311 writel(CSI_BUF_CTRL_DBE, csi->regs + CSI_BUF_CTRL_REG); in sun4i_csi_start_streaming()
314 writel(CSI_INT_FRM_DONE, csi->regs + CSI_INT_STA_REG); in sun4i_csi_start_streaming()
317 writel(CSI_INT_FRM_DONE, csi->regs + CSI_INT_EN_REG); in sun4i_csi_start_streaming()
319 sun4i_csi_capture_start(csi); in sun4i_csi_start_streaming()
321 spin_unlock_irqrestore(&csi->qlock, flags); in sun4i_csi_start_streaming()
323 ret = v4l2_subdev_call(csi->src_subdev, video, s_stream, 1); in sun4i_csi_start_streaming()
330 sun4i_csi_capture_stop(csi); in sun4i_csi_start_streaming()
333 video_device_pipeline_stop(&csi->vdev); in sun4i_csi_start_streaming()
336 dma_free_coherent(csi->dev, csi->scratch.size, csi->scratch.vaddr, in sun4i_csi_start_streaming()
337 csi->scratch.paddr); in sun4i_csi_start_streaming()
340 spin_lock_irqsave(&csi->qlock, flags); in sun4i_csi_start_streaming()
341 return_all_buffers(csi, VB2_BUF_STATE_QUEUED); in sun4i_csi_start_streaming()
342 spin_unlock_irqrestore(&csi->qlock, flags); in sun4i_csi_start_streaming()
349 struct sun4i_csi *csi = vb2_get_drv_priv(vq); in sun4i_csi_stop_streaming() local
352 dev_dbg(csi->dev, "Stopping capture\n"); in sun4i_csi_stop_streaming()
354 v4l2_subdev_call(csi->src_subdev, video, s_stream, 0); in sun4i_csi_stop_streaming()
355 sun4i_csi_capture_stop(csi); in sun4i_csi_stop_streaming()
358 spin_lock_irqsave(&csi->qlock, flags); in sun4i_csi_stop_streaming()
359 return_all_buffers(csi, VB2_BUF_STATE_ERROR); in sun4i_csi_stop_streaming()
360 spin_unlock_irqrestore(&csi->qlock, flags); in sun4i_csi_stop_streaming()
362 video_device_pipeline_stop(&csi->vdev); in sun4i_csi_stop_streaming()
364 dma_free_coherent(csi->dev, csi->scratch.size, csi->scratch.vaddr, in sun4i_csi_stop_streaming()
365 csi->scratch.paddr); in sun4i_csi_stop_streaming()
380 struct sun4i_csi *csi = data; in sun4i_csi_irq() local
383 reg = readl(csi->regs + CSI_INT_STA_REG); in sun4i_csi_irq()
386 writel(reg, csi->regs + CSI_INT_STA_REG); in sun4i_csi_irq()
391 spin_lock(&csi->qlock); in sun4i_csi_irq()
392 if (sun4i_csi_buffer_flip(csi, csi->sequence++)) { in sun4i_csi_irq()
393 dev_warn(csi->dev, "%s: Flip failed\n", __func__); in sun4i_csi_irq()
394 sun4i_csi_capture_stop(csi); in sun4i_csi_irq()
396 spin_unlock(&csi->qlock); in sun4i_csi_irq()
401 int sun4i_csi_dma_register(struct sun4i_csi *csi, int irq) in sun4i_csi_dma_register() argument
403 struct vb2_queue *q = &csi->queue; in sun4i_csi_dma_register()
407 spin_lock_init(&csi->qlock); in sun4i_csi_dma_register()
408 mutex_init(&csi->lock); in sun4i_csi_dma_register()
410 INIT_LIST_HEAD(&csi->buf_list); in sun4i_csi_dma_register()
412 csi->current_buf[i] = NULL; in sun4i_csi_dma_register()
417 q->lock = &csi->lock; in sun4i_csi_dma_register()
418 q->drv_priv = csi; in sun4i_csi_dma_register()
423 q->dev = csi->dev; in sun4i_csi_dma_register()
427 dev_err(csi->dev, "failed to initialize VB2 queue\n"); in sun4i_csi_dma_register()
431 ret = v4l2_device_register(csi->dev, &csi->v4l); in sun4i_csi_dma_register()
433 dev_err(csi->dev, "Couldn't register the v4l2 device\n"); in sun4i_csi_dma_register()
437 ret = devm_request_irq(csi->dev, irq, sun4i_csi_irq, 0, in sun4i_csi_dma_register()
438 dev_name(csi->dev), csi); in sun4i_csi_dma_register()
440 dev_err(csi->dev, "Couldn't register our interrupt\n"); in sun4i_csi_dma_register()
447 v4l2_device_unregister(&csi->v4l); in sun4i_csi_dma_register()
450 mutex_destroy(&csi->lock); in sun4i_csi_dma_register()
454 void sun4i_csi_dma_unregister(struct sun4i_csi *csi) in sun4i_csi_dma_unregister() argument
456 v4l2_device_unregister(&csi->v4l); in sun4i_csi_dma_unregister()
457 mutex_destroy(&csi->lock); in sun4i_csi_dma_unregister()