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

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

68 69 70 71 72 73 74
/*
 * 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
 */
75 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
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;
}

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

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

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

148 149 150 151 152
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;
153
	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
154

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

173 174 175 176
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;
177
	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
178

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

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

198
	/* sane, V4L2 spec compliant, defaults */
199 200 201 202
	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));
203 204 205 206 207 208 209
	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
	 */
210
	if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced))
211
		return -EINVAL;
212

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

221 222 223 224 225 226 227
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;
228
	int min_h = 2;
229

230
	w = min(w, 720);
231 232 233 234 235 236
	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;
	}
237
	h = min(h, cx->is_50hz ? 576 : 480);
238 239
	h = max(h, min_h);

240 241 242 243 244
	cx18_g_fmt_vid_cap(file, fh, fmt);
	fmt->fmt.pix.width = w;
	fmt->fmt.pix.height = h;
	return 0;
}
245

246 247 248 249 250 251 252 253 254
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)
{
255 256 257 258 259 260 261
	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;

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

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;
276
	struct v4l2_mbus_framefmt mbus_fmt;
277
	int ret;
278
	int w, h;
279

280
	ret = v4l2_prio_check(&cx->prio, id->prio);
281 282
	if (ret)
		return ret;
283

284 285 286
	ret = cx18_try_fmt_vid_cap(file, fh, fmt);
	if (ret)
		return ret;
287 288
	w = fmt->fmt.pix.width;
	h = fmt->fmt.pix.height;
289

290
	if (cx->params.width == w && cx->params.height == h)
291
		return 0;
292 293

	if (atomic_read(&cx->ana_capturing) > 0)
294
		return -EBUSY;
295

296 297 298 299
	mbus_fmt.width = cx->params.width = w;
	mbus_fmt.height = cx->params.height = h;
	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
300
	return cx18_g_fmt_vid_cap(file, fh, fmt);
301 302
}

303 304
static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
				struct v4l2_format *fmt)
305
{
306
	struct cx18_open_id *id = fh;
307
	struct cx18 *cx = id->cx;
308
	int ret;
309

310
	ret = v4l2_prio_check(&cx->prio, id->prio);
311 312
	if (ret)
		return ret;
313

314 315 316 317 318
	/*
	 * 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)
319
		return -EBUSY;
320

321 322 323 324 325
	/*
	 * Set the digitizer registers for raw active VBI.
	 * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid
	 * calling conditions
	 */
326
	ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi);
327 328 329 330
	if (ret)
		return ret;

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

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

345
	ret = v4l2_prio_check(&cx->prio, id->prio);
346 347 348
	if (ret)
		return ret;

349
	cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
350

351 352 353 354 355
	/*
	 * 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)
356
		return -EBUSY;
357

358 359 360 361 362
	/*
	 * 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
	 */
363
	ret = v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &fmt->fmt.sliced);
364 365 366
	if (ret)
		return ret;
	/* Store our current v4l2 sliced VBI settings */
367 368 369
	cx->vbi.in.type =  V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
	memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
	return 0;
370 371 372
}

static int cx18_g_chip_ident(struct file *file, void *fh,
373
				struct v4l2_dbg_chip_ident *chip)
374 375
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
376
	int err = 0;
377 378 379

	chip->ident = V4L2_IDENT_NONE;
	chip->revision = 0;
380 381 382 383 384 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
	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;
420
	}
421
	return err;
422 423
}

424 425 426
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
{
427
	struct v4l2_dbg_register *regs = arg;
428 429 430 431 432 433

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

434
	regs->size = 4;
435
	if (cmd == VIDIOC_DBG_S_REGISTER)
436
		cx18_write_enc(cx, regs->val, regs->reg);
437 438
	else
		regs->val = cx18_read_enc(cx, regs->reg);
439 440 441
	return 0;
}

442
static int cx18_g_register(struct file *file, void *fh,
443
				struct v4l2_dbg_register *reg)
444 445 446
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

447
	if (v4l2_chip_match_host(&reg->match))
448
		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
449 450
	/* FIXME - errors shouldn't be ignored */
	cx18_call_all(cx, core, g_register, reg);
451
	return 0;
452 453 454
}

static int cx18_s_register(struct file *file, void *fh,
455
				struct v4l2_dbg_register *reg)
456 457 458
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;

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

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);
472 473 474
	return 0;
}

