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