cx18-ioctl.c 26.0 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@radix.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 44
#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>
#include <linux/i2c-id.h>

45
u16 cx18_service2vbi(int type)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
{
	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;
	}
}

61
/* Check if VBI services are allowed on the (field, line) for the video std */
62 63
static int valid_service_line(int field, int line, int is_pal)
{
64 65
	return (is_pal && line >= 6 &&
		((field == 0 && line <= 23) || (field == 1 && line <= 22))) ||
66 67 68
	       (!is_pal && line >= 10 && line < 22);
}

69 70 71 72 73 74 75
/*
 * 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
 */
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
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;
}

102 103 104 105
/*
 * Expand the service_set of *fmt into valid service_lines for the std,
 * and clear the passed in fmt->service_set
 */
106
void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
107 108 109 110 111 112 113 114 115 116 117
{
	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);
	}
}

118 119 120 121
/*
 * Sanitize the service_lines in *fmt per the video std, and return 1
 * if any service_line is left as valid after santization
 */
122 123 124 125 126 127 128 129 130 131 132 133 134
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;
}
135

136
/* Compute the service_set from the assumed valid service_lines of *fmt */
137
u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
138 139 140 141 142 143 144 145 146 147 148
{
	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;
}

149 150 151 152 153
static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
154
	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
155

156 157 158 159 160
	pixfmt->width = cx->params.width;
	pixfmt->height = cx->params.height;
	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
	pixfmt->field = V4L2_FIELD_INTERLACED;
	pixfmt->priv = 0;
161
	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
162
		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
163
		/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
164 165 166 167
		pixfmt->sizeimage =
			pixfmt->height * pixfmt->width +
			pixfmt->height * (pixfmt->width / 2);
		pixfmt->bytesperline = 720;
168
	} else {
169 170 171
		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
		pixfmt->sizeimage = 128 * 1024;
		pixfmt->bytesperline = 0;
172 173 174
	}
	return 0;
}
175

176 177 178 179
static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
180
	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
181

182
	vbifmt->sampling_rate = 27000000;
183
	vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */
184
	vbifmt->samples_per_line = vbi_active_samples - 4;
185 186 187 188 189 190 191
	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;
192 193 194
	return 0;
}

195 196
static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
					struct v4l2_format *fmt)
197
{
198 199 200
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;

201
	/* sane, V4L2 spec compliant, defaults */
202 203 204 205
	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));
206 207 208 209 210 211 212 213 214
	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
	 */
	if (cx18_av_cmd(cx, VIDIOC_G_FMT, fmt))
		return -EINVAL;
215

216 217 218 219
	/* Ensure V4L2 spec compliant output */
	vbifmt->reserved[0] = 0;
	vbifmt->reserved[1] = 0;
	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
220 221
	vbifmt->service_set = cx18_get_service_set(vbifmt);
	return 0;
222
}
223

224 225 226 227 228 229 230
static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int w = fmt->fmt.pix.width;
	int h = fmt->fmt.pix.height;
231

232 233 234 235 236 237 238 239 240
	w = min(w, 720);
	w = max(w, 1);
	h = min(h, cx->is_50hz ? 576 : 480);
	h = max(h, 2);
	cx18_g_fmt_vid_cap(file, fh, fmt);
	fmt->fmt.pix.width = w;
	fmt->fmt.pix.height = h;
	return 0;
}
241

