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