cx25821-video.c 21.6 KB
Newer Older
1 2 3
/*
 *  Driver for the Conexant CX25821 PCIe bridge
 *
4
 *  Copyright (C) 2009 Conexant Systems Inc.
5
 *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
H
Hans Verkuil 已提交
6
 *  Based on Steven Toth <stoth@linuxtv.org> cx25821 driver
7 8 9
 *  Parts adapted/taken from Eduardo Moscoso Rubino
 *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com>
 *
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 *  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

27 28
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

29 30 31
#include "cx25821-video.h"

MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
32
MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
33 34
MODULE_LICENSE("GPL");

35
static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
36 37 38 39 40

module_param_array(video_nr, int, NULL, 0444);

MODULE_PARM_DESC(video_nr, "video device numbers");

41
static unsigned int video_debug = VIDEO_DEBUG;
42 43 44 45 46 47 48 49 50
module_param(video_debug, int, 0644);
MODULE_PARM_DESC(video_debug, "enable debug messages [video]");

static unsigned int irq_debug;
module_param(irq_debug, int, 0644);
MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");

#define FORMAT_FLAGS_PACKED       0x01

51
static const struct cx25821_fmt formats[] = {
52
	{
53 54 55 56 57 58 59 60 61 62
		.name = "4:1:1, packed, Y41P",
		.fourcc = V4L2_PIX_FMT_Y41P,
		.depth = 12,
		.flags = FORMAT_FLAGS_PACKED,
	}, {
		.name = "4:2:2, packed, YUYV",
		.fourcc = V4L2_PIX_FMT_YUYV,
		.depth = 16,
		.flags = FORMAT_FLAGS_PACKED,
	},
63 64
};

65
static const struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
66
{
67
	unsigned int i;
68

69 70 71 72
	for (i = 0; i < ARRAY_SIZE(formats); i++)
		if (formats[i].fourcc == fourcc)
			return formats + i;
	return NULL;
73 74 75
}

int cx25821_start_video_dma(struct cx25821_dev *dev,
76 77
			    struct cx25821_dmaqueue *q,
			    struct cx25821_buffer *buf,
78
			    const struct sram_channel *channel)
79
{
80
	int tmp = 0;
81

82 83
	/* setup fifo + format */
	cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
84

85 86
	/* reset counter */
	cx_write(channel->gpcnt_ctl, 3);
87

88 89 90
	/* enable irq */
	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
	cx_set(channel->int_msk, 0x11);
91

92 93
	/* start dma */
	cx_write(channel->dma_ctl, 0x11);	/* FIFO and RISC enable */
94

95 96 97
	/* make sure upstream setting if any is reversed */
	tmp = cx_read(VID_CH_MODE_SEL);
	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
98

99
	return 0;
100 101 102 103
}

int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
{
104 105
	int handled = 0;
	u32 mask;
106
	const struct sram_channel *channel = dev->channels[chan_num].sram_channels;
107 108 109 110 111 112 113 114 115

	mask = cx_read(channel->int_msk);
	if (0 == (status & mask))
		return handled;

	cx_write(channel->int_stat, status);

	/* risc op code error */
	if (status & (1 << 16)) {
116 117
		pr_warn("%s, %s: video risc op code error\n",
			dev->name, channel->name);
118 119 120
		cx_clear(channel->dma_ctl, 0x11);
		cx25821_sram_channel_dump(dev, channel);
	}
121

122 123
	/* risc1 y */
	if (status & FLD_VID_DST_RISC1) {
H
Hans Verkuil 已提交
124 125 126
		struct cx25821_dmaqueue *dmaq =
			&dev->channels[channel->i].dma_vidq;
		struct cx25821_buffer *buf;
127

128
		spin_lock(&dev->slock);
H
Hans Verkuil 已提交
129 130 131 132
		if (!list_empty(&dmaq->active)) {
			buf = list_entry(dmaq->active.next,
					 struct cx25821_buffer, queue);

133
			buf->vb.vb2_buf.timestamp = ktime_get_ns();
134
			buf->vb.sequence = dmaq->count++;
H
Hans Verkuil 已提交
135
			list_del(&buf->queue);
136
			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
H
Hans Verkuil 已提交
137
		}
138 139 140 141
		spin_unlock(&dev->slock);
		handled++;
	}
	return handled;
142 143
}

