solo6x10-v4l2-enc.c 38.6 KB
Newer Older
1
/*
2 3 4 5 6 7 8
 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
 *
 * Original author:
 * Ben Collins <bcollins@ubuntu.com>
 *
 * Additional work by:
 * John Brooks <john.brooks@bluecherry.net>
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
25

26 27
#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
28
#include <media/v4l2-event.h>
29
#include <media/videobuf2-dma-sg.h>
30

31
#include "solo6x10.h"
H
Hans Verkuil 已提交
32
#include "solo6x10-tw28.h"
33
#include "solo6x10-jpeg.h"
34

35 36
#define MIN_VID_BUFFERS		2
#define FRAME_BUF_SIZE		(196 * 1024)
37
#define MP4_QS			16
38
#define DMA_ALIGN		4096
39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
/* 6010 M4V */
static unsigned char vop_6010_ntsc_d1[] = {
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
	0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
};

static unsigned char vop_6010_ntsc_cif[] = {
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
	0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
};

static unsigned char vop_6010_pal_d1[] = {
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
	0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
};

static unsigned char vop_6010_pal_cif[] = {
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
	0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
};

/* 6110 h.264 */
static unsigned char vop_6110_ntsc_d1[] = {
	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
	0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
};

static unsigned char vop_6110_ntsc_cif[] = {
	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
	0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
};

static unsigned char vop_6110_pal_d1[] = {
	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
	0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
};

static unsigned char vop_6110_pal_cif[] = {
	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
	0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
92 93
};

94
typedef __le32 vop_header[16];
95 96 97

struct solo_enc_buf {
	enum solo_enc_types	type;
98
	const vop_header	*vh;
99 100 101
	int			motion;
};

102 103
static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
{
104
	struct solo_dev *solo_dev = solo_enc->solo_dev;
105

106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	return (solo_dev->motion_mask >> solo_enc->ch) & 1;
}

static int solo_motion_detected(struct solo_enc_dev *solo_enc)
{
	struct solo_dev *solo_dev = solo_enc->solo_dev;
	unsigned long flags;
	u32 ch_mask = 1 << solo_enc->ch;
	int ret = 0;

	spin_lock_irqsave(&solo_enc->motion_lock, flags);
	if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
		solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
		ret = 1;
	}
	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);

	return ret;
124 125 126 127
}

static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
{
128
	struct solo_dev *solo_dev = solo_enc->solo_dev;
129 130
	u32 mask = 1 << solo_enc->ch;
	unsigned long flags;
131

132
	spin_lock_irqsave(&solo_enc->motion_lock, flags);
133 134

	if (on)
135
		solo_dev->motion_mask |= mask;
136
	else
137
		solo_dev->motion_mask &= ~mask;
138

139
	solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
140

141 142 143 144
	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
		       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));

145
	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
146 147
}

148
void solo_update_mode(struct solo_enc_dev *solo_enc)
149
{
150
	struct solo_dev *solo_dev = solo_enc->solo_dev;
151 152
	int vop_len;
	unsigned char *vop;
153 154 155 156

	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);

157
	if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
158 159
		solo_enc->width = solo_dev->video_hsize >> 1;
		solo_enc->height = solo_dev->video_vsize;
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
		if (solo_dev->type == SOLO_DEV_6110) {
			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
				vop = vop_6110_ntsc_cif;
				vop_len = sizeof(vop_6110_ntsc_cif);
			} else {
				vop = vop_6110_pal_cif;
				vop_len = sizeof(vop_6110_pal_cif);
			}
		} else {
			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
				vop = vop_6010_ntsc_cif;
				vop_len = sizeof(vop_6010_ntsc_cif);
			} else {
				vop = vop_6010_pal_cif;
				vop_len = sizeof(vop_6010_pal_cif);
			}
		}
	} else {
178 179 180
		solo_enc->width = solo_dev->video_hsize;
		solo_enc->height = solo_dev->video_vsize << 1;
		solo_enc->bw_weight <<= 2;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
		if (solo_dev->type == SOLO_DEV_6110) {
			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
				vop = vop_6110_ntsc_d1;
				vop_len = sizeof(vop_6110_ntsc_d1);
			} else {
				vop = vop_6110_pal_d1;
				vop_len = sizeof(vop_6110_pal_d1);
			}
		} else {
			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
				vop = vop_6010_ntsc_d1;
				vop_len = sizeof(vop_6010_ntsc_d1);
			} else {
				vop = vop_6010_pal_d1;
				vop_len = sizeof(vop_6010_pal_d1);
			}
		}
198
	}
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

	memcpy(solo_enc->vop, vop, vop_len);

	/* Some fixups for 6010/M4V */
	if (solo_dev->type == SOLO_DEV_6010) {
		u16 fps = solo_dev->fps * 1000;
		u16 interval = solo_enc->interval * 1000;

		vop = solo_enc->vop;

		/* Frame rate and interval */
		vop[22] = fps >> 4;
		vop[23] = ((fps << 4) & 0xf0) | 0x0c
			| ((interval >> 13) & 0x3);
		vop[24] = (interval >> 5) & 0xff;
		vop[25] = ((interval << 3) & 0xf8) | 0x04;
	}

	solo_enc->vop_len = vop_len;

	/* Now handle the jpeg header */
	vop = solo_enc->jpeg_header;
	vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
	vop[SOF0_START + 6] = 0xff & solo_enc->height;
	vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
	vop[SOF0_START + 8] = 0xff & solo_enc->width;

	memcpy(vop + DQT_START,
	       jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
228 229
}

