blob: f562cbbadc169e26ee5671891811d911a341b93e [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;
Ian Armstrong88ab0752008-04-22 14:42:14 -0300715 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -0300716 u32 data[CX2341X_MBOX_MAX_DATA];
Ian Armstrong77aded62007-11-05 14:27:09 -0300717 int streamtype = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300718
Ian Armstrong77aded62007-11-05 14:27:09 -0300719 if (filp) {
720 id = (struct ivtv_open_id *)filp->private_data;
721 streamtype = id->type;
722 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300723
724 switch (cmd) {
Hans Verkuild46c17d2007-03-10 17:59:15 -0300725 case VIDIOC_G_PRIORITY:
726 {
727 enum v4l2_priority *p = arg;
728
729 *p = v4l2_prio_max(&itv->prio);
730 break;
731 }
732
733 case VIDIOC_S_PRIORITY:
734 {
735 enum v4l2_priority *prio = arg;
736
737 return v4l2_prio_change(&itv->prio, &id->prio, *prio);
738 }
739
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300740 case VIDIOC_QUERYCAP:{
741 struct v4l2_capability *vcap = arg;
742
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300743 memset(vcap, 0, sizeof(*vcap));
744 strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
745 strcpy(vcap->card, itv->card_name); /* card type */
746 strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
747 vcap->version = IVTV_DRIVER_VERSION; /* version */
748 vcap->capabilities = itv->v4l2_cap; /* capabilities */
749
750 /* reserved.. must set to 0! */
751 vcap->reserved[0] = vcap->reserved[1] =
752 vcap->reserved[2] = vcap->reserved[3] = 0;
753 break;
754 }
755
756 case VIDIOC_ENUMAUDIO:{
757 struct v4l2_audio *vin = arg;
758
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300759 return ivtv_get_audio_input(itv, vin->index, vin);
760 }
761
762 case VIDIOC_G_AUDIO:{
763 struct v4l2_audio *vin = arg;
764
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300765 vin->index = itv->audio_input;
766 return ivtv_get_audio_input(itv, vin->index, vin);
767 }
768
769 case VIDIOC_S_AUDIO:{
770 struct v4l2_audio *vout = arg;
771
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300772 if (vout->index >= itv->nof_audio_inputs)
773 return -EINVAL;
774 itv->audio_input = vout->index;
775 ivtv_audio_set_io(itv);
776 break;
777 }
778
779 case VIDIOC_ENUMAUDOUT:{
780 struct v4l2_audioout *vin = arg;
781
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300782 /* set it to defaults from our table */
783 return ivtv_get_audio_output(itv, vin->index, vin);
784 }
785
786 case VIDIOC_G_AUDOUT:{
787 struct v4l2_audioout *vin = arg;
788
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300789 vin->index = 0;
790 return ivtv_get_audio_output(itv, vin->index, vin);
791 }
792
793 case VIDIOC_S_AUDOUT:{
794 struct v4l2_audioout *vout = arg;
795
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300796 return ivtv_get_audio_output(itv, vout->index, vout);
797 }
798
799 case VIDIOC_ENUMINPUT:{
800 struct v4l2_input *vin = arg;
801
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300802 /* set it to defaults from our table */
803 return ivtv_get_input(itv, vin->index, vin);
804 }
805
806 case VIDIOC_ENUMOUTPUT:{
807 struct v4l2_output *vout = arg;
808
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300809 return ivtv_get_output(itv, vout->index, vout);
810 }
811
812 case VIDIOC_TRY_FMT:
813 case VIDIOC_S_FMT: {
814 struct v4l2_format *fmt = arg;
815
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300816 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);
817 }
818
819 case VIDIOC_G_FMT: {
820 struct v4l2_format *fmt = arg;
821 int type = fmt->type;
822
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300823 memset(fmt, 0, sizeof(*fmt));
824 fmt->type = type;
825 return ivtv_get_fmt(itv, id->type, fmt);
826 }
827
Hans Verkuil987e00b2007-05-29 13:03:27 -0300828 case VIDIOC_CROPCAP: {
829 struct v4l2_cropcap *cropcap = arg;
830
831 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
832 cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
833 return -EINVAL;
834 cropcap->bounds.top = cropcap->bounds.left = 0;
835 cropcap->bounds.width = 720;
836 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
837 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
838 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
839 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
Ian Armstrong77aded62007-11-05 14:27:09 -0300840 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Ian Armstrong88ab0752008-04-22 14:42:14 -0300841 if (yi->track_osd) {
842 cropcap->bounds.width = yi->osd_full_w;
843 cropcap->bounds.height = yi->osd_full_h;
844 } else {
845 cropcap->bounds.width = 720;
846 cropcap->bounds.height =
847 itv->is_out_50hz ? 576 : 480;
848 }
Ian Armstrong77aded62007-11-05 14:27:09 -0300849 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
850 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300851 } else {
852 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
853 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
854 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
855 }
856 cropcap->defrect = cropcap->bounds;
857 return 0;
858 }
859
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300860 case VIDIOC_S_CROP: {
861 struct v4l2_crop *crop = arg;
862
Hans Verkuil987e00b2007-05-29 13:03:27 -0300863 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
864 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300865 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Ian Armstrong88ab0752008-04-22 14:42:14 -0300866 yi->main_rect = crop->c;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300867 return 0;
Ian Armstrong77aded62007-11-05 14:27:09 -0300868 } else {
869 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
870 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
871 itv->main_rect = crop->c;
872 return 0;
873 }
Hans Verkuil987e00b2007-05-29 13:03:27 -0300874 }
875 return -EINVAL;
876 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300877 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
878 return -EINVAL;
879 return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
880 }
881
882 case VIDIOC_G_CROP: {
883 struct v4l2_crop *crop = arg;
884
Hans Verkuil987e00b2007-05-29 13:03:27 -0300885 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
886 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300887 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
Ian Armstrong88ab0752008-04-22 14:42:14 -0300888 crop->c = yi->main_rect;
Ian Armstrong77aded62007-11-05 14:27:09 -0300889 else
890 crop->c = itv->main_rect;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300891 return 0;
892 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300893 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
894 return -EINVAL;
895 return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
896 }
897
898 case VIDIOC_ENUM_FMT: {
899 static struct v4l2_fmtdesc formats[] = {
900 { 0, 0, 0,
Ian Armstrong368f0802007-11-05 14:30:03 -0300901 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300902 { 0, 0, 0, 0 }
903 },
904 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
905 "MPEG", V4L2_PIX_FMT_MPEG,
906 { 0, 0, 0, 0 }
907 }
908 };
909 struct v4l2_fmtdesc *fmt = arg;
910 enum v4l2_buf_type type = fmt->type;
911
912 switch (type) {
913 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
914 break;
915 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
916 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
917 return -EINVAL;
918 break;
919 default:
920 return -EINVAL;
921 }
922 if (fmt->index > 1)
923 return -EINVAL;
924 *fmt = formats[fmt->index];
925 fmt->type = type;
926 return 0;
927 }
928
929 case VIDIOC_G_INPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300930 *(int *)arg = itv->active_input;
931 break;
932 }
933
934 case VIDIOC_S_INPUT:{
935 int inp = *(int *)arg;
936
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300937 if (inp < 0 || inp >= itv->nof_inputs)
938 return -EINVAL;
939
940 if (inp == itv->active_input) {
941 IVTV_DEBUG_INFO("Input unchanged\n");
942 break;
943 }
Hans Verkuil3562c432007-08-18 11:46:05 -0300944 if (atomic_read(&itv->capturing) > 0) {
945 return -EBUSY;
946 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300947 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
948 itv->active_input, inp);
949
950 itv->active_input = inp;
951 /* Set the audio input to whatever is appropriate for the
952 input type. */
953 itv->audio_input = itv->card->video_inputs[inp].audio_index;
954
955 /* prevent others from messing with the streams until
956 we're finished changing inputs. */
957 ivtv_mute(itv);
958 ivtv_video_set_io(itv);
959 ivtv_audio_set_io(itv);
960 ivtv_unmute(itv);
961 break;
962 }
963
964 case VIDIOC_G_OUTPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300965 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
966 return -EINVAL;
967 *(int *)arg = itv->active_output;
968 break;
969 }
970
971 case VIDIOC_S_OUTPUT:{
972 int outp = *(int *)arg;
973 struct v4l2_routing route;
974
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300975 if (outp >= itv->card->nof_outputs)
976 return -EINVAL;
977
978 if (outp == itv->active_output) {
979 IVTV_DEBUG_INFO("Output unchanged\n");
980 break;
981 }
982 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
983 itv->active_output, outp);
984
985 itv->active_output = outp;
986 route.input = SAA7127_INPUT_TYPE_NORMAL;
987 route.output = itv->card->video_outputs[outp].video_output;
988 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
989 break;
990 }
991
992 case VIDIOC_G_FREQUENCY:{
993 struct v4l2_frequency *vf = arg;
994
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300995 if (vf->tuner != 0)
996 return -EINVAL;
997 ivtv_call_i2c_clients(itv, cmd, arg);
998 break;
999 }
1000
1001 case VIDIOC_S_FREQUENCY:{
1002 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
1003
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001004 if (vf.tuner != 0)
1005 return -EINVAL;
1006
1007 ivtv_mute(itv);
1008 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
1009 ivtv_call_i2c_clients(itv, cmd, &vf);
1010 ivtv_unmute(itv);
1011 break;
1012 }
1013
1014 case VIDIOC_ENUMSTD:{
1015 struct v4l2_standard *vs = arg;
1016 int idx = vs->index;
1017
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001018 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
1019 return -EINVAL;
1020
1021 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
1022 ivtv_std_60hz : ivtv_std_50hz;
1023 vs->index = idx;
1024 vs->id = enum_stds[idx].std;
1025 strcpy(vs->name, enum_stds[idx].name);
1026 break;
1027 }
1028
1029 case VIDIOC_G_STD:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001030 *(v4l2_std_id *) arg = itv->std;
1031 break;
1032 }
1033
1034 case VIDIOC_S_STD: {
1035 v4l2_std_id std = *(v4l2_std_id *) arg;
1036
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001037 if ((std & V4L2_STD_ALL) == 0)
1038 return -EINVAL;
1039
1040 if (std == itv->std)
1041 break;
1042
1043 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1044 atomic_read(&itv->capturing) > 0 ||
1045 atomic_read(&itv->decoding) > 0) {
1046 /* Switching standard would turn off the radio or mess
1047 with already running streams, prevent that by
1048 returning EBUSY. */
1049 return -EBUSY;
1050 }
1051
1052 itv->std = std;
1053 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
1054 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1055 itv->params.width = 720;
1056 itv->params.height = itv->is_50hz ? 576 : 480;
1057 itv->vbi.count = itv->is_50hz ? 18 : 12;
1058 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1059 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1060 if (itv->hw_flags & IVTV_HW_CX25840) {
1061 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1062 }
Hans Verkuilc4385092007-06-07 09:04:03 -03001063 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001064
1065 /* Tuner */
1066 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1067
1068 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1069 /* set display standard */
1070 itv->std_out = std;
1071 itv->is_out_60hz = itv->is_60hz;
1072 itv->is_out_50hz = itv->is_50hz;
1073 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1074 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1075 itv->main_rect.left = itv->main_rect.top = 0;
1076 itv->main_rect.width = 720;
1077 itv->main_rect.height = itv->params.height;
1078 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1079 720, itv->main_rect.height, 0, 0);
Ian Armstrong88ab0752008-04-22 14:42:14 -03001080 yi->main_rect = itv->main_rect;
Ian Armstrong77aded62007-11-05 14:27:09 -03001081 if (!itv->osd_info) {
Ian Armstrong88ab0752008-04-22 14:42:14 -03001082 yi->osd_full_w = 720;
1083 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
Ian Armstrong77aded62007-11-05 14:27:09 -03001084 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001085 }
1086 break;
1087 }
1088
1089 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
1090 struct v4l2_tuner *vt = arg;
1091
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001092 if (vt->index != 0)
1093 return -EINVAL;
1094
1095 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1096 break;
1097 }
1098
1099 case VIDIOC_G_TUNER: {
1100 struct v4l2_tuner *vt = arg;
1101
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001102 if (vt->index != 0)
1103 return -EINVAL;
1104
1105 memset(vt, 0, sizeof(*vt));
1106 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1107
1108 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1109 strcpy(vt->name, "ivtv Radio Tuner");
1110 vt->type = V4L2_TUNER_RADIO;
1111 } else {
1112 strcpy(vt->name, "ivtv TV Tuner");
1113 vt->type = V4L2_TUNER_ANALOG_TV;
1114 }
1115 break;
1116 }
1117
1118 case VIDIOC_G_SLICED_VBI_CAP: {
1119 struct v4l2_sliced_vbi_cap *cap = arg;
1120 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1121 int f, l;
1122 enum v4l2_buf_type type = cap->type;
1123
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001124 memset(cap, 0, sizeof(*cap));
1125 cap->type = type;
1126 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1127 for (f = 0; f < 2; f++) {
1128 for (l = 0; l < 24; l++) {
1129 if (valid_service_line(f, l, itv->is_50hz)) {
1130 cap->service_lines[f][l] = set;
1131 }
1132 }
1133 }
1134 return 0;
1135 }
1136 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1137 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1138 return -EINVAL;
1139 if (itv->is_60hz) {
1140 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1141 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1142 } else {
1143 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1144 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1145 }
1146 return 0;
1147 }
1148 return -EINVAL;
1149 }
1150
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001151 case VIDIOC_G_ENC_INDEX: {
1152 struct v4l2_enc_idx *idx = arg;
Hans Verkuil5614b022007-08-23 17:48:41 -03001153 struct v4l2_enc_idx_entry *e = idx->entry;
1154 int entries;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001155 int i;
1156
Hans Verkuil5614b022007-08-23 17:48:41 -03001157 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001158 IVTV_MAX_PGM_INDEX;
Hans Verkuil5614b022007-08-23 17:48:41 -03001159 if (entries > V4L2_ENC_IDX_ENTRIES)
1160 entries = V4L2_ENC_IDX_ENTRIES;
1161 idx->entries = 0;
1162 for (i = 0; i < entries; i++) {
1163 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1164 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1165 idx->entries++;
1166 e++;
1167 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001168 }
1169 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1170 break;
1171 }
1172
1173 case VIDIOC_ENCODER_CMD:
1174 case VIDIOC_TRY_ENCODER_CMD: {
1175 struct v4l2_encoder_cmd *enc = arg;
1176 int try = cmd == VIDIOC_TRY_ENCODER_CMD;
1177
Hans Verkuil25415cf2007-03-10 18:29:48 -03001178 memset(&enc->raw, 0, sizeof(enc->raw));
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001179 switch (enc->cmd) {
1180 case V4L2_ENC_CMD_START:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001181 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001182 enc->flags = 0;
1183 if (try)
1184 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001185 return ivtv_start_capture(id);
1186
1187 case V4L2_ENC_CMD_STOP:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001188 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
Hans Verkuil018ba852007-04-10 18:59:09 -03001189 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001190 if (try)
1191 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001192 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1193 return 0;
1194
1195 case V4L2_ENC_CMD_PAUSE:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001196 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001197 enc->flags = 0;
1198 if (try)
1199 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001200 if (!atomic_read(&itv->capturing))
1201 return -EPERM;
1202 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1203 return 0;
1204 ivtv_mute(itv);
1205 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1206 break;
1207
1208 case V4L2_ENC_CMD_RESUME:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001209 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001210 enc->flags = 0;
1211 if (try)
1212 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001213 if (!atomic_read(&itv->capturing))
1214 return -EPERM;
1215 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1216 return 0;
1217 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1218 ivtv_unmute(itv);
1219 break;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001220 default:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001221 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
Hans Verkuil25415cf2007-03-10 18:29:48 -03001222 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001223 }
1224 break;
1225 }
1226
1227 case VIDIOC_G_FBUF: {
1228 struct v4l2_framebuffer *fb = arg;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001229 int pixfmt;
1230 static u32 pixel_format[16] = {
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001231 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001232 V4L2_PIX_FMT_RGB565,
1233 V4L2_PIX_FMT_RGB555,
1234 V4L2_PIX_FMT_RGB444,
1235 V4L2_PIX_FMT_RGB32,
1236 0,
1237 0,
1238 0,
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001239 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1240 V4L2_PIX_FMT_YUV565,
1241 V4L2_PIX_FMT_YUV555,
1242 V4L2_PIX_FMT_YUV444,
1243 V4L2_PIX_FMT_YUV32,
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001244 0,
1245 0,
1246 0,
1247 };
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001248
1249 memset(fb, 0, sizeof(*fb));
1250 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001251 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001252 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001253 V4L2_FBUF_CAP_GLOBAL_ALPHA;
1254 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1255 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1256 pixfmt = (data[0] >> 3) & 0xf;
1257 fb->fmt.pixelformat = pixel_format[pixfmt];
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001258 fb->fmt.width = itv->osd_rect.width;
1259 fb->fmt.height = itv->osd_rect.height;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001260 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001261 if (itv->osd_chroma_key_state)
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001262 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001263 if (itv->osd_global_alpha_state)
1264 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1265 pixfmt &= 7;
1266 /* no local alpha for RGB565 or unknown formats */
1267 if (pixfmt == 1 || pixfmt > 4)
1268 break;
1269 /* 16-bit formats have inverted local alpha */
1270 if (pixfmt == 2 || pixfmt == 3)
1271 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1272 else
1273 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
1274 if (itv->osd_local_alpha_state) {
1275 /* 16-bit formats have inverted local alpha */
1276 if (pixfmt == 2 || pixfmt == 3)
1277 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1278 else
1279 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1280 }
Ian Armstrong88ab0752008-04-22 14:42:14 -03001281 if (yi->track_osd)
1282 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001283 break;
1284 }
1285
1286 case VIDIOC_S_FBUF: {
1287 struct v4l2_framebuffer *fb = arg;
1288
1289 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001290 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001291 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001292 itv->osd_local_alpha_state =
1293 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001294 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
Hans Verkuilc3624f92007-07-31 07:15:56 -03001295 ivtv_set_osd_alpha(itv);
Ian Armstrong88ab0752008-04-22 14:42:14 -03001296 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001297 break;
1298 }
1299
Hans Verkuil7c03a442007-08-19 18:59:42 -03001300 case VIDIOC_OVERLAY: {
1301 int *on = arg;
1302
1303 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1304 return -EINVAL;
1305 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
1306 break;
1307 }
1308
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001309 case VIDIOC_LOG_STATUS:
1310 {
1311 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1312 struct v4l2_input vidin;
1313 struct v4l2_audio audin;
1314 int i;
1315
1316 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
Hans Verkuil94104aa2007-08-04 04:56:00 -03001317 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001318 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1319 struct tveeprom tv;
1320
1321 ivtv_read_eeprom(itv, &tv);
1322 }
1323 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1324 ivtv_get_input(itv, itv->active_input, &vidin);
1325 ivtv_get_audio_input(itv, itv->audio_input, &audin);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001326 IVTV_INFO("Video Input: %s\n", vidin.name);
1327 IVTV_INFO("Audio Input: %s%s\n", audin.name,
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001328 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001329 if (has_output) {
1330 struct v4l2_output vidout;
1331 struct v4l2_audioout audout;
1332 int mode = itv->output_mode;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001333 static const char * const output_modes[5] = {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001334 "None",
1335 "MPEG Streaming",
1336 "YUV Streaming",
1337 "YUV Frames",
1338 "Passthrough",
1339 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001340 static const char * const audio_modes[5] = {
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001341 "Stereo",
1342 "Left",
1343 "Right",
1344 "Mono",
1345 "Swapped"
1346 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001347 static const char * const alpha_mode[4] = {
Hans Verkuil7c03a442007-08-19 18:59:42 -03001348 "None",
1349 "Global",
1350 "Local",
1351 "Global and Local"
1352 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001353 static const char * const pixel_format[16] = {
1354 "ARGB Indexed",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001355 "RGB 5:6:5",
1356 "ARGB 1:5:5:5",
1357 "ARGB 1:4:4:4",
1358 "ARGB 8:8:8:8",
1359 "5",
1360 "6",
1361 "7",
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001362 "AYUV Indexed",
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001363 "YUV 5:6:5",
1364 "AYUV 1:5:5:5",
1365 "AYUV 1:4:4:4",
1366 "AYUV 8:8:8:8",
1367 "13",
1368 "14",
1369 "15",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001370 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001371
1372 ivtv_get_output(itv, itv->active_output, &vidout);
1373 ivtv_get_audio_output(itv, 0, &audout);
1374 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001375 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1376 audio_modes[itv->audio_stereo_mode],
1377 audio_modes[itv->audio_bilingual_mode]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001378 if (mode < 0 || mode > OUT_PASSTHROUGH)
1379 mode = OUT_NONE;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001380 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1381 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001382 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001383 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1384 data[0] & 1 ? "On" : "Off",
1385 alpha_mode[(data[0] >> 1) & 0x3],
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001386 pixel_format[(data[0] >> 3) & 0xf]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001387 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001388 IVTV_INFO("Tuner: %s\n",
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001389 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1390 cx2341x_log_status(&itv->params, itv->name);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001391 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001392 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1393 struct ivtv_stream *s = &itv->streams[i];
1394
1395 if (s->v4l2dev == NULL || s->buffers == 0)
1396 continue;
1397 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1398 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1399 (s->buffers * s->buf_size) / 1024, s->buffers);
1400 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001401 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 -03001402 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1403 break;
1404 }
1405
1406 default:
1407 return -EINVAL;
1408 }
1409 return 0;
1410}
1411
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001412static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001413{
1414 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1415 struct ivtv *itv = id->itv;
1416 int nonblocking = filp->f_flags & O_NONBLOCK;
1417 struct ivtv_stream *s = &itv->streams[id->type];
1418
1419 switch (cmd) {
1420 case IVTV_IOC_DMA_FRAME: {
1421 struct ivtv_dma_frame *args = arg;
1422
1423 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1424 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1425 return -EINVAL;
1426 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1427 return -EINVAL;
1428 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1429 return 0;
1430 if (ivtv_claim_stream(id, id->type)) {
1431 return -EBUSY;
1432 }
1433 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1434 ivtv_release_stream(s);
1435 return -EBUSY;
1436 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001437 /* Mark that this file handle started the UDMA_YUV mode */
1438 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001439 if (args->y_source == NULL)
1440 return 0;
1441 return ivtv_yuv_prep_frame(itv, args);
1442 }
1443
1444 case VIDEO_GET_PTS: {
1445 u32 data[CX2341X_MBOX_MAX_DATA];
1446 u64 *pts = arg;
1447
1448 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1449 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1450 *pts = s->dma_pts;
1451 break;
1452 }
1453 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1454 return -EINVAL;
1455
1456 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1457 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1458 (u64)itv->last_dec_timing[1];
1459 break;
1460 }
1461 *pts = 0;
1462 if (atomic_read(&itv->decoding)) {
1463 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1464 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1465 return -EIO;
1466 }
1467 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1468 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1469 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1470 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1471 }
1472 break;
1473 }
1474
1475 case VIDEO_GET_FRAME_COUNT: {
1476 u32 data[CX2341X_MBOX_MAX_DATA];
1477 u64 *frame = arg;
1478
1479 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1480 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1481 *frame = 0;
1482 break;
1483 }
1484 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1485 return -EINVAL;
1486
1487 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1488 *frame = itv->last_dec_timing[0];
1489 break;
1490 }
1491 *frame = 0;
1492 if (atomic_read(&itv->decoding)) {
1493 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1494 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1495 return -EIO;
1496 }
1497 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1498 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1499 *frame = data[0];
1500 }
1501 break;
1502 }
1503
1504 case VIDEO_PLAY: {
1505 struct video_command vc;
1506
1507 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1508 memset(&vc, 0, sizeof(vc));
1509 vc.cmd = VIDEO_CMD_PLAY;
1510 return ivtv_video_command(itv, id, &vc, 0);
1511 }
1512
1513 case VIDEO_STOP: {
1514 struct video_command vc;
1515
1516 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1517 memset(&vc, 0, sizeof(vc));
1518 vc.cmd = VIDEO_CMD_STOP;
1519 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1520 return ivtv_video_command(itv, id, &vc, 0);
1521 }
1522
1523 case VIDEO_FREEZE: {
1524 struct video_command vc;
1525
1526 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1527 memset(&vc, 0, sizeof(vc));
1528 vc.cmd = VIDEO_CMD_FREEZE;
1529 return ivtv_video_command(itv, id, &vc, 0);
1530 }
1531
1532 case VIDEO_CONTINUE: {
1533 struct video_command vc;
1534
1535 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1536 memset(&vc, 0, sizeof(vc));
1537 vc.cmd = VIDEO_CMD_CONTINUE;
1538 return ivtv_video_command(itv, id, &vc, 0);
1539 }
1540
1541 case VIDEO_COMMAND:
1542 case VIDEO_TRY_COMMAND: {
1543 struct video_command *vc = arg;
1544 int try = (cmd == VIDEO_TRY_COMMAND);
1545
1546 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001547 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001548 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001549 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001550 return ivtv_video_command(itv, id, vc, try);
1551 }
1552
1553 case VIDEO_GET_EVENT: {
1554 struct video_event *ev = arg;
1555 DEFINE_WAIT(wait);
1556
1557 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1558 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1559 return -EINVAL;
1560 memset(ev, 0, sizeof(*ev));
1561 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1562
1563 while (1) {
1564 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1565 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1566 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1567 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001568 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1569 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1570 if (itv->output_mode == OUT_UDMA_YUV &&
1571 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1572 IVTV_YUV_MODE_PROGRESSIVE) {
1573 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1574 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001575 }
1576 if (ev->type)
1577 return 0;
1578 if (nonblocking)
1579 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001580 /* Wait for event. Note that serialize_lock is locked,
1581 so to allow other processes to access the driver while
1582 we are waiting unlock first and later lock again. */
1583 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001584 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1585 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1586 schedule();
1587 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001588 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001589 if (signal_pending(current)) {
1590 /* return if a signal was received */
1591 IVTV_DEBUG_INFO("User stopped wait for event\n");
1592 return -EINTR;
1593 }
1594 }
1595 break;
1596 }
1597
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001598 default:
1599 return -EINVAL;
1600 }
1601 return 0;
1602}
1603
1604static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1605 unsigned int cmd, void *arg)
1606{
1607 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1608 struct ivtv *itv = id->itv;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001609 int ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001610
Hans Verkuild46c17d2007-03-10 17:59:15 -03001611 /* check priority */
1612 switch (cmd) {
1613 case VIDIOC_S_CTRL:
1614 case VIDIOC_S_STD:
1615 case VIDIOC_S_INPUT:
1616 case VIDIOC_S_OUTPUT:
1617 case VIDIOC_S_TUNER:
1618 case VIDIOC_S_FREQUENCY:
1619 case VIDIOC_S_FMT:
1620 case VIDIOC_S_CROP:
1621 case VIDIOC_S_AUDIO:
1622 case VIDIOC_S_AUDOUT:
1623 case VIDIOC_S_EXT_CTRLS:
1624 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001625 case VIDIOC_OVERLAY:
Hans Verkuild46c17d2007-03-10 17:59:15 -03001626 ret = v4l2_prio_check(&itv->prio, &id->prio);
1627 if (ret)
1628 return ret;
1629 }
1630
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001631 switch (cmd) {
1632 case VIDIOC_DBG_G_REGISTER:
1633 case VIDIOC_DBG_S_REGISTER:
1634 case VIDIOC_G_CHIP_IDENT:
1635 case VIDIOC_INT_S_AUDIO_ROUTING:
1636 case VIDIOC_INT_RESET:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001637 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1638 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1639 v4l_printk_ioctl(cmd);
1640 }
1641 return ivtv_debug_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001642
Hans Verkuild46c17d2007-03-10 17:59:15 -03001643 case VIDIOC_G_PRIORITY:
1644 case VIDIOC_S_PRIORITY:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001645 case VIDIOC_QUERYCAP:
1646 case VIDIOC_ENUMINPUT:
1647 case VIDIOC_G_INPUT:
1648 case VIDIOC_S_INPUT:
1649 case VIDIOC_ENUMOUTPUT:
1650 case VIDIOC_G_OUTPUT:
1651 case VIDIOC_S_OUTPUT:
1652 case VIDIOC_G_FMT:
1653 case VIDIOC_S_FMT:
1654 case VIDIOC_TRY_FMT:
1655 case VIDIOC_ENUM_FMT:
Hans Verkuil987e00b2007-05-29 13:03:27 -03001656 case VIDIOC_CROPCAP:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001657 case VIDIOC_G_CROP:
1658 case VIDIOC_S_CROP:
1659 case VIDIOC_G_FREQUENCY:
1660 case VIDIOC_S_FREQUENCY:
1661 case VIDIOC_ENUMSTD:
1662 case VIDIOC_G_STD:
1663 case VIDIOC_S_STD:
1664 case VIDIOC_S_TUNER:
1665 case VIDIOC_G_TUNER:
1666 case VIDIOC_ENUMAUDIO:
1667 case VIDIOC_S_AUDIO:
1668 case VIDIOC_G_AUDIO:
1669 case VIDIOC_ENUMAUDOUT:
1670 case VIDIOC_S_AUDOUT:
1671 case VIDIOC_G_AUDOUT:
1672 case VIDIOC_G_SLICED_VBI_CAP:
1673 case VIDIOC_LOG_STATUS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001674 case VIDIOC_G_ENC_INDEX:
1675 case VIDIOC_ENCODER_CMD:
1676 case VIDIOC_TRY_ENCODER_CMD:
1677 case VIDIOC_G_FBUF:
1678 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001679 case VIDIOC_OVERLAY:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001680 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1681 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1682 v4l_printk_ioctl(cmd);
1683 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001684 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1685
1686 case VIDIOC_QUERYMENU:
1687 case VIDIOC_QUERYCTRL:
1688 case VIDIOC_S_CTRL:
1689 case VIDIOC_G_CTRL:
1690 case VIDIOC_S_EXT_CTRLS:
1691 case VIDIOC_G_EXT_CTRLS:
1692 case VIDIOC_TRY_EXT_CTRLS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001693 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1694 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1695 v4l_printk_ioctl(cmd);
1696 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001697 return ivtv_control_ioctls(itv, cmd, arg);
1698
1699 case IVTV_IOC_DMA_FRAME:
1700 case VIDEO_GET_PTS:
1701 case VIDEO_GET_FRAME_COUNT:
1702 case VIDEO_GET_EVENT:
1703 case VIDEO_PLAY:
1704 case VIDEO_STOP:
1705 case VIDEO_FREEZE:
1706 case VIDEO_CONTINUE:
1707 case VIDEO_COMMAND:
1708 case VIDEO_TRY_COMMAND:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001709 return ivtv_decoder_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001710
1711 case 0x00005401: /* Handle isatty() calls */
1712 return -EINVAL;
1713 default:
1714 return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
1715 ivtv_v4l2_do_ioctl);
1716 }
1717 return 0;
1718}
1719
Hans Verkuilbaa40722007-08-19 07:10:55 -03001720static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1721 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001722{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001723 /* Filter dvb ioctls that cannot be handled by video_usercopy */
1724 switch (cmd) {
1725 case VIDEO_SELECT_SOURCE:
1726 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1727 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1728 return -EINVAL;
1729 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1730
1731 case AUDIO_SET_MUTE:
1732 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1733 itv->speed_mute_audio = arg;
1734 return 0;
1735
1736 case AUDIO_CHANNEL_SELECT:
1737 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1738 if (arg > AUDIO_STEREO_SWAPPED)
1739 return -EINVAL;
1740 itv->audio_stereo_mode = arg;
1741 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1742 return 0;
1743
1744 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1745 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1746 if (arg > AUDIO_STEREO_SWAPPED)
1747 return -EINVAL;
1748 itv->audio_bilingual_mode = arg;
1749 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1750 return 0;
1751
1752 default:
1753 break;
1754 }
1755 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
1756}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001757
1758int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1759 unsigned long arg)
1760{
1761 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1762 struct ivtv *itv = id->itv;
1763 int res;
1764
1765 mutex_lock(&itv->serialize_lock);
1766 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1767 mutex_unlock(&itv->serialize_lock);
1768 return res;
1769}