blob: a6cd02460e75709501188c29cab5c71a74de54ac [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 Verkuil67ec09f2008-11-29 19:38:23 -0300396 v4l2_subdev_call(itv->sd_video, video, s_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
677static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident *chip)
678{
679 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
680
681 chip->ident = V4L2_IDENT_NONE;
682 chip->revision = 0;
683 if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
684 if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
685 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
686 return 0;
687 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300688 if (chip->match_type != V4L2_CHIP_MATCH_I2C_DRIVER &&
689 chip->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
690 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{
698 struct v4l2_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 Verkuil36ecd492008-06-25 06:00:17 -0300713 if (cmd == VIDIOC_DBG_G_REGISTER)
714 regs->val = readl(regs->reg + reg_start);
715 else
716 writel(regs->val, regs->reg + reg_start);
Hans Verkuil36ecd492008-06-25 06:00:17 -0300717 return 0;
718}
719
Hans Verkuil3f038d82008-05-29 16:43:54 -0300720static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg)
721{
722 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
723
724 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
725 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300726 /* TODO: subdev errors should not be ignored, this should become a
727 subdev helper function. */
728 ivtv_call_all(itv, core, g_register, reg);
729 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300730}
731
732static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg)
733{
734 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
735
736 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
737 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300738 /* TODO: subdev errors should not be ignored, this should become a
739 subdev helper function. */
740 ivtv_call_all(itv, core, s_register, reg);
741 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300742}
Hans Verkuil36ecd492008-06-25 06:00:17 -0300743#endif
Hans Verkuil3f038d82008-05-29 16:43:54 -0300744
745static int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
746{
747 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
748
749 *p = v4l2_prio_max(&itv->prio);
750
751 return 0;
752}
753
754static int ivtv_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
755{
756 struct ivtv_open_id *id = fh;
757 struct ivtv *itv = id->itv;
758
759 return v4l2_prio_change(&itv->prio, &id->prio, prio);
760}
761
762static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
763{
764 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
765
Hans Verkuil3f038d82008-05-29 16:43:54 -0300766 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
767 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
Hans Verkuil741e1f32008-09-08 16:59:02 -0300768 snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev));
Hans Verkuil3f038d82008-05-29 16:43:54 -0300769 vcap->version = IVTV_DRIVER_VERSION; /* version */
770 vcap->capabilities = itv->v4l2_cap; /* capabilities */
Hans Verkuil3f038d82008-05-29 16:43:54 -0300771 return 0;
772}
773
774static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
775{
776 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
777
778 return ivtv_get_audio_input(itv, vin->index, vin);
779}
780
781static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
782{
783 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
784
785 vin->index = itv->audio_input;
786 return ivtv_get_audio_input(itv, vin->index, vin);
787}
788
789static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
790{
791 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
792
793 if (vout->index >= itv->nof_audio_inputs)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300794 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300795
796 itv->audio_input = vout->index;
797 ivtv_audio_set_io(itv);
798
799 return 0;
800}
801
802static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
803{
804 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
805
806 /* set it to defaults from our table */
807 return ivtv_get_audio_output(itv, vin->index, vin);
808}
809
810static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
811{
812 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
813
814 vin->index = 0;
815 return ivtv_get_audio_output(itv, vin->index, vin);
816}
817
818static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
819{
820 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
821
822 return ivtv_get_audio_output(itv, vout->index, vout);
823}
824
825static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
826{
827 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
828
829 /* set it to defaults from our table */
830 return ivtv_get_input(itv, vin->index, vin);
831}
832
833static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
834{
835 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
836
837 return ivtv_get_output(itv, vout->index, vout);
838}
839
840static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
841{
842 struct ivtv_open_id *id = fh;
843 struct ivtv *itv = id->itv;
844 struct yuv_playback_info *yi = &itv->yuv_info;
845 int streamtype;
846
847 streamtype = id->type;
848
849 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
850 return -EINVAL;
851 cropcap->bounds.top = cropcap->bounds.left = 0;
852 cropcap->bounds.width = 720;
853 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
854 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
855 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
856 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
857 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
858 if (yi->track_osd) {
859 cropcap->bounds.width = yi->osd_full_w;
860 cropcap->bounds.height = yi->osd_full_h;
861 } else {
862 cropcap->bounds.width = 720;
863 cropcap->bounds.height =
864 itv->is_out_50hz ? 576 : 480;
865 }
866 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
867 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
868 } else {
869 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
870 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
871 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
872 }
873 cropcap->defrect = cropcap->bounds;
874 return 0;
875}
876
877static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
878{
879 struct ivtv_open_id *id = fh;
880 struct ivtv *itv = id->itv;
881 struct yuv_playback_info *yi = &itv->yuv_info;
882 int streamtype;
883
884 streamtype = id->type;
885
Hans Verkuil3f038d82008-05-29 16:43:54 -0300886 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
887 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
888 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
889 yi->main_rect = crop->c;
890 return 0;
891 } else {
892 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
893 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
894 itv->main_rect = crop->c;
895 return 0;
896 }
897 }
898 return -EINVAL;
899 }
900 return -EINVAL;
901}
902
903static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
904{
905 struct ivtv_open_id *id = fh;
906 struct ivtv *itv = id->itv;
907 struct yuv_playback_info *yi = &itv->yuv_info;
908 int streamtype;
909
910 streamtype = id->type;
911
912 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
913 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
914 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
915 crop->c = yi->main_rect;
916 else
917 crop->c = itv->main_rect;
918 return 0;
919 }
920 return -EINVAL;
921}
922
923static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
924{
925 static struct v4l2_fmtdesc formats[] = {
926 { 0, 0, 0,
927 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
928 { 0, 0, 0, 0 }
929 },
930 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
931 "MPEG", V4L2_PIX_FMT_MPEG,
932 { 0, 0, 0, 0 }
933 }
934 };
935 enum v4l2_buf_type type = fmt->type;
936
937 if (fmt->index > 1)
938 return -EINVAL;
939
940 *fmt = formats[fmt->index];
941 fmt->type = type;
942 return 0;
943}
944
945static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
946{
947 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
948
949 static struct v4l2_fmtdesc formats[] = {
950 { 0, 0, 0,
951 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
952 { 0, 0, 0, 0 }
953 },
954 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
955 "MPEG", V4L2_PIX_FMT_MPEG,
956 { 0, 0, 0, 0 }
957 }
958 };
959 enum v4l2_buf_type type = fmt->type;
960
961 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
962 return -EINVAL;
963
964 if (fmt->index > 1)
965 return -EINVAL;
966
967 *fmt = formats[fmt->index];
968 fmt->type = type;
969
970 return 0;
971}
972
973static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
974{
975 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
976
977 *i = itv->active_input;
978
979 return 0;
980}
981
982int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
983{
984 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
985
986 if (inp < 0 || inp >= itv->nof_inputs)
987 return -EINVAL;
988
989 if (inp == itv->active_input) {
990 IVTV_DEBUG_INFO("Input unchanged\n");
991 return 0;
992 }
993
994 if (atomic_read(&itv->capturing) > 0) {
995 return -EBUSY;
996 }
997
998 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
999 itv->active_input, inp);
1000
1001 itv->active_input = inp;
1002 /* Set the audio input to whatever is appropriate for the
1003 input type. */
1004 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1005
1006 /* prevent others from messing with the streams until
1007 we're finished changing inputs. */
1008 ivtv_mute(itv);
1009 ivtv_video_set_io(itv);
1010 ivtv_audio_set_io(itv);
1011 ivtv_unmute(itv);
1012
1013 return 0;
1014}
1015
1016static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1017{
1018 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1019
1020 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1021 return -EINVAL;
1022
1023 *i = itv->active_output;
1024
1025 return 0;
1026}
1027
1028static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1029{
1030 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1031 struct v4l2_routing route;
1032
1033 if (outp >= itv->card->nof_outputs)
1034 return -EINVAL;
1035
1036 if (outp == itv->active_output) {
1037 IVTV_DEBUG_INFO("Output unchanged\n");
1038 return 0;
1039 }
1040 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1041 itv->active_output, outp);
1042
1043 itv->active_output = outp;
1044 route.input = SAA7127_INPUT_TYPE_NORMAL;
1045 route.output = itv->card->video_outputs[outp].video_output;
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001046 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, &route);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001047
1048 return 0;
1049}
1050
1051static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1052{
1053 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1054
1055 if (vf->tuner != 0)
1056 return -EINVAL;
1057
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001058 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001059 return 0;
1060}
1061
1062int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1063{
1064 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1065
1066 if (vf->tuner != 0)
1067 return -EINVAL;
1068
1069 ivtv_mute(itv);
1070 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001071 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001072 ivtv_unmute(itv);
1073 return 0;
1074}
1075
1076static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1077{
1078 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1079
1080 *std = itv->std;
1081 return 0;
1082}
1083
1084int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1085{
1086 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1087 struct yuv_playback_info *yi = &itv->yuv_info;
1088
1089 if ((*std & V4L2_STD_ALL) == 0)
1090 return -EINVAL;
1091
1092 if (*std == itv->std)
1093 return 0;
1094
1095 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1096 atomic_read(&itv->capturing) > 0 ||
1097 atomic_read(&itv->decoding) > 0) {
1098 /* Switching standard would turn off the radio or mess
1099 with already running streams, prevent that by
1100 returning EBUSY. */
1101 return -EBUSY;
1102 }
1103
1104 itv->std = *std;
1105 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1106 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1107 itv->params.width = 720;
1108 itv->params.height = itv->is_50hz ? 576 : 480;
1109 itv->vbi.count = itv->is_50hz ? 18 : 12;
1110 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1111 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1112
1113 if (itv->hw_flags & IVTV_HW_CX25840)
1114 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1115
1116 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
1117
1118 /* Tuner */
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001119 ivtv_call_all(itv, tuner, s_std, itv->std);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001120
1121 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1122 /* set display standard */
1123 itv->std_out = *std;
1124 itv->is_out_60hz = itv->is_60hz;
1125 itv->is_out_50hz = itv->is_50hz;
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001126 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001127 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1128 itv->main_rect.left = itv->main_rect.top = 0;
1129 itv->main_rect.width = 720;
1130 itv->main_rect.height = itv->params.height;
1131 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1132 720, itv->main_rect.height, 0, 0);
1133 yi->main_rect = itv->main_rect;
1134 if (!itv->osd_info) {
1135 yi->osd_full_w = 720;
1136 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1137 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001138 }
1139 return 0;
1140}
1141
Hans Verkuil3f038d82008-05-29 16:43:54 -03001142static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001143{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001144 struct ivtv_open_id *id = fh;
1145 struct ivtv *itv = id->itv;
1146
1147 if (vt->index != 0)
1148 return -EINVAL;
1149
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001150 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001151
1152 return 0;
1153}
1154
1155static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1156{
1157 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1158
1159 if (vt->index != 0)
1160 return -EINVAL;
1161
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001162 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001163
1164 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1165 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
1166 vt->type = V4L2_TUNER_RADIO;
1167 } else {
1168 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
1169 vt->type = V4L2_TUNER_ANALOG_TV;
1170 }
1171
1172 return 0;
1173}
1174
1175static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1176{
1177 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1178 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1179 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001180
Hans Verkuil79afcb12008-06-21 09:02:36 -03001181 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001182 for (f = 0; f < 2; f++) {
1183 for (l = 0; l < 24; l++) {
1184 if (valid_service_line(f, l, itv->is_50hz))
1185 cap->service_lines[f][l] = set;
1186 }
1187 }
1188 return 0;
1189 }
Hans Verkuil79afcb12008-06-21 09:02:36 -03001190 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001191 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1192 return -EINVAL;
1193 if (itv->is_60hz) {
1194 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1195 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1196 } else {
1197 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1198 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1199 }
1200 return 0;
1201 }
1202 return -EINVAL;
1203}
1204
1205static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1206{
1207 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1208 struct v4l2_enc_idx_entry *e = idx->entry;
1209 int entries;
1210 int i;
1211
1212 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1213 IVTV_MAX_PGM_INDEX;
1214 if (entries > V4L2_ENC_IDX_ENTRIES)
1215 entries = V4L2_ENC_IDX_ENTRIES;
1216 idx->entries = 0;
1217 for (i = 0; i < entries; i++) {
1218 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1219 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1220 idx->entries++;
1221 e++;
1222 }
1223 }
1224 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1225 return 0;
1226}
1227
1228static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1229{
1230 struct ivtv_open_id *id = fh;
1231 struct ivtv *itv = id->itv;
1232
Hans Verkuil3f038d82008-05-29 16:43:54 -03001233
1234 switch (enc->cmd) {
1235 case V4L2_ENC_CMD_START:
1236 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1237 enc->flags = 0;
1238 return ivtv_start_capture(id);
1239
1240 case V4L2_ENC_CMD_STOP:
1241 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1242 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1243 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1244 return 0;
1245
1246 case V4L2_ENC_CMD_PAUSE:
1247 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1248 enc->flags = 0;
1249
1250 if (!atomic_read(&itv->capturing))
1251 return -EPERM;
1252 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1253 return 0;
1254
1255 ivtv_mute(itv);
1256 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1257 break;
1258
1259 case V4L2_ENC_CMD_RESUME:
1260 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1261 enc->flags = 0;
1262
1263 if (!atomic_read(&itv->capturing))
1264 return -EPERM;
1265
1266 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1267 return 0;
1268
1269 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1270 ivtv_unmute(itv);
1271 break;
1272 default:
1273 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1274 return -EINVAL;
1275 }
1276
1277 return 0;
1278}
1279
1280static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1281{
1282 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1283
Hans Verkuil3f038d82008-05-29 16:43:54 -03001284 switch (enc->cmd) {
1285 case V4L2_ENC_CMD_START:
1286 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1287 enc->flags = 0;
1288 return 0;
1289
1290 case V4L2_ENC_CMD_STOP:
1291 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1292 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1293 return 0;
1294
1295 case V4L2_ENC_CMD_PAUSE:
1296 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1297 enc->flags = 0;
1298 return 0;
1299
1300 case V4L2_ENC_CMD_RESUME:
1301 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1302 enc->flags = 0;
1303 return 0;
1304 default:
1305 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1306 return -EINVAL;
1307 }
1308}
1309
1310static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1311{
1312 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001313 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001314 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001315
Hans Verkuil3f038d82008-05-29 16:43:54 -03001316 int pixfmt;
1317 static u32 pixel_format[16] = {
1318 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1319 V4L2_PIX_FMT_RGB565,
1320 V4L2_PIX_FMT_RGB555,
1321 V4L2_PIX_FMT_RGB444,
1322 V4L2_PIX_FMT_RGB32,
1323 0,
1324 0,
1325 0,
1326 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1327 V4L2_PIX_FMT_YUV565,
1328 V4L2_PIX_FMT_YUV555,
1329 V4L2_PIX_FMT_YUV444,
1330 V4L2_PIX_FMT_YUV32,
1331 0,
1332 0,
1333 0,
1334 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001335
Hans Verkuil3f038d82008-05-29 16:43:54 -03001336 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1337 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001338 if (!itv->osd_video_pbase)
1339 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001340
Hans Verkuil3f038d82008-05-29 16:43:54 -03001341 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1342 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001343
Hans Verkuil3f038d82008-05-29 16:43:54 -03001344 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1345 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1346 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001347
Hans Verkuil3f038d82008-05-29 16:43:54 -03001348 fb->fmt.pixelformat = pixel_format[pixfmt];
1349 fb->fmt.width = itv->osd_rect.width;
1350 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001351 fb->fmt.field = V4L2_FIELD_INTERLACED;
1352 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001353 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1354 fb->fmt.field = V4L2_FIELD_INTERLACED;
1355 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001356 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1357 fb->fmt.bytesperline *= 2;
1358 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1359 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1360 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001361 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001362 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001363 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001364
Hans Verkuil3f038d82008-05-29 16:43:54 -03001365 if (itv->osd_chroma_key_state)
1366 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001367
Hans Verkuil3f038d82008-05-29 16:43:54 -03001368 if (itv->osd_global_alpha_state)
1369 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001370
Ian Armstrongec9faa12008-10-06 03:06:08 -03001371 if (yi->track_osd)
1372 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1373
Hans Verkuil3f038d82008-05-29 16:43:54 -03001374 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001375
Hans Verkuil3f038d82008-05-29 16:43:54 -03001376 /* no local alpha for RGB565 or unknown formats */
1377 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001378 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001379
Hans Verkuil3f038d82008-05-29 16:43:54 -03001380 /* 16-bit formats have inverted local alpha */
1381 if (pixfmt == 2 || pixfmt == 3)
1382 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1383 else
1384 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001385
Hans Verkuil3f038d82008-05-29 16:43:54 -03001386 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001387 /* 16-bit formats have inverted local alpha */
1388 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001389 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001390 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001391 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001392 }
1393
Hans Verkuil3f038d82008-05-29 16:43:54 -03001394 return 0;
1395}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001396
Hans Verkuil3f038d82008-05-29 16:43:54 -03001397static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1398{
1399 struct ivtv_open_id *id = fh;
1400 struct ivtv *itv = id->itv;
1401 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001402
Hans Verkuil3f038d82008-05-29 16:43:54 -03001403 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001404 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001405 if (!itv->osd_video_pbase)
1406 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001407
1408 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1409 itv->osd_local_alpha_state =
1410 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1411 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1412 ivtv_set_osd_alpha(itv);
1413 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001414 return ivtv_g_fbuf(file, fh, fb);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001415}
1416
1417static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1418{
1419 struct ivtv_open_id *id = fh;
1420 struct ivtv *itv = id->itv;
1421
1422 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1423 return -EINVAL;
1424
1425 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1426
1427 return 0;
1428}
1429
1430static int ivtv_log_status(struct file *file, void *fh)
1431{
1432 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1433 u32 data[CX2341X_MBOX_MAX_DATA];
1434
1435 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1436 struct v4l2_input vidin;
1437 struct v4l2_audio audin;
1438 int i;
1439
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001440 IVTV_INFO("================= START STATUS CARD #%d =================\n",
1441 itv->instance);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001442 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1443 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1444 struct tveeprom tv;
1445
1446 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001447 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001448 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001449 ivtv_get_input(itv, itv->active_input, &vidin);
1450 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1451 IVTV_INFO("Video Input: %s\n", vidin.name);
1452 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1453 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1454 if (has_output) {
1455 struct v4l2_output vidout;
1456 struct v4l2_audioout audout;
1457 int mode = itv->output_mode;
1458 static const char * const output_modes[5] = {
1459 "None",
1460 "MPEG Streaming",
1461 "YUV Streaming",
1462 "YUV Frames",
1463 "Passthrough",
1464 };
1465 static const char * const audio_modes[5] = {
1466 "Stereo",
1467 "Left",
1468 "Right",
1469 "Mono",
1470 "Swapped"
1471 };
1472 static const char * const alpha_mode[4] = {
1473 "None",
1474 "Global",
1475 "Local",
1476 "Global and Local"
1477 };
1478 static const char * const pixel_format[16] = {
1479 "ARGB Indexed",
1480 "RGB 5:6:5",
1481 "ARGB 1:5:5:5",
1482 "ARGB 1:4:4:4",
1483 "ARGB 8:8:8:8",
1484 "5",
1485 "6",
1486 "7",
1487 "AYUV Indexed",
1488 "YUV 5:6:5",
1489 "AYUV 1:5:5:5",
1490 "AYUV 1:4:4:4",
1491 "AYUV 8:8:8:8",
1492 "13",
1493 "14",
1494 "15",
1495 };
1496
1497 ivtv_get_output(itv, itv->active_output, &vidout);
1498 ivtv_get_audio_output(itv, 0, &audout);
1499 IVTV_INFO("Video Output: %s\n", vidout.name);
1500 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1501 audio_modes[itv->audio_stereo_mode],
1502 audio_modes[itv->audio_bilingual_mode]);
1503 if (mode < 0 || mode > OUT_PASSTHROUGH)
1504 mode = OUT_NONE;
1505 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1506 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1507 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1508 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1509 data[0] & 1 ? "On" : "Off",
1510 alpha_mode[(data[0] >> 1) & 0x3],
1511 pixel_format[(data[0] >> 3) & 0xf]);
1512 }
1513 IVTV_INFO("Tuner: %s\n",
1514 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001515 cx2341x_log_status(&itv->params, itv->device.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001516 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1517 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1518 struct ivtv_stream *s = &itv->streams[i];
1519
1520 if (s->v4l2dev == NULL || s->buffers == 0)
1521 continue;
1522 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1523 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1524 (s->buffers * s->buf_size) / 1024, s->buffers);
1525 }
1526
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001527 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1528 (long long)itv->mpg_data_received,
1529 (long long)itv->vbi_data_inserted);
1530 IVTV_INFO("================== END STATUS CARD #%d ==================\n",
1531 itv->instance);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001532
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001533 return 0;
1534}
1535
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001536static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001537{
1538 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1539 struct ivtv *itv = id->itv;
1540 int nonblocking = filp->f_flags & O_NONBLOCK;
1541 struct ivtv_stream *s = &itv->streams[id->type];
1542
1543 switch (cmd) {
1544 case IVTV_IOC_DMA_FRAME: {
1545 struct ivtv_dma_frame *args = arg;
1546
1547 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1548 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1549 return -EINVAL;
1550 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1551 return -EINVAL;
1552 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1553 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001554 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001555 return -EBUSY;
1556 }
1557 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1558 ivtv_release_stream(s);
1559 return -EBUSY;
1560 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001561 /* Mark that this file handle started the UDMA_YUV mode */
1562 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001563 if (args->y_source == NULL)
1564 return 0;
1565 return ivtv_yuv_prep_frame(itv, args);
1566 }
1567
1568 case VIDEO_GET_PTS: {
1569 u32 data[CX2341X_MBOX_MAX_DATA];
1570 u64 *pts = arg;
1571
1572 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1573 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1574 *pts = s->dma_pts;
1575 break;
1576 }
1577 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1578 return -EINVAL;
1579
1580 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1581 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1582 (u64)itv->last_dec_timing[1];
1583 break;
1584 }
1585 *pts = 0;
1586 if (atomic_read(&itv->decoding)) {
1587 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1588 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1589 return -EIO;
1590 }
1591 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1592 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1593 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1594 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1595 }
1596 break;
1597 }
1598
1599 case VIDEO_GET_FRAME_COUNT: {
1600 u32 data[CX2341X_MBOX_MAX_DATA];
1601 u64 *frame = arg;
1602
1603 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1604 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1605 *frame = 0;
1606 break;
1607 }
1608 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1609 return -EINVAL;
1610
1611 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1612 *frame = itv->last_dec_timing[0];
1613 break;
1614 }
1615 *frame = 0;
1616 if (atomic_read(&itv->decoding)) {
1617 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1618 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1619 return -EIO;
1620 }
1621 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1622 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1623 *frame = data[0];
1624 }
1625 break;
1626 }
1627
1628 case VIDEO_PLAY: {
1629 struct video_command vc;
1630
1631 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1632 memset(&vc, 0, sizeof(vc));
1633 vc.cmd = VIDEO_CMD_PLAY;
1634 return ivtv_video_command(itv, id, &vc, 0);
1635 }
1636
1637 case VIDEO_STOP: {
1638 struct video_command vc;
1639
1640 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1641 memset(&vc, 0, sizeof(vc));
1642 vc.cmd = VIDEO_CMD_STOP;
1643 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1644 return ivtv_video_command(itv, id, &vc, 0);
1645 }
1646
1647 case VIDEO_FREEZE: {
1648 struct video_command vc;
1649
1650 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1651 memset(&vc, 0, sizeof(vc));
1652 vc.cmd = VIDEO_CMD_FREEZE;
1653 return ivtv_video_command(itv, id, &vc, 0);
1654 }
1655
1656 case VIDEO_CONTINUE: {
1657 struct video_command vc;
1658
1659 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1660 memset(&vc, 0, sizeof(vc));
1661 vc.cmd = VIDEO_CMD_CONTINUE;
1662 return ivtv_video_command(itv, id, &vc, 0);
1663 }
1664
1665 case VIDEO_COMMAND:
1666 case VIDEO_TRY_COMMAND: {
1667 struct video_command *vc = arg;
1668 int try = (cmd == VIDEO_TRY_COMMAND);
1669
1670 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001671 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001672 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001673 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001674 return ivtv_video_command(itv, id, vc, try);
1675 }
1676
1677 case VIDEO_GET_EVENT: {
1678 struct video_event *ev = arg;
1679 DEFINE_WAIT(wait);
1680
1681 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1682 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1683 return -EINVAL;
1684 memset(ev, 0, sizeof(*ev));
1685 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1686
1687 while (1) {
1688 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1689 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1690 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1691 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001692 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1693 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1694 if (itv->output_mode == OUT_UDMA_YUV &&
1695 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1696 IVTV_YUV_MODE_PROGRESSIVE) {
1697 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1698 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001699 }
1700 if (ev->type)
1701 return 0;
1702 if (nonblocking)
1703 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001704 /* Wait for event. Note that serialize_lock is locked,
1705 so to allow other processes to access the driver while
1706 we are waiting unlock first and later lock again. */
1707 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001708 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1709 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1710 schedule();
1711 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001712 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001713 if (signal_pending(current)) {
1714 /* return if a signal was received */
1715 IVTV_DEBUG_INFO("User stopped wait for event\n");
1716 return -EINTR;
1717 }
1718 }
1719 break;
1720 }
1721
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001722 default:
1723 return -EINVAL;
1724 }
1725 return 0;
1726}
1727
Hans Verkuil3f038d82008-05-29 16:43:54 -03001728static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001729{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001730 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001731
Hans Verkuild46c17d2007-03-10 17:59:15 -03001732 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001733 case VIDIOC_INT_S_AUDIO_ROUTING: {
1734 struct v4l2_routing *route = arg;
1735
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001736 ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, route);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001737 break;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001738 }
1739
Hans Verkuil3f038d82008-05-29 16:43:54 -03001740 case VIDIOC_INT_RESET: {
1741 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001742
Hans Verkuil3f038d82008-05-29 16:43:54 -03001743 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1744 ivtv_reset_ir_gpio(itv);
1745 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001746 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001747 break;
1748 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001749
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001750 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -03001751 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001752 }
1753 return 0;
1754}
1755
Hans Verkuil09882f02008-10-18 13:42:24 -03001756static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
Hans Verkuilbaa40722007-08-19 07:10:55 -03001757 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001758{
Hans Verkuil37f89f92008-06-22 11:57:31 -03001759 struct video_device *vfd = video_devdata(filp);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001760 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
Hans Verkuil09882f02008-10-18 13:42:24 -03001761 long ret;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001762
1763 /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001764 switch (cmd) {
1765 case VIDEO_SELECT_SOURCE:
1766 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1767 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1768 return -EINVAL;
1769 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1770
1771 case AUDIO_SET_MUTE:
1772 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1773 itv->speed_mute_audio = arg;
1774 return 0;
1775
1776 case AUDIO_CHANNEL_SELECT:
1777 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1778 if (arg > AUDIO_STEREO_SWAPPED)
1779 return -EINVAL;
1780 itv->audio_stereo_mode = arg;
1781 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1782 return 0;
1783
1784 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1785 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1786 if (arg > AUDIO_STEREO_SWAPPED)
1787 return -EINVAL;
1788 itv->audio_bilingual_mode = arg;
1789 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1790 return 0;
1791
Hans Verkuil3f038d82008-05-29 16:43:54 -03001792 case IVTV_IOC_DMA_FRAME:
1793 case VIDEO_GET_PTS:
1794 case VIDEO_GET_FRAME_COUNT:
1795 case VIDEO_GET_EVENT:
1796 case VIDEO_PLAY:
1797 case VIDEO_STOP:
1798 case VIDEO_FREEZE:
1799 case VIDEO_CONTINUE:
1800 case VIDEO_COMMAND:
1801 case VIDEO_TRY_COMMAND:
1802 return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
1803
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001804 default:
1805 break;
1806 }
Hans Verkuil3f038d82008-05-29 16:43:54 -03001807
1808 /* check priority */
1809 switch (cmd) {
1810 case VIDIOC_S_CTRL:
1811 case VIDIOC_S_STD:
1812 case VIDIOC_S_INPUT:
1813 case VIDIOC_S_OUTPUT:
1814 case VIDIOC_S_TUNER:
1815 case VIDIOC_S_FREQUENCY:
1816 case VIDIOC_S_FMT:
1817 case VIDIOC_S_CROP:
1818 case VIDIOC_S_AUDIO:
1819 case VIDIOC_S_AUDOUT:
1820 case VIDIOC_S_EXT_CTRLS:
1821 case VIDIOC_S_FBUF:
1822 case VIDIOC_OVERLAY:
1823 ret = v4l2_prio_check(&itv->prio, &id->prio);
1824 if (ret)
1825 return ret;
1826 }
1827
Hans Verkuil37f89f92008-06-22 11:57:31 -03001828 if (ivtv_debug & IVTV_DBGFLG_IOCTL)
1829 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Hans Verkuilbec43662008-12-30 06:58:20 -03001830 ret = video_ioctl2(filp, cmd, arg);
Hans Verkuil37f89f92008-06-22 11:57:31 -03001831 vfd->debug = 0;
1832 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001833}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001834
Hans Verkuil09882f02008-10-18 13:42:24 -03001835long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Hans Verkuilbaa40722007-08-19 07:10:55 -03001836{
1837 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1838 struct ivtv *itv = id->itv;
Hans Verkuil09882f02008-10-18 13:42:24 -03001839 long res;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001840
1841 mutex_lock(&itv->serialize_lock);
Hans Verkuil09882f02008-10-18 13:42:24 -03001842 res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001843 mutex_unlock(&itv->serialize_lock);
1844 return res;
1845}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001846
Hans Verkuila3998102008-07-21 02:57:38 -03001847static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1848 .vidioc_querycap = ivtv_querycap,
1849 .vidioc_g_priority = ivtv_g_priority,
1850 .vidioc_s_priority = ivtv_s_priority,
1851 .vidioc_s_audio = ivtv_s_audio,
1852 .vidioc_g_audio = ivtv_g_audio,
1853 .vidioc_enumaudio = ivtv_enumaudio,
1854 .vidioc_s_audout = ivtv_s_audout,
1855 .vidioc_g_audout = ivtv_g_audout,
1856 .vidioc_enum_input = ivtv_enum_input,
1857 .vidioc_enum_output = ivtv_enum_output,
1858 .vidioc_enumaudout = ivtv_enumaudout,
1859 .vidioc_cropcap = ivtv_cropcap,
1860 .vidioc_s_crop = ivtv_s_crop,
1861 .vidioc_g_crop = ivtv_g_crop,
1862 .vidioc_g_input = ivtv_g_input,
1863 .vidioc_s_input = ivtv_s_input,
1864 .vidioc_g_output = ivtv_g_output,
1865 .vidioc_s_output = ivtv_s_output,
1866 .vidioc_g_frequency = ivtv_g_frequency,
1867 .vidioc_s_frequency = ivtv_s_frequency,
1868 .vidioc_s_tuner = ivtv_s_tuner,
1869 .vidioc_g_tuner = ivtv_g_tuner,
1870 .vidioc_g_enc_index = ivtv_g_enc_index,
1871 .vidioc_g_fbuf = ivtv_g_fbuf,
1872 .vidioc_s_fbuf = ivtv_s_fbuf,
1873 .vidioc_g_std = ivtv_g_std,
1874 .vidioc_s_std = ivtv_s_std,
1875 .vidioc_overlay = ivtv_overlay,
1876 .vidioc_log_status = ivtv_log_status,
1877 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1878 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1879 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
1880 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1881 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1882 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1883 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1884 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1885 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1886 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1887 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1888 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1889 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1890 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1891 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1892 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1893 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1894 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1895 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1896 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1897 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1898 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1899 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1900 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1901#ifdef CONFIG_VIDEO_ADV_DEBUG
1902 .vidioc_g_register = ivtv_g_register,
1903 .vidioc_s_register = ivtv_s_register,
1904#endif
1905 .vidioc_default = ivtv_default,
1906 .vidioc_queryctrl = ivtv_queryctrl,
1907 .vidioc_querymenu = ivtv_querymenu,
1908 .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls,
1909 .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls,
1910 .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls,
1911};
1912
Hans Verkuil3f038d82008-05-29 16:43:54 -03001913void ivtv_set_funcs(struct video_device *vdev)
1914{
Hans Verkuila3998102008-07-21 02:57:38 -03001915 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001916}