cobalt-v4l2.c 36 KB

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