144
static int cx25821_queue_setup(struct vb2_queue *q,
H
Hans Verkuil 已提交
145 146
			   unsigned int *num_buffers, unsigned int *num_planes,
			   unsigned int sizes[], void *alloc_ctxs[])
147
{
H
Hans Verkuil 已提交
148
	struct cx25821_channel *chan = q->drv_priv;
149 150
	unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;

151 152
	if (*num_planes)
		return sizes[0] < size ? -EINVAL : 0;
153

H
Hans Verkuil 已提交
154
	*num_planes = 1;
155
	sizes[0] = size;
156
	return 0;
157 158
}

H
Hans Verkuil 已提交
159
static int cx25821_buffer_prepare(struct vb2_buffer *vb)
160
{
161
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
H
Hans Verkuil 已提交
162
	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
163
	struct cx25821_dev *dev = chan->dev;
164
	struct cx25821_buffer *buf =
165
		container_of(vbuf, struct cx25821_buffer, vb);
H
Hans Verkuil 已提交
166
	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
167
	u32 line0_offset;
168
	int bpl_local = LINE_SIZE_D1;
H
Hans Verkuil 已提交
169
	int ret;
170

H
Hans Verkuil 已提交
171 172 173 174
	if (chan->pixel_formats == PIXEL_FRMT_411)
		buf->bpl = (chan->fmt->depth * chan->width) >> 3;
	else
		buf->bpl = (chan->fmt->depth >> 3) * chan->width;
175

H
Hans Verkuil 已提交
176
	if (vb2_plane_size(vb, 0) < chan->height * buf->bpl)
177
		return -EINVAL;
H
Hans Verkuil 已提交
178
	vb2_set_plane_payload(vb, 0, chan->height * buf->bpl);
179
	buf->vb.field = chan->field;
180

H
Hans Verkuil 已提交
181 182 183 184
	if (chan->pixel_formats == PIXEL_FRMT_411) {
		bpl_local = buf->bpl;
	} else {
		bpl_local = buf->bpl;   /* Default */
185

H
Hans Verkuil 已提交
186 187 188 189 190
		if (chan->use_cif_resolution) {
			if (dev->tvnorm & V4L2_STD_625_50)
				bpl_local = 352 << 1;
			else
				bpl_local = chan->cif_width << 1;
191 192 193
		}
	}

H
Hans Verkuil 已提交
194 195 196 197 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 228 229 230
	switch (chan->field) {
	case V4L2_FIELD_TOP:
		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
				sgt->sgl, 0, UNSET,
				buf->bpl, 0, chan->height);
		break;
	case V4L2_FIELD_BOTTOM:
		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
				sgt->sgl, UNSET, 0,
				buf->bpl, 0, chan->height);
		break;
	case V4L2_FIELD_INTERLACED:
		/* All other formats are top field first */
		line0_offset = 0;
		dprintk(1, "top field first\n");

		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
				sgt->sgl, line0_offset,
				bpl_local, bpl_local, bpl_local,
				chan->height >> 1);
		break;
	case V4L2_FIELD_SEQ_TB:
		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
				sgt->sgl,
				0, buf->bpl * (chan->height >> 1),
				buf->bpl, 0, chan->height >> 1);
		break;
	case V4L2_FIELD_SEQ_BT:
		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
				sgt->sgl,
				buf->bpl * (chan->height >> 1), 0,
				buf->bpl, 0, chan->height >> 1);
		break;
	default:
		WARN_ON(1);
		ret = -EINVAL;
		break;
231
	}
232

233
	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
234
		buf, buf->vb.vb2_buf.index, chan->width, chan->height,
H
Hans Verkuil 已提交
235 236
		chan->fmt->depth, chan->fmt->name,
		(unsigned long)buf->risc.dma);
237

