blob: edef2a579617e722c5357b93775f88620faff327 [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) {
Richard Knutssone1ba33d2007-12-02 14:47:01 -0300676 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300677 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300678 return 0;
679 }
680 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
681 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
682 if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
683 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
684 return -EINVAL;
685 }
686
687 case VIDIOC_INT_S_AUDIO_ROUTING: {
688 struct v4l2_routing *route = arg;
689
Hans Verkuil33c0fca2007-08-23 06:32:46 -0300690 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300691 break;
692 }
693
Hans Verkuil2cc72092007-08-04 05:06:23 -0300694 case VIDIOC_INT_RESET: {
695 u32 val = *(u32 *)arg;
696
697 if ((val == 0 && itv->options.newi2c) || (val & 0x01)) {
698 ivtv_reset_ir_gpio(itv);
699 }
700 if (val & 0x02) {
Richard Knutsson14d5deb2007-12-08 10:35:06 -0300701 itv->video_dec_func(itv, cmd, NULL);
Hans Verkuil2cc72092007-08-04 05:06:23 -0300702 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300703 break;
Hans Verkuil2cc72092007-08-04 05:06:23 -0300704 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300705
706 default:
707 return -EINVAL;
708 }
709 return 0;
710}
711
712int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
713{
714 struct ivtv_open_id *id = NULL;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -0300715 u32 data[CX2341X_MBOX_MAX_DATA];
Ian Armstrong77aded62007-11-05 14:27:09 -0300716 int streamtype = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300717
Ian Armstrong77aded62007-11-05 14:27:09 -0300718 if (filp) {
719 id = (struct ivtv_open_id *)filp->private_data;
720 streamtype = id->type;
721 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300722
723 switch (cmd) {
Hans Verkuild46c17d2007-03-10 17:59:15 -0300724 case VIDIOC_G_PRIORITY:
725 {
726 enum v4l2_priority *p = arg;
727
728 *p = v4l2_prio_max(&itv->prio);
729 break;
730 }
731
732 case VIDIOC_S_PRIORITY:
733 {
734 enum v4l2_priority *prio = arg;
735
736 return v4l2_prio_change(&itv->prio, &id->prio, *prio);
737 }
738
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300739 case VIDIOC_QUERYCAP:{
740 struct v4l2_capability *vcap = arg;
741
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300742 memset(vcap, 0, sizeof(*vcap));
743 strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
744 strcpy(vcap->card, itv->card_name); /* card type */
745 strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
746 vcap->version = IVTV_DRIVER_VERSION; /* version */
747 vcap->capabilities = itv->v4l2_cap; /* capabilities */
748
749 /* reserved.. must set to 0! */
750 vcap->reserved[0] = vcap->reserved[1] =
751 vcap->reserved[2] = vcap->reserved[3] = 0;
752 break;
753 }
754
755 case VIDIOC_ENUMAUDIO:{
756 struct v4l2_audio *vin = arg;
757
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300758 return ivtv_get_audio_input(itv, vin->index, vin);
759 }
760
761 case VIDIOC_G_AUDIO:{
762 struct v4l2_audio *vin = arg;
763
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300764 vin->index = itv->audio_input;
765 return ivtv_get_audio_input(itv, vin->index, vin);
766 }
767
768 case VIDIOC_S_AUDIO:{
769 struct v4l2_audio *vout = arg;
770
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300771 if (vout->index >= itv->nof_audio_inputs)
772 return -EINVAL;
773 itv->audio_input = vout->index;
774 ivtv_audio_set_io(itv);
775 break;
776 }
777
778 case VIDIOC_ENUMAUDOUT:{
779 struct v4l2_audioout *vin = arg;
780
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300781 /* set it to defaults from our table */
782 return ivtv_get_audio_output(itv, vin->index, vin);
783 }
784
785 case VIDIOC_G_AUDOUT:{
786 struct v4l2_audioout *vin = arg;
787
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300788 vin->index = 0;
789 return ivtv_get_audio_output(itv, vin->index, vin);
790 }
791
792 case VIDIOC_S_AUDOUT:{
793 struct v4l2_audioout *vout = arg;
794
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300795 return ivtv_get_audio_output(itv, vout->index, vout);
796 }
797
798 case VIDIOC_ENUMINPUT:{
799 struct v4l2_input *vin = arg;
800
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300801 /* set it to defaults from our table */
802 return ivtv_get_input(itv, vin->index, vin);
803 }
804
805 case VIDIOC_ENUMOUTPUT:{
806 struct v4l2_output *vout = arg;
807
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300808 return ivtv_get_output(itv, vout->index, vout);
809 }
810
811 case VIDIOC_TRY_FMT:
812 case VIDIOC_S_FMT: {
813 struct v4l2_format *fmt = arg;
814
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300815 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);
816 }
817
818 case VIDIOC_G_FMT: {
819 struct v4l2_format *fmt = arg;
820 int type = fmt->type;
821
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300822 memset(fmt, 0, sizeof(*fmt));
823 fmt->type = type;
824 return ivtv_get_fmt(itv, id->type, fmt);
825 }
826
Hans Verkuil987e00b2007-05-29 13:03:27 -0300827 case VIDIOC_CROPCAP: {
828 struct v4l2_cropcap *cropcap = arg;
829
830 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
831 cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
832 return -EINVAL;
833 cropcap->bounds.top = cropcap->bounds.left = 0;
834 cropcap->bounds.width = 720;
835 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
836 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
837 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
838 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
Ian Armstrong77aded62007-11-05 14:27:09 -0300839 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
840 cropcap->bounds.width = itv->yuv_info.osd_full_w;
841 cropcap->bounds.height = itv->yuv_info.osd_full_h;
842 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
843 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300844 } else {
845 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
846 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
847 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
848 }
849 cropcap->defrect = cropcap->bounds;
850 return 0;
851 }
852
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300853 case VIDIOC_S_CROP: {
854 struct v4l2_crop *crop = arg;
855
Hans Verkuil987e00b2007-05-29 13:03:27 -0300856 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
857 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300858 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
859 itv->yuv_info.main_rect = crop->c;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300860 return 0;
Ian Armstrong77aded62007-11-05 14:27:09 -0300861 } else {
862 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
863 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
864 itv->main_rect = crop->c;
865 return 0;
866 }
Hans Verkuil987e00b2007-05-29 13:03:27 -0300867 }
868 return -EINVAL;
869 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300870 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
871 return -EINVAL;
872 return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
873 }
874
875 case VIDIOC_G_CROP: {
876 struct v4l2_crop *crop = arg;
877
Hans Verkuil987e00b2007-05-29 13:03:27 -0300878 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
879 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300880 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
881 crop->c = itv->yuv_info.main_rect;
882 else
883 crop->c = itv->main_rect;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300884 return 0;
885 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300886 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
887 return -EINVAL;
888 return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
889 }
890
891 case VIDIOC_ENUM_FMT: {
892 static struct v4l2_fmtdesc formats[] = {
893 { 0, 0, 0,
Ian Armstrong368f0802007-11-05 14:30:03 -0300894 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300895 { 0, 0, 0, 0 }
896 },
897 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
898 "MPEG", V4L2_PIX_FMT_MPEG,
899 { 0, 0, 0, 0 }
900 }
901 };
902 struct v4l2_fmtdesc *fmt = arg;
903 enum v4l2_buf_type type = fmt->type;
904
905 switch (type) {
906 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
907 break;
908 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
909 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
910 return -EINVAL;
911 break;
912 default:
913 return -EINVAL;
914 }
915 if (fmt->index > 1)
916 return -EINVAL;
917 *fmt = formats[fmt->index];
918 fmt->type = type;
919 return 0;
920 }
921
922 case VIDIOC_G_INPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300923 *(int *)arg = itv->active_input;
924 break;
925 }
926
927 case VIDIOC_S_INPUT:{
928 int inp = *(int *)arg;
929
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300930 if (inp < 0 || inp >= itv->nof_inputs)
931 return -EINVAL;
932
933 if (inp == itv->active_input) {
934 IVTV_DEBUG_INFO("Input unchanged\n");
935 break;
936 }
Hans Verkuil3562c432007-08-18 11:46:05 -0300937 if (atomic_read(&itv->capturing) > 0) {
938 return -EBUSY;
939 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300940 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
941 itv->active_input, inp);
942
943 itv->active_input = inp;
944 /* Set the audio input to whatever is appropriate for the
945 input type. */
946 itv->audio_input = itv->card->video_inputs[inp].audio_index;
947
948 /* prevent others from messing with the streams until
949 we're finished changing inputs. */
950 ivtv_mute(itv);
951 ivtv_video_set_io(itv);
952 ivtv_audio_set_io(itv);
953 ivtv_unmute(itv);
954 break;
955 }
956
957 case VIDIOC_G_OUTPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300958 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
959 return -EINVAL;
960 *(int *)arg = itv->active_output;
961 break;
962 }
963
964 case VIDIOC_S_OUTPUT:{
965 int outp = *(int *)arg;
966 struct v4l2_routing route;
967
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300968 if (outp >= itv->card->nof_outputs)
969 return -EINVAL;
970
971 if (outp == itv->active_output) {
972 IVTV_DEBUG_INFO("Output unchanged\n");
973 break;
974 }
975 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
976 itv->active_output, outp);
977
978 itv->active_output = outp;
979 route.input = SAA7127_INPUT_TYPE_NORMAL;
980 route.output = itv->card->video_outputs[outp].video_output;
981 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
982 break;
983 }
984
985 case VIDIOC_G_FREQUENCY:{
986 struct v4l2_frequency *vf = arg;
987
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300988 if (vf->tuner != 0)
989 return -EINVAL;
990 ivtv_call_i2c_clients(itv, cmd, arg);
991 break;
992 }
993
994 case VIDIOC_S_FREQUENCY:{
995 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
996
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300997 if (vf.tuner != 0)
998 return -EINVAL;
999
1000 ivtv_mute(itv);
1001 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
1002 ivtv_call_i2c_clients(itv, cmd, &vf);
1003 ivtv_unmute(itv);
1004 break;
1005 }
1006
1007 case VIDIOC_ENUMSTD:{
1008 struct v4l2_standard *vs = arg;
1009 int idx = vs->index;
1010
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001011 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
1012 return -EINVAL;
1013
1014 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
1015 ivtv_std_60hz : ivtv_std_50hz;
1016 vs->index = idx;
1017 vs->id = enum_stds[idx].std;
1018 strcpy(vs->name, enum_stds[idx].name);
1019 break;
1020 }
1021
1022 case VIDIOC_G_STD:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001023 *(v4l2_std_id *) arg = itv->std;
1024 break;
1025 }
1026
1027 case VIDIOC_S_STD: {
1028 v4l2_std_id std = *(v4l2_std_id *) arg;
1029
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001030 if ((std & V4L2_STD_ALL) == 0)
1031 return -EINVAL;
1032
1033 if (std == itv->std)
1034 break;
1035
1036 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1037 atomic_read(&itv->capturing) > 0 ||
1038 atomic_read(&itv->decoding) > 0) {
1039 /* Switching standard would turn off the radio or mess
1040 with already running streams, prevent that by
1041 returning EBUSY. */
1042 return -EBUSY;
1043 }
1044
1045 itv->std = std;
1046 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
1047 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1048 itv->params.width = 720;
1049 itv->params.height = itv->is_50hz ? 576 : 480;
1050 itv->vbi.count = itv->is_50hz ? 18 : 12;
1051 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1052 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1053 if (itv->hw_flags & IVTV_HW_CX25840) {
1054 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1055 }
Hans Verkuilc4385092007-06-07 09:04:03 -03001056 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001057
1058 /* Tuner */
1059 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1060
1061 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1062 /* set display standard */
1063 itv->std_out = std;
1064 itv->is_out_60hz = itv->is_60hz;
1065 itv->is_out_50hz = itv->is_50hz;
1066 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1067 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1068 itv->main_rect.left = itv->main_rect.top = 0;
1069 itv->main_rect.width = 720;
1070 itv->main_rect.height = itv->params.height;
1071 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1072 720, itv->main_rect.height, 0, 0);
Ian Armstrong77aded62007-11-05 14:27:09 -03001073 itv->yuv_info.main_rect = itv->main_rect;
1074 if (!itv->osd_info) {
1075 itv->yuv_info.osd_full_w = 720;
1076 itv->yuv_info.osd_full_h =
1077 itv->is_out_50hz ? 576 : 480;
1078 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001079 }
1080 break;
1081 }
1082
1083 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
1084 struct v4l2_tuner *vt = arg;
1085
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001086 if (vt->index != 0)
1087 return -EINVAL;
1088
1089 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1090 break;
1091 }
1092
1093 case VIDIOC_G_TUNER: {
1094 struct v4l2_tuner *vt = arg;
1095
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001096 if (vt->index != 0)
1097 return -EINVAL;
1098
1099 memset(vt, 0, sizeof(*vt));
1100 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1101
1102 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1103 strcpy(vt->name, "ivtv Radio Tuner");
1104 vt->type = V4L2_TUNER_RADIO;
1105 } else {
1106 strcpy(vt->name, "ivtv TV Tuner");
1107 vt->type = V4L2_TUNER_ANALOG_TV;
1108 }
1109 break;
1110 }
1111
1112 case VIDIOC_G_SLICED_VBI_CAP: {
1113 struct v4l2_sliced_vbi_cap *cap = arg;
1114 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1115 int f, l;
1116 enum v4l2_buf_type type = cap->type;
1117
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001118 memset(cap, 0, sizeof(*cap));
1119 cap->type = type;
1120 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1121 for (f = 0; f < 2; f++) {
1122 for (l = 0; l < 24; l++) {
1123 if (valid_service_line(f, l, itv->is_50hz)) {
1124 cap->service_lines[f][l] = set;
1125 }
1126 }
1127 }
1128 return 0;
1129 }
1130 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1131 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1132 return -EINVAL;
1133 if (itv->is_60hz) {
1134 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1135 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1136 } else {
1137 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1138 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1139 }
1140 return 0;
1141 }
1142 return -EINVAL;
1143 }
1144
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001145 case VIDIOC_G_ENC_INDEX: {
1146 struct v4l2_enc_idx *idx = arg;
Hans Verkuil5614b022007-08-23 17:48:41 -03001147 struct v4l2_enc_idx_entry *e = idx->entry;
1148 int entries;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001149 int i;
1150
Hans Verkuil5614b022007-08-23 17:48:41 -03001151 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001152 IVTV_MAX_PGM_INDEX;
Hans Verkuil5614b022007-08-23 17:48:41 -03001153 if (entries > V4L2_ENC_IDX_ENTRIES)
1154 entries = V4L2_ENC_IDX_ENTRIES;
1155 idx->entries = 0;
1156 for (i = 0; i < entries; i++) {
1157 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1158 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1159 idx->entries++;
1160 e++;
1161 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001162 }
1163 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1164 break;
1165 }
1166
1167 case VIDIOC_ENCODER_CMD:
1168 case VIDIOC_TRY_ENCODER_CMD: {
1169 struct v4l2_encoder_cmd *enc = arg;
1170 int try = cmd == VIDIOC_TRY_ENCODER_CMD;
1171
Hans Verkuil25415cf2007-03-10 18:29:48 -03001172 memset(&enc->raw, 0, sizeof(enc->raw));
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001173 switch (enc->cmd) {
1174 case V4L2_ENC_CMD_START:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001175 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001176 enc->flags = 0;
1177 if (try)
1178 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001179 return ivtv_start_capture(id);
1180
1181 case V4L2_ENC_CMD_STOP:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001182 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
Hans Verkuil018ba852007-04-10 18:59:09 -03001183 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001184 if (try)
1185 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001186 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1187 return 0;
1188
1189 case V4L2_ENC_CMD_PAUSE:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001190 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001191 enc->flags = 0;
1192 if (try)
1193 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001194 if (!atomic_read(&itv->capturing))
1195 return -EPERM;
1196 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1197 return 0;
1198 ivtv_mute(itv);
1199 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1200 break;
1201
1202 case V4L2_ENC_CMD_RESUME:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001203 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001204 enc->flags = 0;
1205 if (try)
1206 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001207 if (!atomic_read(&itv->capturing))
1208 return -EPERM;
1209 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1210 return 0;
1211 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1212 ivtv_unmute(itv);
1213 break;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001214 default:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001215 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
Hans Verkuil25415cf2007-03-10 18:29:48 -03001216 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001217 }
1218 break;
1219 }
1220
1221 case VIDIOC_G_FBUF: {
1222 struct v4l2_framebuffer *fb = arg;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001223 int pixfmt;
1224 static u32 pixel_format[16] = {
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001225 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001226 V4L2_PIX_FMT_RGB565,
1227 V4L2_PIX_FMT_RGB555,
1228 V4L2_PIX_FMT_RGB444,
1229 V4L2_PIX_FMT_RGB32,
1230 0,
1231 0,
1232 0,
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001233 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1234 V4L2_PIX_FMT_YUV565,
1235 V4L2_PIX_FMT_YUV555,
1236 V4L2_PIX_FMT_YUV444,
1237 V4L2_PIX_FMT_YUV32,
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001238 0,
1239 0,
1240 0,
1241 };
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001242
1243 memset(fb, 0, sizeof(*fb));
1244 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001245 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001246 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001247 V4L2_FBUF_CAP_GLOBAL_ALPHA;
1248 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1249 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1250 pixfmt = (data[0] >> 3) & 0xf;
1251 fb->fmt.pixelformat = pixel_format[pixfmt];
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001252 fb->fmt.width = itv->osd_rect.width;
1253 fb->fmt.height = itv->osd_rect.height;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001254 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001255 if (itv->osd_chroma_key_state)
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001256 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001257 if (itv->osd_global_alpha_state)
1258 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1259 pixfmt &= 7;
1260 /* no local alpha for RGB565 or unknown formats */
1261 if (pixfmt == 1 || pixfmt > 4)
1262 break;
1263 /* 16-bit formats have inverted local alpha */
1264 if (pixfmt == 2 || pixfmt == 3)
1265 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1266 else
1267 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
1268 if (itv->osd_local_alpha_state) {
1269 /* 16-bit formats have inverted local alpha */
1270 if (pixfmt == 2 || pixfmt == 3)
1271 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1272 else
1273 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1274 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001275 break;
1276 }
1277
1278 case VIDIOC_S_FBUF: {
1279 struct v4l2_framebuffer *fb = arg;
1280
1281 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001282 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001283 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001284 itv->osd_local_alpha_state =
1285 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001286 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
Hans Verkuilc3624f92007-07-31 07:15:56 -03001287 ivtv_set_osd_alpha(itv);
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001288 break;
1289 }
1290
Hans Verkuil7c03a442007-08-19 18:59:42 -03001291 case VIDIOC_OVERLAY: {
1292 int *on = arg;
1293
1294 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1295 return -EINVAL;
1296 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
1297 break;
1298 }
1299
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001300 case VIDIOC_LOG_STATUS:
1301 {
1302 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1303 struct v4l2_input vidin;
1304 struct v4l2_audio audin;
1305 int i;
1306
1307 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
Hans Verkuil94104aa2007-08-04 04:56:00 -03001308 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001309 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1310 struct tveeprom tv;
1311
1312 ivtv_read_eeprom(itv, &tv);
1313 }
1314 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1315 ivtv_get_input(itv, itv->active_input, &vidin);
1316 ivtv_get_audio_input(itv, itv->audio_input, &audin);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001317 IVTV_INFO("Video Input: %s\n", vidin.name);
1318 IVTV_INFO("Audio Input: %s%s\n", audin.name,
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001319 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001320 if (has_output) {
1321 struct v4l2_output vidout;
1322 struct v4l2_audioout audout;
1323 int mode = itv->output_mode;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001324 static const char * const output_modes[5] = {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001325 "None",
1326 "MPEG Streaming",
1327 "YUV Streaming",
1328 "YUV Frames",
1329 "Passthrough",
1330 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001331 static const char * const audio_modes[5] = {
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001332 "Stereo",
1333 "Left",
1334 "Right",
1335 "Mono",
1336 "Swapped"
1337 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001338 static const char * const alpha_mode[4] = {
Hans Verkuil7c03a442007-08-19 18:59:42 -03001339 "None",
1340 "Global",
1341 "Local",
1342 "Global and Local"
1343 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001344 static const char * const pixel_format[16] = {
1345 "ARGB Indexed",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001346 "RGB 5:6:5",
1347 "ARGB 1:5:5:5",
1348 "ARGB 1:4:4:4",
1349 "ARGB 8:8:8:8",
1350 "5",
1351 "6",
1352 "7",
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001353 "AYUV Indexed",
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001354 "YUV 5:6:5",
1355 "AYUV 1:5:5:5",
1356 "AYUV 1:4:4:4",
1357 "AYUV 8:8:8:8",
1358 "13",
1359 "14",
1360 "15",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001361 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001362
1363 ivtv_get_output(itv, itv->active_output, &vidout);
1364 ivtv_get_audio_output(itv, 0, &audout);
1365 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001366 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1367 audio_modes[itv->audio_stereo_mode],
1368 audio_modes[itv->audio_bilingual_mode]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001369 if (mode < 0 || mode > OUT_PASSTHROUGH)
1370 mode = OUT_NONE;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001371 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1372 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001373 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001374 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1375 data[0] & 1 ? "On" : "Off",
1376 alpha_mode[(data[0] >> 1) & 0x3],
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001377 pixel_format[(data[0] >> 3) & 0xf]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001378 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001379 IVTV_INFO("Tuner: %s\n",
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001380 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1381 cx2341x_log_status(&itv->params, itv->name);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001382 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001383 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1384 struct ivtv_stream *s = &itv->streams[i];
1385
1386 if (s->v4l2dev == NULL || s->buffers == 0)
1387 continue;
1388 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1389 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1390 (s->buffers * s->buf_size) / 1024, s->buffers);
1391 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001392 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 -03001393 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1394 break;
1395 }
1396
1397 default:
1398 return -EINVAL;
1399 }
1400 return 0;
1401}
1402
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001403static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001404{
1405 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1406 struct ivtv *itv = id->itv;
1407 int nonblocking = filp->f_flags & O_NONBLOCK;
1408 struct ivtv_stream *s = &itv->streams[id->type];
1409
1410 switch (cmd) {
1411 case IVTV_IOC_DMA_FRAME: {
1412 struct ivtv_dma_frame *args = arg;
1413
1414 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1415 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1416 return -EINVAL;
1417 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1418 return -EINVAL;
1419 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1420 return 0;
1421 if (ivtv_claim_stream(id, id->type)) {
1422 return -EBUSY;
1423 }
1424 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1425 ivtv_release_stream(s);
1426 return -EBUSY;
1427 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001428 /* Mark that this file handle started the UDMA_YUV mode */
1429 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001430 if (args->y_source == NULL)
1431 return 0;
1432 return ivtv_yuv_prep_frame(itv, args);
1433 }
1434
1435 case VIDEO_GET_PTS: {
1436 u32 data[CX2341X_MBOX_MAX_DATA];
1437 u64 *pts = arg;
1438
1439 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1440 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1441 *pts = s->dma_pts;
1442 break;
1443 }
1444 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1445 return -EINVAL;
1446
1447 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1448 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1449 (u64)itv->last_dec_timing[1];
1450 break;
1451 }
1452 *pts = 0;
1453 if (atomic_read(&itv->decoding)) {
1454 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1455 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1456 return -EIO;
1457 }
1458 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1459 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1460 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1461 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1462 }
1463 break;
1464 }
1465
1466 case VIDEO_GET_FRAME_COUNT: {
1467 u32 data[CX2341X_MBOX_MAX_DATA];
1468 u64 *frame = arg;
1469
1470 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1471 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1472 *frame = 0;
1473 break;
1474 }
1475 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1476 return -EINVAL;
1477
1478 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1479 *frame = itv->last_dec_timing[0];
1480 break;
1481 }
1482 *frame = 0;
1483 if (atomic_read(&itv->decoding)) {
1484 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1485 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1486 return -EIO;
1487 }
1488 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1489 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1490 *frame = data[0];
1491 }
1492 break;
1493 }
1494
1495 case VIDEO_PLAY: {
1496 struct video_command vc;
1497
1498 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1499 memset(&vc, 0, sizeof(vc));
1500 vc.cmd = VIDEO_CMD_PLAY;
1501 return ivtv_video_command(itv, id, &vc, 0);
1502 }
1503
1504 case VIDEO_STOP: {
1505 struct video_command vc;
1506
1507 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1508 memset(&vc, 0, sizeof(vc));
1509 vc.cmd = VIDEO_CMD_STOP;
1510 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1511 return ivtv_video_command(itv, id, &vc, 0);
1512 }
1513
1514 case VIDEO_FREEZE: {
1515 struct video_command vc;
1516
1517 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1518 memset(&vc, 0, sizeof(vc));
1519 vc.cmd = VIDEO_CMD_FREEZE;
1520 return ivtv_video_command(itv, id, &vc, 0);
1521 }
1522
1523 case VIDEO_CONTINUE: {
1524 struct video_command vc;
1525
1526 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1527 memset(&vc, 0, sizeof(vc));
1528 vc.cmd = VIDEO_CMD_CONTINUE;
1529 return ivtv_video_command(itv, id, &vc, 0);
1530 }
1531
1532 case VIDEO_COMMAND:
1533 case VIDEO_TRY_COMMAND: {
1534 struct video_command *vc = arg;
1535 int try = (cmd == VIDEO_TRY_COMMAND);
1536
1537 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001538 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001539 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001540 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001541 return ivtv_video_command(itv, id, vc, try);
1542 }
1543
1544 case VIDEO_GET_EVENT: {
1545 struct video_event *ev = arg;
1546 DEFINE_WAIT(wait);
1547
1548 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1549 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1550 return -EINVAL;
1551 memset(ev, 0, sizeof(*ev));
1552 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1553
1554 while (1) {
1555 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1556 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1557 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1558 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001559 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1560 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1561 if (itv->output_mode == OUT_UDMA_YUV &&
1562 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1563 IVTV_YUV_MODE_PROGRESSIVE) {
1564 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1565 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001566 }
1567 if (ev->type)
1568 return 0;
1569 if (nonblocking)
1570 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001571 /* Wait for event. Note that serialize_lock is locked,
1572 so to allow other processes to access the driver while
1573 we are waiting unlock first and later lock again. */
1574 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001575 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1576 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1577 schedule();
1578 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001579 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001580 if (signal_pending(current)) {
1581 /* return if a signal was received */
1582 IVTV_DEBUG_INFO("User stopped wait for event\n");
1583 return -EINTR;
1584 }
1585 }
1586 break;
1587 }
1588
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001589 default:
1590 return -EINVAL;
1591 }
1592 return 0;
1593}
1594
1595static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1596 unsigned int cmd, void *arg)
1597{
1598 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1599 struct ivtv *itv = id->itv;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001600 int ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001601
Hans Verkuild46c17d2007-03-10 17:59:15 -03001602 /* check priority */
1603 switch (cmd) {
1604 case VIDIOC_S_CTRL:
1605 case VIDIOC_S_STD:
1606 case VIDIOC_S_INPUT:
1607 case VIDIOC_S_OUTPUT:
1608 case VIDIOC_S_TUNER:
1609 case VIDIOC_S_FREQUENCY:
1610 case VIDIOC_S_FMT:
1611 case VIDIOC_S_CROP:
1612 case VIDIOC_S_AUDIO:
1613 case VIDIOC_S_AUDOUT:
1614 case VIDIOC_S_EXT_CTRLS:
1615 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001616 case VIDIOC_OVERLAY:
Hans Verkuild46c17d2007-03-10 17:59:15 -03001617 ret = v4l2_prio_check(&itv->prio, &id->prio);
1618 if (ret)
1619 return ret;
1620 }
1621
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001622 switch (cmd) {
1623 case VIDIOC_DBG_G_REGISTER:
1624 case VIDIOC_DBG_S_REGISTER:
1625 case VIDIOC_G_CHIP_IDENT:
1626 case VIDIOC_INT_S_AUDIO_ROUTING:
1627 case VIDIOC_INT_RESET:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001628 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1629 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1630 v4l_printk_ioctl(cmd);
1631 }
1632 return ivtv_debug_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001633
Hans Verkuild46c17d2007-03-10 17:59:15 -03001634 case VIDIOC_G_PRIORITY:
1635 case VIDIOC_S_PRIORITY:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001636 case VIDIOC_QUERYCAP:
1637 case VIDIOC_ENUMINPUT:
1638 case VIDIOC_G_INPUT:
1639 case VIDIOC_S_INPUT:
1640 case VIDIOC_ENUMOUTPUT:
1641 case VIDIOC_G_OUTPUT:
1642 case VIDIOC_S_OUTPUT:
1643 case VIDIOC_G_FMT:
1644 case VIDIOC_S_FMT:
1645 case VIDIOC_TRY_FMT:
1646 case VIDIOC_ENUM_FMT:
Hans Verkuil987e00b2007-05-29 13:03:27 -03001647 case VIDIOC_CROPCAP:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001648 case VIDIOC_G_CROP:
1649 case VIDIOC_S_CROP:
1650 case VIDIOC_G_FREQUENCY:
1651 case VIDIOC_S_FREQUENCY:
1652 case VIDIOC_ENUMSTD:
1653 case VIDIOC_G_STD:
1654 case VIDIOC_S_STD:
1655 case VIDIOC_S_TUNER:
1656 case VIDIOC_G_TUNER:
1657 case VIDIOC_ENUMAUDIO:
1658 case VIDIOC_S_AUDIO:
1659 case VIDIOC_G_AUDIO:
1660 case VIDIOC_ENUMAUDOUT:
1661 case VIDIOC_S_AUDOUT:
1662 case VIDIOC_G_AUDOUT:
1663 case VIDIOC_G_SLICED_VBI_CAP:
1664 case VIDIOC_LOG_STATUS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001665 case VIDIOC_G_ENC_INDEX:
1666 case VIDIOC_ENCODER_CMD:
1667 case VIDIOC_TRY_ENCODER_CMD:
1668 case VIDIOC_G_FBUF:
1669 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001670 case VIDIOC_OVERLAY:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001671 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1672 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1673 v4l_printk_ioctl(cmd);
1674 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001675 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1676
1677 case VIDIOC_QUERYMENU:
1678 case VIDIOC_QUERYCTRL:
1679 case VIDIOC_S_CTRL:
1680 case VIDIOC_G_CTRL:
1681 case VIDIOC_S_EXT_CTRLS:
1682 case VIDIOC_G_EXT_CTRLS:
1683 case VIDIOC_TRY_EXT_CTRLS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001684 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1685 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1686 v4l_printk_ioctl(cmd);
1687 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001688 return ivtv_control_ioctls(itv, cmd, arg);
1689
1690 case IVTV_IOC_DMA_FRAME:
1691 case VIDEO_GET_PTS:
1692 case VIDEO_GET_FRAME_COUNT:
1693 case VIDEO_GET_EVENT:
1694 case VIDEO_PLAY:
1695 case VIDEO_STOP:
1696 case VIDEO_FREEZE:
1697 case VIDEO_CONTINUE:
1698 case VIDEO_COMMAND:
1699 case VIDEO_TRY_COMMAND:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001700 return ivtv_decoder_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001701
1702 case 0x00005401: /* Handle isatty() calls */
1703 return -EINVAL;
1704 default:
1705 return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
1706 ivtv_v4l2_do_ioctl);
1707 }
1708 return 0;
1709}
1710
Hans Verkuilbaa40722007-08-19 07:10:55 -03001711static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1712 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001713{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001714 /* Filter dvb ioctls that cannot be handled by video_usercopy */
1715 switch (cmd) {
1716 case VIDEO_SELECT_SOURCE:
1717 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1718 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1719 return -EINVAL;
1720 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1721
1722 case AUDIO_SET_MUTE:
1723 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1724 itv->speed_mute_audio = arg;
1725 return 0;
1726
1727 case AUDIO_CHANNEL_SELECT:
1728 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1729 if (arg > AUDIO_STEREO_SWAPPED)
1730 return -EINVAL;
1731 itv->audio_stereo_mode = arg;
1732 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1733 return 0;
1734
1735 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1736 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1737 if (arg > AUDIO_STEREO_SWAPPED)
1738 return -EINVAL;
1739 itv->audio_bilingual_mode = arg;
1740 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1741 return 0;
1742
1743 default:
1744 break;
1745 }
1746 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
1747}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001748
1749int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1750 unsigned long arg)
1751{
1752 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1753 struct ivtv *itv = id->itv;
1754 int res;
1755
1756 mutex_lock(&itv->serialize_lock);
1757 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1758 mutex_unlock(&itv->serialize_lock);
1759 return res;
1760}