• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/solo6x10/
1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/kthread.h>
23#include <linux/freezer.h>
24
25#include <media/v4l2-ioctl.h>
26#include <media/v4l2-common.h>
27#include <media/videobuf-dma-contig.h>
28
29#include "solo6010.h"
30#include "solo6010-tw28.h"
31#include "solo6010-jpeg.h"
32
33#define MIN_VID_BUFFERS		4
34#define FRAME_BUF_SIZE		(128 * 1024)
35#define MP4_QS			16
36
37static int solo_enc_thread(void *data);
38
39extern unsigned video_nr;
40
41struct solo_enc_fh {
42	struct			solo_enc_dev *enc;
43	u32			fmt;
44	u16			rd_idx;
45	u8			enc_on;
46	enum solo_enc_types	type;
47	struct videobuf_queue	vidq;
48	struct list_head	vidq_active;
49	struct task_struct	*kthread;
50};
51
52static unsigned char vid_vop_header[] = {
53	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
54	0x02, 0x48, 0x05, 0xc0, 0x00, 0x40, 0x00, 0x40,
55	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
56	0x1f, 0x4c, 0x58, 0x10, 0x78, 0x51, 0x18, 0x3e,
57};
58
59/*
60 * Things we can change around:
61 *
62 * byte  10,        4-bits 01111000                   aspect
63 * bytes 21,22,23  16-bits 000x1111 11111111 1111x000 fps/res
64 * bytes 23,24,25  15-bits 00000n11 11111111 11111x00 interval
65 * bytes 25,26,27  13-bits 00000x11 11111111 111x0000 width
66 * bytes 27,28,29  13-bits 000x1111 11111111 1x000000 height
67 * byte  29         1-bit  0x100000                   interlace
68 */
69
70/* For aspect */
71#define XVID_PAR_43_PAL		2
72#define XVID_PAR_43_NTSC	3
73
74static const u32 solo_user_ctrls[] = {
75	V4L2_CID_BRIGHTNESS,
76	V4L2_CID_CONTRAST,
77	V4L2_CID_SATURATION,
78	V4L2_CID_HUE,
79	V4L2_CID_SHARPNESS,
80	0
81};
82
83static const u32 solo_mpeg_ctrls[] = {
84	V4L2_CID_MPEG_VIDEO_ENCODING,
85	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
86	0
87};
88
89static const u32 solo_private_ctrls[] = {
90	V4L2_CID_MOTION_ENABLE,
91	V4L2_CID_MOTION_THRESHOLD,
92	0
93};
94
95static const u32 solo_fmtx_ctrls[] = {
96	V4L2_CID_RDS_TX_RADIO_TEXT,
97	0
98};
99
100static const u32 *solo_ctrl_classes[] = {
101	solo_user_ctrls,
102	solo_mpeg_ctrls,
103	solo_fmtx_ctrls,
104	solo_private_ctrls,
105	NULL
106};
107
108struct vop_header {
109	/* VD_IDX0 */
110	u32 size:20, sync_start:1, page_stop:1, vop_type:2, channel:4,
111		nop0:1, source_fl:1, interlace:1, progressive:1;
112
113	/* VD_IDX1 */
114	u32 vsize:8, hsize:8, frame_interop:1, nop1:7, win_id:4, scale:4;
115
116	/* VD_IDX2 */
117	u32 base_addr:16, nop2:15, hoff:1;
118
119	/* VD_IDX3 - User set macros */
120	u32 sy:12, sx:12, nop3:1, hzoom:1, read_interop:1, write_interlace:1,
121		scale_mode:4;
122
123	/* VD_IDX4 - User set macros continued */
124	u32 write_page:8, nop4:24;
125
126	/* VD_IDX5 */
127	u32 next_code_addr;
128
129	u32 end_nops[10];
130} __attribute__((packed));
131
132static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
133{
134	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
135	u8 ch = solo_enc->ch;
136
137	if (solo_dev->motion_mask & (1 << ch))
138		return 1;
139	return 0;
140}
141
142static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
143{
144	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
145	u8 ch = solo_enc->ch;
146
147	spin_lock(&solo_enc->lock);
148
149	if (on)
150		solo_dev->motion_mask |= (1 << ch);
151	else
152		solo_dev->motion_mask &= ~(1 << ch);
153
154	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
155		       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
156		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
157
158	if (solo_dev->motion_mask)
159		solo6010_irq_on(solo_dev, SOLO_IRQ_MOTION);
160	else
161		solo6010_irq_off(solo_dev, SOLO_IRQ_MOTION);
162
163	spin_unlock(&solo_enc->lock);
164}
165
166/* Should be called with solo_enc->lock held */
167static void solo_update_mode(struct solo_enc_dev *solo_enc)
168{
169	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
170
171	assert_spin_locked(&solo_enc->lock);
172
173	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
174	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
175
176	switch (solo_enc->mode) {
177	case SOLO_ENC_MODE_CIF:
178		solo_enc->width = solo_dev->video_hsize >> 1;
179		solo_enc->height = solo_dev->video_vsize;
180		break;
181	case SOLO_ENC_MODE_D1:
182		solo_enc->width = solo_dev->video_hsize;
183		solo_enc->height = solo_dev->video_vsize << 1;
184		solo_enc->bw_weight <<= 2;
185		break;
186	default:
187		WARN(1, "mode is unknown");
188	}
189}
190
191/* Should be called with solo_enc->lock held */
192static int solo_enc_on(struct solo_enc_fh *fh)
193{
194	struct solo_enc_dev *solo_enc = fh->enc;
195	u8 ch = solo_enc->ch;
196	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
197	u8 interval;
198
199	assert_spin_locked(&solo_enc->lock);
200
201	if (fh->enc_on)
202		return 0;
203
204	solo_update_mode(solo_enc);
205
206	/* Make sure to bw check on first reader */
207	if (!atomic_read(&solo_enc->readers)) {
208		if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
209			return -EBUSY;
210		else
211			solo_dev->enc_bw_remain -= solo_enc->bw_weight;
212	}
213
214	fh->kthread = kthread_run(solo_enc_thread, fh, SOLO6010_NAME "_enc");
215
216	if (IS_ERR(fh->kthread))
217		return PTR_ERR(fh->kthread);
218
219	fh->enc_on = 1;
220	fh->rd_idx = solo_enc->solo_dev->enc_wr_idx;
221
222	if (fh->type == SOLO_ENC_TYPE_EXT)
223		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
224
225	if (atomic_inc_return(&solo_enc->readers) > 1)
226		return 0;
227
228	/* Disable all encoding for this channel */
229	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
230
231	/* Common for both std and ext encoding */
232	solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
233		       solo_enc->interlaced ? 1 : 0);
234
235	if (solo_enc->interlaced)
236		interval = solo_enc->interval - 1;
237	else
238		interval = solo_enc->interval;
239
240	/* Standard encoding only */
241	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
242	solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
243	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
244
245	/* Extended encoding only */
246	solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
247	solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
248	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
249
250	/* Enables the standard encoder */
251	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
252
253	/* Settle down Beavis... */
254	mdelay(10);
255
256	return 0;
257}
258
259static void solo_enc_off(struct solo_enc_fh *fh)
260{
261	struct solo_enc_dev *solo_enc = fh->enc;
262	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
263
264	if (!fh->enc_on)
265		return;
266
267	if (fh->kthread) {
268		kthread_stop(fh->kthread);
269		fh->kthread = NULL;
270	}
271
272	solo_dev->enc_bw_remain += solo_enc->bw_weight;
273	fh->enc_on = 0;
274
275	if (atomic_dec_return(&solo_enc->readers) > 0)
276		return;
277
278	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
279	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
280}
281
282static void enc_reset_gop(struct solo6010_dev *solo_dev, u8 ch)
283{
284	BUG_ON(ch >= solo_dev->nr_chans);
285	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), 1);
286	solo_dev->v4l2_enc[ch]->reset_gop = 1;
287}
288
289static int enc_gop_reset(struct solo6010_dev *solo_dev, u8 ch, u8 vop)
290{
291	BUG_ON(ch >= solo_dev->nr_chans);
292	if (!solo_dev->v4l2_enc[ch]->reset_gop)
293		return 0;
294	if (vop)
295		return 1;
296	solo_dev->v4l2_enc[ch]->reset_gop = 0;
297	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch),
298		       solo_dev->v4l2_enc[ch]->gop);
299	return 0;
300}
301
302static int enc_get_mpeg_dma_t(struct solo6010_dev *solo_dev, dma_addr_t buf,
303			      unsigned int off, unsigned int size)
304{
305	int ret;
306
307	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
308		return -EINVAL;
309
310	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev))
311		return solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf,
312				      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size);
313
314	/* Buffer wrap */
315	ret = solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf,
316			    SOLO_MP4E_EXT_ADDR(solo_dev) + off,
317			    SOLO_MP4E_EXT_SIZE(solo_dev) - off);
318
319	ret |= solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0,
320			      buf + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
321			      SOLO_MP4E_EXT_ADDR(solo_dev),
322			      size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
323
324	return ret;
325}
326
327static int enc_get_mpeg_dma(struct solo6010_dev *solo_dev, void *buf,
328			    unsigned int off, unsigned int size)
329{
330	int ret;
331
332	dma_addr_t dma_addr = pci_map_single(solo_dev->pdev, buf, size,
333					     PCI_DMA_FROMDEVICE);
334	ret = enc_get_mpeg_dma_t(solo_dev, dma_addr, off, size);
335	pci_unmap_single(solo_dev->pdev, dma_addr, size, PCI_DMA_FROMDEVICE);
336
337	return ret;
338}
339
340static int enc_get_jpeg_dma(struct solo6010_dev *solo_dev, dma_addr_t buf,
341			    unsigned int off, unsigned int size)
342{
343	int ret;
344
345	if (off > SOLO_JPEG_EXT_SIZE(solo_dev))
346		return -EINVAL;
347
348	if (off + size <= SOLO_JPEG_EXT_SIZE(solo_dev))
349		return solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_JPEG, 0, buf,
350				      SOLO_JPEG_EXT_ADDR(solo_dev) + off, size);
351
352	/* Buffer wrap */
353	ret = solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_JPEG, 0, buf,
354			     SOLO_JPEG_EXT_ADDR(solo_dev) + off,
355			     SOLO_JPEG_EXT_SIZE(solo_dev) - off);
356
357	ret |= solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_JPEG, 0,
358			      buf + SOLO_JPEG_EXT_SIZE(solo_dev) - off,
359			      SOLO_JPEG_EXT_ADDR(solo_dev),
360			      size + off - SOLO_JPEG_EXT_SIZE(solo_dev));
361
362	return ret;
363}
364
365static int solo_fill_jpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
366			  struct videobuf_buffer *vb, dma_addr_t vbuf)
367{
368	struct solo_enc_dev *solo_enc = fh->enc;
369	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
370	u8 *p = videobuf_queue_to_vaddr(&fh->vidq, vb);
371
372	memcpy(p, jpeg_header, sizeof(jpeg_header));
373	p[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
374	p[SOF0_START + 6] = 0xff & solo_enc->height;
375	p[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
376	p[SOF0_START + 8] = 0xff & solo_enc->width;
377
378	vbuf += sizeof(jpeg_header);
379	vb->size = enc_buf->jpeg_size + sizeof(jpeg_header);
380
381	return enc_get_jpeg_dma(solo_dev, vbuf, enc_buf->jpeg_off,
382				enc_buf->jpeg_size);
383}
384
385static int solo_fill_mpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
386			  struct videobuf_buffer *vb, dma_addr_t vbuf)
387{
388	struct solo_enc_dev *solo_enc = fh->enc;
389	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
390	struct vop_header vh;
391	int ret;
392	int frame_size, frame_off;
393
394	if (WARN_ON_ONCE(enc_buf->size <= sizeof(vh)))
395		return -1;
396
397	/* First get the hardware vop header (not real mpeg) */
398	ret = enc_get_mpeg_dma(solo_dev, &vh, enc_buf->off, sizeof(vh));
399	if (ret)
400		return -1;
401
402	if (WARN_ON_ONCE(vh.size > enc_buf->size))
403		return -1;
404
405	vb->width = vh.hsize << 4;
406	vb->height = vh.vsize << 4;
407	vb->size = vh.size;
408
409	/* If this is a key frame, add extra m4v header */
410	if (!enc_buf->vop) {
411		u16 fps = solo_dev->fps * 1000;
412		u16 interval = solo_enc->interval * 1000;
413		u8 *p = videobuf_queue_to_vaddr(&fh->vidq, vb);
414
415		memcpy(p, vid_vop_header, sizeof(vid_vop_header));
416
417		if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
418			p[10] |= ((XVID_PAR_43_NTSC << 3) & 0x78);
419		else
420			p[10] |= ((XVID_PAR_43_PAL << 3) & 0x78);
421
422		/* Frame rate and interval */
423		p[22] = fps >> 4;
424		p[23] = ((fps << 4) & 0xf0) | 0x0c | ((interval >> 13) & 0x3);
425		p[24] = (interval >> 5) & 0xff;
426		p[25] = ((interval << 3) & 0xf8) | 0x04;
427
428		/* Width and height */
429		p[26] = (vb->width >> 3) & 0xff;
430		p[27] = ((vb->height >> 9) & 0x0f) | 0x10;
431		p[28] = (vb->height >> 1) & 0xff;
432
433		/* Interlace */
434		if (vh.interlace)
435			p[29] |= 0x20;
436
437		/* Adjust the dma buffer past this header */
438		vb->size += sizeof(vid_vop_header);
439		vbuf += sizeof(vid_vop_header);
440	}
441
442	/* Now get the actual mpeg payload */
443	frame_off = (enc_buf->off + sizeof(vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
444	frame_size = enc_buf->size - sizeof(vh);
445	ret = enc_get_mpeg_dma_t(solo_dev, vbuf, frame_off, frame_size);
446	if (WARN_ON_ONCE(ret))
447		return -1;
448
449	return 0;
450}
451
452/* On successful return (0), leaves solo_enc->lock unlocked */
453static int solo_enc_fillbuf(struct solo_enc_fh *fh,
454			    struct videobuf_buffer *vb)
455{
456	struct solo_enc_dev *solo_enc = fh->enc;
457	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
458	struct solo_enc_buf *enc_buf = NULL;
459	dma_addr_t vbuf;
460	int ret;
461	u16 idx = fh->rd_idx;
462
463	while (idx != solo_dev->enc_wr_idx) {
464		struct solo_enc_buf *ebuf = &solo_dev->enc_buf[idx];
465		idx = (idx + 1) % SOLO_NR_RING_BUFS;
466		if (fh->fmt == V4L2_PIX_FMT_MPEG) {
467			if (fh->type != ebuf->type)
468				continue;
469			if (ebuf->ch == solo_enc->ch) {
470				enc_buf = ebuf;
471				break;
472			}
473		} else if (ebuf->ch == solo_enc->ch) {
474			/* For mjpeg, keep reading to the newest frame */
475			enc_buf = ebuf;
476		}
477	}
478
479	fh->rd_idx = idx;
480
481	if (!enc_buf)
482		return -1;
483
484	if ((fh->fmt == V4L2_PIX_FMT_MPEG &&
485	     vb->bsize < enc_buf->size) ||
486	    (fh->fmt == V4L2_PIX_FMT_MJPEG &&
487	     vb->bsize < (enc_buf->jpeg_size + sizeof(jpeg_header)))) {
488		return -1;
489	}
490
491	if (!(vbuf = videobuf_to_dma_contig(vb)))
492		return -1;
493
494	/* Is it ok that we mess with this buffer out of lock? */
495	spin_unlock(&solo_enc->lock);
496
497	if (fh->fmt == V4L2_PIX_FMT_MPEG)
498		ret = solo_fill_mpeg(fh, enc_buf, vb, vbuf);
499	else
500		ret = solo_fill_jpeg(fh, enc_buf, vb, vbuf);
501
502	if (ret) // Ignore failures
503		return 0;
504
505	list_del(&vb->queue);
506	vb->field_count++;
507	vb->ts = enc_buf->ts;
508	vb->state = VIDEOBUF_DONE;
509
510	wake_up(&vb->done);
511
512	return 0;
513}
514
515static void solo_enc_thread_try(struct solo_enc_fh *fh)
516{
517	struct solo_enc_dev *solo_enc = fh->enc;
518	struct videobuf_buffer *vb;
519
520	for (;;) {
521		spin_lock(&solo_enc->lock);
522
523		if (list_empty(&fh->vidq_active))
524			break;
525
526		vb = list_first_entry(&fh->vidq_active,
527				      struct videobuf_buffer, queue);
528
529		if (!waitqueue_active(&vb->done))
530			break;
531
532		/* On success, returns with solo_enc->lock unlocked */
533		if (solo_enc_fillbuf(fh, vb))
534			break;
535	}
536
537	assert_spin_locked(&solo_enc->lock);
538	spin_unlock(&solo_enc->lock);
539}
540
541static int solo_enc_thread(void *data)
542{
543	struct solo_enc_fh *fh = data;
544	struct solo_enc_dev *solo_enc = fh->enc;
545	DECLARE_WAITQUEUE(wait, current);
546
547	set_freezable();
548	add_wait_queue(&solo_enc->thread_wait, &wait);
549
550	for (;;) {
551		long timeout = schedule_timeout_interruptible(HZ);
552		if (timeout == -ERESTARTSYS || kthread_should_stop())
553			break;
554		solo_enc_thread_try(fh);
555		try_to_freeze();
556	}
557
558	remove_wait_queue(&solo_enc->thread_wait, &wait);
559
560        return 0;
561}
562
563void solo_motion_isr(struct solo6010_dev *solo_dev)
564{
565	u32 status;
566	int i;
567
568	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_MOTION);
569
570	status = solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS);
571
572	for (i = 0; i < solo_dev->nr_chans; i++) {
573		struct solo_enc_dev *solo_enc = solo_dev->v4l2_enc[i];
574
575		BUG_ON(solo_enc == NULL);
576
577		if (solo_enc->motion_detected)
578			continue;
579		if (!(status & (1 << i)))
580			continue;
581
582		solo_enc->motion_detected = 1;
583	}
584}
585
586void solo_enc_v4l2_isr(struct solo6010_dev *solo_dev)
587{
588	struct solo_enc_buf *enc_buf;
589	struct videnc_status vstatus;
590	u32 mpeg_current, mpeg_next, mpeg_size;
591	u32 jpeg_current, jpeg_next, jpeg_size;
592	u32 reg_mpeg_size;
593	u8 cur_q, vop_type;
594	u8 ch;
595	enum solo_enc_types enc_type;
596
597	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_ENCODER);
598
599	vstatus.status11 = solo_reg_read(solo_dev, SOLO_VE_STATE(11));
600	cur_q = (vstatus.status11_st.last_queue + 1) % MP4_QS;
601
602	vstatus.status0 = solo_reg_read(solo_dev, SOLO_VE_STATE(0));
603	reg_mpeg_size = (vstatus.status0_st.mp4_enc_code_size + 64 + 32) &
604			(~31);
605
606	while (solo_dev->enc_idx != cur_q) {
607		mpeg_current = solo_reg_read(solo_dev,
608					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
609		jpeg_current = solo_reg_read(solo_dev,
610					SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
611		solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
612		mpeg_next = solo_reg_read(solo_dev,
613					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
614		jpeg_next = solo_reg_read(solo_dev,
615					SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
616
617		if ((ch = (mpeg_current >> 24) & 0x1f) >= SOLO_MAX_CHANNELS) {
618			ch -= SOLO_MAX_CHANNELS;
619			enc_type = SOLO_ENC_TYPE_EXT;
620		} else
621			enc_type = SOLO_ENC_TYPE_STD;
622
623		vop_type = (mpeg_current >> 29) & 3;
624
625		mpeg_current &= 0x00ffffff;
626		mpeg_next    &= 0x00ffffff;
627		jpeg_current &= 0x00ffffff;
628		jpeg_next    &= 0x00ffffff;
629
630		mpeg_size = (SOLO_MP4E_EXT_SIZE(solo_dev) +
631			     mpeg_next - mpeg_current) %
632			    SOLO_MP4E_EXT_SIZE(solo_dev);
633
634		jpeg_size = (SOLO_JPEG_EXT_SIZE(solo_dev) +
635			     jpeg_next - jpeg_current) %
636			    SOLO_JPEG_EXT_SIZE(solo_dev);
637
638		if (mpeg_current > mpeg_next && mpeg_size != reg_mpeg_size) {
639			enc_reset_gop(solo_dev, ch);
640			continue;
641		}
642
643		/* When resetting the GOP, skip frames until I-frame */
644		if (enc_gop_reset(solo_dev, ch, vop_type))
645			continue;
646
647		enc_buf = &solo_dev->enc_buf[solo_dev->enc_wr_idx];
648
649		enc_buf->vop = vop_type;
650		enc_buf->ch = ch;
651		enc_buf->off = mpeg_current;
652		enc_buf->size = mpeg_size;
653		enc_buf->jpeg_off = jpeg_current;
654		enc_buf->jpeg_size = jpeg_size;
655		enc_buf->type = enc_type;
656
657		do_gettimeofday(&enc_buf->ts);
658
659		solo_dev->enc_wr_idx = (solo_dev->enc_wr_idx + 1) %
660					SOLO_NR_RING_BUFS;
661
662		wake_up_interruptible(&solo_dev->v4l2_enc[ch]->thread_wait);
663	}
664
665	return;
666}
667
668static int solo_enc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
669			      unsigned int *size)
670{
671        *size = FRAME_BUF_SIZE;
672
673        if (*count < MIN_VID_BUFFERS)
674		*count = MIN_VID_BUFFERS;
675
676        return 0;
677}
678
679static int solo_enc_buf_prepare(struct videobuf_queue *vq,
680				struct videobuf_buffer *vb,
681				enum v4l2_field field)
682{
683	struct solo_enc_fh *fh = vq->priv_data;
684	struct solo_enc_dev *solo_enc = fh->enc;
685
686	vb->size = FRAME_BUF_SIZE;
687	if (vb->baddr != 0 && vb->bsize < vb->size)
688		return -EINVAL;
689
690	/* These properties only change when queue is idle */
691	vb->width = solo_enc->width;
692	vb->height = solo_enc->height;
693	vb->field  = field;
694
695	if (vb->state == VIDEOBUF_NEEDS_INIT) {
696		int rc = videobuf_iolock(vq, vb, NULL);
697		if (rc < 0) {
698			videobuf_dma_contig_free(vq, vb);
699			vb->state = VIDEOBUF_NEEDS_INIT;
700			return rc;
701		}
702	}
703	vb->state = VIDEOBUF_PREPARED;
704
705	return 0;
706}
707
708static void solo_enc_buf_queue(struct videobuf_queue *vq,
709			       struct videobuf_buffer *vb)
710{
711	struct solo_enc_fh *fh = vq->priv_data;
712
713	vb->state = VIDEOBUF_QUEUED;
714	list_add_tail(&vb->queue, &fh->vidq_active);
715	wake_up_interruptible(&fh->enc->thread_wait);
716}
717
718static void solo_enc_buf_release(struct videobuf_queue *vq,
719				 struct videobuf_buffer *vb)
720{
721	videobuf_dma_contig_free(vq, vb);
722	vb->state = VIDEOBUF_NEEDS_INIT;
723}
724
725static struct videobuf_queue_ops solo_enc_video_qops = {
726	.buf_setup	= solo_enc_buf_setup,
727	.buf_prepare	= solo_enc_buf_prepare,
728	.buf_queue	= solo_enc_buf_queue,
729	.buf_release	= solo_enc_buf_release,
730};
731
732static unsigned int solo_enc_poll(struct file *file,
733				  struct poll_table_struct *wait)
734{
735	struct solo_enc_fh *fh = file->private_data;
736
737	return videobuf_poll_stream(file, &fh->vidq, wait);
738}
739
740static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
741{
742	struct solo_enc_fh *fh = file->private_data;
743
744	return videobuf_mmap_mapper(&fh->vidq, vma);
745}
746
747static int solo_enc_open(struct file *file)
748{
749	struct solo_enc_dev *solo_enc = video_drvdata(file);
750	struct solo_enc_fh *fh;
751
752	if ((fh = kzalloc(sizeof(*fh), GFP_KERNEL)) == NULL)
753		return -ENOMEM;
754
755	spin_lock(&solo_enc->lock);
756
757	fh->enc = solo_enc;
758	file->private_data = fh;
759	INIT_LIST_HEAD(&fh->vidq_active);
760	fh->fmt = V4L2_PIX_FMT_MPEG;
761	fh->type = SOLO_ENC_TYPE_STD;
762
763	videobuf_queue_dma_contig_init(&fh->vidq, &solo_enc_video_qops,
764				    &solo_enc->solo_dev->pdev->dev,
765				    &solo_enc->lock,
766				    V4L2_BUF_TYPE_VIDEO_CAPTURE,
767				    V4L2_FIELD_INTERLACED,
768				    sizeof(struct videobuf_buffer), fh);
769
770	spin_unlock(&solo_enc->lock);
771
772	return 0;
773}
774
775static ssize_t solo_enc_read(struct file *file, char __user *data,
776			     size_t count, loff_t *ppos)
777{
778	struct solo_enc_fh *fh = file->private_data;
779	struct solo_enc_dev *solo_enc = fh->enc;
780
781	/* Make sure the encoder is on */
782	if (!fh->enc_on) {
783		int ret;
784
785		spin_lock(&solo_enc->lock);
786		ret = solo_enc_on(fh);
787	        spin_unlock(&solo_enc->lock);
788		if (ret)
789			return ret;
790	}
791
792	return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
793				    file->f_flags & O_NONBLOCK);
794}
795
796static int solo_enc_release(struct file *file)
797{
798	struct solo_enc_fh *fh = file->private_data;
799
800	videobuf_stop(&fh->vidq);
801	videobuf_mmap_free(&fh->vidq);
802	solo_enc_off(fh);
803	kfree(fh);
804
805	return 0;
806}
807
808static int solo_enc_querycap(struct file *file, void  *priv,
809			     struct v4l2_capability *cap)
810{
811	struct solo_enc_fh *fh = priv;
812	struct solo_enc_dev *solo_enc = fh->enc;
813	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
814
815	strcpy(cap->driver, SOLO6010_NAME);
816	snprintf(cap->card, sizeof(cap->card), "Softlogic 6010 Enc %d",
817		 solo_enc->ch);
818	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
819		 pci_name(solo_dev->pdev));
820	cap->version = SOLO6010_VER_NUM;
821	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
822				V4L2_CAP_READWRITE |
823				V4L2_CAP_STREAMING;
824	return 0;
825}
826
827static int solo_enc_enum_input(struct file *file, void *priv,
828			       struct v4l2_input *input)
829{
830	struct solo_enc_fh *fh = priv;
831	struct solo_enc_dev *solo_enc = fh->enc;
832	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
833
834	if (input->index)
835		return -EINVAL;
836
837	snprintf(input->name, sizeof(input->name), "Encoder %d",
838		 solo_enc->ch + 1);
839	input->type = V4L2_INPUT_TYPE_CAMERA;
840
841	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
842		input->std = V4L2_STD_NTSC_M;
843	else
844		input->std = V4L2_STD_PAL_M;
845
846	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
847		input->status = V4L2_IN_ST_NO_SIGNAL;
848
849	return 0;
850}
851
852static int solo_enc_set_input(struct file *file, void *priv, unsigned int index)
853{
854	if (index)
855		return -EINVAL;
856
857	return 0;
858}
859
860static int solo_enc_get_input(struct file *file, void *priv,
861			      unsigned int *index)
862{
863	*index = 0;
864
865	return 0;
866}
867
868static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
869				 struct v4l2_fmtdesc *f)
870{
871	switch (f->index) {
872	case 0:
873		f->pixelformat = V4L2_PIX_FMT_MPEG;
874		strcpy(f->description, "MPEG-4 AVC");
875		break;
876	case 1:
877		f->pixelformat = V4L2_PIX_FMT_MJPEG;
878		strcpy(f->description, "MJPEG");
879		break;
880	default:
881		return -EINVAL;
882	}
883
884	f->flags = V4L2_FMT_FLAG_COMPRESSED;
885
886	return 0;
887}
888
889static int solo_enc_try_fmt_cap(struct file *file, void *priv,
890			    struct v4l2_format *f)
891{
892	struct solo_enc_fh *fh = priv;
893	struct solo_enc_dev *solo_enc = fh->enc;
894	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
895	struct v4l2_pix_format *pix = &f->fmt.pix;
896
897	if (pix->pixelformat != V4L2_PIX_FMT_MPEG &&
898	    pix->pixelformat != V4L2_PIX_FMT_MJPEG)
899		return -EINVAL;
900
901	/* We cannot change width/height in mid read */
902	if (atomic_read(&solo_enc->readers) > 0) {
903		if (pix->width != solo_enc->width ||
904		    pix->height != solo_enc->height)
905			return -EBUSY;
906	} else if (!(pix->width == solo_dev->video_hsize &&
907	      pix->height == solo_dev->video_vsize << 1) &&
908	    !(pix->width == solo_dev->video_hsize >> 1 &&
909	      pix->height == solo_dev->video_vsize)) {
910		/* Default to CIF 1/2 size */
911		pix->width = solo_dev->video_hsize >> 1;
912		pix->height = solo_dev->video_vsize;
913	}
914
915	if (pix->field == V4L2_FIELD_ANY)
916		pix->field = V4L2_FIELD_INTERLACED;
917	else if (pix->field != V4L2_FIELD_INTERLACED) {
918		pix->field = V4L2_FIELD_INTERLACED;
919	}
920
921	/* Just set these */
922	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
923	pix->sizeimage = FRAME_BUF_SIZE;
924
925	return 0;
926}
927
928static int solo_enc_set_fmt_cap(struct file *file, void *priv,
929				struct v4l2_format *f)
930{
931	struct solo_enc_fh *fh = priv;
932	struct solo_enc_dev *solo_enc = fh->enc;
933	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
934	struct v4l2_pix_format *pix = &f->fmt.pix;
935	int ret;
936
937	spin_lock(&solo_enc->lock);
938
939	if ((ret = solo_enc_try_fmt_cap(file, priv, f))) {
940		spin_unlock(&solo_enc->lock);
941		return ret;
942	}
943
944	if (pix->width == solo_dev->video_hsize)
945		solo_enc->mode = SOLO_ENC_MODE_D1;
946	else
947		solo_enc->mode = SOLO_ENC_MODE_CIF;
948
949	/* This does not change the encoder at all */
950	fh->fmt = pix->pixelformat;
951
952	if (pix->priv)
953		fh->type = SOLO_ENC_TYPE_EXT;
954	ret = solo_enc_on(fh);
955
956	spin_unlock(&solo_enc->lock);
957
958	return ret;
959}
960
961static int solo_enc_get_fmt_cap(struct file *file, void *priv,
962				struct v4l2_format *f)
963{
964	struct solo_enc_fh *fh = priv;
965	struct solo_enc_dev *solo_enc = fh->enc;
966	struct v4l2_pix_format *pix = &f->fmt.pix;
967
968	pix->width = solo_enc->width;
969	pix->height = solo_enc->height;
970	pix->pixelformat = fh->fmt;
971	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
972		     V4L2_FIELD_NONE;
973	pix->sizeimage = FRAME_BUF_SIZE;
974	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
975
976	return 0;
977}
978
979static int solo_enc_reqbufs(struct file *file, void *priv,
980			    struct v4l2_requestbuffers *req)
981{
982	struct solo_enc_fh *fh = priv;
983
984	return videobuf_reqbufs(&fh->vidq, req);
985}
986
987static int solo_enc_querybuf(struct file *file, void *priv,
988			     struct v4l2_buffer *buf)
989{
990	struct solo_enc_fh *fh = priv;
991
992	return videobuf_querybuf(&fh->vidq, buf);
993}
994
995static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
996{
997	struct solo_enc_fh *fh = priv;
998
999	return videobuf_qbuf(&fh->vidq, buf);
1000}
1001
1002static int solo_enc_dqbuf(struct file *file, void *priv,
1003			  struct v4l2_buffer *buf)
1004{
1005	struct solo_enc_fh *fh = priv;
1006	struct solo_enc_dev *solo_enc = fh->enc;
1007	int ret;
1008
1009	/* Make sure the encoder is on */
1010	if (!fh->enc_on) {
1011		spin_lock(&solo_enc->lock);
1012		ret = solo_enc_on(fh);
1013		spin_unlock(&solo_enc->lock);
1014		if (ret)
1015			return ret;
1016	}
1017
1018	ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
1019	if (ret)
1020		return ret;
1021
1022	/* Signal motion detection */
1023	if (solo_is_motion_on(solo_enc)) {
1024		buf->flags |= V4L2_BUF_FLAG_MOTION_ON;
1025		if (solo_enc->motion_detected) {
1026			buf->flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
1027			solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
1028				       1 << solo_enc->ch);
1029			solo_enc->motion_detected = 0;
1030		}
1031	}
1032
1033	/* Check for key frame on mpeg data */
1034	if (fh->fmt == V4L2_PIX_FMT_MPEG) {
1035		struct videobuf_buffer *vb = fh->vidq.bufs[buf->index];
1036		u8 *p = videobuf_queue_to_vaddr(&fh->vidq, vb);
1037		if (p[3] == 0x00)
1038			buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1039		else
1040			buf->flags |= V4L2_BUF_FLAG_PFRAME;
1041	}
1042
1043	return 0;
1044}
1045
1046static int solo_enc_streamon(struct file *file, void *priv,
1047			     enum v4l2_buf_type i)
1048{
1049	struct solo_enc_fh *fh = priv;
1050
1051	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1052		return -EINVAL;
1053
1054	return videobuf_streamon(&fh->vidq);
1055}
1056
1057static int solo_enc_streamoff(struct file *file, void *priv,
1058			      enum v4l2_buf_type i)
1059{
1060	struct solo_enc_fh *fh = priv;
1061
1062	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1063		return -EINVAL;
1064
1065	return videobuf_streamoff(&fh->vidq);
1066}
1067
1068static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
1069{
1070	return 0;
1071}
1072
1073static int solo_enum_framesizes(struct file *file, void *priv,
1074				struct v4l2_frmsizeenum *fsize)
1075{
1076	struct solo_enc_fh *fh = priv;
1077	struct solo6010_dev *solo_dev = fh->enc->solo_dev;
1078
1079	if (fsize->pixel_format != V4L2_PIX_FMT_MPEG)
1080		return -EINVAL;
1081
1082	switch (fsize->index) {
1083	case 0:
1084		fsize->discrete.width = solo_dev->video_hsize >> 1;
1085		fsize->discrete.height = solo_dev->video_vsize;
1086		break;
1087	case 1:
1088		fsize->discrete.width = solo_dev->video_hsize;
1089		fsize->discrete.height = solo_dev->video_vsize << 1;
1090		break;
1091	default:
1092		return -EINVAL;
1093	}
1094
1095	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1096
1097	return 0;
1098}
1099
1100static int solo_enum_frameintervals(struct file *file, void *priv,
1101				    struct v4l2_frmivalenum *fintv)
1102{
1103	struct solo_enc_fh *fh = priv;
1104	struct solo6010_dev *solo_dev = fh->enc->solo_dev;
1105
1106	if (fintv->pixel_format != V4L2_PIX_FMT_MPEG || fintv->index)
1107		return -EINVAL;
1108
1109	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
1110
1111	fintv->stepwise.min.numerator = solo_dev->fps;
1112	fintv->stepwise.min.denominator = 1;
1113
1114	fintv->stepwise.max.numerator = solo_dev->fps;
1115	fintv->stepwise.max.denominator = 15;
1116
1117	fintv->stepwise.step.numerator = 1;
1118	fintv->stepwise.step.denominator = 1;
1119
1120	return 0;
1121}
1122
1123static int solo_g_parm(struct file *file, void *priv,
1124		       struct v4l2_streamparm *sp)
1125{
1126	struct solo_enc_fh *fh = priv;
1127	struct solo_enc_dev *solo_enc = fh->enc;
1128	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
1129	struct v4l2_captureparm *cp = &sp->parm.capture;
1130
1131	cp->capability = V4L2_CAP_TIMEPERFRAME;
1132	cp->timeperframe.numerator = solo_enc->interval;
1133	cp->timeperframe.denominator = solo_dev->fps;
1134	cp->capturemode = 0;
1135	cp->readbuffers = 2;
1136
1137        return 0;
1138}
1139
1140static int solo_s_parm(struct file *file, void *priv,
1141		       struct v4l2_streamparm *sp)
1142{
1143	struct solo_enc_fh *fh = priv;
1144	struct solo_enc_dev *solo_enc = fh->enc;
1145	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
1146	struct v4l2_captureparm *cp = &sp->parm.capture;
1147
1148	spin_lock(&solo_enc->lock);
1149
1150	if (atomic_read(&solo_enc->readers) > 0) {
1151		spin_unlock(&solo_enc->lock);
1152		return -EBUSY;
1153	}
1154
1155	if ((cp->timeperframe.numerator == 0) ||
1156	    (cp->timeperframe.denominator == 0)) {
1157		/* reset framerate */
1158		cp->timeperframe.numerator = 1;
1159		cp->timeperframe.denominator = solo_dev->fps;
1160	}
1161
1162	if (cp->timeperframe.denominator != solo_dev->fps)
1163		cp->timeperframe.denominator = solo_dev->fps;
1164
1165	if (cp->timeperframe.numerator > 15)
1166		cp->timeperframe.numerator = 15;
1167
1168	solo_enc->interval = cp->timeperframe.numerator;
1169
1170	cp->capability = V4L2_CAP_TIMEPERFRAME;
1171
1172	solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
1173	solo_update_mode(solo_enc);
1174
1175	spin_unlock(&solo_enc->lock);
1176
1177        return 0;
1178}
1179
1180static int solo_queryctrl(struct file *file, void *priv,
1181			  struct v4l2_queryctrl *qc)
1182{
1183	struct solo_enc_fh *fh = priv;
1184	struct solo_enc_dev *solo_enc = fh->enc;
1185	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
1186
1187	qc->id = v4l2_ctrl_next(solo_ctrl_classes, qc->id);
1188	if (!qc->id)
1189		return -EINVAL;
1190
1191	switch (qc->id) {
1192	case V4L2_CID_BRIGHTNESS:
1193	case V4L2_CID_CONTRAST:
1194	case V4L2_CID_SATURATION:
1195	case V4L2_CID_HUE:
1196		return v4l2_ctrl_query_fill(qc, 0x00, 0xff, 1, 0x80);
1197	case V4L2_CID_SHARPNESS:
1198		return v4l2_ctrl_query_fill(qc, 0x00, 0x0f, 1, 0x00);
1199	case V4L2_CID_MPEG_VIDEO_ENCODING:
1200		return v4l2_ctrl_query_fill(
1201			qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
1202			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
1203			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
1204	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1205		return v4l2_ctrl_query_fill(qc, 1, 255, 1, solo_dev->fps);
1206#ifdef PRIVATE_CIDS
1207	case V4L2_CID_MOTION_THRESHOLD:
1208		qc->flags |= V4L2_CTRL_FLAG_SLIDER;
1209		qc->type = V4L2_CTRL_TYPE_INTEGER;
1210		qc->minimum = 0;
1211		qc->maximum = 0xffff;
1212		qc->step = 1;
1213		qc->default_value = SOLO_DEF_MOT_THRESH;
1214		strlcpy(qc->name, "Motion Detection Threshold",
1215			sizeof(qc->name));
1216		return 0;
1217	case V4L2_CID_MOTION_ENABLE:
1218		qc->type = V4L2_CTRL_TYPE_BOOLEAN;
1219		qc->minimum = 0;
1220		qc->maximum = qc->step = 1;
1221		qc->default_value = 0;
1222		strlcpy(qc->name, "Motion Detection Enable", sizeof(qc->name));
1223		return 0;
1224#else
1225	case V4L2_CID_MOTION_THRESHOLD:
1226		return v4l2_ctrl_query_fill(qc, 0, 0xffff, 1,
1227					    SOLO_DEF_MOT_THRESH);
1228	case V4L2_CID_MOTION_ENABLE:
1229		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
1230#endif
1231	case V4L2_CID_RDS_TX_RADIO_TEXT:
1232		qc->type = V4L2_CTRL_TYPE_STRING;
1233		qc->minimum = 0;
1234		qc->maximum = OSD_TEXT_MAX;
1235		qc->step = 1;
1236		qc->default_value = 0;
1237		strlcpy(qc->name, "OSD Text", sizeof(qc->name));
1238		return 0;
1239	}
1240
1241        return -EINVAL;
1242}
1243
1244static int solo_querymenu(struct file *file, void *priv,
1245			  struct v4l2_querymenu *qmenu)
1246{
1247	struct v4l2_queryctrl qctrl;
1248	int err;
1249
1250	qctrl.id = qmenu->id;
1251	if ((err = solo_queryctrl(file, priv, &qctrl)))
1252		return err;
1253
1254	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
1255}
1256
1257static int solo_g_ctrl(struct file *file, void *priv,
1258		       struct v4l2_control *ctrl)
1259{
1260	struct solo_enc_fh *fh = priv;
1261	struct solo_enc_dev *solo_enc = fh->enc;
1262	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
1263
1264	switch (ctrl->id) {
1265	case V4L2_CID_BRIGHTNESS:
1266	case V4L2_CID_CONTRAST:
1267	case V4L2_CID_SATURATION:
1268	case V4L2_CID_HUE:
1269	case V4L2_CID_SHARPNESS:
1270		return tw28_get_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
1271					 &ctrl->value);
1272	case V4L2_CID_MPEG_VIDEO_ENCODING:
1273		ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
1274		break;
1275	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1276		ctrl->value = solo_enc->gop;
1277		break;
1278	case V4L2_CID_MOTION_THRESHOLD:
1279		ctrl->value = solo_enc->motion_thresh;
1280		break;
1281	case V4L2_CID_MOTION_ENABLE:
1282		ctrl->value = solo_is_motion_on(solo_enc);
1283		break;
1284	default:
1285		return -EINVAL;
1286	}
1287
1288	return 0;
1289}
1290
1291static int solo_s_ctrl(struct file *file, void *priv,
1292		       struct v4l2_control *ctrl)
1293{
1294	struct solo_enc_fh *fh = priv;
1295	struct solo_enc_dev *solo_enc = fh->enc;
1296	struct solo6010_dev *solo_dev = solo_enc->solo_dev;
1297
1298	switch (ctrl->id) {
1299	case V4L2_CID_BRIGHTNESS:
1300	case V4L2_CID_CONTRAST:
1301	case V4L2_CID_SATURATION:
1302	case V4L2_CID_HUE:
1303	case V4L2_CID_SHARPNESS:
1304		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
1305					 ctrl->value);
1306	case V4L2_CID_MPEG_VIDEO_ENCODING:
1307		if (ctrl->value != V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
1308			return -ERANGE;
1309		break;
1310	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1311		if (ctrl->value < 1 || ctrl->value > 255)
1312			return -ERANGE;
1313		solo_enc->gop = ctrl->value;
1314		solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch),
1315			       solo_enc->gop);
1316		solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch),
1317			       solo_enc->gop);
1318		break;
1319	case V4L2_CID_MOTION_THRESHOLD:
1320		/* TODO accept value on lower 16-bits and use high
1321		 * 16-bits to assign the value to a specific block */
1322		if (ctrl->value < 0 || ctrl->value > 0xffff)
1323			return -ERANGE;
1324		solo_enc->motion_thresh = ctrl->value;
1325		solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->value);
1326		break;
1327	case V4L2_CID_MOTION_ENABLE:
1328		solo_motion_toggle(solo_enc, ctrl->value);
1329		break;
1330	default:
1331		return -EINVAL;
1332	}
1333
1334	return 0;
1335}
1336
1337static int solo_s_ext_ctrls(struct file *file, void *priv,
1338			    struct v4l2_ext_controls *ctrls)
1339{
1340	struct solo_enc_fh *fh = priv;
1341	struct solo_enc_dev *solo_enc = fh->enc;
1342	int i;
1343
1344	for (i = 0; i < ctrls->count; i++) {
1345		struct v4l2_ext_control *ctrl = (ctrls->controls + i);
1346		int err;
1347
1348		switch (ctrl->id) {
1349		case V4L2_CID_RDS_TX_RADIO_TEXT:
1350			if (ctrl->size - 1 > OSD_TEXT_MAX)
1351                                err = -ERANGE;
1352			else {
1353                        	err = copy_from_user(solo_enc->osd_text,
1354						     ctrl->string,
1355						     OSD_TEXT_MAX);
1356				solo_enc->osd_text[OSD_TEXT_MAX] = '\0';
1357				if (!err)
1358					err = solo_osd_print(solo_enc);
1359			}
1360			break;
1361		default:
1362			err = -EINVAL;
1363		}
1364
1365		if (err < 0) {
1366			ctrls->error_idx = i;
1367			return err;
1368		}
1369	}
1370
1371	return 0;
1372}
1373
1374static int solo_g_ext_ctrls(struct file *file, void *priv,
1375			    struct v4l2_ext_controls *ctrls)
1376{
1377	struct solo_enc_fh *fh = priv;
1378	struct solo_enc_dev *solo_enc = fh->enc;
1379	int i;
1380
1381	for (i = 0; i < ctrls->count; i++) {
1382		struct v4l2_ext_control *ctrl = (ctrls->controls + i);
1383		int err;
1384
1385		switch (ctrl->id) {
1386		case V4L2_CID_RDS_TX_RADIO_TEXT:
1387			if (ctrl->size < OSD_TEXT_MAX) {
1388				ctrl->size = OSD_TEXT_MAX;
1389				err = -ENOSPC;
1390			} else {
1391				err = copy_to_user(ctrl->string,
1392						   solo_enc->osd_text,
1393						   OSD_TEXT_MAX);
1394			}
1395			break;
1396		default:
1397			err = -EINVAL;
1398		}
1399
1400		if (err < 0) {
1401			ctrls->error_idx = i;
1402			return err;
1403		}
1404	}
1405
1406	return 0;
1407}
1408
1409static const struct v4l2_file_operations solo_enc_fops = {
1410	.owner			= THIS_MODULE,
1411	.open			= solo_enc_open,
1412	.release		= solo_enc_release,
1413	.read			= solo_enc_read,
1414	.poll			= solo_enc_poll,
1415	.mmap			= solo_enc_mmap,
1416	.ioctl			= video_ioctl2,
1417};
1418
1419static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1420	.vidioc_querycap		= solo_enc_querycap,
1421	.vidioc_s_std			= solo_enc_s_std,
1422	/* Input callbacks */
1423	.vidioc_enum_input		= solo_enc_enum_input,
1424	.vidioc_s_input			= solo_enc_set_input,
1425	.vidioc_g_input			= solo_enc_get_input,
1426	/* Video capture format callbacks */
1427	.vidioc_enum_fmt_vid_cap	= solo_enc_enum_fmt_cap,
1428	.vidioc_try_fmt_vid_cap		= solo_enc_try_fmt_cap,
1429	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
1430	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
1431	/* Streaming I/O */
1432	.vidioc_reqbufs			= solo_enc_reqbufs,
1433	.vidioc_querybuf		= solo_enc_querybuf,
1434	.vidioc_qbuf			= solo_enc_qbuf,
1435	.vidioc_dqbuf			= solo_enc_dqbuf,
1436	.vidioc_streamon		= solo_enc_streamon,
1437	.vidioc_streamoff		= solo_enc_streamoff,
1438	/* Frame size and interval */
1439	.vidioc_enum_framesizes		= solo_enum_framesizes,
1440	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
1441	/* Video capture parameters */
1442	.vidioc_s_parm			= solo_s_parm,
1443	.vidioc_g_parm			= solo_g_parm,
1444	/* Controls */
1445	.vidioc_queryctrl		= solo_queryctrl,
1446	.vidioc_querymenu		= solo_querymenu,
1447	.vidioc_g_ctrl			= solo_g_ctrl,
1448	.vidioc_s_ctrl			= solo_s_ctrl,
1449	.vidioc_g_ext_ctrls		= solo_g_ext_ctrls,
1450	.vidioc_s_ext_ctrls		= solo_s_ext_ctrls,
1451};
1452
1453static struct video_device solo_enc_template = {
1454	.name			= SOLO6010_NAME,
1455	.fops			= &solo_enc_fops,
1456	.ioctl_ops		= &solo_enc_ioctl_ops,
1457	.minor			= -1,
1458	.release		= video_device_release,
1459
1460	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL_M,
1461	.current_norm		= V4L2_STD_NTSC_M,
1462};
1463
1464static struct solo_enc_dev *solo_enc_alloc(struct solo6010_dev *solo_dev, u8 ch)
1465{
1466	struct solo_enc_dev *solo_enc;
1467	int ret;
1468
1469	solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
1470	if (!solo_enc)
1471		return ERR_PTR(-ENOMEM);
1472
1473	solo_enc->vfd = video_device_alloc();
1474	if (!solo_enc->vfd) {
1475		kfree(solo_enc);
1476		return ERR_PTR(-ENOMEM);
1477	}
1478
1479	solo_enc->solo_dev = solo_dev;
1480	solo_enc->ch = ch;
1481
1482	*solo_enc->vfd = solo_enc_template;
1483	solo_enc->vfd->parent = &solo_dev->pdev->dev;
1484	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
1485				    video_nr);
1486	if (ret < 0) {
1487		video_device_release(solo_enc->vfd);
1488		kfree(solo_enc);
1489		return ERR_PTR(ret);
1490	}
1491
1492	video_set_drvdata(solo_enc->vfd, solo_enc);
1493
1494	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
1495		 "%s-enc (%i/%i)", SOLO6010_NAME, solo_dev->vfd->num,
1496		 solo_enc->vfd->num);
1497
1498	if (video_nr >= 0)
1499		video_nr++;
1500
1501	spin_lock_init(&solo_enc->lock);
1502	init_waitqueue_head(&solo_enc->thread_wait);
1503	atomic_set(&solo_enc->readers, 0);
1504
1505	solo_enc->qp = SOLO_DEFAULT_QP;
1506        solo_enc->gop = solo_dev->fps;
1507	solo_enc->interval = 1;
1508	solo_enc->mode = SOLO_ENC_MODE_CIF;
1509	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
1510
1511	spin_lock(&solo_enc->lock);
1512	solo_update_mode(solo_enc);
1513	spin_unlock(&solo_enc->lock);
1514
1515	return solo_enc;
1516}
1517
1518static void solo_enc_free(struct solo_enc_dev *solo_enc)
1519{
1520	if (solo_enc == NULL)
1521		return;
1522
1523	video_unregister_device(solo_enc->vfd);
1524	kfree(solo_enc);
1525}
1526
1527int solo_enc_v4l2_init(struct solo6010_dev *solo_dev)
1528{
1529	int i;
1530
1531	for (i = 0; i < solo_dev->nr_chans; i++) {
1532		solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i);
1533		if (IS_ERR(solo_dev->v4l2_enc[i]))
1534			break;
1535	}
1536
1537	if (i != solo_dev->nr_chans) {
1538		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1539		while (i--)
1540			solo_enc_free(solo_dev->v4l2_enc[i]);
1541		return ret;
1542	}
1543
1544	/* D1@MAX-FPS * 4 */
1545	solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
1546
1547	dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
1548		 solo_dev->v4l2_enc[0]->vfd->num,
1549		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
1550
1551	return 0;
1552}
1553
1554void solo_enc_v4l2_exit(struct solo6010_dev *solo_dev)
1555{
1556	int i;
1557
1558	solo6010_irq_off(solo_dev, SOLO_IRQ_MOTION);
1559
1560	for (i = 0; i < solo_dev->nr_chans; i++)
1561		solo_enc_free(solo_dev->v4l2_enc[i]);
1562}
1563