blob: 01215a1c4b82d8fdeb1547ae1f344da7d72b4718 [file] [log] [blame]
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001/*
2 ioctl system call
3 Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com>
4 Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "ivtv-driver.h"
22#include "ivtv-version.h"
23#include "ivtv-mailbox.h"
24#include "ivtv-i2c.h"
25#include "ivtv-queue.h"
26#include "ivtv-fileops.h"
27#include "ivtv-vbi.h"
Hans Verkuil33c0fca2007-08-23 06:32:46 -030028#include "ivtv-routing.h"
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030029#include "ivtv-streams.h"
30#include "ivtv-yuv.h"
31#include "ivtv-ioctl.h"
32#include "ivtv-gpio.h"
33#include "ivtv-controls.h"
34#include "ivtv-cards.h"
35#include <media/saa7127.h>
36#include <media/tveeprom.h>
37#include <media/v4l2-chip-ident.h>
38#include <linux/dvb/audio.h>
39#include <linux/i2c-id.h>
40
41u16 service2vbi(int type)
42{
43 switch (type) {
44 case V4L2_SLICED_TELETEXT_B:
45 return IVTV_SLICED_TYPE_TELETEXT_B;
46 case V4L2_SLICED_CAPTION_525:
47 return IVTV_SLICED_TYPE_CAPTION_525;
48 case V4L2_SLICED_WSS_625:
49 return IVTV_SLICED_TYPE_WSS_625;
50 case V4L2_SLICED_VPS:
51 return IVTV_SLICED_TYPE_VPS;
52 default:
53 return 0;
54 }
55}
56
57static int valid_service_line(int field, int line, int is_pal)
58{
59 return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
60 (!is_pal && line >= 10 && line < 22);
61}
62
63static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
64{
65 u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
66 int i;
67
68 set = set & valid_set;
69 if (set == 0 || !valid_service_line(field, line, is_pal)) {
70 return 0;
71 }
72 if (!is_pal) {
73 if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
74 return V4L2_SLICED_CAPTION_525;
75 }
76 else {
77 if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
78 return V4L2_SLICED_VPS;
79 if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
80 return V4L2_SLICED_WSS_625;
81 if (line == 23)
82 return 0;
83 }
84 for (i = 0; i < 32; i++) {
85 if ((1 << i) & set)
86 return 1 << i;
87 }
88 return 0;
89}
90
91void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
92{
93 u16 set = fmt->service_set;
94 int f, l;
95
96 fmt->service_set = 0;
97 for (f = 0; f < 2; f++) {
98 for (l = 0; l < 24; l++) {
99 fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
100 }
101 }
102}
103
104static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
105{
106 int f, l;
107 u16 set = 0;
108
109 for (f = 0; f < 2; f++) {
110 for (l = 0; l < 24; l++) {
111 fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
112 set |= fmt->service_lines[f][l];
113 }
114 }
115 return set != 0;
116}
117
118u16 get_service_set(struct v4l2_sliced_vbi_format *fmt)
119{
120 int f, l;
121 u16 set = 0;
122
123 for (f = 0; f < 2; f++) {
124 for (l = 0; l < 24; l++) {
125 set |= fmt->service_lines[f][l];
126 }
127 }
128 return set;
129}
130
131static const struct {
132 v4l2_std_id std;
133 char *name;
134} enum_stds[] = {
135 { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" },
136 { V4L2_STD_PAL_DK, "PAL-DK" },
137 { V4L2_STD_PAL_I, "PAL-I" },
138 { V4L2_STD_PAL_M, "PAL-M" },
139 { V4L2_STD_PAL_N, "PAL-N" },
140 { V4L2_STD_PAL_Nc, "PAL-Nc" },
141 { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" },
142 { V4L2_STD_SECAM_DK, "SECAM-DK" },
143 { V4L2_STD_SECAM_L, "SECAM-L" },
144 { V4L2_STD_SECAM_LC, "SECAM-L'" },
145 { V4L2_STD_NTSC_M, "NTSC-M" },
146 { V4L2_STD_NTSC_M_JP, "NTSC-J" },
147 { V4L2_STD_NTSC_M_KR, "NTSC-K" },
148};
149
150static const struct v4l2_standard ivtv_std_60hz =
151{
152 .frameperiod = {.numerator = 1001, .denominator = 30000},
153 .framelines = 525,
154};
155
156static const struct v4l2_standard ivtv_std_50hz =
157{
158 .frameperiod = {.numerator = 1, .denominator = 25},
159 .framelines = 625,
160};
161
162void ivtv_set_osd_alpha(struct ivtv *itv)
163{
164 ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
165 itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300166 ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300167}
168
169int ivtv_set_speed(struct ivtv *itv, int speed)
170{
171 u32 data[CX2341X_MBOX_MAX_DATA];
172 struct ivtv_stream *s;
173 int single_step = (speed == 1 || speed == -1);
174 DEFINE_WAIT(wait);
175
176 if (speed == 0) speed = 1000;
177
178 /* No change? */
179 if (speed == itv->speed && !single_step)
180 return 0;
181
182 s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
183
184 if (single_step && (speed < 0) == (itv->speed < 0)) {
185 /* Single step video and no need to change direction */
186 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
187 itv->speed = speed;
188 return 0;
189 }
190 if (single_step)
191 /* Need to change direction */
192 speed = speed < 0 ? -1000 : 1000;
193
194 data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
195 data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
196 data[1] = (speed < 0);
197 data[2] = speed < 0 ? 3 : 7;
198 data[3] = itv->params.video_b_frames;
199 data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
200 data[5] = 0;
201 data[6] = 0;
202
203 if (speed == 1500 || speed == -1500) data[0] |= 1;
204 else if (speed == 2000 || speed == -2000) data[0] |= 2;
205 else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
206 else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
207
208 /* If not decoding, just change speed setting */
209 if (atomic_read(&itv->decoding) > 0) {
210 int got_sig = 0;
211
212 /* Stop all DMA and decoding activity */
213 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
214
215 /* Wait for any DMA to finish */
216 prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
217 while (itv->i_flags & IVTV_F_I_DMA) {
218 got_sig = signal_pending(current);
219 if (got_sig)
220 break;
221 got_sig = 0;
222 schedule();
223 }
224 finish_wait(&itv->dma_waitq, &wait);
225 if (got_sig)
226 return -EINTR;
227
228 /* Change Speed safely */
229 ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
230 IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
231 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
232 }
233 if (single_step) {
234 speed = (speed < 0) ? -1 : 1;
235 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
236 }
237 itv->speed = speed;
238 return 0;
239}
240
241static int ivtv_validate_speed(int cur_speed, int new_speed)
242{
243 int fact = new_speed < 0 ? -1 : 1;
244 int s;
245
246 if (new_speed < 0) new_speed = -new_speed;
247 if (cur_speed < 0) cur_speed = -cur_speed;
248
249 if (cur_speed <= new_speed) {
250 if (new_speed > 1500) return fact * 2000;
251 if (new_speed > 1000) return fact * 1500;
252 }
253 else {
254 if (new_speed >= 2000) return fact * 2000;
255 if (new_speed >= 1500) return fact * 1500;
256 if (new_speed >= 1000) return fact * 1000;
257 }
258 if (new_speed == 0) return 1000;
259 if (new_speed == 1 || new_speed == 1000) return fact * new_speed;
260
261 s = new_speed;
262 new_speed = 1000 / new_speed;
263 if (1000 / cur_speed == new_speed)
264 new_speed += (cur_speed < s) ? -1 : 1;
265 if (new_speed > 60) return 1000 / (fact * 60);
266 return 1000 / (fact * new_speed);
267}
268
269static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
270 struct video_command *vc, int try)
271{
272 struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
273
274 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
275 return -EINVAL;
276
277 switch (vc->cmd) {
278 case VIDEO_CMD_PLAY: {
Hans Verkuil25415cf2007-03-10 18:29:48 -0300279 vc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300280 vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed);
281 if (vc->play.speed < 0)
282 vc->play.format = VIDEO_PLAY_FMT_GOP;
283 if (try) break;
284
285 if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
286 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300287 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
288 /* forces ivtv_set_speed to be called */
289 itv->speed = 0;
290 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300291 return ivtv_start_decoding(id, vc->play.speed);
292 }
293
294 case VIDEO_CMD_STOP:
Hans Verkuil018ba852007-04-10 18:59:09 -0300295 vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300296 if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY)
297 vc->stop.pts = 0;
298 if (try) break;
299 if (atomic_read(&itv->decoding) == 0)
300 return 0;
301 if (itv->output_mode != OUT_MPG)
302 return -EBUSY;
303
304 itv->output_mode = OUT_NONE;
305 return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts);
306
307 case VIDEO_CMD_FREEZE:
Hans Verkuil018ba852007-04-10 18:59:09 -0300308 vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300309 if (try) break;
310 if (itv->output_mode != OUT_MPG)
311 return -EBUSY;
312 if (atomic_read(&itv->decoding) > 0) {
313 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
314 (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0);
Hans Verkuilac425142007-07-22 08:46:38 -0300315 set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300316 }
317 break;
318
319 case VIDEO_CMD_CONTINUE:
Hans Verkuil25415cf2007-03-10 18:29:48 -0300320 vc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300321 if (try) break;
322 if (itv->output_mode != OUT_MPG)
323 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300324 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
325 int speed = itv->speed;
326 itv->speed = 0;
327 return ivtv_start_decoding(id, speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300328 }
329 break;
330
331 default:
332 return -EINVAL;
333 }
334 return 0;
335}
336
337static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
338{
339 struct v4l2_register *regs = arg;
340 unsigned long flags;
341 volatile u8 __iomem *reg_start;
342
343 if (!capable(CAP_SYS_ADMIN))
344 return -EPERM;
345 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
346 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
347 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
348 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
349 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
350 else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
351 reg_start = itv->enc_mem;
352 else
353 return -EINVAL;
354
355 spin_lock_irqsave(&ivtv_cards_lock, flags);
356 if (cmd == VIDIOC_DBG_G_REGISTER) {
357 regs->val = readl(regs->reg + reg_start);
358 } else {
359 writel(regs->val, regs->reg + reg_start);
360 }
361 spin_unlock_irqrestore(&ivtv_cards_lock, flags);
362 return 0;
363}
364
365static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fmt)
366{
367 switch (fmt->type) {
368 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
369 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
370 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300371 fmt->fmt.pix.width = itv->main_rect.width;
372 fmt->fmt.pix.height = itv->main_rect.height;
373 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
374 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
375 if (itv->output_mode == OUT_UDMA_YUV) {
376 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
377 case IVTV_YUV_MODE_INTERLACED:
378 fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
379 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
380 break;
381 case IVTV_YUV_MODE_PROGRESSIVE:
382 fmt->fmt.pix.field = V4L2_FIELD_NONE;
383 break;
384 default:
385 fmt->fmt.pix.field = V4L2_FIELD_ANY;
386 break;
387 }
388 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
389 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
390 fmt->fmt.pix.sizeimage =
391 fmt->fmt.pix.height * fmt->fmt.pix.width +
392 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
393 }
394 else if (itv->output_mode == OUT_YUV ||
395 streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
396 streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
397 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
398 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
399 fmt->fmt.pix.sizeimage =
400 fmt->fmt.pix.height * fmt->fmt.pix.width +
401 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
402 } else {
403 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
404 fmt->fmt.pix.sizeimage = 128 * 1024;
405 }
406 break;
407
408 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300409 fmt->fmt.pix.width = itv->params.width;
410 fmt->fmt.pix.height = itv->params.height;
411 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
412 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
413 if (streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
414 streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
415 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
416 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
417 fmt->fmt.pix.sizeimage =
418 fmt->fmt.pix.height * fmt->fmt.pix.width +
419 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
420 } else {
421 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
422 fmt->fmt.pix.sizeimage = 128 * 1024;
423 }
424 break;
425
426 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
427 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
428 return -EINVAL;
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300429 fmt->fmt.win.chromakey = itv->osd_chroma_key;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300430 fmt->fmt.win.global_alpha = itv->osd_global_alpha;
431 break;
432
433 case V4L2_BUF_TYPE_VBI_CAPTURE:
434 fmt->fmt.vbi.sampling_rate = 27000000;
435 fmt->fmt.vbi.offset = 248;
436 fmt->fmt.vbi.samples_per_line = itv->vbi.raw_decoder_line_size - 4;
437 fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
438 fmt->fmt.vbi.start[0] = itv->vbi.start[0];
439 fmt->fmt.vbi.start[1] = itv->vbi.start[1];
440 fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = itv->vbi.count;
441 break;
442
443 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
444 {
445 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
446
447 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
448 return -EINVAL;
449 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
450 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
451 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
452 if (itv->is_60hz) {
453 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
454 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
455 } else {
456 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
457 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
458 }
459 vbifmt->service_set = get_service_set(vbifmt);
460 break;
461 }
462
463 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
464 {
465 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
466
467 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
468 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
469 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
470
471 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
472 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
473 V4L2_SLICED_VBI_525;
474 expand_service_set(vbifmt, itv->is_50hz);
475 break;
476 }
477
478 itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);
479 vbifmt->service_set = get_service_set(vbifmt);
480 break;
481 }
482 case V4L2_BUF_TYPE_VBI_OUTPUT:
483 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
484 default:
485 return -EINVAL;
486 }
487 return 0;
488}
489
490static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
491 struct v4l2_format *fmt, int set_fmt)
492{
493 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
494 u16 set;
495
496 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
497 struct v4l2_rect r;
498 int field;
499
500 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
501 return -EINVAL;
502 field = fmt->fmt.pix.field;
Hans Verkuilc74e83a2007-05-17 06:41:44 -0300503 r.top = 0;
504 r.left = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300505 r.width = fmt->fmt.pix.width;
506 r.height = fmt->fmt.pix.height;
507 ivtv_get_fmt(itv, streamtype, fmt);
508 if (itv->output_mode != OUT_UDMA_YUV) {
509 /* TODO: would setting the rect also be valid for this mode? */
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300510 fmt->fmt.pix.width = r.width;
511 fmt->fmt.pix.height = r.height;
512 }
513 if (itv->output_mode == OUT_UDMA_YUV) {
514 /* TODO: add checks for validity */
515 fmt->fmt.pix.field = field;
516 }
517 if (set_fmt) {
518 if (itv->output_mode == OUT_UDMA_YUV) {
519 switch (field) {
520 case V4L2_FIELD_NONE:
521 itv->yuv_info.lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
522 break;
523 case V4L2_FIELD_ANY:
524 itv->yuv_info.lace_mode = IVTV_YUV_MODE_AUTO;
525 break;
526 case V4L2_FIELD_INTERLACED_BT:
527 itv->yuv_info.lace_mode =
528 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
529 break;
530 case V4L2_FIELD_INTERLACED_TB:
531 default:
532 itv->yuv_info.lace_mode = IVTV_YUV_MODE_INTERLACED;
533 break;
534 }
535 itv->yuv_info.lace_sync_field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
536
537 /* Force update of yuv registers */
538 itv->yuv_info.yuv_forced_update = 1;
539 return 0;
540 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300541 }
542 return 0;
543 }
544
545 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) {
546 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
547 return -EINVAL;
548 if (set_fmt) {
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300549 itv->osd_chroma_key = fmt->fmt.win.chromakey;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300550 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
551 ivtv_set_osd_alpha(itv);
552 }
553 return 0;
554 }
555
556 /* set window size */
557 if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
558 int w = fmt->fmt.pix.width;
559 int h = fmt->fmt.pix.height;
560
561 if (w > 720) w = 720;
562 else if (w < 1) w = 1;
563 if (h > (itv->is_50hz ? 576 : 480)) h = (itv->is_50hz ? 576 : 480);
564 else if (h < 2) h = 2;
565 ivtv_get_fmt(itv, streamtype, fmt);
566 fmt->fmt.pix.width = w;
567 fmt->fmt.pix.height = h;
568
569 if (!set_fmt || (itv->params.width == w && itv->params.height == h))
570 return 0;
571 if (atomic_read(&itv->capturing) > 0)
572 return -EBUSY;
573
574 itv->params.width = w;
575 itv->params.height = h;
576 if (w != 720 || h != (itv->is_50hz ? 576 : 480))
577 itv->params.video_temporal_filter = 0;
578 else
579 itv->params.video_temporal_filter = 8;
580 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
581 return ivtv_get_fmt(itv, streamtype, fmt);
582 }
583
584 /* set raw VBI format */
585 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Hans Verkuilea115d52007-08-20 16:26:40 -0300586 if (set_fmt && atomic_read(&itv->capturing) > 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300587 return -EBUSY;
588 }
589 if (set_fmt) {
590 itv->vbi.sliced_in->service_set = 0;
591 itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
592 }
593 return ivtv_get_fmt(itv, streamtype, fmt);
594 }
595
596 /* set sliced VBI output
597 In principle the user could request that only certain
598 VBI types are output and that the others are ignored.
599 I.e., suppress CC in the even fields or only output
600 WSS and no VPS. Currently though there is no choice. */
601 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
602 return ivtv_get_fmt(itv, streamtype, fmt);
603
604 /* any else but sliced VBI capture is an error */
605 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
606 return -EINVAL;
607
608 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI)
609 return ivtv_get_fmt(itv, streamtype, fmt);
610
611 /* set sliced VBI capture format */
612 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
613 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
614
615 if (vbifmt->service_set)
616 expand_service_set(vbifmt, itv->is_50hz);
617 set = check_service_set(vbifmt, itv->is_50hz);
618 vbifmt->service_set = get_service_set(vbifmt);
619
620 if (!set_fmt)
621 return 0;
622 if (set == 0)
623 return -EINVAL;
Hans Verkuilea115d52007-08-20 16:26:40 -0300624 if (atomic_read(&itv->capturing) > 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300625 return -EBUSY;
626 }
627 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
628 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
629 return 0;
630}
631
Hans Verkuild4e7ee32007-03-10 18:19:12 -0300632static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300633{
634 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
635 struct ivtv *itv = id->itv;
636 struct v4l2_register *reg = arg;
637
638 switch (cmd) {
639 /* ioctls to allow direct access to the encoder registers for testing */
640 case VIDIOC_DBG_G_REGISTER:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300641 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
642 return ivtv_itvc(itv, cmd, arg);
643 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
644 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
645 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
646
647 case VIDIOC_DBG_S_REGISTER:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300648 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
649 return ivtv_itvc(itv, cmd, arg);
650 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
651 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
652 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
653
654 case VIDIOC_G_CHIP_IDENT: {
655 struct v4l2_chip_ident *chip = arg;
656
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300657 chip->ident = V4L2_IDENT_NONE;
658 chip->revision = 0;
659 if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
660 if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {
661 struct v4l2_chip_ident *chip = arg;
662
663 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
664 }
665 return 0;
666 }
667 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
668 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
669 if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
670 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
671 return -EINVAL;
672 }
673
674 case VIDIOC_INT_S_AUDIO_ROUTING: {
675 struct v4l2_routing *route = arg;
676
Hans Verkuil33c0fca2007-08-23 06:32:46 -0300677 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300678 break;
679 }
680
Hans Verkuil2cc72092007-08-04 05:06:23 -0300681 case VIDIOC_INT_RESET: {
682 u32 val = *(u32 *)arg;
683
684 if ((val == 0 && itv->options.newi2c) || (val & 0x01)) {
685 ivtv_reset_ir_gpio(itv);
686 }
687 if (val & 0x02) {
688 itv->video_dec_func(itv, cmd, 0);
689 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300690 break;
Hans Verkuil2cc72092007-08-04 05:06:23 -0300691 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300692
693 default:
694 return -EINVAL;
695 }
696 return 0;
697}
698
699int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
700{
701 struct ivtv_open_id *id = NULL;
702
703 if (filp) id = (struct ivtv_open_id *)filp->private_data;
704
705 switch (cmd) {
Hans Verkuild46c17d2007-03-10 17:59:15 -0300706 case VIDIOC_G_PRIORITY:
707 {
708 enum v4l2_priority *p = arg;
709
710 *p = v4l2_prio_max(&itv->prio);
711 break;
712 }
713
714 case VIDIOC_S_PRIORITY:
715 {
716 enum v4l2_priority *prio = arg;
717
718 return v4l2_prio_change(&itv->prio, &id->prio, *prio);
719 }
720
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300721 case VIDIOC_QUERYCAP:{
722 struct v4l2_capability *vcap = arg;
723
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300724 memset(vcap, 0, sizeof(*vcap));
725 strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
726 strcpy(vcap->card, itv->card_name); /* card type */
727 strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
728 vcap->version = IVTV_DRIVER_VERSION; /* version */
729 vcap->capabilities = itv->v4l2_cap; /* capabilities */
730
731 /* reserved.. must set to 0! */
732 vcap->reserved[0] = vcap->reserved[1] =
733 vcap->reserved[2] = vcap->reserved[3] = 0;
734 break;
735 }
736
737 case VIDIOC_ENUMAUDIO:{
738 struct v4l2_audio *vin = arg;
739
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300740 return ivtv_get_audio_input(itv, vin->index, vin);
741 }
742
743 case VIDIOC_G_AUDIO:{
744 struct v4l2_audio *vin = arg;
745
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300746 vin->index = itv->audio_input;
747 return ivtv_get_audio_input(itv, vin->index, vin);
748 }
749
750 case VIDIOC_S_AUDIO:{
751 struct v4l2_audio *vout = arg;
752
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300753 if (vout->index >= itv->nof_audio_inputs)
754 return -EINVAL;
755 itv->audio_input = vout->index;
756 ivtv_audio_set_io(itv);
757 break;
758 }
759
760 case VIDIOC_ENUMAUDOUT:{
761 struct v4l2_audioout *vin = arg;
762
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300763 /* set it to defaults from our table */
764 return ivtv_get_audio_output(itv, vin->index, vin);
765 }
766
767 case VIDIOC_G_AUDOUT:{
768 struct v4l2_audioout *vin = arg;
769
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300770 vin->index = 0;
771 return ivtv_get_audio_output(itv, vin->index, vin);
772 }
773
774 case VIDIOC_S_AUDOUT:{
775 struct v4l2_audioout *vout = arg;
776
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300777 return ivtv_get_audio_output(itv, vout->index, vout);
778 }
779
780 case VIDIOC_ENUMINPUT:{
781 struct v4l2_input *vin = arg;
782
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300783 /* set it to defaults from our table */
784 return ivtv_get_input(itv, vin->index, vin);
785 }
786
787 case VIDIOC_ENUMOUTPUT:{
788 struct v4l2_output *vout = arg;
789
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300790 return ivtv_get_output(itv, vout->index, vout);
791 }
792
793 case VIDIOC_TRY_FMT:
794 case VIDIOC_S_FMT: {
795 struct v4l2_format *fmt = arg;
796
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300797 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);
798 }
799
800 case VIDIOC_G_FMT: {
801 struct v4l2_format *fmt = arg;
802 int type = fmt->type;
803
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300804 memset(fmt, 0, sizeof(*fmt));
805 fmt->type = type;
806 return ivtv_get_fmt(itv, id->type, fmt);
807 }
808
Hans Verkuil987e00b2007-05-29 13:03:27 -0300809 case VIDIOC_CROPCAP: {
810 struct v4l2_cropcap *cropcap = arg;
811
812 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
813 cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
814 return -EINVAL;
815 cropcap->bounds.top = cropcap->bounds.left = 0;
816 cropcap->bounds.width = 720;
817 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
818 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
819 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
820 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
821 } else {
822 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
823 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
824 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
825 }
826 cropcap->defrect = cropcap->bounds;
827 return 0;
828 }
829
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300830 case VIDIOC_S_CROP: {
831 struct v4l2_crop *crop = arg;
832
Hans Verkuil987e00b2007-05-29 13:03:27 -0300833 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
834 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
835 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
836 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
837 itv->main_rect = crop->c;
838 return 0;
839 }
840 return -EINVAL;
841 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300842 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
843 return -EINVAL;
844 return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
845 }
846
847 case VIDIOC_G_CROP: {
848 struct v4l2_crop *crop = arg;
849
Hans Verkuil987e00b2007-05-29 13:03:27 -0300850 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
851 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
852 crop->c = itv->main_rect;
853 return 0;
854 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300855 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
856 return -EINVAL;
857 return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
858 }
859
860 case VIDIOC_ENUM_FMT: {
861 static struct v4l2_fmtdesc formats[] = {
862 { 0, 0, 0,
863 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
864 { 0, 0, 0, 0 }
865 },
866 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
867 "MPEG", V4L2_PIX_FMT_MPEG,
868 { 0, 0, 0, 0 }
869 }
870 };
871 struct v4l2_fmtdesc *fmt = arg;
872 enum v4l2_buf_type type = fmt->type;
873
874 switch (type) {
875 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
876 break;
877 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
878 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
879 return -EINVAL;
880 break;
881 default:
882 return -EINVAL;
883 }
884 if (fmt->index > 1)
885 return -EINVAL;
886 *fmt = formats[fmt->index];
887 fmt->type = type;
888 return 0;
889 }
890
891 case VIDIOC_G_INPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300892 *(int *)arg = itv->active_input;
893 break;
894 }
895
896 case VIDIOC_S_INPUT:{
897 int inp = *(int *)arg;
898
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300899 if (inp < 0 || inp >= itv->nof_inputs)
900 return -EINVAL;
901
902 if (inp == itv->active_input) {
903 IVTV_DEBUG_INFO("Input unchanged\n");
904 break;
905 }
Hans Verkuil3562c432007-08-18 11:46:05 -0300906 if (atomic_read(&itv->capturing) > 0) {
907 return -EBUSY;
908 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300909 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
910 itv->active_input, inp);
911
912 itv->active_input = inp;
913 /* Set the audio input to whatever is appropriate for the
914 input type. */
915 itv->audio_input = itv->card->video_inputs[inp].audio_index;
916
917 /* prevent others from messing with the streams until
918 we're finished changing inputs. */
919 ivtv_mute(itv);
920 ivtv_video_set_io(itv);
921 ivtv_audio_set_io(itv);
922 ivtv_unmute(itv);
923 break;
924 }
925
926 case VIDIOC_G_OUTPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300927 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
928 return -EINVAL;
929 *(int *)arg = itv->active_output;
930 break;
931 }
932
933 case VIDIOC_S_OUTPUT:{
934 int outp = *(int *)arg;
935 struct v4l2_routing route;
936
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300937 if (outp >= itv->card->nof_outputs)
938 return -EINVAL;
939
940 if (outp == itv->active_output) {
941 IVTV_DEBUG_INFO("Output unchanged\n");
942 break;
943 }
944 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
945 itv->active_output, outp);
946
947 itv->active_output = outp;
948 route.input = SAA7127_INPUT_TYPE_NORMAL;
949 route.output = itv->card->video_outputs[outp].video_output;
950 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
951 break;
952 }
953
954 case VIDIOC_G_FREQUENCY:{
955 struct v4l2_frequency *vf = arg;
956
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300957 if (vf->tuner != 0)
958 return -EINVAL;
959 ivtv_call_i2c_clients(itv, cmd, arg);
960 break;
961 }
962
963 case VIDIOC_S_FREQUENCY:{
964 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
965
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300966 if (vf.tuner != 0)
967 return -EINVAL;
968
969 ivtv_mute(itv);
970 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
971 ivtv_call_i2c_clients(itv, cmd, &vf);
972 ivtv_unmute(itv);
973 break;
974 }
975
976 case VIDIOC_ENUMSTD:{
977 struct v4l2_standard *vs = arg;
978 int idx = vs->index;
979
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300980 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
981 return -EINVAL;
982
983 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
984 ivtv_std_60hz : ivtv_std_50hz;
985 vs->index = idx;
986 vs->id = enum_stds[idx].std;
987 strcpy(vs->name, enum_stds[idx].name);
988 break;
989 }
990
991 case VIDIOC_G_STD:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300992 *(v4l2_std_id *) arg = itv->std;
993 break;
994 }
995
996 case VIDIOC_S_STD: {
997 v4l2_std_id std = *(v4l2_std_id *) arg;
998
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300999 if ((std & V4L2_STD_ALL) == 0)
1000 return -EINVAL;
1001
1002 if (std == itv->std)
1003 break;
1004
1005 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1006 atomic_read(&itv->capturing) > 0 ||
1007 atomic_read(&itv->decoding) > 0) {
1008 /* Switching standard would turn off the radio or mess
1009 with already running streams, prevent that by
1010 returning EBUSY. */
1011 return -EBUSY;
1012 }
1013
1014 itv->std = std;
1015 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
1016 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1017 itv->params.width = 720;
1018 itv->params.height = itv->is_50hz ? 576 : 480;
1019 itv->vbi.count = itv->is_50hz ? 18 : 12;
1020 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1021 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1022 if (itv->hw_flags & IVTV_HW_CX25840) {
1023 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1024 }
Hans Verkuilc4385092007-06-07 09:04:03 -03001025 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001026
1027 /* Tuner */
1028 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1029
1030 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1031 /* set display standard */
1032 itv->std_out = std;
1033 itv->is_out_60hz = itv->is_60hz;
1034 itv->is_out_50hz = itv->is_50hz;
1035 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1036 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1037 itv->main_rect.left = itv->main_rect.top = 0;
1038 itv->main_rect.width = 720;
1039 itv->main_rect.height = itv->params.height;
1040 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1041 720, itv->main_rect.height, 0, 0);
1042 }
1043 break;
1044 }
1045
1046 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
1047 struct v4l2_tuner *vt = arg;
1048
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001049 if (vt->index != 0)
1050 return -EINVAL;
1051
1052 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1053 break;
1054 }
1055
1056 case VIDIOC_G_TUNER: {
1057 struct v4l2_tuner *vt = arg;
1058
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001059 if (vt->index != 0)
1060 return -EINVAL;
1061
1062 memset(vt, 0, sizeof(*vt));
1063 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1064
1065 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1066 strcpy(vt->name, "ivtv Radio Tuner");
1067 vt->type = V4L2_TUNER_RADIO;
1068 } else {
1069 strcpy(vt->name, "ivtv TV Tuner");
1070 vt->type = V4L2_TUNER_ANALOG_TV;
1071 }
1072 break;
1073 }
1074
1075 case VIDIOC_G_SLICED_VBI_CAP: {
1076 struct v4l2_sliced_vbi_cap *cap = arg;
1077 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1078 int f, l;
1079 enum v4l2_buf_type type = cap->type;
1080
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001081 memset(cap, 0, sizeof(*cap));
1082 cap->type = type;
1083 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1084 for (f = 0; f < 2; f++) {
1085 for (l = 0; l < 24; l++) {
1086 if (valid_service_line(f, l, itv->is_50hz)) {
1087 cap->service_lines[f][l] = set;
1088 }
1089 }
1090 }
1091 return 0;
1092 }
1093 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1094 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1095 return -EINVAL;
1096 if (itv->is_60hz) {
1097 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1098 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1099 } else {
1100 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1101 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1102 }
1103 return 0;
1104 }
1105 return -EINVAL;
1106 }
1107
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001108 case VIDIOC_G_ENC_INDEX: {
1109 struct v4l2_enc_idx *idx = arg;
Hans Verkuil5614b022007-08-23 17:48:41 -03001110 struct v4l2_enc_idx_entry *e = idx->entry;
1111 int entries;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001112 int i;
1113
Hans Verkuil5614b022007-08-23 17:48:41 -03001114 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001115 IVTV_MAX_PGM_INDEX;
Hans Verkuil5614b022007-08-23 17:48:41 -03001116 if (entries > V4L2_ENC_IDX_ENTRIES)
1117 entries = V4L2_ENC_IDX_ENTRIES;
1118 idx->entries = 0;
1119 for (i = 0; i < entries; i++) {
1120 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1121 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1122 idx->entries++;
1123 e++;
1124 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001125 }
1126 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1127 break;
1128 }
1129
1130 case VIDIOC_ENCODER_CMD:
1131 case VIDIOC_TRY_ENCODER_CMD: {
1132 struct v4l2_encoder_cmd *enc = arg;
1133 int try = cmd == VIDIOC_TRY_ENCODER_CMD;
1134
Hans Verkuil25415cf2007-03-10 18:29:48 -03001135 memset(&enc->raw, 0, sizeof(enc->raw));
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001136 switch (enc->cmd) {
1137 case V4L2_ENC_CMD_START:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001138 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001139 enc->flags = 0;
1140 if (try)
1141 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001142 return ivtv_start_capture(id);
1143
1144 case V4L2_ENC_CMD_STOP:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001145 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
Hans Verkuil018ba852007-04-10 18:59:09 -03001146 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001147 if (try)
1148 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001149 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1150 return 0;
1151
1152 case V4L2_ENC_CMD_PAUSE:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001153 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001154 enc->flags = 0;
1155 if (try)
1156 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001157 if (!atomic_read(&itv->capturing))
1158 return -EPERM;
1159 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1160 return 0;
1161 ivtv_mute(itv);
1162 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1163 break;
1164
1165 case V4L2_ENC_CMD_RESUME:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001166 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001167 enc->flags = 0;
1168 if (try)
1169 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001170 if (!atomic_read(&itv->capturing))
1171 return -EPERM;
1172 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1173 return 0;
1174 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1175 ivtv_unmute(itv);
1176 break;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001177 default:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001178 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
Hans Verkuil25415cf2007-03-10 18:29:48 -03001179 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001180 }
1181 break;
1182 }
1183
1184 case VIDIOC_G_FBUF: {
1185 struct v4l2_framebuffer *fb = arg;
1186
1187 memset(fb, 0, sizeof(*fb));
1188 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001189 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001190 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1191 V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_GLOBAL_ALPHA;
1192 fb->fmt.pixelformat = itv->osd_pixelformat;
1193 fb->fmt.width = itv->osd_rect.width;
1194 fb->fmt.height = itv->osd_rect.height;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001195 fb->base = (void *)itv->osd_video_pbase;
1196 if (itv->osd_global_alpha_state)
1197 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1198 if (itv->osd_local_alpha_state)
1199 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001200 if (itv->osd_chroma_key_state)
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001201 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
1202 break;
1203 }
1204
1205 case VIDIOC_S_FBUF: {
1206 struct v4l2_framebuffer *fb = arg;
1207
1208 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001209 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001210 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1211 itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001212 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
Hans Verkuilc3624f92007-07-31 07:15:56 -03001213 ivtv_set_osd_alpha(itv);
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001214 break;
1215 }
1216
Hans Verkuil7c03a442007-08-19 18:59:42 -03001217 case VIDIOC_OVERLAY: {
1218 int *on = arg;
1219
1220 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1221 return -EINVAL;
1222 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
1223 break;
1224 }
1225
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001226 case VIDIOC_LOG_STATUS:
1227 {
1228 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001229 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001230 struct v4l2_input vidin;
1231 struct v4l2_audio audin;
1232 int i;
1233
1234 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
Hans Verkuil94104aa2007-08-04 04:56:00 -03001235 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001236 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1237 struct tveeprom tv;
1238
1239 ivtv_read_eeprom(itv, &tv);
1240 }
1241 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1242 ivtv_get_input(itv, itv->active_input, &vidin);
1243 ivtv_get_audio_input(itv, itv->audio_input, &audin);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001244 IVTV_INFO("Video Input: %s\n", vidin.name);
1245 IVTV_INFO("Audio Input: %s%s\n", audin.name,
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001246 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001247 if (has_output) {
1248 struct v4l2_output vidout;
1249 struct v4l2_audioout audout;
1250 int mode = itv->output_mode;
1251 static const char * const output_modes[] = {
1252 "None",
1253 "MPEG Streaming",
1254 "YUV Streaming",
1255 "YUV Frames",
1256 "Passthrough",
1257 };
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001258 static const char * const audio_modes[] = {
1259 "Stereo",
1260 "Left",
1261 "Right",
1262 "Mono",
1263 "Swapped"
1264 };
Hans Verkuil7c03a442007-08-19 18:59:42 -03001265 static const char * const alpha_mode[] = {
1266 "None",
1267 "Global",
1268 "Local",
1269 "Global and Local"
1270 };
1271 static const char * const pixel_format[] = {
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001272 "RGB Indexed",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001273 "RGB 5:6:5",
1274 "ARGB 1:5:5:5",
1275 "ARGB 1:4:4:4",
1276 "ARGB 8:8:8:8",
1277 "5",
1278 "6",
1279 "7",
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001280 "YUV Indexed",
1281 "YUV 5:6:5",
1282 "AYUV 1:5:5:5",
1283 "AYUV 1:4:4:4",
1284 "AYUV 8:8:8:8",
1285 "13",
1286 "14",
1287 "15",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001288 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001289
1290 ivtv_get_output(itv, itv->active_output, &vidout);
1291 ivtv_get_audio_output(itv, 0, &audout);
1292 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001293 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1294 audio_modes[itv->audio_stereo_mode],
1295 audio_modes[itv->audio_bilingual_mode]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001296 if (mode < 0 || mode > OUT_PASSTHROUGH)
1297 mode = OUT_NONE;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001298 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1299 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001300 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001301 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1302 data[0] & 1 ? "On" : "Off",
1303 alpha_mode[(data[0] >> 1) & 0x3],
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001304 pixel_format[(data[0] >> 3) & 0xf]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001305 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001306 IVTV_INFO("Tuner: %s\n",
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001307 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1308 cx2341x_log_status(&itv->params, itv->name);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001309 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001310 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1311 struct ivtv_stream *s = &itv->streams[i];
1312
1313 if (s->v4l2dev == NULL || s->buffers == 0)
1314 continue;
1315 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1316 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1317 (s->buffers * s->buf_size) / 1024, s->buffers);
1318 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001319 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001320 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1321 break;
1322 }
1323
1324 default:
1325 return -EINVAL;
1326 }
1327 return 0;
1328}
1329
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001330static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001331{
1332 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1333 struct ivtv *itv = id->itv;
1334 int nonblocking = filp->f_flags & O_NONBLOCK;
1335 struct ivtv_stream *s = &itv->streams[id->type];
1336
1337 switch (cmd) {
1338 case IVTV_IOC_DMA_FRAME: {
1339 struct ivtv_dma_frame *args = arg;
1340
1341 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1342 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1343 return -EINVAL;
1344 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1345 return -EINVAL;
1346 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1347 return 0;
1348 if (ivtv_claim_stream(id, id->type)) {
1349 return -EBUSY;
1350 }
1351 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1352 ivtv_release_stream(s);
1353 return -EBUSY;
1354 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001355 /* Mark that this file handle started the UDMA_YUV mode */
1356 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001357 if (args->y_source == NULL)
1358 return 0;
1359 return ivtv_yuv_prep_frame(itv, args);
1360 }
1361
1362 case VIDEO_GET_PTS: {
1363 u32 data[CX2341X_MBOX_MAX_DATA];
1364 u64 *pts = arg;
1365
1366 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1367 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1368 *pts = s->dma_pts;
1369 break;
1370 }
1371 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1372 return -EINVAL;
1373
1374 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1375 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1376 (u64)itv->last_dec_timing[1];
1377 break;
1378 }
1379 *pts = 0;
1380 if (atomic_read(&itv->decoding)) {
1381 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1382 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1383 return -EIO;
1384 }
1385 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1386 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1387 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1388 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1389 }
1390 break;
1391 }
1392
1393 case VIDEO_GET_FRAME_COUNT: {
1394 u32 data[CX2341X_MBOX_MAX_DATA];
1395 u64 *frame = arg;
1396
1397 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1398 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1399 *frame = 0;
1400 break;
1401 }
1402 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1403 return -EINVAL;
1404
1405 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1406 *frame = itv->last_dec_timing[0];
1407 break;
1408 }
1409 *frame = 0;
1410 if (atomic_read(&itv->decoding)) {
1411 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1412 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1413 return -EIO;
1414 }
1415 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1416 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1417 *frame = data[0];
1418 }
1419 break;
1420 }
1421
1422 case VIDEO_PLAY: {
1423 struct video_command vc;
1424
1425 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1426 memset(&vc, 0, sizeof(vc));
1427 vc.cmd = VIDEO_CMD_PLAY;
1428 return ivtv_video_command(itv, id, &vc, 0);
1429 }
1430
1431 case VIDEO_STOP: {
1432 struct video_command vc;
1433
1434 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1435 memset(&vc, 0, sizeof(vc));
1436 vc.cmd = VIDEO_CMD_STOP;
1437 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1438 return ivtv_video_command(itv, id, &vc, 0);
1439 }
1440
1441 case VIDEO_FREEZE: {
1442 struct video_command vc;
1443
1444 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1445 memset(&vc, 0, sizeof(vc));
1446 vc.cmd = VIDEO_CMD_FREEZE;
1447 return ivtv_video_command(itv, id, &vc, 0);
1448 }
1449
1450 case VIDEO_CONTINUE: {
1451 struct video_command vc;
1452
1453 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1454 memset(&vc, 0, sizeof(vc));
1455 vc.cmd = VIDEO_CMD_CONTINUE;
1456 return ivtv_video_command(itv, id, &vc, 0);
1457 }
1458
1459 case VIDEO_COMMAND:
1460 case VIDEO_TRY_COMMAND: {
1461 struct video_command *vc = arg;
1462 int try = (cmd == VIDEO_TRY_COMMAND);
1463
1464 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001465 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001466 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001467 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001468 return ivtv_video_command(itv, id, vc, try);
1469 }
1470
1471 case VIDEO_GET_EVENT: {
1472 struct video_event *ev = arg;
1473 DEFINE_WAIT(wait);
1474
1475 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1476 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1477 return -EINVAL;
1478 memset(ev, 0, sizeof(*ev));
1479 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1480
1481 while (1) {
1482 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1483 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1484 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1485 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001486 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1487 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1488 if (itv->output_mode == OUT_UDMA_YUV &&
1489 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1490 IVTV_YUV_MODE_PROGRESSIVE) {
1491 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1492 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001493 }
1494 if (ev->type)
1495 return 0;
1496 if (nonblocking)
1497 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001498 /* Wait for event. Note that serialize_lock is locked,
1499 so to allow other processes to access the driver while
1500 we are waiting unlock first and later lock again. */
1501 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001502 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1503 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1504 schedule();
1505 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001506 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001507 if (signal_pending(current)) {
1508 /* return if a signal was received */
1509 IVTV_DEBUG_INFO("User stopped wait for event\n");
1510 return -EINTR;
1511 }
1512 }
1513 break;
1514 }
1515
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001516 default:
1517 return -EINVAL;
1518 }
1519 return 0;
1520}
1521
1522static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1523 unsigned int cmd, void *arg)
1524{
1525 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1526 struct ivtv *itv = id->itv;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001527 int ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001528
Hans Verkuild46c17d2007-03-10 17:59:15 -03001529 /* check priority */
1530 switch (cmd) {
1531 case VIDIOC_S_CTRL:
1532 case VIDIOC_S_STD:
1533 case VIDIOC_S_INPUT:
1534 case VIDIOC_S_OUTPUT:
1535 case VIDIOC_S_TUNER:
1536 case VIDIOC_S_FREQUENCY:
1537 case VIDIOC_S_FMT:
1538 case VIDIOC_S_CROP:
1539 case VIDIOC_S_AUDIO:
1540 case VIDIOC_S_AUDOUT:
1541 case VIDIOC_S_EXT_CTRLS:
1542 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001543 case VIDIOC_OVERLAY:
Hans Verkuild46c17d2007-03-10 17:59:15 -03001544 ret = v4l2_prio_check(&itv->prio, &id->prio);
1545 if (ret)
1546 return ret;
1547 }
1548
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001549 switch (cmd) {
1550 case VIDIOC_DBG_G_REGISTER:
1551 case VIDIOC_DBG_S_REGISTER:
1552 case VIDIOC_G_CHIP_IDENT:
1553 case VIDIOC_INT_S_AUDIO_ROUTING:
1554 case VIDIOC_INT_RESET:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001555 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1556 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1557 v4l_printk_ioctl(cmd);
1558 }
1559 return ivtv_debug_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001560
Hans Verkuild46c17d2007-03-10 17:59:15 -03001561 case VIDIOC_G_PRIORITY:
1562 case VIDIOC_S_PRIORITY:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001563 case VIDIOC_QUERYCAP:
1564 case VIDIOC_ENUMINPUT:
1565 case VIDIOC_G_INPUT:
1566 case VIDIOC_S_INPUT:
1567 case VIDIOC_ENUMOUTPUT:
1568 case VIDIOC_G_OUTPUT:
1569 case VIDIOC_S_OUTPUT:
1570 case VIDIOC_G_FMT:
1571 case VIDIOC_S_FMT:
1572 case VIDIOC_TRY_FMT:
1573 case VIDIOC_ENUM_FMT:
Hans Verkuil987e00b2007-05-29 13:03:27 -03001574 case VIDIOC_CROPCAP:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001575 case VIDIOC_G_CROP:
1576 case VIDIOC_S_CROP:
1577 case VIDIOC_G_FREQUENCY:
1578 case VIDIOC_S_FREQUENCY:
1579 case VIDIOC_ENUMSTD:
1580 case VIDIOC_G_STD:
1581 case VIDIOC_S_STD:
1582 case VIDIOC_S_TUNER:
1583 case VIDIOC_G_TUNER:
1584 case VIDIOC_ENUMAUDIO:
1585 case VIDIOC_S_AUDIO:
1586 case VIDIOC_G_AUDIO:
1587 case VIDIOC_ENUMAUDOUT:
1588 case VIDIOC_S_AUDOUT:
1589 case VIDIOC_G_AUDOUT:
1590 case VIDIOC_G_SLICED_VBI_CAP:
1591 case VIDIOC_LOG_STATUS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001592 case VIDIOC_G_ENC_INDEX:
1593 case VIDIOC_ENCODER_CMD:
1594 case VIDIOC_TRY_ENCODER_CMD:
1595 case VIDIOC_G_FBUF:
1596 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001597 case VIDIOC_OVERLAY:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001598 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1599 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1600 v4l_printk_ioctl(cmd);
1601 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001602 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1603
1604 case VIDIOC_QUERYMENU:
1605 case VIDIOC_QUERYCTRL:
1606 case VIDIOC_S_CTRL:
1607 case VIDIOC_G_CTRL:
1608 case VIDIOC_S_EXT_CTRLS:
1609 case VIDIOC_G_EXT_CTRLS:
1610 case VIDIOC_TRY_EXT_CTRLS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001611 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1612 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1613 v4l_printk_ioctl(cmd);
1614 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001615 return ivtv_control_ioctls(itv, cmd, arg);
1616
1617 case IVTV_IOC_DMA_FRAME:
1618 case VIDEO_GET_PTS:
1619 case VIDEO_GET_FRAME_COUNT:
1620 case VIDEO_GET_EVENT:
1621 case VIDEO_PLAY:
1622 case VIDEO_STOP:
1623 case VIDEO_FREEZE:
1624 case VIDEO_CONTINUE:
1625 case VIDEO_COMMAND:
1626 case VIDEO_TRY_COMMAND:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001627 return ivtv_decoder_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001628
1629 case 0x00005401: /* Handle isatty() calls */
1630 return -EINVAL;
1631 default:
1632 return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
1633 ivtv_v4l2_do_ioctl);
1634 }
1635 return 0;
1636}
1637
Hans Verkuilbaa40722007-08-19 07:10:55 -03001638static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1639 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001640{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001641 /* Filter dvb ioctls that cannot be handled by video_usercopy */
1642 switch (cmd) {
1643 case VIDEO_SELECT_SOURCE:
1644 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1645 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1646 return -EINVAL;
1647 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1648
1649 case AUDIO_SET_MUTE:
1650 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1651 itv->speed_mute_audio = arg;
1652 return 0;
1653
1654 case AUDIO_CHANNEL_SELECT:
1655 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1656 if (arg > AUDIO_STEREO_SWAPPED)
1657 return -EINVAL;
1658 itv->audio_stereo_mode = arg;
1659 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1660 return 0;
1661
1662 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1663 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1664 if (arg > AUDIO_STEREO_SWAPPED)
1665 return -EINVAL;
1666 itv->audio_bilingual_mode = arg;
1667 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1668 return 0;
1669
1670 default:
1671 break;
1672 }
1673 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
1674}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001675
1676int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1677 unsigned long arg)
1678{
1679 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1680 struct ivtv *itv = id->itv;
1681 int res;
1682
1683 mutex_lock(&itv->serialize_lock);
1684 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1685 mutex_unlock(&itv->serialize_lock);
1686 return res;
1687}