230
static int solo_enc_on(struct solo_enc_dev *solo_enc)
231 232
{
	u8 ch = solo_enc->ch;
233
	struct solo_dev *solo_dev = solo_enc->solo_dev;
234 235 236 237
	u8 interval;

	solo_update_mode(solo_enc);

238 239 240
	/* Make sure to do a bandwidth check */
	if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
		return -EBUSY;
241
	solo_enc->sequence = 0;
242 243
	solo_enc->motion_last_state = false;
	solo_enc->frames_since_last_motion = 0;
244
	solo_dev->enc_bw_remain -= solo_enc->bw_weight;
245

246
	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);

	/* Disable all encoding for this channel */
	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);

	/* Common for both std and ext encoding */
	solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
		       solo_enc->interlaced ? 1 : 0);

	if (solo_enc->interlaced)
		interval = solo_enc->interval - 1;
	else
		interval = solo_enc->interval;

	/* Standard encoding only */
	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
	solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);

	/* Extended encoding only */
	solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
	solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);

	/* Enables the standard encoder */
	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);

	return 0;
}

277
static void solo_enc_off(struct solo_enc_dev *solo_enc)
278
{
279
	struct solo_dev *solo_dev = solo_enc->solo_dev;
280

281
	solo_dev->enc_bw_remain += solo_enc->bw_weight;
282

283 284
	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
285 286
}

287 288
static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
			      unsigned int off, unsigned int size)
289 290 291 292 293 294
{
	int ret;

	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
		return -EINVAL;

295
	/* Single shot */
296
	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
297 298 299
		return solo_p2m_dma_t(solo_dev, 0, dma,
				      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
				      0, 0);
300
	}
301 302

	/* Buffer wrap */
303
	ret = solo_p2m_dma_t(solo_dev, 0, dma,
304
			     SOLO_MP4E_EXT_ADDR(solo_dev) + off,
305
			     SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
306

307 308 309 310 311 312
	if (!ret) {
		ret = solo_p2m_dma_t(solo_dev, 0,
			     dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
			     SOLO_MP4E_EXT_ADDR(solo_dev),
			     size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
	}
313 314 315 316

	return ret;
}

317 318
/* Build a descriptor queue out of an SG list and send it to the P2M for
 * processing. */
319
static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
320
			  struct sg_table *vbuf, int off, int size,
321
			  unsigned int base, unsigned int base_size)
322
{
323
	struct solo_dev *solo_dev = solo_enc->solo_dev;
324 325
	struct scatterlist *sg;
	int i;
326 327
	int ret;

328
	if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
329 330
		return -EINVAL;

331
	solo_enc->desc_count = 1;
332

333
	for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
334 335 336 337 338
		struct solo_p2m_desc *desc;
		dma_addr_t dma;
		int len;
		int left = base_size - off;

339
		desc = &solo_enc->desc_items[solo_enc->desc_count++];
340 341 342 343 344 345 346 347 348 349 350
		dma = sg_dma_address(sg);
		len = sg_dma_len(sg);

		/* We assume this is smaller than the scatter size */
		BUG_ON(skip >= len);
		if (skip) {
			len -= skip;
			dma += skip;
			size -= skip;
			skip = 0;
		}
351

352
		len = min(len, size);
353

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
		if (len <= left) {
			/* Single descriptor */
			solo_p2m_fill_desc(desc, 0, dma, base + off,
					   len, 0, 0);
		} else {
			/* Buffer wrap */
			/* XXX: Do these as separate DMA requests, to avoid
			   timeout errors triggered by awkwardly sized
			   descriptors. See
			   <https://github.com/bluecherrydvr/solo6x10/issues/8>
			 */
			ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
					     left, 0, 0);
			if (ret)
				return ret;

			ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
					     len - left, 0, 0);
			if (ret)
				return ret;

375
			solo_enc->desc_count--;
376
		}
377

378 379 380
		size -= len;
		if (size <= 0)
			break;
381

382 383 384 385 386
		off += len;
		if (off >= base_size)
			off -= base_size;

		/* Because we may use two descriptors per loop */
387 388 389 390
		if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
			ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
						solo_enc->desc_dma,
						solo_enc->desc_count - 1);
391 392
			if (ret)
				return ret;
393
			solo_enc->desc_count = 1;
394
		}
395
	}
396

397
	if (solo_enc->desc_count <= 1)
398
		return 0;
399

400 401
	return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
			solo_enc->desc_dma, solo_enc->desc_count - 1);
402 403
}

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
/* Extract values from VOP header - VE_STATUSxx */
static inline int vop_interlaced(const vop_header *vh)
{
	return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
}

static inline u8 vop_channel(const vop_header *vh)
{
	return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
}

static inline u8 vop_type(const vop_header *vh)
{
	return (__le32_to_cpu((*vh)[0]) >> 22) & 3;
}

static inline u32 vop_mpeg_size(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
}

static inline u8 vop_hsize(const vop_header *vh)
{
	return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
}

static inline u8 vop_vsize(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[1]) & 0xFF;
}

static inline u32 vop_mpeg_offset(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[2]);
}

static inline u32 vop_jpeg_offset(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[3]);
}

static inline u32 vop_jpeg_size(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
}

static inline u32 vop_sec(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[5]);
}

static inline u32 vop_usec(const vop_header *vh)
{
	return __le32_to_cpu((*vh)[6]);
}

460
static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
461
			  struct vb2_buffer *vb, const vop_header *vh)