H
Hans Verkuil 已提交
238
	return ret;
239 240
}

H
Hans Verkuil 已提交
241
static void cx25821_buffer_finish(struct vb2_buffer *vb)
242
{
243
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
244
	struct cx25821_buffer *buf =
245
		container_of(vbuf, struct cx25821_buffer, vb);
H
Hans Verkuil 已提交
246 247
	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
	struct cx25821_dev *dev = chan->dev;
248

H
Hans Verkuil 已提交
249
	cx25821_free_buffer(dev, buf);
250 251
}

H
Hans Verkuil 已提交
252
static void cx25821_buffer_queue(struct vb2_buffer *vb)
253
{
254
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
255
	struct cx25821_buffer *buf =
256
		container_of(vbuf, struct cx25821_buffer, vb);
H
Hans Verkuil 已提交
257
	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
258
	struct cx25821_dev *dev = chan->dev;
H
Hans Verkuil 已提交
259
	struct cx25821_buffer *prev;
260
	struct cx25821_dmaqueue *q = &dev->channels[chan->id].dma_vidq;
261

H
Hans Verkuil 已提交
262 263 264 265 266 267 268
	buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 12);
	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 12);
	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */

	if (list_empty(&q->active)) {
		list_add_tail(&buf->queue, &q->active);
269
	} else {
H
Hans Verkuil 已提交
270
		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
271
		prev = list_entry(q->active.prev, struct cx25821_buffer,
H
Hans Verkuil 已提交
272 273 274
				queue);
		list_add_tail(&buf->queue, &q->active);
		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
275
	}
276 277
}

H
Hans Verkuil 已提交
278
static int cx25821_start_streaming(struct vb2_queue *q, unsigned int count)
279
{
H
Hans Verkuil 已提交
280
	struct cx25821_channel *chan = q->drv_priv;
281
	struct cx25821_dev *dev = chan->dev;
H
Hans Verkuil 已提交
282 283 284
	struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq;
	struct cx25821_buffer *buf = list_entry(dmaq->active.next,
			struct cx25821_buffer, queue);
285

H
Hans Verkuil 已提交
286 287 288
	dmaq->count = 0;
	cx25821_start_video_dma(dev, dmaq, buf, chan->sram_channels);
	return 0;
289 290
}

H
Hans Verkuil 已提交
291
static void cx25821_stop_streaming(struct vb2_queue *q)
292
{
H
Hans Verkuil 已提交
293
	struct cx25821_channel *chan = q->drv_priv;
294
	struct cx25821_dev *dev = chan->dev;
H
Hans Verkuil 已提交
295 296
	struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq;
	unsigned long flags;
297

H
Hans Verkuil 已提交
298 299 300 301 302
	cx_write(chan->sram_channels->dma_ctl, 0); /* FIFO and RISC disable */
	spin_lock_irqsave(&dev->slock, flags);
	while (!list_empty(&dmaq->active)) {
		struct cx25821_buffer *buf = list_entry(dmaq->active.next,
			struct cx25821_buffer, queue);
303

H
Hans Verkuil 已提交
304
		list_del(&buf->queue);
305
		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
306
	}
H
Hans Verkuil 已提交
307
	spin_unlock_irqrestore(&dev->slock, flags);
308 309
}

H
Hans Verkuil 已提交
310 311 312 313 314 315 316 317 318 319 320
static struct vb2_ops cx25821_video_qops = {
	.queue_setup    = cx25821_queue_setup,
	.buf_prepare  = cx25821_buffer_prepare,
	.buf_finish = cx25821_buffer_finish,
	.buf_queue    = cx25821_buffer_queue,
	.wait_prepare = vb2_ops_wait_prepare,
	.wait_finish = vb2_ops_wait_finish,
	.start_streaming = cx25821_start_streaming,
	.stop_streaming = cx25821_stop_streaming,
};

321
/* VIDEO IOCTLS */
322 323 324 325 326 327 328 329 330 331 332 333 334