242 243 244 245 246 247 248 249 250
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)
{
251 252 253 254 255 256 257
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
	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;

258
	/* If given a service set, expand it validly & clear passed in set */
259 260
	if (vbifmt->service_set)
		cx18_expand_service_set(vbifmt, cx->is_50hz);
261 262 263
	/* 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);
264
	return 0;
265 266 267 268 269 270 271 272
}

static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int ret;
273
	int w, h;
274 275 276 277

	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;
278

279 280 281
	ret = cx18_try_fmt_vid_cap(file, fh, fmt);
	if (ret)
		return ret;
282 283
	w = fmt->fmt.pix.width;
	h = fmt->fmt.pix.height;
284

285
	if (cx->params.width == w && cx->params.height == h)
286
		return 0;
287 288

	if (atomic_read(&cx->ana_capturing) > 0)
289
		return -EBUSY;
290 291 292

	cx->params.width = w;
	cx->params.height = h;
293
	cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
294
	return cx18_g_fmt_vid_cap(file, fh, fmt);
295 296
}

297 298
static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
299
{
300
	struct cx18_open_id *id = fh;
301
	struct cx18 *cx = id->cx;
302
	int ret;
303

304 305 306
	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;
307

308 309 310 311 312
	/*
	 * 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)
313
		return -EBUSY;
314

315 316 317 318 319 320 321 322 323 324
	/*
	 * Set the digitizer registers for raw active VBI.
	 * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid
	 * calling conditions
	 */
	ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
	if (ret)
		return ret;

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

328 329 330 331 332 333
	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)
{
334 335 336 337 338 339 340 341 342
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int ret;
	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;

	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;

343
	cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
344

345 346 347 348 349
	/*
	 * 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)
350
		return -EBUSY;
351

352 353 354 355 356 357 358 359 360
	/*
	 * 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
	 */
	ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
	if (ret)
		return ret;
	/* Store our current v4l2 sliced VBI settings */
361 362 363
	cx->vbi.in.type =  V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
	memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
	return 0;
364 365 366
}

static int cx18_g_chip_ident(struct file *file, void *fh,
367
				struct v4l2_dbg_chip_ident *chip)
368 369 370 371 372
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

	chip->ident = V4L2_IDENT_NONE;
	chip->revision = 0;
373 374
	if (v4l2_chip_match_host(&chip->match)) {
		chip->ident = V4L2_IDENT_CX23418;
375
		return 0;
376
	}
377 378
	cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip);
	return 0;
379 380
}

381 382 383
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
{
384
	struct v4l2_dbg_register *regs = arg;
385 386 387 388 389 390 391 392
	unsigned long flags;

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

	spin_lock_irqsave(&cx18_cards_lock, flags);
393
	regs->size = 4;
394
	if (cmd == VIDIOC_DBG_G_REGISTER)
395
		regs->val = cx18_read_enc(cx, regs->reg);
396
	else
397
		cx18_write_enc(cx, regs->val, regs->reg);
398 399 400 401
	spin_unlock_irqrestore(&cx18_cards_lock, flags);
	return 0;
}

402
static int cx18_g_register(struct file *file, void *fh,
403
				struct v4l2_dbg_register *reg)
404 405 406
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

407
	if (v4l2_chip_match_host(&reg->match))
408
		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
409 410
	cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg);
	return 0;
411 412 413
}

static int cx18_s_register(struct file *file, void *fh,
414
				struct v4l2_dbg_register *reg)
415 416 417
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

418
	if (v4l2_chip_match_host(&reg->match))
419
		return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
420 421
	cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg);
	return 0;
422
}
423
#endif
424 425 426 427 428 429

static int cx18_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

	*p = v4l2_prio_max(&cx->prio);
430 431 432
	return 0;
}

433
static int cx18_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
434
{
435 436
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
437

438 439
	return v4l2_prio_change(&cx->prio, &id->prio, prio);
}
440

441 442 443 444
static int cx18_querycap(struct file *file, void *fh,
				struct v4l2_capability *vcap)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
445

446 447
	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
448 449
	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
		 "PCI:%s", pci_name(cx->pci_dev));
450 451 452 453
	vcap->version = CX18_DRIVER_VERSION; 	    /* version */
	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
	return 0;
}
454

455 456 457
static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
458

459 460
	return cx18_get_audio_input(cx, vin->index, vin);
}
461

462 463 464
static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
465

466 467 468
	vin->index = cx->audio_input;
	return cx18_get_audio_input(cx, vin->index, vin);
}
469

470 471 472
static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
473

474 475 476 477 478 479
	if (vout->index >= cx->nof_audio_inputs)
		return -EINVAL;
	cx->audio_input = vout->index;
	cx18_audio_set_io(cx);
	return 0;
}
480

481 482 483
static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
484

