blob: 26cc0f6699fdc9d44bfcdce386d2533f3cc06227 [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
Hans Verkuilfeb5bce2008-05-01 09:22:13 -030041u16 ivtv_service2vbi(int type)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030042{
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
Hans Verkuilfeb5bce2008-05-01 09:22:13 -030091void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030092{
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
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300118u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300119{
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
Hans Verkuil94dee762008-04-26 09:26:13 -0300246 if (cur_speed == 0)
247 cur_speed = 1000;
248 if (new_speed < 0)
249 new_speed = -new_speed;
250 if (cur_speed < 0)
251 cur_speed = -cur_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300252
253 if (cur_speed <= new_speed) {
Hans Verkuil94dee762008-04-26 09:26:13 -0300254 if (new_speed > 1500)
255 return fact * 2000;
256 if (new_speed > 1000)
257 return fact * 1500;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300258 }
259 else {
Hans Verkuil94dee762008-04-26 09:26:13 -0300260 if (new_speed >= 2000)
261 return fact * 2000;
262 if (new_speed >= 1500)
263 return fact * 1500;
264 if (new_speed >= 1000)
265 return fact * 1000;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300266 }
Hans Verkuil94dee762008-04-26 09:26:13 -0300267 if (new_speed == 0)
268 return 1000;
269 if (new_speed == 1 || new_speed == 1000)
270 return fact * new_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300271
272 s = new_speed;
273 new_speed = 1000 / new_speed;
274 if (1000 / cur_speed == new_speed)
275 new_speed += (cur_speed < s) ? -1 : 1;
276 if (new_speed > 60) return 1000 / (fact * 60);
277 return 1000 / (fact * new_speed);
278}
279
280static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
281 struct video_command *vc, int try)
282{
283 struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
284
285 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
286 return -EINVAL;
287
288 switch (vc->cmd) {
289 case VIDEO_CMD_PLAY: {
Hans Verkuil25415cf2007-03-10 18:29:48 -0300290 vc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300291 vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed);
292 if (vc->play.speed < 0)
293 vc->play.format = VIDEO_PLAY_FMT_GOP;
294 if (try) break;
295
296 if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
297 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300298 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
299 /* forces ivtv_set_speed to be called */
300 itv->speed = 0;
301 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300302 return ivtv_start_decoding(id, vc->play.speed);
303 }
304
305 case VIDEO_CMD_STOP:
Hans Verkuil018ba852007-04-10 18:59:09 -0300306 vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300307 if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY)
308 vc->stop.pts = 0;
309 if (try) break;
310 if (atomic_read(&itv->decoding) == 0)
311 return 0;
312 if (itv->output_mode != OUT_MPG)
313 return -EBUSY;
314
315 itv->output_mode = OUT_NONE;
316 return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts);
317
318 case VIDEO_CMD_FREEZE:
Hans Verkuil018ba852007-04-10 18:59:09 -0300319 vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300320 if (try) break;
321 if (itv->output_mode != OUT_MPG)
322 return -EBUSY;
323 if (atomic_read(&itv->decoding) > 0) {
324 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
325 (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0);
Hans Verkuilac425142007-07-22 08:46:38 -0300326 set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300327 }
328 break;
329
330 case VIDEO_CMD_CONTINUE:
Hans Verkuil25415cf2007-03-10 18:29:48 -0300331 vc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300332 if (try) break;
333 if (itv->output_mode != OUT_MPG)
334 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300335 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
336 int speed = itv->speed;
337 itv->speed = 0;
338 return ivtv_start_decoding(id, speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300339 }
340 break;
341
342 default:
343 return -EINVAL;
344 }
345 return 0;
346}
347
348static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
349{
350 struct v4l2_register *regs = arg;
351 unsigned long flags;
352 volatile u8 __iomem *reg_start;
353
354 if (!capable(CAP_SYS_ADMIN))
355 return -EPERM;
356 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
357 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
358 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
359 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
360 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
361 else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
362 reg_start = itv->enc_mem;
363 else
364 return -EINVAL;
365
366 spin_lock_irqsave(&ivtv_cards_lock, flags);
367 if (cmd == VIDIOC_DBG_G_REGISTER) {
368 regs->val = readl(regs->reg + reg_start);
369 } else {
370 writel(regs->val, regs->reg + reg_start);
371 }
372 spin_unlock_irqrestore(&ivtv_cards_lock, flags);
373 return 0;
374}
375
376static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fmt)
377{
378 switch (fmt->type) {
379 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
380 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
381 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300382 fmt->fmt.pix.width = itv->main_rect.width;
383 fmt->fmt.pix.height = itv->main_rect.height;
384 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
385 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
Ian Armstrong77aded62007-11-05 14:27:09 -0300386 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300387 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
388 case IVTV_YUV_MODE_INTERLACED:
389 fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
390 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
391 break;
392 case IVTV_YUV_MODE_PROGRESSIVE:
393 fmt->fmt.pix.field = V4L2_FIELD_NONE;
394 break;
395 default:
396 fmt->fmt.pix.field = V4L2_FIELD_ANY;
397 break;
398 }
399 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
Ian Armstrong77aded62007-11-05 14:27:09 -0300400 fmt->fmt.pix.bytesperline = 720;
401 fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w;
402 fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300403 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
404 fmt->fmt.pix.sizeimage =
Ian Armstrong77aded62007-11-05 14:27:09 -0300405 1080 * ((fmt->fmt.pix.height + 31) & ~31);
406 } else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300407 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
408 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
409 fmt->fmt.pix.sizeimage =
410 fmt->fmt.pix.height * fmt->fmt.pix.width +
411 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
412 } else {
413 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
414 fmt->fmt.pix.sizeimage = 128 * 1024;
415 }
416 break;
417
418 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300419 fmt->fmt.pix.width = itv->params.width;
420 fmt->fmt.pix.height = itv->params.height;
421 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
422 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
423 if (streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
424 streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
425 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
426 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
427 fmt->fmt.pix.sizeimage =
428 fmt->fmt.pix.height * fmt->fmt.pix.width +
429 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
430 } else {
431 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
432 fmt->fmt.pix.sizeimage = 128 * 1024;
433 }
434 break;
435
436 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
437 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
438 return -EINVAL;
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300439 fmt->fmt.win.chromakey = itv->osd_chroma_key;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300440 fmt->fmt.win.global_alpha = itv->osd_global_alpha;
441 break;
442
443 case V4L2_BUF_TYPE_VBI_CAPTURE:
444 fmt->fmt.vbi.sampling_rate = 27000000;
445 fmt->fmt.vbi.offset = 248;
446 fmt->fmt.vbi.samples_per_line = itv->vbi.raw_decoder_line_size - 4;
447 fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
448 fmt->fmt.vbi.start[0] = itv->vbi.start[0];
449 fmt->fmt.vbi.start[1] = itv->vbi.start[1];
450 fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = itv->vbi.count;
451 break;
452
453 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
454 {
455 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
456
457 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
458 return -EINVAL;
459 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
460 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
461 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
462 if (itv->is_60hz) {
463 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
464 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
465 } else {
466 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
467 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
468 }
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300469 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300470 break;
471 }
472
473 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
474 {
475 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
476
477 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
478 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
479 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
480
481 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
482 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
483 V4L2_SLICED_VBI_525;
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300484 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300485 break;
486 }
487
488 itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300489 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300490 break;
491 }
492 case V4L2_BUF_TYPE_VBI_OUTPUT:
493 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
494 default:
495 return -EINVAL;
496 }
497 return 0;
498}
499
500static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
501 struct v4l2_format *fmt, int set_fmt)
502{
Ian Armstrong77aded62007-11-05 14:27:09 -0300503 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300504 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
505 u16 set;
506
507 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
508 struct v4l2_rect r;
509 int field;
510
511 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
512 return -EINVAL;
513 field = fmt->fmt.pix.field;
Hans Verkuilc74e83a2007-05-17 06:41:44 -0300514 r.top = 0;
515 r.left = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300516 r.width = fmt->fmt.pix.width;
517 r.height = fmt->fmt.pix.height;
518 ivtv_get_fmt(itv, streamtype, fmt);
Ian Armstrong77aded62007-11-05 14:27:09 -0300519 fmt->fmt.pix.width = r.width;
520 fmt->fmt.pix.height = r.height;
521 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300522 fmt->fmt.pix.field = field;
Ian Armstrong77aded62007-11-05 14:27:09 -0300523 if (fmt->fmt.pix.width < 2)
524 fmt->fmt.pix.width = 2;
525 if (fmt->fmt.pix.width > 720)
526 fmt->fmt.pix.width = 720;
527 if (fmt->fmt.pix.height < 2)
528 fmt->fmt.pix.height = 2;
529 if (fmt->fmt.pix.height > 576)
530 fmt->fmt.pix.height = 576;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300531 }
Ian Armstrong77aded62007-11-05 14:27:09 -0300532 if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
533 /* Return now if we already have some frame data */
534 if (yi->stream_size)
535 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300536
Ian Armstrong77aded62007-11-05 14:27:09 -0300537 yi->v4l2_src_w = r.width;
538 yi->v4l2_src_h = r.height;
539
540 switch (field) {
541 case V4L2_FIELD_NONE:
542 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
543 break;
544 case V4L2_FIELD_ANY:
545 yi->lace_mode = IVTV_YUV_MODE_AUTO;
546 break;
547 case V4L2_FIELD_INTERLACED_BT:
548 yi->lace_mode =
549 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
550 break;
551 case V4L2_FIELD_INTERLACED_TB:
552 default:
553 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
554 break;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300555 }
Ian Armstrong77aded62007-11-05 14:27:09 -0300556 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
557
558 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
559 itv->dma_data_req_size =
560 1080 * ((yi->v4l2_src_h + 31) & ~31);
561
562 /* Force update of yuv registers */
563 yi->yuv_forced_update = 1;
564 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300565 }
566 return 0;
567 }
568
569 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) {
570 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
571 return -EINVAL;
572 if (set_fmt) {
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300573 itv->osd_chroma_key = fmt->fmt.win.chromakey;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300574 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
575 ivtv_set_osd_alpha(itv);
576 }
577 return 0;
578 }
579
580 /* set window size */
581 if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300582 struct cx2341x_mpeg_params *p = &itv->params;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300583 int w = fmt->fmt.pix.width;
584 int h = fmt->fmt.pix.height;
585
586 if (w > 720) w = 720;
587 else if (w < 1) w = 1;
588 if (h > (itv->is_50hz ? 576 : 480)) h = (itv->is_50hz ? 576 : 480);
589 else if (h < 2) h = 2;
590 ivtv_get_fmt(itv, streamtype, fmt);
591 fmt->fmt.pix.width = w;
592 fmt->fmt.pix.height = h;
593
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300594 if (!set_fmt || (p->width == w && p->height == h))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300595 return 0;
596 if (atomic_read(&itv->capturing) > 0)
597 return -EBUSY;
598
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300599 p->width = w;
600 p->height = h;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300601 if (w != 720 || h != (itv->is_50hz ? 576 : 480))
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300602 p->video_temporal_filter = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300603 else
Hans Verkuil34ca7d32007-10-12 12:39:36 -0300604 p->video_temporal_filter = 8;
605 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
606 fmt->fmt.pix.width /= 2;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300607 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
608 return ivtv_get_fmt(itv, streamtype, fmt);
609 }
610
611 /* set raw VBI format */
612 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Hans Verkuilea115d52007-08-20 16:26:40 -0300613 if (set_fmt && atomic_read(&itv->capturing) > 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300614 return -EBUSY;
615 }
616 if (set_fmt) {
617 itv->vbi.sliced_in->service_set = 0;
618 itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
619 }
620 return ivtv_get_fmt(itv, streamtype, fmt);
621 }
622
623 /* set sliced VBI output
624 In principle the user could request that only certain
625 VBI types are output and that the others are ignored.
626 I.e., suppress CC in the even fields or only output
627 WSS and no VPS. Currently though there is no choice. */
628 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
629 return ivtv_get_fmt(itv, streamtype, fmt);
630
631 /* any else but sliced VBI capture is an error */
632 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
633 return -EINVAL;
634
635 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI)
636 return ivtv_get_fmt(itv, streamtype, fmt);
637
638 /* set sliced VBI capture format */
639 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
640 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
641
642 if (vbifmt->service_set)
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300643 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300644 set = check_service_set(vbifmt, itv->is_50hz);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300645 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300646
647 if (!set_fmt)
648 return 0;
649 if (set == 0)
650 return -EINVAL;
Hans Verkuilea115d52007-08-20 16:26:40 -0300651 if (atomic_read(&itv->capturing) > 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300652 return -EBUSY;
653 }
654 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
655 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
656 return 0;
657}
658
Hans Verkuild4e7ee32007-03-10 18:19:12 -0300659static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300660{
661 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
662 struct ivtv *itv = id->itv;
663 struct v4l2_register *reg = arg;
664
665 switch (cmd) {
666 /* ioctls to allow direct access to the encoder registers for testing */
667 case VIDIOC_DBG_G_REGISTER:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300668 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
669 return ivtv_itvc(itv, cmd, arg);
670 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
671 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
672 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
673
674 case VIDIOC_DBG_S_REGISTER:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300675 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
676 return ivtv_itvc(itv, cmd, arg);
677 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
678 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
679 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
680
681 case VIDIOC_G_CHIP_IDENT: {
682 struct v4l2_chip_ident *chip = arg;
683
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300684 chip->ident = V4L2_IDENT_NONE;
685 chip->revision = 0;
686 if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
Richard Knutssone1ba33d2007-12-02 14:47:01 -0300687 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300688 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300689 return 0;
690 }
691 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
692 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
693 if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
694 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
695 return -EINVAL;
696 }
697
698 case VIDIOC_INT_S_AUDIO_ROUTING: {
699 struct v4l2_routing *route = arg;
700
Hans Verkuil33c0fca2007-08-23 06:32:46 -0300701 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300702 break;
703 }
704
Hans Verkuil2cc72092007-08-04 05:06:23 -0300705 case VIDIOC_INT_RESET: {
706 u32 val = *(u32 *)arg;
707
708 if ((val == 0 && itv->options.newi2c) || (val & 0x01)) {
709 ivtv_reset_ir_gpio(itv);
710 }
711 if (val & 0x02) {
Richard Knutsson14d5deb2007-12-08 10:35:06 -0300712 itv->video_dec_func(itv, cmd, NULL);
Hans Verkuil2cc72092007-08-04 05:06:23 -0300713 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300714 break;
Hans Verkuil2cc72092007-08-04 05:06:23 -0300715 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300716
717 default:
718 return -EINVAL;
719 }
720 return 0;
721}
722
723int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
724{
725 struct ivtv_open_id *id = NULL;
Ian Armstrong88ab0752008-04-22 14:42:14 -0300726 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -0300727 u32 data[CX2341X_MBOX_MAX_DATA];
Ian Armstrong77aded62007-11-05 14:27:09 -0300728 int streamtype = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300729
Ian Armstrong77aded62007-11-05 14:27:09 -0300730 if (filp) {
731 id = (struct ivtv_open_id *)filp->private_data;
732 streamtype = id->type;
733 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300734
735 switch (cmd) {
Hans Verkuild46c17d2007-03-10 17:59:15 -0300736 case VIDIOC_G_PRIORITY:
737 {
738 enum v4l2_priority *p = arg;
739
740 *p = v4l2_prio_max(&itv->prio);
741 break;
742 }
743
744 case VIDIOC_S_PRIORITY:
745 {
746 enum v4l2_priority *prio = arg;
747
748 return v4l2_prio_change(&itv->prio, &id->prio, *prio);
749 }
750
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300751 case VIDIOC_QUERYCAP:{
752 struct v4l2_capability *vcap = arg;
753
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300754 memset(vcap, 0, sizeof(*vcap));
Hans Verkuilcebfadf2008-04-26 08:51:51 -0300755 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
756 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
757 strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300758 vcap->version = IVTV_DRIVER_VERSION; /* version */
759 vcap->capabilities = itv->v4l2_cap; /* capabilities */
760
761 /* reserved.. must set to 0! */
762 vcap->reserved[0] = vcap->reserved[1] =
763 vcap->reserved[2] = vcap->reserved[3] = 0;
764 break;
765 }
766
767 case VIDIOC_ENUMAUDIO:{
768 struct v4l2_audio *vin = arg;
769
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300770 return ivtv_get_audio_input(itv, vin->index, vin);
771 }
772
773 case VIDIOC_G_AUDIO:{
774 struct v4l2_audio *vin = arg;
775
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300776 vin->index = itv->audio_input;
777 return ivtv_get_audio_input(itv, vin->index, vin);
778 }
779
780 case VIDIOC_S_AUDIO:{
781 struct v4l2_audio *vout = arg;
782
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300783 if (vout->index >= itv->nof_audio_inputs)
784 return -EINVAL;
785 itv->audio_input = vout->index;
786 ivtv_audio_set_io(itv);
787 break;
788 }
789
790 case VIDIOC_ENUMAUDOUT:{
791 struct v4l2_audioout *vin = arg;
792
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300793 /* set it to defaults from our table */
794 return ivtv_get_audio_output(itv, vin->index, vin);
795 }
796
797 case VIDIOC_G_AUDOUT:{
798 struct v4l2_audioout *vin = arg;
799
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300800 vin->index = 0;
801 return ivtv_get_audio_output(itv, vin->index, vin);
802 }
803
804 case VIDIOC_S_AUDOUT:{
805 struct v4l2_audioout *vout = arg;
806
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300807 return ivtv_get_audio_output(itv, vout->index, vout);
808 }
809
810 case VIDIOC_ENUMINPUT:{
811 struct v4l2_input *vin = arg;
812
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300813 /* set it to defaults from our table */
814 return ivtv_get_input(itv, vin->index, vin);
815 }
816
817 case VIDIOC_ENUMOUTPUT:{
818 struct v4l2_output *vout = arg;
819
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300820 return ivtv_get_output(itv, vout->index, vout);
821 }
822
823 case VIDIOC_TRY_FMT:
824 case VIDIOC_S_FMT: {
825 struct v4l2_format *fmt = arg;
826
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300827 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT);
828 }
829
830 case VIDIOC_G_FMT: {
831 struct v4l2_format *fmt = arg;
832 int type = fmt->type;
833
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300834 memset(fmt, 0, sizeof(*fmt));
835 fmt->type = type;
836 return ivtv_get_fmt(itv, id->type, fmt);
837 }
838
Hans Verkuil987e00b2007-05-29 13:03:27 -0300839 case VIDIOC_CROPCAP: {
840 struct v4l2_cropcap *cropcap = arg;
841
Hans Verkuilc9aec062008-04-22 14:42:15 -0300842 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
Hans Verkuil987e00b2007-05-29 13:03:27 -0300843 return -EINVAL;
844 cropcap->bounds.top = cropcap->bounds.left = 0;
845 cropcap->bounds.width = 720;
846 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
847 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
848 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
849 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
Ian Armstrong77aded62007-11-05 14:27:09 -0300850 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Ian Armstrong88ab0752008-04-22 14:42:14 -0300851 if (yi->track_osd) {
852 cropcap->bounds.width = yi->osd_full_w;
853 cropcap->bounds.height = yi->osd_full_h;
854 } else {
855 cropcap->bounds.width = 720;
856 cropcap->bounds.height =
857 itv->is_out_50hz ? 576 : 480;
858 }
Ian Armstrong77aded62007-11-05 14:27:09 -0300859 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
860 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300861 } else {
862 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
863 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
864 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
865 }
866 cropcap->defrect = cropcap->bounds;
867 return 0;
868 }
869
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300870 case VIDIOC_S_CROP: {
871 struct v4l2_crop *crop = arg;
872
Hans Verkuil987e00b2007-05-29 13:03:27 -0300873 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
874 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300875 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
Ian Armstrong88ab0752008-04-22 14:42:14 -0300876 yi->main_rect = crop->c;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300877 return 0;
Ian Armstrong77aded62007-11-05 14:27:09 -0300878 } else {
879 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
880 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
881 itv->main_rect = crop->c;
882 return 0;
883 }
Hans Verkuil987e00b2007-05-29 13:03:27 -0300884 }
885 return -EINVAL;
886 }
Hans Verkuilc9aec062008-04-22 14:42:15 -0300887 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300888 }
889
890 case VIDIOC_G_CROP: {
891 struct v4l2_crop *crop = arg;
892
Hans Verkuil987e00b2007-05-29 13:03:27 -0300893 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
894 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
Ian Armstrong77aded62007-11-05 14:27:09 -0300895 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
Ian Armstrong88ab0752008-04-22 14:42:14 -0300896 crop->c = yi->main_rect;
Ian Armstrong77aded62007-11-05 14:27:09 -0300897 else
898 crop->c = itv->main_rect;
Hans Verkuil987e00b2007-05-29 13:03:27 -0300899 return 0;
900 }
Hans Verkuilc9aec062008-04-22 14:42:15 -0300901 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300902 }
903
904 case VIDIOC_ENUM_FMT: {
905 static struct v4l2_fmtdesc formats[] = {
906 { 0, 0, 0,
Ian Armstrong368f0802007-11-05 14:30:03 -0300907 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300908 { 0, 0, 0, 0 }
909 },
910 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
911 "MPEG", V4L2_PIX_FMT_MPEG,
912 { 0, 0, 0, 0 }
913 }
914 };
915 struct v4l2_fmtdesc *fmt = arg;
916 enum v4l2_buf_type type = fmt->type;
917
918 switch (type) {
919 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
920 break;
921 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
922 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
923 return -EINVAL;
924 break;
925 default:
926 return -EINVAL;
927 }
928 if (fmt->index > 1)
929 return -EINVAL;
930 *fmt = formats[fmt->index];
931 fmt->type = type;
932 return 0;
933 }
934
935 case VIDIOC_G_INPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300936 *(int *)arg = itv->active_input;
937 break;
938 }
939
940 case VIDIOC_S_INPUT:{
941 int inp = *(int *)arg;
942
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300943 if (inp < 0 || inp >= itv->nof_inputs)
944 return -EINVAL;
945
946 if (inp == itv->active_input) {
947 IVTV_DEBUG_INFO("Input unchanged\n");
948 break;
949 }
Hans Verkuil3562c432007-08-18 11:46:05 -0300950 if (atomic_read(&itv->capturing) > 0) {
951 return -EBUSY;
952 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300953 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
954 itv->active_input, inp);
955
956 itv->active_input = inp;
957 /* Set the audio input to whatever is appropriate for the
958 input type. */
959 itv->audio_input = itv->card->video_inputs[inp].audio_index;
960
961 /* prevent others from messing with the streams until
962 we're finished changing inputs. */
963 ivtv_mute(itv);
964 ivtv_video_set_io(itv);
965 ivtv_audio_set_io(itv);
966 ivtv_unmute(itv);
967 break;
968 }
969
970 case VIDIOC_G_OUTPUT:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300971 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
972 return -EINVAL;
973 *(int *)arg = itv->active_output;
974 break;
975 }
976
977 case VIDIOC_S_OUTPUT:{
978 int outp = *(int *)arg;
979 struct v4l2_routing route;
980
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300981 if (outp >= itv->card->nof_outputs)
982 return -EINVAL;
983
984 if (outp == itv->active_output) {
985 IVTV_DEBUG_INFO("Output unchanged\n");
986 break;
987 }
988 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
989 itv->active_output, outp);
990
991 itv->active_output = outp;
992 route.input = SAA7127_INPUT_TYPE_NORMAL;
993 route.output = itv->card->video_outputs[outp].video_output;
994 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
995 break;
996 }
997
998 case VIDIOC_G_FREQUENCY:{
999 struct v4l2_frequency *vf = arg;
1000
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001001 if (vf->tuner != 0)
1002 return -EINVAL;
1003 ivtv_call_i2c_clients(itv, cmd, arg);
1004 break;
1005 }
1006
1007 case VIDIOC_S_FREQUENCY:{
1008 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
1009
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001010 if (vf.tuner != 0)
1011 return -EINVAL;
1012
1013 ivtv_mute(itv);
1014 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
1015 ivtv_call_i2c_clients(itv, cmd, &vf);
1016 ivtv_unmute(itv);
1017 break;
1018 }
1019
1020 case VIDIOC_ENUMSTD:{
1021 struct v4l2_standard *vs = arg;
1022 int idx = vs->index;
1023
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001024 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
1025 return -EINVAL;
1026
1027 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
1028 ivtv_std_60hz : ivtv_std_50hz;
1029 vs->index = idx;
1030 vs->id = enum_stds[idx].std;
Hans Verkuilcebfadf2008-04-26 08:51:51 -03001031 strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001032 break;
1033 }
1034
1035 case VIDIOC_G_STD:{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001036 *(v4l2_std_id *) arg = itv->std;
1037 break;
1038 }
1039
1040 case VIDIOC_S_STD: {
1041 v4l2_std_id std = *(v4l2_std_id *) arg;
1042
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001043 if ((std & V4L2_STD_ALL) == 0)
1044 return -EINVAL;
1045
1046 if (std == itv->std)
1047 break;
1048
1049 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1050 atomic_read(&itv->capturing) > 0 ||
1051 atomic_read(&itv->decoding) > 0) {
1052 /* Switching standard would turn off the radio or mess
1053 with already running streams, prevent that by
1054 returning EBUSY. */
1055 return -EBUSY;
1056 }
1057
1058 itv->std = std;
1059 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
1060 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1061 itv->params.width = 720;
1062 itv->params.height = itv->is_50hz ? 576 : 480;
1063 itv->vbi.count = itv->is_50hz ? 18 : 12;
1064 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1065 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1066 if (itv->hw_flags & IVTV_HW_CX25840) {
1067 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1068 }
Hans Verkuilc4385092007-06-07 09:04:03 -03001069 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001070
1071 /* Tuner */
1072 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1073
1074 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1075 /* set display standard */
1076 itv->std_out = std;
1077 itv->is_out_60hz = itv->is_60hz;
1078 itv->is_out_50hz = itv->is_50hz;
1079 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1080 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1081 itv->main_rect.left = itv->main_rect.top = 0;
1082 itv->main_rect.width = 720;
1083 itv->main_rect.height = itv->params.height;
1084 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1085 720, itv->main_rect.height, 0, 0);
Ian Armstrong88ab0752008-04-22 14:42:14 -03001086 yi->main_rect = itv->main_rect;
Ian Armstrong77aded62007-11-05 14:27:09 -03001087 if (!itv->osd_info) {
Ian Armstrong88ab0752008-04-22 14:42:14 -03001088 yi->osd_full_w = 720;
1089 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
Ian Armstrong77aded62007-11-05 14:27:09 -03001090 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001091 }
1092 break;
1093 }
1094
1095 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
1096 struct v4l2_tuner *vt = arg;
1097
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001098 if (vt->index != 0)
1099 return -EINVAL;
1100
1101 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1102 break;
1103 }
1104
1105 case VIDIOC_G_TUNER: {
1106 struct v4l2_tuner *vt = arg;
1107
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001108 if (vt->index != 0)
1109 return -EINVAL;
1110
1111 memset(vt, 0, sizeof(*vt));
1112 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1113
1114 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
Hans Verkuilcebfadf2008-04-26 08:51:51 -03001115 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001116 vt->type = V4L2_TUNER_RADIO;
1117 } else {
Hans Verkuilcebfadf2008-04-26 08:51:51 -03001118 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001119 vt->type = V4L2_TUNER_ANALOG_TV;
1120 }
1121 break;
1122 }
1123
1124 case VIDIOC_G_SLICED_VBI_CAP: {
1125 struct v4l2_sliced_vbi_cap *cap = arg;
1126 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1127 int f, l;
1128 enum v4l2_buf_type type = cap->type;
1129
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001130 memset(cap, 0, sizeof(*cap));
1131 cap->type = type;
1132 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1133 for (f = 0; f < 2; f++) {
1134 for (l = 0; l < 24; l++) {
1135 if (valid_service_line(f, l, itv->is_50hz)) {
1136 cap->service_lines[f][l] = set;
1137 }
1138 }
1139 }
1140 return 0;
1141 }
1142 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1143 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1144 return -EINVAL;
1145 if (itv->is_60hz) {
1146 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1147 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1148 } else {
1149 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1150 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1151 }
1152 return 0;
1153 }
1154 return -EINVAL;
1155 }
1156
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001157 case VIDIOC_G_ENC_INDEX: {
1158 struct v4l2_enc_idx *idx = arg;
Hans Verkuil5614b022007-08-23 17:48:41 -03001159 struct v4l2_enc_idx_entry *e = idx->entry;
1160 int entries;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001161 int i;
1162
Hans Verkuil5614b022007-08-23 17:48:41 -03001163 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001164 IVTV_MAX_PGM_INDEX;
Hans Verkuil5614b022007-08-23 17:48:41 -03001165 if (entries > V4L2_ENC_IDX_ENTRIES)
1166 entries = V4L2_ENC_IDX_ENTRIES;
1167 idx->entries = 0;
1168 for (i = 0; i < entries; i++) {
1169 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1170 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1171 idx->entries++;
1172 e++;
1173 }
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001174 }
1175 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1176 break;
1177 }
1178
1179 case VIDIOC_ENCODER_CMD:
1180 case VIDIOC_TRY_ENCODER_CMD: {
1181 struct v4l2_encoder_cmd *enc = arg;
1182 int try = cmd == VIDIOC_TRY_ENCODER_CMD;
1183
Hans Verkuil25415cf2007-03-10 18:29:48 -03001184 memset(&enc->raw, 0, sizeof(enc->raw));
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001185 switch (enc->cmd) {
1186 case V4L2_ENC_CMD_START:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001187 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001188 enc->flags = 0;
1189 if (try)
1190 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001191 return ivtv_start_capture(id);
1192
1193 case V4L2_ENC_CMD_STOP:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001194 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
Hans Verkuil018ba852007-04-10 18:59:09 -03001195 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001196 if (try)
1197 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001198 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1199 return 0;
1200
1201 case V4L2_ENC_CMD_PAUSE:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001202 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001203 enc->flags = 0;
1204 if (try)
1205 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001206 if (!atomic_read(&itv->capturing))
1207 return -EPERM;
1208 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1209 return 0;
1210 ivtv_mute(itv);
1211 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1212 break;
1213
1214 case V4L2_ENC_CMD_RESUME:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001215 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
Hans Verkuil25415cf2007-03-10 18:29:48 -03001216 enc->flags = 0;
1217 if (try)
1218 return 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001219 if (!atomic_read(&itv->capturing))
1220 return -EPERM;
1221 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1222 return 0;
1223 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1224 ivtv_unmute(itv);
1225 break;
Hans Verkuil25415cf2007-03-10 18:29:48 -03001226 default:
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001227 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
Hans Verkuil25415cf2007-03-10 18:29:48 -03001228 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001229 }
1230 break;
1231 }
1232
1233 case VIDIOC_G_FBUF: {
1234 struct v4l2_framebuffer *fb = arg;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001235 int pixfmt;
1236 static u32 pixel_format[16] = {
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001237 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001238 V4L2_PIX_FMT_RGB565,
1239 V4L2_PIX_FMT_RGB555,
1240 V4L2_PIX_FMT_RGB444,
1241 V4L2_PIX_FMT_RGB32,
1242 0,
1243 0,
1244 0,
Hans Verkuil3eaeef52007-08-25 15:19:18 -03001245 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1246 V4L2_PIX_FMT_YUV565,
1247 V4L2_PIX_FMT_YUV555,
1248 V4L2_PIX_FMT_YUV444,
1249 V4L2_PIX_FMT_YUV32,
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001250 0,
1251 0,
1252 0,
1253 };
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001254
1255 memset(fb, 0, sizeof(*fb));
1256 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001257 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001258 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001259 V4L2_FBUF_CAP_GLOBAL_ALPHA;
1260 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1261 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1262 pixfmt = (data[0] >> 3) & 0xf;
1263 fb->fmt.pixelformat = pixel_format[pixfmt];
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001264 fb->fmt.width = itv->osd_rect.width;
1265 fb->fmt.height = itv->osd_rect.height;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001266 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001267 if (itv->osd_chroma_key_state)
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001268 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001269 if (itv->osd_global_alpha_state)
1270 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1271 pixfmt &= 7;
1272 /* no local alpha for RGB565 or unknown formats */
1273 if (pixfmt == 1 || pixfmt > 4)
1274 break;
1275 /* 16-bit formats have inverted local alpha */
1276 if (pixfmt == 2 || pixfmt == 3)
1277 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1278 else
1279 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
1280 if (itv->osd_local_alpha_state) {
1281 /* 16-bit formats have inverted local alpha */
1282 if (pixfmt == 2 || pixfmt == 3)
1283 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1284 else
1285 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1286 }
Ian Armstrong88ab0752008-04-22 14:42:14 -03001287 if (yi->track_osd)
1288 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001289 break;
1290 }
1291
1292 case VIDIOC_S_FBUF: {
1293 struct v4l2_framebuffer *fb = arg;
1294
1295 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuilf5948bb2007-06-16 18:24:47 -03001296 return -EINVAL;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001297 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001298 itv->osd_local_alpha_state =
1299 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
Hans Verkuilfd8b2812007-08-23 10:13:15 -03001300 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
Hans Verkuilc3624f92007-07-31 07:15:56 -03001301 ivtv_set_osd_alpha(itv);
Ian Armstrong88ab0752008-04-22 14:42:14 -03001302 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001303 break;
1304 }
1305
Hans Verkuil7c03a442007-08-19 18:59:42 -03001306 case VIDIOC_OVERLAY: {
1307 int *on = arg;
1308
1309 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1310 return -EINVAL;
1311 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
1312 break;
1313 }
1314
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001315 case VIDIOC_LOG_STATUS:
1316 {
1317 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1318 struct v4l2_input vidin;
1319 struct v4l2_audio audin;
1320 int i;
1321
1322 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
Hans Verkuil94104aa2007-08-04 04:56:00 -03001323 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001324 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1325 struct tveeprom tv;
1326
1327 ivtv_read_eeprom(itv, &tv);
1328 }
1329 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1330 ivtv_get_input(itv, itv->active_input, &vidin);
1331 ivtv_get_audio_input(itv, itv->audio_input, &audin);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001332 IVTV_INFO("Video Input: %s\n", vidin.name);
1333 IVTV_INFO("Audio Input: %s%s\n", audin.name,
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001334 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001335 if (has_output) {
1336 struct v4l2_output vidout;
1337 struct v4l2_audioout audout;
1338 int mode = itv->output_mode;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001339 static const char * const output_modes[5] = {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001340 "None",
1341 "MPEG Streaming",
1342 "YUV Streaming",
1343 "YUV Frames",
1344 "Passthrough",
1345 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001346 static const char * const audio_modes[5] = {
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001347 "Stereo",
1348 "Left",
1349 "Right",
1350 "Mono",
1351 "Swapped"
1352 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001353 static const char * const alpha_mode[4] = {
Hans Verkuil7c03a442007-08-19 18:59:42 -03001354 "None",
1355 "Global",
1356 "Local",
1357 "Global and Local"
1358 };
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001359 static const char * const pixel_format[16] = {
1360 "ARGB Indexed",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001361 "RGB 5:6:5",
1362 "ARGB 1:5:5:5",
1363 "ARGB 1:4:4:4",
1364 "ARGB 8:8:8:8",
1365 "5",
1366 "6",
1367 "7",
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001368 "AYUV Indexed",
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001369 "YUV 5:6:5",
1370 "AYUV 1:5:5:5",
1371 "AYUV 1:4:4:4",
1372 "AYUV 8:8:8:8",
1373 "13",
1374 "14",
1375 "15",
Hans Verkuil7c03a442007-08-19 18:59:42 -03001376 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001377
1378 ivtv_get_output(itv, itv->active_output, &vidout);
1379 ivtv_get_audio_output(itv, 0, &audout);
1380 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil25e3f8f2007-08-19 15:03:05 -03001381 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1382 audio_modes[itv->audio_stereo_mode],
1383 audio_modes[itv->audio_bilingual_mode]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001384 if (mode < 0 || mode > OUT_PASSTHROUGH)
1385 mode = OUT_NONE;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001386 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1387 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001388 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
Hans Verkuil7c03a442007-08-19 18:59:42 -03001389 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1390 data[0] & 1 ? "On" : "Off",
1391 alpha_mode[(data[0] >> 1) & 0x3],
Hans Verkuild2a35fb2007-08-22 08:43:34 -03001392 pixel_format[(data[0] >> 3) & 0xf]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001393 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001394 IVTV_INFO("Tuner: %s\n",
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001395 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1396 cx2341x_log_status(&itv->params, itv->name);
Hans Verkuil7c03a442007-08-19 18:59:42 -03001397 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001398 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1399 struct ivtv_stream *s = &itv->streams[i];
1400
1401 if (s->v4l2dev == NULL || s->buffers == 0)
1402 continue;
1403 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1404 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1405 (s->buffers * s->buf_size) / 1024, s->buffers);
1406 }
Hans Verkuil7c03a442007-08-19 18:59:42 -03001407 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 -03001408 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1409 break;
1410 }
1411
1412 default:
1413 return -EINVAL;
1414 }
1415 return 0;
1416}
1417
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001418static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001419{
1420 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1421 struct ivtv *itv = id->itv;
1422 int nonblocking = filp->f_flags & O_NONBLOCK;
1423 struct ivtv_stream *s = &itv->streams[id->type];
1424
1425 switch (cmd) {
1426 case IVTV_IOC_DMA_FRAME: {
1427 struct ivtv_dma_frame *args = arg;
1428
1429 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1430 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1431 return -EINVAL;
1432 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1433 return -EINVAL;
1434 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1435 return 0;
1436 if (ivtv_claim_stream(id, id->type)) {
1437 return -EBUSY;
1438 }
1439 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1440 ivtv_release_stream(s);
1441 return -EBUSY;
1442 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001443 /* Mark that this file handle started the UDMA_YUV mode */
1444 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001445 if (args->y_source == NULL)
1446 return 0;
1447 return ivtv_yuv_prep_frame(itv, args);
1448 }
1449
1450 case VIDEO_GET_PTS: {
1451 u32 data[CX2341X_MBOX_MAX_DATA];
1452 u64 *pts = arg;
1453
1454 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1455 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1456 *pts = s->dma_pts;
1457 break;
1458 }
1459 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1460 return -EINVAL;
1461
1462 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1463 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1464 (u64)itv->last_dec_timing[1];
1465 break;
1466 }
1467 *pts = 0;
1468 if (atomic_read(&itv->decoding)) {
1469 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1470 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1471 return -EIO;
1472 }
1473 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1474 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1475 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1476 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1477 }
1478 break;
1479 }
1480
1481 case VIDEO_GET_FRAME_COUNT: {
1482 u32 data[CX2341X_MBOX_MAX_DATA];
1483 u64 *frame = arg;
1484
1485 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1486 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1487 *frame = 0;
1488 break;
1489 }
1490 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1491 return -EINVAL;
1492
1493 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1494 *frame = itv->last_dec_timing[0];
1495 break;
1496 }
1497 *frame = 0;
1498 if (atomic_read(&itv->decoding)) {
1499 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1500 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1501 return -EIO;
1502 }
1503 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1504 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1505 *frame = data[0];
1506 }
1507 break;
1508 }
1509
1510 case VIDEO_PLAY: {
1511 struct video_command vc;
1512
1513 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1514 memset(&vc, 0, sizeof(vc));
1515 vc.cmd = VIDEO_CMD_PLAY;
1516 return ivtv_video_command(itv, id, &vc, 0);
1517 }
1518
1519 case VIDEO_STOP: {
1520 struct video_command vc;
1521
1522 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1523 memset(&vc, 0, sizeof(vc));
1524 vc.cmd = VIDEO_CMD_STOP;
1525 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1526 return ivtv_video_command(itv, id, &vc, 0);
1527 }
1528
1529 case VIDEO_FREEZE: {
1530 struct video_command vc;
1531
1532 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1533 memset(&vc, 0, sizeof(vc));
1534 vc.cmd = VIDEO_CMD_FREEZE;
1535 return ivtv_video_command(itv, id, &vc, 0);
1536 }
1537
1538 case VIDEO_CONTINUE: {
1539 struct video_command vc;
1540
1541 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1542 memset(&vc, 0, sizeof(vc));
1543 vc.cmd = VIDEO_CMD_CONTINUE;
1544 return ivtv_video_command(itv, id, &vc, 0);
1545 }
1546
1547 case VIDEO_COMMAND:
1548 case VIDEO_TRY_COMMAND: {
1549 struct video_command *vc = arg;
1550 int try = (cmd == VIDEO_TRY_COMMAND);
1551
1552 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001553 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001554 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001555 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001556 return ivtv_video_command(itv, id, vc, try);
1557 }
1558
1559 case VIDEO_GET_EVENT: {
1560 struct video_event *ev = arg;
1561 DEFINE_WAIT(wait);
1562
1563 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1564 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1565 return -EINVAL;
1566 memset(ev, 0, sizeof(*ev));
1567 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1568
1569 while (1) {
1570 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1571 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1572 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1573 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001574 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1575 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1576 if (itv->output_mode == OUT_UDMA_YUV &&
1577 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1578 IVTV_YUV_MODE_PROGRESSIVE) {
1579 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1580 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001581 }
1582 if (ev->type)
1583 return 0;
1584 if (nonblocking)
1585 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001586 /* Wait for event. Note that serialize_lock is locked,
1587 so to allow other processes to access the driver while
1588 we are waiting unlock first and later lock again. */
1589 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001590 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1591 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1592 schedule();
1593 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001594 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001595 if (signal_pending(current)) {
1596 /* return if a signal was received */
1597 IVTV_DEBUG_INFO("User stopped wait for event\n");
1598 return -EINTR;
1599 }
1600 }
1601 break;
1602 }
1603
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001604 default:
1605 return -EINVAL;
1606 }
1607 return 0;
1608}
1609
1610static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1611 unsigned int cmd, void *arg)
1612{
1613 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1614 struct ivtv *itv = id->itv;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001615 int ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001616
Hans Verkuild46c17d2007-03-10 17:59:15 -03001617 /* check priority */
1618 switch (cmd) {
1619 case VIDIOC_S_CTRL:
1620 case VIDIOC_S_STD:
1621 case VIDIOC_S_INPUT:
1622 case VIDIOC_S_OUTPUT:
1623 case VIDIOC_S_TUNER:
1624 case VIDIOC_S_FREQUENCY:
1625 case VIDIOC_S_FMT:
1626 case VIDIOC_S_CROP:
1627 case VIDIOC_S_AUDIO:
1628 case VIDIOC_S_AUDOUT:
1629 case VIDIOC_S_EXT_CTRLS:
1630 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001631 case VIDIOC_OVERLAY:
Hans Verkuild46c17d2007-03-10 17:59:15 -03001632 ret = v4l2_prio_check(&itv->prio, &id->prio);
1633 if (ret)
1634 return ret;
1635 }
1636
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001637 switch (cmd) {
1638 case VIDIOC_DBG_G_REGISTER:
1639 case VIDIOC_DBG_S_REGISTER:
1640 case VIDIOC_G_CHIP_IDENT:
1641 case VIDIOC_INT_S_AUDIO_ROUTING:
1642 case VIDIOC_INT_RESET:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001643 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1644 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1645 v4l_printk_ioctl(cmd);
Mauro Carvalho Chehab5e28e002008-04-13 15:06:24 -03001646 printk("\n");
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001647 }
1648 return ivtv_debug_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001649
Hans Verkuild46c17d2007-03-10 17:59:15 -03001650 case VIDIOC_G_PRIORITY:
1651 case VIDIOC_S_PRIORITY:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001652 case VIDIOC_QUERYCAP:
1653 case VIDIOC_ENUMINPUT:
1654 case VIDIOC_G_INPUT:
1655 case VIDIOC_S_INPUT:
1656 case VIDIOC_ENUMOUTPUT:
1657 case VIDIOC_G_OUTPUT:
1658 case VIDIOC_S_OUTPUT:
1659 case VIDIOC_G_FMT:
1660 case VIDIOC_S_FMT:
1661 case VIDIOC_TRY_FMT:
1662 case VIDIOC_ENUM_FMT:
Hans Verkuil987e00b2007-05-29 13:03:27 -03001663 case VIDIOC_CROPCAP:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001664 case VIDIOC_G_CROP:
1665 case VIDIOC_S_CROP:
1666 case VIDIOC_G_FREQUENCY:
1667 case VIDIOC_S_FREQUENCY:
1668 case VIDIOC_ENUMSTD:
1669 case VIDIOC_G_STD:
1670 case VIDIOC_S_STD:
1671 case VIDIOC_S_TUNER:
1672 case VIDIOC_G_TUNER:
1673 case VIDIOC_ENUMAUDIO:
1674 case VIDIOC_S_AUDIO:
1675 case VIDIOC_G_AUDIO:
1676 case VIDIOC_ENUMAUDOUT:
1677 case VIDIOC_S_AUDOUT:
1678 case VIDIOC_G_AUDOUT:
1679 case VIDIOC_G_SLICED_VBI_CAP:
1680 case VIDIOC_LOG_STATUS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001681 case VIDIOC_G_ENC_INDEX:
1682 case VIDIOC_ENCODER_CMD:
1683 case VIDIOC_TRY_ENCODER_CMD:
1684 case VIDIOC_G_FBUF:
1685 case VIDIOC_S_FBUF:
Hans Verkuil7c03a442007-08-19 18:59:42 -03001686 case VIDIOC_OVERLAY:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001687 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1688 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1689 v4l_printk_ioctl(cmd);
Mauro Carvalho Chehab5e28e002008-04-13 15:06:24 -03001690 printk("\n");
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001691 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001692 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1693
1694 case VIDIOC_QUERYMENU:
1695 case VIDIOC_QUERYCTRL:
1696 case VIDIOC_S_CTRL:
1697 case VIDIOC_G_CTRL:
1698 case VIDIOC_S_EXT_CTRLS:
1699 case VIDIOC_G_EXT_CTRLS:
1700 case VIDIOC_TRY_EXT_CTRLS:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001701 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1702 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1703 v4l_printk_ioctl(cmd);
Mauro Carvalho Chehab5e28e002008-04-13 15:06:24 -03001704 printk("\n");
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001705 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001706 return ivtv_control_ioctls(itv, cmd, arg);
1707
1708 case IVTV_IOC_DMA_FRAME:
1709 case VIDEO_GET_PTS:
1710 case VIDEO_GET_FRAME_COUNT:
1711 case VIDEO_GET_EVENT:
1712 case VIDEO_PLAY:
1713 case VIDEO_STOP:
1714 case VIDEO_FREEZE:
1715 case VIDEO_CONTINUE:
1716 case VIDEO_COMMAND:
1717 case VIDEO_TRY_COMMAND:
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001718 return ivtv_decoder_ioctls(filp, cmd, arg);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001719
1720 case 0x00005401: /* Handle isatty() calls */
1721 return -EINVAL;
1722 default:
1723 return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
1724 ivtv_v4l2_do_ioctl);
1725 }
1726 return 0;
1727}
1728
Hans Verkuilbaa40722007-08-19 07:10:55 -03001729static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1730 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001731{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001732 /* Filter dvb ioctls that cannot be handled by video_usercopy */
1733 switch (cmd) {
1734 case VIDEO_SELECT_SOURCE:
1735 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1736 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1737 return -EINVAL;
1738 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1739
1740 case AUDIO_SET_MUTE:
1741 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1742 itv->speed_mute_audio = arg;
1743 return 0;
1744
1745 case AUDIO_CHANNEL_SELECT:
1746 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1747 if (arg > AUDIO_STEREO_SWAPPED)
1748 return -EINVAL;
1749 itv->audio_stereo_mode = arg;
1750 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1751 return 0;
1752
1753 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1754 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1755 if (arg > AUDIO_STEREO_SWAPPED)
1756 return -EINVAL;
1757 itv->audio_bilingual_mode = arg;
1758 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1759 return 0;
1760
1761 default:
1762 break;
1763 }
1764 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
1765}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001766
1767int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1768 unsigned long arg)
1769{
1770 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1771 struct ivtv *itv = id->itv;
1772 int res;
1773
1774 mutex_lock(&itv->serialize_lock);
1775 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1776 mutex_unlock(&itv->serialize_lock);
1777 return res;
1778}