static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
			    struct v4l2_fmtdesc *f)
{
	if (unlikely(f->index >= ARRAY_SIZE(formats)))
		return -EINVAL;

	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
	f->pixelformat = formats[f->index].fourcc;

	return 0;
}

335 336 337
static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
				 struct v4l2_format *f)
{
338
	struct cx25821_channel *chan = video_drvdata(file);
339

340 341
	f->fmt.pix.width = chan->width;
	f->fmt.pix.height = chan->height;
H
Hans Verkuil 已提交
342
	f->fmt.pix.field = chan->field;
343
	f->fmt.pix.pixelformat = chan->fmt->fourcc;
344 345 346
	f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
	f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
347 348 349 350 351 352 353

	return 0;
}

static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
				   struct v4l2_format *f)
{
354 355
	struct cx25821_channel *chan = video_drvdata(file);
	struct cx25821_dev *dev = chan->dev;
356
	const struct cx25821_fmt *fmt;
357
	enum v4l2_field field = f->fmt.pix.field;
358
	unsigned int maxh;
359
	unsigned w;
360 361 362 363

	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
	if (NULL == fmt)
		return -EINVAL;
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
	maxh = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480;

	w = f->fmt.pix.width;
	if (field != V4L2_FIELD_BOTTOM)
		field = V4L2_FIELD_TOP;
	if (w < 352) {
		w = 176;
		f->fmt.pix.height = maxh / 4;
	} else if (w < 720) {
		w = 352;
		f->fmt.pix.height = maxh / 2;
	} else {
		w = 720;
		f->fmt.pix.height = maxh;
		field = V4L2_FIELD_INTERLACED;
379 380
	}
	f->fmt.pix.field = field;
381
	f->fmt.pix.width = w;
382 383
	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
384
	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
385 386 387

	return 0;
}
388 389

static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
390
				struct v4l2_format *f)
391
{
392
	struct cx25821_channel *chan = video_drvdata(file);
393
	struct cx25821_dev *dev = chan->dev;
394
	int pix_format = PIXEL_FRMT_422;
395
	int err;
396

397
	err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
398

399 400
	if (0 != err)
		return err;
401

402
	chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
H
Hans Verkuil 已提交
403
	chan->field = f->fmt.pix.field;
404 405
	chan->width = f->fmt.pix.width;
	chan->height = f->fmt.pix.height;
406

407 408 409
	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
		pix_format = PIXEL_FRMT_411;
	else
410
		pix_format = PIXEL_FRMT_422;
411

412
	cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
413

414
	/* check if cif resolution */
415 416
	if (chan->width == 320 || chan->width == 352)
		chan->use_cif_resolution = 1;
417
	else
418
		chan->use_cif_resolution = 0;
419

420 421
	chan->cif_width = chan->width;
	medusa_set_resolution(dev, chan->width, SRAM_CH00);
422
	return 0;
423 424 425 426
}

static int vidioc_log_status(struct file *file, void *priv)
{
427 428 429
	struct cx25821_channel *chan = video_drvdata(file);
	struct cx25821_dev *dev = chan->dev;
	const struct sram_channel *sram_ch = chan->sram_channels;
430
	u32 tmp = 0;
431

432
	tmp = cx_read(sram_ch->dma_ctl);
433 434
	pr_info("Video input 0 is %s\n",
		(tmp & 0x11) ? "streaming" : "stopped");
435
	return 0;
436 437
}

438

439
static int cx25821_vidioc_querycap(struct file *file, void *priv,
440
			    struct v4l2_capability *cap)
441
{
442 443
	struct cx25821_channel *chan = video_drvdata(file);
	struct cx25821_dev *dev = chan->dev;
444 445
	const u32 cap_input = V4L2_CAP_VIDEO_CAPTURE |
			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
446
	const u32 cap_output = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE;
447 448 449 450

	strcpy(cap->driver, "cx25821");
	strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
	sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
451
	if (chan->id >= VID_CHANNEL_NUM)
452 453 454
		cap->device_caps = cap_output;
	else
		cap->device_caps = cap_input;
455
	cap->capabilities = cap_input | cap_output | V4L2_CAP_DEVICE_CAPS;
456
	return 0;
457 458
}

