]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157
[thirdparty/kernel/stable.git] / drivers / media / pci / solo6x10 / solo6x10-v4l2-enc.c
CommitLineData
c942fddf 1// SPDX-License-Identifier: GPL-2.0-or-later
faa4fd2a 2/*
dcae5dac
HV
3 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
4 *
5 * Original author:
6 * Ben Collins <bcollins@ubuntu.com>
7 *
8 * Additional work by:
9 * John Brooks <john.brooks@bluecherry.net>
faa4fd2a
BC
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/kthread.h>
15#include <linux/freezer.h>
dcae5dac 16
faa4fd2a
BC
17#include <media/v4l2-ioctl.h>
18#include <media/v4l2-common.h>
94160497 19#include <media/v4l2-event.h>
382c31a9 20#include <media/videobuf2-dma-sg.h>
dcae5dac 21
ae69b22c 22#include "solo6x10.h"
dad7fab9 23#include "solo6x10-tw28.h"
b3c7d453 24#include "solo6x10-jpeg.h"
faa4fd2a 25
dcae5dac 26#define MIN_VID_BUFFERS 2
e34f2a96 27#define FRAME_BUF_SIZE (400 * 1024)
faa4fd2a 28#define MP4_QS 16
dcae5dac 29#define DMA_ALIGN 4096
faa4fd2a 30
dcae5dac 31/* 6010 M4V */
8a4d9a9c 32static u8 vop_6010_ntsc_d1[] = {
dcae5dac
HV
33 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
34 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
35 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
36 0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
37};
38
8a4d9a9c 39static u8 vop_6010_ntsc_cif[] = {
dcae5dac
HV
40 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
41 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
42 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
43 0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
44};
45
8a4d9a9c 46static u8 vop_6010_pal_d1[] = {
dcae5dac
HV
47 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
48 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
49 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
50 0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
51};
52
8a4d9a9c 53static u8 vop_6010_pal_cif[] = {
dcae5dac
HV
54 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
55 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
56 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
57 0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
58};
59
60/* 6110 h.264 */
8a4d9a9c 61static u8 vop_6110_ntsc_d1[] = {
dcae5dac
HV
62 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
63 0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
64 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
65};
66
8a4d9a9c 67static u8 vop_6110_ntsc_cif[] = {
dcae5dac
HV
68 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
69 0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
70 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
71};
72
8a4d9a9c 73static u8 vop_6110_pal_d1[] = {
dcae5dac
HV
74 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
75 0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
76 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
77};
78
8a4d9a9c 79static u8 vop_6110_pal_cif[] = {
dcae5dac
HV
80 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
81 0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
82 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
faa4fd2a
BC
83};
84
4a61ad3c 85typedef __le32 vop_header[16];
dcae5dac
HV
86
87struct solo_enc_buf {
88 enum solo_enc_types type;
4a61ad3c 89 const vop_header *vh;
dcae5dac
HV
90 int motion;
91};
92
faa4fd2a
BC
93static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
94{
decebabf 95 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a 96
dcae5dac
HV
97 return (solo_dev->motion_mask >> solo_enc->ch) & 1;
98}
99
100static int solo_motion_detected(struct solo_enc_dev *solo_enc)
101{
102 struct solo_dev *solo_dev = solo_enc->solo_dev;
103 unsigned long flags;
104 u32 ch_mask = 1 << solo_enc->ch;
105 int ret = 0;
106
107 spin_lock_irqsave(&solo_enc->motion_lock, flags);
108 if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
109 solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
110 ret = 1;
111 }
112 spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
113
114 return ret;
faa4fd2a
BC
115}
116
117static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
118{
decebabf 119 struct solo_dev *solo_dev = solo_enc->solo_dev;
dcae5dac
HV
120 u32 mask = 1 << solo_enc->ch;
121 unsigned long flags;
faa4fd2a 122
dcae5dac 123 spin_lock_irqsave(&solo_enc->motion_lock, flags);
faa4fd2a
BC
124
125 if (on)
dcae5dac 126 solo_dev->motion_mask |= mask;
faa4fd2a 127 else
dcae5dac 128 solo_dev->motion_mask &= ~mask;
faa4fd2a 129
dcae5dac 130 solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
f62de9be 131
faa4fd2a
BC
132 solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
133 SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
134 (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
135
dcae5dac 136 spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
faa4fd2a
BC
137}
138
4c211ed7 139void solo_update_mode(struct solo_enc_dev *solo_enc)
faa4fd2a 140{
decebabf 141 struct solo_dev *solo_dev = solo_enc->solo_dev;
dcae5dac 142 int vop_len;
8a4d9a9c 143 u8 *vop;
faa4fd2a
BC
144
145 solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
146 solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
147
dcae5dac 148 if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
faa4fd2a
BC
149 solo_enc->width = solo_dev->video_hsize >> 1;
150 solo_enc->height = solo_dev->video_vsize;
dcae5dac
HV
151 if (solo_dev->type == SOLO_DEV_6110) {
152 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
153 vop = vop_6110_ntsc_cif;
154 vop_len = sizeof(vop_6110_ntsc_cif);
155 } else {
156 vop = vop_6110_pal_cif;
157 vop_len = sizeof(vop_6110_pal_cif);
158 }
159 } else {
160 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
161 vop = vop_6010_ntsc_cif;
162 vop_len = sizeof(vop_6010_ntsc_cif);
163 } else {
164 vop = vop_6010_pal_cif;
165 vop_len = sizeof(vop_6010_pal_cif);
166 }
167 }
168 } else {
faa4fd2a
BC
169 solo_enc->width = solo_dev->video_hsize;
170 solo_enc->height = solo_dev->video_vsize << 1;
171 solo_enc->bw_weight <<= 2;
dcae5dac
HV
172 if (solo_dev->type == SOLO_DEV_6110) {
173 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
174 vop = vop_6110_ntsc_d1;
175 vop_len = sizeof(vop_6110_ntsc_d1);
176 } else {
177 vop = vop_6110_pal_d1;
178 vop_len = sizeof(vop_6110_pal_d1);
179 }
180 } else {
181 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
182 vop = vop_6010_ntsc_d1;
183 vop_len = sizeof(vop_6010_ntsc_d1);
184 } else {
185 vop = vop_6010_pal_d1;
186 vop_len = sizeof(vop_6010_pal_d1);
187 }
188 }
faa4fd2a 189 }
dcae5dac
HV
190
191 memcpy(solo_enc->vop, vop, vop_len);
192
193 /* Some fixups for 6010/M4V */
194 if (solo_dev->type == SOLO_DEV_6010) {
195 u16 fps = solo_dev->fps * 1000;
196 u16 interval = solo_enc->interval * 1000;
197
198 vop = solo_enc->vop;
199
200 /* Frame rate and interval */
201 vop[22] = fps >> 4;
202 vop[23] = ((fps << 4) & 0xf0) | 0x0c
203 | ((interval >> 13) & 0x3);
204 vop[24] = (interval >> 5) & 0xff;
205 vop[25] = ((interval << 3) & 0xf8) | 0x04;
206 }
207
208 solo_enc->vop_len = vop_len;
209
210 /* Now handle the jpeg header */
211 vop = solo_enc->jpeg_header;
212 vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
213 vop[SOF0_START + 6] = 0xff & solo_enc->height;
214 vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
215 vop[SOF0_START + 8] = 0xff & solo_enc->width;
216
217 memcpy(vop + DQT_START,
218 jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
faa4fd2a
BC
219}
220
382c31a9 221static int solo_enc_on(struct solo_enc_dev *solo_enc)
faa4fd2a 222{
faa4fd2a 223 u8 ch = solo_enc->ch;
decebabf 224 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
225 u8 interval;
226
faa4fd2a
BC
227 solo_update_mode(solo_enc);
228
382c31a9
HV
229 /* Make sure to do a bandwidth check */
230 if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
231 return -EBUSY;
15513c12 232 solo_enc->sequence = 0;
382c31a9 233 solo_dev->enc_bw_remain -= solo_enc->bw_weight;
faa4fd2a 234
a7eb931d 235 if (solo_enc->type == SOLO_ENC_TYPE_EXT)
faa4fd2a
BC
236 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
237
faa4fd2a
BC
238 /* Disable all encoding for this channel */
239 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
240
241 /* Common for both std and ext encoding */
242 solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
243 solo_enc->interlaced ? 1 : 0);
244
245 if (solo_enc->interlaced)
246 interval = solo_enc->interval - 1;
247 else
248 interval = solo_enc->interval;
249
250 /* Standard encoding only */
251 solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
252 solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
253 solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
254
255 /* Extended encoding only */
256 solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
257 solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
258 solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
259
260 /* Enables the standard encoder */
261 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
262
faa4fd2a
BC
263 return 0;
264}
265
382c31a9 266static void solo_enc_off(struct solo_enc_dev *solo_enc)
f62de9be 267{
dcae5dac 268 struct solo_dev *solo_dev = solo_enc->solo_dev;
f62de9be 269
dcae5dac 270 solo_dev->enc_bw_remain += solo_enc->bw_weight;
f62de9be 271
dcae5dac
HV
272 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
273 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
f62de9be
BC
274}
275
dcae5dac
HV
276static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
277 unsigned int off, unsigned int size)
faa4fd2a
BC
278{
279 int ret;
280
281 if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
282 return -EINVAL;
283
dcae5dac 284 /* Single shot */
f62de9be 285 if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
dcae5dac
HV
286 return solo_p2m_dma_t(solo_dev, 0, dma,
287 SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
288 0, 0);
f62de9be 289 }
faa4fd2a
BC
290
291 /* Buffer wrap */
dcae5dac 292 ret = solo_p2m_dma_t(solo_dev, 0, dma,
f62de9be 293 SOLO_MP4E_EXT_ADDR(solo_dev) + off,
dcae5dac 294 SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
faa4fd2a 295
dcae5dac
HV
296 if (!ret) {
297 ret = solo_p2m_dma_t(solo_dev, 0,
298 dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
299 SOLO_MP4E_EXT_ADDR(solo_dev),
300 size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
301 }
faa4fd2a
BC
302
303 return ret;
304}
305
dcae5dac
HV
306/* Build a descriptor queue out of an SG list and send it to the P2M for
307 * processing. */
a7eb931d 308static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
22301247 309 struct sg_table *vbuf, int off, int size,
dcae5dac 310 unsigned int base, unsigned int base_size)
faa4fd2a 311{
a7eb931d 312 struct solo_dev *solo_dev = solo_enc->solo_dev;
dcae5dac
HV
313 struct scatterlist *sg;
314 int i;
faa4fd2a
BC
315 int ret;
316
dcae5dac 317 if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
faa4fd2a
BC
318 return -EINVAL;
319
a7eb931d 320 solo_enc->desc_count = 1;
dcae5dac 321
22301247 322 for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
dcae5dac
HV
323 struct solo_p2m_desc *desc;
324 dma_addr_t dma;
325 int len;
326 int left = base_size - off;
327
a7eb931d 328 desc = &solo_enc->desc_items[solo_enc->desc_count++];
dcae5dac
HV
329 dma = sg_dma_address(sg);
330 len = sg_dma_len(sg);
331
332 /* We assume this is smaller than the scatter size */
333 BUG_ON(skip >= len);
334 if (skip) {
335 len -= skip;
336 dma += skip;
337 size -= skip;
338 skip = 0;
339 }
faa4fd2a 340
dcae5dac 341 len = min(len, size);
faa4fd2a 342
dcae5dac
HV
343 if (len <= left) {
344 /* Single descriptor */
345 solo_p2m_fill_desc(desc, 0, dma, base + off,
346 len, 0, 0);
347 } else {
348 /* Buffer wrap */
349 /* XXX: Do these as separate DMA requests, to avoid
350 timeout errors triggered by awkwardly sized
351 descriptors. See
352 <https://github.com/bluecherrydvr/solo6x10/issues/8>
353 */
354 ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
355 left, 0, 0);
356 if (ret)
357 return ret;
358
359 ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
360 len - left, 0, 0);
361 if (ret)
362 return ret;
363
a7eb931d 364 solo_enc->desc_count--;
dcae5dac 365 }
faa4fd2a 366
dcae5dac
HV
367 size -= len;
368 if (size <= 0)
369 break;
f62de9be 370
dcae5dac
HV
371 off += len;
372 if (off >= base_size)
373 off -= base_size;
374
375 /* Because we may use two descriptors per loop */
a7eb931d
HV
376 if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
377 ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
378 solo_enc->desc_dma,
379 solo_enc->desc_count - 1);
dcae5dac
HV
380 if (ret)
381 return ret;
a7eb931d 382 solo_enc->desc_count = 1;
dcae5dac 383 }
f62de9be 384 }
c55564fd 385
a7eb931d 386 if (solo_enc->desc_count <= 1)
dcae5dac 387 return 0;
c55564fd 388
fa91783e
AO
389 return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
390 solo_enc->desc_dma, solo_enc->desc_count - 1);
c55564fd
KH
391}
392
4a61ad3c
KH
393/* Extract values from VOP header - VE_STATUSxx */
394static inline int vop_interlaced(const vop_header *vh)
395{
396 return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
397}
398
399static inline u8 vop_channel(const vop_header *vh)
400{
401 return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
402}
403
404static inline u8 vop_type(const vop_header *vh)
405{
406 return (__le32_to_cpu((*vh)[0]) >> 22) & 3;
407}
408
409static inline u32 vop_mpeg_size(const vop_header *vh)
410{
411 return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
412}
413
414static inline u8 vop_hsize(const vop_header *vh)
415{
416 return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
417}
418
419static inline u8 vop_vsize(const vop_header *vh)
420{
421 return __le32_to_cpu((*vh)[1]) & 0xFF;
422}
423
424static inline u32 vop_mpeg_offset(const vop_header *vh)
425{
426 return __le32_to_cpu((*vh)[2]);
427}
428
429static inline u32 vop_jpeg_offset(const vop_header *vh)
430{
431 return __le32_to_cpu((*vh)[3]);
432}
433
434static inline u32 vop_jpeg_size(const vop_header *vh)
435{
436 return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
437}
438
439static inline u32 vop_sec(const vop_header *vh)
440{
441 return __le32_to_cpu((*vh)[5]);
442}
443
444static inline u32 vop_usec(const vop_header *vh)
445{
446 return __le32_to_cpu((*vh)[6]);
447}
448
382c31a9 449static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
4a61ad3c 450 struct vb2_buffer *vb, const vop_header *vh)
908113d8 451{
2d700715 452 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
dcae5dac 453 struct solo_dev *solo_dev = solo_enc->solo_dev;
2d700715 454 struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
dcae5dac 455 int frame_size;
908113d8 456
2d700715 457 vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
908113d8 458
4a61ad3c 459 if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
dcae5dac 460 return -EIO;
908113d8 461
0cb6dfd7 462 frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
4a61ad3c 463 vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
382c31a9 464
2d700715 465 return solo_send_desc(solo_enc, solo_enc->jpeg_len, sgt,
4a61ad3c
KH
466 vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
467 frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
468 SOLO_JPEG_EXT_SIZE(solo_dev));
908113d8
KH
469}
470
382c31a9 471static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
4a61ad3c 472 struct vb2_buffer *vb, const vop_header *vh)
faa4fd2a 473{
2d700715 474 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
decebabf 475 struct solo_dev *solo_dev = solo_enc->solo_dev;
2d700715 476 struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
dcae5dac 477 int frame_off, frame_size;
f62de9be 478 int skip = 0;
faa4fd2a 479
4a61ad3c 480 if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
dcae5dac 481 return -EIO;
faa4fd2a 482
dcae5dac 483 /* If this is a key frame, add extra header */
2d700715 484 vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
fa91783e 485 V4L2_BUF_FLAG_BFRAME);
4a61ad3c 486 if (!vop_type(vh)) {
dcae5dac 487 skip = solo_enc->vop_len;
2d700715 488 vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
fa91783e
AO
489 vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
490 solo_enc->vop_len);
dcae5dac 491 } else {
2d700715 492 vbuf->flags |= V4L2_BUF_FLAG_PFRAME;
4a61ad3c 493 vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
faa4fd2a
BC
494 }
495
496 /* Now get the actual mpeg payload */
fa91783e
AO
497 frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) +
498 sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
0cb6dfd7 499 frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
f62de9be 500
2d700715 501 return solo_send_desc(solo_enc, skip, sgt, frame_off, frame_size,
382c31a9
HV
502 SOLO_MP4E_EXT_ADDR(solo_dev),
503 SOLO_MP4E_EXT_SIZE(solo_dev));
faa4fd2a
BC
504}
505
a7eb931d 506static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
382c31a9 507 struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
faa4fd2a 508{
2d700715 509 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
4a61ad3c 510 const vop_header *vh = enc_buf->vh;
faa4fd2a 511 int ret;
f62de9be 512
16af690f
IL
513 switch (solo_enc->fmt) {
514 case V4L2_PIX_FMT_MPEG4:
515 case V4L2_PIX_FMT_H264:
382c31a9 516 ret = solo_fill_mpeg(solo_enc, vb, vh);
16af690f
IL
517 break;
518 default: /* V4L2_PIX_FMT_MJPEG */
382c31a9 519 ret = solo_fill_jpeg(solo_enc, vb, vh);
16af690f
IL
520 break;
521 }
faa4fd2a 522
382c31a9 523 if (!ret) {
2d700715 524 vbuf->sequence = solo_enc->sequence++;
d6dd645e 525 vb->timestamp = ktime_get_ns();
316d9e84
HV
526
527 /* Check for motion flags */
e476f4e1 528 if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
316d9e84
HV
529 struct v4l2_event ev = {
530 .type = V4L2_EVENT_MOTION_DET,
531 .u.motion_det = {
2d700715
JS
532 .flags
533 = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
534 .frame_sequence = vbuf->sequence,
316d9e84
HV
535 .region_mask = enc_buf->motion ? 1 : 0,
536 },
537 };
538
316d9e84
HV
539 v4l2_event_queue(solo_enc->vfd, &ev);
540 }
dcae5dac 541 }
faa4fd2a 542
382c31a9
HV
543 vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
544
dcae5dac 545 return ret;
faa4fd2a
BC
546}
547
dcae5dac
HV
548static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
549 struct solo_enc_buf *enc_buf)
faa4fd2a 550{
382c31a9 551 struct solo_vb2_buf *vb;
a7eb931d 552 unsigned long flags;
faa4fd2a 553
382c31a9 554 mutex_lock(&solo_enc->lock);
a7eb931d
HV
555 if (solo_enc->type != enc_buf->type)
556 goto unlock;
dcae5dac 557
a7eb931d 558 spin_lock_irqsave(&solo_enc->av_lock, flags);
382c31a9
HV
559 if (list_empty(&solo_enc->vidq_active)) {
560 spin_unlock_irqrestore(&solo_enc->av_lock, flags);
561 goto unlock;
562 }
fa91783e
AO
563 vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf,
564 list);
382c31a9 565 list_del(&vb->list);
a7eb931d 566 spin_unlock_irqrestore(&solo_enc->av_lock, flags);
faa4fd2a 567
2d700715 568 solo_enc_fillbuf(solo_enc, &vb->vb.vb2_buf, enc_buf);
a7eb931d 569unlock:
382c31a9 570 mutex_unlock(&solo_enc->lock);
faa4fd2a
BC
571}
572
dcae5dac 573void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
faa4fd2a 574{
dcae5dac 575 wake_up_interruptible_all(&solo_dev->ring_thread_wait);
faa4fd2a
BC
576}
577
dcae5dac 578static void solo_handle_ring(struct solo_dev *solo_dev)
faa4fd2a 579{
dcae5dac
HV
580 for (;;) {
581 struct solo_enc_dev *solo_enc;
582 struct solo_enc_buf enc_buf;
583 u32 mpeg_current, off;
584 u8 ch;
585 u8 cur_q;
586
587 /* Check if the hardware has any new ones in the queue */
588 cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
589 if (cur_q == solo_dev->enc_idx)
590 break;
faa4fd2a 591
faa4fd2a
BC
592 mpeg_current = solo_reg_read(solo_dev,
593 SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
faa4fd2a 594 solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
faa4fd2a 595
afabbe6d 596 ch = (mpeg_current >> 24) & 0x1f;
dcae5dac
HV
597 off = mpeg_current & 0x00ffffff;
598
afabbe6d 599 if (ch >= SOLO_MAX_CHANNELS) {
faa4fd2a 600 ch -= SOLO_MAX_CHANNELS;
dcae5dac 601 enc_buf.type = SOLO_ENC_TYPE_EXT;
faa4fd2a 602 } else
dcae5dac 603 enc_buf.type = SOLO_ENC_TYPE_STD;
faa4fd2a 604
dcae5dac
HV
605 solo_enc = solo_dev->v4l2_enc[ch];
606 if (solo_enc == NULL) {
607 dev_err(&solo_dev->pdev->dev,
608 "Got spurious packet for channel %d\n", ch);
faa4fd2a
BC
609 continue;
610 }
611
dcae5dac
HV
612 /* FAIL... */
613 if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
4a61ad3c 614 sizeof(vop_header)))
faa4fd2a
BC
615 continue;
616
4a61ad3c 617 enc_buf.vh = solo_dev->vh_buf;
faa4fd2a 618
dcae5dac 619 /* Sanity check */
fa91783e
AO
620 if (vop_mpeg_offset(enc_buf.vh) !=
621 SOLO_MP4E_EXT_ADDR(solo_dev) + off)
dcae5dac
HV
622 continue;
623
624 if (solo_motion_detected(solo_enc))
625 enc_buf.motion = 1;
626 else
627 enc_buf.motion = 0;
628
629 solo_enc_handle_one(solo_enc, &enc_buf);
630 }
631}
faa4fd2a 632
dcae5dac
HV
633static int solo_ring_thread(void *data)
634{
635 struct solo_dev *solo_dev = data;
636 DECLARE_WAITQUEUE(wait, current);
faa4fd2a 637
dcae5dac
HV
638 set_freezable();
639 add_wait_queue(&solo_dev->ring_thread_wait, &wait);
faa4fd2a 640
dcae5dac
HV
641 for (;;) {
642 long timeout = schedule_timeout_interruptible(HZ);
1c6f3db0 643
dcae5dac
HV
644 if (timeout == -ERESTARTSYS || kthread_should_stop())
645 break;
dcae5dac 646 solo_handle_ring(solo_dev);
dcae5dac 647 try_to_freeze();
faa4fd2a
BC
648 }
649
dcae5dac
HV
650 remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
651
652 return 0;
faa4fd2a
BC
653}
654
fa91783e 655static int solo_enc_queue_setup(struct vb2_queue *q,
fa91783e
AO
656 unsigned int *num_buffers,
657 unsigned int *num_planes, unsigned int sizes[],
36c0f8b3 658 struct device *alloc_devs[])
faa4fd2a 659{
382c31a9
HV
660 sizes[0] = FRAME_BUF_SIZE;
661 *num_planes = 1;
faa4fd2a 662
382c31a9
HV
663 if (*num_buffers < MIN_VID_BUFFERS)
664 *num_buffers = MIN_VID_BUFFERS;
faa4fd2a
BC
665
666 return 0;
667}
668
382c31a9 669static void solo_enc_buf_queue(struct vb2_buffer *vb)
faa4fd2a 670{
2d700715 671 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
382c31a9
HV
672 struct vb2_queue *vq = vb->vb2_queue;
673 struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
674 struct solo_vb2_buf *solo_vb =
2d700715 675 container_of(vbuf, struct solo_vb2_buf, vb);
faa4fd2a 676
382c31a9
HV
677 spin_lock(&solo_enc->av_lock);
678 list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
679 spin_unlock(&solo_enc->av_lock);
faa4fd2a
BC
680}
681
dcae5dac
HV
682static int solo_ring_start(struct solo_dev *solo_dev)
683{
dcae5dac
HV
684 solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
685 SOLO6X10_NAME "_ring");
686 if (IS_ERR(solo_dev->ring_thread)) {
687 int err = PTR_ERR(solo_dev->ring_thread);
1c6f3db0 688
dcae5dac
HV
689 solo_dev->ring_thread = NULL;
690 return err;
691 }
692
693 solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
694
695 return 0;
696}
697
698static void solo_ring_stop(struct solo_dev *solo_dev)
699{
dcae5dac
HV
700 if (solo_dev->ring_thread) {
701 kthread_stop(solo_dev->ring_thread);
702 solo_dev->ring_thread = NULL;
703 }
704
705 solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
706}
707
382c31a9 708static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
faa4fd2a 709{
382c31a9 710 struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
faa4fd2a 711
670390c2 712 return solo_enc_on(solo_enc);
faa4fd2a
BC
713}
714
e37559b2 715static void solo_enc_stop_streaming(struct vb2_queue *q)
faa4fd2a 716{
382c31a9 717 struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
9ccd1809 718 unsigned long flags;
faa4fd2a 719
9ccd1809 720 spin_lock_irqsave(&solo_enc->av_lock, flags);
a7eb931d 721 solo_enc_off(solo_enc);
9ccd1809
AU
722 while (!list_empty(&solo_enc->vidq_active)) {
723 struct solo_vb2_buf *buf = list_entry(
724 solo_enc->vidq_active.next,
725 struct solo_vb2_buf, list);
726
727 list_del(&buf->list);
2d700715 728 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
9ccd1809
AU
729 }
730 spin_unlock_irqrestore(&solo_enc->av_lock, flags);
faa4fd2a
BC
731}
732
d790b7ed
HV
733static void solo_enc_buf_finish(struct vb2_buffer *vb)
734{
2d700715 735 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
d790b7ed 736 struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
2d700715 737 struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
d790b7ed
HV
738
739 switch (solo_enc->fmt) {
740 case V4L2_PIX_FMT_MPEG4:
741 case V4L2_PIX_FMT_H264:
2d700715
JS
742 if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)
743 sg_copy_from_buffer(sgt->sgl, sgt->nents,
d790b7ed
HV
744 solo_enc->vop, solo_enc->vop_len);
745 break;
746 default: /* V4L2_PIX_FMT_MJPEG */
2d700715 747 sg_copy_from_buffer(sgt->sgl, sgt->nents,
d790b7ed
HV
748 solo_enc->jpeg_header, solo_enc->jpeg_len);
749 break;
750 }
751}
752
10accd2e 753static const struct vb2_ops solo_enc_video_qops = {
382c31a9
HV
754 .queue_setup = solo_enc_queue_setup,
755 .buf_queue = solo_enc_buf_queue,
d790b7ed 756 .buf_finish = solo_enc_buf_finish,
382c31a9
HV
757 .start_streaming = solo_enc_start_streaming,
758 .stop_streaming = solo_enc_stop_streaming,
759 .wait_prepare = vb2_ops_wait_prepare,
760 .wait_finish = vb2_ops_wait_finish,
761};
762
faa4fd2a
BC
763static int solo_enc_querycap(struct file *file, void *priv,
764 struct v4l2_capability *cap)
765{
a7eb931d 766 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 767 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a 768
cc1e6315 769 strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
decebabf 770 snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
faa4fd2a 771 solo_enc->ch);
20c5f492 772 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
faa4fd2a 773 pci_name(solo_dev->pdev));
20c5f492
HV
774 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
775 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
776 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
faa4fd2a
BC
777 return 0;
778}
779
780static int solo_enc_enum_input(struct file *file, void *priv,
781 struct v4l2_input *input)
782{
a7eb931d 783 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 784 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
785
786 if (input->index)
787 return -EINVAL;
788
789 snprintf(input->name, sizeof(input->name), "Encoder %d",
790 solo_enc->ch + 1);
791 input->type = V4L2_INPUT_TYPE_CAMERA;
4c211ed7 792 input->std = solo_enc->vfd->tvnorms;
faa4fd2a
BC
793
794 if (!tw28_get_video_status(solo_dev, solo_enc->ch))
795 input->status = V4L2_IN_ST_NO_SIGNAL;
796
797 return 0;
798}
799
dcae5dac
HV
800static int solo_enc_set_input(struct file *file, void *priv,
801 unsigned int index)
faa4fd2a
BC
802{
803 if (index)
804 return -EINVAL;
805
806 return 0;
807}
808
809static int solo_enc_get_input(struct file *file, void *priv,
810 unsigned int *index)
811{
812 *index = 0;
813
814 return 0;
815}
816
817static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
818 struct v4l2_fmtdesc *f)
819{
16af690f
IL
820 struct solo_enc_dev *solo_enc = video_drvdata(file);
821 int dev_type = solo_enc->solo_dev->type;
822
faa4fd2a
BC
823 switch (f->index) {
824 case 0:
16af690f
IL
825 switch (dev_type) {
826 case SOLO_DEV_6010:
827 f->pixelformat = V4L2_PIX_FMT_MPEG4;
cc1e6315
MCC
828 strscpy(f->description, "MPEG-4 part 2",
829 sizeof(f->description));
16af690f
IL
830 break;
831 case SOLO_DEV_6110:
832 f->pixelformat = V4L2_PIX_FMT_H264;
cc1e6315 833 strscpy(f->description, "H.264", sizeof(f->description));
16af690f
IL
834 break;
835 }
faa4fd2a
BC
836 break;
837 case 1:
838 f->pixelformat = V4L2_PIX_FMT_MJPEG;
cc1e6315 839 strscpy(f->description, "MJPEG", sizeof(f->description));
faa4fd2a
BC
840 break;
841 default:
842 return -EINVAL;
843 }
844
845 f->flags = V4L2_FMT_FLAG_COMPRESSED;
846
847 return 0;
848}
849
16af690f
IL
850static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
851{
852 return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
853 || (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
854 || pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
855}
856
faa4fd2a
BC
857static int solo_enc_try_fmt_cap(struct file *file, void *priv,
858 struct v4l2_format *f)
859{
a7eb931d 860 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 861 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
862 struct v4l2_pix_format *pix = &f->fmt.pix;
863
16af690f 864 if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
faa4fd2a
BC
865 return -EINVAL;
866
98ab1c99
KH
867 if (pix->width < solo_dev->video_hsize ||
868 pix->height < solo_dev->video_vsize << 1) {
faa4fd2a
BC
869 /* Default to CIF 1/2 size */
870 pix->width = solo_dev->video_hsize >> 1;
871 pix->height = solo_dev->video_vsize;
98ab1c99
KH
872 } else {
873 /* Full frame */
874 pix->width = solo_dev->video_hsize;
875 pix->height = solo_dev->video_vsize << 1;
faa4fd2a
BC
876 }
877
016afda4
HV
878 switch (pix->field) {
879 case V4L2_FIELD_NONE:
880 case V4L2_FIELD_INTERLACED:
881 break;
882 case V4L2_FIELD_ANY:
883 default:
faa4fd2a 884 pix->field = V4L2_FIELD_INTERLACED;
016afda4
HV
885 break;
886 }
faa4fd2a
BC
887
888 /* Just set these */
889 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
890 pix->sizeimage = FRAME_BUF_SIZE;
94160497 891 pix->bytesperline = 0;
016afda4 892 pix->priv = 0;
faa4fd2a
BC
893
894 return 0;
895}
896
897static int solo_enc_set_fmt_cap(struct file *file, void *priv,
898 struct v4l2_format *f)
899{
a7eb931d 900 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 901 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
902 struct v4l2_pix_format *pix = &f->fmt.pix;
903 int ret;
904
382c31a9
HV
905 if (vb2_is_busy(&solo_enc->vidq))
906 return -EBUSY;
faa4fd2a 907
afabbe6d 908 ret = solo_enc_try_fmt_cap(file, priv, f);
016afda4
HV
909 if (ret)
910 return ret;
911
faa4fd2a
BC
912 if (pix->width == solo_dev->video_hsize)
913 solo_enc->mode = SOLO_ENC_MODE_D1;
914 else
915 solo_enc->mode = SOLO_ENC_MODE_CIF;
916
917 /* This does not change the encoder at all */
a7eb931d 918 solo_enc->fmt = pix->pixelformat;
faa4fd2a 919
69996873
HV
920 /*
921 * More information is needed about these 'extended' types. As far
922 * as I can tell these are basically additional video streams with
923 * different MPEG encoding attributes that can run in parallel with
924 * the main stream. If so, then this should be implemented as a
925 * second video node. Abusing priv like this is certainly not the
926 * right approach.
faa4fd2a 927 if (pix->priv)
a7eb931d 928 solo_enc->type = SOLO_ENC_TYPE_EXT;
69996873 929 */
cdcfe40a 930 solo_update_mode(solo_enc);
dcae5dac 931 return 0;
faa4fd2a
BC
932}
933
934static int solo_enc_get_fmt_cap(struct file *file, void *priv,
935 struct v4l2_format *f)
936{
a7eb931d 937 struct solo_enc_dev *solo_enc = video_drvdata(file);
faa4fd2a
BC
938 struct v4l2_pix_format *pix = &f->fmt.pix;
939
940 pix->width = solo_enc->width;
941 pix->height = solo_enc->height;
a7eb931d 942 pix->pixelformat = solo_enc->fmt;
faa4fd2a
BC
943 pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
944 V4L2_FIELD_NONE;
945 pix->sizeimage = FRAME_BUF_SIZE;
946 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
016afda4 947 pix->priv = 0;
faa4fd2a
BC
948
949 return 0;
950}
951
4c211ed7 952static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
faa4fd2a 953{
4c211ed7
HV
954 struct solo_enc_dev *solo_enc = video_drvdata(file);
955 struct solo_dev *solo_dev = solo_enc->solo_dev;
956
957 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
958 *i = V4L2_STD_NTSC_M;
959 else
960 *i = V4L2_STD_PAL;
faa4fd2a
BC
961 return 0;
962}
963
4c211ed7
HV
964static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
965{
966 struct solo_enc_dev *solo_enc = video_drvdata(file);
967
429df502 968 return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
4c211ed7
HV
969}
970
faa4fd2a
BC
971static int solo_enum_framesizes(struct file *file, void *priv,
972 struct v4l2_frmsizeenum *fsize)
973{
a7eb931d
HV
974 struct solo_enc_dev *solo_enc = video_drvdata(file);
975 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a 976
16af690f 977 if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
faa4fd2a
BC
978 return -EINVAL;
979
980 switch (fsize->index) {
981 case 0:
982 fsize->discrete.width = solo_dev->video_hsize >> 1;
983 fsize->discrete.height = solo_dev->video_vsize;
984 break;
985 case 1:
986 fsize->discrete.width = solo_dev->video_hsize;
987 fsize->discrete.height = solo_dev->video_vsize << 1;
988 break;
989 default:
990 return -EINVAL;
991 }
992
993 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
994
995 return 0;
996}
997
998static int solo_enum_frameintervals(struct file *file, void *priv,
999 struct v4l2_frmivalenum *fintv)
1000{
a7eb931d
HV
1001 struct solo_enc_dev *solo_enc = video_drvdata(file);
1002 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a 1003
16af690f 1004 if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
016afda4
HV
1005 return -EINVAL;
1006 if (fintv->index)
1007 return -EINVAL;
1008 if ((fintv->width != solo_dev->video_hsize >> 1 ||
1009 fintv->height != solo_dev->video_vsize) &&
1010 (fintv->width != solo_dev->video_hsize ||
1011 fintv->height != solo_dev->video_vsize << 1))
faa4fd2a
BC
1012 return -EINVAL;
1013
1014 fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
1015
4c211ed7 1016 fintv->stepwise.min.numerator = 1;
016afda4 1017 fintv->stepwise.min.denominator = solo_dev->fps;
faa4fd2a 1018
4c211ed7 1019 fintv->stepwise.max.numerator = 15;
016afda4 1020 fintv->stepwise.max.denominator = solo_dev->fps;
faa4fd2a
BC
1021
1022 fintv->stepwise.step.numerator = 1;
4c211ed7 1023 fintv->stepwise.step.denominator = solo_dev->fps;
faa4fd2a
BC
1024
1025 return 0;
1026}
1027
1028static int solo_g_parm(struct file *file, void *priv,
1029 struct v4l2_streamparm *sp)
1030{
a7eb931d 1031 struct solo_enc_dev *solo_enc = video_drvdata(file);
faa4fd2a
BC
1032 struct v4l2_captureparm *cp = &sp->parm.capture;
1033
1034 cp->capability = V4L2_CAP_TIMEPERFRAME;
1035 cp->timeperframe.numerator = solo_enc->interval;
88107675 1036 cp->timeperframe.denominator = solo_enc->solo_dev->fps;
faa4fd2a
BC
1037 cp->capturemode = 0;
1038 /* XXX: Shouldn't we be able to get/set this from videobuf? */
1039 cp->readbuffers = 2;
1040
f62de9be 1041 return 0;
faa4fd2a
BC
1042}
1043
88107675
IL
1044static inline int calc_interval(u8 fps, u32 n, u32 d)
1045{
1046 if (!n || !d)
1047 return 1;
1048 if (d == fps)
1049 return n;
1050 n *= fps;
1051 return min(15U, n / d + (n % d >= (fps >> 1)));
1052}
1053
faa4fd2a
BC
1054static int solo_s_parm(struct file *file, void *priv,
1055 struct v4l2_streamparm *sp)
1056{
a7eb931d 1057 struct solo_enc_dev *solo_enc = video_drvdata(file);
88107675
IL
1058 struct v4l2_fract *t = &sp->parm.capture.timeperframe;
1059 u8 fps = solo_enc->solo_dev->fps;
faa4fd2a 1060
382c31a9 1061 if (vb2_is_streaming(&solo_enc->vidq))
faa4fd2a 1062 return -EBUSY;
faa4fd2a 1063
88107675 1064 solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
faa4fd2a 1065 solo_update_mode(solo_enc);
88107675 1066 return solo_g_parm(file, priv, sp);
faa4fd2a
BC
1067}
1068
c813bd3c 1069static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
faa4fd2a 1070{
c813bd3c
HV
1071 struct solo_enc_dev *solo_enc =
1072 container_of(ctrl->handler, struct solo_enc_dev, hdl);
decebabf 1073 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
1074 int err;
1075
faa4fd2a
BC
1076 switch (ctrl->id) {
1077 case V4L2_CID_BRIGHTNESS:
1078 case V4L2_CID_CONTRAST:
1079 case V4L2_CID_SATURATION:
1080 case V4L2_CID_HUE:
1081 case V4L2_CID_SHARPNESS:
1082 return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
c813bd3c 1083 ctrl->val);
faa4fd2a 1084 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
c813bd3c 1085 solo_enc->gop = ctrl->val;
63e9b45b
AU
1086 solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
1087 solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
c813bd3c 1088 return 0;
56981116
AU
1089 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
1090 solo_enc->qp = ctrl->val;
63e9b45b
AU
1091 solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
1092 solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
56981116 1093 return 0;
4063a3c7
HV
1094 case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
1095 solo_enc->motion_thresh = ctrl->val << 8;
f5df0b7f
HV
1096 if (!solo_enc->motion_global || !solo_enc->motion_enabled)
1097 return 0;
fa91783e 1098 return solo_set_motion_threshold(solo_dev, solo_enc->ch,
4063a3c7
HV
1099 solo_enc->motion_thresh);
1100 case V4L2_CID_DETECT_MD_MODE:
1101 solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
1102 solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
f5df0b7f
HV
1103 if (ctrl->val) {
1104 if (solo_enc->motion_global)
0a128308 1105 err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
4063a3c7 1106 solo_enc->motion_thresh);
f5df0b7f 1107 else
0a128308 1108 err = solo_set_motion_block(solo_dev, solo_enc->ch,
4063a3c7 1109 solo_enc->md_thresholds->p_cur.p_u16);
0a128308
HV
1110 if (err)
1111 return err;
dcae5dac 1112 }
c813bd3c
HV
1113 solo_motion_toggle(solo_enc, ctrl->val);
1114 return 0;
4063a3c7
HV
1115 case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
1116 if (solo_enc->motion_enabled && !solo_enc->motion_global)
1117 return solo_set_motion_block(solo_dev, solo_enc->ch,
1118 solo_enc->md_thresholds->p_new.p_u16);
1119 break;
c813bd3c 1120 case V4L2_CID_OSD_TEXT:
cc1e6315
MCC
1121 strscpy(solo_enc->osd_text, ctrl->p_new.p_char,
1122 sizeof(solo_enc->osd_text));
0a128308 1123 return solo_osd_print(solo_enc);
faa4fd2a
BC
1124 default:
1125 return -EINVAL;
1126 }
1127
1128 return 0;
1129}
1130
316d9e84
HV
1131static int solo_subscribe_event(struct v4l2_fh *fh,
1132 const struct v4l2_event_subscription *sub)
1133{
1134
1135 switch (sub->type) {
316d9e84
HV
1136 case V4L2_EVENT_MOTION_DET:
1137 /* Allow for up to 30 events (1 second for NTSC) to be
1138 * stored. */
1139 return v4l2_event_subscribe(fh, sub, 30, NULL);
f4fde9a7
GP
1140 default:
1141 return v4l2_ctrl_subscribe_event(fh, sub);
316d9e84 1142 }
316d9e84
HV
1143}
1144
faa4fd2a
BC
1145static const struct v4l2_file_operations solo_enc_fops = {
1146 .owner = THIS_MODULE,
382c31a9
HV
1147 .open = v4l2_fh_open,
1148 .release = vb2_fop_release,
1149 .read = vb2_fop_read,
1150 .poll = vb2_fop_poll,
1151 .mmap = vb2_fop_mmap,
1152 .unlocked_ioctl = video_ioctl2,
faa4fd2a
BC
1153};
1154
1155static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1156 .vidioc_querycap = solo_enc_querycap,
1157 .vidioc_s_std = solo_enc_s_std,
4c211ed7 1158 .vidioc_g_std = solo_enc_g_std,
faa4fd2a
BC
1159 /* Input callbacks */
1160 .vidioc_enum_input = solo_enc_enum_input,
1161 .vidioc_s_input = solo_enc_set_input,
1162 .vidioc_g_input = solo_enc_get_input,
1163 /* Video capture format callbacks */
1164 .vidioc_enum_fmt_vid_cap = solo_enc_enum_fmt_cap,
1165 .vidioc_try_fmt_vid_cap = solo_enc_try_fmt_cap,
1166 .vidioc_s_fmt_vid_cap = solo_enc_set_fmt_cap,
1167 .vidioc_g_fmt_vid_cap = solo_enc_get_fmt_cap,
1168 /* Streaming I/O */
382c31a9
HV
1169 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1170 .vidioc_querybuf = vb2_ioctl_querybuf,
1171 .vidioc_qbuf = vb2_ioctl_qbuf,
1172 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1173 .vidioc_streamon = vb2_ioctl_streamon,
1174 .vidioc_streamoff = vb2_ioctl_streamoff,
faa4fd2a
BC
1175 /* Frame size and interval */
1176 .vidioc_enum_framesizes = solo_enum_framesizes,
1177 .vidioc_enum_frameintervals = solo_enum_frameintervals,
1178 /* Video capture parameters */
1179 .vidioc_s_parm = solo_s_parm,
1180 .vidioc_g_parm = solo_g_parm,
94160497
HV
1181 /* Logging and events */
1182 .vidioc_log_status = v4l2_ctrl_log_status,
316d9e84 1183 .vidioc_subscribe_event = solo_subscribe_event,
94160497 1184 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
faa4fd2a
BC
1185};
1186
dcae5dac 1187static const struct video_device solo_enc_template = {
decebabf 1188 .name = SOLO6X10_NAME,
faa4fd2a
BC
1189 .fops = &solo_enc_fops,
1190 .ioctl_ops = &solo_enc_ioctl_ops,
1191 .minor = -1,
1192 .release = video_device_release,
4c211ed7 1193 .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL,
faa4fd2a
BC
1194};
1195
c813bd3c
HV
1196static const struct v4l2_ctrl_ops solo_ctrl_ops = {
1197 .s_ctrl = solo_s_ctrl,
1198};
1199
c813bd3c
HV
1200static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
1201 .ops = &solo_ctrl_ops,
1202 .id = V4L2_CID_OSD_TEXT,
1203 .name = "OSD Text",
1204 .type = V4L2_CTRL_TYPE_STRING,
1205 .max = OSD_TEXT_MAX,
1206 .step = 1,
1207};
1208
4063a3c7
HV
1209/* Motion Detection Threshold matrix */
1210static const struct v4l2_ctrl_config solo_md_thresholds = {
1211 .ops = &solo_ctrl_ops,
1212 .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
1213 .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
1214 .def = SOLO_DEF_MOT_THRESH,
1215 .max = 65535,
1216 .step = 1,
1217};
1218
dcae5dac
HV
1219static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
1220 u8 ch, unsigned nr)
faa4fd2a
BC
1221{
1222 struct solo_enc_dev *solo_enc;
c813bd3c 1223 struct v4l2_ctrl_handler *hdl;
faa4fd2a
BC
1224 int ret;
1225
1226 solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
1227 if (!solo_enc)
1228 return ERR_PTR(-ENOMEM);
1229
c813bd3c
HV
1230 hdl = &solo_enc->hdl;
1231 v4l2_ctrl_handler_init(hdl, 10);
1232 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1233 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1234 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1235 V4L2_CID_CONTRAST, 0, 255, 1, 128);
1236 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1237 V4L2_CID_SATURATION, 0, 255, 1, 128);
1238 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1239 V4L2_CID_HUE, 0, 255, 1, 128);
1240 if (tw28_has_sharpness(solo_dev, ch))
1241 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1242 V4L2_CID_SHARPNESS, 0, 15, 1, 0);
c813bd3c
HV
1243 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1244 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
56981116
AU
1245 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1246 V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
4063a3c7
HV
1247 v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
1248 V4L2_CID_DETECT_MD_MODE,
1249 V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
1250 V4L2_DETECT_MD_MODE_DISABLED);
1251 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1252 V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
1253 SOLO_DEF_MOT_THRESH >> 8);
c813bd3c 1254 v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
4063a3c7
HV
1255 solo_enc->md_thresholds =
1256 v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
c813bd3c
HV
1257 if (hdl->error) {
1258 ret = hdl->error;
a7eb931d 1259 goto hdl_free;
faa4fd2a
BC
1260 }
1261
1262 solo_enc->solo_dev = solo_dev;
1263 solo_enc->ch = ch;
382c31a9 1264 mutex_init(&solo_enc->lock);
a7eb931d
HV
1265 spin_lock_init(&solo_enc->av_lock);
1266 INIT_LIST_HEAD(&solo_enc->vidq_active);
16af690f
IL
1267 solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
1268 V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
a7eb931d 1269 solo_enc->type = SOLO_ENC_TYPE_STD;
faa4fd2a 1270
faa4fd2a 1271 solo_enc->qp = SOLO_DEFAULT_QP;
f62de9be 1272 solo_enc->gop = solo_dev->fps;
faa4fd2a
BC
1273 solo_enc->interval = 1;
1274 solo_enc->mode = SOLO_ENC_MODE_CIF;
f5df0b7f 1275 solo_enc->motion_global = true;
faa4fd2a 1276 solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
382c31a9
HV
1277 solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1278 solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1279 solo_enc->vidq.ops = &solo_enc_video_qops;
1280 solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
1281 solo_enc->vidq.drv_priv = solo_enc;
d0164adc 1282 solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
ade48681 1283 solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
382c31a9
HV
1284 solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
1285 solo_enc->vidq.lock = &solo_enc->lock;
2bc46b3a 1286 solo_enc->vidq.dev = &solo_dev->pdev->dev;
382c31a9
HV
1287 ret = vb2_queue_init(&solo_enc->vidq);
1288 if (ret)
1289 goto hdl_free;
faa4fd2a 1290 solo_update_mode(solo_enc);
a7eb931d 1291
a7eb931d
HV
1292 spin_lock_init(&solo_enc->motion_lock);
1293
dcae5dac
HV
1294 /* Initialize this per encoder */
1295 solo_enc->jpeg_len = sizeof(jpeg_header);
1296 memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
faa4fd2a 1297
a7eb931d
HV
1298 solo_enc->desc_nelts = 32;
1299 solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
1300 sizeof(struct solo_p2m_desc) *
fa91783e
AO
1301 solo_enc->desc_nelts,
1302 &solo_enc->desc_dma);
a7eb931d
HV
1303 ret = -ENOMEM;
1304 if (solo_enc->desc_items == NULL)
1305 goto hdl_free;
1306
a7eb931d
HV
1307 solo_enc->vfd = video_device_alloc();
1308 if (!solo_enc->vfd)
1309 goto pci_free;
1310
1311 *solo_enc->vfd = solo_enc_template;
1312 solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
1313 solo_enc->vfd->ctrl_handler = hdl;
382c31a9
HV
1314 solo_enc->vfd->queue = &solo_enc->vidq;
1315 solo_enc->vfd->lock = &solo_enc->lock;
a7eb931d
HV
1316 video_set_drvdata(solo_enc->vfd, solo_enc);
1317 ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
1318 if (ret < 0)
1319 goto vdev_release;
1320
1321 snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
1322 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
1323 solo_enc->vfd->num);
1324
faa4fd2a 1325 return solo_enc;
a7eb931d
HV
1326
1327vdev_release:
1328 video_device_release(solo_enc->vfd);
1329pci_free:
1330 pci_free_consistent(solo_enc->solo_dev->pdev,
1331 sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
1332 solo_enc->desc_items, solo_enc->desc_dma);
1333hdl_free:
1334 v4l2_ctrl_handler_free(hdl);
1335 kfree(solo_enc);
1336 return ERR_PTR(ret);
faa4fd2a
BC
1337}
1338
1339static void solo_enc_free(struct solo_enc_dev *solo_enc)
1340{
1341 if (solo_enc == NULL)
1342 return;
1343
0cb2df38
AU
1344 pci_free_consistent(solo_enc->solo_dev->pdev,
1345 sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
1346 solo_enc->desc_items, solo_enc->desc_dma);
faa4fd2a 1347 video_unregister_device(solo_enc->vfd);
c813bd3c 1348 v4l2_ctrl_handler_free(&solo_enc->hdl);
faa4fd2a
BC
1349 kfree(solo_enc);
1350}
1351
dcae5dac 1352int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
faa4fd2a
BC
1353{
1354 int i;
1355
dcae5dac
HV
1356 init_waitqueue_head(&solo_dev->ring_thread_wait);
1357
4a61ad3c 1358 solo_dev->vh_size = sizeof(vop_header);
dcae5dac
HV
1359 solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
1360 solo_dev->vh_size,
1361 &solo_dev->vh_dma);
1362 if (solo_dev->vh_buf == NULL)
1363 return -ENOMEM;
1364
faa4fd2a 1365 for (i = 0; i < solo_dev->nr_chans; i++) {
dcae5dac 1366 solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
faa4fd2a
BC
1367 if (IS_ERR(solo_dev->v4l2_enc[i]))
1368 break;
1369 }
1370
1371 if (i != solo_dev->nr_chans) {
1372 int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1c6f3db0 1373
faa4fd2a
BC
1374 while (i--)
1375 solo_enc_free(solo_dev->v4l2_enc[i]);
dcae5dac
HV
1376 pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
1377 solo_dev->vh_buf, solo_dev->vh_dma);
a7eb931d 1378 solo_dev->vh_buf = NULL;
faa4fd2a
BC
1379 return ret;
1380 }
1381
dcae5dac
HV
1382 if (solo_dev->type == SOLO_DEV_6010)
1383 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
1384 else
1385 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
faa4fd2a
BC
1386
1387 dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
1388 solo_dev->v4l2_enc[0]->vfd->num,
1389 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
1390
670390c2 1391 return solo_ring_start(solo_dev);
faa4fd2a
BC
1392}
1393
decebabf 1394void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
faa4fd2a
BC
1395{
1396 int i;
1397
670390c2
AU
1398 solo_ring_stop(solo_dev);
1399
faa4fd2a
BC
1400 for (i = 0; i < solo_dev->nr_chans; i++)
1401 solo_enc_free(solo_dev->v4l2_enc[i]);
dcae5dac 1402
a7eb931d
HV
1403 if (solo_dev->vh_buf)
1404 pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
dcae5dac 1405 solo_dev->vh_buf, solo_dev->vh_dma);
faa4fd2a 1406}