cx18-ioctl.c 32.1 KB
Newer Older
1 2 3 4 5 6
/*
 *  cx18 ioctl system call
 *
 *  Derived from ivtv-ioctl.c
 *
 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
7
 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA
 */

#include "cx18-driver.h"
26
#include "cx18-io.h"
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
#include "cx18-version.h"
#include "cx18-mailbox.h"
#include "cx18-i2c.h"
#include "cx18-queue.h"
#include "cx18-fileops.h"
#include "cx18-vbi.h"
#include "cx18-audio.h"
#include "cx18-video.h"
#include "cx18-streams.h"
#include "cx18-ioctl.h"
#include "cx18-gpio.h"
#include "cx18-controls.h"
#include "cx18-cards.h"
#include "cx18-av-core.h"
#include <media/tveeprom.h>
#include <media/v4l2-chip-ident.h>

44 45 46 47 48 49 50 51 52 53 54 55
static struct v4l2_fmtdesc formats[] = {
	{ 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
	  "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
	},
	{ 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
	  "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
	},
	{ 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
	  "YUYV 4:2:2", V4L2_PIX_FMT_YUYV, { 0, 0, 0, 0 }
	},
};

56
u16 cx18_service2vbi(int type)
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
{
	switch (type) {
	case V4L2_SLICED_TELETEXT_B:
		return CX18_SLICED_TYPE_TELETEXT_B;
	case V4L2_SLICED_CAPTION_525:
		return CX18_SLICED_TYPE_CAPTION_525;
	case V4L2_SLICED_WSS_625:
		return CX18_SLICED_TYPE_WSS_625;
	case V4L2_SLICED_VPS:
		return CX18_SLICED_TYPE_VPS;
	default:
		return 0;
	}
}

72
/* Check if VBI services are allowed on the (field, line) for the video std */
73 74
static int valid_service_line(int field, int line, int is_pal)
{
75 76
	return (is_pal && line >= 6 &&
		((field == 0 && line <= 23) || (field == 1 && line <= 22))) ||
77 78 79
	       (!is_pal && line >= 10 && line < 22);
}

80 81 82 83 84 85 86
/*
 * For a (field, line, std) and inbound potential set of services for that line,
 * return the first valid service of those passed in the incoming set for that
 * line in priority order:
 * CC, VPS, or WSS over TELETEXT for well known lines
 * TELETEXT, before VPS, before CC, before WSS, for other lines
 */
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
{
	u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
	int i;

	set = set & valid_set;
	if (set == 0 || !valid_service_line(field, line, is_pal))
		return 0;
	if (!is_pal) {
		if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
			return V4L2_SLICED_CAPTION_525;
	} else {
		if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
			return V4L2_SLICED_VPS;
		if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
			return V4L2_SLICED_WSS_625;
		if (line == 23)
			return 0;
	}
	for (i = 0; i < 32; i++) {
		if ((1 << i) & set)
			return 1 << i;
	}
	return 0;
}

113 114 115 116
/*
 * Expand the service_set of *fmt into valid service_lines for the std,
 * and clear the passed in fmt->service_set
 */
117
void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
118 119 120 121 122 123 124 125 126 127 128
{
	u16 set = fmt->service_set;
	int f, l;

	fmt->service_set = 0;
	for (f = 0; f < 2; f++) {
		for (l = 0; l < 24; l++)
			fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
	}
}

129 130 131 132
/*
 * Sanitize the service_lines in *fmt per the video std, and return 1
 * if any service_line is left as valid after santization
 */
133 134 135 136 137 138 139 140 141 142 143 144 145
static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
{
	int f, l;
	u16 set = 0;

	for (f = 0; f < 2; f++) {
		for (l = 0; l < 24; l++) {
			fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
			set |= fmt->service_lines[f][l];
		}
	}
	return set != 0;
}
146

147
/* Compute the service_set from the assumed valid service_lines of *fmt */
148
u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
149 150 151 152 153 154 155 156 157 158 159
{
	int f, l;
	u16 set = 0;

	for (f = 0; f < 2; f++) {
		for (l = 0; l < 24; l++)
			set |= fmt->service_lines[f][l];
	}
	return set;
}

160 161 162
static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
163
	struct cx18_open_id *id = fh2id(fh);
164
	struct cx18 *cx = id->cx;
165
	struct cx18_stream *s = &cx->streams[id->type];
166
	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
167

168 169
	pixfmt->width = cx->cxhdl.width;
	pixfmt->height = cx->cxhdl.height;