459
static int cx25821_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
460
{
461
	struct cx25821_channel *chan = video_drvdata(file);
462

463
	*tvnorms = chan->dev->tvnorm;
464 465 466
	return 0;
}

467 468
static int cx25821_vidioc_s_std(struct file *file, void *priv,
				v4l2_std_id tvnorms)
469
{
470 471
	struct cx25821_channel *chan = video_drvdata(file);
	struct cx25821_dev *dev = chan->dev;
472

473
	if (dev->tvnorm == tvnorms)
474
		return 0;
475

476
	dev->tvnorm = tvnorms;
477 478
	chan->width = 720;
	chan->height = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480;
479

480
	medusa_set_videostandard(dev);
481

482
	return 0;
483 484
}

485 486
static int cx25821_vidioc_enum_input(struct file *file, void *priv,
			      struct v4l2_input *i)
487
{
488
	if (i->index)
489
		return -EINVAL;
490

491 492
	i->type = V4L2_INPUT_TYPE_CAMERA;
	i->std = CX25821_NORMS;
493
	strcpy(i->name, "Composite");
494
	return 0;
495 496
}

497
static int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
498
{
499
	*i = 0;
500
	return 0;
501 502
}

503
static int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
504
{
505
	return i ? -EINVAL : 0;
506 507
}

508
static int cx25821_s_ctrl(struct v4l2_ctrl *ctrl)
509
{
510 511 512
	struct cx25821_channel *chan =
		container_of(ctrl->handler, struct cx25821_channel, hdl);
	struct cx25821_dev *dev = chan->dev;
513

514
	switch (ctrl->id) {
515
	case V4L2_CID_BRIGHTNESS:
516
		medusa_set_brightness(dev, ctrl->val, chan->id);
517
		break;
518
	case V4L2_CID_HUE:
519
		medusa_set_hue(dev, ctrl->val, chan->id);
520
		break;
521
	case V4L2_CID_CONTRAST:
522
		medusa_set_contrast(dev, ctrl->val, chan->id);
523
		break;
524
	case V4L2_CID_SATURATION:
525
		medusa_set_saturation(dev, ctrl->val, chan->id);
526
		break;
527
	default:
528
		return -EINVAL;
529
	}
530
	return 0;
531 532
}

533 534
static int cx25821_vidioc_enum_output(struct file *file, void *priv,
			      struct v4l2_output *o)
535
{
536 537
	if (o->index)
		return -EINVAL;
538

539 540 541
	o->type = V4L2_INPUT_TYPE_CAMERA;
	o->std = CX25821_NORMS;
	strcpy(o->name, "Composite");
542
	return 0;
543 544
}

545
static int cx25821_vidioc_g_output(struct file *file, void *priv, unsigned int *o)
546
{
547
	*o = 0;
548
	return 0;
549 550
}

551
static int cx25821_vidioc_s_output(struct file *file, void *priv, unsigned int o)
552
{
553
	return o ? -EINVAL : 0;
554 555
}

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
				   struct v4l2_format *f)
{
	struct cx25821_channel *chan = video_drvdata(file);
	struct cx25821_dev *dev = chan->dev;
	const struct cx25821_fmt *fmt;

	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
	if (NULL == fmt)
		return -EINVAL;
	f->fmt.pix.width = 720;
	f->fmt.pix.height = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480;
	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
	return 0;
}

static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
				struct v4l2_format *f)
{
	struct cx25821_channel *chan = video_drvdata(file);
	int err;

	err = cx25821_vidioc_try_fmt_vid_out(file, priv, f);

	if (0 != err)
		return err;

	chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
H
Hans Verkuil 已提交
587
	chan->field = f->fmt.pix.field;
588 589 590 591 592 593 594 595 596
	chan->width = f->fmt.pix.width;
	chan->height = f->fmt.pix.height;
	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
		chan->pixel_formats = PIXEL_FRMT_411;
	else
		chan->pixel_formats = PIXEL_FRMT_422;
	return 0;
}