462
{
463
	struct solo_dev *solo_dev = solo_enc->solo_dev;
464
	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
465
	int frame_size;
466
	int ret;
467

468
	vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
469

470
	if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
471
		return -EIO;
472

473
	frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
474
	vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
475

476
	/* may discard all previous data in vbuf->sgl */
477 478 479
	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
			DMA_FROM_DEVICE))
		return -ENOMEM;
480 481 482 483
	ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
			     vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
			     frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
			     SOLO_JPEG_EXT_SIZE(solo_dev));
484
	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
485
			DMA_FROM_DEVICE);
486 487 488 489 490

	/* add the header only after dma_unmap_sg() */
	sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
			    solo_enc->jpeg_header, solo_enc->jpeg_len);

491
	return ret;
492 493
}

494
static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
495
		struct vb2_buffer *vb, const vop_header *vh)
496
{
497
	struct solo_dev *solo_dev = solo_enc->solo_dev;
498
	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
499
	int frame_off, frame_size;
500
	int skip = 0;
501
	int ret;
502

503
	if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
504
		return -EIO;
505

506
	/* If this is a key frame, add extra header */
507 508
	vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
		V4L2_BUF_FLAG_BFRAME);
509
	if (!vop_type(vh)) {
510
		skip = solo_enc->vop_len;
511
		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
512 513
		vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
			solo_enc->vop_len);
514
	} else {
515
		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
516
		vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
517 518 519
	}

	/* Now get the actual mpeg payload */
520 521
	frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) +
		sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
522
	frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
523

524
	/* may discard all previous data in vbuf->sgl */
525 526 527
	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
			DMA_FROM_DEVICE))
		return -ENOMEM;
528 529 530
	ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
			SOLO_MP4E_EXT_ADDR(solo_dev),
			SOLO_MP4E_EXT_SIZE(solo_dev));
531
	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
532
			DMA_FROM_DEVICE);
533 534 535 536 537

	/* add the header only after dma_unmap_sg() */
	if (!vop_type(vh))
		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
				    solo_enc->vop, solo_enc->vop_len);
538
	return ret;
539 540
}

541
static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
542
			    struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
543
{
544
	const vop_header *vh = enc_buf->vh;
545
	int ret;
546

547 548 549
	switch (solo_enc->fmt) {
	case V4L2_PIX_FMT_MPEG4:
	case V4L2_PIX_FMT_H264:
550
		ret = solo_fill_mpeg(solo_enc, vb, vh);
551 552
		break;
	default: /* V4L2_PIX_FMT_MJPEG */
553
		ret = solo_fill_jpeg(solo_enc, vb, vh);
554 555
		break;
	}
556

557
	if (!ret) {
558 559
		bool send_event = false;

560
		vb->v4l2_buf.sequence = solo_enc->sequence++;
561 562
		vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
		vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600

		/* Check for motion flags */
		if (solo_is_motion_on(solo_enc)) {
			/* It takes a few frames for the hardware to detect
			 * motion. Once it does it clears the motion detection
			 * register and it takes again a few frames before
			 * motion is seen. This means in practice that when the
			 * motion field is 1, it will go back to 0 for the next
			 * frame. This leads to motion detection event being
			 * sent all the time, which is not what we want.
			 * Instead wait a few frames before deciding that the
			 * motion has halted. After some experimentation it
			 * turns out that waiting for 5 frames works well.
			 */
			if (enc_buf->motion == 0 &&
			    solo_enc->motion_last_state &&
			    solo_enc->frames_since_last_motion++ > 5)
				send_event = true;
			else if (enc_buf->motion) {
				solo_enc->frames_since_last_motion = 0;
				send_event = !solo_enc->motion_last_state;
			}
		}

		if (send_event) {
			struct v4l2_event ev = {
				.type = V4L2_EVENT_MOTION_DET,
				.u.motion_det = {
					.flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
					.frame_sequence = vb->v4l2_buf.sequence,
					.region_mask = enc_buf->motion ? 1 : 0,
				},
			};

			solo_enc->motion_last_state = enc_buf->motion;
			solo_enc->frames_since_last_motion = 0;
			v4l2_event_queue(solo_enc->vfd, &ev);
		}
601
	}
602

603 604
	vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);

605
	return ret;
606 607
}

608 609
static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
				struct solo_enc_buf *enc_buf)
610
{
611
	struct solo_vb2_buf *vb;
612
	unsigned long flags;
613

614
	mutex_lock(&solo_enc->lock);
615 616
	if (solo_enc->type != enc_buf->type)
		goto unlock;
617

618
	spin_lock_irqsave(&solo_enc->av_lock, flags);
619 620 621 622
	if (list_empty(&solo_enc->vidq_active)) {
		spin_unlock_irqrestore(&solo_enc->av_lock, flags);
		goto unlock;
	}
623 624
	vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf,
		list);
625
	list_del(&vb->list);
626
	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
627

628
	solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf);
629
unlock:
630
	mutex_unlock(&solo_enc->lock);
631 632
}

633
void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
634
{
635
	wake_up_interruptible_all(&solo_dev->ring_thread_wait);
636 637
}

