blob: 0618fee24952aaa65c439f92a1c62f36b7d3a72d [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;
Ian Armstrong77aded62007-11-05 14:27:09 -0300375 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300376 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;
Ian Armstrong77aded62007-11-05 14:27:09 -0300389 fmt->fmt.pix.bytesperline = 720;
390 fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w;
391 fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300392 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
393 fmt->fmt.pix.sizeimage =
Ian Armstrong77aded62007-11-05 14:27:09 -0300394 1080 * ((fmt->fmt.pix.height + 31) & ~31);
395 } else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300396 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
397 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
398 fmt->fmt.pix.sizeimage =
399 fmt->fmt.pix.height * fmt->fmt.pix.width +
400 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
401 } else {
402 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
403 fmt->fmt.pix.sizeimage = 128 * 1024;
404 }
405 break;
406
407 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300408 fmt->fmt.pix.width = itv->params.width;
409 fmt->fmt.pix.height = itv->params.height;
410 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
411 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
412 if (streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
413 streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
414 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
415 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
416 fmt->fmt.pix.sizeimage =
417 fmt->fmt.pix.height * fmt->fmt.pix.width +
418 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
419 } else {
420 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
421 fmt->fmt.pix.sizeimage = 128 * 1024;
422 }
423 break;
424
425 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
426 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
427 return -EINVAL;
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300428 fmt->fmt.win.chromakey = itv->osd_chroma_key;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300429 fmt->fmt.win.global_alpha = itv->osd_global_alpha;
430 break;
431
432 case V4L2_BUF_TYPE_VBI_CAPTURE:
433 fmt->fmt.vbi.sampling_rate = 27000000;
434 fmt->fmt.vbi.offset = 248;
435 fmt->fmt.vbi.samples_per_line = itv->vbi.raw_decoder_line_size - 4;
436 fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
437 fmt->fmt.vbi.start[0] = itv->vbi.start[0];
438 fmt->fmt.vbi.start[1] = itv->vbi.start[1];
439 fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = itv->vbi.count;
440 break;
441
442 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
443 {
444 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
445
446 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
447 return -EINVAL;
448 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
449 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
450 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
451 if (itv->is_60hz) {
452 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
453 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
454 } else {
455 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
456 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
457 }
458 vbifmt->service_set = get_service_set(vbifmt);
459 break;
460 }
461
462 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
463 {
464 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
465
466 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
467 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
468 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
469
470 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
471 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
472 V4L2_SLICED_VBI_525;
473 expand_service_set(vbifmt, itv->is_50hz);
474 break;
475 }
476
477 itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);
478 vbifmt->service_set = get_service_set(vbifmt);
479 break;
480 }
481 case V4L2_BUF_TYPE_VBI_OUTPUT:
482 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
483 default:
484 return -EINVAL;
485 }
486 return 0;
487}
488
489static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
490 struct v4l2_format *fmt, int set_fmt)
491{
Ian Armstrong77aded62007-11-05 14:27:09 -0300492 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300493 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);
Ian Armstrong77aded62007-11-05 14:27:09 -0300508 fmt->fmt.pix.width = r.width;
509 fmt->fmt.pix.height = r.height;
510 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300511 fmt->fmt.pix.field = field;
Ian Armstrong77aded62007-11-05 14:27:09 -0300512 if (fmt->fmt.pix.width < 2)
513 fmt->fmt.pix.width = 2;
514 if (fmt->fmt.pix.width > 720)
515 fmt->fmt.pix.width = 720;
516 if (fmt->fmt.pix.height < 2)
517 fmt->fmt.pix.height = 2;
518 if (fmt->fmt.pix.height > 576)
519 fmt->fmt.pix.height = 576;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300520 }
Ian Armstrong77aded62007-11-05 14:27:09 -0300521 if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
522 /* Return now if we already have some frame data */
523 if (yi->stream_size)
524 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300525
Ian Armstrong77aded62007-11-05 14:27:09 -0300526 yi->v4l2_src_w = r.width;
527 yi->v4l2_src_h = r.height;
528
529 switch (field) {
530 case V4L2_FIELD_NONE:
531 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
532 break;
533 case V4L2_FIELD_ANY:
534 yi->lace_mode = IVTV_YUV_MODE_AUTO;
535 break;
536 case V4L2_FIELD_INTERLACED_BT:
537 yi->lace_mode =
538 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
539 break;
540 case V4L2_FIELD_INTERLACED_TB:
541 default:
542 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
543 break;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300544 }
Ian Armstrong77aded62007-11-05 14:27:09 -0300545 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
546
547 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
548 itv->dma_data_req_size =
549 1080 * ((yi->v4l2_src_h + 31) & ~31);
550
551 /* Force update of yuv registers */
552 yi->yuv_forced_update = 1;
553 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300554 }
555 return 0;
556 }
557
558 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) {
559 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
560 return -EINVAL;
561 if (set_fmt) {
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300562 itv->osd_chroma_key = fmt->fmt.win.chromakey;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300563 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
564 ivtv_set_osd_alpha(itv);
565 }
566 return 0;
567 }
568
569 /* set window size */
570 if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300571 struct cx2341x_mpeg_params *p = &itv->params;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300572 int w = fmt->fmt.pix.width;
573 int h = fmt->fmt.pix.height;
574
575 if (w > 720) w = 720;
576 else if (w < 1) w = 1;
577 if (h > (itv->is_50hz ? 576 : 480)) h = (itv->is_50hz ? 576 : 480);
578 else if (h < 2) h = 2;
579 ivtv_get_fmt(itv, streamtype, fmt);
580 fmt->fmt.pix.width = w;
581 fmt->fmt.pix.height = h;
582
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300583 if (!set_fmt || (p->width == w && p->height == h))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300584 return 0;
585 if (atomic_read(&itv->capturing) > 0)
586 return -EBUSY;
587
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300588 p->width = w;
589 p->height = h;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300590 if (w != 720 || h != (itv->is_50hz ? 576 : 480))
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300591 p->video_temporal_filter = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300592 else
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300593 p->video_temporal_filter = 8;
594 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
595 fmt->fmt.pix.width /= 2;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300596 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
597 return ivtv_get_fmt(itv, streamtype, fmt);
598 }
599
600 /* set raw VBI format */
601 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Hans Verkuilea115d52007-08-20 16:26:40 -0300602 if (set_fmt && atomic_read(&itv->capturing) > 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300603 return -EBUSY;
604 }
605 if (set_fmt) {
606 itv->vbi.sliced_in->service_set = 0;
607 itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
608 }
609 return ivtv_get_fmt(itv, streamtype, fmt);
610 }
611
612 /* set sliced VBI output
613 In principle the user could request that only certain
614 VBI types are output and that the others are ignored.
615 I.e., suppress CC in the even fields or only output
616 WSS and no VPS. Currently though there is no choice. */
617 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
618 return ivtv_get_fmt(itv, streamtype, fmt);
619
620 /* any else but sliced VBI capture is an error */
621 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
622 return -EINVAL;
623
624 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI)
625 return ivtv_get_fmt(itv, streamtype, fmt);
626
627 /* set sliced VBI capture format */
628 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
629 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
630
631 if (vbifmt->service_set)
632 expand_service_set(vbifmt, itv->is_50hz);
633 set = check_service_set(vbifmt, itv->is_50hz);
634 vbifmt->service_set = get_service_set(vbifmt);
635
636 if (!set_fmt)
637 return 0;
638 if (set == 0)
639 return -EINVAL;
Hans Verkuilea115d52007-08-20 16:26:40 -0300640 if (atomic_read(&itv->capturing) > 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300641 return -EBUSY;
642 }
643 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
644 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
645 return 0;
646}
647
Hans Verkuild4e7ee32007-03-10 18:19:12 -0300648static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300649{
650 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
651 struct ivtv *itv = id->itv;
652 struct v4l2_register *reg = arg;
653
654 switch (cmd) {
655 /* ioctls to allow direct access to the encoder registers for testing */
656 case VIDIOC_DBG_G_REGISTER:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300657 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
658 return ivtv_itvc(itv, cmd, arg);
659 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
660 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
661 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
662
663 case VIDIOC_DBG_S_REGISTER:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300664 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
665 return ivtv_itvc(itv, cmd, arg);
666 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
667 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
668 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
669
670 case VIDIOC_G_CHIP_IDENT: {
671 struct v4l2_chip_ident *chip = arg;
672
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300673 chip->ident = V4L2_IDENT_NONE;
674 chip->revision = 0;
675 if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
676 if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {
677 struct v4l2_chip_ident *chip = arg;
678
679 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
680 }
681 return 0;
682 }
683 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
684 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
685 if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
686 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
687 return -EINVAL;
688 }
689
690 case VIDIOC_INT_S_AUDIO_ROUTING: {
691 struct v4l2_routing *route = arg;
692
Hans Verkuil33c0fca2007-08-23 06:32:46 -0300693 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300694 break;
695 }
696
Hans Verkuil2cc72092007-08-04 05:06:23 -0300697 case VIDIOC_INT_RESET: {
698 u32 val = *(u32 *)arg;
699
700 if ((val == 0 && itv->options.newi2c) || (val & 0x01)) {
701 ivtv_reset_ir_gpio(itv);
702 }
703 if (val & 0x02) {
704 itv->video_dec_func(itv, cmd, 0);
705 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300706 break;
Hans Verkuil2cc72092007-08-04 05:06:23 -0300707 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300708
709 default:
710 return -EINVAL;
711 }
712 return 0;
713}
714
715int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
716{
717 struct ivtv_open_id *id = NULL;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -0300718 u32 data[CX2341X_MBOX_MAX_DATA];
Ian Armstrong77aded62007-11-05 14:27:09 -0300719 int streamtype = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300720
Ian Armstrong77aded62007-11-05 14:27:09 -0300721 if (filp) {
722 id = (struct ivtv_open_id *)filp->private_data;
723 streamtype = id->type;
724 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300725
726 switch (cmd) {
Hans Verkuild46c17d2007-03-10 17:59:15 -0300727 case VIDIOC_G_PRIORITY:
728 {
729 enum v4l2_priority *p = arg;
730
731 *p = v4l2_prio_max(&itv->prio);
732 break;
733 }
734
735 case VIDIOC_S_PRIORITY:
736 {
737 enum v4l2_priority *prio = arg;
738
739 return v4l2_prio_change(&itv->prio, &id->prio, *prio);
740 }
741
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300742 case VIDIOC_QUERYCAP:{
743 struct v4l2_capability *vcap = arg;
744
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300745 memset(vcap, 0, sizeof(*vcap));
746 strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
747 strcpy(vcap->card, itv->card_name); /* card type */
748 strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
749 vcap->version = IVTV_DRIVER_VERSION; /* version */
750 vcap->capabilities = itv->v4l2_cap; /* capabilities */
751
752 /* reserved.. must set to 0! */
753 vcap->reserved[0] = vcap->reserved[1] =
754 vcap->reserved[2] = vcap->reserved[3] = 0;
755 break;
756 }
757
758 case VIDIOC_ENUMAUDIO:{
759 struct v4l2_audio *vin = arg;
760
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300761 return ivtv_get_audio_input(itv, vin->index, vin);
762 }
763
764 case VIDIOC_G_AUDIO:{
765 struct v4l2_audio *vin = arg;
766
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300767 vin->index = itv->audio_input;
768 return ivtv_get_audio_input(itv, vin->index, vin);
769 }
770
771 case VIDIOC_S_AUDIO:{
772 struct v4l2_audio *vout = arg;
773
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300774 if (vout->index >= itv->nof_audio_inputs)
775 return -EINVAL;
776 itv->audio_input = vout->index;
777 ivtv_audio_set_io(itv);
778 break;
779 }
780
781 case VIDIOC_ENUMAUDOUT:{
782 struct v4l2_audioout *vin = arg;
783
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300784 /* set it to defaults from our table */
785 return ivtv_get_audio_output(itv, vin->index, vin);
786 }
787
788 case VIDIOC_G_AUDOUT:{
789 struct v4l2_audioout *vin = arg;
790
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300791 vin->index = 0;
792 return ivtv_get_audio_output(itv, vin->index, vin);
793 }
794
795 case VIDIOC_S_AUDOUT:{
796 struct v4l2_audioout *vout = arg;
797
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300798 return ivtv_get_audio_output(itv, vout->index, vout);
799 }
800
801 case VIDIOC_ENUMINPUT:{
802 struct v4l2_input *vin = arg;
803
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300804 /* set it to defaults from our table */
805 return ivtv_get_input(itv, vin->index, vin);
806 }
807
808 case VIDIOC_ENUMOUTPUT:{
809 struct v4l2_output *vout = arg;
810
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300811 return ivtv_get_output(itv, vout->index, vout);
812 }
813
814 case VIDIOC_TRY_FMT:
815 case VIDIOC_S_FMT: {
816 struct v4l2_format *fmt = arg;
817
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300818 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);
819 }
820
821 case VIDIOC_G_FMT: {
822 struct v4l2_format *fmt = arg;
823 int type = fmt->type;
824
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300825 memset(fmt, 0, sizeof(*fmt));
826 fmt->type = type;
827 return ivtv_get_fmt(itv, id->type, fmt);
828 }
829
Hans Verkuil987e00b2007-05-29 13:03:27 -0300830 case VIDIOC_CROPCAP: {
831 struct v4l2_cropcap *cropcap = arg;
832
833 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
834 cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
835 return -EINVAL;
836 cropcap->bounds.top = cropcap->bounds.left = 0;
837 cropcap->bounds.width = 720;
838 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
839 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
840 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
841 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
Ian Armstrong77aded62007-11-05 14:27:09 -0300842 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
843 cropcap->bounds.width = itv->yuv_info.osd_full_w;
844 cropcap->bounds.height = itv->yuv_info.osd_full_h;
845 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
846 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300847 } else {
848 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
849 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
850 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
851 }
852 cropcap->defrect = cropcap->bounds;
853 return 0;
854 }
855
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300856 case VIDIOC_S_CROP: {
857 struct v4l2_crop *crop = arg;
858
Hans Verkuil987e00b2007-05-29 13:03:27 -0300859 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
860 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300861 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
862 itv->yuv_info.main_rect = crop->c;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300863 return 0;
Ian Armstrong77aded62007-11-05 14:27:09 -0300864 } else {
865 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
866 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
867 itv->main_rect = crop->c;
868 return 0;
869 }
Hans Verkuil987e00b2007-05-29 13:03:27 -0300870 }
871 return -EINVAL;
872 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300873 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
874 return -EINVAL;
875 return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
876 }
877
878 case VIDIOC_G_CROP: {
879 struct v4l2_crop *crop = arg;
880
Hans Verkuil987e00b2007-05-29 13:03:27 -0300881 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
882 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300883 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
884 crop->c = itv->yuv_info.main_rect;
885 else
886 crop->c = itv->main_rect;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300887 return 0;
888 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300889 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
890 return -EINVAL;
891 return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
892 }
893
894 case VIDIOC_ENUM_FMT: {
895 static struct v4l2_fmtdesc formats[] = {
896 { 0, 0, 0,
Ian Armstrong368f0802007-11-05 14:30:03 -0300897 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300898 { 0, 0, 0, 0 }
899 },
900 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
901 "MPEG", V4L2_PIX_FMT_MPEG,
902 { 0, 0, 0, 0 }
903 }
904 };
905 struct v4l2_fmtdesc *fmt = arg;
906 enum v4l2_buf_type type = fmt->type;
907
908 switch (type) {
909 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
910 break;
911 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
912 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
913 return -EINVAL;
914 break;
915 default:
916 return -EINVAL;
917 }
918 if (fmt->index > 1)
919 return -EINVAL;
920 *fmt = formats[fmt->index];
921 fmt->type = type;
922 return 0;
923 }
924
925 case VIDIOC_G_INPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300926 *(int *)arg = itv->active_input;
927 break;
928 }
929
930 case VIDIOC_S_INPUT:{
931 int inp = *(int *)arg;
932
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300933 if (inp < 0 || inp >= itv->nof_inputs)
934 return -EINVAL;
935
936 if (inp == itv->active_input) {
937 IVTV_DEBUG_INFO("Input unchanged\n");
938 break;
939 }
Hans Verkuil3562c432007-08-18 11:46:05 -0300940 if (atomic_read(&itv->capturing) > 0) {
941 return -EBUSY;
942 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300943 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
944 itv->active_input, inp);
945
946 itv->active_input = inp;
947 /* Set the audio input to whatever is appropriate for the
948 input type. */
949 itv->audio_input = itv->card->video_inputs[inp].audio_index;
950
951 /* prevent others from messing with the streams until
952 we're finished changing inputs. */
953 ivtv_mute(itv);
954 ivtv_video_set_io(itv);
955 ivtv_audio_set_io(itv);
956 ivtv_unmute(itv);
957 break;
958 }
959
960 case VIDIOC_G_OUTPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300961 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
962 return -EINVAL;
963 *(int *)arg = itv->active_output;
964 break;
965 }
966
967 case VIDIOC_S_OUTPUT:{
968 int outp = *(int *)arg;
969 struct v4l2_routing route;
970
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300971 if (outp >= itv->card->nof_outputs)
972 return -EINVAL;
973
974 if (outp == itv->active_output) {
975 IVTV_DEBUG_INFO("Output unchanged\n");
976 break;
977 }
978 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
979 itv->active_output, outp);
980
981 itv->active_output = outp;
982 route.input = SAA7127_INPUT_TYPE_NORMAL;
983 route.output = itv->card->video_outputs[outp].video_output;
984 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
985 break;
986 }
987
988 case VIDIOC_G_FREQUENCY:{
989 struct v4l2_frequency *vf = arg;
990
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300991 if (vf->tuner != 0)
992 return -EINVAL;
993 ivtv_call_i2c_clients(itv, cmd, arg);
994 break;
995 }
996
997 case VIDIOC_S_FREQUENCY:{
998 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
999
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001000 if (vf.tuner != 0)
1001 return -EINVAL;
1002
1003 ivtv_mute(itv);
1004 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
1005 ivtv_call_i2c_clients(itv, cmd, &vf);
1006 ivtv_unmute(itv);
1007 break;
1008 }
1009
1010 case VIDIOC_ENUMSTD:{
1011 struct v4l2_standard *vs = arg;
1012 int idx = vs->index;
1013
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001014 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
1015 return -EINVAL;
1016
1017 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
1018 ivtv_std_60hz : ivtv_std_50hz;
1019 vs->index = idx;
1020 vs->id = enum_stds[idx].std;
1021 strcpy(vs->name, enum_stds[idx].name);
1022 break;
1023 }
1024
1025 case VIDIOC_G_STD:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001026 *(v4l2_std_id *) arg = itv->std;
1027 break;
1028 }
1029
1030 case VIDIOC_S_STD: {
1031 v4l2_std_id std = *(v4l2_std_id *) arg;
1032
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001033 if ((std & V4L2_STD_ALL) == 0)
1034 return -EINVAL;
1035
1036 if (std == itv->std)
1037 break;
1038
1039 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1040 atomic_read(&itv->capturing) > 0 ||
1041 atomic_read(&itv->decoding) > 0) {
1042 /* Switching standard would turn off the radio or mess
1043 with already running streams, prevent that by
1044 returning EBUSY. */
1045 return -EBUSY;
1046 }
1047
1048 itv->std = std;
1049 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
1050 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1051 itv->params.width = 720;
1052 itv->params.height = itv->is_50hz ? 576 : 480;
1053 itv->vbi.count = itv->is_50hz ? 18 : 12;
1054 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1055 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1056 if (itv->hw_flags & IVTV_HW_CX25840) {
1057 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1058 }
Hans Verkuilc4385092007-06-07 09:04:03 -03001059 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001060
1061 /* Tuner */
1062 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1063
1064 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1065 /* set display standard */
1066 itv->std_out = std;
1067 itv->is_out_60hz = itv->is_60hz;
1068 itv->is_out_50hz = itv->is_50hz;
1069 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1070 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1071 itv->main_rect.left = itv->main_rect.top = 0;
1072 itv->main_rect.width = 720;
1073 itv->main_rect.height = itv->params.height;
1074 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1075 720, itv->main_rect.height, 0, 0);
Ian Armstrong77aded62007-11-05 14:27:09 -03001076 itv->yuv_info.main_rect = itv->main_rect;
1077 if (!itv->osd_info) {
1078 itv->yuv_info.osd_full_w = 720;
1079 itv->yuv_info.osd_full_h =
1080 itv->is_out_50hz ? 576 : 480;
1081 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001082 }
1083 break;
1084 }
1085
1086 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
1087 struct v4l2_tuner *vt = arg;
1088
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001089 if (vt->index != 0)
1090 return -EINVAL;
1091
1092 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1093 break;
1094 }
1095
1096 case VIDIOC_G_TUNER: {
1097 struct v4l2_tuner *vt = arg;
1098
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001099 if (vt->index != 0)
1100 return -EINVAL;
1101
1102 memset(vt, 0, sizeof(*vt));
1103 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1104
1105 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1106 strcpy(vt->name, "ivtv Radio Tuner");
1107 vt->type = V4L2_TUNER_RADIO;
1108 } else {
1109 strcpy(vt->name, "ivtv TV Tuner");
1110 vt->type = V4L2_TUNER_ANALOG_TV;
1111 }
1112 break;
1113 }
1114
1115 case VIDIOC_G_SLICED_VBI_CAP: {
1116 struct v4l2_sliced_vbi_cap *cap = arg;
1117 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1118 int f, l;
1119 enum v4l2_buf_type type = cap->type;
1120
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001121 memset(cap, 0, sizeof(*cap));
1122 cap->type = type;
1123 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1124 for (f = 0; f < 2; f++) {
1125 for (l = 0; l < 24; l++) {
1126 if (valid_service_line(f, l, itv->is_50hz)) {
1127 cap->service_lines[f][l] = set;
1128 }
1129 }
1130 }
1131 return 0;
1132 }
1133 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1134 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1135 return -EINVAL;
1136 if (itv->is_60hz) {
1137 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1138 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1139 } else {
1140 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1141 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1142 }
1143 return 0;
1144 }
1145 return -EINVAL;
1146 }
1147
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001148 case VIDIOC_G_ENC_INDEX: {
1149 struct v4l2_enc_idx *idx = arg;
Hans Verkuil5614b022007-08-23 17:48:41 -03001150 struct v4l2_enc_idx_entry *e = idx->entry;
1151 int entries;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001152 int i;
1153
Hans Verkuil5614b022007-08-23 17:48:41 -03001154 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001155 IVTV_MAX_PGM_INDEX;
Hans Verkuil5614b022007-08-23 17:48:41 -03001156 if (entries > V4L2_ENC_IDX_ENTRIES)
1157 entries = V4L2_ENC_IDX_ENTRIES;
1158 idx->entries = 0;
1159 for (i = 0; i < entries; i++) {
1160 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1161 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1162 idx->entries++;
1163 e++;
1164 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001165 }
1166 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1167 break;
1168 }
1169
1170 case VIDIOC_ENCODER_CMD:
1171 case VIDIOC_TRY_ENCODER_CMD: {
1172 struct v4l2_encoder_cmd *enc = arg;
1173 int try = cmd == VIDIOC_TRY_ENCODER_CMD;
1174
Hans Verkuil25415cf2007-03-10 18:29:48 -03001175 memset(&enc->raw, 0, sizeof(enc->raw));
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001176 switch (enc->cmd) {
1177 case V4L2_ENC_CMD_START:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001178 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001179 enc->flags = 0;
1180 if (try)
1181 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001182 return ivtv_start_capture(id);
1183
1184 case V4L2_ENC_CMD_STOP:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001185 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
Hans Verkuil018ba852007-04-10 18:59:09 -03001186 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001187 if (try)
1188 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001189 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1190 return 0;
1191
1192 case V4L2_ENC_CMD_PAUSE:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001193 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001194 enc->flags = 0;
1195 if (try)
1196 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001197 if (!atomic_read(&itv->capturing))
1198 return -EPERM;
1199 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1200 return 0;
1201 ivtv_mute(itv);
1202 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1203 break;
1204
1205 case V4L2_ENC_CMD_RESUME:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001206 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001207 enc->flags = 0;
1208 if (try)
1209 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001210 if (!atomic_read(&itv->capturing))
1211 return -EPERM;
1212 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1213 return 0;
1214 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1215 ivtv_unmute(itv);
1216 break;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001217 default:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001218 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
Hans Verkuil25415cf2007-03-10 18:29:48 -03001219 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001220 }
1221 break;
1222 }
1223
1224 case VIDIOC_G_FBUF: {
1225 struct v4l2_framebuffer *fb = arg;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001226 int pixfmt;
1227 static u32 pixel_format[16] = {
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001228 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001229 V4L2_PIX_FMT_RGB565,
1230 V4L2_PIX_FMT_RGB555,
1231 V4L2_PIX_FMT_RGB444,
1232 V4L2_PIX_FMT_RGB32,
1233 0,
1234 0,
1235 0,
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001236 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1237 V4L2_PIX_FMT_YUV565,
1238 V4L2_PIX_FMT_YUV555,
1239 V4L2_PIX_FMT_YUV444,
1240 V4L2_PIX_FMT_YUV32,
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001241 0,
1242 0,
1243 0,
1244 };
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001245
1246 memset(fb, 0, sizeof(*fb));
1247 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001248 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001249 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001250 V4L2_FBUF_CAP_GLOBAL_ALPHA;
1251 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1252 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1253 pixfmt = (data[0] >> 3) & 0xf;
1254 fb->fmt.pixelformat = pixel_format[pixfmt];
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001255 fb->fmt.width = itv->osd_rect.width;
1256 fb->fmt.height = itv->osd_rect.height;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001257 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001258 if (itv->osd_chroma_key_state)
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001259 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001260 if (itv->osd_global_alpha_state)
1261 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1262 pixfmt &= 7;
1263 /* no local alpha for RGB565 or unknown formats */
1264 if (pixfmt == 1 || pixfmt > 4)
1265 break;
1266 /* 16-bit formats have inverted local alpha */
1267 if (pixfmt == 2 || pixfmt == 3)
1268 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1269 else
1270 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
1271 if (itv->osd_local_alpha_state) {
1272 /* 16-bit formats have inverted local alpha */
1273 if (pixfmt == 2 || pixfmt == 3)
1274 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1275 else
1276 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1277 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001278 break;
1279 }
1280
1281 case VIDIOC_S_FBUF: {
1282 struct v4l2_framebuffer *fb = arg;
1283
1284 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001285 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001286 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001287 itv->osd_local_alpha_state =
1288 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001289 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
Hans Verkuilc3624f92007-07-31 07:15:56 -03001290 ivtv_set_osd_alpha(itv);
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001291 break;
1292 }
1293
Hans Verkuil7c03a442007-08-19 18:59:42 -03001294 case VIDIOC_OVERLAY: {
1295 int *on = arg;
1296
1297 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1298 return -EINVAL;
1299 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
1300 break;
1301 }
1302
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001303 case VIDIOC_LOG_STATUS:
1304 {
1305 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1306 struct v4l2_input vidin;
1307 struct v4l2_audio audin;
1308 int i;
1309
1310 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
Hans Verkuil94104aa2007-08-04 04:56:00 -03001311 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001312 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1313 struct tveeprom tv;
1314
1315 ivtv_read_eeprom(itv, &tv);
1316 }
1317 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1318 ivtv_get_input(itv, itv->active_input, &vidin);
1319 ivtv_get_audio_input(itv, itv->audio_input, &audin);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001320 IVTV_INFO("Video Input: %s\n", vidin.name);
1321 IVTV_INFO("Audio Input: %s%s\n", audin.name,
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001322 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001323 if (has_output) {
1324 struct v4l2_output vidout;
1325 struct v4l2_audioout audout;
1326 int mode = itv->output_mode;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001327 static const char * const output_modes[5] = {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001328 "None",
1329 "MPEG Streaming",
1330 "YUV Streaming",
1331 "YUV Frames",
1332 "Passthrough",
1333 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001334 static const char * const audio_modes[5] = {
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001335 "Stereo",
1336 "Left",
1337 "Right",
1338 "Mono",
1339 "Swapped"
1340 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001341 static const char * const alpha_mode[4] = {
Hans Verkuil7c03a442007-08-19 18:59:42 -03001342 "None",
1343 "Global",
1344 "Local",
1345 "Global and Local"
1346 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001347 static const char * const pixel_format[16] = {
1348 "ARGB Indexed",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001349 "RGB 5:6:5",
1350 "ARGB 1:5:5:5",
1351 "ARGB 1:4:4:4",
1352 "ARGB 8:8:8:8",
1353 "5",
1354 "6",
1355 "7",
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001356 "AYUV Indexed",
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001357 "YUV 5:6:5",
1358 "AYUV 1:5:5:5",
1359 "AYUV 1:4:4:4",
1360 "AYUV 8:8:8:8",
1361 "13",
1362 "14",
1363 "15",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001364 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001365
1366 ivtv_get_output(itv, itv->active_output, &vidout);
1367 ivtv_get_audio_output(itv, 0, &audout);
1368 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001369 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1370 audio_modes[itv->audio_stereo_mode],
1371 audio_modes[itv->audio_bilingual_mode]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001372 if (mode < 0 || mode > OUT_PASSTHROUGH)
1373 mode = OUT_NONE;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001374 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1375 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001376 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001377 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1378 data[0] & 1 ? "On" : "Off",
1379 alpha_mode[(data[0] >> 1) & 0x3],
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001380 pixel_format[(data[0] >> 3) & 0xf]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001381 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001382 IVTV_INFO("Tuner: %s\n",
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001383 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1384 cx2341x_log_status(&itv->params, itv->name);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001385 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001386 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1387 struct ivtv_stream *s = &itv->streams[i];
1388
1389 if (s->v4l2dev == NULL || s->buffers == 0)
1390 continue;
1391 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1392 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1393 (s->buffers * s->buf_size) / 1024, s->buffers);
1394 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001395 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 -03001396 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1397 break;
1398 }
1399
1400 default:
1401 return -EINVAL;
1402 }
1403 return 0;
1404}
1405
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001406static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001407{
1408 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1409 struct ivtv *itv = id->itv;
1410 int nonblocking = filp->f_flags & O_NONBLOCK;
1411 struct ivtv_stream *s = &itv->streams[id->type];
1412
1413 switch (cmd) {
1414 case IVTV_IOC_DMA_FRAME: {
1415 struct ivtv_dma_frame *args = arg;
1416
1417 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1418 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1419 return -EINVAL;
1420 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1421 return -EINVAL;
1422 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1423 return 0;
1424 if (ivtv_claim_stream(id, id->type)) {
1425 return -EBUSY;
1426 }
1427 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1428 ivtv_release_stream(s);
1429 return -EBUSY;
1430 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001431 /* Mark that this file handle started the UDMA_YUV mode */
1432 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001433 if (args->y_source == NULL)
1434 return 0;
1435 return ivtv_yuv_prep_frame(itv, args);
1436 }
1437
1438 case VIDEO_GET_PTS: {
1439 u32 data[CX2341X_MBOX_MAX_DATA];
1440 u64 *pts = arg;
1441
1442 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1443 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1444 *pts = s->dma_pts;
1445 break;
1446 }
1447 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1448 return -EINVAL;
1449
1450 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1451 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1452 (u64)itv->last_dec_timing[1];
1453 break;
1454 }
1455 *pts = 0;
1456 if (atomic_read(&itv->decoding)) {
1457 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1458 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1459 return -EIO;
1460 }
1461 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1462 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1463 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1464 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1465 }
1466 break;
1467 }
1468
1469 case VIDEO_GET_FRAME_COUNT: {
1470 u32 data[CX2341X_MBOX_MAX_DATA];
1471 u64 *frame = arg;
1472
1473 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1474 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1475 *frame = 0;
1476 break;
1477 }
1478 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1479 return -EINVAL;
1480
1481 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1482 *frame = itv->last_dec_timing[0];
1483 break;
1484 }
1485 *frame = 0;
1486 if (atomic_read(&itv->decoding)) {
1487 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1488 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1489 return -EIO;
1490 }
1491 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1492 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1493 *frame = data[0];
1494 }
1495 break;
1496 }
1497
1498 case VIDEO_PLAY: {
1499 struct video_command vc;
1500
1501 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1502 memset(&vc, 0, sizeof(vc));
1503 vc.cmd = VIDEO_CMD_PLAY;
1504 return ivtv_video_command(itv, id, &vc, 0);
1505 }
1506
1507 case VIDEO_STOP: {
1508 struct video_command vc;
1509
1510 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1511 memset(&vc, 0, sizeof(vc));
1512 vc.cmd = VIDEO_CMD_STOP;
1513 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1514 return ivtv_video_command(itv, id, &vc, 0);
1515 }
1516
1517 case VIDEO_FREEZE: {
1518 struct video_command vc;
1519
1520 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1521 memset(&vc, 0, sizeof(vc));
1522 vc.cmd = VIDEO_CMD_FREEZE;
1523 return ivtv_video_command(itv, id, &vc, 0);
1524 }
1525
1526 case VIDEO_CONTINUE: {
1527 struct video_command vc;
1528
1529 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1530 memset(&vc, 0, sizeof(vc));
1531 vc.cmd = VIDEO_CMD_CONTINUE;
1532 return ivtv_video_command(itv, id, &vc, 0);
1533 }
1534
1535 case VIDEO_COMMAND:
1536 case VIDEO_TRY_COMMAND: {
1537 struct video_command *vc = arg;
1538 int try = (cmd == VIDEO_TRY_COMMAND);
1539
1540 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001541 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001542 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001543 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001544 return ivtv_video_command(itv, id, vc, try);
1545 }
1546
1547 case VIDEO_GET_EVENT: {
1548 struct video_event *ev = arg;
1549 DEFINE_WAIT(wait);
1550
1551 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1552 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1553 return -EINVAL;
1554 memset(ev, 0, sizeof(*ev));
1555 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1556
1557 while (1) {
1558 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1559 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1560 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1561 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001562 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1563 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1564 if (itv->output_mode == OUT_UDMA_YUV &&
1565 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1566 IVTV_YUV_MODE_PROGRESSIVE) {
1567 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1568 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001569 }
1570 if (ev->type)
1571 return 0;
1572 if (nonblocking)
1573 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001574 /* Wait for event. Note that serialize_lock is locked,
1575 so to allow other processes to access the driver while
1576 we are waiting unlock first and later lock again. */
1577 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001578 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1579 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1580 schedule();
1581 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001582 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001583 if (signal_pending(current)) {
1584 /* return if a signal was received */
1585 IVTV_DEBUG_INFO("User stopped wait for event\n");
1586 return -EINTR;
1587 }
1588 }
1589 break;
1590 }
1591
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001592 default:
1593 return -EINVAL;
1594 }
1595 return 0;
1596}
1597
1598static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1599 unsigned int cmd, void *arg)
1600{
1601 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1602 struct ivtv *itv = id->itv;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001603 int ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001604
Hans Verkuild46c17d2007-03-10 17:59:15 -03001605 /* check priority */
1606 switch (cmd) {
1607 case VIDIOC_S_CTRL:
1608 case VIDIOC_S_STD:
1609 case VIDIOC_S_INPUT:
1610 case VIDIOC_S_OUTPUT:
1611 case VIDIOC_S_TUNER:
1612 case VIDIOC_S_FREQUENCY:
1613 case VIDIOC_S_FMT:
1614 case VIDIOC_S_CROP:
1615 case VIDIOC_S_AUDIO:
1616 case VIDIOC_S_AUDOUT:
1617 case VIDIOC_S_EXT_CTRLS:
1618 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001619 case VIDIOC_OVERLAY:
Hans Verkuild46c17d2007-03-10 17:59:15 -03001620 ret = v4l2_prio_check(&itv->prio, &id->prio);
1621 if (ret)
1622 return ret;
1623 }
1624
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001625 switch (cmd) {
1626 case VIDIOC_DBG_G_REGISTER:
1627 case VIDIOC_DBG_S_REGISTER:
1628 case VIDIOC_G_CHIP_IDENT:
1629 case VIDIOC_INT_S_AUDIO_ROUTING:
1630 case VIDIOC_INT_RESET:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001631 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1632 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1633 v4l_printk_ioctl(cmd);
1634 }
1635 return ivtv_debug_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001636
Hans Verkuild46c17d2007-03-10 17:59:15 -03001637 case VIDIOC_G_PRIORITY:
1638 case VIDIOC_S_PRIORITY:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001639 case VIDIOC_QUERYCAP:
1640 case VIDIOC_ENUMINPUT:
1641 case VIDIOC_G_INPUT:
1642 case VIDIOC_S_INPUT:
1643 case VIDIOC_ENUMOUTPUT:
1644 case VIDIOC_G_OUTPUT:
1645 case VIDIOC_S_OUTPUT:
1646 case VIDIOC_G_FMT:
1647 case VIDIOC_S_FMT:
1648 case VIDIOC_TRY_FMT:
1649 case VIDIOC_ENUM_FMT:
Hans Verkuil987e00b2007-05-29 13:03:27 -03001650 case VIDIOC_CROPCAP:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001651 case VIDIOC_G_CROP:
1652 case VIDIOC_S_CROP:
1653 case VIDIOC_G_FREQUENCY:
1654 case VIDIOC_S_FREQUENCY:
1655 case VIDIOC_ENUMSTD:
1656 case VIDIOC_G_STD:
1657 case VIDIOC_S_STD:
1658 case VIDIOC_S_TUNER:
1659 case VIDIOC_G_TUNER:
1660 case VIDIOC_ENUMAUDIO:
1661 case VIDIOC_S_AUDIO:
1662 case VIDIOC_G_AUDIO:
1663 case VIDIOC_ENUMAUDOUT:
1664 case VIDIOC_S_AUDOUT:
1665 case VIDIOC_G_AUDOUT:
1666 case VIDIOC_G_SLICED_VBI_CAP:
1667 case VIDIOC_LOG_STATUS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001668 case VIDIOC_G_ENC_INDEX:
1669 case VIDIOC_ENCODER_CMD:
1670 case VIDIOC_TRY_ENCODER_CMD:
1671 case VIDIOC_G_FBUF:
1672 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001673 case VIDIOC_OVERLAY:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001674 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1675 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1676 v4l_printk_ioctl(cmd);
1677 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001678 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1679
1680 case VIDIOC_QUERYMENU:
1681 case VIDIOC_QUERYCTRL:
1682 case VIDIOC_S_CTRL:
1683 case VIDIOC_G_CTRL:
1684 case VIDIOC_S_EXT_CTRLS:
1685 case VIDIOC_G_EXT_CTRLS:
1686 case VIDIOC_TRY_EXT_CTRLS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001687 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1688 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1689 v4l_printk_ioctl(cmd);
1690 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001691 return ivtv_control_ioctls(itv, cmd, arg);
1692
1693 case IVTV_IOC_DMA_FRAME:
1694 case VIDEO_GET_PTS:
1695 case VIDEO_GET_FRAME_COUNT:
1696 case VIDEO_GET_EVENT:
1697 case VIDEO_PLAY:
1698 case VIDEO_STOP:
1699 case VIDEO_FREEZE:
1700 case VIDEO_CONTINUE:
1701 case VIDEO_COMMAND:
1702 case VIDEO_TRY_COMMAND:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001703 return ivtv_decoder_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001704
1705 case 0x00005401: /* Handle isatty() calls */
1706 return -EINVAL;
1707 default:
1708 return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
1709 ivtv_v4l2_do_ioctl);
1710 }
1711 return 0;
1712}
1713
Hans Verkuilbaa40722007-08-19 07:10:55 -03001714static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1715 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001716{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001717 /* Filter dvb ioctls that cannot be handled by video_usercopy */
1718 switch (cmd) {
1719 case VIDEO_SELECT_SOURCE:
1720 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1721 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1722 return -EINVAL;
1723 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1724
1725 case AUDIO_SET_MUTE:
1726 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1727 itv->speed_mute_audio = arg;
1728 return 0;
1729
1730 case AUDIO_CHANNEL_SELECT:
1731 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1732 if (arg > AUDIO_STEREO_SWAPPED)
1733 return -EINVAL;
1734 itv->audio_stereo_mode = arg;
1735 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1736 return 0;
1737
1738 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1739 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1740 if (arg > AUDIO_STEREO_SWAPPED)
1741 return -EINVAL;
1742 itv->audio_bilingual_mode = arg;
1743 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1744 return 0;
1745
1746 default:
1747 break;
1748 }
1749 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
1750}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001751
1752int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1753 unsigned long arg)
1754{
1755 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1756 struct ivtv *itv = id->itv;
1757 int res;
1758
1759 mutex_lock(&itv->serialize_lock);
1760 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1761 mutex_unlock(&itv->serialize_lock);
1762 return res;
1763}