170 171 172
	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
	pixfmt->field = V4L2_FIELD_INTERLACED;
	pixfmt->priv = 0;
173
	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
174
		pixfmt->pixelformat = s->pixelformat;
175 176
		/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
		pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
177
		pixfmt->bytesperline = 720;
178
	} else {
179 180 181
		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
		pixfmt->sizeimage = 128 * 1024;
		pixfmt->bytesperline = 0;
182 183 184
	}
	return 0;
}
185

186 187 188
static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
189
	struct cx18 *cx = fh2id(fh)->cx;
190
	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
191

192
	vbifmt->sampling_rate = 27000000;
193
	vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */
194
	vbifmt->samples_per_line = vbi_active_samples - 4;
195 196 197 198 199 200 201
	vbifmt->sample_format = V4L2_PIX_FMT_GREY;
	vbifmt->start[0] = cx->vbi.start[0];
	vbifmt->start[1] = cx->vbi.start[1];
	vbifmt->count[0] = vbifmt->count[1] = cx->vbi.count;
	vbifmt->flags = 0;
	vbifmt->reserved[0] = 0;
	vbifmt->reserved[1] = 0;
202 203 204
	return 0;
}

205 206
static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
					struct v4l2_format *fmt)
207
{
208
	struct cx18 *cx = fh2id(fh)->cx;
209 210
	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;

211
	/* sane, V4L2 spec compliant, defaults */
212 213 214 215
	vbifmt->reserved[0] = 0;
	vbifmt->reserved[1] = 0;
	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
	memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
216 217 218 219 220 221 222
	vbifmt->service_set = 0;

	/*
	 * Fetch the configured service_lines and total service_set from the
	 * digitizer/slicer.  Note, cx18_av_vbi() wipes the passed in
	 * fmt->fmt.sliced under valid calling conditions
	 */
223
	if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced))
224
		return -EINVAL;
225

226 227 228 229
	/* Ensure V4L2 spec compliant output */
	vbifmt->reserved[0] = 0;
	vbifmt->reserved[1] = 0;
	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
230 231
	vbifmt->service_set = cx18_get_service_set(vbifmt);
	return 0;
232
}
233

234 235 236
static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
237
	struct cx18_open_id *id = fh2id(fh);
238 239 240
	struct cx18 *cx = id->cx;
	int w = fmt->fmt.pix.width;
	int h = fmt->fmt.pix.height;
241
	int min_h = 2;
242

243
	w = min(w, 720);
244 245 246 247 248 249
	w = max(w, 2);
	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
		/* YUV height must be a multiple of 32 */
		h &= ~0x1f;
		min_h = 32;
	}
250
	h = min(h, cx->is_50hz ? 576 : 480);
251 252
	h = max(h, min_h);

253 254 255 256
	fmt->fmt.pix.width = w;
	fmt->fmt.pix.height = h;
	return 0;
}
257

258 259 260 261 262 263 264 265 266
static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
	return cx18_g_fmt_vbi_cap(file, fh, fmt);
}

static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
					struct v4l2_format *fmt)
{
267
	struct cx18 *cx = fh2id(fh)->cx;
268 269 270 271 272 273
	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;

	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
	vbifmt->reserved[0] = 0;
	vbifmt->reserved[1] = 0;

274
	/* If given a service set, expand it validly & clear passed in set */
275 276
	if (vbifmt->service_set)
		cx18_expand_service_set(vbifmt, cx->is_50hz);
277 278 279
	/* Sanitize the service_lines, and compute the new set if any valid */
	if (check_service_set(vbifmt, cx->is_50hz))
		vbifmt->service_set = cx18_get_service_set(vbifmt);
280
	return 0;
281 282 283 284 285
}

static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
286
	struct cx18_open_id *id = fh2id(fh);
287
	struct cx18 *cx = id->cx;
288
	struct v4l2_mbus_framefmt mbus_fmt;
289
	struct cx18_stream *s = &cx->streams[id->type];
290
	int ret;
291
	int w, h;
292 293 294 295

	ret = cx18_try_fmt_vid_cap(file, fh, fmt);
	if (ret)
		return ret;
296 297
	w = fmt->fmt.pix.width;
	h = fmt->fmt.pix.height;
298

299 300 301 302
	s->pixelformat = fmt->fmt.pix.pixelformat;
	s->vbheight = h;
	s->vbwidth = w;

303
	if (cx->cxhdl.width == w && cx->cxhdl.height == h)
304
		return 0;
305 306

	if (atomic_read(&cx->ana_capturing) > 0)