485 486 487
	/* set it to defaults from our table */
	return cx18_get_input(cx, vin->index, vin);
}
488

489 490 491 492
static int cx18_cropcap(struct file *file, void *fh,
			struct v4l2_cropcap *cropcap)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
493

494 495 496 497 498 499 500 501 502 503
	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;
}
504

505 506 507 508 509
static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int ret;
510

511 512 513
	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;
514

515 516 517 518
	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
	return cx18_av_cmd(cx, VIDIOC_S_CROP, crop);
}
519

520 521 522
static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
523

524 525 526 527 528 529 530 531 532 533 534 535 536 537
	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
	return cx18_av_cmd(cx, VIDIOC_G_CROP, crop);
}

static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
					struct v4l2_fmtdesc *fmt)
{
	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 }
538
		}
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
	};

	if (fmt->index > 1)
		return -EINVAL;
	*fmt = formats[fmt->index];
	return 0;
}

static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

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

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

	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;

	if (inp < 0 || inp >= cx->nof_inputs)
		return -EINVAL;

	if (inp == cx->active_input) {
		CX18_DEBUG_INFO("Input unchanged\n");
570 571 572
		return 0;
	}

573 574
	CX18_DEBUG_INFO("Changing input from %d to %d\n",
			cx->active_input, inp);
575

576 577 578
	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;
579

580 581 582 583 584 585 586 587
	/* 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;
}
588

589 590 591 592
static int cx18_g_frequency(struct file *file, void *fh,
				struct v4l2_frequency *vf)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
593

594 595
	if (vf->tuner != 0)
		return -EINVAL;
596

597 598 599
	cx18_call_i2c_clients(cx, VIDIOC_G_FREQUENCY, vf);
	return 0;
}
600

601 602 603 604 605
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int ret;
606

607 608 609
	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;
610

611 612
	if (vf->tuner != 0)
		return -EINVAL;
613

614 615 616 617 618 619
	cx18_mute(cx);
	CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
	cx18_call_i2c_clients(cx, VIDIOC_S_FREQUENCY, vf);
	cx18_unmute(cx);
	return 0;
}
620

621 622 623
static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
624

625 626 627
	*std = cx->std;
	return 0;
}
628

629 630 631 632 633
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int ret;
634

635 636 637
	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;
638

639 640
	if ((*std & V4L2_STD_ALL) == 0)
		return -EINVAL;
641

642 643 644 645 646 647 648 649 650
	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;
651 652
	}

653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
	cx->std = *std;
	cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
	cx->params.is_50hz = cx->is_50hz = !cx->is_60hz;
	cx->params.width = 720;
	cx->params.height = cx->is_50hz ? 576 : 480;
	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 */
	cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
	return 0;
}
668

669 670 671 672 673
static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
	int ret;
674

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
	ret = v4l2_prio_check(&cx->prio, &id->prio);
	if (ret)
		return ret;

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

	/* Setting tuner can only set audio mode */
	cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt);

	return 0;
}

static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

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

	cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);

	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;
703 704
	}

705 706 707 708 709 710
	return 0;
}

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

715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
	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;
730 731
		}
	}
732 733 734
	for (f = 0; f < 3; f++)
		cap->reserved[f] = 0;
	return 0;
735
}
736

737 738 739 740 741
static int cx18_g_enc_index(struct file *file, void *fh,
				struct v4l2_enc_idx *idx)
{
	return -EINVAL;
}
742

743 744 745 746 747
static int cx18_encoder_cmd(struct file *file, void *fh,
				struct v4l2_encoder_cmd *enc)
{
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
748
	u32 h;
749

750 751 752 753 754 755 756 757 758 759 760
	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);
761 762
		break;

763 764 765 766 767 768
	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))
769
			return 0;
770 771 772 773 774 775
		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;
		}
776
		cx18_mute(cx);
777
		cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
778 779 780 781 782 783 784 785 786
		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;
787 788 789 790 791 792 793
		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);
794 795 796 797 798
		cx18_unmute(cx);
		break;

	default:
		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
799 800
		return -EINVAL;
	}
801 802
	return 0;
}
803