638
static void solo_handle_ring(struct solo_dev *solo_dev)
639
{
640 641 642 643 644 645 646 647 648 649 650
	for (;;) {
		struct solo_enc_dev *solo_enc;
		struct solo_enc_buf enc_buf;
		u32 mpeg_current, off;
		u8 ch;
		u8 cur_q;

		/* Check if the hardware has any new ones in the queue */
		cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
		if (cur_q == solo_dev->enc_idx)
			break;
651 652 653 654 655

		mpeg_current = solo_reg_read(solo_dev,
					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
		solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;

656
		ch = (mpeg_current >> 24) & 0x1f;
657 658
		off = mpeg_current & 0x00ffffff;

659
		if (ch >= SOLO_MAX_CHANNELS) {
660
			ch -= SOLO_MAX_CHANNELS;
661
			enc_buf.type = SOLO_ENC_TYPE_EXT;
662
		} else
663
			enc_buf.type = SOLO_ENC_TYPE_STD;
664

665 666 667 668
		solo_enc = solo_dev->v4l2_enc[ch];
		if (solo_enc == NULL) {
			dev_err(&solo_dev->pdev->dev,
				"Got spurious packet for channel %d\n", ch);
669 670 671
			continue;
		}

672 673
		/* FAIL... */
		if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
674
				     sizeof(vop_header)))
675 676
			continue;

677
		enc_buf.vh = solo_dev->vh_buf;
678

679
		/* Sanity check */
680 681
		if (vop_mpeg_offset(enc_buf.vh) !=
			SOLO_MP4E_EXT_ADDR(solo_dev) + off)
682 683 684 685 686 687 688 689 690 691
			continue;

		if (solo_motion_detected(solo_enc))
			enc_buf.motion = 1;
		else
			enc_buf.motion = 0;

		solo_enc_handle_one(solo_enc, &enc_buf);
	}
}
692

693 694 695 696
static int solo_ring_thread(void *data)
{
	struct solo_dev *solo_dev = data;
	DECLARE_WAITQUEUE(wait, current);
697

698 699
	set_freezable();
	add_wait_queue(&solo_dev->ring_thread_wait, &wait);
700

701 702
	for (;;) {
		long timeout = schedule_timeout_interruptible(HZ);
703

704 705 706 707 708 709
		if (timeout == -ERESTARTSYS || kthread_should_stop())
			break;
		solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
		solo_handle_ring(solo_dev);
		solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
		try_to_freeze();
710 711
	}

712 713 714
	remove_wait_queue(&solo_dev->ring_thread_wait, &wait);

	return 0;
715 716
}

717 718 719 720 721
static int solo_enc_queue_setup(struct vb2_queue *q,
				const struct v4l2_format *fmt,
				unsigned int *num_buffers,
				unsigned int *num_planes, unsigned int sizes[],
				void *alloc_ctxs[])
722
{
723 724
	sizes[0] = FRAME_BUF_SIZE;
	*num_planes = 1;
725

726 727
	if (*num_buffers < MIN_VID_BUFFERS)
		*num_buffers = MIN_VID_BUFFERS;
728 729 730 731

	return 0;
}

732
static void solo_enc_buf_queue(struct vb2_buffer *vb)
733
{
734 735 736 737
	struct vb2_queue *vq = vb->vb2_queue;
	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
	struct solo_vb2_buf *solo_vb =
		container_of(vb, struct solo_vb2_buf, vb);
738

739 740 741
	spin_lock(&solo_enc->av_lock);
	list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
	spin_unlock(&solo_enc->av_lock);
742 743
}

744 745 746 747 748 749
static int solo_ring_start(struct solo_dev *solo_dev)
{
	solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
					    SOLO6X10_NAME "_ring");
	if (IS_ERR(solo_dev->ring_thread)) {
		int err = PTR_ERR(solo_dev->ring_thread);
750

751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
		solo_dev->ring_thread = NULL;
		return err;
	}

	solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);

	return 0;
}

static void solo_ring_stop(struct solo_dev *solo_dev)
{
	if (solo_dev->ring_thread) {
		kthread_stop(solo_dev->ring_thread);
		solo_dev->ring_thread = NULL;
	}

	solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
}

770
static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
771
{
772
	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
773
	int ret;
774

775
	ret = solo_enc_on(solo_enc);
776 777
	if (ret)
		return ret;
778
	return solo_ring_start(solo_enc->solo_dev);
779 780
}

781
static void solo_enc_stop_streaming(struct vb2_queue *q)
782
{
783
	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
784
	unsigned long flags;
785

786
	spin_lock_irqsave(&solo_enc->av_lock, flags);
787
	solo_enc_off(solo_enc);
788 789 790 791 792 793 794 795 796
	while (!list_empty(&solo_enc->vidq_active)) {
		struct solo_vb2_buf *buf = list_entry(
				solo_enc->vidq_active.next,
				struct solo_vb2_buf, list);

		list_del(&buf->list);
		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
	}
	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
797
	solo_ring_stop(solo_enc->solo_dev);
798 799
}

800 801 802 803 804 805 806 807 808
static struct vb2_ops solo_enc_video_qops = {
	.queue_setup	= solo_enc_queue_setup,
	.buf_queue	= solo_enc_buf_queue,
	.start_streaming = solo_enc_start_streaming,
	.stop_streaming = solo_enc_stop_streaming,
	.wait_prepare	= vb2_ops_wait_prepare,
	.wait_finish	= vb2_ops_wait_finish,
};

809 810 811
static int solo_enc_querycap(struct file *file, void  *priv,
			     struct v4l2_capability *cap)
{
812
	struct solo_enc_dev *solo_enc = video_drvdata(file);
813
	struct solo_dev *solo_dev = solo_enc->solo_dev;
814

815 816
	strcpy(cap->driver, SOLO6X10_NAME);
	snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
817
		 solo_enc->ch);