307
		return -EBUSY;
308

309 310
	mbus_fmt.width = cx->cxhdl.width = w;
	mbus_fmt.height = cx->cxhdl.height = h;
311 312
	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
313
	return cx18_g_fmt_vid_cap(file, fh, fmt);
314 315
}

316 317
static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
318
{
319
	struct cx18_open_id *id = fh2id(fh);
320
	struct cx18 *cx = id->cx;
321
	int ret;
322

323 324 325 326 327
	/*
	 * Changing the Encoder's Raw VBI parameters won't have any effect
	 * if any analog capture is ongoing
	 */
	if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
328
		return -EBUSY;
329

330 331
	/*
	 * Set the digitizer registers for raw active VBI.
L
Lucas De Marchi 已提交
332
	 * Note cx18_av_vbi_wipes out a lot of the passed in fmt under valid
333 334
	 * calling conditions
	 */
335
	ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi);
336 337 338 339
	if (ret)
		return ret;

	/* Store our new v4l2 (non-)sliced VBI state */
340
	cx->vbi.sliced_in->service_set = 0;
341
	cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
342

343 344 345 346 347 348
	return cx18_g_fmt_vbi_cap(file, fh, fmt);
}

static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
					struct v4l2_format *fmt)
{
349
	struct cx18_open_id *id = fh2id(fh);
350 351 352 353
	struct cx18 *cx = id->cx;
	int ret;
	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;

354
	cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
355

356 357 358 359 360
	/*
	 * Changing the Encoder's Raw VBI parameters won't have any effect
	 * if any analog capture is ongoing
	 */
	if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
361
		return -EBUSY;
362

363 364 365 366 367
	/*
	 * Set the service_lines requested in the digitizer/slicer registers.
	 * Note, cx18_av_vbi() wipes some "impossible" service lines in the
	 * passed in fmt->fmt.sliced under valid calling conditions
	 */
368
	ret = v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &fmt->fmt.sliced);
369 370 371
	if (ret)
		return ret;
	/* Store our current v4l2 sliced VBI settings */
372 373 374
	cx->vbi.in.type =  V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
	memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
	return 0;
375 376 377
}

static int cx18_g_chip_ident(struct file *file, void *fh,
378
				struct v4l2_dbg_chip_ident *chip)
379
{
380
	struct cx18 *cx = fh2id(fh)->cx;
381
	int err = 0;
382 383 384

	chip->ident = V4L2_IDENT_NONE;
	chip->revision = 0;
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
	switch (chip->match.type) {
	case V4L2_CHIP_MATCH_HOST:
		switch (chip->match.addr) {
		case 0:
			chip->ident = V4L2_IDENT_CX23418;
			chip->revision = cx18_read_reg(cx, 0xC72028);
			break;
		case 1:
			/*
			 * The A/V decoder is always present, but in the rare
			 * case that the card doesn't have analog, we don't
			 * use it.  We find it w/o using the cx->sd_av pointer
			 */
			cx18_call_hw(cx, CX18_HW_418_AV,
				     core, g_chip_ident, chip);
			break;
		default:
			/*
			 * Could return ident = V4L2_IDENT_UNKNOWN if we had
			 * other host chips at higher addresses, but we don't
			 */
			err = -EINVAL; /* per V4L2 spec */
			break;
		}
		break;
	case V4L2_CHIP_MATCH_I2C_DRIVER:
		/* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
		cx18_call_all(cx, core, g_chip_ident, chip);
		break;
	case V4L2_CHIP_MATCH_I2C_ADDR:
		/*
		 * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
		 * to look if a chip is at the address with no driver.  That's a
		 * dangerous thing to do with EEPROMs anyway.
		 */
		cx18_call_all(cx, core, g_chip_ident, chip);
		break;
	default:
		err = -EINVAL;
		break;
425
	}
426
	return err;
427 428
}

429 430 431
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
{
432
	struct v4l2_dbg_register *regs = arg;
433 434 435 436 437 438

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;
	if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
		return -EINVAL;

439
	regs->size = 4;
440
	if (cmd == VIDIOC_DBG_S_REGISTER)
441
		cx18_write_enc(cx, regs->val, regs->reg);
442 443
	else
		regs->val = cx18_read_enc(cx, regs->reg);
444 445 446
	return 0;
}

447
static int cx18_g_register(struct file *file, void *fh,
448
				struct v4l2_dbg_register *reg)