804 805 806 807
static int cx18_try_encoder_cmd(struct file *file, void *fh,
				struct v4l2_encoder_cmd *enc)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
808

809 810 811 812
	switch (enc->cmd) {
	case V4L2_ENC_CMD_START:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
		enc->flags = 0;
813 814
		break;

815 816 817 818
	case V4L2_ENC_CMD_STOP:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
		break;
819

820 821 822 823
	case V4L2_ENC_CMD_PAUSE:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
		enc->flags = 0;
		break;
824

825 826 827
	case V4L2_ENC_CMD_RESUME:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
		enc->flags = 0;
828 829 830
		break;

	default:
831
		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
832 833 834 835 836
		return -EINVAL;
	}
	return 0;
}

837
static int cx18_log_status(struct file *file, void *fh)
838
{
839 840 841 842
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
	struct v4l2_input vidin;
	struct v4l2_audio audin;
	int i;
843

844 845 846
	CX18_INFO("=================  START STATUS CARD #%d  "
		  "=================\n", cx->num);
	CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
847 848 849 850 851 852 853 854 855 856
	if (cx->hw_flags & CX18_HW_TVEEPROM) {
		struct tveeprom tv;

		cx18_read_eeprom(cx, &tv);
	}
	cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL);
	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);
857
	mutex_lock(&cx->gpio_lock);
858 859
	CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
		cx->gpio_dir, cx->gpio_val);
860
	mutex_unlock(&cx->gpio_lock);
861 862 863 864 865 866 867
	CX18_INFO("Tuner: %s\n",
		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
	cx2341x_log_status(&cx->params, cx->name);
	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];

868
		if (s->video_dev == NULL || s->buffers == 0)
869 870 871
			continue;
		CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
			  s->name, s->s_flags,
872
			  atomic_read(&s->q_full.buffers) * 100 / s->buffers,
873 874 875 876 877 878 879 880 881
			  (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);
	CX18_INFO("==================  END STATUS CARD #%d  ==================\n", cx->num);
	return 0;
}

882
static long cx18_default(struct file *file, void *fh, int cmd, void *arg)
883 884
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
885 886

	switch (cmd) {
887 888
	case VIDIOC_INT_S_AUDIO_ROUTING: {
		struct v4l2_routing *route = arg;
889 890 891

		CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n",
			route->input, route->output);
892 893 894
		cx18_audio_set_route(cx, route);
		break;
	}
895 896 897 898 899 900 901 902 903

	case VIDIOC_INT_RESET: {
		u32 val = *(u32 *)arg;

		if ((val == 0) || (val & 0x01))
			cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]);
		break;
	}

904
	default:
905 906 907 908 909
		return -EINVAL;
	}
	return 0;
}

910
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
911 912
		    unsigned long arg)
{
913
	struct video_device *vfd = video_devdata(filp);
914 915
	struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
	struct cx18 *cx = id->cx;
916
	long res;
917 918

	mutex_lock(&cx->serialize_lock);
919 920 921

	if (cx18_debug & CX18_DBGFLG_IOCTL)
		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
922
	res = video_ioctl2(filp, cmd, arg);
923
	vfd->debug = 0;
924 925 926
	mutex_unlock(&cx->serialize_lock);
	return res;
}
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
static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
	.vidioc_querycap                = cx18_querycap,
	.vidioc_g_priority              = cx18_g_priority,
	.vidioc_s_priority              = cx18_s_priority,
	.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,
963
#ifdef CONFIG_VIDEO_ADV_DEBUG
964 965
	.vidioc_g_register              = cx18_g_register,
	.vidioc_s_register              = cx18_s_register,
966
#endif
967 968 969 970 971 972 973 974 975 976 977
	.vidioc_default                 = cx18_default,
	.vidioc_queryctrl               = cx18_queryctrl,
	.vidioc_querymenu               = cx18_querymenu,
	.vidioc_g_ext_ctrls             = cx18_g_ext_ctrls,
	.vidioc_s_ext_ctrls             = cx18_s_ext_ctrls,
	.vidioc_try_ext_ctrls           = cx18_try_ext_ctrls,
};

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