blob: c13bd2aa0bea6180a98fe078be7449e6ea2e25ca [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
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300104static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300105{
106 int f, l;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300107
108 for (f = 0; f < 2; f++) {
109 for (l = 0; l < 24; l++) {
110 fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300111 }
112 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300113}
114
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300115u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300116{
117 int f, l;
118 u16 set = 0;
119
120 for (f = 0; f < 2; f++) {
121 for (l = 0; l < 24; l++) {
122 set |= fmt->service_lines[f][l];
123 }
124 }
125 return set;
126}
127
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300128void ivtv_set_osd_alpha(struct ivtv *itv)
129{
130 ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
131 itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300132 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 -0300133}
134
135int ivtv_set_speed(struct ivtv *itv, int speed)
136{
137 u32 data[CX2341X_MBOX_MAX_DATA];
138 struct ivtv_stream *s;
139 int single_step = (speed == 1 || speed == -1);
140 DEFINE_WAIT(wait);
141
142 if (speed == 0) speed = 1000;
143
144 /* No change? */
145 if (speed == itv->speed && !single_step)
146 return 0;
147
148 s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
149
150 if (single_step && (speed < 0) == (itv->speed < 0)) {
151 /* Single step video and no need to change direction */
152 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
153 itv->speed = speed;
154 return 0;
155 }
156 if (single_step)
157 /* Need to change direction */
158 speed = speed < 0 ? -1000 : 1000;
159
160 data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
161 data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
162 data[1] = (speed < 0);
163 data[2] = speed < 0 ? 3 : 7;
164 data[3] = itv->params.video_b_frames;
165 data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
166 data[5] = 0;
167 data[6] = 0;
168
169 if (speed == 1500 || speed == -1500) data[0] |= 1;
170 else if (speed == 2000 || speed == -2000) data[0] |= 2;
171 else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
172 else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
173
174 /* If not decoding, just change speed setting */
175 if (atomic_read(&itv->decoding) > 0) {
176 int got_sig = 0;
177
178 /* Stop all DMA and decoding activity */
179 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
180
181 /* Wait for any DMA to finish */
182 prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
183 while (itv->i_flags & IVTV_F_I_DMA) {
184 got_sig = signal_pending(current);
185 if (got_sig)
186 break;
187 got_sig = 0;
188 schedule();
189 }
190 finish_wait(&itv->dma_waitq, &wait);
191 if (got_sig)
192 return -EINTR;
193
194 /* Change Speed safely */
195 ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
196 IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
197 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
198 }
199 if (single_step) {
200 speed = (speed < 0) ? -1 : 1;
201 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
202 }
203 itv->speed = speed;
204 return 0;
205}
206
207static int ivtv_validate_speed(int cur_speed, int new_speed)
208{
209 int fact = new_speed < 0 ? -1 : 1;
210 int s;
211
Hans Verkuil94dee762008-04-26 09:26:13 -0300212 if (cur_speed == 0)
213 cur_speed = 1000;
214 if (new_speed < 0)
215 new_speed = -new_speed;
216 if (cur_speed < 0)
217 cur_speed = -cur_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300218
219 if (cur_speed <= new_speed) {
Hans Verkuil94dee762008-04-26 09:26:13 -0300220 if (new_speed > 1500)
221 return fact * 2000;
222 if (new_speed > 1000)
223 return fact * 1500;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300224 }
225 else {
Hans Verkuil94dee762008-04-26 09:26:13 -0300226 if (new_speed >= 2000)
227 return fact * 2000;
228 if (new_speed >= 1500)
229 return fact * 1500;
230 if (new_speed >= 1000)
231 return fact * 1000;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300232 }
Hans Verkuil94dee762008-04-26 09:26:13 -0300233 if (new_speed == 0)
234 return 1000;
235 if (new_speed == 1 || new_speed == 1000)
236 return fact * new_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300237
238 s = new_speed;
239 new_speed = 1000 / new_speed;
240 if (1000 / cur_speed == new_speed)
241 new_speed += (cur_speed < s) ? -1 : 1;
242 if (new_speed > 60) return 1000 / (fact * 60);
243 return 1000 / (fact * new_speed);
244}
245
246static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
247 struct video_command *vc, int try)
248{
249 struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
250
251 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
252 return -EINVAL;
253
254 switch (vc->cmd) {
255 case VIDEO_CMD_PLAY: {
Hans Verkuil25415cf2007-03-10 18:29:48 -0300256 vc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300257 vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed);
258 if (vc->play.speed < 0)
259 vc->play.format = VIDEO_PLAY_FMT_GOP;
260 if (try) break;
261
262 if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
263 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300264 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
265 /* forces ivtv_set_speed to be called */
266 itv->speed = 0;
267 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300268 return ivtv_start_decoding(id, vc->play.speed);
269 }
270
271 case VIDEO_CMD_STOP:
Hans Verkuil018ba852007-04-10 18:59:09 -0300272 vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300273 if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY)
274 vc->stop.pts = 0;
275 if (try) break;
276 if (atomic_read(&itv->decoding) == 0)
277 return 0;
278 if (itv->output_mode != OUT_MPG)
279 return -EBUSY;
280
281 itv->output_mode = OUT_NONE;
282 return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts);
283
284 case VIDEO_CMD_FREEZE:
Hans Verkuil018ba852007-04-10 18:59:09 -0300285 vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300286 if (try) break;
287 if (itv->output_mode != OUT_MPG)
288 return -EBUSY;
289 if (atomic_read(&itv->decoding) > 0) {
290 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
291 (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0);
Hans Verkuilac425142007-07-22 08:46:38 -0300292 set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300293 }
294 break;
295
296 case VIDEO_CMD_CONTINUE:
Hans Verkuil25415cf2007-03-10 18:29:48 -0300297 vc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300298 if (try) break;
299 if (itv->output_mode != OUT_MPG)
300 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300301 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
302 int speed = itv->speed;
303 itv->speed = 0;
304 return ivtv_start_decoding(id, speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300305 }
306 break;
307
308 default:
309 return -EINVAL;
310 }
311 return 0;
312}
313
Hans Verkuil3f038d82008-05-29 16:43:54 -0300314static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300315{
Hans Verkuil3f038d82008-05-29 16:43:54 -0300316 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
317 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300318
Hans Verkuile88360c2008-06-21 08:00:56 -0300319 vbifmt->reserved[0] = 0;
320 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300321 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300322 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300323 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
324 if (itv->is_60hz) {
325 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
326 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
327 } else {
328 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
329 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
330 }
331 vbifmt->service_set = ivtv_get_service_set(vbifmt);
332 return 0;
333}
334
335static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
336{
337 struct ivtv_open_id *id = fh;
338 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300339 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300340
Hans Verkuile88360c2008-06-21 08:00:56 -0300341 pixfmt->width = itv->params.width;
342 pixfmt->height = itv->params.height;
343 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
344 pixfmt->field = V4L2_FIELD_INTERLACED;
345 pixfmt->priv = 0;
346 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
347 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300348 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
Hans Verkuile88360c2008-06-21 08:00:56 -0300349 pixfmt->sizeimage =
350 pixfmt->height * pixfmt->width +
351 pixfmt->height * (pixfmt->width / 2);
352 pixfmt->bytesperline = 720;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300353 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300354 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
355 pixfmt->sizeimage = 128 * 1024;
356 pixfmt->bytesperline = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300357 }
358 return 0;
359}
360
Hans Verkuil3f038d82008-05-29 16:43:54 -0300361static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300362{
Hans Verkuil3f038d82008-05-29 16:43:54 -0300363 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300364 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300365
Hans Verkuile88360c2008-06-21 08:00:56 -0300366 vbifmt->sampling_rate = 27000000;
367 vbifmt->offset = 248;
368 vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
369 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
370 vbifmt->start[0] = itv->vbi.start[0];
371 vbifmt->start[1] = itv->vbi.start[1];
372 vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
373 vbifmt->flags = 0;
374 vbifmt->reserved[0] = 0;
375 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300376 return 0;
377}
378
379static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
380{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300381 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300382 struct ivtv_open_id *id = fh;
383 struct ivtv *itv = id->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300384
Hans Verkuile88360c2008-06-21 08:00:56 -0300385 vbifmt->reserved[0] = 0;
386 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300387 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300388
Hans Verkuil3f038d82008-05-29 16:43:54 -0300389 if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
390 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
391 V4L2_SLICED_VBI_525;
392 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300393 return 0;
394 }
395
Hans Verkuil7bf432d2009-02-16 04:25:32 -0300396 v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300397 vbifmt->service_set = ivtv_get_service_set(vbifmt);
398 return 0;
399}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300400
Hans Verkuil3f038d82008-05-29 16:43:54 -0300401static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
402{
403 struct ivtv_open_id *id = fh;
404 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300405 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300406
Hans Verkuil3f038d82008-05-29 16:43:54 -0300407 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300408 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300409 pixfmt->width = itv->main_rect.width;
410 pixfmt->height = itv->main_rect.height;
411 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
412 pixfmt->field = V4L2_FIELD_INTERLACED;
413 pixfmt->priv = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300414 if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
415 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
416 case IVTV_YUV_MODE_INTERLACED:
Hans Verkuile88360c2008-06-21 08:00:56 -0300417 pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
Hans Verkuil3f038d82008-05-29 16:43:54 -0300418 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
419 break;
420 case IVTV_YUV_MODE_PROGRESSIVE:
Hans Verkuile88360c2008-06-21 08:00:56 -0300421 pixfmt->field = V4L2_FIELD_NONE;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300422 break;
423 default:
Hans Verkuile88360c2008-06-21 08:00:56 -0300424 pixfmt->field = V4L2_FIELD_ANY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300425 break;
426 }
Hans Verkuile88360c2008-06-21 08:00:56 -0300427 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
428 pixfmt->bytesperline = 720;
429 pixfmt->width = itv->yuv_info.v4l2_src_w;
430 pixfmt->height = itv->yuv_info.v4l2_src_h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300431 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
Hans Verkuile88360c2008-06-21 08:00:56 -0300432 pixfmt->sizeimage =
433 1080 * ((pixfmt->height + 31) & ~31);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300434 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300435 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
436 pixfmt->sizeimage = 128 * 1024;
437 pixfmt->bytesperline = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300438 }
439 return 0;
440}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300441
Hans Verkuil3f038d82008-05-29 16:43:54 -0300442static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
443{
444 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300445 struct v4l2_window *winfmt = &fmt->fmt.win;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300446
447 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
448 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300449 winfmt->chromakey = itv->osd_chroma_key;
450 winfmt->global_alpha = itv->osd_global_alpha;
451 winfmt->field = V4L2_FIELD_INTERLACED;
452 winfmt->clips = NULL;
453 winfmt->clipcount = 0;
454 winfmt->bitmap = NULL;
455 winfmt->w.top = winfmt->w.left = 0;
456 winfmt->w.width = itv->osd_rect.width;
457 winfmt->w.height = itv->osd_rect.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300458 return 0;
459}
460
461static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
462{
463 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
464}
465
466static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
467{
468 struct ivtv_open_id *id = fh;
469 struct ivtv *itv = id->itv;
470 int w = fmt->fmt.pix.width;
471 int h = fmt->fmt.pix.height;
472
473 w = min(w, 720);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300474 w = max(w, 2);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300475 h = min(h, itv->is_50hz ? 576 : 480);
476 h = max(h, 2);
477 ivtv_g_fmt_vid_cap(file, fh, fmt);
478 fmt->fmt.pix.width = w;
479 fmt->fmt.pix.height = h;
480 return 0;
481}
482
483static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
484{
485 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
486}
487
488static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
489{
490 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
491 struct ivtv_open_id *id = fh;
492 struct ivtv *itv = id->itv;
493
494 if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
495 return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300496
497 /* set sliced VBI capture format */
498 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuile88360c2008-06-21 08:00:56 -0300499 vbifmt->reserved[0] = 0;
500 vbifmt->reserved[1] = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300501
502 if (vbifmt->service_set)
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300503 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300504 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300505 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300506 return 0;
507}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300508
Hans Verkuil3f038d82008-05-29 16:43:54 -0300509static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
510{
511 struct ivtv_open_id *id = fh;
Hans Verkuileffc3462008-09-06 08:24:37 -0300512 s32 w = fmt->fmt.pix.width;
513 s32 h = fmt->fmt.pix.height;
514 int field = fmt->fmt.pix.field;
515 int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300516
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300517 w = min(w, 720);
518 w = max(w, 2);
Hans Verkuil962d6992008-10-11 09:00:39 -0300519 /* Why can the height be 576 even when the output is NTSC?
520
521 Internally the buffers of the PVR350 are always set to 720x576. The
522 decoded video frame will always be placed in the top left corner of
523 this buffer. For any video which is not 720x576, the buffer will
524 then be cropped to remove the unused right and lower areas, with
525 the remaining image being scaled by the hardware to fit the display
526 area. The video can be scaled both up and down, so a 720x480 video
527 can be displayed full-screen on PAL and a 720x576 video can be
528 displayed without cropping on NTSC.
529
530 Note that the scaling only occurs on the video stream, the osd
531 resolution is locked to the broadcast standard and not scaled.
532
533 Thanks to Ian Armstrong for this explanation. */
534 h = min(h, 576);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300535 h = max(h, 2);
536 if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300537 fmt->fmt.pix.field = field;
Hans Verkuileffc3462008-09-06 08:24:37 -0300538 fmt->fmt.pix.width = w;
539 fmt->fmt.pix.height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300540 return ret;
541}
542
543static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
544{
545 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300546 u32 chromakey = fmt->fmt.win.chromakey;
547 u8 global_alpha = fmt->fmt.win.global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300548
549 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
550 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300551 ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
552 fmt->fmt.win.chromakey = chromakey;
553 fmt->fmt.win.global_alpha = global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300554 return 0;
555}
556
557static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
558{
559 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
560}
561
562static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
563{
564 struct ivtv_open_id *id = fh;
565 struct ivtv *itv = id->itv;
566 struct cx2341x_mpeg_params *p = &itv->params;
Hans Verkuileffc3462008-09-06 08:24:37 -0300567 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300568 int w = fmt->fmt.pix.width;
569 int h = fmt->fmt.pix.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300570
571 if (ret)
572 return ret;
573
574 if (p->width == w && p->height == h)
575 return 0;
576
577 if (atomic_read(&itv->capturing) > 0)
578 return -EBUSY;
579
580 p->width = w;
581 p->height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300582 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
583 fmt->fmt.pix.width /= 2;
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300584 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300585 return ivtv_g_fmt_vid_cap(file, fh, fmt);
586}
587
588static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
589{
590 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
591
Hans Verkuila8b86432008-10-04 08:05:30 -0300592 if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
593 return -EBUSY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300594 itv->vbi.sliced_in->service_set = 0;
Hans Verkuila8b86432008-10-04 08:05:30 -0300595 itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300596 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300597 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
598}
599
600static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
601{
602 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
603 struct ivtv_open_id *id = fh;
604 struct ivtv *itv = id->itv;
605 int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
606
607 if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
608 return ret;
609
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300610 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuila8b86432008-10-04 08:05:30 -0300611 if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300612 return -EBUSY;
Hans Verkuila8b86432008-10-04 08:05:30 -0300613 itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300614 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300615 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
616 return 0;
617}
618
Hans Verkuil3f038d82008-05-29 16:43:54 -0300619static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300620{
Hans Verkuil3f038d82008-05-29 16:43:54 -0300621 struct ivtv_open_id *id = fh;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300622 struct ivtv *itv = id->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300623 struct yuv_playback_info *yi = &itv->yuv_info;
624 int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300625
Hans Verkuil3f038d82008-05-29 16:43:54 -0300626 if (ret)
627 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300628
Hans Verkuil3f038d82008-05-29 16:43:54 -0300629 if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
630 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300631
Hans Verkuil3f038d82008-05-29 16:43:54 -0300632 /* Return now if we already have some frame data */
633 if (yi->stream_size)
634 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300635
Hans Verkuil3f038d82008-05-29 16:43:54 -0300636 yi->v4l2_src_w = fmt->fmt.pix.width;
637 yi->v4l2_src_h = fmt->fmt.pix.height;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300638
Hans Verkuil3f038d82008-05-29 16:43:54 -0300639 switch (fmt->fmt.pix.field) {
640 case V4L2_FIELD_NONE:
641 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300642 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300643 case V4L2_FIELD_ANY:
644 yi->lace_mode = IVTV_YUV_MODE_AUTO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300645 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300646 case V4L2_FIELD_INTERLACED_BT:
647 yi->lace_mode =
648 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
649 break;
650 case V4L2_FIELD_INTERLACED_TB:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300651 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -0300652 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
653 break;
654 }
655 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
656
657 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
658 itv->dma_data_req_size =
659 1080 * ((yi->v4l2_src_h + 31) & ~31);
660
Hans Verkuil3f038d82008-05-29 16:43:54 -0300661 return 0;
662}
663
664static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
665{
666 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
667 int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
668
669 if (ret == 0) {
670 itv->osd_chroma_key = fmt->fmt.win.chromakey;
671 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
672 ivtv_set_osd_alpha(itv);
673 }
674 return ret;
675}
676
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300677static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300678{
679 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
680
681 chip->ident = V4L2_IDENT_NONE;
682 chip->revision = 0;
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300683 if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
684 if (v4l2_chip_match_host(&chip->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300685 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
686 return 0;
687 }
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300688 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
689 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300690 return -EINVAL;
691 /* TODO: is this correct? */
692 return ivtv_call_all_err(itv, core, g_chip_ident, chip);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300693}
694
Hans Verkuil36ecd492008-06-25 06:00:17 -0300695#ifdef CONFIG_VIDEO_ADV_DEBUG
696static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
697{
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300698 struct v4l2_dbg_register *regs = arg;
Hans Verkuiladb65bc2008-06-25 06:32:44 -0300699 volatile u8 __iomem *reg_start;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300700
701 if (!capable(CAP_SYS_ADMIN))
702 return -EPERM;
703 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
704 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
705 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
706 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
707 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
708 else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
709 reg_start = itv->enc_mem;
710 else
711 return -EINVAL;
712
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300713 regs->size = 4;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300714 if (cmd == VIDIOC_DBG_G_REGISTER)
715 regs->val = readl(regs->reg + reg_start);
716 else
717 writel(regs->val, regs->reg + reg_start);
Hans Verkuil36ecd492008-06-25 06:00:17 -0300718 return 0;
719}
720
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300721static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300722{
723 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
724
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300725 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300726 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300727 /* TODO: subdev errors should not be ignored, this should become a
728 subdev helper function. */
729 ivtv_call_all(itv, core, g_register, reg);
730 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300731}
732
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300733static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300734{
735 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
736
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300737 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300738 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300739 /* TODO: subdev errors should not be ignored, this should become a
740 subdev helper function. */
741 ivtv_call_all(itv, core, s_register, reg);
742 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300743}
Hans Verkuil36ecd492008-06-25 06:00:17 -0300744#endif
Hans Verkuil3f038d82008-05-29 16:43:54 -0300745
746static int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
747{
748 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
749
750 *p = v4l2_prio_max(&itv->prio);
751
752 return 0;
753}
754
755static int ivtv_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
756{
757 struct ivtv_open_id *id = fh;
758 struct ivtv *itv = id->itv;
759
760 return v4l2_prio_change(&itv->prio, &id->prio, prio);
761}
762
763static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
764{
765 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
766
Hans Verkuil3f038d82008-05-29 16:43:54 -0300767 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
768 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
Hans Verkuil741e1f32008-09-08 16:59:02 -0300769 snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev));
Hans Verkuil3f038d82008-05-29 16:43:54 -0300770 vcap->version = IVTV_DRIVER_VERSION; /* version */
771 vcap->capabilities = itv->v4l2_cap; /* capabilities */
Hans Verkuil3f038d82008-05-29 16:43:54 -0300772 return 0;
773}
774
775static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
776{
777 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
778
779 return ivtv_get_audio_input(itv, vin->index, vin);
780}
781
782static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
783{
784 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
785
786 vin->index = itv->audio_input;
787 return ivtv_get_audio_input(itv, vin->index, vin);
788}
789
790static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
791{
792 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
793
794 if (vout->index >= itv->nof_audio_inputs)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300795 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300796
797 itv->audio_input = vout->index;
798 ivtv_audio_set_io(itv);
799
800 return 0;
801}
802
803static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
804{
805 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
806
807 /* set it to defaults from our table */
808 return ivtv_get_audio_output(itv, vin->index, vin);
809}
810
811static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
812{
813 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
814
815 vin->index = 0;
816 return ivtv_get_audio_output(itv, vin->index, vin);
817}
818
819static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
820{
821 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
822
823 return ivtv_get_audio_output(itv, vout->index, vout);
824}
825
826static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
827{
828 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
829
830 /* set it to defaults from our table */
831 return ivtv_get_input(itv, vin->index, vin);
832}
833
834static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
835{
836 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
837
838 return ivtv_get_output(itv, vout->index, vout);
839}
840
841static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
842{
843 struct ivtv_open_id *id = fh;
844 struct ivtv *itv = id->itv;
845 struct yuv_playback_info *yi = &itv->yuv_info;
846 int streamtype;
847
848 streamtype = id->type;
849
850 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
851 return -EINVAL;
852 cropcap->bounds.top = cropcap->bounds.left = 0;
853 cropcap->bounds.width = 720;
854 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
855 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
856 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
857 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
858 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
859 if (yi->track_osd) {
860 cropcap->bounds.width = yi->osd_full_w;
861 cropcap->bounds.height = yi->osd_full_h;
862 } else {
863 cropcap->bounds.width = 720;
864 cropcap->bounds.height =
865 itv->is_out_50hz ? 576 : 480;
866 }
867 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
868 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
869 } else {
870 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
871 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
872 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
873 }
874 cropcap->defrect = cropcap->bounds;
875 return 0;
876}
877
878static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
879{
880 struct ivtv_open_id *id = fh;
881 struct ivtv *itv = id->itv;
882 struct yuv_playback_info *yi = &itv->yuv_info;
883 int streamtype;
884
885 streamtype = id->type;
886
Hans Verkuil3f038d82008-05-29 16:43:54 -0300887 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
888 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
889 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
890 yi->main_rect = crop->c;
891 return 0;
892 } else {
893 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
894 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
895 itv->main_rect = crop->c;
896 return 0;
897 }
898 }
899 return -EINVAL;
900 }
901 return -EINVAL;
902}
903
904static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
905{
906 struct ivtv_open_id *id = fh;
907 struct ivtv *itv = id->itv;
908 struct yuv_playback_info *yi = &itv->yuv_info;
909 int streamtype;
910
911 streamtype = id->type;
912
913 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
914 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
915 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
916 crop->c = yi->main_rect;
917 else
918 crop->c = itv->main_rect;
919 return 0;
920 }
921 return -EINVAL;
922}
923
924static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
925{
926 static struct v4l2_fmtdesc formats[] = {
927 { 0, 0, 0,
928 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
929 { 0, 0, 0, 0 }
930 },
931 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
932 "MPEG", V4L2_PIX_FMT_MPEG,
933 { 0, 0, 0, 0 }
934 }
935 };
936 enum v4l2_buf_type type = fmt->type;
937
938 if (fmt->index > 1)
939 return -EINVAL;
940
941 *fmt = formats[fmt->index];
942 fmt->type = type;
943 return 0;
944}
945
946static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
947{
948 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
949
950 static struct v4l2_fmtdesc formats[] = {
951 { 0, 0, 0,
952 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
953 { 0, 0, 0, 0 }
954 },
955 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
956 "MPEG", V4L2_PIX_FMT_MPEG,
957 { 0, 0, 0, 0 }
958 }
959 };
960 enum v4l2_buf_type type = fmt->type;
961
962 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
963 return -EINVAL;
964
965 if (fmt->index > 1)
966 return -EINVAL;
967
968 *fmt = formats[fmt->index];
969 fmt->type = type;
970
971 return 0;
972}
973
974static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
975{
976 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
977
978 *i = itv->active_input;
979
980 return 0;
981}
982
983int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
984{
985 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
986
987 if (inp < 0 || inp >= itv->nof_inputs)
988 return -EINVAL;
989
990 if (inp == itv->active_input) {
991 IVTV_DEBUG_INFO("Input unchanged\n");
992 return 0;
993 }
994
995 if (atomic_read(&itv->capturing) > 0) {
996 return -EBUSY;
997 }
998
999 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
1000 itv->active_input, inp);
1001
1002 itv->active_input = inp;
1003 /* Set the audio input to whatever is appropriate for the
1004 input type. */
1005 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1006
1007 /* prevent others from messing with the streams until
1008 we're finished changing inputs. */
1009 ivtv_mute(itv);
1010 ivtv_video_set_io(itv);
1011 ivtv_audio_set_io(itv);
1012 ivtv_unmute(itv);
1013
1014 return 0;
1015}
1016
1017static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1018{
1019 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1020
1021 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1022 return -EINVAL;
1023
1024 *i = itv->active_output;
1025
1026 return 0;
1027}
1028
1029static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1030{
1031 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1032 struct v4l2_routing route;
1033
1034 if (outp >= itv->card->nof_outputs)
1035 return -EINVAL;
1036
1037 if (outp == itv->active_output) {
1038 IVTV_DEBUG_INFO("Output unchanged\n");
1039 return 0;
1040 }
1041 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1042 itv->active_output, outp);
1043
1044 itv->active_output = outp;
1045 route.input = SAA7127_INPUT_TYPE_NORMAL;
1046 route.output = itv->card->video_outputs[outp].video_output;
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001047 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, &route);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001048
1049 return 0;
1050}
1051
1052static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1053{
1054 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1055
1056 if (vf->tuner != 0)
1057 return -EINVAL;
1058
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001059 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001060 return 0;
1061}
1062
1063int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1064{
1065 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1066
1067 if (vf->tuner != 0)
1068 return -EINVAL;
1069
1070 ivtv_mute(itv);
1071 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001072 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001073 ivtv_unmute(itv);
1074 return 0;
1075}
1076
1077static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1078{
1079 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1080
1081 *std = itv->std;
1082 return 0;
1083}
1084
1085int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1086{
1087 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1088 struct yuv_playback_info *yi = &itv->yuv_info;
1089
1090 if ((*std & V4L2_STD_ALL) == 0)
1091 return -EINVAL;
1092
1093 if (*std == itv->std)
1094 return 0;
1095
1096 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1097 atomic_read(&itv->capturing) > 0 ||
1098 atomic_read(&itv->decoding) > 0) {
1099 /* Switching standard would turn off the radio or mess
1100 with already running streams, prevent that by
1101 returning EBUSY. */
1102 return -EBUSY;
1103 }
1104
1105 itv->std = *std;
1106 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1107 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1108 itv->params.width = 720;
1109 itv->params.height = itv->is_50hz ? 576 : 480;
1110 itv->vbi.count = itv->is_50hz ? 18 : 12;
1111 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1112 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1113
1114 if (itv->hw_flags & IVTV_HW_CX25840)
1115 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1116
1117 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
1118
1119 /* Tuner */
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001120 ivtv_call_all(itv, tuner, s_std, itv->std);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001121
1122 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1123 /* set display standard */
1124 itv->std_out = *std;
1125 itv->is_out_60hz = itv->is_60hz;
1126 itv->is_out_50hz = itv->is_50hz;
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001127 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001128 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1129 itv->main_rect.left = itv->main_rect.top = 0;
1130 itv->main_rect.width = 720;
1131 itv->main_rect.height = itv->params.height;
1132 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1133 720, itv->main_rect.height, 0, 0);
1134 yi->main_rect = itv->main_rect;
1135 if (!itv->osd_info) {
1136 yi->osd_full_w = 720;
1137 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1138 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001139 }
1140 return 0;
1141}
1142
Hans Verkuil3f038d82008-05-29 16:43:54 -03001143static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001144{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001145 struct ivtv_open_id *id = fh;
1146 struct ivtv *itv = id->itv;
1147
1148 if (vt->index != 0)
1149 return -EINVAL;
1150
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001151 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001152
1153 return 0;
1154}
1155
1156static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1157{
1158 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1159
1160 if (vt->index != 0)
1161 return -EINVAL;
1162
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001163 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001164
1165 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1166 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
1167 vt->type = V4L2_TUNER_RADIO;
1168 } else {
1169 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
1170 vt->type = V4L2_TUNER_ANALOG_TV;
1171 }
1172
1173 return 0;
1174}
1175
1176static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1177{
1178 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1179 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1180 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001181
Hans Verkuil79afcb12008-06-21 09:02:36 -03001182 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001183 for (f = 0; f < 2; f++) {
1184 for (l = 0; l < 24; l++) {
1185 if (valid_service_line(f, l, itv->is_50hz))
1186 cap->service_lines[f][l] = set;
1187 }
1188 }
1189 return 0;
1190 }
Hans Verkuil79afcb12008-06-21 09:02:36 -03001191 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001192 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1193 return -EINVAL;
1194 if (itv->is_60hz) {
1195 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1196 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1197 } else {
1198 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1199 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1200 }
1201 return 0;
1202 }
1203 return -EINVAL;
1204}
1205
1206static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1207{
1208 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1209 struct v4l2_enc_idx_entry *e = idx->entry;
1210 int entries;
1211 int i;
1212
1213 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1214 IVTV_MAX_PGM_INDEX;
1215 if (entries > V4L2_ENC_IDX_ENTRIES)
1216 entries = V4L2_ENC_IDX_ENTRIES;
1217 idx->entries = 0;
1218 for (i = 0; i < entries; i++) {
1219 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1220 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1221 idx->entries++;
1222 e++;
1223 }
1224 }
1225 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1226 return 0;
1227}
1228
1229static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1230{
1231 struct ivtv_open_id *id = fh;
1232 struct ivtv *itv = id->itv;
1233
Hans Verkuil3f038d82008-05-29 16:43:54 -03001234
1235 switch (enc->cmd) {
1236 case V4L2_ENC_CMD_START:
1237 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1238 enc->flags = 0;
1239 return ivtv_start_capture(id);
1240
1241 case V4L2_ENC_CMD_STOP:
1242 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1243 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1244 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1245 return 0;
1246
1247 case V4L2_ENC_CMD_PAUSE:
1248 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1249 enc->flags = 0;
1250
1251 if (!atomic_read(&itv->capturing))
1252 return -EPERM;
1253 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1254 return 0;
1255
1256 ivtv_mute(itv);
1257 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1258 break;
1259
1260 case V4L2_ENC_CMD_RESUME:
1261 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1262 enc->flags = 0;
1263
1264 if (!atomic_read(&itv->capturing))
1265 return -EPERM;
1266
1267 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1268 return 0;
1269
1270 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1271 ivtv_unmute(itv);
1272 break;
1273 default:
1274 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1275 return -EINVAL;
1276 }
1277
1278 return 0;
1279}
1280
1281static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1282{
1283 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1284
Hans Verkuil3f038d82008-05-29 16:43:54 -03001285 switch (enc->cmd) {
1286 case V4L2_ENC_CMD_START:
1287 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1288 enc->flags = 0;
1289 return 0;
1290
1291 case V4L2_ENC_CMD_STOP:
1292 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1293 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1294 return 0;
1295
1296 case V4L2_ENC_CMD_PAUSE:
1297 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1298 enc->flags = 0;
1299 return 0;
1300
1301 case V4L2_ENC_CMD_RESUME:
1302 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1303 enc->flags = 0;
1304 return 0;
1305 default:
1306 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1307 return -EINVAL;
1308 }
1309}
1310
1311static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1312{
1313 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001314 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001315 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001316
Hans Verkuil3f038d82008-05-29 16:43:54 -03001317 int pixfmt;
1318 static u32 pixel_format[16] = {
1319 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1320 V4L2_PIX_FMT_RGB565,
1321 V4L2_PIX_FMT_RGB555,
1322 V4L2_PIX_FMT_RGB444,
1323 V4L2_PIX_FMT_RGB32,
1324 0,
1325 0,
1326 0,
1327 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1328 V4L2_PIX_FMT_YUV565,
1329 V4L2_PIX_FMT_YUV555,
1330 V4L2_PIX_FMT_YUV444,
1331 V4L2_PIX_FMT_YUV32,
1332 0,
1333 0,
1334 0,
1335 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001336
Hans Verkuil3f038d82008-05-29 16:43:54 -03001337 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1338 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001339 if (!itv->osd_video_pbase)
1340 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001341
Hans Verkuil3f038d82008-05-29 16:43:54 -03001342 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1343 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001344
Hans Verkuil3f038d82008-05-29 16:43:54 -03001345 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1346 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1347 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001348
Hans Verkuil3f038d82008-05-29 16:43:54 -03001349 fb->fmt.pixelformat = pixel_format[pixfmt];
1350 fb->fmt.width = itv->osd_rect.width;
1351 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001352 fb->fmt.field = V4L2_FIELD_INTERLACED;
1353 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001354 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1355 fb->fmt.field = V4L2_FIELD_INTERLACED;
1356 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001357 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1358 fb->fmt.bytesperline *= 2;
1359 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1360 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1361 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001362 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001363 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001364 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001365
Hans Verkuil3f038d82008-05-29 16:43:54 -03001366 if (itv->osd_chroma_key_state)
1367 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001368
Hans Verkuil3f038d82008-05-29 16:43:54 -03001369 if (itv->osd_global_alpha_state)
1370 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001371
Ian Armstrongec9faa12008-10-06 03:06:08 -03001372 if (yi->track_osd)
1373 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1374
Hans Verkuil3f038d82008-05-29 16:43:54 -03001375 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001376
Hans Verkuil3f038d82008-05-29 16:43:54 -03001377 /* no local alpha for RGB565 or unknown formats */
1378 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001379 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001380
Hans Verkuil3f038d82008-05-29 16:43:54 -03001381 /* 16-bit formats have inverted local alpha */
1382 if (pixfmt == 2 || pixfmt == 3)
1383 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1384 else
1385 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001386
Hans Verkuil3f038d82008-05-29 16:43:54 -03001387 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001388 /* 16-bit formats have inverted local alpha */
1389 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001390 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001391 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001392 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001393 }
1394
Hans Verkuil3f038d82008-05-29 16:43:54 -03001395 return 0;
1396}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001397
Hans Verkuil3f038d82008-05-29 16:43:54 -03001398static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1399{
1400 struct ivtv_open_id *id = fh;
1401 struct ivtv *itv = id->itv;
1402 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001403
Hans Verkuil3f038d82008-05-29 16:43:54 -03001404 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001405 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001406 if (!itv->osd_video_pbase)
1407 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001408
1409 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1410 itv->osd_local_alpha_state =
1411 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1412 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1413 ivtv_set_osd_alpha(itv);
1414 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001415 return ivtv_g_fbuf(file, fh, fb);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001416}
1417
1418static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1419{
1420 struct ivtv_open_id *id = fh;
1421 struct ivtv *itv = id->itv;
1422
1423 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1424 return -EINVAL;
1425
1426 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1427
1428 return 0;
1429}
1430
1431static int ivtv_log_status(struct file *file, void *fh)
1432{
1433 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1434 u32 data[CX2341X_MBOX_MAX_DATA];
1435
1436 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1437 struct v4l2_input vidin;
1438 struct v4l2_audio audin;
1439 int i;
1440
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001441 IVTV_INFO("================= START STATUS CARD #%d =================\n",
1442 itv->instance);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001443 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1444 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1445 struct tveeprom tv;
1446
1447 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001448 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001449 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001450 ivtv_get_input(itv, itv->active_input, &vidin);
1451 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1452 IVTV_INFO("Video Input: %s\n", vidin.name);
1453 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1454 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1455 if (has_output) {
1456 struct v4l2_output vidout;
1457 struct v4l2_audioout audout;
1458 int mode = itv->output_mode;
1459 static const char * const output_modes[5] = {
1460 "None",
1461 "MPEG Streaming",
1462 "YUV Streaming",
1463 "YUV Frames",
1464 "Passthrough",
1465 };
1466 static const char * const audio_modes[5] = {
1467 "Stereo",
1468 "Left",
1469 "Right",
1470 "Mono",
1471 "Swapped"
1472 };
1473 static const char * const alpha_mode[4] = {
1474 "None",
1475 "Global",
1476 "Local",
1477 "Global and Local"
1478 };
1479 static const char * const pixel_format[16] = {
1480 "ARGB Indexed",
1481 "RGB 5:6:5",
1482 "ARGB 1:5:5:5",
1483 "ARGB 1:4:4:4",
1484 "ARGB 8:8:8:8",
1485 "5",
1486 "6",
1487 "7",
1488 "AYUV Indexed",
1489 "YUV 5:6:5",
1490 "AYUV 1:5:5:5",
1491 "AYUV 1:4:4:4",
1492 "AYUV 8:8:8:8",
1493 "13",
1494 "14",
1495 "15",
1496 };
1497
1498 ivtv_get_output(itv, itv->active_output, &vidout);
1499 ivtv_get_audio_output(itv, 0, &audout);
1500 IVTV_INFO("Video Output: %s\n", vidout.name);
1501 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1502 audio_modes[itv->audio_stereo_mode],
1503 audio_modes[itv->audio_bilingual_mode]);
1504 if (mode < 0 || mode > OUT_PASSTHROUGH)
1505 mode = OUT_NONE;
1506 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1507 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1508 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1509 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1510 data[0] & 1 ? "On" : "Off",
1511 alpha_mode[(data[0] >> 1) & 0x3],
1512 pixel_format[(data[0] >> 3) & 0xf]);
1513 }
1514 IVTV_INFO("Tuner: %s\n",
1515 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001516 cx2341x_log_status(&itv->params, itv->device.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001517 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1518 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1519 struct ivtv_stream *s = &itv->streams[i];
1520
1521 if (s->v4l2dev == NULL || s->buffers == 0)
1522 continue;
1523 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1524 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1525 (s->buffers * s->buf_size) / 1024, s->buffers);
1526 }
1527
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001528 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1529 (long long)itv->mpg_data_received,
1530 (long long)itv->vbi_data_inserted);
1531 IVTV_INFO("================== END STATUS CARD #%d ==================\n",
1532 itv->instance);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001533
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001534 return 0;
1535}
1536
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001537static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001538{
1539 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1540 struct ivtv *itv = id->itv;
1541 int nonblocking = filp->f_flags & O_NONBLOCK;
1542 struct ivtv_stream *s = &itv->streams[id->type];
1543
1544 switch (cmd) {
1545 case IVTV_IOC_DMA_FRAME: {
1546 struct ivtv_dma_frame *args = arg;
1547
1548 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1549 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1550 return -EINVAL;
1551 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1552 return -EINVAL;
1553 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1554 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001555 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001556 return -EBUSY;
1557 }
1558 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1559 ivtv_release_stream(s);
1560 return -EBUSY;
1561 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001562 /* Mark that this file handle started the UDMA_YUV mode */
1563 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001564 if (args->y_source == NULL)
1565 return 0;
1566 return ivtv_yuv_prep_frame(itv, args);
1567 }
1568
1569 case VIDEO_GET_PTS: {
1570 u32 data[CX2341X_MBOX_MAX_DATA];
1571 u64 *pts = arg;
1572
1573 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1574 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1575 *pts = s->dma_pts;
1576 break;
1577 }
1578 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1579 return -EINVAL;
1580
1581 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1582 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1583 (u64)itv->last_dec_timing[1];
1584 break;
1585 }
1586 *pts = 0;
1587 if (atomic_read(&itv->decoding)) {
1588 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1589 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1590 return -EIO;
1591 }
1592 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1593 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1594 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1595 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1596 }
1597 break;
1598 }
1599
1600 case VIDEO_GET_FRAME_COUNT: {
1601 u32 data[CX2341X_MBOX_MAX_DATA];
1602 u64 *frame = arg;
1603
1604 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1605 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1606 *frame = 0;
1607 break;
1608 }
1609 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1610 return -EINVAL;
1611
1612 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1613 *frame = itv->last_dec_timing[0];
1614 break;
1615 }
1616 *frame = 0;
1617 if (atomic_read(&itv->decoding)) {
1618 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1619 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1620 return -EIO;
1621 }
1622 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1623 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1624 *frame = data[0];
1625 }
1626 break;
1627 }
1628
1629 case VIDEO_PLAY: {
1630 struct video_command vc;
1631
1632 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1633 memset(&vc, 0, sizeof(vc));
1634 vc.cmd = VIDEO_CMD_PLAY;
1635 return ivtv_video_command(itv, id, &vc, 0);
1636 }
1637
1638 case VIDEO_STOP: {
1639 struct video_command vc;
1640
1641 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1642 memset(&vc, 0, sizeof(vc));
1643 vc.cmd = VIDEO_CMD_STOP;
1644 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1645 return ivtv_video_command(itv, id, &vc, 0);
1646 }
1647
1648 case VIDEO_FREEZE: {
1649 struct video_command vc;
1650
1651 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1652 memset(&vc, 0, sizeof(vc));
1653 vc.cmd = VIDEO_CMD_FREEZE;
1654 return ivtv_video_command(itv, id, &vc, 0);
1655 }
1656
1657 case VIDEO_CONTINUE: {
1658 struct video_command vc;
1659
1660 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1661 memset(&vc, 0, sizeof(vc));
1662 vc.cmd = VIDEO_CMD_CONTINUE;
1663 return ivtv_video_command(itv, id, &vc, 0);
1664 }
1665
1666 case VIDEO_COMMAND:
1667 case VIDEO_TRY_COMMAND: {
1668 struct video_command *vc = arg;
1669 int try = (cmd == VIDEO_TRY_COMMAND);
1670
1671 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001672 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001673 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001674 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001675 return ivtv_video_command(itv, id, vc, try);
1676 }
1677
1678 case VIDEO_GET_EVENT: {
1679 struct video_event *ev = arg;
1680 DEFINE_WAIT(wait);
1681
1682 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1683 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1684 return -EINVAL;
1685 memset(ev, 0, sizeof(*ev));
1686 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1687
1688 while (1) {
1689 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1690 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1691 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1692 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001693 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1694 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1695 if (itv->output_mode == OUT_UDMA_YUV &&
1696 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1697 IVTV_YUV_MODE_PROGRESSIVE) {
1698 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1699 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001700 }
1701 if (ev->type)
1702 return 0;
1703 if (nonblocking)
1704 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001705 /* Wait for event. Note that serialize_lock is locked,
1706 so to allow other processes to access the driver while
1707 we are waiting unlock first and later lock again. */
1708 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001709 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1710 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1711 schedule();
1712 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001713 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001714 if (signal_pending(current)) {
1715 /* return if a signal was received */
1716 IVTV_DEBUG_INFO("User stopped wait for event\n");
1717 return -EINTR;
1718 }
1719 }
1720 break;
1721 }
1722
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001723 default:
1724 return -EINVAL;
1725 }
1726 return 0;
1727}
1728
Hans Verkuil069b7472008-12-30 07:04:34 -03001729static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001730{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001731 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001732
Hans Verkuild46c17d2007-03-10 17:59:15 -03001733 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001734 case VIDIOC_INT_S_AUDIO_ROUTING: {
1735 struct v4l2_routing *route = arg;
1736
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001737 ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, route);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001738 break;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001739 }
1740
Hans Verkuil3f038d82008-05-29 16:43:54 -03001741 case VIDIOC_INT_RESET: {
1742 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001743
Hans Verkuil3f038d82008-05-29 16:43:54 -03001744 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1745 ivtv_reset_ir_gpio(itv);
1746 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001747 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001748 break;
1749 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001750
Hans Verkuilac9575f2009-02-14 19:58:33 -03001751 case IVTV_IOC_DMA_FRAME:
1752 case VIDEO_GET_PTS:
1753 case VIDEO_GET_FRAME_COUNT:
1754 case VIDEO_GET_EVENT:
1755 case VIDEO_PLAY:
1756 case VIDEO_STOP:
1757 case VIDEO_FREEZE:
1758 case VIDEO_CONTINUE:
1759 case VIDEO_COMMAND:
1760 case VIDEO_TRY_COMMAND:
1761 return ivtv_decoder_ioctls(file, cmd, (void *)arg);
1762
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001763 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -03001764 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001765 }
1766 return 0;
1767}
1768
Hans Verkuil09882f02008-10-18 13:42:24 -03001769static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
Hans Verkuilbaa40722007-08-19 07:10:55 -03001770 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001771{
Hans Verkuil37f89f92008-06-22 11:57:31 -03001772 struct video_device *vfd = video_devdata(filp);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001773 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
Hans Verkuil09882f02008-10-18 13:42:24 -03001774 long ret;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001775
1776 /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001777 switch (cmd) {
1778 case VIDEO_SELECT_SOURCE:
1779 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1780 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1781 return -EINVAL;
1782 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1783
1784 case AUDIO_SET_MUTE:
1785 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1786 itv->speed_mute_audio = arg;
1787 return 0;
1788
1789 case AUDIO_CHANNEL_SELECT:
1790 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1791 if (arg > AUDIO_STEREO_SWAPPED)
1792 return -EINVAL;
1793 itv->audio_stereo_mode = arg;
1794 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1795 return 0;
1796
1797 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1798 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1799 if (arg > AUDIO_STEREO_SWAPPED)
1800 return -EINVAL;
1801 itv->audio_bilingual_mode = arg;
1802 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1803 return 0;
1804
1805 default:
1806 break;
1807 }
Hans Verkuil3f038d82008-05-29 16:43:54 -03001808
1809 /* check priority */
1810 switch (cmd) {
1811 case VIDIOC_S_CTRL:
1812 case VIDIOC_S_STD:
1813 case VIDIOC_S_INPUT:
1814 case VIDIOC_S_OUTPUT:
1815 case VIDIOC_S_TUNER:
1816 case VIDIOC_S_FREQUENCY:
1817 case VIDIOC_S_FMT:
1818 case VIDIOC_S_CROP:
1819 case VIDIOC_S_AUDIO:
1820 case VIDIOC_S_AUDOUT:
1821 case VIDIOC_S_EXT_CTRLS:
1822 case VIDIOC_S_FBUF:
1823 case VIDIOC_OVERLAY:
1824 ret = v4l2_prio_check(&itv->prio, &id->prio);
1825 if (ret)
1826 return ret;
1827 }
1828
Hans Verkuil37f89f92008-06-22 11:57:31 -03001829 if (ivtv_debug & IVTV_DBGFLG_IOCTL)
1830 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Hans Verkuilbec43662008-12-30 06:58:20 -03001831 ret = video_ioctl2(filp, cmd, arg);
Hans Verkuil37f89f92008-06-22 11:57:31 -03001832 vfd->debug = 0;
1833 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001834}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001835
Hans Verkuil09882f02008-10-18 13:42:24 -03001836long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Hans Verkuilbaa40722007-08-19 07:10:55 -03001837{
1838 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1839 struct ivtv *itv = id->itv;
Hans Verkuil09882f02008-10-18 13:42:24 -03001840 long res;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001841
1842 mutex_lock(&itv->serialize_lock);
Hans Verkuil09882f02008-10-18 13:42:24 -03001843 res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001844 mutex_unlock(&itv->serialize_lock);
1845 return res;
1846}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001847
Hans Verkuila3998102008-07-21 02:57:38 -03001848static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1849 .vidioc_querycap = ivtv_querycap,
1850 .vidioc_g_priority = ivtv_g_priority,
1851 .vidioc_s_priority = ivtv_s_priority,
1852 .vidioc_s_audio = ivtv_s_audio,
1853 .vidioc_g_audio = ivtv_g_audio,
1854 .vidioc_enumaudio = ivtv_enumaudio,
1855 .vidioc_s_audout = ivtv_s_audout,
1856 .vidioc_g_audout = ivtv_g_audout,
1857 .vidioc_enum_input = ivtv_enum_input,
1858 .vidioc_enum_output = ivtv_enum_output,
1859 .vidioc_enumaudout = ivtv_enumaudout,
1860 .vidioc_cropcap = ivtv_cropcap,
1861 .vidioc_s_crop = ivtv_s_crop,
1862 .vidioc_g_crop = ivtv_g_crop,
1863 .vidioc_g_input = ivtv_g_input,
1864 .vidioc_s_input = ivtv_s_input,
1865 .vidioc_g_output = ivtv_g_output,
1866 .vidioc_s_output = ivtv_s_output,
1867 .vidioc_g_frequency = ivtv_g_frequency,
1868 .vidioc_s_frequency = ivtv_s_frequency,
1869 .vidioc_s_tuner = ivtv_s_tuner,
1870 .vidioc_g_tuner = ivtv_g_tuner,
1871 .vidioc_g_enc_index = ivtv_g_enc_index,
1872 .vidioc_g_fbuf = ivtv_g_fbuf,
1873 .vidioc_s_fbuf = ivtv_s_fbuf,
1874 .vidioc_g_std = ivtv_g_std,
1875 .vidioc_s_std = ivtv_s_std,
1876 .vidioc_overlay = ivtv_overlay,
1877 .vidioc_log_status = ivtv_log_status,
1878 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1879 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1880 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
1881 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1882 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1883 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1884 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1885 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1886 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1887 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1888 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1889 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1890 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1891 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1892 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1893 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1894 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1895 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1896 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1897 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1898 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1899 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1900 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1901 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1902#ifdef CONFIG_VIDEO_ADV_DEBUG
1903 .vidioc_g_register = ivtv_g_register,
1904 .vidioc_s_register = ivtv_s_register,
1905#endif
1906 .vidioc_default = ivtv_default,
1907 .vidioc_queryctrl = ivtv_queryctrl,
1908 .vidioc_querymenu = ivtv_querymenu,
1909 .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls,
1910 .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls,
1911 .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls,
1912};
1913
Hans Verkuil3f038d82008-05-29 16:43:54 -03001914void ivtv_set_funcs(struct video_device *vdev)
1915{
Hans Verkuila3998102008-07-21 02:57:38 -03001916 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001917}