449
{
450
	struct cx18 *cx = fh2id(fh)->cx;
451

452
	if (v4l2_chip_match_host(&reg->match))
453
		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
454 455
	/* FIXME - errors shouldn't be ignored */
	cx18_call_all(cx, core, g_register, reg);
456
	return 0;
457 458 459
}

static int cx18_s_register(struct file *file, void *fh,
460
				struct v4l2_dbg_register *reg)
461
{
462
	struct cx18 *cx = fh2id(fh)->cx;
463

464
	if (v4l2_chip_match_host(&reg->match))
465
		return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
466 467
	/* FIXME - errors shouldn't be ignored */
	cx18_call_all(cx, core, s_register, reg);
468
	return 0;
469
}
470
#endif
471 472 473 474

static int cx18_querycap(struct file *file, void *fh,
				struct v4l2_capability *vcap)
{
475
	struct cx18 *cx = fh2id(fh)->cx;
476

477 478
	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
479 480
	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
		 "PCI:%s", pci_name(cx->pci_dev));
481 482 483 484
	vcap->version = CX18_DRIVER_VERSION; 	    /* version */
	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
	return 0;
}
485

486 487
static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
{
488
	struct cx18 *cx = fh2id(fh)->cx;
489

490 491
	return cx18_get_audio_input(cx, vin->index, vin);
}
492

493 494
static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
{
495
	struct cx18 *cx = fh2id(fh)->cx;
496

497 498 499
	vin->index = cx->audio_input;
	return cx18_get_audio_input(cx, vin->index, vin);
}
500

501 502
static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
{
503
	struct cx18 *cx = fh2id(fh)->cx;
504

505 506 507 508 509 510
	if (vout->index >= cx->nof_audio_inputs)
		return -EINVAL;
	cx->audio_input = vout->index;
	cx18_audio_set_io(cx);
	return 0;
}
511

512 513
static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
{
514
	struct cx18 *cx = fh2id(fh)->cx;
515

516 517 518
	/* set it to defaults from our table */
	return cx18_get_input(cx, vin->index, vin);
}
519

520 521 522
static int cx18_cropcap(struct file *file, void *fh,
			struct v4l2_cropcap *cropcap)
{
523
	struct cx18 *cx = fh2id(fh)->cx;
524

525 526 527 528 529 530 531 532 533 534
	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
	cropcap->bounds.top = cropcap->bounds.left = 0;
	cropcap->bounds.width = 720;
	cropcap->bounds.height = cx->is_50hz ? 576 : 480;
	cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
	cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
	cropcap->defrect = cropcap->bounds;
	return 0;
}
535

536 537
static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
{
538
	struct cx18_open_id *id = fh2id(fh);
539
	struct cx18 *cx = id->cx;
540

541 542
	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
543 544
	CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n");
	return -EINVAL;
545
}
546

547 548
static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
{
549
	struct cx18 *cx = fh2id(fh)->cx;
550

551 552
	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
553 554
	CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
	return -EINVAL;
555 556 557 558 559
}

static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
					struct v4l2_fmtdesc *fmt)
{
560
	if (fmt->index > ARRAY_SIZE(formats) - 1)
561 562 563 564 565 566 567
		return -EINVAL;
	*fmt = formats[fmt->index];
	return 0;
}

static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
{
568
	struct cx18 *cx = fh2id(fh)->cx;
569 570 571 572 573 574 575

	*i = cx->active_input;
	return 0;
}

int cx18_s_input(struct file *file, void *fh, unsigned int inp)
{
576
	struct cx18_open_id *id = fh2id(fh);
577 578
	struct cx18 *cx = id->cx;

579
	if (inp >= cx->nof_inputs)
580 581 582 583
		return -EINVAL;

	if (inp == cx->active_input) {
		CX18_DEBUG_INFO("Input unchanged\n");
584 585 586
		return 0;
	}

587 588
	CX18_DEBUG_INFO("Changing input from %d to %d\n",
			cx->active_input, inp);
589

590 591 592
	cx->active_input = inp;
	/* Set the audio input to whatever is appropriate for the input type. */
	cx->audio_input = cx->card->video_inputs[inp].audio_index;
593

594 595 596 597 598 599 600 601
	/* prevent others from messing with the streams until
	   we're finished changing inputs. */
	cx18_mute(cx);
	cx18_video_set_io(cx);
	cx18_audio_set_io(cx);
	cx18_unmute(cx);
	return 0;
}
602

