]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
Merge tag 'drm-next-2025-07-30' of https://gitlab.freedesktop.org/drm/kernel
[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/*
cf293a4f 3 * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
dcae5dac
HV
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 393/* Extract values from VOP header - VE_STATUSxx */
02d6276f 394static inline __always_unused int vop_interlaced(const vop_header *vh)
4a61ad3c
KH
395{
396 return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
397}
398
02d6276f 399static inline __always_unused u8 vop_channel(const vop_header *vh)
4a61ad3c
KH
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
02d6276f 414static inline u8 __always_unused vop_hsize(const vop_header *vh)
4a61ad3c
KH
415{
416 return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
417}
418
02d6276f 419static inline u8 __always_unused vop_vsize(const vop_header *vh)
4a61ad3c
KH
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
02d6276f 439static inline u32 __always_unused vop_sec(const vop_header *vh)
4a61ad3c
KH
440{
441 return __le32_to_cpu((*vh)[5]);
442}
443
02d6276f 444static inline __always_unused u32 vop_usec(const vop_header *vh)
4a61ad3c
KH
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,
382c31a9
HV
759};
760
faa4fd2a
BC
761static int solo_enc_querycap(struct file *file, void *priv,
762 struct v4l2_capability *cap)
763{
a7eb931d 764 struct solo_enc_dev *solo_enc = video_drvdata(file);
faa4fd2a 765
cc1e6315 766 strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
decebabf 767 snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
faa4fd2a 768 solo_enc->ch);
faa4fd2a
BC
769 return 0;
770}
771
772static int solo_enc_enum_input(struct file *file, void *priv,
773 struct v4l2_input *input)
774{
a7eb931d 775 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 776 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
777
778 if (input->index)
779 return -EINVAL;
780
781 snprintf(input->name, sizeof(input->name), "Encoder %d",
782 solo_enc->ch + 1);
783 input->type = V4L2_INPUT_TYPE_CAMERA;
4c211ed7 784 input->std = solo_enc->vfd->tvnorms;
faa4fd2a
BC
785
786 if (!tw28_get_video_status(solo_dev, solo_enc->ch))
787 input->status = V4L2_IN_ST_NO_SIGNAL;
788
789 return 0;
790}
791
dcae5dac
HV
792static int solo_enc_set_input(struct file *file, void *priv,
793 unsigned int index)
faa4fd2a
BC
794{
795 if (index)
796 return -EINVAL;
797
798 return 0;
799}
800
801static int solo_enc_get_input(struct file *file, void *priv,
802 unsigned int *index)
803{
804 *index = 0;
805
806 return 0;
807}
808
809static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
810 struct v4l2_fmtdesc *f)
811{
16af690f
IL
812 struct solo_enc_dev *solo_enc = video_drvdata(file);
813 int dev_type = solo_enc->solo_dev->type;
814
faa4fd2a
BC
815 switch (f->index) {
816 case 0:
16af690f
IL
817 switch (dev_type) {
818 case SOLO_DEV_6010:
819 f->pixelformat = V4L2_PIX_FMT_MPEG4;
16af690f
IL
820 break;
821 case SOLO_DEV_6110:
822 f->pixelformat = V4L2_PIX_FMT_H264;
16af690f
IL
823 break;
824 }
faa4fd2a
BC
825 break;
826 case 1:
827 f->pixelformat = V4L2_PIX_FMT_MJPEG;
faa4fd2a
BC
828 break;
829 default:
830 return -EINVAL;
831 }
faa4fd2a
BC
832 return 0;
833}
834
16af690f
IL
835static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
836{
837 return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
838 || (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
839 || pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
840}
841
faa4fd2a
BC
842static int solo_enc_try_fmt_cap(struct file *file, void *priv,
843 struct v4l2_format *f)
844{
a7eb931d 845 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 846 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
847 struct v4l2_pix_format *pix = &f->fmt.pix;
848
16af690f 849 if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
faa4fd2a
BC
850 return -EINVAL;
851
98ab1c99
KH
852 if (pix->width < solo_dev->video_hsize ||
853 pix->height < solo_dev->video_vsize << 1) {
faa4fd2a
BC
854 /* Default to CIF 1/2 size */
855 pix->width = solo_dev->video_hsize >> 1;
856 pix->height = solo_dev->video_vsize;
98ab1c99
KH
857 } else {
858 /* Full frame */
859 pix->width = solo_dev->video_hsize;
860 pix->height = solo_dev->video_vsize << 1;
faa4fd2a
BC
861 }
862
016afda4
HV
863 switch (pix->field) {
864 case V4L2_FIELD_NONE:
865 case V4L2_FIELD_INTERLACED:
866 break;
867 case V4L2_FIELD_ANY:
868 default:
faa4fd2a 869 pix->field = V4L2_FIELD_INTERLACED;
016afda4
HV
870 break;
871 }
faa4fd2a
BC
872
873 /* Just set these */
874 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
875 pix->sizeimage = FRAME_BUF_SIZE;
94160497 876 pix->bytesperline = 0;
faa4fd2a
BC
877
878 return 0;
879}
880
881static int solo_enc_set_fmt_cap(struct file *file, void *priv,
882 struct v4l2_format *f)
883{
a7eb931d 884 struct solo_enc_dev *solo_enc = video_drvdata(file);
decebabf 885 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
886 struct v4l2_pix_format *pix = &f->fmt.pix;
887 int ret;
888
382c31a9
HV
889 if (vb2_is_busy(&solo_enc->vidq))
890 return -EBUSY;
faa4fd2a 891
afabbe6d 892 ret = solo_enc_try_fmt_cap(file, priv, f);
016afda4
HV
893 if (ret)
894 return ret;
895
faa4fd2a
BC
896 if (pix->width == solo_dev->video_hsize)
897 solo_enc->mode = SOLO_ENC_MODE_D1;
898 else
899 solo_enc->mode = SOLO_ENC_MODE_CIF;
900
901 /* This does not change the encoder at all */
a7eb931d 902 solo_enc->fmt = pix->pixelformat;
faa4fd2a 903
69996873
HV
904 /*
905 * More information is needed about these 'extended' types. As far
906 * as I can tell these are basically additional video streams with
907 * different MPEG encoding attributes that can run in parallel with
908 * the main stream. If so, then this should be implemented as a
909 * second video node. Abusing priv like this is certainly not the
910 * right approach.
faa4fd2a 911 if (pix->priv)
a7eb931d 912 solo_enc->type = SOLO_ENC_TYPE_EXT;
69996873 913 */
cdcfe40a 914 solo_update_mode(solo_enc);
dcae5dac 915 return 0;
faa4fd2a
BC
916}
917
918static int solo_enc_get_fmt_cap(struct file *file, void *priv,
919 struct v4l2_format *f)
920{
a7eb931d 921 struct solo_enc_dev *solo_enc = video_drvdata(file);
faa4fd2a
BC
922 struct v4l2_pix_format *pix = &f->fmt.pix;
923
924 pix->width = solo_enc->width;
925 pix->height = solo_enc->height;
a7eb931d 926 pix->pixelformat = solo_enc->fmt;
faa4fd2a
BC
927 pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
928 V4L2_FIELD_NONE;
929 pix->sizeimage = FRAME_BUF_SIZE;
930 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
931
932 return 0;
933}
934
4c211ed7 935static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
faa4fd2a 936{
4c211ed7
HV
937 struct solo_enc_dev *solo_enc = video_drvdata(file);
938 struct solo_dev *solo_dev = solo_enc->solo_dev;
939
940 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
941 *i = V4L2_STD_NTSC_M;
942 else
943 *i = V4L2_STD_PAL;
faa4fd2a
BC
944 return 0;
945}
946
4c211ed7
HV
947static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
948{
949 struct solo_enc_dev *solo_enc = video_drvdata(file);
950
429df502 951 return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
4c211ed7
HV
952}
953
faa4fd2a
BC
954static int solo_enum_framesizes(struct file *file, void *priv,
955 struct v4l2_frmsizeenum *fsize)
956{
a7eb931d
HV
957 struct solo_enc_dev *solo_enc = video_drvdata(file);
958 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a 959
16af690f 960 if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
faa4fd2a
BC
961 return -EINVAL;
962
963 switch (fsize->index) {
964 case 0:
965 fsize->discrete.width = solo_dev->video_hsize >> 1;
966 fsize->discrete.height = solo_dev->video_vsize;
967 break;
968 case 1:
969 fsize->discrete.width = solo_dev->video_hsize;
970 fsize->discrete.height = solo_dev->video_vsize << 1;
971 break;
972 default:
973 return -EINVAL;
974 }
975
976 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
977
978 return 0;
979}
980
981static int solo_enum_frameintervals(struct file *file, void *priv,
982 struct v4l2_frmivalenum *fintv)
983{
a7eb931d
HV
984 struct solo_enc_dev *solo_enc = video_drvdata(file);
985 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a 986
16af690f 987 if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
016afda4
HV
988 return -EINVAL;
989 if (fintv->index)
990 return -EINVAL;
991 if ((fintv->width != solo_dev->video_hsize >> 1 ||
992 fintv->height != solo_dev->video_vsize) &&
993 (fintv->width != solo_dev->video_hsize ||
994 fintv->height != solo_dev->video_vsize << 1))
faa4fd2a
BC
995 return -EINVAL;
996
997 fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
998
4c211ed7 999 fintv->stepwise.min.numerator = 1;
016afda4 1000 fintv->stepwise.min.denominator = solo_dev->fps;
faa4fd2a 1001
4c211ed7 1002 fintv->stepwise.max.numerator = 15;
016afda4 1003 fintv->stepwise.max.denominator = solo_dev->fps;
faa4fd2a
BC
1004
1005 fintv->stepwise.step.numerator = 1;
4c211ed7 1006 fintv->stepwise.step.denominator = solo_dev->fps;
faa4fd2a
BC
1007
1008 return 0;
1009}
1010
1011static int solo_g_parm(struct file *file, void *priv,
1012 struct v4l2_streamparm *sp)
1013{
a7eb931d 1014 struct solo_enc_dev *solo_enc = video_drvdata(file);
faa4fd2a
BC
1015 struct v4l2_captureparm *cp = &sp->parm.capture;
1016
1017 cp->capability = V4L2_CAP_TIMEPERFRAME;
1018 cp->timeperframe.numerator = solo_enc->interval;
88107675 1019 cp->timeperframe.denominator = solo_enc->solo_dev->fps;
faa4fd2a 1020 cp->capturemode = 0;
f068a6ce 1021 /* XXX: Shouldn't we be able to get/set this from vb2? */
faa4fd2a
BC
1022 cp->readbuffers = 2;
1023
f62de9be 1024 return 0;
faa4fd2a
BC
1025}
1026
88107675
IL
1027static inline int calc_interval(u8 fps, u32 n, u32 d)
1028{
1029 if (!n || !d)
1030 return 1;
1031 if (d == fps)
1032 return n;
1033 n *= fps;
1034 return min(15U, n / d + (n % d >= (fps >> 1)));
1035}
1036
faa4fd2a
BC
1037static int solo_s_parm(struct file *file, void *priv,
1038 struct v4l2_streamparm *sp)
1039{
a7eb931d 1040 struct solo_enc_dev *solo_enc = video_drvdata(file);
88107675
IL
1041 struct v4l2_fract *t = &sp->parm.capture.timeperframe;
1042 u8 fps = solo_enc->solo_dev->fps;
faa4fd2a 1043
382c31a9 1044 if (vb2_is_streaming(&solo_enc->vidq))
faa4fd2a 1045 return -EBUSY;
faa4fd2a 1046
88107675 1047 solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
faa4fd2a 1048 solo_update_mode(solo_enc);
88107675 1049 return solo_g_parm(file, priv, sp);
faa4fd2a
BC
1050}
1051
c813bd3c 1052static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
faa4fd2a 1053{
c813bd3c
HV
1054 struct solo_enc_dev *solo_enc =
1055 container_of(ctrl->handler, struct solo_enc_dev, hdl);
decebabf 1056 struct solo_dev *solo_dev = solo_enc->solo_dev;
faa4fd2a
BC
1057 int err;
1058
faa4fd2a
BC
1059 switch (ctrl->id) {
1060 case V4L2_CID_BRIGHTNESS:
1061 case V4L2_CID_CONTRAST:
1062 case V4L2_CID_SATURATION:
1063 case V4L2_CID_HUE:
1064 case V4L2_CID_SHARPNESS:
1065 return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
c813bd3c 1066 ctrl->val);
faa4fd2a 1067 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
c813bd3c 1068 solo_enc->gop = ctrl->val;
63e9b45b
AU
1069 solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
1070 solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
c813bd3c 1071 return 0;
56981116
AU
1072 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
1073 solo_enc->qp = ctrl->val;
63e9b45b
AU
1074 solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
1075 solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
56981116 1076 return 0;
4063a3c7
HV
1077 case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
1078 solo_enc->motion_thresh = ctrl->val << 8;
f5df0b7f
HV
1079 if (!solo_enc->motion_global || !solo_enc->motion_enabled)
1080 return 0;
fa91783e 1081 return solo_set_motion_threshold(solo_dev, solo_enc->ch,
4063a3c7
HV
1082 solo_enc->motion_thresh);
1083 case V4L2_CID_DETECT_MD_MODE:
1084 solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
1085 solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
f5df0b7f
HV
1086 if (ctrl->val) {
1087 if (solo_enc->motion_global)
0a128308 1088 err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
4063a3c7 1089 solo_enc->motion_thresh);
f5df0b7f 1090 else
0a128308 1091 err = solo_set_motion_block(solo_dev, solo_enc->ch,
4063a3c7 1092 solo_enc->md_thresholds->p_cur.p_u16);
0a128308
HV
1093 if (err)
1094 return err;
dcae5dac 1095 }
c813bd3c
HV
1096 solo_motion_toggle(solo_enc, ctrl->val);
1097 return 0;
4063a3c7
HV
1098 case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
1099 if (solo_enc->motion_enabled && !solo_enc->motion_global)
1100 return solo_set_motion_block(solo_dev, solo_enc->ch,
1101 solo_enc->md_thresholds->p_new.p_u16);
1102 break;
c813bd3c 1103 case V4L2_CID_OSD_TEXT:
cc1e6315
MCC
1104 strscpy(solo_enc->osd_text, ctrl->p_new.p_char,
1105 sizeof(solo_enc->osd_text));
0a128308 1106 return solo_osd_print(solo_enc);
faa4fd2a
BC
1107 default:
1108 return -EINVAL;
1109 }
1110
1111 return 0;
1112}
1113
316d9e84
HV
1114static int solo_subscribe_event(struct v4l2_fh *fh,
1115 const struct v4l2_event_subscription *sub)
1116{
1117
1118 switch (sub->type) {
316d9e84
HV
1119 case V4L2_EVENT_MOTION_DET:
1120 /* Allow for up to 30 events (1 second for NTSC) to be
1121 * stored. */
1122 return v4l2_event_subscribe(fh, sub, 30, NULL);
f4fde9a7
GP
1123 default:
1124 return v4l2_ctrl_subscribe_event(fh, sub);
316d9e84 1125 }
316d9e84
HV
1126}
1127
faa4fd2a
BC
1128static const struct v4l2_file_operations solo_enc_fops = {
1129 .owner = THIS_MODULE,
382c31a9
HV
1130 .open = v4l2_fh_open,
1131 .release = vb2_fop_release,
1132 .read = vb2_fop_read,
1133 .poll = vb2_fop_poll,
1134 .mmap = vb2_fop_mmap,
1135 .unlocked_ioctl = video_ioctl2,
faa4fd2a
BC
1136};
1137
1138static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1139 .vidioc_querycap = solo_enc_querycap,
1140 .vidioc_s_std = solo_enc_s_std,
4c211ed7 1141 .vidioc_g_std = solo_enc_g_std,
faa4fd2a
BC
1142 /* Input callbacks */
1143 .vidioc_enum_input = solo_enc_enum_input,
1144 .vidioc_s_input = solo_enc_set_input,
1145 .vidioc_g_input = solo_enc_get_input,
1146 /* Video capture format callbacks */
1147 .vidioc_enum_fmt_vid_cap = solo_enc_enum_fmt_cap,
1148 .vidioc_try_fmt_vid_cap = solo_enc_try_fmt_cap,
1149 .vidioc_s_fmt_vid_cap = solo_enc_set_fmt_cap,
1150 .vidioc_g_fmt_vid_cap = solo_enc_get_fmt_cap,
1151 /* Streaming I/O */
382c31a9
HV
1152 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1153 .vidioc_querybuf = vb2_ioctl_querybuf,
1154 .vidioc_qbuf = vb2_ioctl_qbuf,
1155 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1156 .vidioc_streamon = vb2_ioctl_streamon,
1157 .vidioc_streamoff = vb2_ioctl_streamoff,
faa4fd2a
BC
1158 /* Frame size and interval */
1159 .vidioc_enum_framesizes = solo_enum_framesizes,
1160 .vidioc_enum_frameintervals = solo_enum_frameintervals,
1161 /* Video capture parameters */
1162 .vidioc_s_parm = solo_s_parm,
1163 .vidioc_g_parm = solo_g_parm,
94160497
HV
1164 /* Logging and events */
1165 .vidioc_log_status = v4l2_ctrl_log_status,
316d9e84 1166 .vidioc_subscribe_event = solo_subscribe_event,
94160497 1167 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
faa4fd2a
BC
1168};
1169
dcae5dac 1170static const struct video_device solo_enc_template = {
decebabf 1171 .name = SOLO6X10_NAME,
faa4fd2a
BC
1172 .fops = &solo_enc_fops,
1173 .ioctl_ops = &solo_enc_ioctl_ops,
1174 .minor = -1,
1175 .release = video_device_release,
4c211ed7 1176 .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL,
21615365
HV
1177 .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
1178 V4L2_CAP_STREAMING,
faa4fd2a
BC
1179};
1180
c813bd3c
HV
1181static const struct v4l2_ctrl_ops solo_ctrl_ops = {
1182 .s_ctrl = solo_s_ctrl,
1183};
1184
c813bd3c
HV
1185static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
1186 .ops = &solo_ctrl_ops,
1187 .id = V4L2_CID_OSD_TEXT,
1188 .name = "OSD Text",
1189 .type = V4L2_CTRL_TYPE_STRING,
1190 .max = OSD_TEXT_MAX,
1191 .step = 1,
1192};
1193
4063a3c7
HV
1194/* Motion Detection Threshold matrix */
1195static const struct v4l2_ctrl_config solo_md_thresholds = {
1196 .ops = &solo_ctrl_ops,
1197 .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
1198 .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
1199 .def = SOLO_DEF_MOT_THRESH,
1200 .max = 65535,
1201 .step = 1,
1202};
1203
dcae5dac
HV
1204static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
1205 u8 ch, unsigned nr)
faa4fd2a
BC
1206{
1207 struct solo_enc_dev *solo_enc;
c813bd3c 1208 struct v4l2_ctrl_handler *hdl;
faa4fd2a
BC
1209 int ret;
1210
1211 solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
1212 if (!solo_enc)
1213 return ERR_PTR(-ENOMEM);
1214
c813bd3c
HV
1215 hdl = &solo_enc->hdl;
1216 v4l2_ctrl_handler_init(hdl, 10);
1217 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1218 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1219 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1220 V4L2_CID_CONTRAST, 0, 255, 1, 128);
1221 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1222 V4L2_CID_SATURATION, 0, 255, 1, 128);
1223 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1224 V4L2_CID_HUE, 0, 255, 1, 128);
1225 if (tw28_has_sharpness(solo_dev, ch))
1226 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1227 V4L2_CID_SHARPNESS, 0, 15, 1, 0);
c813bd3c
HV
1228 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1229 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
56981116
AU
1230 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1231 V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
4063a3c7
HV
1232 v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
1233 V4L2_CID_DETECT_MD_MODE,
1234 V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
1235 V4L2_DETECT_MD_MODE_DISABLED);
1236 v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1237 V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
1238 SOLO_DEF_MOT_THRESH >> 8);
c813bd3c 1239 v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
4063a3c7
HV
1240 solo_enc->md_thresholds =
1241 v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
c813bd3c
HV
1242 if (hdl->error) {
1243 ret = hdl->error;
a7eb931d 1244 goto hdl_free;
faa4fd2a
BC
1245 }
1246
1247 solo_enc->solo_dev = solo_dev;
1248 solo_enc->ch = ch;
382c31a9 1249 mutex_init(&solo_enc->lock);
a7eb931d
HV
1250 spin_lock_init(&solo_enc->av_lock);
1251 INIT_LIST_HEAD(&solo_enc->vidq_active);
16af690f
IL
1252 solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
1253 V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
a7eb931d 1254 solo_enc->type = SOLO_ENC_TYPE_STD;
faa4fd2a 1255
faa4fd2a 1256 solo_enc->qp = SOLO_DEFAULT_QP;
f62de9be 1257 solo_enc->gop = solo_dev->fps;
faa4fd2a
BC
1258 solo_enc->interval = 1;
1259 solo_enc->mode = SOLO_ENC_MODE_CIF;
f5df0b7f 1260 solo_enc->motion_global = true;
faa4fd2a 1261 solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
382c31a9
HV
1262 solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1263 solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1264 solo_enc->vidq.ops = &solo_enc_video_qops;
1265 solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
1266 solo_enc->vidq.drv_priv = solo_enc;
d0164adc 1267 solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
ade48681 1268 solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
382c31a9
HV
1269 solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
1270 solo_enc->vidq.lock = &solo_enc->lock;
2bc46b3a 1271 solo_enc->vidq.dev = &solo_dev->pdev->dev;
382c31a9
HV
1272 ret = vb2_queue_init(&solo_enc->vidq);
1273 if (ret)
1274 goto hdl_free;
faa4fd2a 1275 solo_update_mode(solo_enc);
a7eb931d 1276
a7eb931d
HV
1277 spin_lock_init(&solo_enc->motion_lock);
1278
dcae5dac
HV
1279 /* Initialize this per encoder */
1280 solo_enc->jpeg_len = sizeof(jpeg_header);
1281 memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
faa4fd2a 1282
a7eb931d 1283 solo_enc->desc_nelts = 32;
0c5a71dc
CJ
1284 solo_enc->desc_items = dma_alloc_coherent(&solo_dev->pdev->dev,
1285 sizeof(struct solo_p2m_desc) *
1286 solo_enc->desc_nelts,
1287 &solo_enc->desc_dma,
1288 GFP_KERNEL);
a7eb931d
HV
1289 ret = -ENOMEM;
1290 if (solo_enc->desc_items == NULL)
1291 goto hdl_free;
1292
a7eb931d
HV
1293 solo_enc->vfd = video_device_alloc();
1294 if (!solo_enc->vfd)
1295 goto pci_free;
1296
1297 *solo_enc->vfd = solo_enc_template;
1298 solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
1299 solo_enc->vfd->ctrl_handler = hdl;
382c31a9
HV
1300 solo_enc->vfd->queue = &solo_enc->vidq;
1301 solo_enc->vfd->lock = &solo_enc->lock;
a7eb931d 1302 video_set_drvdata(solo_enc->vfd, solo_enc);
3e30a927 1303 ret = video_register_device(solo_enc->vfd, VFL_TYPE_VIDEO, nr);
a7eb931d
HV
1304 if (ret < 0)
1305 goto vdev_release;
1306
1307 snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
1308 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
1309 solo_enc->vfd->num);
1310
faa4fd2a 1311 return solo_enc;
a7eb931d
HV
1312
1313vdev_release:
1314 video_device_release(solo_enc->vfd);
1315pci_free:
0c5a71dc
CJ
1316 dma_free_coherent(&solo_enc->solo_dev->pdev->dev,
1317 sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
1318 solo_enc->desc_items, solo_enc->desc_dma);
a7eb931d
HV
1319hdl_free:
1320 v4l2_ctrl_handler_free(hdl);
1321 kfree(solo_enc);
1322 return ERR_PTR(ret);
faa4fd2a
BC
1323}
1324
1325static void solo_enc_free(struct solo_enc_dev *solo_enc)
1326{
1327 if (solo_enc == NULL)
1328 return;
1329
0c5a71dc
CJ
1330 dma_free_coherent(&solo_enc->solo_dev->pdev->dev,
1331 sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
1332 solo_enc->desc_items, solo_enc->desc_dma);
faa4fd2a 1333 video_unregister_device(solo_enc->vfd);
c813bd3c 1334 v4l2_ctrl_handler_free(&solo_enc->hdl);
faa4fd2a
BC
1335 kfree(solo_enc);
1336}
1337
dcae5dac 1338int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
faa4fd2a
BC
1339{
1340 int i;
1341
dcae5dac
HV
1342 init_waitqueue_head(&solo_dev->ring_thread_wait);
1343
4a61ad3c 1344 solo_dev->vh_size = sizeof(vop_header);
0c5a71dc
CJ
1345 solo_dev->vh_buf = dma_alloc_coherent(&solo_dev->pdev->dev,
1346 solo_dev->vh_size,
1347 &solo_dev->vh_dma, GFP_KERNEL);
dcae5dac
HV
1348 if (solo_dev->vh_buf == NULL)
1349 return -ENOMEM;
1350
faa4fd2a 1351 for (i = 0; i < solo_dev->nr_chans; i++) {
dcae5dac 1352 solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
faa4fd2a
BC
1353 if (IS_ERR(solo_dev->v4l2_enc[i]))
1354 break;
1355 }
1356
1357 if (i != solo_dev->nr_chans) {
1358 int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1c6f3db0 1359
faa4fd2a
BC
1360 while (i--)
1361 solo_enc_free(solo_dev->v4l2_enc[i]);
0c5a71dc
CJ
1362 dma_free_coherent(&solo_dev->pdev->dev, solo_dev->vh_size,
1363 solo_dev->vh_buf, solo_dev->vh_dma);
a7eb931d 1364 solo_dev->vh_buf = NULL;
faa4fd2a
BC
1365 return ret;
1366 }
1367
dcae5dac
HV
1368 if (solo_dev->type == SOLO_DEV_6010)
1369 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
1370 else
1371 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
faa4fd2a
BC
1372
1373 dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
1374 solo_dev->v4l2_enc[0]->vfd->num,
1375 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
1376
670390c2 1377 return solo_ring_start(solo_dev);
faa4fd2a
BC
1378}
1379
decebabf 1380void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
faa4fd2a
BC
1381{
1382 int i;
1383
670390c2
AU
1384 solo_ring_stop(solo_dev);
1385
faa4fd2a
BC
1386 for (i = 0; i < solo_dev->nr_chans; i++)
1387 solo_enc_free(solo_dev->v4l2_enc[i]);
dcae5dac 1388
a7eb931d 1389 if (solo_dev->vh_buf)
0c5a71dc
CJ
1390 dma_free_coherent(&solo_dev->pdev->dev, solo_dev->vh_size,
1391 solo_dev->vh_buf, solo_dev->vh_dma);
faa4fd2a 1392}