818
	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
819
		 pci_name(solo_dev->pdev));
820 821 822
	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
823 824 825 826 827 828
	return 0;
}

static int solo_enc_enum_input(struct file *file, void *priv,
			       struct v4l2_input *input)
{
829
	struct solo_enc_dev *solo_enc = video_drvdata(file);
830
	struct solo_dev *solo_dev = solo_enc->solo_dev;
831 832 833 834 835 836 837

	if (input->index)
		return -EINVAL;

	snprintf(input->name, sizeof(input->name), "Encoder %d",
		 solo_enc->ch + 1);
	input->type = V4L2_INPUT_TYPE_CAMERA;
838
	input->std = solo_enc->vfd->tvnorms;
839 840 841 842 843 844 845

	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
		input->status = V4L2_IN_ST_NO_SIGNAL;

	return 0;
}

846 847
static int solo_enc_set_input(struct file *file, void *priv,
			      unsigned int index)
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
{
	if (index)
		return -EINVAL;

	return 0;
}

static int solo_enc_get_input(struct file *file, void *priv,
			      unsigned int *index)
{
	*index = 0;

	return 0;
}

static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
				 struct v4l2_fmtdesc *f)
{
866 867 868
	struct solo_enc_dev *solo_enc = video_drvdata(file);
	int dev_type = solo_enc->solo_dev->type;

869 870
	switch (f->index) {
	case 0:
871 872 873 874 875 876 877 878 879 880
		switch (dev_type) {
		case SOLO_DEV_6010:
			f->pixelformat = V4L2_PIX_FMT_MPEG4;
			strcpy(f->description, "MPEG-4 part 2");
			break;
		case SOLO_DEV_6110:
			f->pixelformat = V4L2_PIX_FMT_H264;
			strcpy(f->description, "H.264");
			break;
		}
881 882 883 884 885 886 887 888 889 890 891 892 893 894
		break;
	case 1:
		f->pixelformat = V4L2_PIX_FMT_MJPEG;
		strcpy(f->description, "MJPEG");
		break;
	default:
		return -EINVAL;
	}

	f->flags = V4L2_FMT_FLAG_COMPRESSED;

	return 0;
}