603 604 605
static int cx18_g_frequency(struct file *file, void *fh,
				struct v4l2_frequency *vf)
{
606
	struct cx18 *cx = fh2id(fh)->cx;
607

608 609
	if (vf->tuner != 0)
		return -EINVAL;
610

611
	cx18_call_all(cx, tuner, g_frequency, vf);
612 613
	return 0;
}
614

615 616
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
{
617
	struct cx18_open_id *id = fh2id(fh);
618
	struct cx18 *cx = id->cx;
619

620 621
	if (vf->tuner != 0)
		return -EINVAL;
622

623 624
	cx18_mute(cx);
	CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
625
	cx18_call_all(cx, tuner, s_frequency, vf);
626 627 628
	cx18_unmute(cx);
	return 0;
}
629

630 631
static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
{
632
	struct cx18 *cx = fh2id(fh)->cx;
633

634 635 636
	*std = cx->std;
	return 0;
}
637

638 639
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
{
640
	struct cx18_open_id *id = fh2id(fh);
641
	struct cx18 *cx = id->cx;
642

643 644
	if ((*std & V4L2_STD_ALL) == 0)
		return -EINVAL;
645

646 647 648 649 650 651 652 653 654
	if (*std == cx->std)
		return 0;

	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
	    atomic_read(&cx->ana_capturing) > 0) {
		/* Switching standard would turn off the radio or mess
		   with already running streams, prevent that by
		   returning EBUSY. */
		return -EBUSY;
655 656
	}

657 658
	cx->std = *std;
	cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
659 660 661 662
	cx->is_50hz = !cx->is_60hz;
	cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
	cx->cxhdl.width = 720;
	cx->cxhdl.height = cx->is_50hz ? 576 : 480;
663 664 665 666 667 668 669
	cx->vbi.count = cx->is_50hz ? 18 : 12;
	cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
	cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
	CX18_DEBUG_INFO("Switching standard to %llx.\n",
			(unsigned long long) cx->std);

	/* Tuner */
670
	cx18_call_all(cx, core, s_std, cx->std);
671 672
	return 0;
}
673

674 675
static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
{
676
	struct cx18_open_id *id = fh2id(fh);
677 678 679 680 681
	struct cx18 *cx = id->cx;

	if (vt->index != 0)
		return -EINVAL;

682
	cx18_call_all(cx, tuner, s_tuner, vt);
683 684 685 686 687
	return 0;
}

static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
{
688
	struct cx18 *cx = fh2id(fh)->cx;
689 690 691 692

	if (vt->index != 0)
		return -EINVAL;

693
	cx18_call_all(cx, tuner, g_tuner, vt);
694 695 696 697 698 699 700

	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
		strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
		vt->type = V4L2_TUNER_RADIO;
	} else {
		strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
		vt->type = V4L2_TUNER_ANALOG_TV;
701 702
	}

703 704 705 706 707 708
	return 0;
}

static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
					struct v4l2_sliced_vbi_cap *cap)
{
709
	struct cx18 *cx = fh2id(fh)->cx;
710 711 712
	int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
	int f, l;

713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
	if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
		return -EINVAL;

	cap->service_set = 0;
	for (f = 0; f < 2; f++) {
		for (l = 0; l < 24; l++) {
			if (valid_service_line(f, l, cx->is_50hz)) {
				/*
				 * We can find all v4l2 supported vbi services
				 * for the standard, on a valid line for the std
				 */
				cap->service_lines[f][l] = set;
				cap->service_set |= set;
			} else
				cap->service_lines[f][l] = 0;
728 729
		}
	}
730 731 732
	for (f = 0; f < 3; f++)
		cap->reserved[f] = 0;
	return 0;
733
}
734

735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
static int _cx18_process_idx_data(struct cx18_buffer *buf,
				  struct v4l2_enc_idx *idx)
{
	int consumed, remaining;
	struct v4l2_enc_idx_entry *e_idx;
	struct cx18_enc_idx_entry *e_buf;

	/* Frame type lookup: 1=I, 2=P, 4=B */
	const int mapping[8] = {
		-1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P,
		-1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1
	};

