1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/delay.h>
5*4882a593Smuzhiyun #include <linux/pm_runtime.h>
6*4882a593Smuzhiyun #include <media/v4l2-common.h>
7*4882a593Smuzhiyun #include <media/v4l2-event.h>
8*4882a593Smuzhiyun #include <media/v4l2-fh.h>
9*4882a593Smuzhiyun #include <media/v4l2-ioctl.h>
10*4882a593Smuzhiyun #include <media/v4l2-subdev.h>
11*4882a593Smuzhiyun #include <media/videobuf2-dma-contig.h>
12*4882a593Smuzhiyun #include <linux/dma-iommu.h>
13*4882a593Smuzhiyun #include "dev.h"
14*4882a593Smuzhiyun #include "regs.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define CIF_ISP_REQ_BUFS_MIN 1
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static const struct capture_fmt dmarx_fmts[] = {
19*4882a593Smuzhiyun /* bayer raw */
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_SRGGB8,
22*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
23*4882a593Smuzhiyun .fmt_type = FMT_BAYER,
24*4882a593Smuzhiyun .bpp = { 8 },
25*4882a593Smuzhiyun .mplanes = 1,
26*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
27*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_RGB_BAYER_8BIT,
28*4882a593Smuzhiyun }, {
29*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_SGRBG8,
30*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
31*4882a593Smuzhiyun .fmt_type = FMT_BAYER,
32*4882a593Smuzhiyun .bpp = { 8 },
33*4882a593Smuzhiyun .mplanes = 1,
34*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
35*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_RGB_BAYER_8BIT,
36*4882a593Smuzhiyun }, {
37*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_SGBRG8,
38*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
39*4882a593Smuzhiyun .fmt_type = FMT_BAYER,
40*4882a593Smuzhiyun .bpp = { 8 },
41*4882a593Smuzhiyun .mplanes = 1,
42*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
43*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_RGB_BAYER_8BIT,
44*4882a593Smuzhiyun }, {
45*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_SBGGR8,
46*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
47*4882a593Smuzhiyun .fmt_type = FMT_BAYER,
48*4882a593Smuzhiyun .bpp = { 8 },
49*4882a593Smuzhiyun .mplanes = 1,
50*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
51*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_RGB_BAYER_8BIT,
52*4882a593Smuzhiyun }, { /* 12bit used, 4 lower bits of LSB unused */
53*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_SBGGR16,
54*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
55*4882a593Smuzhiyun .fmt_type = FMT_BAYER,
56*4882a593Smuzhiyun .bpp = { 16 },
57*4882a593Smuzhiyun .mplanes = 1,
58*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
59*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_RGB_BAYER_16BIT,
60*4882a593Smuzhiyun }, {
61*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_YUYV,
62*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
63*4882a593Smuzhiyun .fmt_type = FMT_YUV,
64*4882a593Smuzhiyun .bpp = { 16 },
65*4882a593Smuzhiyun .cplanes = 1,
66*4882a593Smuzhiyun .mplanes = 1,
67*4882a593Smuzhiyun .uv_swap = 0,
68*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
69*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_FMT_YUV422,
70*4882a593Smuzhiyun }, {
71*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_YVYU,
72*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
73*4882a593Smuzhiyun .fmt_type = FMT_YUV,
74*4882a593Smuzhiyun .bpp = { 16 },
75*4882a593Smuzhiyun .cplanes = 1,
76*4882a593Smuzhiyun .mplanes = 1,
77*4882a593Smuzhiyun .uv_swap = 0,
78*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
79*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_FMT_YUV422,
80*4882a593Smuzhiyun }, {
81*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_UYVY,
82*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
83*4882a593Smuzhiyun .fmt_type = FMT_YUV,
84*4882a593Smuzhiyun .bpp = { 16 },
85*4882a593Smuzhiyun .cplanes = 1,
86*4882a593Smuzhiyun .mplanes = 1,
87*4882a593Smuzhiyun .uv_swap = 0,
88*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
89*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_FMT_YUV422,
90*4882a593Smuzhiyun }, {
91*4882a593Smuzhiyun .fourcc = V4L2_PIX_FMT_VYUY,
92*4882a593Smuzhiyun .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
93*4882a593Smuzhiyun .fmt_type = FMT_YUV,
94*4882a593Smuzhiyun .bpp = { 16 },
95*4882a593Smuzhiyun .cplanes = 1,
96*4882a593Smuzhiyun .mplanes = 1,
97*4882a593Smuzhiyun .uv_swap = 0,
98*4882a593Smuzhiyun .write_format = CIF_MI_DMA_CTRL_READ_FMT_PACKED,
99*4882a593Smuzhiyun .output_format = CIF_MI_DMA_CTRL_FMT_YUV422,
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun static struct stream_config rkisp1_dmarx_stream_config = {
104*4882a593Smuzhiyun .fmts = dmarx_fmts,
105*4882a593Smuzhiyun .fmt_size = ARRAY_SIZE(dmarx_fmts),
106*4882a593Smuzhiyun .mi = {
107*4882a593Smuzhiyun .y_size_init = CIF_MI_DMA_Y_PIC_SIZE,
108*4882a593Smuzhiyun .y_base_ad_init = CIF_MI_DMA_Y_PIC_START_AD,
109*4882a593Smuzhiyun .cb_base_ad_init = CIF_MI_DMA_CB_PIC_START_AD,
110*4882a593Smuzhiyun .cr_base_ad_init = CIF_MI_DMA_CR_PIC_START_AD,
111*4882a593Smuzhiyun },
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun static const
find_fmt(struct rkisp1_stream * stream,const u32 pixelfmt)115*4882a593Smuzhiyun struct capture_fmt *find_fmt(struct rkisp1_stream *stream,
116*4882a593Smuzhiyun const u32 pixelfmt)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun const struct capture_fmt *fmt;
119*4882a593Smuzhiyun int i;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun for (i = 0; i < stream->config->fmt_size; i++) {
122*4882a593Smuzhiyun fmt = &stream->config->fmts[i];
123*4882a593Smuzhiyun if (fmt->fourcc == pixelfmt)
124*4882a593Smuzhiyun return fmt;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun return NULL;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
dmarx_config_mi(struct rkisp1_stream * stream)129*4882a593Smuzhiyun static int dmarx_config_mi(struct rkisp1_stream *stream)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct rkisp1_device *dev = stream->ispdev;
132*4882a593Smuzhiyun void __iomem *base = dev->base_addr;
133*4882a593Smuzhiyun struct capture_fmt *dmarx_in_fmt = &stream->out_isp_fmt;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
136*4882a593Smuzhiyun "%s %dx%x y_stride:%d\n", __func__,
137*4882a593Smuzhiyun stream->out_fmt.width,
138*4882a593Smuzhiyun stream->out_fmt.height,
139*4882a593Smuzhiyun stream->u.dmarx.y_stride);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun mi_set_y_size(stream, stream->out_fmt.width *
142*4882a593Smuzhiyun stream->out_fmt.height);
143*4882a593Smuzhiyun dmarx_set_y_width(base, stream->out_fmt.width);
144*4882a593Smuzhiyun dmarx_set_y_line_length(base, stream->u.dmarx.y_stride);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun mi_dmarx_ready_enable(stream);
147*4882a593Smuzhiyun if (dmarx_in_fmt->uv_swap)
148*4882a593Smuzhiyun dmarx_set_uv_swap(base);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun dmarx_ctrl(base,
151*4882a593Smuzhiyun dmarx_in_fmt->write_format |
152*4882a593Smuzhiyun dmarx_in_fmt->output_format |
153*4882a593Smuzhiyun CIF_MI_DMA_CTRL_BURST_LEN_LUM_16 |
154*4882a593Smuzhiyun CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16);
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
update_dmarx(struct rkisp1_stream * stream)158*4882a593Smuzhiyun static void update_dmarx(struct rkisp1_stream *stream)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun void __iomem *base = stream->ispdev->base_addr;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (stream->curr_buf) {
163*4882a593Smuzhiyun mi_set_y_addr(stream,
164*4882a593Smuzhiyun stream->curr_buf->buff_addr[RKISP1_PLANE_Y]);
165*4882a593Smuzhiyun mi_set_cb_addr(stream,
166*4882a593Smuzhiyun stream->curr_buf->buff_addr[RKISP1_PLANE_CB]);
167*4882a593Smuzhiyun mi_set_cr_addr(stream,
168*4882a593Smuzhiyun stream->curr_buf->buff_addr[RKISP1_PLANE_CR]);
169*4882a593Smuzhiyun mi_dmarx_start(base);
170*4882a593Smuzhiyun stream->frame_end = false;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
dmarx_stop_mi(struct rkisp1_stream * stream)174*4882a593Smuzhiyun static void dmarx_stop_mi(struct rkisp1_stream *stream)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun mi_dmarx_ready_disable(stream);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun static struct streams_ops rkisp1_dmarx_streams_ops = {
180*4882a593Smuzhiyun .config_mi = dmarx_config_mi,
181*4882a593Smuzhiyun .stop_mi = dmarx_stop_mi,
182*4882a593Smuzhiyun .update_mi = update_dmarx,
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun
dmarx_frame_end(struct rkisp1_stream * stream)185*4882a593Smuzhiyun static int dmarx_frame_end(struct rkisp1_stream *stream)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun unsigned long lock_flags = 0;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (stream->curr_buf) {
190*4882a593Smuzhiyun vb2_buffer_done(&stream->curr_buf->vb.vb2_buf,
191*4882a593Smuzhiyun VB2_BUF_STATE_DONE);
192*4882a593Smuzhiyun stream->curr_buf = NULL;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun spin_lock_irqsave(&stream->vbq_lock, lock_flags);
196*4882a593Smuzhiyun if (!list_empty(&stream->buf_queue)) {
197*4882a593Smuzhiyun stream->curr_buf =
198*4882a593Smuzhiyun list_first_entry(&stream->buf_queue,
199*4882a593Smuzhiyun struct rkisp1_buffer,
200*4882a593Smuzhiyun queue);
201*4882a593Smuzhiyun list_del(&stream->curr_buf->queue);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun stream->ops->update_mi(stream);
206*4882a593Smuzhiyun return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /***************************** vb2 operations*******************************/
210*4882a593Smuzhiyun
dmarx_stop(struct rkisp1_stream * stream)211*4882a593Smuzhiyun static void dmarx_stop(struct rkisp1_stream *stream)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun struct rkisp1_device *dev = stream->ispdev;
214*4882a593Smuzhiyun struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
215*4882a593Smuzhiyun int ret = 0;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun stream->stopping = true;
218*4882a593Smuzhiyun if (dev->isp_state == ISP_START &&
219*4882a593Smuzhiyun !stream->frame_end) {
220*4882a593Smuzhiyun ret = wait_event_timeout(stream->done,
221*4882a593Smuzhiyun !stream->streaming,
222*4882a593Smuzhiyun msecs_to_jiffies(500));
223*4882a593Smuzhiyun if (!ret)
224*4882a593Smuzhiyun v4l2_warn(v4l2_dev,
225*4882a593Smuzhiyun "dmarx:%d waiting on event return error %d\n",
226*4882a593Smuzhiyun stream->id, ret);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun if (stream->ops->stop_mi)
229*4882a593Smuzhiyun stream->ops->stop_mi(stream);
230*4882a593Smuzhiyun stream->stopping = false;
231*4882a593Smuzhiyun stream->streaming = false;
232*4882a593Smuzhiyun stream->frame_end = false;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
dmarx_start(struct rkisp1_stream * stream)235*4882a593Smuzhiyun static int dmarx_start(struct rkisp1_stream *stream)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun int ret;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun ret = stream->ops->config_mi(stream);
240*4882a593Smuzhiyun if (ret)
241*4882a593Smuzhiyun return ret;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun stream->curr_buf = NULL;
244*4882a593Smuzhiyun dmarx_frame_end(stream);
245*4882a593Smuzhiyun stream->streaming = true;
246*4882a593Smuzhiyun return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
rkisp1_queue_setup(struct vb2_queue * queue,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_ctxs[])249*4882a593Smuzhiyun static int rkisp1_queue_setup(struct vb2_queue *queue,
250*4882a593Smuzhiyun unsigned int *num_buffers,
251*4882a593Smuzhiyun unsigned int *num_planes,
252*4882a593Smuzhiyun unsigned int sizes[],
253*4882a593Smuzhiyun struct device *alloc_ctxs[])
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun struct rkisp1_stream *stream = queue->drv_priv;
256*4882a593Smuzhiyun struct rkisp1_device *dev = stream->ispdev;
257*4882a593Smuzhiyun const struct v4l2_pix_format_mplane *pixm = NULL;
258*4882a593Smuzhiyun const struct capture_fmt *isp_fmt = NULL;
259*4882a593Smuzhiyun u32 i;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun pixm = &stream->out_fmt;
262*4882a593Smuzhiyun isp_fmt = &stream->out_isp_fmt;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun *num_planes = isp_fmt->mplanes;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun for (i = 0; i < isp_fmt->mplanes; i++) {
267*4882a593Smuzhiyun const struct v4l2_plane_pix_format *plane_fmt;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun plane_fmt = &pixm->plane_fmt[i];
270*4882a593Smuzhiyun sizes[i] = plane_fmt->sizeimage;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "%s count %d, size %d\n",
274*4882a593Smuzhiyun v4l2_type_names[queue->type], *num_buffers, sizes[0]);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun return 0;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /*
280*4882a593Smuzhiyun * The vb2_buffer are stored in rkisp1_buffer, in order to unify
281*4882a593Smuzhiyun * mplane buffer and none-mplane buffer.
282*4882a593Smuzhiyun */
rkisp1_buf_queue(struct vb2_buffer * vb)283*4882a593Smuzhiyun static void rkisp1_buf_queue(struct vb2_buffer *vb)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
286*4882a593Smuzhiyun struct rkisp1_buffer *ispbuf = to_rkisp1_buffer(vbuf);
287*4882a593Smuzhiyun struct vb2_queue *queue = vb->vb2_queue;
288*4882a593Smuzhiyun struct rkisp1_stream *stream = queue->drv_priv;
289*4882a593Smuzhiyun unsigned long lock_flags = 0;
290*4882a593Smuzhiyun struct v4l2_pix_format_mplane *pixm = &stream->out_fmt;
291*4882a593Smuzhiyun struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
292*4882a593Smuzhiyun int i;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr));
295*4882a593Smuzhiyun for (i = 0; i < isp_fmt->mplanes; i++)
296*4882a593Smuzhiyun ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /*
299*4882a593Smuzhiyun * NOTE: plane_fmt[0].sizeimage is total size of all planes for single
300*4882a593Smuzhiyun * memory plane formats, so calculate the size explicitly.
301*4882a593Smuzhiyun */
302*4882a593Smuzhiyun if (isp_fmt->mplanes == 1) {
303*4882a593Smuzhiyun for (i = 0; i < isp_fmt->cplanes - 1; i++) {
304*4882a593Smuzhiyun ispbuf->buff_addr[i + 1] = (i == 0) ?
305*4882a593Smuzhiyun ispbuf->buff_addr[i] +
306*4882a593Smuzhiyun pixm->plane_fmt[i].bytesperline *
307*4882a593Smuzhiyun pixm->height :
308*4882a593Smuzhiyun ispbuf->buff_addr[i] +
309*4882a593Smuzhiyun pixm->plane_fmt[i].sizeimage;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun spin_lock_irqsave(&stream->vbq_lock, lock_flags);
314*4882a593Smuzhiyun if (stream->streaming &&
315*4882a593Smuzhiyun list_empty(&stream->buf_queue) &&
316*4882a593Smuzhiyun !stream->curr_buf) {
317*4882a593Smuzhiyun stream->curr_buf = ispbuf;
318*4882a593Smuzhiyun stream->ops->update_mi(stream);
319*4882a593Smuzhiyun } else {
320*4882a593Smuzhiyun list_add_tail(&ispbuf->queue, &stream->buf_queue);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
dmarx_stop_streaming(struct vb2_queue * queue)325*4882a593Smuzhiyun static void dmarx_stop_streaming(struct vb2_queue *queue)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun struct rkisp1_stream *stream = queue->drv_priv;
328*4882a593Smuzhiyun struct rkisp1_buffer *buf;
329*4882a593Smuzhiyun unsigned long lock_flags = 0;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun dmarx_stop(stream);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun spin_lock_irqsave(&stream->vbq_lock, lock_flags);
334*4882a593Smuzhiyun if (stream->curr_buf) {
335*4882a593Smuzhiyun list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
336*4882a593Smuzhiyun stream->curr_buf = NULL;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun while (!list_empty(&stream->buf_queue)) {
339*4882a593Smuzhiyun buf = list_first_entry(&stream->buf_queue,
340*4882a593Smuzhiyun struct rkisp1_buffer, queue);
341*4882a593Smuzhiyun list_del(&buf->queue);
342*4882a593Smuzhiyun vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
dmarx_start_streaming(struct vb2_queue * queue,unsigned int count)347*4882a593Smuzhiyun static int dmarx_start_streaming(struct vb2_queue *queue,
348*4882a593Smuzhiyun unsigned int count)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun struct rkisp1_stream *stream = queue->drv_priv;
351*4882a593Smuzhiyun struct rkisp1_device *dev = stream->ispdev;
352*4882a593Smuzhiyun struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
353*4882a593Smuzhiyun int ret = 0;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (atomic_read(&dev->open_cnt) < 2) {
356*4882a593Smuzhiyun v4l2_err(v4l2_dev,
357*4882a593Smuzhiyun "other stream should enable first\n");
358*4882a593Smuzhiyun return -EINVAL;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun if (WARN_ON(stream->streaming))
362*4882a593Smuzhiyun return -EBUSY;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun ret = dmarx_start(stream);
365*4882a593Smuzhiyun if (ret < 0)
366*4882a593Smuzhiyun v4l2_err(v4l2_dev,
367*4882a593Smuzhiyun "start dmarx stream:%d failed\n",
368*4882a593Smuzhiyun stream->id);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun return ret;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun static struct vb2_ops dmarx_vb2_ops = {
374*4882a593Smuzhiyun .queue_setup = rkisp1_queue_setup,
375*4882a593Smuzhiyun .buf_queue = rkisp1_buf_queue,
376*4882a593Smuzhiyun .wait_prepare = vb2_ops_wait_prepare,
377*4882a593Smuzhiyun .wait_finish = vb2_ops_wait_finish,
378*4882a593Smuzhiyun .stop_streaming = dmarx_stop_streaming,
379*4882a593Smuzhiyun .start_streaming = dmarx_start_streaming,
380*4882a593Smuzhiyun };
381*4882a593Smuzhiyun
rkisp_init_vb2_queue(struct vb2_queue * q,struct rkisp1_stream * stream,enum v4l2_buf_type buf_type)382*4882a593Smuzhiyun static int rkisp_init_vb2_queue(struct vb2_queue *q,
383*4882a593Smuzhiyun struct rkisp1_stream *stream,
384*4882a593Smuzhiyun enum v4l2_buf_type buf_type)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun q->type = buf_type;
387*4882a593Smuzhiyun q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
388*4882a593Smuzhiyun q->drv_priv = stream;
389*4882a593Smuzhiyun q->ops = &dmarx_vb2_ops;
390*4882a593Smuzhiyun q->mem_ops = &vb2_dma_contig_memops;
391*4882a593Smuzhiyun q->buf_struct_size = sizeof(struct rkisp1_buffer);
392*4882a593Smuzhiyun q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN;
393*4882a593Smuzhiyun q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
394*4882a593Smuzhiyun q->lock = &stream->ispdev->apilock;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun return vb2_queue_init(q);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
rkisp1_set_fmt(struct rkisp1_stream * stream,struct v4l2_pix_format_mplane * pixm,bool try)399*4882a593Smuzhiyun static int rkisp1_set_fmt(struct rkisp1_stream *stream,
400*4882a593Smuzhiyun struct v4l2_pix_format_mplane *pixm,
401*4882a593Smuzhiyun bool try)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun const struct capture_fmt *fmt;
404*4882a593Smuzhiyun unsigned int imagsize = 0;
405*4882a593Smuzhiyun unsigned int planes;
406*4882a593Smuzhiyun u32 xsubs = 1, ysubs = 1;
407*4882a593Smuzhiyun unsigned int i;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun fmt = find_fmt(stream, pixm->pixelformat);
410*4882a593Smuzhiyun if (!fmt) {
411*4882a593Smuzhiyun v4l2_err(&stream->ispdev->v4l2_dev,
412*4882a593Smuzhiyun "nonsupport pixelformat:%c%c%c%c\n",
413*4882a593Smuzhiyun pixm->pixelformat,
414*4882a593Smuzhiyun pixm->pixelformat >> 8,
415*4882a593Smuzhiyun pixm->pixelformat >> 16,
416*4882a593Smuzhiyun pixm->pixelformat >> 24);
417*4882a593Smuzhiyun return -EINVAL;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun pixm->num_planes = fmt->mplanes;
421*4882a593Smuzhiyun pixm->field = V4L2_FIELD_NONE;
422*4882a593Smuzhiyun if (!pixm->quantization)
423*4882a593Smuzhiyun pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun /* calculate size */
426*4882a593Smuzhiyun fcc_xysubs(fmt->fourcc, &xsubs, &ysubs);
427*4882a593Smuzhiyun planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
428*4882a593Smuzhiyun for (i = 0; i < planes; i++) {
429*4882a593Smuzhiyun struct v4l2_plane_pix_format *plane_fmt;
430*4882a593Smuzhiyun unsigned int width, height, bytesperline;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun plane_fmt = pixm->plane_fmt + i;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun if (i == 0) {
435*4882a593Smuzhiyun width = pixm->width;
436*4882a593Smuzhiyun height = pixm->height;
437*4882a593Smuzhiyun } else {
438*4882a593Smuzhiyun width = pixm->width / xsubs;
439*4882a593Smuzhiyun height = pixm->height / ysubs;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8);
443*4882a593Smuzhiyun /* stride is only available for sp stream and y plane */
444*4882a593Smuzhiyun if (i != 0 ||
445*4882a593Smuzhiyun plane_fmt->bytesperline < bytesperline)
446*4882a593Smuzhiyun plane_fmt->bytesperline = bytesperline;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun plane_fmt->sizeimage = plane_fmt->bytesperline * height;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun imagsize += plane_fmt->sizeimage;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun /* convert to non-MPLANE format.
454*4882a593Smuzhiyun * it's important since we want to unify none-MPLANE
455*4882a593Smuzhiyun * and MPLANE.
456*4882a593Smuzhiyun */
457*4882a593Smuzhiyun if (fmt->mplanes == 1)
458*4882a593Smuzhiyun pixm->plane_fmt[0].sizeimage = imagsize;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun if (!try) {
461*4882a593Smuzhiyun stream->out_isp_fmt = *fmt;
462*4882a593Smuzhiyun stream->out_fmt = *pixm;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun stream->u.dmarx.y_stride =
465*4882a593Smuzhiyun pixm->plane_fmt[0].bytesperline /
466*4882a593Smuzhiyun DIV_ROUND_UP(fmt->bpp[0], 8);
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
469*4882a593Smuzhiyun "%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
470*4882a593Smuzhiyun stream->id, pixm->width, pixm->height,
471*4882a593Smuzhiyun stream->out_fmt.width, stream->out_fmt.height);
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun return 0;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /************************* v4l2_file_operations***************************/
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun static const struct v4l2_file_operations rkisp1_fops = {
480*4882a593Smuzhiyun .open = rkisp1_fh_open,
481*4882a593Smuzhiyun .release = rkisp1_fop_release,
482*4882a593Smuzhiyun .unlocked_ioctl = video_ioctl2,
483*4882a593Smuzhiyun .poll = vb2_fop_poll,
484*4882a593Smuzhiyun .mmap = vb2_fop_mmap,
485*4882a593Smuzhiyun };
486*4882a593Smuzhiyun
rkisp1_try_fmt_vid_out_mplane(struct file * file,void * fh,struct v4l2_format * f)487*4882a593Smuzhiyun static int rkisp1_try_fmt_vid_out_mplane(struct file *file, void *fh,
488*4882a593Smuzhiyun struct v4l2_format *f)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun struct rkisp1_stream *stream = video_drvdata(file);
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun return rkisp1_set_fmt(stream, &f->fmt.pix_mp, true);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
rkisp1_enum_fmt_vid_out_mplane(struct file * file,void * priv,struct v4l2_fmtdesc * f)495*4882a593Smuzhiyun static int rkisp1_enum_fmt_vid_out_mplane(struct file *file, void *priv,
496*4882a593Smuzhiyun struct v4l2_fmtdesc *f)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun struct rkisp1_stream *stream = video_drvdata(file);
499*4882a593Smuzhiyun const struct capture_fmt *fmt = NULL;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (f->index >= stream->config->fmt_size)
502*4882a593Smuzhiyun return -EINVAL;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun fmt = &stream->config->fmts[f->index];
505*4882a593Smuzhiyun f->pixelformat = fmt->fourcc;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun return 0;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
rkisp1_s_fmt_vid_out_mplane(struct file * file,void * priv,struct v4l2_format * f)510*4882a593Smuzhiyun static int rkisp1_s_fmt_vid_out_mplane(struct file *file,
511*4882a593Smuzhiyun void *priv, struct v4l2_format *f)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun struct rkisp1_stream *stream = video_drvdata(file);
514*4882a593Smuzhiyun struct video_device *vdev = &stream->vnode.vdev;
515*4882a593Smuzhiyun struct rkisp1_vdev_node *node = vdev_to_node(vdev);
516*4882a593Smuzhiyun struct rkisp1_device *dev = stream->ispdev;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun if (vb2_is_busy(&node->buf_queue)) {
519*4882a593Smuzhiyun v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
520*4882a593Smuzhiyun return -EBUSY;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun return rkisp1_set_fmt(stream, &f->fmt.pix_mp, false);
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
rkisp1_g_fmt_vid_out_mplane(struct file * file,void * fh,struct v4l2_format * f)526*4882a593Smuzhiyun static int rkisp1_g_fmt_vid_out_mplane(struct file *file, void *fh,
527*4882a593Smuzhiyun struct v4l2_format *f)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun struct rkisp1_stream *stream = video_drvdata(file);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun f->fmt.pix_mp = stream->out_fmt;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun return 0;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
rkisp1_querycap(struct file * file,void * priv,struct v4l2_capability * cap)536*4882a593Smuzhiyun static int rkisp1_querycap(struct file *file, void *priv,
537*4882a593Smuzhiyun struct v4l2_capability *cap)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun struct rkisp1_stream *stream = video_drvdata(file);
540*4882a593Smuzhiyun struct device *dev = stream->ispdev->dev;
541*4882a593Smuzhiyun struct video_device *vdev = video_devdata(file);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun strlcpy(cap->card, vdev->name, sizeof(cap->card));
544*4882a593Smuzhiyun snprintf(cap->driver, sizeof(cap->driver),
545*4882a593Smuzhiyun "%s_v%d", dev->driver->name,
546*4882a593Smuzhiyun stream->ispdev->isp_ver >> 4);
547*4882a593Smuzhiyun snprintf(cap->bus_info, sizeof(cap->bus_info),
548*4882a593Smuzhiyun "platform:%s", dev_name(dev));
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun static const struct v4l2_ioctl_ops rkisp1_dmarx_ioctl = {
554*4882a593Smuzhiyun .vidioc_reqbufs = vb2_ioctl_reqbufs,
555*4882a593Smuzhiyun .vidioc_querybuf = vb2_ioctl_querybuf,
556*4882a593Smuzhiyun .vidioc_create_bufs = vb2_ioctl_create_bufs,
557*4882a593Smuzhiyun .vidioc_qbuf = vb2_ioctl_qbuf,
558*4882a593Smuzhiyun .vidioc_expbuf = vb2_ioctl_expbuf,
559*4882a593Smuzhiyun .vidioc_dqbuf = vb2_ioctl_dqbuf,
560*4882a593Smuzhiyun .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
561*4882a593Smuzhiyun .vidioc_streamon = vb2_ioctl_streamon,
562*4882a593Smuzhiyun .vidioc_streamoff = vb2_ioctl_streamoff,
563*4882a593Smuzhiyun .vidioc_try_fmt_vid_out_mplane = rkisp1_try_fmt_vid_out_mplane,
564*4882a593Smuzhiyun .vidioc_enum_fmt_vid_out = rkisp1_enum_fmt_vid_out_mplane,
565*4882a593Smuzhiyun .vidioc_s_fmt_vid_out_mplane = rkisp1_s_fmt_vid_out_mplane,
566*4882a593Smuzhiyun .vidioc_g_fmt_vid_out_mplane = rkisp1_g_fmt_vid_out_mplane,
567*4882a593Smuzhiyun .vidioc_querycap = rkisp1_querycap,
568*4882a593Smuzhiyun };
569*4882a593Smuzhiyun
rkisp1_unregister_dmarx_video(struct rkisp1_stream * stream)570*4882a593Smuzhiyun static void rkisp1_unregister_dmarx_video(struct rkisp1_stream *stream)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun media_entity_cleanup(&stream->vnode.vdev.entity);
573*4882a593Smuzhiyun video_unregister_device(&stream->vnode.vdev);
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
rkisp1_register_dmarx_video(struct rkisp1_stream * stream)576*4882a593Smuzhiyun static int rkisp1_register_dmarx_video(struct rkisp1_stream *stream)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun struct rkisp1_device *dev = stream->ispdev;
579*4882a593Smuzhiyun struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
580*4882a593Smuzhiyun struct video_device *vdev = &stream->vnode.vdev;
581*4882a593Smuzhiyun struct rkisp1_vdev_node *node;
582*4882a593Smuzhiyun int ret = 0;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun node = vdev_to_node(vdev);
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun vdev->release = video_device_release_empty;
587*4882a593Smuzhiyun vdev->fops = &rkisp1_fops;
588*4882a593Smuzhiyun vdev->minor = -1;
589*4882a593Smuzhiyun vdev->v4l2_dev = v4l2_dev;
590*4882a593Smuzhiyun vdev->lock = &dev->apilock;
591*4882a593Smuzhiyun video_set_drvdata(vdev, stream);
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun vdev->ioctl_ops = &rkisp1_dmarx_ioctl;
594*4882a593Smuzhiyun vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE |
595*4882a593Smuzhiyun V4L2_CAP_STREAMING;
596*4882a593Smuzhiyun vdev->vfl_dir = VFL_DIR_TX;
597*4882a593Smuzhiyun node->pad.flags = MEDIA_PAD_FL_SOURCE;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun rkisp_init_vb2_queue(&node->buf_queue, stream,
600*4882a593Smuzhiyun V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
601*4882a593Smuzhiyun vdev->queue = &node->buf_queue;
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
604*4882a593Smuzhiyun if (ret < 0) {
605*4882a593Smuzhiyun v4l2_err(v4l2_dev,
606*4882a593Smuzhiyun "video register failed with error %d\n", ret);
607*4882a593Smuzhiyun return ret;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
611*4882a593Smuzhiyun if (ret < 0)
612*4882a593Smuzhiyun goto unreg;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun return 0;
615*4882a593Smuzhiyun unreg:
616*4882a593Smuzhiyun video_unregister_device(vdev);
617*4882a593Smuzhiyun return ret;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun /**************** Interrupter Handler ****************/
621*4882a593Smuzhiyun
rkisp1_dmarx_isr(u32 mis_val,struct rkisp1_device * dev)622*4882a593Smuzhiyun void rkisp1_dmarx_isr(u32 mis_val, struct rkisp1_device *dev)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun void __iomem *base = dev->base_addr;
625*4882a593Smuzhiyun struct rkisp1_stream *stream;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun if (mis_val & CIF_MI_DMA_READY) {
628*4882a593Smuzhiyun stream = &dev->dmarx_dev.stream[RKISP1_STREAM_DMARX];
629*4882a593Smuzhiyun stream->frame_end = true;
630*4882a593Smuzhiyun writel(CIF_MI_DMA_READY, base + CIF_MI_ICR);
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun if (stream->stopping) {
633*4882a593Smuzhiyun stream->stopping = false;
634*4882a593Smuzhiyun stream->streaming = false;
635*4882a593Smuzhiyun wake_up(&stream->done);
636*4882a593Smuzhiyun } else {
637*4882a593Smuzhiyun dmarx_frame_end(stream);
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
rkisp1_register_dmarx_vdev(struct rkisp1_device * dev)642*4882a593Smuzhiyun int rkisp1_register_dmarx_vdev(struct rkisp1_device *dev)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun struct rkisp1_dmarx_device *dmarx_dev = &dev->dmarx_dev;
645*4882a593Smuzhiyun struct rkisp1_stream *stream;
646*4882a593Smuzhiyun struct video_device *vdev;
647*4882a593Smuzhiyun struct media_entity *source, *sink;
648*4882a593Smuzhiyun int ret = 0;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun memset(dmarx_dev, 0, sizeof(*dmarx_dev));
651*4882a593Smuzhiyun dmarx_dev->ispdev = dev;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun if (dev->isp_ver <= ISP_V13) {
654*4882a593Smuzhiyun stream = &dmarx_dev->stream[RKISP1_STREAM_DMARX];
655*4882a593Smuzhiyun INIT_LIST_HEAD(&stream->buf_queue);
656*4882a593Smuzhiyun init_waitqueue_head(&stream->done);
657*4882a593Smuzhiyun spin_lock_init(&stream->vbq_lock);
658*4882a593Smuzhiyun stream->id = RKISP1_STREAM_DMARX;
659*4882a593Smuzhiyun stream->ispdev = dev;
660*4882a593Smuzhiyun stream->ops = &rkisp1_dmarx_streams_ops;
661*4882a593Smuzhiyun stream->config = &rkisp1_dmarx_stream_config;
662*4882a593Smuzhiyun vdev = &stream->vnode.vdev;
663*4882a593Smuzhiyun strlcpy(vdev->name, DMA_VDEV_NAME, sizeof(vdev->name));
664*4882a593Smuzhiyun ret = rkisp1_register_dmarx_video(stream);
665*4882a593Smuzhiyun if (ret < 0)
666*4882a593Smuzhiyun return ret;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* dmarx links -> isp subdev */
669*4882a593Smuzhiyun source = &vdev->entity;
670*4882a593Smuzhiyun sink = &dev->isp_sdev.sd.entity;
671*4882a593Smuzhiyun ret = media_create_pad_link(source, 0,
672*4882a593Smuzhiyun sink, RKISP1_ISP_PAD_SINK, 0);
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun return ret;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
rkisp1_unregister_dmarx_vdev(struct rkisp1_device * dev)678*4882a593Smuzhiyun void rkisp1_unregister_dmarx_vdev(struct rkisp1_device *dev)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun struct rkisp1_dmarx_device *dmarx_dev = &dev->dmarx_dev;
681*4882a593Smuzhiyun struct rkisp1_stream *stream;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (dev->isp_ver <= ISP_V13) {
684*4882a593Smuzhiyun stream = &dmarx_dev->stream[RKISP1_STREAM_DMARX];
685*4882a593Smuzhiyun rkisp1_unregister_dmarx_video(stream);
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun }
688