475
static int cx18_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
476
{
477 478
	struct cx18_open_id *id = fh;
	struct cx18 *cx = id->cx;
479

480 481
	return v4l2_prio_change(&cx->prio, &id->prio, prio);
}
482

483 484 485 486
static int cx18_querycap(struct file *file, void *fh,
				struct v4l2_capability *vcap)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
487

488 489
	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
490 491
	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
		 "PCI:%s", pci_name(cx->pci_dev));
492 493 494 495
	vcap->version = CX18_DRIVER_VERSION; 	    /* version */
	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
	return 0;
}
496

497 498 499
static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
500

501 502
	return cx18_get_audio_input(cx, vin->index, vin);
}
503

504 505 506
static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
507

508 509 510
	vin->index = cx->audio_input;
	return cx18_get_audio_input(cx, vin->index, vin);
}
511

512 513 514
static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
515

516 517 518 519 520 521
	if (vout->index >= cx->nof_audio_inputs)
		return -EINVAL;
	cx->audio_input = vout->index;
	cx18_audio_set_io(cx);
	return 0;
}
522

523 524 525
static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
526

527 528 529
	/* set it to defaults from our table */
	return cx18_get_input(cx, vin->index, vin);
}
530

531 532 533 534
static int cx18_cropcap(struct file *file, void *fh,
			struct v4l2_cropcap *cropcap)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
535

536 537 538 539 540 541 542 543 544 545
	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;
}
546

547 548 549 550 551
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;
552

553
	ret = v4l2_prio_check(&cx->prio, id->prio);
554 555
	if (ret)
		return ret;
556

557 558
	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
559 560
	CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n");
	return -EINVAL;
561
}
562

563 564 565
static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
566

567 568
	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
569 570
	CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
	return -EINVAL;
571 572 573 574 575 576 577 578 579 580 581
}

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 }
582
		}
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
	};

	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;

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

609
	if (inp >= cx->nof_inputs)
610 611 612 613
		return -EINVAL;

	if (inp == cx->active_input) {
		CX18_DEBUG_INFO("Input unchanged\n");
614 615 616
		return 0;
	}

617 618
	CX18_DEBUG_INFO("Changing input from %d to %d\n",
			cx->active_input, inp);
619

620 621 622
	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;
623

624 625 626 627 628 629 630 631
	/* 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;
}
632

633 634 635 636
static int cx18_g_frequency(struct file *file, void *fh,
				struct v4l2_frequency *vf)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
637

638 639
	if (vf->tuner != 0)
		return -EINVAL;
640

641
	cx18_call_all(cx, tuner, g_frequency, vf);
642 643
	return 0;
}
644

645 646 647 648 649
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;
650

651
	ret = v4l2_prio_check(&cx->prio, id->prio);
652 653
	if (ret)
		return ret;
654

655 656
	if (vf->tuner != 0)
		return -EINVAL;
657

658 659
	cx18_mute(cx);
	CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
660
	cx18_call_all(cx, tuner, s_frequency, vf);
661 662 663
	cx18_unmute(cx);
	return 0;
}
664

665 666 667
static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
668

669 670 671
	*std = cx->std;
	return 0;
}
672

673 674 675 676 677
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;
678

679
	ret = v4l2_prio_check(&cx->prio, id->prio);
680 681
	if (ret)
		return ret;
682

683 684
	if ((*std & V4L2_STD_ALL) == 0)
		return -EINVAL;
685

686 687 688 689 690 691 692 693 694
	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;
695 696
	}

697 698 699 700 701 702 703 704 705 706 707 708
	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 */
709
	cx18_call_all(cx, core, s_std, cx->std);
710 711
	return 0;
}
712

713 714 715 716 717
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;
718

719
	ret = v4l2_prio_check(&cx->prio, id->prio);
720 721 722 723 724 725
	if (ret)
		return ret;

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

726
	cx18_call_all(cx, tuner, s_tuner, vt);
727 728 729 730 731 732 733 734 735 736
	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;

737
	cx18_call_all(cx, tuner, g_tuner, vt);
738 739 740 741 742 743 744

	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;
745 746
	}

747 748 749 750 751 752
	return 0;
}

static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
					struct v4l2_sliced_vbi_cap *cap)
{
753 754 755 756
	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;

757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
	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;
772 773
		}
	}
774 775 776
	for (f = 0; f < 3; f++)
		cap->reserved[f] = 0;
	return 0;
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 827 828 829 830 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
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;
}