	/*
	 * Assumption here is that a buf holds an integral number of
	 * struct cx18_enc_idx_entry objects and is properly aligned.
	 * This is enforced by the module options on IDX buffer sizes.
	 */
	remaining = buf->bytesused - buf->readpos;
	consumed = 0;
	e_idx = &idx->entry[idx->entries];
	e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos];

	while (remaining >= sizeof(struct cx18_enc_idx_entry) &&
	       idx->entries < V4L2_ENC_IDX_ENTRIES) {

		e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32)
				| le32_to_cpu(e_buf->offset_low);

		e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32)
			     | le32_to_cpu(e_buf->pts_low);

		e_idx->length = le32_to_cpu(e_buf->length);

		e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7];

		e_idx->reserved[0] = 0;
		e_idx->reserved[1] = 0;

		idx->entries++;
		e_idx = &idx->entry[idx->entries];
		e_buf++;

		remaining -= sizeof(struct cx18_enc_idx_entry);
		consumed += sizeof(struct cx18_enc_idx_entry);
	}

	/* Swallow any partial entries at the end, if there are any */
	if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry))
		consumed += remaining;

	buf->readpos += consumed;
	return consumed;
}

static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl,
				 struct v4l2_enc_idx *idx)
{
	if (s->type != CX18_ENC_STREAM_TYPE_IDX)
		return -EINVAL;

	if (mdl->curr_buf == NULL)
		mdl->curr_buf = list_first_entry(&mdl->buf_list,
						 struct cx18_buffer, list);

	if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
		/*
		 * For some reason we've exhausted the buffers, but the MDL
		 * object still said some data was unread.
		 * Fix that and bail out.
		 */
		mdl->readpos = mdl->bytesused;
		return 0;
	}

	list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {

		/* Skip any empty buffers in the MDL */
		if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
			continue;

		mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx);

		/* exit when MDL drained or request satisfied */
		if (idx->entries >= V4L2_ENC_IDX_ENTRIES ||
		    mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
		    mdl->readpos >= mdl->bytesused)
			break;
	}
	return 0;
}

827 828 829
static int cx18_g_enc_index(struct file *file, void *fh,
				struct v4l2_enc_idx *idx)
{
830
	struct cx18 *cx = fh2id(fh)->cx;
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
	struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
	s32 tmp;
	struct cx18_mdl *mdl;

	if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */
		return -EINVAL;

	/* Compute the best case number of entries we can buffer */
	tmp = s->buffers -
			  s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN;
	if (tmp <= 0)
		tmp = 1;
	tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry);

	/* Fill out the header of the return structure */
	idx->entries = 0;
	idx->entries_cap = tmp;
	memset(idx->reserved, 0, sizeof(idx->reserved));

	/* Pull IDX MDLs and buffers from q_full and populate the entries */
	do {
		mdl = cx18_dequeue(s, &s->q_full);
		if (mdl == NULL) /* No more IDX data right now */
			break;

		/* Extract the Index entry data from the MDL and buffers */
		cx18_process_idx_data(s, mdl, idx);
		if (mdl->readpos < mdl->bytesused) {
			/* We finished with data remaining, push the MDL back */
			cx18_push(s, mdl, &s->q_full);
			break;
		}

		/* We drained this MDL, schedule it to go to the firmware */
		cx18_enqueue(s, mdl, &s->q_free);

	} while (idx->entries < V4L2_ENC_IDX_ENTRIES);

	/* Tell the work handler to send free IDX MDLs to the firmware */
	cx18_stream_load_fw_queue(s);
	return 0;
872
}
873

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
{
	struct videobuf_queue *q = NULL;

	switch (id->vb_type) {
	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
		q = &id->vbuf_q;
		break;
	case V4L2_BUF_TYPE_VBI_CAPTURE:
		break;
	default:
		break;
	}
	return q;
}

static int cx18_streamon(struct file *file, void *priv,
	enum v4l2_buf_type type)
{
	struct cx18_open_id *id = file->private_data;
	struct cx18 *cx = id->cx;
	struct cx18_stream *s = &cx->streams[id->type];

	/* Start the hardware only if we're the video device */
	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
		return -EINVAL;

	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
		return -EINVAL;

	/* Establish a buffer timeout */
	mod_timer(&s->vb_timeout, jiffies + (HZ * 2));

	return videobuf_streamon(cx18_vb_queue(id));
}

static int cx18_streamoff(struct file *file, void *priv,
	enum v4l2_buf_type type)
{
	struct cx18_open_id *id = file->private_data;

	/* Start the hardware only if we're the video device */
	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
		return -EINVAL;

	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
		return -EINVAL;

	return videobuf_streamoff(cx18_vb_queue(id));
}

static int cx18_reqbufs(struct file *file, void *priv,
	struct v4l2_requestbuffers *rb)
{
	struct cx18_open_id *id = file->private_data;

	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
		return -EINVAL;

	return videobuf_reqbufs(cx18_vb_queue(id), rb);
}

