c0ba458f6cf3781a05839d2b47a36711ad6daa3d
[sfrench/cifs-2.6.git] / drivers / media / pci / cobalt / cobalt-v4l2.c
1 /*
2  *  cobalt V4L2 API
3  *
4  *  Derived from ivtv-ioctl.c and cx18-fileops.c
5  *
6  *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
7  *  All rights reserved.
8  *
9  *  This program is free software; you may redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; version 2 of the License.
12  *
13  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
17  *  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18  *  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  *  SOFTWARE.
21  */
22
23 #include <linux/dma-mapping.h>
24 #include <linux/delay.h>
25 #include <linux/math64.h>
26 #include <linux/pci.h>
27 #include <linux/v4l2-dv-timings.h>
28
29 #include <media/v4l2-ctrls.h>
30 #include <media/v4l2-event.h>
31 #include <media/v4l2-dv-timings.h>
32 #include <media/i2c/adv7604.h>
33 #include <media/i2c/adv7842.h>
34
35 #include "cobalt-alsa.h"
36 #include "cobalt-cpld.h"
37 #include "cobalt-driver.h"
38 #include "cobalt-v4l2.h"
39 #include "cobalt-irq.h"
40 #include "cobalt-omnitek.h"
41
42 static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
43
44 /* vb2 DMA streaming ops */
45
46 static int cobalt_queue_setup(struct vb2_queue *q,
47                         unsigned int *num_buffers, unsigned int *num_planes,
48                         unsigned int sizes[], void *alloc_ctxs[])
49 {
50         struct cobalt_stream *s = q->drv_priv;
51         unsigned size = s->stride * s->height;
52
53         if (*num_buffers < 3)
54                 *num_buffers = 3;
55         if (*num_buffers > NR_BUFS)
56                 *num_buffers = NR_BUFS;
57         alloc_ctxs[0] = s->cobalt->alloc_ctx;
58         if (*num_planes)
59                 return sizes[0] < size ? -EINVAL : 0;
60         *num_planes = 1;
61         sizes[0] = size;
62         return 0;
63 }
64
65 static int cobalt_buf_init(struct vb2_buffer *vb)
66 {
67         struct cobalt_stream *s = vb->vb2_queue->drv_priv;
68         struct cobalt *cobalt = s->cobalt;
69         const size_t max_pages_per_line =
70                 (COBALT_MAX_WIDTH * COBALT_MAX_BPP) / PAGE_SIZE + 2;
71         const size_t bytes =
72                 COBALT_MAX_HEIGHT * max_pages_per_line * 0x20;
73         const size_t audio_bytes = ((1920 * 4) / PAGE_SIZE + 1) * 0x20;
74         struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index];
75         struct sg_table *sg_desc = vb2_dma_sg_plane_desc(vb, 0);
76         unsigned size;
77         int ret;
78
79         size = s->stride * s->height;
80         if (vb2_plane_size(vb, 0) < size) {
81                 cobalt_info("data will not fit into plane (%lu < %u)\n",
82                                         vb2_plane_size(vb, 0), size);
83                 return -EINVAL;
84         }
85
86         if (desc->virt == NULL) {
87                 desc->dev = &cobalt->pci_dev->dev;
88                 descriptor_list_allocate(desc,
89                         s->is_audio ? audio_bytes : bytes);
90                 if (desc->virt == NULL)
91                         return -ENOMEM;
92         }
93         ret = descriptor_list_create(cobalt, sg_desc->sgl,
94                         !s->is_output, sg_desc->nents, size,
95                         s->width * s->bpp, s->stride, desc);
96         if (ret)
97                 descriptor_list_free(desc);
98         return ret;
99 }
100
101 static void cobalt_buf_cleanup(struct vb2_buffer *vb)
102 {
103         struct cobalt_stream *s = vb->vb2_queue->drv_priv;
104         struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index];
105
106         descriptor_list_free(desc);
107 }
108
109 static int cobalt_buf_prepare(struct vb2_buffer *vb)
110 {
111         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
112         struct cobalt_stream *s = vb->vb2_queue->drv_priv;
113
114         vb2_set_plane_payload(vb, 0, s->stride * s->height);
115         vbuf->field = V4L2_FIELD_NONE;
116         return 0;
117 }
118
119 static void chain_all_buffers(struct cobalt_stream *s)
120 {
121         struct sg_dma_desc_info *desc[NR_BUFS];
122         struct cobalt_buffer *cb;
123         struct list_head *p;
124         int i = 0;
125
126         list_for_each(p, &s->bufs) {
127                 cb = list_entry(p, struct cobalt_buffer, list);
128                 desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index];
129                 if (i > 0)
130                         descriptor_list_chain(desc[i-1], desc[i]);
131                 i++;
132         }
133 }
134
135 static void cobalt_buf_queue(struct vb2_buffer *vb)
136 {
137         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
138         struct vb2_queue *q = vb->vb2_queue;
139         struct cobalt_stream *s = q->drv_priv;
140         struct cobalt_buffer *cb = to_cobalt_buffer(vbuf);
141         struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index];
142         unsigned long flags;
143
144         /* Prepare new buffer */
145         descriptor_list_loopback(desc);
146         descriptor_list_interrupt_disable(desc);
147
148         spin_lock_irqsave(&s->irqlock, flags);
149         list_add_tail(&cb->list, &s->bufs);
150         chain_all_buffers(s);
151         spin_unlock_irqrestore(&s->irqlock, flags);
152 }
153
154 static void cobalt_enable_output(struct cobalt_stream *s)
155 {
156         struct cobalt *cobalt = s->cobalt;
157         struct v4l2_bt_timings *bt = &s->timings.bt;
158         struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
159                 COBALT_TX_BASE(cobalt);
160         unsigned fmt = s->pixfmt != V4L2_PIX_FMT_BGR32 ?
161                         M00514_CONTROL_BITMAP_FORMAT_16_BPP_MSK : 0;
162         struct v4l2_subdev_format sd_fmt = {
163                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
164         };
165
166         if (!cobalt_cpld_set_freq(cobalt, bt->pixelclock)) {
167                 cobalt_err("pixelclock out of range\n");
168                 return;
169         }
170
171         sd_fmt.format.colorspace = s->colorspace;
172         sd_fmt.format.xfer_func = s->xfer_func;
173         sd_fmt.format.ycbcr_enc = s->ycbcr_enc;
174         sd_fmt.format.quantization = s->quantization;
175         sd_fmt.format.width = bt->width;
176         sd_fmt.format.height = bt->height;
177
178         /* Set up FDMA packer */
179         switch (s->pixfmt) {
180         case V4L2_PIX_FMT_YUYV:
181                 sd_fmt.format.code = MEDIA_BUS_FMT_UYVY8_1X16;
182                 break;
183         case V4L2_PIX_FMT_BGR32:
184                 sd_fmt.format.code = MEDIA_BUS_FMT_RGB888_1X24;
185                 break;
186         }
187         v4l2_subdev_call(s->sd, pad, set_fmt, NULL, &sd_fmt);
188
189         iowrite32(0, &vo->control);
190         /* 1080p60 */
191         iowrite32(bt->hsync, &vo->sync_generator_h_sync_length);
192         iowrite32(bt->hbackporch, &vo->sync_generator_h_backporch_length);
193         iowrite32(bt->width, &vo->sync_generator_h_active_length);
194         iowrite32(bt->hfrontporch, &vo->sync_generator_h_frontporch_length);
195         iowrite32(bt->vsync, &vo->sync_generator_v_sync_length);
196         iowrite32(bt->vbackporch, &vo->sync_generator_v_backporch_length);
197         iowrite32(bt->height, &vo->sync_generator_v_active_length);
198         iowrite32(bt->vfrontporch, &vo->sync_generator_v_frontporch_length);
199         iowrite32(0x9900c1, &vo->error_color);
200
201         iowrite32(M00514_CONTROL_BITMAP_SYNC_GENERATOR_LOAD_PARAM_MSK | fmt,
202                   &vo->control);
203         iowrite32(M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK | fmt, &vo->control);
204         iowrite32(M00514_CONTROL_BITMAP_SYNC_GENERATOR_ENABLE_MSK |
205                   M00514_CONTROL_BITMAP_FLOW_CTRL_OUTPUT_ENABLE_MSK |
206                   fmt, &vo->control);
207 }
208
209 static void cobalt_enable_input(struct cobalt_stream *s)
210 {
211         struct cobalt *cobalt = s->cobalt;
212         int ch = (int)s->video_channel;
213         struct m00235_fdma_packer_regmap __iomem *packer;
214         struct v4l2_subdev_format sd_fmt_yuyv = {
215                 .pad = s->pad_source,
216                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
217                 .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
218         };
219         struct v4l2_subdev_format sd_fmt_rgb = {
220                 .pad = s->pad_source,
221                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
222                 .format.code = MEDIA_BUS_FMT_RGB888_1X24,
223         };
224
225         cobalt_dbg(1, "video_channel %d (%s, %s)\n",
226                    s->video_channel,
227                    s->input == 0 ? "hdmi" : "generator",
228                    "YUYV");
229
230         packer = COBALT_CVI_PACKER(cobalt, ch);
231
232         /* Set up FDMA packer */
233         switch (s->pixfmt) {
234         case V4L2_PIX_FMT_YUYV:
235                 iowrite32(M00235_CONTROL_BITMAP_ENABLE_MSK |
236                           (1 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST),
237                           &packer->control);
238                 v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
239                                  &sd_fmt_yuyv);
240                 break;
241         case V4L2_PIX_FMT_RGB24:
242                 iowrite32(M00235_CONTROL_BITMAP_ENABLE_MSK |
243                           (2 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST),
244                           &packer->control);
245                 v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
246                                  &sd_fmt_rgb);
247                 break;
248         case V4L2_PIX_FMT_BGR32:
249                 iowrite32(M00235_CONTROL_BITMAP_ENABLE_MSK |
250                           M00235_CONTROL_BITMAP_ENDIAN_FORMAT_MSK |
251                           (3 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST),
252                           &packer->control);
253                 v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
254                                  &sd_fmt_rgb);
255                 break;
256         }
257 }
258
259 static void cobalt_dma_start_streaming(struct cobalt_stream *s)
260 {
261         struct cobalt *cobalt = s->cobalt;
262         int rx = s->video_channel;
263         struct m00460_evcnt_regmap __iomem *evcnt =
264                 COBALT_CVI_EVCNT(cobalt, rx);
265         struct cobalt_buffer *cb;
266         unsigned long flags;
267
268         spin_lock_irqsave(&s->irqlock, flags);
269         if (!s->is_output) {
270                 iowrite32(M00460_CONTROL_BITMAP_CLEAR_MSK, &evcnt->control);
271                 iowrite32(M00460_CONTROL_BITMAP_ENABLE_MSK, &evcnt->control);
272         } else {
273                 struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
274                         COBALT_TX_BASE(cobalt);
275                 u32 ctrl = ioread32(&vo->control);
276
277                 ctrl &= ~(M00514_CONTROL_BITMAP_EVCNT_ENABLE_MSK |
278                           M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK);
279                 iowrite32(ctrl | M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK,
280                           &vo->control);
281                 iowrite32(ctrl | M00514_CONTROL_BITMAP_EVCNT_ENABLE_MSK,
282                           &vo->control);
283         }
284         cb = list_first_entry(&s->bufs, struct cobalt_buffer, list);
285         omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.vb2_buf.index]);
286         spin_unlock_irqrestore(&s->irqlock, flags);
287 }
288
289 static int cobalt_start_streaming(struct vb2_queue *q, unsigned int count)
290 {
291         struct cobalt_stream *s = q->drv_priv;
292         struct cobalt *cobalt = s->cobalt;
293         struct m00233_video_measure_regmap __iomem *vmr;
294         struct m00473_freewheel_regmap __iomem *fw;
295         struct m00479_clk_loss_detector_regmap __iomem *clkloss;
296         int rx = s->video_channel;
297         struct m00389_cvi_regmap __iomem *cvi = COBALT_CVI(cobalt, rx);
298         struct m00460_evcnt_regmap __iomem *evcnt = COBALT_CVI_EVCNT(cobalt, rx);
299         struct v4l2_bt_timings *bt = &s->timings.bt;
300         u64 tot_size;
301         u32 clk_freq;
302
303         if (s->is_audio)
304                 goto done;
305         if (s->is_output) {
306                 s->unstable_frame = false;
307                 cobalt_enable_output(s);
308                 goto done;
309         }
310
311         cobalt_enable_input(s);
312
313         fw = COBALT_CVI_FREEWHEEL(cobalt, rx);
314         vmr = COBALT_CVI_VMR(cobalt, rx);
315         clkloss = COBALT_CVI_CLK_LOSS(cobalt, rx);
316
317         iowrite32(M00460_CONTROL_BITMAP_CLEAR_MSK, &evcnt->control);
318         iowrite32(M00460_CONTROL_BITMAP_ENABLE_MSK, &evcnt->control);
319         iowrite32(bt->width, &cvi->frame_width);
320         iowrite32(bt->height, &cvi->frame_height);
321         tot_size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
322         iowrite32(div_u64((u64)V4L2_DV_BT_FRAME_WIDTH(bt) * COBALT_CLK * 4,
323                           bt->pixelclock), &vmr->hsync_timeout_val);
324         iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK, &vmr->control);
325         clk_freq = ioread32(&fw->clk_freq);
326         iowrite32(clk_freq / 1000000, &clkloss->ref_clk_cnt_val);
327         /* The lower bound for the clock frequency is 0.5% lower as is
328          * allowed by the spec */
329         iowrite32(div_u64(bt->pixelclock * 995, 1000000000),
330                   &clkloss->test_clk_cnt_val);
331         /* will be enabled after the first frame has been received */
332         iowrite32(bt->width * bt->height, &fw->active_length);
333         iowrite32(div_u64((u64)clk_freq * tot_size, bt->pixelclock),
334                   &fw->total_length);
335         iowrite32(M00233_IRQ_TRIGGERS_BITMAP_VACTIVE_AREA_MSK |
336                   M00233_IRQ_TRIGGERS_BITMAP_HACTIVE_AREA_MSK,
337                   &vmr->irq_triggers);
338         iowrite32(0, &cvi->control);
339         iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK, &vmr->control);
340
341         iowrite32(0xff, &fw->output_color);
342         iowrite32(M00479_CTRL_BITMAP_ENABLE_MSK, &clkloss->ctrl);
343         iowrite32(M00473_CTRL_BITMAP_ENABLE_MSK |
344                   M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK, &fw->ctrl);
345         s->unstable_frame = true;
346         s->enable_freewheel = false;
347         s->enable_cvi = false;
348         s->skip_first_frames = 0;
349
350 done:
351         s->sequence = 0;
352         cobalt_dma_start_streaming(s);
353         return 0;
354 }
355
356 static void cobalt_dma_stop_streaming(struct cobalt_stream *s)
357 {
358         struct cobalt *cobalt = s->cobalt;
359         struct sg_dma_desc_info *desc;
360         struct cobalt_buffer *cb;
361         struct list_head *p;
362         unsigned long flags;
363         int timeout_msec = 100;
364         int rx = s->video_channel;
365         struct m00460_evcnt_regmap __iomem *evcnt =
366                 COBALT_CVI_EVCNT(cobalt, rx);
367
368         if (!s->is_output) {
369                 iowrite32(0, &evcnt->control);
370         } else if (!s->is_audio) {
371                 struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
372                         COBALT_TX_BASE(cobalt);
373
374                 iowrite32(M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK, &vo->control);
375                 iowrite32(0, &vo->control);
376         }
377
378         /* Try to stop the DMA engine gracefully */
379         spin_lock_irqsave(&s->irqlock, flags);
380         list_for_each(p, &s->bufs) {
381                 cb = list_entry(p, struct cobalt_buffer, list);
382                 desc = &s->dma_desc_info[cb->vb.vb2_buf.index];
383                 /* Stop DMA after this descriptor chain */
384                 descriptor_list_end_of_chain(desc);
385         }
386         spin_unlock_irqrestore(&s->irqlock, flags);
387
388         /* Wait 100 milisecond for DMA to finish, abort on timeout. */
389         if (!wait_event_timeout(s->q.done_wq, is_dma_done(s),
390                                 msecs_to_jiffies(timeout_msec))) {
391                 omni_sg_dma_abort_channel(s);
392                 pr_warn("aborted\n");
393         }
394         cobalt_write_bar0(cobalt, DMA_INTERRUPT_STATUS_REG,
395                         1 << s->dma_channel);
396 }
397
398 static void cobalt_stop_streaming(struct vb2_queue *q)
399 {
400         struct cobalt_stream *s = q->drv_priv;
401         struct cobalt *cobalt = s->cobalt;
402         int rx = s->video_channel;
403         struct m00233_video_measure_regmap __iomem *vmr;
404         struct m00473_freewheel_regmap __iomem *fw;
405         struct m00479_clk_loss_detector_regmap __iomem *clkloss;
406         struct cobalt_buffer *cb;
407         struct list_head *p, *safe;
408         unsigned long flags;
409
410         cobalt_dma_stop_streaming(s);
411
412         /* Return all buffers to user space */
413         spin_lock_irqsave(&s->irqlock, flags);
414         list_for_each_safe(p, safe, &s->bufs) {
415                 cb = list_entry(p, struct cobalt_buffer, list);
416                 list_del(&cb->list);
417                 vb2_buffer_done(&cb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
418         }
419         spin_unlock_irqrestore(&s->irqlock, flags);
420
421         if (s->is_audio || s->is_output)
422                 return;
423
424         fw = COBALT_CVI_FREEWHEEL(cobalt, rx);
425         vmr = COBALT_CVI_VMR(cobalt, rx);
426         clkloss = COBALT_CVI_CLK_LOSS(cobalt, rx);
427         iowrite32(0, &vmr->control);
428         iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK, &vmr->control);
429         iowrite32(0, &fw->ctrl);
430         iowrite32(0, &clkloss->ctrl);
431 }
432
433 static const struct vb2_ops cobalt_qops = {
434         .queue_setup = cobalt_queue_setup,
435         .buf_init = cobalt_buf_init,
436         .buf_cleanup = cobalt_buf_cleanup,
437         .buf_prepare = cobalt_buf_prepare,
438         .buf_queue = cobalt_buf_queue,
439         .start_streaming = cobalt_start_streaming,
440         .stop_streaming = cobalt_stop_streaming,
441         .wait_prepare = vb2_ops_wait_prepare,
442         .wait_finish = vb2_ops_wait_finish,
443 };
444
445 /* V4L2 ioctls */
446
447 #ifdef CONFIG_VIDEO_ADV_DEBUG
448 static int cobalt_cobaltc(struct cobalt *cobalt, unsigned int cmd, void *arg)
449 {
450         struct v4l2_dbg_register *regs = arg;
451         void __iomem *adrs = cobalt->bar1 + regs->reg;
452
453         cobalt_info("cobalt_cobaltc: adrs = %p\n", adrs);
454
455         if (!capable(CAP_SYS_ADMIN))
456                 return -EPERM;
457
458         regs->size = 4;
459         if (cmd == VIDIOC_DBG_S_REGISTER)
460                 iowrite32(regs->val, adrs);
461         else
462                 regs->val = ioread32(adrs);
463         return 0;
464 }
465
466 static int cobalt_g_register(struct file *file, void *priv_fh,
467                 struct v4l2_dbg_register *reg)
468 {
469         struct cobalt_stream *s = video_drvdata(file);
470         struct cobalt *cobalt = s->cobalt;
471
472         return cobalt_cobaltc(cobalt, VIDIOC_DBG_G_REGISTER, reg);
473 }
474
475 static int cobalt_s_register(struct file *file, void *priv_fh,
476                 const struct v4l2_dbg_register *reg)
477 {
478         struct cobalt_stream *s = video_drvdata(file);
479         struct cobalt *cobalt = s->cobalt;
480
481         return cobalt_cobaltc(cobalt, VIDIOC_DBG_S_REGISTER,
482                         (struct v4l2_dbg_register *)reg);
483 }
484 #endif
485
486 static int cobalt_querycap(struct file *file, void *priv_fh,
487                                 struct v4l2_capability *vcap)
488 {
489         struct cobalt_stream *s = video_drvdata(file);
490         struct cobalt *cobalt = s->cobalt;
491
492         strlcpy(vcap->driver, "cobalt", sizeof(vcap->driver));
493         strlcpy(vcap->card, "cobalt", sizeof(vcap->card));
494         snprintf(vcap->bus_info, sizeof(vcap->bus_info),
495                  "PCIe:%s", pci_name(cobalt->pci_dev));
496         vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
497         if (s->is_output)
498                 vcap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
499         else
500                 vcap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
501         vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS |
502                 V4L2_CAP_VIDEO_CAPTURE;
503         if (cobalt->have_hsma_tx)
504                 vcap->capabilities |= V4L2_CAP_VIDEO_OUTPUT;
505         return 0;
506 }
507
508 static void cobalt_video_input_status_show(struct cobalt_stream *s)
509 {
510         struct m00389_cvi_regmap __iomem *cvi;
511         struct m00233_video_measure_regmap __iomem *vmr;
512         struct m00473_freewheel_regmap __iomem *fw;
513         struct m00479_clk_loss_detector_regmap __iomem *clkloss;
514         struct m00235_fdma_packer_regmap __iomem *packer;
515         int rx = s->video_channel;
516         struct cobalt *cobalt = s->cobalt;
517         u32 cvi_ctrl, cvi_stat;
518         u32 vmr_ctrl, vmr_stat;
519
520         cvi = COBALT_CVI(cobalt, rx);
521         vmr = COBALT_CVI_VMR(cobalt, rx);
522         fw = COBALT_CVI_FREEWHEEL(cobalt, rx);
523         clkloss = COBALT_CVI_CLK_LOSS(cobalt, rx);
524         packer = COBALT_CVI_PACKER(cobalt, rx);
525         cvi_ctrl = ioread32(&cvi->control);
526         cvi_stat = ioread32(&cvi->status);
527         vmr_ctrl = ioread32(&vmr->control);
528         vmr_stat = ioread32(&vmr->control);
529         cobalt_info("rx%d: cvi resolution: %dx%d\n", rx,
530                     ioread32(&cvi->frame_width), ioread32(&cvi->frame_height));
531         cobalt_info("rx%d: cvi control: %s%s%s\n", rx,
532                 (cvi_ctrl & M00389_CONTROL_BITMAP_ENABLE_MSK) ?
533                         "enable " : "disable ",
534                 (cvi_ctrl & M00389_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK) ?
535                         "HSync- " : "HSync+ ",
536                 (cvi_ctrl & M00389_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK) ?
537                         "VSync- " : "VSync+ ");
538         cobalt_info("rx%d: cvi status: %s%s\n", rx,
539                 (cvi_stat & M00389_STATUS_BITMAP_LOCK_MSK) ?
540                         "lock " : "no-lock ",
541                 (cvi_stat & M00389_STATUS_BITMAP_ERROR_MSK) ?
542                         "error " : "no-error ");
543
544         cobalt_info("rx%d: Measurements: %s%s%s%s%s%s%s\n", rx,
545                 (vmr_ctrl & M00233_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK) ?
546                         "HSync- " : "HSync+ ",
547                 (vmr_ctrl & M00233_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK) ?
548                         "VSync- " : "VSync+ ",
549                 (vmr_ctrl & M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK) ?
550                         "enabled " : "disabled ",
551                 (vmr_ctrl & M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_MSK) ?
552                         "irq-enabled " : "irq-disabled ",
553                 (vmr_ctrl & M00233_CONTROL_BITMAP_UPDATE_ON_HSYNC_MSK) ?
554                         "update-on-hsync " : "",
555                 (vmr_stat & M00233_STATUS_BITMAP_HSYNC_TIMEOUT_MSK) ?
556                         "hsync-timeout " : "",
557                 (vmr_stat & M00233_STATUS_BITMAP_INIT_DONE_MSK) ?
558                         "init-done" : "");
559         cobalt_info("rx%d: irq_status: 0x%02x irq_triggers: 0x%02x\n", rx,
560                         ioread32(&vmr->irq_status) & 0xff,
561                         ioread32(&vmr->irq_triggers) & 0xff);
562         cobalt_info("rx%d: vsync: %d\n", rx, ioread32(&vmr->vsync_time));
563         cobalt_info("rx%d: vbp: %d\n", rx, ioread32(&vmr->vback_porch));
564         cobalt_info("rx%d: vact: %d\n", rx, ioread32(&vmr->vactive_area));
565         cobalt_info("rx%d: vfb: %d\n", rx, ioread32(&vmr->vfront_porch));
566         cobalt_info("rx%d: hsync: %d\n", rx, ioread32(&vmr->hsync_time));
567         cobalt_info("rx%d: hbp: %d\n", rx, ioread32(&vmr->hback_porch));
568         cobalt_info("rx%d: hact: %d\n", rx, ioread32(&vmr->hactive_area));
569         cobalt_info("rx%d: hfb: %d\n", rx, ioread32(&vmr->hfront_porch));
570         cobalt_info("rx%d: Freewheeling: %s%s%s\n", rx,
571                 (ioread32(&fw->ctrl) & M00473_CTRL_BITMAP_ENABLE_MSK) ?
572                         "enabled " : "disabled ",
573                 (ioread32(&fw->ctrl) & M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK) ?
574                         "forced " : "",
575                 (ioread32(&fw->status) & M00473_STATUS_BITMAP_FREEWHEEL_MODE_MSK) ?
576                         "freewheeling " : "video-passthrough ");
577         iowrite32(0xff, &vmr->irq_status);
578         cobalt_info("rx%d: Clock Loss Detection: %s%s\n", rx,
579                 (ioread32(&clkloss->ctrl) & M00479_CTRL_BITMAP_ENABLE_MSK) ?
580                         "enabled " : "disabled ",
581                 (ioread32(&clkloss->status) & M00479_STATUS_BITMAP_CLOCK_MISSING_MSK) ?
582                         "clock-missing " : "found-clock ");
583         cobalt_info("rx%d: Packer: %x\n", rx, ioread32(&packer->control));
584 }
585
586 static int cobalt_log_status(struct file *file, void *priv_fh)
587 {
588         struct cobalt_stream *s = video_drvdata(file);
589         struct cobalt *cobalt = s->cobalt;
590         struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
591                 COBALT_TX_BASE(cobalt);
592         u8 stat;
593
594         cobalt_info("%s", cobalt->hdl_info);
595         cobalt_info("sysctrl: %08x, sysstat: %08x\n",
596                         cobalt_g_sysctrl(cobalt),
597                         cobalt_g_sysstat(cobalt));
598         cobalt_info("dma channel: %d, video channel: %d\n",
599                         s->dma_channel, s->video_channel);
600         cobalt_pcie_status_show(cobalt);
601         cobalt_cpld_status(cobalt);
602         cobalt_irq_log_status(cobalt);
603         v4l2_subdev_call(s->sd, core, log_status);
604         if (!s->is_output) {
605                 cobalt_video_input_status_show(s);
606                 return 0;
607         }
608
609         stat = ioread32(&vo->rd_status);
610
611         cobalt_info("tx: status: %s%s\n",
612                 (stat & M00514_RD_STATUS_BITMAP_FLOW_CTRL_NO_DATA_ERROR_MSK) ?
613                         "no_data " : "",
614                 (stat & M00514_RD_STATUS_BITMAP_READY_BUFFER_FULL_MSK) ?
615                         "ready_buffer_full " : "");
616         cobalt_info("tx: evcnt: %d\n", ioread32(&vo->rd_evcnt_count));
617         return 0;
618 }
619
620 static int cobalt_enum_dv_timings(struct file *file, void *priv_fh,
621                                     struct v4l2_enum_dv_timings *timings)
622 {
623         struct cobalt_stream *s = video_drvdata(file);
624
625         if (s->input == 1) {
626                 if (timings->index)
627                         return -EINVAL;
628                 memset(timings->reserved, 0, sizeof(timings->reserved));
629                 timings->timings = cea1080p60;
630                 return 0;
631         }
632         timings->pad = 0;
633         return v4l2_subdev_call(s->sd,
634                         pad, enum_dv_timings, timings);
635 }
636
637 static int cobalt_s_dv_timings(struct file *file, void *priv_fh,
638                                     struct v4l2_dv_timings *timings)
639 {
640         struct cobalt_stream *s = video_drvdata(file);
641         int err;
642
643         if (s->input == 1) {
644                 *timings = cea1080p60;
645                 return 0;
646         }
647
648         if (v4l2_match_dv_timings(timings, &s->timings, 0, false))
649                 return 0;
650
651         if (vb2_is_busy(&s->q))
652                 return -EBUSY;
653
654         err = v4l2_subdev_call(s->sd,
655                         video, s_dv_timings, timings);
656         if (!err) {
657                 s->timings = *timings;
658                 s->width = timings->bt.width;
659                 s->height = timings->bt.height;
660                 s->stride = timings->bt.width * s->bpp;
661         }
662         return err;
663 }
664
665 static int cobalt_g_dv_timings(struct file *file, void *priv_fh,
666                                     struct v4l2_dv_timings *timings)
667 {
668         struct cobalt_stream *s = video_drvdata(file);
669
670         if (s->input == 1) {
671                 *timings = cea1080p60;
672                 return 0;
673         }
674         return v4l2_subdev_call(s->sd,
675                         video, g_dv_timings, timings);
676 }
677
678 static int cobalt_query_dv_timings(struct file *file, void *priv_fh,
679                                     struct v4l2_dv_timings *timings)
680 {
681         struct cobalt_stream *s = video_drvdata(file);
682
683         if (s->input == 1) {
684                 *timings = cea1080p60;
685                 return 0;
686         }
687         return v4l2_subdev_call(s->sd,
688                         video, query_dv_timings, timings);
689 }
690
691 static int cobalt_dv_timings_cap(struct file *file, void *priv_fh,
692                                     struct v4l2_dv_timings_cap *cap)
693 {
694         struct cobalt_stream *s = video_drvdata(file);
695
696         cap->pad = 0;
697         return v4l2_subdev_call(s->sd,
698                         pad, dv_timings_cap, cap);
699 }
700
701 static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh,
702                 struct v4l2_fmtdesc *f)
703 {
704         switch (f->index) {
705         case 0:
706                 strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
707                 f->pixelformat = V4L2_PIX_FMT_YUYV;
708                 break;
709         case 1:
710                 strlcpy(f->description, "RGB24", sizeof(f->description));
711                 f->pixelformat = V4L2_PIX_FMT_RGB24;
712                 break;
713         case 2:
714                 strlcpy(f->description, "RGB32", sizeof(f->description));
715                 f->pixelformat = V4L2_PIX_FMT_BGR32;
716                 break;
717         default:
718                 return -EINVAL;
719         }
720
721         return 0;
722 }
723
724 static int cobalt_g_fmt_vid_cap(struct file *file, void *priv_fh,
725                 struct v4l2_format *f)
726 {
727         struct cobalt_stream *s = video_drvdata(file);
728         struct v4l2_pix_format *pix = &f->fmt.pix;
729         struct v4l2_subdev_format sd_fmt;
730
731         pix->width = s->width;
732         pix->height = s->height;
733         pix->bytesperline = s->stride;
734         pix->field = V4L2_FIELD_NONE;
735
736         if (s->input == 1) {
737                 pix->colorspace = V4L2_COLORSPACE_SRGB;
738         } else {
739                 sd_fmt.pad = s->pad_source;
740                 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
741                 v4l2_subdev_call(s->sd, pad, get_fmt, NULL, &sd_fmt);
742                 v4l2_fill_pix_format(pix, &sd_fmt.format);
743         }
744
745         pix->pixelformat = s->pixfmt;
746         pix->sizeimage = pix->bytesperline * pix->height;
747
748         return 0;
749 }
750
751 static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh,
752                 struct v4l2_format *f)
753 {
754         struct cobalt_stream *s = video_drvdata(file);
755         struct v4l2_pix_format *pix = &f->fmt.pix;
756         struct v4l2_subdev_format sd_fmt;
757
758         /* Check for min (QCIF) and max (Full HD) size */
759         if ((pix->width < 176) || (pix->height < 144)) {
760                 pix->width = 176;
761                 pix->height = 144;
762         }
763
764         if ((pix->width > 1920) || (pix->height > 1080)) {
765                 pix->width = 1920;
766                 pix->height = 1080;
767         }
768
769         /* Make width multiple of 4 */
770         pix->width &= ~0x3;
771
772         /* Make height multiple of 2 */
773         pix->height &= ~0x1;
774
775         if (s->input == 1) {
776                 /* Generator => fixed format only */
777                 pix->width = 1920;
778                 pix->height = 1080;
779                 pix->colorspace = V4L2_COLORSPACE_SRGB;
780         } else {
781                 sd_fmt.pad = s->pad_source;
782                 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
783                 v4l2_subdev_call(s->sd, pad, get_fmt, NULL, &sd_fmt);
784                 v4l2_fill_pix_format(pix, &sd_fmt.format);
785         }
786
787         switch (pix->pixelformat) {
788         case V4L2_PIX_FMT_YUYV:
789         default:
790                 pix->bytesperline = max(pix->bytesperline & ~0x3,
791                                 pix->width * COBALT_BYTES_PER_PIXEL_YUYV);
792                 pix->pixelformat = V4L2_PIX_FMT_YUYV;
793                 break;
794         case V4L2_PIX_FMT_RGB24:
795                 pix->bytesperline = max(pix->bytesperline & ~0x3,
796                                 pix->width * COBALT_BYTES_PER_PIXEL_RGB24);
797                 break;
798         case V4L2_PIX_FMT_BGR32:
799                 pix->bytesperline = max(pix->bytesperline & ~0x3,
800                                 pix->width * COBALT_BYTES_PER_PIXEL_RGB32);
801                 break;
802         }
803
804         pix->sizeimage = pix->bytesperline * pix->height;
805         pix->field = V4L2_FIELD_NONE;
806         pix->priv = 0;
807
808         return 0;
809 }
810
811 static int cobalt_s_fmt_vid_cap(struct file *file, void *priv_fh,
812                 struct v4l2_format *f)
813 {
814         struct cobalt_stream *s = video_drvdata(file);
815         struct v4l2_pix_format *pix = &f->fmt.pix;
816
817         if (vb2_is_busy(&s->q))
818                 return -EBUSY;
819
820         if (cobalt_try_fmt_vid_cap(file, priv_fh, f))
821                 return -EINVAL;
822
823         s->width = pix->width;
824         s->height = pix->height;
825         s->stride = pix->bytesperline;
826         switch (pix->pixelformat) {
827         case V4L2_PIX_FMT_YUYV:
828                 s->bpp = COBALT_BYTES_PER_PIXEL_YUYV;
829                 break;
830         case V4L2_PIX_FMT_RGB24:
831                 s->bpp = COBALT_BYTES_PER_PIXEL_RGB24;
832                 break;
833         case V4L2_PIX_FMT_BGR32:
834                 s->bpp = COBALT_BYTES_PER_PIXEL_RGB32;
835                 break;
836         default:
837                 return -EINVAL;
838         }
839         s->pixfmt = pix->pixelformat;
840         cobalt_enable_input(s);
841
842         return 0;
843 }
844
845 static int cobalt_try_fmt_vid_out(struct file *file, void *priv_fh,
846                 struct v4l2_format *f)
847 {
848         struct v4l2_pix_format *pix = &f->fmt.pix;
849
850         /* Check for min (QCIF) and max (Full HD) size */
851         if ((pix->width < 176) || (pix->height < 144)) {
852                 pix->width = 176;
853                 pix->height = 144;
854         }
855
856         if ((pix->width > 1920) || (pix->height > 1080)) {
857                 pix->width = 1920;
858                 pix->height = 1080;
859         }
860
861         /* Make width multiple of 4 */
862         pix->width &= ~0x3;
863
864         /* Make height multiple of 2 */
865         pix->height &= ~0x1;
866
867         switch (pix->pixelformat) {
868         case V4L2_PIX_FMT_YUYV:
869         default:
870                 pix->bytesperline = max(pix->bytesperline & ~0x3,
871                                 pix->width * COBALT_BYTES_PER_PIXEL_YUYV);
872                 pix->pixelformat = V4L2_PIX_FMT_YUYV;
873                 break;
874         case V4L2_PIX_FMT_BGR32:
875                 pix->bytesperline = max(pix->bytesperline & ~0x3,
876                                 pix->width * COBALT_BYTES_PER_PIXEL_RGB32);
877                 break;
878         }
879
880         pix->sizeimage = pix->bytesperline * pix->height;
881         pix->field = V4L2_FIELD_NONE;
882
883         return 0;
884 }
885
886 static int cobalt_g_fmt_vid_out(struct file *file, void *priv_fh,
887                 struct v4l2_format *f)
888 {
889         struct cobalt_stream *s = video_drvdata(file);
890         struct v4l2_pix_format *pix = &f->fmt.pix;
891
892         pix->width = s->width;
893         pix->height = s->height;
894         pix->bytesperline = s->stride;
895         pix->field = V4L2_FIELD_NONE;
896         pix->pixelformat = s->pixfmt;
897         pix->colorspace = s->colorspace;
898         pix->xfer_func = s->xfer_func;
899         pix->ycbcr_enc = s->ycbcr_enc;
900         pix->quantization = s->quantization;
901         pix->sizeimage = pix->bytesperline * pix->height;
902
903         return 0;
904 }
905
906 static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh,
907                 struct v4l2_fmtdesc *f)
908 {
909         switch (f->index) {
910         case 0:
911                 strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
912                 f->pixelformat = V4L2_PIX_FMT_YUYV;
913                 break;
914         case 1:
915                 strlcpy(f->description, "RGB32", sizeof(f->description));
916                 f->pixelformat = V4L2_PIX_FMT_BGR32;
917                 break;
918         default:
919                 return -EINVAL;
920         }
921
922         return 0;
923 }
924
925 static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh,
926                 struct v4l2_format *f)
927 {
928         struct cobalt_stream *s = video_drvdata(file);
929         struct v4l2_pix_format *pix = &f->fmt.pix;
930         struct v4l2_subdev_format sd_fmt = { 0 };
931         u32 code;
932
933         if (cobalt_try_fmt_vid_out(file, priv_fh, f))
934                 return -EINVAL;
935
936         if (vb2_is_busy(&s->q) && (pix->pixelformat != s->pixfmt ||
937             pix->width != s->width || pix->height != s->height ||
938             pix->bytesperline != s->stride))
939                 return -EBUSY;
940
941         switch (pix->pixelformat) {
942         case V4L2_PIX_FMT_YUYV:
943                 s->bpp = COBALT_BYTES_PER_PIXEL_YUYV;
944                 code = MEDIA_BUS_FMT_UYVY8_1X16;
945                 break;
946         case V4L2_PIX_FMT_BGR32:
947                 s->bpp = COBALT_BYTES_PER_PIXEL_RGB32;
948                 code = MEDIA_BUS_FMT_RGB888_1X24;
949                 break;
950         default:
951                 return -EINVAL;
952         }
953         s->width = pix->width;
954         s->height = pix->height;
955         s->stride = pix->bytesperline;
956         s->pixfmt = pix->pixelformat;
957         s->colorspace = pix->colorspace;
958         s->xfer_func = pix->xfer_func;
959         s->ycbcr_enc = pix->ycbcr_enc;
960         s->quantization = pix->quantization;
961         sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
962         v4l2_fill_mbus_format(&sd_fmt.format, pix, code);
963         v4l2_subdev_call(s->sd, pad, set_fmt, NULL, &sd_fmt);
964         return 0;
965 }
966
967 static int cobalt_enum_input(struct file *file, void *priv_fh,
968                                  struct v4l2_input *inp)
969 {
970         struct cobalt_stream *s = video_drvdata(file);
971
972         if (inp->index > 1)
973                 return -EINVAL;
974         if (inp->index == 0)
975                 snprintf(inp->name, sizeof(inp->name),
976                                 "HDMI-%d", s->video_channel);
977         else
978                 snprintf(inp->name, sizeof(inp->name),
979                                 "Generator-%d", s->video_channel);
980         inp->type = V4L2_INPUT_TYPE_CAMERA;
981         inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
982         if (inp->index == 1)
983                 return 0;
984         return v4l2_subdev_call(s->sd,
985                         video, g_input_status, &inp->status);
986 }
987
988 static int cobalt_g_input(struct file *file, void *priv_fh, unsigned int *i)
989 {
990         struct cobalt_stream *s = video_drvdata(file);
991
992         *i = s->input;
993         return 0;
994 }
995
996 static int cobalt_s_input(struct file *file, void *priv_fh, unsigned int i)
997 {
998         struct cobalt_stream *s = video_drvdata(file);
999
1000         if (i >= 2)
1001                 return -EINVAL;
1002         if (vb2_is_busy(&s->q))
1003                 return -EBUSY;
1004         s->input = i;
1005
1006         cobalt_enable_input(s);
1007
1008         if (s->input == 1) /* Test Pattern Generator */
1009                 return 0;
1010
1011         return v4l2_subdev_call(s->sd, video, s_routing,
1012                         ADV76XX_PAD_HDMI_PORT_A, 0, 0);
1013 }
1014
1015 static int cobalt_enum_output(struct file *file, void *priv_fh,
1016                                  struct v4l2_output *out)
1017 {
1018         if (out->index)
1019                 return -EINVAL;
1020         snprintf(out->name, sizeof(out->name), "HDMI-%d", out->index);
1021         out->type = V4L2_OUTPUT_TYPE_ANALOG;
1022         out->capabilities = V4L2_OUT_CAP_DV_TIMINGS;
1023         return 0;
1024 }
1025
1026 static int cobalt_g_output(struct file *file, void *priv_fh, unsigned int *i)
1027 {
1028         *i = 0;
1029         return 0;
1030 }
1031
1032 static int cobalt_s_output(struct file *file, void *priv_fh, unsigned int i)
1033 {
1034         return i ? -EINVAL : 0;
1035 }
1036
1037 static int cobalt_g_edid(struct file *file, void *fh, struct v4l2_edid *edid)
1038 {
1039         struct cobalt_stream *s = video_drvdata(file);
1040         u32 pad = edid->pad;
1041         int ret;
1042
1043         if (edid->pad >= (s->is_output ? 1 : 2))
1044                 return -EINVAL;
1045         edid->pad = 0;
1046         ret = v4l2_subdev_call(s->sd, pad, get_edid, edid);
1047         edid->pad = pad;
1048         return ret;
1049 }
1050
1051 static int cobalt_s_edid(struct file *file, void *fh, struct v4l2_edid *edid)
1052 {
1053         struct cobalt_stream *s = video_drvdata(file);
1054         u32 pad = edid->pad;
1055         int ret;
1056
1057         if (edid->pad >= 2)
1058                 return -EINVAL;
1059         edid->pad = 0;
1060         ret = v4l2_subdev_call(s->sd, pad, set_edid, edid);
1061         edid->pad = pad;
1062         return ret;
1063 }
1064
1065 static int cobalt_subscribe_event(struct v4l2_fh *fh,
1066                                   const struct v4l2_event_subscription *sub)
1067 {
1068         switch (sub->type) {
1069         case V4L2_EVENT_SOURCE_CHANGE:
1070                 return v4l2_event_subscribe(fh, sub, 4, NULL);
1071         }
1072         return v4l2_ctrl_subscribe_event(fh, sub);
1073 }
1074
1075 static int cobalt_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1076 {
1077         if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1078                 return -EINVAL;
1079         a->parm.capture.timeperframe.numerator = 1;
1080         a->parm.capture.timeperframe.denominator = 60;
1081         a->parm.capture.readbuffers = 3;
1082         return 0;
1083 }
1084
1085 static const struct v4l2_ioctl_ops cobalt_ioctl_ops = {
1086         .vidioc_querycap                = cobalt_querycap,
1087         .vidioc_g_parm                  = cobalt_g_parm,
1088         .vidioc_log_status              = cobalt_log_status,
1089         .vidioc_streamon                = vb2_ioctl_streamon,
1090         .vidioc_streamoff               = vb2_ioctl_streamoff,
1091         .vidioc_enum_input              = cobalt_enum_input,
1092         .vidioc_g_input                 = cobalt_g_input,
1093         .vidioc_s_input                 = cobalt_s_input,
1094         .vidioc_enum_fmt_vid_cap        = cobalt_enum_fmt_vid_cap,
1095         .vidioc_g_fmt_vid_cap           = cobalt_g_fmt_vid_cap,
1096         .vidioc_s_fmt_vid_cap           = cobalt_s_fmt_vid_cap,
1097         .vidioc_try_fmt_vid_cap         = cobalt_try_fmt_vid_cap,
1098         .vidioc_enum_output             = cobalt_enum_output,
1099         .vidioc_g_output                = cobalt_g_output,
1100         .vidioc_s_output                = cobalt_s_output,
1101         .vidioc_enum_fmt_vid_out        = cobalt_enum_fmt_vid_out,
1102         .vidioc_g_fmt_vid_out           = cobalt_g_fmt_vid_out,
1103         .vidioc_s_fmt_vid_out           = cobalt_s_fmt_vid_out,
1104         .vidioc_try_fmt_vid_out         = cobalt_try_fmt_vid_out,
1105         .vidioc_s_dv_timings            = cobalt_s_dv_timings,
1106         .vidioc_g_dv_timings            = cobalt_g_dv_timings,
1107         .vidioc_query_dv_timings        = cobalt_query_dv_timings,
1108         .vidioc_enum_dv_timings         = cobalt_enum_dv_timings,
1109         .vidioc_dv_timings_cap          = cobalt_dv_timings_cap,
1110         .vidioc_g_edid                  = cobalt_g_edid,
1111         .vidioc_s_edid                  = cobalt_s_edid,
1112         .vidioc_subscribe_event         = cobalt_subscribe_event,
1113         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
1114         .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
1115         .vidioc_create_bufs             = vb2_ioctl_create_bufs,
1116         .vidioc_querybuf                = vb2_ioctl_querybuf,
1117         .vidioc_qbuf                    = vb2_ioctl_qbuf,
1118         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
1119         .vidioc_expbuf                  = vb2_ioctl_expbuf,
1120 #ifdef CONFIG_VIDEO_ADV_DEBUG
1121         .vidioc_g_register              = cobalt_g_register,
1122         .vidioc_s_register              = cobalt_s_register,
1123 #endif
1124 };
1125
1126 static const struct v4l2_ioctl_ops cobalt_ioctl_empty_ops = {
1127 #ifdef CONFIG_VIDEO_ADV_DEBUG
1128         .vidioc_g_register              = cobalt_g_register,
1129         .vidioc_s_register              = cobalt_s_register,
1130 #endif
1131 };
1132
1133 /* Register device nodes */
1134
1135 static const struct v4l2_file_operations cobalt_fops = {
1136         .owner = THIS_MODULE,
1137         .open = v4l2_fh_open,
1138         .unlocked_ioctl = video_ioctl2,
1139         .release = vb2_fop_release,
1140         .poll = vb2_fop_poll,
1141         .mmap = vb2_fop_mmap,
1142         .read = vb2_fop_read,
1143 };
1144
1145 static const struct v4l2_file_operations cobalt_out_fops = {
1146         .owner = THIS_MODULE,
1147         .open = v4l2_fh_open,
1148         .unlocked_ioctl = video_ioctl2,
1149         .release = vb2_fop_release,
1150         .poll = vb2_fop_poll,
1151         .mmap = vb2_fop_mmap,
1152         .write = vb2_fop_write,
1153 };
1154
1155 static const struct v4l2_file_operations cobalt_empty_fops = {
1156         .owner = THIS_MODULE,
1157         .open = v4l2_fh_open,
1158         .unlocked_ioctl = video_ioctl2,
1159         .release = v4l2_fh_release,
1160 };
1161
1162 static int cobalt_node_register(struct cobalt *cobalt, int node)
1163 {
1164         static const struct v4l2_dv_timings dv1080p60 =
1165                 V4L2_DV_BT_CEA_1920X1080P60;
1166         struct cobalt_stream *s = cobalt->streams + node;
1167         struct video_device *vdev = &s->vdev;
1168         struct vb2_queue *q = &s->q;
1169         int ret;
1170
1171         mutex_init(&s->lock);
1172         spin_lock_init(&s->irqlock);
1173
1174         snprintf(vdev->name, sizeof(vdev->name),
1175                         "%s-%d", cobalt->v4l2_dev.name, node);
1176         s->width = 1920;
1177         /* Audio frames are just 4 lines of 1920 bytes */
1178         s->height = s->is_audio ? 4 : 1080;
1179
1180         if (s->is_audio) {
1181                 s->bpp = 1;
1182                 s->pixfmt = V4L2_PIX_FMT_GREY;
1183         } else if (s->is_output) {
1184                 s->bpp = COBALT_BYTES_PER_PIXEL_RGB32;
1185                 s->pixfmt = V4L2_PIX_FMT_BGR32;
1186         } else {
1187                 s->bpp = COBALT_BYTES_PER_PIXEL_YUYV;
1188                 s->pixfmt = V4L2_PIX_FMT_YUYV;
1189         }
1190         s->colorspace = V4L2_COLORSPACE_SRGB;
1191         s->stride = s->width * s->bpp;
1192
1193         if (!s->is_audio) {
1194                 if (s->is_dummy)
1195                         cobalt_warn("Setting up dummy video node %d\n", node);
1196                 vdev->v4l2_dev = &cobalt->v4l2_dev;
1197                 if (s->is_dummy)
1198                         vdev->fops = &cobalt_empty_fops;
1199                 else
1200                         vdev->fops = s->is_output ? &cobalt_out_fops :
1201                                                     &cobalt_fops;
1202                 vdev->release = video_device_release_empty;
1203                 vdev->vfl_dir = s->is_output ? VFL_DIR_TX : VFL_DIR_RX;
1204                 vdev->lock = &s->lock;
1205                 if (s->sd)
1206                         vdev->ctrl_handler = s->sd->ctrl_handler;
1207                 s->timings = dv1080p60;
1208                 v4l2_subdev_call(s->sd, video, s_dv_timings, &s->timings);
1209                 if (!s->is_output && s->sd)
1210                         cobalt_enable_input(s);
1211                 vdev->ioctl_ops = s->is_dummy ? &cobalt_ioctl_empty_ops :
1212                                   &cobalt_ioctl_ops;
1213         }
1214
1215         INIT_LIST_HEAD(&s->bufs);
1216         q->type = s->is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT :
1217                                  V4L2_BUF_TYPE_VIDEO_CAPTURE;
1218         q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1219         q->io_modes |= s->is_output ? VB2_WRITE : VB2_READ;
1220         q->drv_priv = s;
1221         q->buf_struct_size = sizeof(struct cobalt_buffer);
1222         q->ops = &cobalt_qops;
1223         q->mem_ops = &vb2_dma_sg_memops;
1224         q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1225         q->min_buffers_needed = 2;
1226         q->lock = &s->lock;
1227         vdev->queue = q;
1228
1229         video_set_drvdata(vdev, s);
1230         ret = vb2_queue_init(q);
1231         if (!s->is_audio && ret == 0)
1232                 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1233         else if (!s->is_dummy)
1234                 ret = cobalt_alsa_init(s);
1235
1236         if (ret < 0) {
1237                 if (!s->is_audio)
1238                         cobalt_err("couldn't register v4l2 device node %d\n",
1239                                         node);
1240                 return ret;
1241         }
1242         cobalt_info("registered node %d\n", node);
1243         return 0;
1244 }
1245
1246 /* Initialize v4l2 variables and register v4l2 devices */
1247 int cobalt_nodes_register(struct cobalt *cobalt)
1248 {
1249         int node, ret;
1250
1251         /* Setup V4L2 Devices */
1252         for (node = 0; node < COBALT_NUM_STREAMS; node++) {
1253                 ret = cobalt_node_register(cobalt, node);
1254                 if (ret)
1255                         return ret;
1256         }
1257         return 0;
1258 }
1259
1260 /* Unregister v4l2 devices */
1261 void cobalt_nodes_unregister(struct cobalt *cobalt)
1262 {
1263         int node;
1264
1265         /* Teardown all streams */
1266         for (node = 0; node < COBALT_NUM_STREAMS; node++) {
1267                 struct cobalt_stream *s = cobalt->streams + node;
1268                 struct video_device *vdev = &s->vdev;
1269
1270                 if (!s->is_audio)
1271                         video_unregister_device(vdev);
1272                 else if (!s->is_dummy)
1273                         cobalt_alsa_exit(s);
1274         }
1275 }