blob: 6d24c6b9a45b7c8e3f13306fc000c79ddf961f5f [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;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -0300702 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300703
704 if (filp) id = (struct ivtv_open_id *)filp->private_data;
705
706 switch (cmd) {
Hans Verkuild46c17d2007-03-10 17:59:15 -0300707 case VIDIOC_G_PRIORITY:
708 {
709 enum v4l2_priority *p = arg;
710
711 *p = v4l2_prio_max(&itv->prio);
712 break;
713 }
714
715 case VIDIOC_S_PRIORITY:
716 {
717 enum v4l2_priority *prio = arg;
718
719 return v4l2_prio_change(&itv->prio, &id->prio, *prio);
720 }
721
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300722 case VIDIOC_QUERYCAP:{
723 struct v4l2_capability *vcap = arg;
724
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300725 memset(vcap, 0, sizeof(*vcap));
726 strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
727 strcpy(vcap->card, itv->card_name); /* card type */
728 strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
729 vcap->version = IVTV_DRIVER_VERSION; /* version */
730 vcap->capabilities = itv->v4l2_cap; /* capabilities */
731
732 /* reserved.. must set to 0! */
733 vcap->reserved[0] = vcap->reserved[1] =
734 vcap->reserved[2] = vcap->reserved[3] = 0;
735 break;
736 }
737
738 case VIDIOC_ENUMAUDIO:{
739 struct v4l2_audio *vin = arg;
740
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300741 return ivtv_get_audio_input(itv, vin->index, vin);
742 }
743
744 case VIDIOC_G_AUDIO:{
745 struct v4l2_audio *vin = arg;
746
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300747 vin->index = itv->audio_input;
748 return ivtv_get_audio_input(itv, vin->index, vin);
749 }
750
751 case VIDIOC_S_AUDIO:{
752 struct v4l2_audio *vout = arg;
753
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300754 if (vout->index >= itv->nof_audio_inputs)
755 return -EINVAL;
756 itv->audio_input = vout->index;
757 ivtv_audio_set_io(itv);
758 break;
759 }
760
761 case VIDIOC_ENUMAUDOUT:{
762 struct v4l2_audioout *vin = arg;
763
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300764 /* set it to defaults from our table */
765 return ivtv_get_audio_output(itv, vin->index, vin);
766 }
767
768 case VIDIOC_G_AUDOUT:{
769 struct v4l2_audioout *vin = arg;
770
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300771 vin->index = 0;
772 return ivtv_get_audio_output(itv, vin->index, vin);
773 }
774
775 case VIDIOC_S_AUDOUT:{
776 struct v4l2_audioout *vout = arg;
777
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300778 return ivtv_get_audio_output(itv, vout->index, vout);
779 }
780
781 case VIDIOC_ENUMINPUT:{
782 struct v4l2_input *vin = arg;
783
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300784 /* set it to defaults from our table */
785 return ivtv_get_input(itv, vin->index, vin);
786 }
787
788 case VIDIOC_ENUMOUTPUT:{
789 struct v4l2_output *vout = arg;
790
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300791 return ivtv_get_output(itv, vout->index, vout);
792 }
793
794 case VIDIOC_TRY_FMT:
795 case VIDIOC_S_FMT: {
796 struct v4l2_format *fmt = arg;
797
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300798 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);
799 }
800
801 case VIDIOC_G_FMT: {
802 struct v4l2_format *fmt = arg;
803 int type = fmt->type;
804
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300805 memset(fmt, 0, sizeof(*fmt));
806 fmt->type = type;
807 return ivtv_get_fmt(itv, id->type, fmt);
808 }
809
Hans Verkuil987e00b2007-05-29 13:03:27 -0300810 case VIDIOC_CROPCAP: {
811 struct v4l2_cropcap *cropcap = arg;
812
813 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
814 cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
815 return -EINVAL;
816 cropcap->bounds.top = cropcap->bounds.left = 0;
817 cropcap->bounds.width = 720;
818 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
819 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
820 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
821 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
822 } else {
823 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
824 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
825 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
826 }
827 cropcap->defrect = cropcap->bounds;
828 return 0;
829 }
830
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300831 case VIDIOC_S_CROP: {
832 struct v4l2_crop *crop = arg;
833
Hans Verkuil987e00b2007-05-29 13:03:27 -0300834 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
835 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
836 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
837 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
838 itv->main_rect = crop->c;
839 return 0;
840 }
841 return -EINVAL;
842 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300843 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
844 return -EINVAL;
845 return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
846 }
847
848 case VIDIOC_G_CROP: {
849 struct v4l2_crop *crop = arg;
850
Hans Verkuil987e00b2007-05-29 13:03:27 -0300851 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
852 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
853 crop->c = itv->main_rect;
854 return 0;
855 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300856 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
857 return -EINVAL;
858 return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
859 }
860
861 case VIDIOC_ENUM_FMT: {
862 static struct v4l2_fmtdesc formats[] = {
863 { 0, 0, 0,
864 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
865 { 0, 0, 0, 0 }
866 },
867 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
868 "MPEG", V4L2_PIX_FMT_MPEG,
869 { 0, 0, 0, 0 }
870 }
871 };
872 struct v4l2_fmtdesc *fmt = arg;
873 enum v4l2_buf_type type = fmt->type;
874
875 switch (type) {
876 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
877 break;
878 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
879 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
880 return -EINVAL;
881 break;
882 default:
883 return -EINVAL;
884 }
885 if (fmt->index > 1)
886 return -EINVAL;
887 *fmt = formats[fmt->index];
888 fmt->type = type;
889 return 0;
890 }
891
892 case VIDIOC_G_INPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300893 *(int *)arg = itv->active_input;
894 break;
895 }
896
897 case VIDIOC_S_INPUT:{
898 int inp = *(int *)arg;
899
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300900 if (inp < 0 || inp >= itv->nof_inputs)
901 return -EINVAL;
902
903 if (inp == itv->active_input) {
904 IVTV_DEBUG_INFO("Input unchanged\n");
905 break;
906 }
Hans Verkuil3562c432007-08-18 11:46:05 -0300907 if (atomic_read(&itv->capturing) > 0) {
908 return -EBUSY;
909 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300910 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
911 itv->active_input, inp);
912
913 itv->active_input = inp;
914 /* Set the audio input to whatever is appropriate for the
915 input type. */
916 itv->audio_input = itv->card->video_inputs[inp].audio_index;
917
918 /* prevent others from messing with the streams until
919 we're finished changing inputs. */
920 ivtv_mute(itv);
921 ivtv_video_set_io(itv);
922 ivtv_audio_set_io(itv);
923 ivtv_unmute(itv);
924 break;
925 }
926
927 case VIDIOC_G_OUTPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300928 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
929 return -EINVAL;
930 *(int *)arg = itv->active_output;
931 break;
932 }
933
934 case VIDIOC_S_OUTPUT:{
935 int outp = *(int *)arg;
936 struct v4l2_routing route;
937
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300938 if (outp >= itv->card->nof_outputs)
939 return -EINVAL;
940
941 if (outp == itv->active_output) {
942 IVTV_DEBUG_INFO("Output unchanged\n");
943 break;
944 }
945 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
946 itv->active_output, outp);
947
948 itv->active_output = outp;
949 route.input = SAA7127_INPUT_TYPE_NORMAL;
950 route.output = itv->card->video_outputs[outp].video_output;
951 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
952 break;
953 }
954
955 case VIDIOC_G_FREQUENCY:{
956 struct v4l2_frequency *vf = arg;
957
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300958 if (vf->tuner != 0)
959 return -EINVAL;
960 ivtv_call_i2c_clients(itv, cmd, arg);
961 break;
962 }
963
964 case VIDIOC_S_FREQUENCY:{
965 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
966
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300967 if (vf.tuner != 0)
968 return -EINVAL;
969
970 ivtv_mute(itv);
971 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
972 ivtv_call_i2c_clients(itv, cmd, &vf);
973 ivtv_unmute(itv);
974 break;
975 }
976
977 case VIDIOC_ENUMSTD:{
978 struct v4l2_standard *vs = arg;
979 int idx = vs->index;
980
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300981 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
982 return -EINVAL;
983
984 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
985 ivtv_std_60hz : ivtv_std_50hz;
986 vs->index = idx;
987 vs->id = enum_stds[idx].std;
988 strcpy(vs->name, enum_stds[idx].name);
989 break;
990 }
991
992 case VIDIOC_G_STD:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300993 *(v4l2_std_id *) arg = itv->std;
994 break;
995 }
996
997 case VIDIOC_S_STD: {
998 v4l2_std_id std = *(v4l2_std_id *) arg;
999
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001000 if ((std & V4L2_STD_ALL) == 0)
1001 return -EINVAL;
1002
1003 if (std == itv->std)
1004 break;
1005
1006 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1007 atomic_read(&itv->capturing) > 0 ||
1008 atomic_read(&itv->decoding) > 0) {
1009 /* Switching standard would turn off the radio or mess
1010 with already running streams, prevent that by
1011 returning EBUSY. */
1012 return -EBUSY;
1013 }
1014
1015 itv->std = std;
1016 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
1017 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1018 itv->params.width = 720;
1019 itv->params.height = itv->is_50hz ? 576 : 480;
1020 itv->vbi.count = itv->is_50hz ? 18 : 12;
1021 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1022 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1023 if (itv->hw_flags & IVTV_HW_CX25840) {
1024 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1025 }
Hans Verkuilc4385092007-06-07 09:04:03 -03001026 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001027
1028 /* Tuner */
1029 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1030
1031 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1032 /* set display standard */
1033 itv->std_out = std;
1034 itv->is_out_60hz = itv->is_60hz;
1035 itv->is_out_50hz = itv->is_50hz;
1036 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1037 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1038 itv->main_rect.left = itv->main_rect.top = 0;
1039 itv->main_rect.width = 720;
1040 itv->main_rect.height = itv->params.height;
1041 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1042 720, itv->main_rect.height, 0, 0);
1043 }
1044 break;
1045 }
1046
1047 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
1048 struct v4l2_tuner *vt = arg;
1049
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001050 if (vt->index != 0)
1051 return -EINVAL;
1052
1053 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1054 break;
1055 }
1056
1057 case VIDIOC_G_TUNER: {
1058 struct v4l2_tuner *vt = arg;
1059
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001060 if (vt->index != 0)
1061 return -EINVAL;
1062
1063 memset(vt, 0, sizeof(*vt));
1064 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1065
1066 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1067 strcpy(vt->name, "ivtv Radio Tuner");
1068 vt->type = V4L2_TUNER_RADIO;
1069 } else {
1070 strcpy(vt->name, "ivtv TV Tuner");
1071 vt->type = V4L2_TUNER_ANALOG_TV;
1072 }
1073 break;
1074 }
1075
1076 case VIDIOC_G_SLICED_VBI_CAP: {
1077 struct v4l2_sliced_vbi_cap *cap = arg;
1078 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1079 int f, l;
1080 enum v4l2_buf_type type = cap->type;
1081
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001082 memset(cap, 0, sizeof(*cap));
1083 cap->type = type;
1084 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1085 for (f = 0; f < 2; f++) {
1086 for (l = 0; l < 24; l++) {
1087 if (valid_service_line(f, l, itv->is_50hz)) {
1088 cap->service_lines[f][l] = set;
1089 }
1090 }
1091 }
1092 return 0;
1093 }
1094 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1095 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1096 return -EINVAL;
1097 if (itv->is_60hz) {
1098 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1099 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1100 } else {
1101 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1102 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1103 }
1104 return 0;
1105 }
1106 return -EINVAL;
1107 }
1108
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001109 case VIDIOC_G_ENC_INDEX: {
1110 struct v4l2_enc_idx *idx = arg;
Hans Verkuil5614b022007-08-23 17:48:41 -03001111 struct v4l2_enc_idx_entry *e = idx->entry;
1112 int entries;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001113 int i;
1114
Hans Verkuil5614b022007-08-23 17:48:41 -03001115 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001116 IVTV_MAX_PGM_INDEX;
Hans Verkuil5614b022007-08-23 17:48:41 -03001117 if (entries > V4L2_ENC_IDX_ENTRIES)
1118 entries = V4L2_ENC_IDX_ENTRIES;
1119 idx->entries = 0;
1120 for (i = 0; i < entries; i++) {
1121 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1122 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1123 idx->entries++;
1124 e++;
1125 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001126 }
1127 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1128 break;
1129 }
1130
1131 case VIDIOC_ENCODER_CMD:
1132 case VIDIOC_TRY_ENCODER_CMD: {
1133 struct v4l2_encoder_cmd *enc = arg;
1134 int try = cmd == VIDIOC_TRY_ENCODER_CMD;
1135
Hans Verkuil25415cf2007-03-10 18:29:48 -03001136 memset(&enc->raw, 0, sizeof(enc->raw));
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001137 switch (enc->cmd) {
1138 case V4L2_ENC_CMD_START:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001139 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001140 enc->flags = 0;
1141 if (try)
1142 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001143 return ivtv_start_capture(id);
1144
1145 case V4L2_ENC_CMD_STOP:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001146 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
Hans Verkuil018ba852007-04-10 18:59:09 -03001147 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001148 if (try)
1149 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001150 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1151 return 0;
1152
1153 case V4L2_ENC_CMD_PAUSE:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001154 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001155 enc->flags = 0;
1156 if (try)
1157 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001158 if (!atomic_read(&itv->capturing))
1159 return -EPERM;
1160 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1161 return 0;
1162 ivtv_mute(itv);
1163 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1164 break;
1165
1166 case V4L2_ENC_CMD_RESUME:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001167 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001168 enc->flags = 0;
1169 if (try)
1170 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001171 if (!atomic_read(&itv->capturing))
1172 return -EPERM;
1173 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1174 return 0;
1175 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1176 ivtv_unmute(itv);
1177 break;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001178 default:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001179 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
Hans Verkuil25415cf2007-03-10 18:29:48 -03001180 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001181 }
1182 break;
1183 }
1184
1185 case VIDIOC_G_FBUF: {
1186 struct v4l2_framebuffer *fb = arg;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001187 int pixfmt;
1188 static u32 pixel_format[16] = {
1189 V4L2_PIX_FMT_RGB332, /* Really RGB Indexed */
1190 V4L2_PIX_FMT_RGB565,
1191 V4L2_PIX_FMT_RGB555,
1192 V4L2_PIX_FMT_RGB444,
1193 V4L2_PIX_FMT_RGB32,
1194 0,
1195 0,
1196 0,
1197 /* Really YUV variants */
1198 V4L2_PIX_FMT_RGB332, /* Really YUV Indexed */
1199 V4L2_PIX_FMT_RGB565,
1200 V4L2_PIX_FMT_RGB555,
1201 V4L2_PIX_FMT_RGB444,
1202 V4L2_PIX_FMT_RGB32,
1203 0,
1204 0,
1205 0,
1206 };
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001207
1208 memset(fb, 0, sizeof(*fb));
1209 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001210 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001211 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001212 V4L2_FBUF_CAP_GLOBAL_ALPHA;
1213 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1214 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1215 pixfmt = (data[0] >> 3) & 0xf;
1216 fb->fmt.pixelformat = pixel_format[pixfmt];
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001217 fb->fmt.width = itv->osd_rect.width;
1218 fb->fmt.height = itv->osd_rect.height;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001219 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001220 if (itv->osd_chroma_key_state)
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001221 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001222 if (itv->osd_global_alpha_state)
1223 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1224 pixfmt &= 7;
1225 /* no local alpha for RGB565 or unknown formats */
1226 if (pixfmt == 1 || pixfmt > 4)
1227 break;
1228 /* 16-bit formats have inverted local alpha */
1229 if (pixfmt == 2 || pixfmt == 3)
1230 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1231 else
1232 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
1233 if (itv->osd_local_alpha_state) {
1234 /* 16-bit formats have inverted local alpha */
1235 if (pixfmt == 2 || pixfmt == 3)
1236 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1237 else
1238 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1239 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001240 break;
1241 }
1242
1243 case VIDIOC_S_FBUF: {
1244 struct v4l2_framebuffer *fb = arg;
1245
1246 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001247 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001248 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001249 itv->osd_local_alpha_state =
1250 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001251 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
Hans Verkuilc3624f92007-07-31 07:15:56 -03001252 ivtv_set_osd_alpha(itv);
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001253 break;
1254 }
1255
Hans Verkuil7c03a442007-08-19 18:59:42 -03001256 case VIDIOC_OVERLAY: {
1257 int *on = arg;
1258
1259 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1260 return -EINVAL;
1261 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
1262 break;
1263 }
1264
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001265 case VIDIOC_LOG_STATUS:
1266 {
1267 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1268 struct v4l2_input vidin;
1269 struct v4l2_audio audin;
1270 int i;
1271
1272 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
Hans Verkuil94104aa2007-08-04 04:56:00 -03001273 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001274 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1275 struct tveeprom tv;
1276
1277 ivtv_read_eeprom(itv, &tv);
1278 }
1279 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1280 ivtv_get_input(itv, itv->active_input, &vidin);
1281 ivtv_get_audio_input(itv, itv->audio_input, &audin);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001282 IVTV_INFO("Video Input: %s\n", vidin.name);
1283 IVTV_INFO("Audio Input: %s%s\n", audin.name,
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001284 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001285 if (has_output) {
1286 struct v4l2_output vidout;
1287 struct v4l2_audioout audout;
1288 int mode = itv->output_mode;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001289 static const char * const output_modes[5] = {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001290 "None",
1291 "MPEG Streaming",
1292 "YUV Streaming",
1293 "YUV Frames",
1294 "Passthrough",
1295 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001296 static const char * const audio_modes[5] = {
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001297 "Stereo",
1298 "Left",
1299 "Right",
1300 "Mono",
1301 "Swapped"
1302 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001303 static const char * const alpha_mode[4] = {
Hans Verkuil7c03a442007-08-19 18:59:42 -03001304 "None",
1305 "Global",
1306 "Local",
1307 "Global and Local"
1308 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001309 static const char * const pixel_format[16] = {
1310 "ARGB Indexed",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001311 "RGB 5:6:5",
1312 "ARGB 1:5:5:5",
1313 "ARGB 1:4:4:4",
1314 "ARGB 8:8:8:8",
1315 "5",
1316 "6",
1317 "7",
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001318 "AYUV Indexed",
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001319 "YUV 5:6:5",
1320 "AYUV 1:5:5:5",
1321 "AYUV 1:4:4:4",
1322 "AYUV 8:8:8:8",
1323 "13",
1324 "14",
1325 "15",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001326 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001327
1328 ivtv_get_output(itv, itv->active_output, &vidout);
1329 ivtv_get_audio_output(itv, 0, &audout);
1330 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001331 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1332 audio_modes[itv->audio_stereo_mode],
1333 audio_modes[itv->audio_bilingual_mode]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001334 if (mode < 0 || mode > OUT_PASSTHROUGH)
1335 mode = OUT_NONE;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001336 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1337 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001338 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001339 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1340 data[0] & 1 ? "On" : "Off",
1341 alpha_mode[(data[0] >> 1) & 0x3],
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001342 pixel_format[(data[0] >> 3) & 0xf]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001343 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001344 IVTV_INFO("Tuner: %s\n",
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001345 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1346 cx2341x_log_status(&itv->params, itv->name);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001347 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001348 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1349 struct ivtv_stream *s = &itv->streams[i];
1350
1351 if (s->v4l2dev == NULL || s->buffers == 0)
1352 continue;
1353 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1354 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1355 (s->buffers * s->buf_size) / 1024, s->buffers);
1356 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001357 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 -03001358 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1359 break;
1360 }
1361
1362 default:
1363 return -EINVAL;
1364 }
1365 return 0;
1366}
1367
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001368static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001369{
1370 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1371 struct ivtv *itv = id->itv;
1372 int nonblocking = filp->f_flags & O_NONBLOCK;
1373 struct ivtv_stream *s = &itv->streams[id->type];
1374
1375 switch (cmd) {
1376 case IVTV_IOC_DMA_FRAME: {
1377 struct ivtv_dma_frame *args = arg;
1378
1379 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1380 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1381 return -EINVAL;
1382 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1383 return -EINVAL;
1384 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1385 return 0;
1386 if (ivtv_claim_stream(id, id->type)) {
1387 return -EBUSY;
1388 }
1389 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1390 ivtv_release_stream(s);
1391 return -EBUSY;
1392 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001393 /* Mark that this file handle started the UDMA_YUV mode */
1394 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001395 if (args->y_source == NULL)
1396 return 0;
1397 return ivtv_yuv_prep_frame(itv, args);
1398 }
1399
1400 case VIDEO_GET_PTS: {
1401 u32 data[CX2341X_MBOX_MAX_DATA];
1402 u64 *pts = arg;
1403
1404 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1405 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1406 *pts = s->dma_pts;
1407 break;
1408 }
1409 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1410 return -EINVAL;
1411
1412 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1413 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1414 (u64)itv->last_dec_timing[1];
1415 break;
1416 }
1417 *pts = 0;
1418 if (atomic_read(&itv->decoding)) {
1419 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1420 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1421 return -EIO;
1422 }
1423 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1424 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1425 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1426 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1427 }
1428 break;
1429 }
1430
1431 case VIDEO_GET_FRAME_COUNT: {
1432 u32 data[CX2341X_MBOX_MAX_DATA];
1433 u64 *frame = arg;
1434
1435 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1436 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1437 *frame = 0;
1438 break;
1439 }
1440 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1441 return -EINVAL;
1442
1443 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1444 *frame = itv->last_dec_timing[0];
1445 break;
1446 }
1447 *frame = 0;
1448 if (atomic_read(&itv->decoding)) {
1449 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1450 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1451 return -EIO;
1452 }
1453 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1454 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1455 *frame = data[0];
1456 }
1457 break;
1458 }
1459
1460 case VIDEO_PLAY: {
1461 struct video_command vc;
1462
1463 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1464 memset(&vc, 0, sizeof(vc));
1465 vc.cmd = VIDEO_CMD_PLAY;
1466 return ivtv_video_command(itv, id, &vc, 0);
1467 }
1468
1469 case VIDEO_STOP: {
1470 struct video_command vc;
1471
1472 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1473 memset(&vc, 0, sizeof(vc));
1474 vc.cmd = VIDEO_CMD_STOP;
1475 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1476 return ivtv_video_command(itv, id, &vc, 0);
1477 }
1478
1479 case VIDEO_FREEZE: {
1480 struct video_command vc;
1481
1482 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1483 memset(&vc, 0, sizeof(vc));
1484 vc.cmd = VIDEO_CMD_FREEZE;
1485 return ivtv_video_command(itv, id, &vc, 0);
1486 }
1487
1488 case VIDEO_CONTINUE: {
1489 struct video_command vc;
1490
1491 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1492 memset(&vc, 0, sizeof(vc));
1493 vc.cmd = VIDEO_CMD_CONTINUE;
1494 return ivtv_video_command(itv, id, &vc, 0);
1495 }
1496
1497 case VIDEO_COMMAND:
1498 case VIDEO_TRY_COMMAND: {
1499 struct video_command *vc = arg;
1500 int try = (cmd == VIDEO_TRY_COMMAND);
1501
1502 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001503 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001504 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001505 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001506 return ivtv_video_command(itv, id, vc, try);
1507 }
1508
1509 case VIDEO_GET_EVENT: {
1510 struct video_event *ev = arg;
1511 DEFINE_WAIT(wait);
1512
1513 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1514 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1515 return -EINVAL;
1516 memset(ev, 0, sizeof(*ev));
1517 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1518
1519 while (1) {
1520 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1521 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1522 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1523 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001524 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1525 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1526 if (itv->output_mode == OUT_UDMA_YUV &&
1527 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1528 IVTV_YUV_MODE_PROGRESSIVE) {
1529 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1530 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001531 }
1532 if (ev->type)
1533 return 0;
1534 if (nonblocking)
1535 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001536 /* Wait for event. Note that serialize_lock is locked,
1537 so to allow other processes to access the driver while
1538 we are waiting unlock first and later lock again. */
1539 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001540 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1541 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1542 schedule();
1543 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001544 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001545 if (signal_pending(current)) {
1546 /* return if a signal was received */
1547 IVTV_DEBUG_INFO("User stopped wait for event\n");
1548 return -EINTR;
1549 }
1550 }
1551 break;
1552 }
1553
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001554 default:
1555 return -EINVAL;
1556 }
1557 return 0;
1558}
1559
1560static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1561 unsigned int cmd, void *arg)
1562{
1563 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1564 struct ivtv *itv = id->itv;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001565 int ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001566
Hans Verkuild46c17d2007-03-10 17:59:15 -03001567 /* check priority */
1568 switch (cmd) {
1569 case VIDIOC_S_CTRL:
1570 case VIDIOC_S_STD:
1571 case VIDIOC_S_INPUT:
1572 case VIDIOC_S_OUTPUT:
1573 case VIDIOC_S_TUNER:
1574 case VIDIOC_S_FREQUENCY:
1575 case VIDIOC_S_FMT:
1576 case VIDIOC_S_CROP:
1577 case VIDIOC_S_AUDIO:
1578 case VIDIOC_S_AUDOUT:
1579 case VIDIOC_S_EXT_CTRLS:
1580 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001581 case VIDIOC_OVERLAY:
Hans Verkuild46c17d2007-03-10 17:59:15 -03001582 ret = v4l2_prio_check(&itv->prio, &id->prio);
1583 if (ret)
1584 return ret;
1585 }
1586
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001587 switch (cmd) {
1588 case VIDIOC_DBG_G_REGISTER:
1589 case VIDIOC_DBG_S_REGISTER:
1590 case VIDIOC_G_CHIP_IDENT:
1591 case VIDIOC_INT_S_AUDIO_ROUTING:
1592 case VIDIOC_INT_RESET:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001593 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1594 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1595 v4l_printk_ioctl(cmd);
1596 }
1597 return ivtv_debug_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001598
Hans Verkuild46c17d2007-03-10 17:59:15 -03001599 case VIDIOC_G_PRIORITY:
1600 case VIDIOC_S_PRIORITY:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001601 case VIDIOC_QUERYCAP:
1602 case VIDIOC_ENUMINPUT:
1603 case VIDIOC_G_INPUT:
1604 case VIDIOC_S_INPUT:
1605 case VIDIOC_ENUMOUTPUT:
1606 case VIDIOC_G_OUTPUT:
1607 case VIDIOC_S_OUTPUT:
1608 case VIDIOC_G_FMT:
1609 case VIDIOC_S_FMT:
1610 case VIDIOC_TRY_FMT:
1611 case VIDIOC_ENUM_FMT:
Hans Verkuil987e00b2007-05-29 13:03:27 -03001612 case VIDIOC_CROPCAP:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001613 case VIDIOC_G_CROP:
1614 case VIDIOC_S_CROP:
1615 case VIDIOC_G_FREQUENCY:
1616 case VIDIOC_S_FREQUENCY:
1617 case VIDIOC_ENUMSTD:
1618 case VIDIOC_G_STD:
1619 case VIDIOC_S_STD:
1620 case VIDIOC_S_TUNER:
1621 case VIDIOC_G_TUNER:
1622 case VIDIOC_ENUMAUDIO:
1623 case VIDIOC_S_AUDIO:
1624 case VIDIOC_G_AUDIO:
1625 case VIDIOC_ENUMAUDOUT:
1626 case VIDIOC_S_AUDOUT:
1627 case VIDIOC_G_AUDOUT:
1628 case VIDIOC_G_SLICED_VBI_CAP:
1629 case VIDIOC_LOG_STATUS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001630 case VIDIOC_G_ENC_INDEX:
1631 case VIDIOC_ENCODER_CMD:
1632 case VIDIOC_TRY_ENCODER_CMD:
1633 case VIDIOC_G_FBUF:
1634 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001635 case VIDIOC_OVERLAY:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001636 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1637 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1638 v4l_printk_ioctl(cmd);
1639 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001640 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1641
1642 case VIDIOC_QUERYMENU:
1643 case VIDIOC_QUERYCTRL:
1644 case VIDIOC_S_CTRL:
1645 case VIDIOC_G_CTRL:
1646 case VIDIOC_S_EXT_CTRLS:
1647 case VIDIOC_G_EXT_CTRLS:
1648 case VIDIOC_TRY_EXT_CTRLS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001649 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1650 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1651 v4l_printk_ioctl(cmd);
1652 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001653 return ivtv_control_ioctls(itv, cmd, arg);
1654
1655 case IVTV_IOC_DMA_FRAME:
1656 case VIDEO_GET_PTS:
1657 case VIDEO_GET_FRAME_COUNT:
1658 case VIDEO_GET_EVENT:
1659 case VIDEO_PLAY:
1660 case VIDEO_STOP:
1661 case VIDEO_FREEZE:
1662 case VIDEO_CONTINUE:
1663 case VIDEO_COMMAND:
1664 case VIDEO_TRY_COMMAND:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001665 return ivtv_decoder_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001666
1667 case 0x00005401: /* Handle isatty() calls */
1668 return -EINVAL;
1669 default:
1670 return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
1671 ivtv_v4l2_do_ioctl);
1672 }
1673 return 0;
1674}
1675
Hans Verkuilbaa40722007-08-19 07:10:55 -03001676static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1677 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001678{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001679 /* Filter dvb ioctls that cannot be handled by video_usercopy */
1680 switch (cmd) {
1681 case VIDEO_SELECT_SOURCE:
1682 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1683 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1684 return -EINVAL;
1685 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1686
1687 case AUDIO_SET_MUTE:
1688 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1689 itv->speed_mute_audio = arg;
1690 return 0;
1691
1692 case AUDIO_CHANNEL_SELECT:
1693 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1694 if (arg > AUDIO_STEREO_SWAPPED)
1695 return -EINVAL;
1696 itv->audio_stereo_mode = arg;
1697 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1698 return 0;
1699
1700 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1701 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1702 if (arg > AUDIO_STEREO_SWAPPED)
1703 return -EINVAL;
1704 itv->audio_bilingual_mode = arg;
1705 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1706 return 0;
1707
1708 default:
1709 break;
1710 }
1711 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
1712}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001713
1714int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1715 unsigned long arg)
1716{
1717 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1718 struct ivtv *itv = id->itv;
1719 int res;
1720
1721 mutex_lock(&itv->serialize_lock);
1722 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1723 mutex_unlock(&itv->serialize_lock);
1724 return res;
1725}