871 872 873
static int cx18_g_enc_index(struct file *file, void *fh,
				struct v4l2_enc_idx *idx)
{
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
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
	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;
916
}
917

918 919 920 921 922
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;
923
	u32 h;
924

925 926 927 928 929 930 931 932 933 934 935
	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);
936 937
		break;

938 939 940 941 942 943
	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))
944
			return 0;
945 946 947 948 949 950
		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;
		}
951
		cx18_mute(cx);
952
		cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
953 954 955 956 957 958 959 960 961
		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;
962 963 964 965 966 967 968
		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);
969 970 971 972 973
		cx18_unmute(cx);
		break;

	default:
		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
974 975
		return -EINVAL;
	}
976 977
	return 0;
}
978

979 980 981 982
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;
983

984 985 986 987
	switch (enc->cmd) {
	case V4L2_ENC_CMD_START:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
		enc->flags = 0;
988 989
		break;

990 991 992 993
	case V4L2_ENC_CMD_STOP:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
		break;
994

995 996 997 998
	case V4L2_ENC_CMD_PAUSE:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
		enc->flags = 0;
		break;
999

1000 1001 1002
	case V4L2_ENC_CMD_RESUME:
		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
		enc->flags = 0;
1003 1004 1005
		break;

	default:
1006
		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1007 1008 1009 1010 1011
		return -EINVAL;
	}
	return 0;
}

1012
static int cx18_log_status(struct file *file, void *fh)
1013
{
1014 1015 1016 1017
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
	struct v4l2_input vidin;
	struct v4l2_audio audin;
	int i;
1018

1019
	CX18_INFO("=================  START STATUS CARD #%d  "
1020
		  "=================\n", cx->instance);
1021
	CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
1022 1023 1024 1025 1026
	if (cx->hw_flags & CX18_HW_TVEEPROM) {
		struct tveeprom tv;

		cx18_read_eeprom(cx, &tv);
	}
1027
	cx18_call_all(cx, core, log_status);
1028 1029 1030 1031
	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);
1032
	mutex_lock(&cx->gpio_lock);
1033 1034
	CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
		cx->gpio_dir, cx->gpio_val);
1035
	mutex_unlock(&cx->gpio_lock);
1036 1037
	CX18_INFO("Tuner: %s\n",
		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
1038
	cx2341x_log_status(&cx->params, cx->v4l2_dev.name);
1039 1040 1041 1042
	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];

1043
		if (s->video_dev == NULL || s->buffers == 0)
1044 1045 1046
			continue;
		CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
			  s->name, s->s_flags,
1047 1048
			  atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
			   / s->buffers,
1049 1050 1051 1052 1053
			  (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);
1054 1055
	CX18_INFO("==================  END STATUS CARD #%d  "
		  "==================\n", cx->instance);
1056 1057 1058
	return 0;
}

1059
static long cx18_default(struct file *file, void *fh, int cmd, void *arg)
1060 1061
{
	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
1062 1063

	switch (cmd) {
1064 1065 1066 1067
	case VIDIOC_INT_RESET: {
		u32 val = *(u32 *)arg;

		if ((val == 0) || (val & 0x01))
1068 1069
			cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
				     (u32) CX18_GPIO_RESET_Z8F0811);
1070 1071 1072
		break;
	}

1073
	default:
1074 1075 1076 1077 1078
		return -EINVAL;
	}
	return 0;
}

1079
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
1080 1081
		    unsigned long arg)
{
1082
	struct video_device *vfd = video_devdata(filp);
1083
	struct cx18_open_id *id = filp->private_data;
1084
	struct cx18 *cx = id->cx;
1085
	long res;
1086 1087

	mutex_lock(&cx->serialize_lock);
1088

1089 1090
	/* FIXME - consolidate v4l2_prio_check()'s here */

1091 1092
	if (cx18_debug & CX18_DBGFLG_IOCTL)
		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1093
	res = video_ioctl2(filp, cmd, arg);
1094
	vfd->debug = 0;
1095 1096 1097
	mutex_unlock(&cx->serialize_lock);
	return res;
}
1098

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
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,
1134
#ifdef CONFIG_VIDEO_ADV_DEBUG
1135 1136
	.vidioc_g_register              = cx18_g_register,
	.vidioc_s_register              = cx18_s_register,
1137
#endif
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
	.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;
1149
}