static int cx18_querybuf(struct file *file, void *priv,
	struct v4l2_buffer *b)
{
	struct cx18_open_id *id = file->private_data;

	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
		return -EINVAL;

	return videobuf_querybuf(cx18_vb_queue(id), b);
}

static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
	struct cx18_open_id *id = file->private_data;

	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
		return -EINVAL;

	return videobuf_qbuf(cx18_vb_queue(id), b);
}

static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
	struct cx18_open_id *id = file->private_data;
	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
		return -EINVAL;

	return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
}

972 973 974
static int cx18_encoder_cmd(struct file *file, void *fh,
				struct v4l2_encoder_cmd *enc)
{
975
	struct cx18_open_id *id = fh2id(fh);
976
	struct cx18 *cx = id->cx;
977
	u32 h;
978

979 980 981 982 983 984 985 986 987 988 989
	switch (enc->cmd) {
	case V4L2_ENC_CMD_START:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
		enc->flags = 0;
		return cx18_start_capture(id);

	case V4L2_ENC_CMD_STOP:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
		cx18_stop_capture(id,
				  enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
990 991
		break;

992 993 994 995 996 997
	case V4L2_ENC_CMD_PAUSE:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
		enc->flags = 0;
		if (!atomic_read(&cx->ana_capturing))
			return -EPERM;
		if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
998
			return 0;
999 1000 1001 1002 1003 1004
		h = cx18_find_handle(cx);
		if (h == CX18_INVALID_TASK_HANDLE) {
			CX18_ERR("Can't find valid task handle for "
				 "V4L2_ENC_CMD_PAUSE\n");
			return -EBADFD;
		}
1005
		cx18_mute(cx);
1006
		cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
1007 1008 1009 1010 1011 1012 1013 1014 1015
		break;

	case V4L2_ENC_CMD_RESUME:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
		enc->flags = 0;
		if (!atomic_read(&cx->ana_capturing))
			return -EPERM;
		if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
			return 0;
1016 1017 1018 1019 1020 1021 1022
		h = cx18_find_handle(cx);
		if (h == CX18_INVALID_TASK_HANDLE) {
			CX18_ERR("Can't find valid task handle for "
				 "V4L2_ENC_CMD_RESUME\n");
			return -EBADFD;
		}
		cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
1023 1024 1025 1026 1027
		cx18_unmute(cx);
		break;

	default:
		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1028 1029
		return -EINVAL;
	}
1030 1031
	return 0;
}
1032

1033 1034 1035
static int cx18_try_encoder_cmd(struct file *file, void *fh,
				struct v4l2_encoder_cmd *enc)
{
1036
	struct cx18 *cx = fh2id(fh)->cx;
1037

1038 1039 1040 1041
	switch (enc->cmd) {
	case V4L2_ENC_CMD_START:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
		enc->flags = 0;
1042 1043
		break;

1044 1045 1046 1047
	case V4L2_ENC_CMD_STOP:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
		break;
1048

1049 1050 1051 1052
	case V4L2_ENC_CMD_PAUSE:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
		enc->flags = 0;
		break;
1053

1054 1055 1056
	case V4L2_ENC_CMD_RESUME:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
		enc->flags = 0;
1057 1058 1059
		break;

	default:
1060
		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1061 1062 1063 1064 1065
		return -EINVAL;
	}
	return 0;
}

1066
static int cx18_log_status(struct file *file, void *fh)
1067
{
1068
	struct cx18 *cx = fh2id(fh)->cx;
1069 1070 1071
	struct v4l2_input vidin;
	struct v4l2_audio audin;
	int i;
1072

1073
	CX18_INFO("=================  START STATUS CARD #%d  "
1074
		  "=================\n", cx->instance);
1075
	CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
1076 1077 1078 1079 1080
	if (cx->hw_flags & CX18_HW_TVEEPROM) {
		struct tveeprom tv;

		cx18_read_eeprom(cx, &tv);
	}
1081
	cx18_call_all(cx, core, log_status);
1082 1083 1084 1085
	cx18_get_input(cx, cx->active_input, &vidin);
	cx18_get_audio_input(cx, cx->audio_input, &audin);
	CX18_INFO("Video Input: %s\n", vidin.name);
	CX18_INFO("Audio Input: %s\n", audin.name);
1086
	mutex_lock(&cx->gpio_lock);
1087 1088
	CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
		cx->gpio_dir, cx->gpio_val);
1089
	mutex_unlock(&cx->gpio_lock);
1090 1091
	CX18_INFO("Tuner: %s\n",
		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
1092
	v4l2_ctrl_handler_log_status(&cx->cxhdl.hdl, cx->v4l2_dev.name);
1093 1094 1095 1096
	CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
	for (i = 0; i < CX18_MAX_STREAMS; i++) {
		struct cx18_stream *s = &cx->streams[i];

1097
		if (s->video_dev == NULL || s->buffers == 0)
1098 1099 1100
			continue;
		CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
			  s->name, s->s_flags,
1101 1102
			  atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
			   / s->buffers,
1103 1104 1105 1106 1107
			  (s->buffers * s->buf_size) / 1024, s->buffers);
	}
	CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
			(long long)cx->mpg_data_received,
			(long long)cx->vbi_data_inserted);
