blob: 208fb54842f2f4a91f8527f280e5023cd8780215 [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 Verkuil3f038d82008-05-29 16:43:54 -0300396 itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);
397 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;
584 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
585 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;
596 itv->video_dec_func(itv, VIDIOC_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 Verkuil1a0adaf2007-04-27 12:31:25 -0300614 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
615 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 }
688 if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
689 return ivtv_i2c_id(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip);
690 if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
691 return ivtv_call_i2c_client(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip);
692 return -EINVAL;
693}
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;
699 unsigned long flags;
Hans Verkuiladb65bc2008-06-25 06:32:44 -0300700 volatile u8 __iomem *reg_start;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300701
702 if (!capable(CAP_SYS_ADMIN))
703 return -EPERM;
704 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
705 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
706 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
707 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
708 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
709 else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
710 reg_start = itv->enc_mem;
711 else
712 return -EINVAL;
713
714 spin_lock_irqsave(&ivtv_cards_lock, flags);
715 if (cmd == VIDIOC_DBG_G_REGISTER)
716 regs->val = readl(regs->reg + reg_start);
717 else
718 writel(regs->val, regs->reg + reg_start);
719 spin_unlock_irqrestore(&ivtv_cards_lock, flags);
720 return 0;
721}
722
Hans Verkuil3f038d82008-05-29 16:43:54 -0300723static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg)
724{
725 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
726
727 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
728 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
729 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
730 return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg);
731 return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg);
732}
733
734static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg)
735{
736 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
737
738 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
739 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
740 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
741 return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);
742 return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);
743}
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
887 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
888 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
889 /* Should be replaced */
890 /* v4l_printk_ioctl(VIDIOC_S_CROP); */
891 }
892
893 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
894 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
895 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
896 yi->main_rect = crop->c;
897 return 0;
898 } else {
899 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
900 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
901 itv->main_rect = crop->c;
902 return 0;
903 }
904 }
905 return -EINVAL;
906 }
907 return -EINVAL;
908}
909
910static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
911{
912 struct ivtv_open_id *id = fh;
913 struct ivtv *itv = id->itv;
914 struct yuv_playback_info *yi = &itv->yuv_info;
915 int streamtype;
916
917 streamtype = id->type;
918
919 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
920 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
921 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
922 crop->c = yi->main_rect;
923 else
924 crop->c = itv->main_rect;
925 return 0;
926 }
927 return -EINVAL;
928}
929
930static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
931{
932 static struct v4l2_fmtdesc formats[] = {
933 { 0, 0, 0,
934 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
935 { 0, 0, 0, 0 }
936 },
937 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
938 "MPEG", V4L2_PIX_FMT_MPEG,
939 { 0, 0, 0, 0 }
940 }
941 };
942 enum v4l2_buf_type type = fmt->type;
943
944 if (fmt->index > 1)
945 return -EINVAL;
946
947 *fmt = formats[fmt->index];
948 fmt->type = type;
949 return 0;
950}
951
952static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
953{
954 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
955
956 static struct v4l2_fmtdesc formats[] = {
957 { 0, 0, 0,
958 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
959 { 0, 0, 0, 0 }
960 },
961 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
962 "MPEG", V4L2_PIX_FMT_MPEG,
963 { 0, 0, 0, 0 }
964 }
965 };
966 enum v4l2_buf_type type = fmt->type;
967
968 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
969 return -EINVAL;
970
971 if (fmt->index > 1)
972 return -EINVAL;
973
974 *fmt = formats[fmt->index];
975 fmt->type = type;
976
977 return 0;
978}
979
980static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
981{
982 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
983
984 *i = itv->active_input;
985
986 return 0;
987}
988
989int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
990{
991 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
992
993 if (inp < 0 || inp >= itv->nof_inputs)
994 return -EINVAL;
995
996 if (inp == itv->active_input) {
997 IVTV_DEBUG_INFO("Input unchanged\n");
998 return 0;
999 }
1000
1001 if (atomic_read(&itv->capturing) > 0) {
1002 return -EBUSY;
1003 }
1004
1005 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
1006 itv->active_input, inp);
1007
1008 itv->active_input = inp;
1009 /* Set the audio input to whatever is appropriate for the
1010 input type. */
1011 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1012
1013 /* prevent others from messing with the streams until
1014 we're finished changing inputs. */
1015 ivtv_mute(itv);
1016 ivtv_video_set_io(itv);
1017 ivtv_audio_set_io(itv);
1018 ivtv_unmute(itv);
1019
1020 return 0;
1021}
1022
1023static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1024{
1025 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1026
1027 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1028 return -EINVAL;
1029
1030 *i = itv->active_output;
1031
1032 return 0;
1033}
1034
1035static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1036{
1037 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1038 struct v4l2_routing route;
1039
1040 if (outp >= itv->card->nof_outputs)
1041 return -EINVAL;
1042
1043 if (outp == itv->active_output) {
1044 IVTV_DEBUG_INFO("Output unchanged\n");
1045 return 0;
1046 }
1047 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1048 itv->active_output, outp);
1049
1050 itv->active_output = outp;
1051 route.input = SAA7127_INPUT_TYPE_NORMAL;
1052 route.output = itv->card->video_outputs[outp].video_output;
1053 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
1054
1055 return 0;
1056}
1057
1058static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1059{
1060 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1061
1062 if (vf->tuner != 0)
1063 return -EINVAL;
1064
1065 ivtv_call_i2c_clients(itv, VIDIOC_G_FREQUENCY, vf);
1066 return 0;
1067}
1068
1069int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1070{
1071 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1072
1073 if (vf->tuner != 0)
1074 return -EINVAL;
1075
1076 ivtv_mute(itv);
1077 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
1078 ivtv_call_i2c_clients(itv, VIDIOC_S_FREQUENCY, vf);
1079 ivtv_unmute(itv);
1080 return 0;
1081}
1082
1083static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1084{
1085 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1086
1087 *std = itv->std;
1088 return 0;
1089}
1090
1091int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1092{
1093 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1094 struct yuv_playback_info *yi = &itv->yuv_info;
1095
1096 if ((*std & V4L2_STD_ALL) == 0)
1097 return -EINVAL;
1098
1099 if (*std == itv->std)
1100 return 0;
1101
1102 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1103 atomic_read(&itv->capturing) > 0 ||
1104 atomic_read(&itv->decoding) > 0) {
1105 /* Switching standard would turn off the radio or mess
1106 with already running streams, prevent that by
1107 returning EBUSY. */
1108 return -EBUSY;
1109 }
1110
1111 itv->std = *std;
1112 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1113 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1114 itv->params.width = 720;
1115 itv->params.height = itv->is_50hz ? 576 : 480;
1116 itv->vbi.count = itv->is_50hz ? 18 : 12;
1117 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1118 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1119
1120 if (itv->hw_flags & IVTV_HW_CX25840)
1121 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1122
1123 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
1124
1125 /* Tuner */
1126 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1127
1128 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1129 /* set display standard */
1130 itv->std_out = *std;
1131 itv->is_out_60hz = itv->is_60hz;
1132 itv->is_out_50hz = itv->is_50hz;
1133 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1134 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1135 itv->main_rect.left = itv->main_rect.top = 0;
1136 itv->main_rect.width = 720;
1137 itv->main_rect.height = itv->params.height;
1138 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1139 720, itv->main_rect.height, 0, 0);
1140 yi->main_rect = itv->main_rect;
1141 if (!itv->osd_info) {
1142 yi->osd_full_w = 720;
1143 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1144 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001145 }
1146 return 0;
1147}
1148
Hans Verkuil3f038d82008-05-29 16:43:54 -03001149static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001150{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001151 struct ivtv_open_id *id = fh;
1152 struct ivtv *itv = id->itv;
1153
1154 if (vt->index != 0)
1155 return -EINVAL;
1156
1157 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1158
1159 return 0;
1160}
1161
1162static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1163{
1164 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1165
1166 if (vt->index != 0)
1167 return -EINVAL;
1168
Hans Verkuil3f038d82008-05-29 16:43:54 -03001169 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1170
1171 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1172 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
1173 vt->type = V4L2_TUNER_RADIO;
1174 } else {
1175 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
1176 vt->type = V4L2_TUNER_ANALOG_TV;
1177 }
1178
1179 return 0;
1180}
1181
1182static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1183{
1184 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1185 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1186 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001187
Hans Verkuil79afcb12008-06-21 09:02:36 -03001188 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001189 for (f = 0; f < 2; f++) {
1190 for (l = 0; l < 24; l++) {
1191 if (valid_service_line(f, l, itv->is_50hz))
1192 cap->service_lines[f][l] = set;
1193 }
1194 }
1195 return 0;
1196 }
Hans Verkuil79afcb12008-06-21 09:02:36 -03001197 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001198 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1199 return -EINVAL;
1200 if (itv->is_60hz) {
1201 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1202 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1203 } else {
1204 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1205 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1206 }
1207 return 0;
1208 }
1209 return -EINVAL;
1210}
1211
1212static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1213{
1214 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1215 struct v4l2_enc_idx_entry *e = idx->entry;
1216 int entries;
1217 int i;
1218
1219 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1220 IVTV_MAX_PGM_INDEX;
1221 if (entries > V4L2_ENC_IDX_ENTRIES)
1222 entries = V4L2_ENC_IDX_ENTRIES;
1223 idx->entries = 0;
1224 for (i = 0; i < entries; i++) {
1225 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1226 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1227 idx->entries++;
1228 e++;
1229 }
1230 }
1231 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1232 return 0;
1233}
1234
1235static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1236{
1237 struct ivtv_open_id *id = fh;
1238 struct ivtv *itv = id->itv;
1239
Hans Verkuil3f038d82008-05-29 16:43:54 -03001240
1241 switch (enc->cmd) {
1242 case V4L2_ENC_CMD_START:
1243 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1244 enc->flags = 0;
1245 return ivtv_start_capture(id);
1246
1247 case V4L2_ENC_CMD_STOP:
1248 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1249 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1250 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1251 return 0;
1252
1253 case V4L2_ENC_CMD_PAUSE:
1254 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1255 enc->flags = 0;
1256
1257 if (!atomic_read(&itv->capturing))
1258 return -EPERM;
1259 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1260 return 0;
1261
1262 ivtv_mute(itv);
1263 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1264 break;
1265
1266 case V4L2_ENC_CMD_RESUME:
1267 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1268 enc->flags = 0;
1269
1270 if (!atomic_read(&itv->capturing))
1271 return -EPERM;
1272
1273 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1274 return 0;
1275
1276 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1277 ivtv_unmute(itv);
1278 break;
1279 default:
1280 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1281 return -EINVAL;
1282 }
1283
1284 return 0;
1285}
1286
1287static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1288{
1289 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1290
Hans Verkuil3f038d82008-05-29 16:43:54 -03001291 switch (enc->cmd) {
1292 case V4L2_ENC_CMD_START:
1293 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1294 enc->flags = 0;
1295 return 0;
1296
1297 case V4L2_ENC_CMD_STOP:
1298 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1299 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1300 return 0;
1301
1302 case V4L2_ENC_CMD_PAUSE:
1303 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1304 enc->flags = 0;
1305 return 0;
1306
1307 case V4L2_ENC_CMD_RESUME:
1308 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1309 enc->flags = 0;
1310 return 0;
1311 default:
1312 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1313 return -EINVAL;
1314 }
1315}
1316
1317static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1318{
1319 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001320 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001321 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001322
Hans Verkuil3f038d82008-05-29 16:43:54 -03001323 int pixfmt;
1324 static u32 pixel_format[16] = {
1325 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1326 V4L2_PIX_FMT_RGB565,
1327 V4L2_PIX_FMT_RGB555,
1328 V4L2_PIX_FMT_RGB444,
1329 V4L2_PIX_FMT_RGB32,
1330 0,
1331 0,
1332 0,
1333 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1334 V4L2_PIX_FMT_YUV565,
1335 V4L2_PIX_FMT_YUV555,
1336 V4L2_PIX_FMT_YUV444,
1337 V4L2_PIX_FMT_YUV32,
1338 0,
1339 0,
1340 0,
1341 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001342
Hans Verkuil3f038d82008-05-29 16:43:54 -03001343 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1344 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001345 if (!itv->osd_video_pbase)
1346 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001347
Hans Verkuil3f038d82008-05-29 16:43:54 -03001348 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1349 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001350
Hans Verkuil3f038d82008-05-29 16:43:54 -03001351 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1352 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1353 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001354
Hans Verkuil3f038d82008-05-29 16:43:54 -03001355 fb->fmt.pixelformat = pixel_format[pixfmt];
1356 fb->fmt.width = itv->osd_rect.width;
1357 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001358 fb->fmt.field = V4L2_FIELD_INTERLACED;
1359 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001360 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1361 fb->fmt.field = V4L2_FIELD_INTERLACED;
1362 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001363 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1364 fb->fmt.bytesperline *= 2;
1365 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1366 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1367 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001368 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001369 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001370 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001371
Hans Verkuil3f038d82008-05-29 16:43:54 -03001372 if (itv->osd_chroma_key_state)
1373 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001374
Hans Verkuil3f038d82008-05-29 16:43:54 -03001375 if (itv->osd_global_alpha_state)
1376 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001377
Ian Armstrongec9faa12008-10-06 03:06:08 -03001378 if (yi->track_osd)
1379 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1380
Hans Verkuil3f038d82008-05-29 16:43:54 -03001381 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001382
Hans Verkuil3f038d82008-05-29 16:43:54 -03001383 /* no local alpha for RGB565 or unknown formats */
1384 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001385 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001386
Hans Verkuil3f038d82008-05-29 16:43:54 -03001387 /* 16-bit formats have inverted local alpha */
1388 if (pixfmt == 2 || pixfmt == 3)
1389 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1390 else
1391 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001392
Hans Verkuil3f038d82008-05-29 16:43:54 -03001393 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001394 /* 16-bit formats have inverted local alpha */
1395 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001396 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001397 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001398 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001399 }
1400
Hans Verkuil3f038d82008-05-29 16:43:54 -03001401 return 0;
1402}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001403
Hans Verkuil3f038d82008-05-29 16:43:54 -03001404static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1405{
1406 struct ivtv_open_id *id = fh;
1407 struct ivtv *itv = id->itv;
1408 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001409
Hans Verkuil3f038d82008-05-29 16:43:54 -03001410 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001411 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001412 if (!itv->osd_video_pbase)
1413 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001414
1415 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1416 itv->osd_local_alpha_state =
1417 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1418 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1419 ivtv_set_osd_alpha(itv);
1420 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001421 return ivtv_g_fbuf(file, fh, fb);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001422}
1423
1424static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1425{
1426 struct ivtv_open_id *id = fh;
1427 struct ivtv *itv = id->itv;
1428
1429 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1430 return -EINVAL;
1431
1432 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1433
1434 return 0;
1435}
1436
1437static int ivtv_log_status(struct file *file, void *fh)
1438{
1439 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1440 u32 data[CX2341X_MBOX_MAX_DATA];
1441
1442 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1443 struct v4l2_input vidin;
1444 struct v4l2_audio audin;
1445 int i;
1446
1447 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
1448 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1449 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1450 struct tveeprom tv;
1451
1452 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001453 }
Hans Verkuil3f038d82008-05-29 16:43:54 -03001454 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1455 ivtv_get_input(itv, itv->active_input, &vidin);
1456 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1457 IVTV_INFO("Video Input: %s\n", vidin.name);
1458 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1459 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1460 if (has_output) {
1461 struct v4l2_output vidout;
1462 struct v4l2_audioout audout;
1463 int mode = itv->output_mode;
1464 static const char * const output_modes[5] = {
1465 "None",
1466 "MPEG Streaming",
1467 "YUV Streaming",
1468 "YUV Frames",
1469 "Passthrough",
1470 };
1471 static const char * const audio_modes[5] = {
1472 "Stereo",
1473 "Left",
1474 "Right",
1475 "Mono",
1476 "Swapped"
1477 };
1478 static const char * const alpha_mode[4] = {
1479 "None",
1480 "Global",
1481 "Local",
1482 "Global and Local"
1483 };
1484 static const char * const pixel_format[16] = {
1485 "ARGB Indexed",
1486 "RGB 5:6:5",
1487 "ARGB 1:5:5:5",
1488 "ARGB 1:4:4:4",
1489 "ARGB 8:8:8:8",
1490 "5",
1491 "6",
1492 "7",
1493 "AYUV Indexed",
1494 "YUV 5:6:5",
1495 "AYUV 1:5:5:5",
1496 "AYUV 1:4:4:4",
1497 "AYUV 8:8:8:8",
1498 "13",
1499 "14",
1500 "15",
1501 };
1502
1503 ivtv_get_output(itv, itv->active_output, &vidout);
1504 ivtv_get_audio_output(itv, 0, &audout);
1505 IVTV_INFO("Video Output: %s\n", vidout.name);
1506 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1507 audio_modes[itv->audio_stereo_mode],
1508 audio_modes[itv->audio_bilingual_mode]);
1509 if (mode < 0 || mode > OUT_PASSTHROUGH)
1510 mode = OUT_NONE;
1511 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1512 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1513 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1514 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1515 data[0] & 1 ? "On" : "Off",
1516 alpha_mode[(data[0] >> 1) & 0x3],
1517 pixel_format[(data[0] >> 3) & 0xf]);
1518 }
1519 IVTV_INFO("Tuner: %s\n",
1520 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1521 cx2341x_log_status(&itv->params, itv->name);
1522 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1523 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1524 struct ivtv_stream *s = &itv->streams[i];
1525
1526 if (s->v4l2dev == NULL || s->buffers == 0)
1527 continue;
1528 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1529 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1530 (s->buffers * s->buf_size) / 1024, s->buffers);
1531 }
1532
1533 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
1534 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1535
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001536 return 0;
1537}
1538
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001539static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001540{
1541 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1542 struct ivtv *itv = id->itv;
1543 int nonblocking = filp->f_flags & O_NONBLOCK;
1544 struct ivtv_stream *s = &itv->streams[id->type];
1545
1546 switch (cmd) {
1547 case IVTV_IOC_DMA_FRAME: {
1548 struct ivtv_dma_frame *args = arg;
1549
1550 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1551 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1552 return -EINVAL;
1553 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1554 return -EINVAL;
1555 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1556 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001557 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001558 return -EBUSY;
1559 }
1560 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1561 ivtv_release_stream(s);
1562 return -EBUSY;
1563 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001564 /* Mark that this file handle started the UDMA_YUV mode */
1565 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001566 if (args->y_source == NULL)
1567 return 0;
1568 return ivtv_yuv_prep_frame(itv, args);
1569 }
1570
1571 case VIDEO_GET_PTS: {
1572 u32 data[CX2341X_MBOX_MAX_DATA];
1573 u64 *pts = arg;
1574
1575 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1576 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1577 *pts = s->dma_pts;
1578 break;
1579 }
1580 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1581 return -EINVAL;
1582
1583 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1584 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1585 (u64)itv->last_dec_timing[1];
1586 break;
1587 }
1588 *pts = 0;
1589 if (atomic_read(&itv->decoding)) {
1590 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1591 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1592 return -EIO;
1593 }
1594 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1595 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1596 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1597 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1598 }
1599 break;
1600 }
1601
1602 case VIDEO_GET_FRAME_COUNT: {
1603 u32 data[CX2341X_MBOX_MAX_DATA];
1604 u64 *frame = arg;
1605
1606 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1607 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1608 *frame = 0;
1609 break;
1610 }
1611 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1612 return -EINVAL;
1613
1614 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1615 *frame = itv->last_dec_timing[0];
1616 break;
1617 }
1618 *frame = 0;
1619 if (atomic_read(&itv->decoding)) {
1620 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1621 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1622 return -EIO;
1623 }
1624 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1625 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1626 *frame = data[0];
1627 }
1628 break;
1629 }
1630
1631 case VIDEO_PLAY: {
1632 struct video_command vc;
1633
1634 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1635 memset(&vc, 0, sizeof(vc));
1636 vc.cmd = VIDEO_CMD_PLAY;
1637 return ivtv_video_command(itv, id, &vc, 0);
1638 }
1639
1640 case VIDEO_STOP: {
1641 struct video_command vc;
1642
1643 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1644 memset(&vc, 0, sizeof(vc));
1645 vc.cmd = VIDEO_CMD_STOP;
1646 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1647 return ivtv_video_command(itv, id, &vc, 0);
1648 }
1649
1650 case VIDEO_FREEZE: {
1651 struct video_command vc;
1652
1653 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1654 memset(&vc, 0, sizeof(vc));
1655 vc.cmd = VIDEO_CMD_FREEZE;
1656 return ivtv_video_command(itv, id, &vc, 0);
1657 }
1658
1659 case VIDEO_CONTINUE: {
1660 struct video_command vc;
1661
1662 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1663 memset(&vc, 0, sizeof(vc));
1664 vc.cmd = VIDEO_CMD_CONTINUE;
1665 return ivtv_video_command(itv, id, &vc, 0);
1666 }
1667
1668 case VIDEO_COMMAND:
1669 case VIDEO_TRY_COMMAND: {
1670 struct video_command *vc = arg;
1671 int try = (cmd == VIDEO_TRY_COMMAND);
1672
1673 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001674 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001675 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001676 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001677 return ivtv_video_command(itv, id, vc, try);
1678 }
1679
1680 case VIDEO_GET_EVENT: {
1681 struct video_event *ev = arg;
1682 DEFINE_WAIT(wait);
1683
1684 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1685 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1686 return -EINVAL;
1687 memset(ev, 0, sizeof(*ev));
1688 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1689
1690 while (1) {
1691 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1692 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1693 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1694 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001695 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1696 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1697 if (itv->output_mode == OUT_UDMA_YUV &&
1698 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1699 IVTV_YUV_MODE_PROGRESSIVE) {
1700 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1701 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001702 }
1703 if (ev->type)
1704 return 0;
1705 if (nonblocking)
1706 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001707 /* Wait for event. Note that serialize_lock is locked,
1708 so to allow other processes to access the driver while
1709 we are waiting unlock first and later lock again. */
1710 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001711 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
1712 if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
1713 schedule();
1714 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001715 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001716 if (signal_pending(current)) {
1717 /* return if a signal was received */
1718 IVTV_DEBUG_INFO("User stopped wait for event\n");
1719 return -EINTR;
1720 }
1721 }
1722 break;
1723 }
1724
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001725 default:
1726 return -EINVAL;
1727 }
1728 return 0;
1729}
1730
Hans Verkuil3f038d82008-05-29 16:43:54 -03001731static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001732{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001733 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001734
Hans Verkuild46c17d2007-03-10 17:59:15 -03001735 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001736 case VIDIOC_INT_S_AUDIO_ROUTING: {
1737 struct v4l2_routing *route = arg;
1738
1739 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
1740 break;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001741 }
1742
Hans Verkuil3f038d82008-05-29 16:43:54 -03001743 case VIDIOC_INT_RESET: {
1744 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001745
Hans Verkuil3f038d82008-05-29 16:43:54 -03001746 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1747 ivtv_reset_ir_gpio(itv);
1748 if (val & 0x02)
1749 itv->video_dec_func(itv, cmd, NULL);
1750 break;
1751 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001752
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001753 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -03001754 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001755 }
1756 return 0;
1757}
1758
Hans Verkuilbaa40722007-08-19 07:10:55 -03001759static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1760 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001761{
Hans Verkuil37f89f92008-06-22 11:57:31 -03001762 struct video_device *vfd = video_devdata(filp);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001763 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1764 int ret;
1765
1766 /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001767 switch (cmd) {
1768 case VIDEO_SELECT_SOURCE:
1769 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1770 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1771 return -EINVAL;
1772 return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX);
1773
1774 case AUDIO_SET_MUTE:
1775 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1776 itv->speed_mute_audio = arg;
1777 return 0;
1778
1779 case AUDIO_CHANNEL_SELECT:
1780 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1781 if (arg > AUDIO_STEREO_SWAPPED)
1782 return -EINVAL;
1783 itv->audio_stereo_mode = arg;
1784 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1785 return 0;
1786
1787 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1788 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1789 if (arg > AUDIO_STEREO_SWAPPED)
1790 return -EINVAL;
1791 itv->audio_bilingual_mode = arg;
1792 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1793 return 0;
1794
Hans Verkuil3f038d82008-05-29 16:43:54 -03001795 case IVTV_IOC_DMA_FRAME:
1796 case VIDEO_GET_PTS:
1797 case VIDEO_GET_FRAME_COUNT:
1798 case VIDEO_GET_EVENT:
1799 case VIDEO_PLAY:
1800 case VIDEO_STOP:
1801 case VIDEO_FREEZE:
1802 case VIDEO_CONTINUE:
1803 case VIDEO_COMMAND:
1804 case VIDEO_TRY_COMMAND:
1805 return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
1806
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001807 default:
1808 break;
1809 }
Hans Verkuil3f038d82008-05-29 16:43:54 -03001810
1811 /* check priority */
1812 switch (cmd) {
1813 case VIDIOC_S_CTRL:
1814 case VIDIOC_S_STD:
1815 case VIDIOC_S_INPUT:
1816 case VIDIOC_S_OUTPUT:
1817 case VIDIOC_S_TUNER:
1818 case VIDIOC_S_FREQUENCY:
1819 case VIDIOC_S_FMT:
1820 case VIDIOC_S_CROP:
1821 case VIDIOC_S_AUDIO:
1822 case VIDIOC_S_AUDOUT:
1823 case VIDIOC_S_EXT_CTRLS:
1824 case VIDIOC_S_FBUF:
1825 case VIDIOC_OVERLAY:
1826 ret = v4l2_prio_check(&itv->prio, &id->prio);
1827 if (ret)
1828 return ret;
1829 }
1830
Hans Verkuil37f89f92008-06-22 11:57:31 -03001831 if (ivtv_debug & IVTV_DBGFLG_IOCTL)
1832 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1833 ret = video_ioctl2(inode, filp, cmd, arg);
1834 vfd->debug = 0;
1835 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001836}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001837
1838int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1839 unsigned long arg)
1840{
1841 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1842 struct ivtv *itv = id->itv;
1843 int res;
1844
1845 mutex_lock(&itv->serialize_lock);
1846 res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
1847 mutex_unlock(&itv->serialize_lock);
1848 return res;
1849}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001850
Hans Verkuila3998102008-07-21 02:57:38 -03001851static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1852 .vidioc_querycap = ivtv_querycap,
1853 .vidioc_g_priority = ivtv_g_priority,
1854 .vidioc_s_priority = ivtv_s_priority,
1855 .vidioc_s_audio = ivtv_s_audio,
1856 .vidioc_g_audio = ivtv_g_audio,
1857 .vidioc_enumaudio = ivtv_enumaudio,
1858 .vidioc_s_audout = ivtv_s_audout,
1859 .vidioc_g_audout = ivtv_g_audout,
1860 .vidioc_enum_input = ivtv_enum_input,
1861 .vidioc_enum_output = ivtv_enum_output,
1862 .vidioc_enumaudout = ivtv_enumaudout,
1863 .vidioc_cropcap = ivtv_cropcap,
1864 .vidioc_s_crop = ivtv_s_crop,
1865 .vidioc_g_crop = ivtv_g_crop,
1866 .vidioc_g_input = ivtv_g_input,
1867 .vidioc_s_input = ivtv_s_input,
1868 .vidioc_g_output = ivtv_g_output,
1869 .vidioc_s_output = ivtv_s_output,
1870 .vidioc_g_frequency = ivtv_g_frequency,
1871 .vidioc_s_frequency = ivtv_s_frequency,
1872 .vidioc_s_tuner = ivtv_s_tuner,
1873 .vidioc_g_tuner = ivtv_g_tuner,
1874 .vidioc_g_enc_index = ivtv_g_enc_index,
1875 .vidioc_g_fbuf = ivtv_g_fbuf,
1876 .vidioc_s_fbuf = ivtv_s_fbuf,
1877 .vidioc_g_std = ivtv_g_std,
1878 .vidioc_s_std = ivtv_s_std,
1879 .vidioc_overlay = ivtv_overlay,
1880 .vidioc_log_status = ivtv_log_status,
1881 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1882 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1883 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
1884 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1885 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1886 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1887 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1888 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1889 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1890 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1891 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1892 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1893 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1894 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1895 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1896 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1897 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1898 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1899 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1900 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1901 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1902 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1903 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1904 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1905#ifdef CONFIG_VIDEO_ADV_DEBUG
1906 .vidioc_g_register = ivtv_g_register,
1907 .vidioc_s_register = ivtv_s_register,
1908#endif
1909 .vidioc_default = ivtv_default,
1910 .vidioc_queryctrl = ivtv_queryctrl,
1911 .vidioc_querymenu = ivtv_querymenu,
1912 .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls,
1913 .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls,
1914 .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls,
1915};
1916
Hans Verkuil3f038d82008-05-29 16:43:54 -03001917void ivtv_set_funcs(struct video_device *vdev)
1918{
Hans Verkuila3998102008-07-21 02:57:38 -03001919 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001920}