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