1108 1109
	CX18_INFO("==================  END STATUS CARD #%d  "
		  "==================\n", cx->instance);
1110 1111 1112
	return 0;
}

1113 1114
static long cx18_default(struct file *file, void *fh, bool valid_prio,
							int cmd, void *arg)
1115
{
1116
	struct cx18 *cx = fh2id(fh)->cx;
1117 1118

	switch (cmd) {
1119 1120 1121 1122
	case VIDIOC_INT_RESET: {
		u32 val = *(u32 *)arg;

		if ((val == 0) || (val & 0x01))
1123 1124
			cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
				     (u32) CX18_GPIO_RESET_Z8F0811);
1125 1126 1127
		break;
	}

1128
	default:
1129 1130 1131 1132 1133
		return -EINVAL;
	}
	return 0;
}

1134
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
1135 1136
		    unsigned long arg)
{
1137
	struct video_device *vfd = video_devdata(filp);
1138
	struct cx18_open_id *id = file2id(filp);
1139
	struct cx18 *cx = id->cx;
1140
	long res;
1141 1142

	mutex_lock(&cx->serialize_lock);
1143 1144 1145

	if (cx18_debug & CX18_DBGFLG_IOCTL)
		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1146
	res = video_ioctl2(filp, cmd, arg);
1147
	vfd->debug = 0;
1148 1149 1150
	mutex_unlock(&cx->serialize_lock);
	return res;
}
1151

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
	.vidioc_querycap                = cx18_querycap,
	.vidioc_s_audio                 = cx18_s_audio,
	.vidioc_g_audio                 = cx18_g_audio,
	.vidioc_enumaudio               = cx18_enumaudio,
	.vidioc_enum_input              = cx18_enum_input,
	.vidioc_cropcap                 = cx18_cropcap,
	.vidioc_s_crop                  = cx18_s_crop,
	.vidioc_g_crop                  = cx18_g_crop,
	.vidioc_g_input                 = cx18_g_input,
	.vidioc_s_input                 = cx18_s_input,
	.vidioc_g_frequency             = cx18_g_frequency,
	.vidioc_s_frequency             = cx18_s_frequency,
	.vidioc_s_tuner                 = cx18_s_tuner,
	.vidioc_g_tuner                 = cx18_g_tuner,
	.vidioc_g_enc_index             = cx18_g_enc_index,
	.vidioc_g_std                   = cx18_g_std,
	.vidioc_s_std                   = cx18_s_std,
	.vidioc_log_status              = cx18_log_status,
	.vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap,
	.vidioc_encoder_cmd             = cx18_encoder_cmd,
	.vidioc_try_encoder_cmd         = cx18_try_encoder_cmd,
	.vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap,
	.vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap,
	.vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap,
	.vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap,
	.vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap,
	.vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap,
	.vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap,
	.vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap,
	.vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap,
	.vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap,
	.vidioc_g_chip_ident            = cx18_g_chip_ident,
1185
#ifdef CONFIG_VIDEO_ADV_DEBUG
1186 1187
	.vidioc_g_register              = cx18_g_register,
	.vidioc_s_register              = cx18_s_register,
1188
#endif
1189
	.vidioc_default                 = cx18_default,
1190 1191 1192 1193 1194 1195
	.vidioc_streamon                = cx18_streamon,
	.vidioc_streamoff               = cx18_streamoff,
	.vidioc_reqbufs                 = cx18_reqbufs,
	.vidioc_querybuf                = cx18_querybuf,
	.vidioc_qbuf                    = cx18_qbuf,
	.vidioc_dqbuf                   = cx18_dqbuf,
1196 1197 1198 1199 1200
};

void cx18_set_funcs(struct video_device *vdev)
{
	vdev->ioctl_ops = &cx18_ioctl_ops;
1201
}