895 896 897 898 899 900 901
static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
{
	return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
		|| (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
		|| pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
}

902 903 904
static int solo_enc_try_fmt_cap(struct file *file, void *priv,
			    struct v4l2_format *f)
{
905
	struct solo_enc_dev *solo_enc = video_drvdata(file);
906
	struct solo_dev *solo_dev = solo_enc->solo_dev;
907 908
	struct v4l2_pix_format *pix = &f->fmt.pix;

909
	if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
910 911
		return -EINVAL;

912 913
	if (pix->width < solo_dev->video_hsize ||
	    pix->height < solo_dev->video_vsize << 1) {
914 915 916
		/* Default to CIF 1/2 size */
		pix->width = solo_dev->video_hsize >> 1;
		pix->height = solo_dev->video_vsize;
917 918 919 920
	} else {
		/* Full frame */
		pix->width = solo_dev->video_hsize;
		pix->height = solo_dev->video_vsize << 1;
921 922
	}

923 924 925 926 927 928
	switch (pix->field) {
	case V4L2_FIELD_NONE:
	case V4L2_FIELD_INTERLACED:
		break;
	case V4L2_FIELD_ANY:
	default:
929
		pix->field = V4L2_FIELD_INTERLACED;
930 931
		break;
	}
932 933 934 935

	/* Just set these */
	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
	pix->sizeimage = FRAME_BUF_SIZE;
936
	pix->bytesperline = 0;
937
	pix->priv = 0;
938 939 940 941 942 943 944

	return 0;
}

static int solo_enc_set_fmt_cap(struct file *file, void *priv,
				struct v4l2_format *f)
{
945
	struct solo_enc_dev *solo_enc = video_drvdata(file);
946
	struct solo_dev *solo_dev = solo_enc->solo_dev;
947 948 949
	struct v4l2_pix_format *pix = &f->fmt.pix;
	int ret;

950 951
	if (vb2_is_busy(&solo_enc->vidq))
		return -EBUSY;
952

953
	ret = solo_enc_try_fmt_cap(file, priv, f);
954 955 956
	if (ret)
		return ret;

957 958 959 960 961 962
	if (pix->width == solo_dev->video_hsize)
		solo_enc->mode = SOLO_ENC_MODE_D1;
	else
		solo_enc->mode = SOLO_ENC_MODE_CIF;

	/* This does not change the encoder at all */
963
	solo_enc->fmt = pix->pixelformat;
964

965 966 967 968 969 970 971
	/*
	 * More information is needed about these 'extended' types. As far
	 * as I can tell these are basically additional video streams with
	 * different MPEG encoding attributes that can run in parallel with
	 * the main stream. If so, then this should be implemented as a
	 * second video node. Abusing priv like this is certainly not the
	 * right approach.
972
	if (pix->priv)
973
		solo_enc->type = SOLO_ENC_TYPE_EXT;
974
	 */
975
	solo_update_mode(solo_enc);
976
	return 0;
977 978 979 980 981
}

static int solo_enc_get_fmt_cap(struct file *file, void *priv,
				struct v4l2_format *f)
{
982
	struct solo_enc_dev *solo_enc = video_drvdata(file);
983 984 985 986
	struct v4l2_pix_format *pix = &f->fmt.pix;

	pix->width = solo_enc->width;
	pix->height = solo_enc->height;
987
	pix->pixelformat = solo_enc->fmt;
988 989 990 991
	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
		     V4L2_FIELD_NONE;
	pix->sizeimage = FRAME_BUF_SIZE;
	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
992
	pix->priv = 0;
993 994 995 996

	return 0;
}

997
static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
998
{
999 1000 1001 1002 1003 1004 1005
	struct solo_enc_dev *solo_enc = video_drvdata(file);
	struct solo_dev *solo_dev = solo_enc->solo_dev;

	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
		*i = V4L2_STD_NTSC_M;
	else
		*i = V4L2_STD_PAL;
1006 1007 1008
	return 0;
}

1009 1010 1011 1012
static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
{
	struct solo_enc_dev *solo_enc = video_drvdata(file);

1013
	return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
1014 1015
}

1016 1017 1018
static int solo_enum_framesizes(struct file *file, void *priv,
				struct v4l2_frmsizeenum *fsize)
{
1019 1020
	struct solo_enc_dev *solo_enc = video_drvdata(file);
	struct solo_dev *solo_dev = solo_enc->solo_dev;
1021

1022
	if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
		return -EINVAL;

	switch (fsize->index) {
	case 0:
		fsize->discrete.width = solo_dev->video_hsize >> 1;
		fsize->discrete.height = solo_dev->video_vsize;
		break;
	case 1:
		fsize->discrete.width = solo_dev->video_hsize;
		fsize->discrete.height = solo_dev->video_vsize << 1;
		break;
	default:
		return -EINVAL;
	}

	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;

	return 0;
}

static int solo_enum_frameintervals(struct file *file, void *priv,
				    struct v4l2_frmivalenum *fintv)
{
1046 1047
	struct solo_enc_dev *solo_enc = video_drvdata(file);
	struct solo_dev *solo_dev = solo_enc->solo_dev;
1048

1049
	if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
1050 1051 1052 1053 1054 1055 1056
		return -EINVAL;
	if (fintv->index)
		return -EINVAL;
	if ((fintv->width != solo_dev->video_hsize >> 1 ||
	     fintv->height != solo_dev->video_vsize) &&
	    (fintv->width != solo_dev->video_hsize ||
	     fintv->height != solo_dev->video_vsize << 1))
1057 1058 1059 1060
		return -EINVAL;

	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;

1061
	fintv->stepwise.min.numerator = 1;
1062
	fintv->stepwise.min.denominator = solo_dev->fps;
1063

1064
	fintv->stepwise.max.numerator = 15;
1065
	fintv->stepwise.max.denominator = solo_dev->fps;
1066 1067

	fintv->stepwise.step.numerator = 1;
1068
	fintv->stepwise.step.denominator = solo_dev->fps;
1069 1070 1071 1072 1073 1074 1075

	return 0;
}

static int solo_g_parm(struct file *file, void *priv,
		       struct v4l2_streamparm *sp)
{
1076
	struct solo_enc_dev *solo_enc = video_drvdata(file);
1077 1078 1079 1080
	struct v4l2_captureparm *cp = &sp->parm.capture;

	cp->capability = V4L2_CAP_TIMEPERFRAME;
	cp->timeperframe.numerator = solo_enc->interval;
1081
	cp->timeperframe.denominator = solo_enc->solo_dev->fps;
1082 1083 1084 1085
	cp->capturemode = 0;
	/* XXX: Shouldn't we be able to get/set this from videobuf? */
	cp->readbuffers = 2;

1086
	return 0;
1087 1088
}

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
static inline int calc_interval(u8 fps, u32 n, u32 d)
{
	if (!n || !d)
		return 1;
	if (d == fps)
		return n;
	n *= fps;
	return min(15U, n / d + (n % d >= (fps >> 1)));
}

1099 1100 1101
static int solo_s_parm(struct file *file, void *priv,
		       struct v4l2_streamparm *sp)
{
1102
	struct solo_enc_dev *solo_enc = video_drvdata(file);
1103 1104
	struct v4l2_fract *t = &sp->parm.capture.timeperframe;
	u8 fps = solo_enc->solo_dev->fps;
1105

1106
	if (vb2_is_streaming(&solo_enc->vidq))
1107 1108
		return -EBUSY;

1109
	solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
1110
	solo_update_mode(solo_enc);
1111
	return solo_g_parm(file, priv, sp);
1112 1113
}

1114
static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
1115
{
1116 1117
	struct solo_enc_dev *solo_enc =
		container_of(ctrl->handler, struct solo_enc_dev, hdl);
1118
	struct solo_dev *solo_dev = solo_enc->solo_dev;
1119 1120 1121 1122 1123 1124 1125 1126 1127
	int err;

	switch (ctrl->id) {
	case V4L2_CID_BRIGHTNESS:
	case V4L2_CID_CONTRAST:
	case V4L2_CID_SATURATION:
	case V4L2_CID_HUE:
	case V4L2_CID_SHARPNESS:
		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
1128
					 ctrl->val);
1129
	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1130
		solo_enc->gop = ctrl->val;
1131 1132
		solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
		solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
1133
		return 0;
1134 1135
	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
		solo_enc->qp = ctrl->val;
1136 1137
		solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
		solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
1138
		return 0;
1139 1140
	case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
		solo_enc->motion_thresh = ctrl->val << 8;
1141 1142
		if (!solo_enc->motion_global || !solo_enc->motion_enabled)
			return 0;
1143
		return solo_set_motion_threshold(solo_dev, solo_enc->ch,
1144 1145 1146 1147
				solo_enc->motion_thresh);
	case V4L2_CID_DETECT_MD_MODE:
		solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
		solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
1148 1149
		if (ctrl->val) {
			if (solo_enc->motion_global)
1150
				err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
1151
					solo_enc->motion_thresh);
1152
			else
1153
				err = solo_set_motion_block(solo_dev, solo_enc->ch,
1154
					solo_enc->md_thresholds->p_cur.p_u16);
1155 1156
			if (err)
				return err;
1157
		}
1158 1159
		solo_motion_toggle(solo_enc, ctrl->val);
		return 0;
1160 1161 1162 1163 1164
	case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
		if (solo_enc->motion_enabled && !solo_enc->motion_global)
			return solo_set_motion_block(solo_dev, solo_enc->ch,
					solo_enc->md_thresholds->p_new.p_u16);
		break;
1165
	case V4L2_CID_OSD_TEXT:
1166
		strcpy(solo_enc->osd_text, ctrl->p_new.p_char);
1167
		return solo_osd_print(solo_enc);
1168 1169 1170 1171 1172 1173 1174
	default:
		return -EINVAL;
	}

	return 0;
}