597 598 599 600
static const struct v4l2_ctrl_ops cx25821_ctrl_ops = {
	.s_ctrl = cx25821_s_ctrl,
};

601
static const struct v4l2_file_operations video_fops = {
602
	.owner = THIS_MODULE,
603
	.open = v4l2_fh_open,
H
Hans Verkuil 已提交
604 605 606
	.release        = vb2_fop_release,
	.read           = vb2_fop_read,
	.poll		= vb2_fop_poll,
607
	.unlocked_ioctl = video_ioctl2,
H
Hans Verkuil 已提交
608
	.mmap           = vb2_fop_mmap,
609 610 611
};

static const struct v4l2_ioctl_ops video_ioctl_ops = {
612 613 614 615 616
	.vidioc_querycap = cx25821_vidioc_querycap,
	.vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
	.vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
	.vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
	.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
H
Hans Verkuil 已提交
617 618
	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
619
	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
H
Hans Verkuil 已提交
620 621 622 623 624
	.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,
625
	.vidioc_g_std = cx25821_vidioc_g_std,
626 627 628 629 630
	.vidioc_s_std = cx25821_vidioc_s_std,
	.vidioc_enum_input = cx25821_vidioc_enum_input,
	.vidioc_g_input = cx25821_vidioc_g_input,
	.vidioc_s_input = cx25821_vidioc_s_input,
	.vidioc_log_status = vidioc_log_status,
631 632
	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
633 634
};

635 636
static const struct video_device cx25821_video_device = {
	.name = "cx25821-video",
637
	.fops = &video_fops,
638
	.release = video_device_release_empty,
639
	.minor = -1,
640 641
	.ioctl_ops = &video_ioctl_ops,
	.tvnorms = CX25821_NORMS,
642
};
643

644 645 646
static const struct v4l2_file_operations video_out_fops = {
	.owner = THIS_MODULE,
	.open = v4l2_fh_open,
H
Hans Verkuil 已提交
647 648 649
	.release        = vb2_fop_release,
	.write          = vb2_fop_write,
	.poll		= vb2_fop_poll,
650
	.unlocked_ioctl = video_ioctl2,
H
Hans Verkuil 已提交
651
	.mmap           = vb2_fop_mmap,
652 653 654 655
};

static const struct v4l2_ioctl_ops video_out_ioctl_ops = {
	.vidioc_querycap = cx25821_vidioc_querycap,
656 657 658 659
	.vidioc_enum_fmt_vid_out = cx25821_vidioc_enum_fmt_vid_cap,
	.vidioc_g_fmt_vid_out = cx25821_vidioc_g_fmt_vid_cap,
	.vidioc_try_fmt_vid_out = cx25821_vidioc_try_fmt_vid_out,
	.vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
	.vidioc_g_std = cx25821_vidioc_g_std,
	.vidioc_s_std = cx25821_vidioc_s_std,
	.vidioc_enum_output = cx25821_vidioc_enum_output,
	.vidioc_g_output = cx25821_vidioc_g_output,
	.vidioc_s_output = cx25821_vidioc_s_output,
	.vidioc_log_status = vidioc_log_status,
};

static const struct video_device cx25821_video_out_device = {
	.name = "cx25821-video",
	.fops = &video_out_fops,
	.release = video_device_release_empty,
	.minor = -1,
	.ioctl_ops = &video_out_ioctl_ops,
	.tvnorms = CX25821_NORMS,
};

677 678 679 680
void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
{
	cx_clear(PCI_INT_MSK, 1);

681 682
	if (video_is_registered(&dev->channels[chan_num].vdev)) {
		video_unregister_device(&dev->channels[chan_num].vdev);
683
		v4l2_ctrl_handler_free(&dev->channels[chan_num].hdl);
684 685 686 687 688 689 690 691
	}
}

int cx25821_video_register(struct cx25821_dev *dev)
{
	int err;
	int i;

H
Hans Verkuil 已提交
692
	/* initial device configuration */
693
	dev->tvnorm = V4L2_STD_NTSC_M;
H
Hans Verkuil 已提交
694

695 696
	spin_lock_init(&dev->slock);

697
	for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; ++i) {
698 699 700
		struct cx25821_channel *chan = &dev->channels[i];
		struct video_device *vdev = &chan->vdev;
		struct v4l2_ctrl_handler *hdl = &chan->hdl;
H
Hans Verkuil 已提交
701
		struct vb2_queue *q;
702
		bool is_output = i > SRAM_CH08;
703

704 705 706
		if (i == SRAM_CH08) /* audio channel */
			continue;

707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
		if (!is_output) {
			v4l2_ctrl_handler_init(hdl, 4);
			v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
					V4L2_CID_BRIGHTNESS, 0, 10000, 1, 6200);
			v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
					V4L2_CID_CONTRAST, 0, 10000, 1, 5000);
			v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
					V4L2_CID_SATURATION, 0, 10000, 1, 5000);
			v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
					V4L2_CID_HUE, 0, 10000, 1, 5000);
			if (hdl->error) {
				err = hdl->error;
				goto fail_unreg;
			}
			err = v4l2_ctrl_handler_setup(hdl);
			if (err)
				goto fail_unreg;
724 725 726
		} else {
			chan->out = &dev->vid_out_data[i - SRAM_CH09];
			chan->out->chan = chan;
727
		}
728

729 730
		chan->sram_channels = &cx25821_sram_channels[i];
		chan->width = 720;
H
Hans Verkuil 已提交
731
		chan->field = V4L2_FIELD_INTERLACED;
732 733 734 735
		if (dev->tvnorm & V4L2_STD_625_50)
			chan->height = 576;
		else
			chan->height = 480;
736

737 738 739 740
		if (chan->pixel_formats == PIXEL_FRMT_411)
			chan->fmt = cx25821_format_by_fourcc(V4L2_PIX_FMT_Y41P);
		else
			chan->fmt = cx25821_format_by_fourcc(V4L2_PIX_FMT_YUYV);
741

742
		cx_write(chan->sram_channels->int_stat, 0xffffffff);
743

744 745
		INIT_LIST_HEAD(&chan->dma_vidq.active);

H
Hans Verkuil 已提交
746 747 748 749 750 751 752 753 754 755 756 757 758 759
		q = &chan->vidq;

		q->type = is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT :
				      V4L2_BUF_TYPE_VIDEO_CAPTURE;
		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
		q->io_modes |= is_output ? VB2_WRITE : VB2_READ;
		q->gfp_flags = GFP_DMA32;
		q->min_buffers_needed = 2;
		q->drv_priv = chan;
		q->buf_struct_size = sizeof(struct cx25821_buffer);
		q->ops = &cx25821_video_qops;
		q->mem_ops = &vb2_dma_sg_memops;
		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
		q->lock = &dev->lock;
760
		q->dev = &dev->pci->dev;
761

H
Hans Verkuil 已提交
762 763 764 765 766
		if (!is_output) {
			err = vb2_queue_init(q);
			if (err < 0)
				goto fail_unreg;
		}
767 768

		/* register v4l devices */
769
		*vdev = is_output ? cx25821_video_out_device : cx25821_video_device;
770
		vdev->v4l2_dev = &dev->v4l2_dev;
771 772 773 774
		if (!is_output)
			vdev->ctrl_handler = hdl;
		else
			vdev->vfl_dir = VFL_DIR_TX;
H
Hans Verkuil 已提交
775
		vdev->lock = &dev->lock;
H
Hans Verkuil 已提交
776
		vdev->queue = q;
777
		snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
778
		video_set_drvdata(vdev, chan);
779

780 781
		err = video_register_device(vdev, VFL_TYPE_GRABBER,
					    video_nr[dev->nr]);
782 783 784 785 786 787 788 789 790 791 792

		if (err < 0)
			goto fail_unreg;
	}

	/* set PCI interrupt */
	cx_set(PCI_INT_MSK, 0xff);

	return 0;

fail_unreg:
793 794
	while (i >= 0)
		cx25821_video_unregister(dev, i--);
795 796
	return err;
}