1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
static int solo_subscribe_event(struct v4l2_fh *fh,
				const struct v4l2_event_subscription *sub)
{

	switch (sub->type) {
	case V4L2_EVENT_CTRL:
		return v4l2_ctrl_subscribe_event(fh, sub);
	case V4L2_EVENT_MOTION_DET:
		/* Allow for up to 30 events (1 second for NTSC) to be
		 * stored. */
		return v4l2_event_subscribe(fh, sub, 30, NULL);
	}
	return -EINVAL;
}

1190 1191
static const struct v4l2_file_operations solo_enc_fops = {
	.owner			= THIS_MODULE,
1192 1193 1194 1195 1196 1197
	.open			= v4l2_fh_open,
	.release		= vb2_fop_release,
	.read			= vb2_fop_read,
	.poll			= vb2_fop_poll,
	.mmap			= vb2_fop_mmap,
	.unlocked_ioctl		= video_ioctl2,
1198 1199 1200 1201 1202
};

static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
	.vidioc_querycap		= solo_enc_querycap,
	.vidioc_s_std			= solo_enc_s_std,
1203
	.vidioc_g_std			= solo_enc_g_std,
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
	/* Input callbacks */
	.vidioc_enum_input		= solo_enc_enum_input,
	.vidioc_s_input			= solo_enc_set_input,
	.vidioc_g_input			= solo_enc_get_input,
	/* Video capture format callbacks */
	.vidioc_enum_fmt_vid_cap	= solo_enc_enum_fmt_cap,
	.vidioc_try_fmt_vid_cap		= solo_enc_try_fmt_cap,
	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
	/* Streaming I/O */
1214 1215 1216 1217 1218 1219
	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
	.vidioc_querybuf		= vb2_ioctl_querybuf,
	.vidioc_qbuf			= vb2_ioctl_qbuf,
	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
	.vidioc_streamon		= vb2_ioctl_streamon,
	.vidioc_streamoff		= vb2_ioctl_streamoff,
1220 1221 1222 1223 1224 1225
	/* Frame size and interval */
	.vidioc_enum_framesizes		= solo_enum_framesizes,
	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
	/* Video capture parameters */
	.vidioc_s_parm			= solo_s_parm,
	.vidioc_g_parm			= solo_g_parm,
1226 1227
	/* Logging and events */
	.vidioc_log_status		= v4l2_ctrl_log_status,
1228
	.vidioc_subscribe_event		= solo_subscribe_event,
1229
	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
1230 1231
};

1232
static const struct video_device solo_enc_template = {
1233
	.name			= SOLO6X10_NAME,
1234 1235 1236 1237
	.fops			= &solo_enc_fops,
	.ioctl_ops		= &solo_enc_ioctl_ops,
	.minor			= -1,
	.release		= video_device_release,
1238
	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
1239 1240
};

1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
static const struct v4l2_ctrl_ops solo_ctrl_ops = {
	.s_ctrl = solo_s_ctrl,
};

static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
	.ops = &solo_ctrl_ops,
	.id = V4L2_CID_OSD_TEXT,
	.name = "OSD Text",
	.type = V4L2_CTRL_TYPE_STRING,
	.max = OSD_TEXT_MAX,
	.step = 1,
};

1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
/* Motion Detection Threshold matrix */
static const struct v4l2_ctrl_config solo_md_thresholds = {
	.ops = &solo_ctrl_ops,
	.id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
	.dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
	.def = SOLO_DEF_MOT_THRESH,
	.max = 65535,
	.step = 1,
};

1264 1265
static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
					   u8 ch, unsigned nr)
1266 1267
{
	struct solo_enc_dev *solo_enc;
1268
	struct v4l2_ctrl_handler *hdl;
1269 1270 1271 1272 1273 1274
	int ret;

	solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
	if (!solo_enc)
		return ERR_PTR(-ENOMEM);

1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
	hdl = &solo_enc->hdl;
	v4l2_ctrl_handler_init(hdl, 10);
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_CONTRAST, 0, 255, 1, 128);
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_SATURATION, 0, 255, 1, 128);
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_HUE, 0, 255, 1, 128);
	if (tw28_has_sharpness(solo_dev, ch))
		v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_SHARPNESS, 0, 15, 1, 0);
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
1290 1291
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
1292 1293 1294 1295 1296 1297 1298
	v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
			V4L2_CID_DETECT_MD_MODE,
			V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
			V4L2_DETECT_MD_MODE_DISABLED);
	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
			V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
			SOLO_DEF_MOT_THRESH >> 8);
1299
	v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
1300 1301
	solo_enc->md_thresholds =
		v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
1302 1303
	if (hdl->error) {
		ret = hdl->error;
1304
		goto hdl_free;
1305 1306 1307 1308
	}

	solo_enc->solo_dev = solo_dev;
	solo_enc->ch = ch;
1309
	mutex_init(&solo_enc->lock);
1310 1311
	spin_lock_init(&solo_enc->av_lock);
	INIT_LIST_HEAD(&solo_enc->vidq_active);
1312 1313
	solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
		V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
1314
	solo_enc->type = SOLO_ENC_TYPE_STD;
1315 1316

	solo_enc->qp = SOLO_DEFAULT_QP;
1317
	solo_enc->gop = solo_dev->fps;
1318 1319
	solo_enc->interval = 1;
	solo_enc->mode = SOLO_ENC_MODE_CIF;
1320
	solo_enc->motion_global = true;
1321
	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
1322 1323 1324 1325 1326 1327
	solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
	solo_enc->vidq.ops = &solo_enc_video_qops;
	solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
	solo_enc->vidq.drv_priv = solo_enc;
	solo_enc->vidq.gfp_flags = __GFP_DMA32;
1328
	solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1329 1330 1331 1332 1333
	solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
	solo_enc->vidq.lock = &solo_enc->lock;
	ret = vb2_queue_init(&solo_enc->vidq);
	if (ret)
		goto hdl_free;
1334
	solo_update_mode(solo_enc);
1335 1336 1337

	spin_lock_init(&solo_enc->motion_lock);

1338 1339 1340
	/* Initialize this per encoder */
	solo_enc->jpeg_len = sizeof(jpeg_header);
	memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
1341

1342 1343 1344
	solo_enc->desc_nelts = 32;
	solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
				      sizeof(struct solo_p2m_desc) *
1345 1346
				      solo_enc->desc_nelts,
				      &solo_enc->desc_dma);
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
	ret = -ENOMEM;
	if (solo_enc->desc_items == NULL)
		goto hdl_free;

	solo_enc->vfd = video_device_alloc();
	if (!solo_enc->vfd)
		goto pci_free;

	*solo_enc->vfd = solo_enc_template;
	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
	solo_enc->vfd->ctrl_handler = hdl;
1358 1359
	solo_enc->vfd->queue = &solo_enc->vidq;
	solo_enc->vfd->lock = &solo_enc->lock;
1360 1361 1362 1363 1364 1365 1366 1367 1368
	video_set_drvdata(solo_enc->vfd, solo_enc);
	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
	if (ret < 0)
		goto vdev_release;

	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
		 solo_enc->vfd->num);

1369
	return solo_enc;
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380

vdev_release:
	video_device_release(solo_enc->vfd);
pci_free:
	pci_free_consistent(solo_enc->solo_dev->pdev,
			sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
			solo_enc->desc_items, solo_enc->desc_dma);
hdl_free:
	v4l2_ctrl_handler_free(hdl);
	kfree(solo_enc);
	return ERR_PTR(ret);
1381 1382 1383 1384 1385 1386 1387
}

static void solo_enc_free(struct solo_enc_dev *solo_enc)
{
	if (solo_enc == NULL)
		return;

1388 1389 1390
	pci_free_consistent(solo_enc->solo_dev->pdev,
			sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
			solo_enc->desc_items, solo_enc->desc_dma);
1391
	video_unregister_device(solo_enc->vfd);
1392
	v4l2_ctrl_handler_free(&solo_enc->hdl);
1393 1394 1395
	kfree(solo_enc);
}

1396
int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
1397 1398 1399
{
	int i;

1400 1401
	init_waitqueue_head(&solo_dev->ring_thread_wait);

1402
	solo_dev->vh_size = sizeof(vop_header);
1403 1404 1405 1406 1407 1408
	solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
						solo_dev->vh_size,
						&solo_dev->vh_dma);
	if (solo_dev->vh_buf == NULL)
		return -ENOMEM;

1409
	for (i = 0; i < solo_dev->nr_chans; i++) {
1410
		solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
1411 1412 1413 1414 1415 1416
		if (IS_ERR(solo_dev->v4l2_enc[i]))
			break;
	}

	if (i != solo_dev->nr_chans) {
		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1417

1418 1419
		while (i--)
			solo_enc_free(solo_dev->v4l2_enc[i]);
1420 1421
		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
				    solo_dev->vh_buf, solo_dev->vh_dma);
1422
		solo_dev->vh_buf = NULL;
1423 1424 1425
		return ret;
	}

1426 1427 1428 1429
	if (solo_dev->type == SOLO_DEV_6010)
		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
	else
		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
1430 1431 1432 1433 1434 1435 1436 1437

	dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
		 solo_dev->v4l2_enc[0]->vfd->num,
		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);

	return 0;
}

1438
void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
1439 1440 1441 1442 1443
{
	int i;

	for (i = 0; i < solo_dev->nr_chans; i++)
		solo_enc_free(solo_dev->v4l2_enc[i]);
1444

1445 1446
	if (solo_dev->vh_buf)
		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
1447
			    solo_dev->vh_buf, solo_dev->vh_dma);
1448
}