blob: 6422cf8f189df534cfe86e4a9ef8e379d2b72e7d [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);
Hans Verkuilec105a42009-05-02 11:10:23 -0300183 while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300184 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 Verkuila4a78712009-02-06 15:31:59 -0300348 /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
349 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
Hans Verkuile88360c2008-06-21 08:00:56 -0300350 pixfmt->bytesperline = 720;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300351 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300352 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
353 pixfmt->sizeimage = 128 * 1024;
354 pixfmt->bytesperline = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300355 }
356 return 0;
357}
358
Hans Verkuil3f038d82008-05-29 16:43:54 -0300359static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300360{
Hans Verkuil3f038d82008-05-29 16:43:54 -0300361 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300362 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300363
Hans Verkuile88360c2008-06-21 08:00:56 -0300364 vbifmt->sampling_rate = 27000000;
365 vbifmt->offset = 248;
366 vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
367 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
368 vbifmt->start[0] = itv->vbi.start[0];
369 vbifmt->start[1] = itv->vbi.start[1];
370 vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
371 vbifmt->flags = 0;
372 vbifmt->reserved[0] = 0;
373 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300374 return 0;
375}
376
377static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
378{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300379 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300380 struct ivtv_open_id *id = fh;
381 struct ivtv *itv = id->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300382
Hans Verkuile88360c2008-06-21 08:00:56 -0300383 vbifmt->reserved[0] = 0;
384 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300385 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300386
Hans Verkuil3f038d82008-05-29 16:43:54 -0300387 if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
388 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
389 V4L2_SLICED_VBI_525;
390 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300391 return 0;
392 }
393
Hans Verkuil7bf432d2009-02-16 04:25:32 -0300394 v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300395 vbifmt->service_set = ivtv_get_service_set(vbifmt);
396 return 0;
397}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300398
Hans Verkuil3f038d82008-05-29 16:43:54 -0300399static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
400{
401 struct ivtv_open_id *id = fh;
402 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300403 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300404
Hans Verkuil3f038d82008-05-29 16:43:54 -0300405 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300406 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300407 pixfmt->width = itv->main_rect.width;
408 pixfmt->height = itv->main_rect.height;
409 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
410 pixfmt->field = V4L2_FIELD_INTERLACED;
411 pixfmt->priv = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300412 if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
413 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
414 case IVTV_YUV_MODE_INTERLACED:
Hans Verkuile88360c2008-06-21 08:00:56 -0300415 pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
Hans Verkuil3f038d82008-05-29 16:43:54 -0300416 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
417 break;
418 case IVTV_YUV_MODE_PROGRESSIVE:
Hans Verkuile88360c2008-06-21 08:00:56 -0300419 pixfmt->field = V4L2_FIELD_NONE;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300420 break;
421 default:
Hans Verkuile88360c2008-06-21 08:00:56 -0300422 pixfmt->field = V4L2_FIELD_ANY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300423 break;
424 }
Hans Verkuile88360c2008-06-21 08:00:56 -0300425 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
426 pixfmt->bytesperline = 720;
427 pixfmt->width = itv->yuv_info.v4l2_src_w;
428 pixfmt->height = itv->yuv_info.v4l2_src_h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300429 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
Hans Verkuile88360c2008-06-21 08:00:56 -0300430 pixfmt->sizeimage =
431 1080 * ((pixfmt->height + 31) & ~31);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300432 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300433 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
434 pixfmt->sizeimage = 128 * 1024;
435 pixfmt->bytesperline = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300436 }
437 return 0;
438}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300439
Hans Verkuil3f038d82008-05-29 16:43:54 -0300440static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
441{
442 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300443 struct v4l2_window *winfmt = &fmt->fmt.win;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300444
445 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
446 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300447 winfmt->chromakey = itv->osd_chroma_key;
448 winfmt->global_alpha = itv->osd_global_alpha;
449 winfmt->field = V4L2_FIELD_INTERLACED;
450 winfmt->clips = NULL;
451 winfmt->clipcount = 0;
452 winfmt->bitmap = NULL;
453 winfmt->w.top = winfmt->w.left = 0;
454 winfmt->w.width = itv->osd_rect.width;
455 winfmt->w.height = itv->osd_rect.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300456 return 0;
457}
458
459static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
460{
461 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
462}
463
464static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
465{
466 struct ivtv_open_id *id = fh;
467 struct ivtv *itv = id->itv;
468 int w = fmt->fmt.pix.width;
469 int h = fmt->fmt.pix.height;
Hans Verkuila4a78712009-02-06 15:31:59 -0300470 int min_h = 2;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300471
472 w = min(w, 720);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300473 w = max(w, 2);
Hans Verkuila4a78712009-02-06 15:31:59 -0300474 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
475 /* YUV height must be a multiple of 32 */
476 h &= ~0x1f;
477 min_h = 32;
478 }
Hans Verkuil3f038d82008-05-29 16:43:54 -0300479 h = min(h, itv->is_50hz ? 576 : 480);
Hans Verkuila4a78712009-02-06 15:31:59 -0300480 h = max(h, min_h);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300481 ivtv_g_fmt_vid_cap(file, fh, fmt);
482 fmt->fmt.pix.width = w;
483 fmt->fmt.pix.height = h;
484 return 0;
485}
486
487static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
488{
489 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
490}
491
492static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
493{
494 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
495 struct ivtv_open_id *id = fh;
496 struct ivtv *itv = id->itv;
497
498 if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
499 return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300500
501 /* set sliced VBI capture format */
502 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuile88360c2008-06-21 08:00:56 -0300503 vbifmt->reserved[0] = 0;
504 vbifmt->reserved[1] = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300505
506 if (vbifmt->service_set)
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300507 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300508 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300509 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300510 return 0;
511}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300512
Hans Verkuil3f038d82008-05-29 16:43:54 -0300513static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
514{
515 struct ivtv_open_id *id = fh;
Hans Verkuileffc3462008-09-06 08:24:37 -0300516 s32 w = fmt->fmt.pix.width;
517 s32 h = fmt->fmt.pix.height;
518 int field = fmt->fmt.pix.field;
519 int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300520
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300521 w = min(w, 720);
522 w = max(w, 2);
Hans Verkuil962d6992008-10-11 09:00:39 -0300523 /* Why can the height be 576 even when the output is NTSC?
524
525 Internally the buffers of the PVR350 are always set to 720x576. The
526 decoded video frame will always be placed in the top left corner of
527 this buffer. For any video which is not 720x576, the buffer will
528 then be cropped to remove the unused right and lower areas, with
529 the remaining image being scaled by the hardware to fit the display
530 area. The video can be scaled both up and down, so a 720x480 video
531 can be displayed full-screen on PAL and a 720x576 video can be
532 displayed without cropping on NTSC.
533
534 Note that the scaling only occurs on the video stream, the osd
535 resolution is locked to the broadcast standard and not scaled.
536
537 Thanks to Ian Armstrong for this explanation. */
538 h = min(h, 576);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300539 h = max(h, 2);
540 if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300541 fmt->fmt.pix.field = field;
Hans Verkuileffc3462008-09-06 08:24:37 -0300542 fmt->fmt.pix.width = w;
543 fmt->fmt.pix.height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300544 return ret;
545}
546
547static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
548{
549 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300550 u32 chromakey = fmt->fmt.win.chromakey;
551 u8 global_alpha = fmt->fmt.win.global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300552
553 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
554 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300555 ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
556 fmt->fmt.win.chromakey = chromakey;
557 fmt->fmt.win.global_alpha = global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300558 return 0;
559}
560
561static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
562{
563 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
564}
565
566static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
567{
568 struct ivtv_open_id *id = fh;
569 struct ivtv *itv = id->itv;
570 struct cx2341x_mpeg_params *p = &itv->params;
Hans Verkuileffc3462008-09-06 08:24:37 -0300571 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300572 int w = fmt->fmt.pix.width;
573 int h = fmt->fmt.pix.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300574
575 if (ret)
576 return ret;
577
578 if (p->width == w && p->height == h)
579 return 0;
580
581 if (atomic_read(&itv->capturing) > 0)
582 return -EBUSY;
583
584 p->width = w;
585 p->height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300586 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
587 fmt->fmt.pix.width /= 2;
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300588 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300589 return ivtv_g_fmt_vid_cap(file, fh, fmt);
590}
591
592static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
593{
594 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
595
Hans Verkuila8b86432008-10-04 08:05:30 -0300596 if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
597 return -EBUSY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300598 itv->vbi.sliced_in->service_set = 0;
Hans Verkuila8b86432008-10-04 08:05:30 -0300599 itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300600 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300601 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
602}
603
604static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
605{
606 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
607 struct ivtv_open_id *id = fh;
608 struct ivtv *itv = id->itv;
609 int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
610
611 if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
612 return ret;
613
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300614 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuila8b86432008-10-04 08:05:30 -0300615 if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300616 return -EBUSY;
Hans Verkuila8b86432008-10-04 08:05:30 -0300617 itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300618 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300619 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
620 return 0;
621}
622
Hans Verkuil3f038d82008-05-29 16:43:54 -0300623static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300624{
Hans Verkuil3f038d82008-05-29 16:43:54 -0300625 struct ivtv_open_id *id = fh;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300626 struct ivtv *itv = id->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300627 struct yuv_playback_info *yi = &itv->yuv_info;
628 int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300629
Hans Verkuil3f038d82008-05-29 16:43:54 -0300630 if (ret)
631 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300632
Hans Verkuil3f038d82008-05-29 16:43:54 -0300633 if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
634 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300635
Hans Verkuil3f038d82008-05-29 16:43:54 -0300636 /* Return now if we already have some frame data */
637 if (yi->stream_size)
638 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300639
Hans Verkuil3f038d82008-05-29 16:43:54 -0300640 yi->v4l2_src_w = fmt->fmt.pix.width;
641 yi->v4l2_src_h = fmt->fmt.pix.height;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300642
Hans Verkuil3f038d82008-05-29 16:43:54 -0300643 switch (fmt->fmt.pix.field) {
644 case V4L2_FIELD_NONE:
645 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300646 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300647 case V4L2_FIELD_ANY:
648 yi->lace_mode = IVTV_YUV_MODE_AUTO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300649 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300650 case V4L2_FIELD_INTERLACED_BT:
651 yi->lace_mode =
652 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
653 break;
654 case V4L2_FIELD_INTERLACED_TB:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300655 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -0300656 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
657 break;
658 }
659 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
660
661 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
662 itv->dma_data_req_size =
663 1080 * ((yi->v4l2_src_h + 31) & ~31);
664
Hans Verkuil3f038d82008-05-29 16:43:54 -0300665 return 0;
666}
667
668static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
669{
670 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
671 int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
672
673 if (ret == 0) {
674 itv->osd_chroma_key = fmt->fmt.win.chromakey;
675 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
676 ivtv_set_osd_alpha(itv);
677 }
678 return ret;
679}
680
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300681static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300682{
683 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
684
685 chip->ident = V4L2_IDENT_NONE;
686 chip->revision = 0;
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300687 if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
688 if (v4l2_chip_match_host(&chip->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300689 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
690 return 0;
691 }
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300692 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
693 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300694 return -EINVAL;
695 /* TODO: is this correct? */
696 return ivtv_call_all_err(itv, core, g_chip_ident, chip);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300697}
698
Hans Verkuil36ecd492008-06-25 06:00:17 -0300699#ifdef CONFIG_VIDEO_ADV_DEBUG
700static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
701{
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300702 struct v4l2_dbg_register *regs = arg;
Hans Verkuiladb65bc2008-06-25 06:32:44 -0300703 volatile u8 __iomem *reg_start;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300704
705 if (!capable(CAP_SYS_ADMIN))
706 return -EPERM;
707 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
708 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
709 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
710 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
711 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
Roel Kluin223ffe52009-05-02 16:38:47 -0300712 else if (regs->reg < IVTV_ENCODER_SIZE)
Hans Verkuil36ecd492008-06-25 06:00:17 -0300713 reg_start = itv->enc_mem;
714 else
715 return -EINVAL;
716
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300717 regs->size = 4;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300718 if (cmd == VIDIOC_DBG_G_REGISTER)
719 regs->val = readl(regs->reg + reg_start);
720 else
721 writel(regs->val, regs->reg + reg_start);
Hans Verkuil36ecd492008-06-25 06:00:17 -0300722 return 0;
723}
724
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300725static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300726{
727 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
728
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300729 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300730 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300731 /* TODO: subdev errors should not be ignored, this should become a
732 subdev helper function. */
733 ivtv_call_all(itv, core, g_register, reg);
734 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300735}
736
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300737static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300738{
739 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
740
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300741 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300742 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300743 /* TODO: subdev errors should not be ignored, this should become a
744 subdev helper function. */
745 ivtv_call_all(itv, core, s_register, reg);
746 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300747}
Hans Verkuil36ecd492008-06-25 06:00:17 -0300748#endif
Hans Verkuil3f038d82008-05-29 16:43:54 -0300749
750static int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
751{
752 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
753
754 *p = v4l2_prio_max(&itv->prio);
755
756 return 0;
757}
758
759static int ivtv_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
760{
761 struct ivtv_open_id *id = fh;
762 struct ivtv *itv = id->itv;
763
764 return v4l2_prio_change(&itv->prio, &id->prio, prio);
765}
766
767static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
768{
769 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
770
Hans Verkuil3f038d82008-05-29 16:43:54 -0300771 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
772 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
Hans Verkuil8ac05ae2009-02-07 07:02:27 -0300773 snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
Hans Verkuil3f038d82008-05-29 16:43:54 -0300774 vcap->version = IVTV_DRIVER_VERSION; /* version */
775 vcap->capabilities = itv->v4l2_cap; /* capabilities */
Hans Verkuil3f038d82008-05-29 16:43:54 -0300776 return 0;
777}
778
779static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
780{
781 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
782
783 return ivtv_get_audio_input(itv, vin->index, vin);
784}
785
786static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
787{
788 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
789
790 vin->index = itv->audio_input;
791 return ivtv_get_audio_input(itv, vin->index, vin);
792}
793
794static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
795{
796 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
797
798 if (vout->index >= itv->nof_audio_inputs)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300799 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300800
801 itv->audio_input = vout->index;
802 ivtv_audio_set_io(itv);
803
804 return 0;
805}
806
807static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
808{
809 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
810
811 /* set it to defaults from our table */
812 return ivtv_get_audio_output(itv, vin->index, vin);
813}
814
815static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
816{
817 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
818
819 vin->index = 0;
820 return ivtv_get_audio_output(itv, vin->index, vin);
821}
822
823static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
824{
825 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
826
827 return ivtv_get_audio_output(itv, vout->index, vout);
828}
829
830static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
831{
832 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
833
834 /* set it to defaults from our table */
835 return ivtv_get_input(itv, vin->index, vin);
836}
837
838static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
839{
840 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
841
842 return ivtv_get_output(itv, vout->index, vout);
843}
844
845static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
846{
847 struct ivtv_open_id *id = fh;
848 struct ivtv *itv = id->itv;
849 struct yuv_playback_info *yi = &itv->yuv_info;
850 int streamtype;
851
852 streamtype = id->type;
853
854 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
855 return -EINVAL;
856 cropcap->bounds.top = cropcap->bounds.left = 0;
857 cropcap->bounds.width = 720;
858 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
859 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
860 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
861 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
862 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
863 if (yi->track_osd) {
864 cropcap->bounds.width = yi->osd_full_w;
865 cropcap->bounds.height = yi->osd_full_h;
866 } else {
867 cropcap->bounds.width = 720;
868 cropcap->bounds.height =
869 itv->is_out_50hz ? 576 : 480;
870 }
871 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
872 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
873 } else {
874 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
875 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
876 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
877 }
878 cropcap->defrect = cropcap->bounds;
879 return 0;
880}
881
882static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
883{
884 struct ivtv_open_id *id = fh;
885 struct ivtv *itv = id->itv;
886 struct yuv_playback_info *yi = &itv->yuv_info;
887 int streamtype;
888
889 streamtype = id->type;
890
Hans Verkuil3f038d82008-05-29 16:43:54 -0300891 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
892 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
893 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
894 yi->main_rect = crop->c;
895 return 0;
896 } else {
897 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
898 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
899 itv->main_rect = crop->c;
900 return 0;
901 }
902 }
903 return -EINVAL;
904 }
905 return -EINVAL;
906}
907
908static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
909{
910 struct ivtv_open_id *id = fh;
911 struct ivtv *itv = id->itv;
912 struct yuv_playback_info *yi = &itv->yuv_info;
913 int streamtype;
914
915 streamtype = id->type;
916
917 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
918 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
919 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
920 crop->c = yi->main_rect;
921 else
922 crop->c = itv->main_rect;
923 return 0;
924 }
925 return -EINVAL;
926}
927
928static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
929{
930 static struct v4l2_fmtdesc formats[] = {
931 { 0, 0, 0,
932 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
933 { 0, 0, 0, 0 }
934 },
935 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
936 "MPEG", V4L2_PIX_FMT_MPEG,
937 { 0, 0, 0, 0 }
938 }
939 };
940 enum v4l2_buf_type type = fmt->type;
941
942 if (fmt->index > 1)
943 return -EINVAL;
944
945 *fmt = formats[fmt->index];
946 fmt->type = type;
947 return 0;
948}
949
950static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
951{
952 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
953
954 static struct v4l2_fmtdesc formats[] = {
955 { 0, 0, 0,
956 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
957 { 0, 0, 0, 0 }
958 },
959 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
960 "MPEG", V4L2_PIX_FMT_MPEG,
961 { 0, 0, 0, 0 }
962 }
963 };
964 enum v4l2_buf_type type = fmt->type;
965
966 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
967 return -EINVAL;
968
969 if (fmt->index > 1)
970 return -EINVAL;
971
972 *fmt = formats[fmt->index];
973 fmt->type = type;
974
975 return 0;
976}
977
978static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
979{
980 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
981
982 *i = itv->active_input;
983
984 return 0;
985}
986
987int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
988{
989 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
990
991 if (inp < 0 || inp >= itv->nof_inputs)
992 return -EINVAL;
993
994 if (inp == itv->active_input) {
995 IVTV_DEBUG_INFO("Input unchanged\n");
996 return 0;
997 }
998
999 if (atomic_read(&itv->capturing) > 0) {
1000 return -EBUSY;
1001 }
1002
1003 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
1004 itv->active_input, inp);
1005
1006 itv->active_input = inp;
1007 /* Set the audio input to whatever is appropriate for the
1008 input type. */
1009 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1010
1011 /* prevent others from messing with the streams until
1012 we're finished changing inputs. */
1013 ivtv_mute(itv);
1014 ivtv_video_set_io(itv);
1015 ivtv_audio_set_io(itv);
1016 ivtv_unmute(itv);
1017
1018 return 0;
1019}
1020
1021static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1022{
1023 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1024
1025 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1026 return -EINVAL;
1027
1028 *i = itv->active_output;
1029
1030 return 0;
1031}
1032
1033static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1034{
1035 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001036
1037 if (outp >= itv->card->nof_outputs)
1038 return -EINVAL;
1039
1040 if (outp == itv->active_output) {
1041 IVTV_DEBUG_INFO("Output unchanged\n");
1042 return 0;
1043 }
1044 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1045 itv->active_output, outp);
1046
1047 itv->active_output = outp;
Hans Verkuil5325b422009-04-02 11:26:22 -03001048 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
1049 SAA7127_INPUT_TYPE_NORMAL,
1050 itv->card->video_outputs[outp].video_output, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001051
1052 return 0;
1053}
1054
1055static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1056{
1057 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1058
1059 if (vf->tuner != 0)
1060 return -EINVAL;
1061
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001062 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001063 return 0;
1064}
1065
1066int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1067{
1068 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1069
1070 if (vf->tuner != 0)
1071 return -EINVAL;
1072
1073 ivtv_mute(itv);
1074 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001075 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001076 ivtv_unmute(itv);
1077 return 0;
1078}
1079
1080static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1081{
1082 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1083
1084 *std = itv->std;
1085 return 0;
1086}
1087
1088int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1089{
Ian Armstrong2443bae2010-03-13 20:22:34 -03001090 DEFINE_WAIT(wait);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001091 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1092 struct yuv_playback_info *yi = &itv->yuv_info;
Ian Armstrong2443bae2010-03-13 20:22:34 -03001093 int f;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001094
1095 if ((*std & V4L2_STD_ALL) == 0)
1096 return -EINVAL;
1097
1098 if (*std == itv->std)
1099 return 0;
1100
1101 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1102 atomic_read(&itv->capturing) > 0 ||
1103 atomic_read(&itv->decoding) > 0) {
1104 /* Switching standard would turn off the radio or mess
1105 with already running streams, prevent that by
1106 returning EBUSY. */
1107 return -EBUSY;
1108 }
1109
1110 itv->std = *std;
1111 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1112 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1113 itv->params.width = 720;
1114 itv->params.height = itv->is_50hz ? 576 : 480;
1115 itv->vbi.count = itv->is_50hz ? 18 : 12;
1116 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1117 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1118
1119 if (itv->hw_flags & IVTV_HW_CX25840)
1120 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1121
1122 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
1123
1124 /* Tuner */
Hans Verkuilf41737e2009-04-01 03:52:39 -03001125 ivtv_call_all(itv, core, s_std, itv->std);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001126
1127 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1128 /* set display standard */
1129 itv->std_out = *std;
1130 itv->is_out_60hz = itv->is_60hz;
1131 itv->is_out_50hz = itv->is_50hz;
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001132 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Ian Armstrong2443bae2010-03-13 20:22:34 -03001133
1134 /*
1135 * The next firmware call is time sensitive. Time it to
1136 * avoid risk of a hard lock, by trying to ensure the call
1137 * happens within the first 100 lines of the top field.
1138 * Make 4 attempts to sync to the decoder before giving up.
1139 */
1140 for (f = 0; f < 4; f++) {
1141 prepare_to_wait(&itv->vsync_waitq, &wait,
1142 TASK_UNINTERRUPTIBLE);
Andy Walls4e1af312010-03-13 20:37:25 -03001143 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
Ian Armstrong2443bae2010-03-13 20:22:34 -03001144 break;
1145 schedule_timeout(msecs_to_jiffies(25));
1146 }
1147 finish_wait(&itv->vsync_waitq, &wait);
1148
1149 if (f == 4)
1150 IVTV_WARN("Mode change failed to sync to decoder\n");
1151
Hans Verkuil3f038d82008-05-29 16:43:54 -03001152 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1153 itv->main_rect.left = itv->main_rect.top = 0;
1154 itv->main_rect.width = 720;
1155 itv->main_rect.height = itv->params.height;
1156 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1157 720, itv->main_rect.height, 0, 0);
1158 yi->main_rect = itv->main_rect;
1159 if (!itv->osd_info) {
1160 yi->osd_full_w = 720;
1161 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1162 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001163 }
1164 return 0;
1165}
1166
Hans Verkuil3f038d82008-05-29 16:43:54 -03001167static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001168{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001169 struct ivtv_open_id *id = fh;
1170 struct ivtv *itv = id->itv;
1171
1172 if (vt->index != 0)
1173 return -EINVAL;
1174
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001175 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001176
1177 return 0;
1178}
1179
1180static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1181{
1182 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1183
1184 if (vt->index != 0)
1185 return -EINVAL;
1186
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001187 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001188
1189 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1190 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
1191 vt->type = V4L2_TUNER_RADIO;
1192 } else {
1193 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
1194 vt->type = V4L2_TUNER_ANALOG_TV;
1195 }
1196
1197 return 0;
1198}
1199
1200static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1201{
1202 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1203 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1204 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001205
Hans Verkuil79afcb12008-06-21 09:02:36 -03001206 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001207 for (f = 0; f < 2; f++) {
1208 for (l = 0; l < 24; l++) {
1209 if (valid_service_line(f, l, itv->is_50hz))
1210 cap->service_lines[f][l] = set;
1211 }
1212 }
1213 return 0;
1214 }
Hans Verkuil79afcb12008-06-21 09:02:36 -03001215 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001216 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1217 return -EINVAL;
1218 if (itv->is_60hz) {
1219 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1220 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1221 } else {
1222 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1223 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1224 }
1225 return 0;
1226 }
1227 return -EINVAL;
1228}
1229
1230static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1231{
1232 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1233 struct v4l2_enc_idx_entry *e = idx->entry;
1234 int entries;
1235 int i;
1236
1237 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1238 IVTV_MAX_PGM_INDEX;
1239 if (entries > V4L2_ENC_IDX_ENTRIES)
1240 entries = V4L2_ENC_IDX_ENTRIES;
1241 idx->entries = 0;
1242 for (i = 0; i < entries; i++) {
1243 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1244 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1245 idx->entries++;
1246 e++;
1247 }
1248 }
1249 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1250 return 0;
1251}
1252
1253static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1254{
1255 struct ivtv_open_id *id = fh;
1256 struct ivtv *itv = id->itv;
1257
Hans Verkuil3f038d82008-05-29 16:43:54 -03001258
1259 switch (enc->cmd) {
1260 case V4L2_ENC_CMD_START:
1261 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1262 enc->flags = 0;
1263 return ivtv_start_capture(id);
1264
1265 case V4L2_ENC_CMD_STOP:
1266 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1267 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1268 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1269 return 0;
1270
1271 case V4L2_ENC_CMD_PAUSE:
1272 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1273 enc->flags = 0;
1274
1275 if (!atomic_read(&itv->capturing))
1276 return -EPERM;
1277 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1278 return 0;
1279
1280 ivtv_mute(itv);
1281 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1282 break;
1283
1284 case V4L2_ENC_CMD_RESUME:
1285 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1286 enc->flags = 0;
1287
1288 if (!atomic_read(&itv->capturing))
1289 return -EPERM;
1290
1291 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1292 return 0;
1293
1294 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1295 ivtv_unmute(itv);
1296 break;
1297 default:
1298 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1299 return -EINVAL;
1300 }
1301
1302 return 0;
1303}
1304
1305static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1306{
1307 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1308
Hans Verkuil3f038d82008-05-29 16:43:54 -03001309 switch (enc->cmd) {
1310 case V4L2_ENC_CMD_START:
1311 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1312 enc->flags = 0;
1313 return 0;
1314
1315 case V4L2_ENC_CMD_STOP:
1316 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1317 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1318 return 0;
1319
1320 case V4L2_ENC_CMD_PAUSE:
1321 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1322 enc->flags = 0;
1323 return 0;
1324
1325 case V4L2_ENC_CMD_RESUME:
1326 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1327 enc->flags = 0;
1328 return 0;
1329 default:
1330 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1331 return -EINVAL;
1332 }
1333}
1334
1335static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1336{
1337 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001338 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001339 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001340
Hans Verkuil3f038d82008-05-29 16:43:54 -03001341 int pixfmt;
1342 static u32 pixel_format[16] = {
1343 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1344 V4L2_PIX_FMT_RGB565,
1345 V4L2_PIX_FMT_RGB555,
1346 V4L2_PIX_FMT_RGB444,
1347 V4L2_PIX_FMT_RGB32,
1348 0,
1349 0,
1350 0,
1351 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1352 V4L2_PIX_FMT_YUV565,
1353 V4L2_PIX_FMT_YUV555,
1354 V4L2_PIX_FMT_YUV444,
1355 V4L2_PIX_FMT_YUV32,
1356 0,
1357 0,
1358 0,
1359 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001360
Hans Verkuil3f038d82008-05-29 16:43:54 -03001361 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1362 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001363 if (!itv->osd_video_pbase)
1364 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001365
Hans Verkuil3f038d82008-05-29 16:43:54 -03001366 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1367 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001368
Hans Verkuil3f038d82008-05-29 16:43:54 -03001369 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1370 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1371 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001372
Hans Verkuil3f038d82008-05-29 16:43:54 -03001373 fb->fmt.pixelformat = pixel_format[pixfmt];
1374 fb->fmt.width = itv->osd_rect.width;
1375 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001376 fb->fmt.field = V4L2_FIELD_INTERLACED;
1377 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001378 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1379 fb->fmt.field = V4L2_FIELD_INTERLACED;
1380 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001381 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1382 fb->fmt.bytesperline *= 2;
1383 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1384 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1385 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001386 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001387 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001388 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001389
Hans Verkuil3f038d82008-05-29 16:43:54 -03001390 if (itv->osd_chroma_key_state)
1391 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001392
Hans Verkuil3f038d82008-05-29 16:43:54 -03001393 if (itv->osd_global_alpha_state)
1394 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001395
Ian Armstrongec9faa12008-10-06 03:06:08 -03001396 if (yi->track_osd)
1397 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1398
Hans Verkuil3f038d82008-05-29 16:43:54 -03001399 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001400
Hans Verkuil3f038d82008-05-29 16:43:54 -03001401 /* no local alpha for RGB565 or unknown formats */
1402 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001403 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001404
Hans Verkuil3f038d82008-05-29 16:43:54 -03001405 /* 16-bit formats have inverted local alpha */
1406 if (pixfmt == 2 || pixfmt == 3)
1407 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1408 else
1409 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001410
Hans Verkuil3f038d82008-05-29 16:43:54 -03001411 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001412 /* 16-bit formats have inverted local alpha */
1413 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001414 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001415 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001416 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001417 }
1418
Hans Verkuil3f038d82008-05-29 16:43:54 -03001419 return 0;
1420}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001421
Hans Verkuil3f038d82008-05-29 16:43:54 -03001422static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1423{
1424 struct ivtv_open_id *id = fh;
1425 struct ivtv *itv = id->itv;
1426 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001427
Hans Verkuil3f038d82008-05-29 16:43:54 -03001428 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001429 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001430 if (!itv->osd_video_pbase)
1431 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001432
1433 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1434 itv->osd_local_alpha_state =
1435 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1436 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1437 ivtv_set_osd_alpha(itv);
1438 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001439 return ivtv_g_fbuf(file, fh, fb);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001440}
1441
1442static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1443{
1444 struct ivtv_open_id *id = fh;
1445 struct ivtv *itv = id->itv;
1446
1447 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1448 return -EINVAL;
1449
1450 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1451
1452 return 0;
1453}
1454
1455static int ivtv_log_status(struct file *file, void *fh)
1456{
1457 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1458 u32 data[CX2341X_MBOX_MAX_DATA];
1459
1460 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1461 struct v4l2_input vidin;
1462 struct v4l2_audio audin;
1463 int i;
1464
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001465 IVTV_INFO("================= START STATUS CARD #%d =================\n",
1466 itv->instance);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001467 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1468 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1469 struct tveeprom tv;
1470
1471 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001472 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001473 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001474 ivtv_get_input(itv, itv->active_input, &vidin);
1475 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1476 IVTV_INFO("Video Input: %s\n", vidin.name);
1477 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1478 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1479 if (has_output) {
1480 struct v4l2_output vidout;
1481 struct v4l2_audioout audout;
1482 int mode = itv->output_mode;
1483 static const char * const output_modes[5] = {
1484 "None",
1485 "MPEG Streaming",
1486 "YUV Streaming",
1487 "YUV Frames",
1488 "Passthrough",
1489 };
1490 static const char * const audio_modes[5] = {
1491 "Stereo",
1492 "Left",
1493 "Right",
1494 "Mono",
1495 "Swapped"
1496 };
1497 static const char * const alpha_mode[4] = {
1498 "None",
1499 "Global",
1500 "Local",
1501 "Global and Local"
1502 };
1503 static const char * const pixel_format[16] = {
1504 "ARGB Indexed",
1505 "RGB 5:6:5",
1506 "ARGB 1:5:5:5",
1507 "ARGB 1:4:4:4",
1508 "ARGB 8:8:8:8",
1509 "5",
1510 "6",
1511 "7",
1512 "AYUV Indexed",
1513 "YUV 5:6:5",
1514 "AYUV 1:5:5:5",
1515 "AYUV 1:4:4:4",
1516 "AYUV 8:8:8:8",
1517 "13",
1518 "14",
1519 "15",
1520 };
1521
1522 ivtv_get_output(itv, itv->active_output, &vidout);
1523 ivtv_get_audio_output(itv, 0, &audout);
1524 IVTV_INFO("Video Output: %s\n", vidout.name);
1525 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1526 audio_modes[itv->audio_stereo_mode],
1527 audio_modes[itv->audio_bilingual_mode]);
1528 if (mode < 0 || mode > OUT_PASSTHROUGH)
1529 mode = OUT_NONE;
1530 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1531 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1532 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1533 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1534 data[0] & 1 ? "On" : "Off",
1535 alpha_mode[(data[0] >> 1) & 0x3],
1536 pixel_format[(data[0] >> 3) & 0xf]);
1537 }
1538 IVTV_INFO("Tuner: %s\n",
1539 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuil8ac05ae2009-02-07 07:02:27 -03001540 cx2341x_log_status(&itv->params, itv->v4l2_dev.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001541 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1542 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1543 struct ivtv_stream *s = &itv->streams[i];
1544
Hans Verkuil8ac05ae2009-02-07 07:02:27 -03001545 if (s->vdev == NULL || s->buffers == 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001546 continue;
1547 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1548 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1549 (s->buffers * s->buf_size) / 1024, s->buffers);
1550 }
1551
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001552 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1553 (long long)itv->mpg_data_received,
1554 (long long)itv->vbi_data_inserted);
1555 IVTV_INFO("================== END STATUS CARD #%d ==================\n",
1556 itv->instance);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001557
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001558 return 0;
1559}
1560
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001561static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001562{
1563 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1564 struct ivtv *itv = id->itv;
1565 int nonblocking = filp->f_flags & O_NONBLOCK;
1566 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuilce680252010-04-06 15:58:53 -03001567 unsigned long iarg = (unsigned long)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001568
1569 switch (cmd) {
1570 case IVTV_IOC_DMA_FRAME: {
1571 struct ivtv_dma_frame *args = arg;
1572
1573 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1574 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1575 return -EINVAL;
1576 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1577 return -EINVAL;
1578 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1579 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001580 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001581 return -EBUSY;
1582 }
1583 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1584 ivtv_release_stream(s);
1585 return -EBUSY;
1586 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001587 /* Mark that this file handle started the UDMA_YUV mode */
1588 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001589 if (args->y_source == NULL)
1590 return 0;
1591 return ivtv_yuv_prep_frame(itv, args);
1592 }
1593
1594 case VIDEO_GET_PTS: {
1595 u32 data[CX2341X_MBOX_MAX_DATA];
1596 u64 *pts = arg;
1597
1598 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1599 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1600 *pts = s->dma_pts;
1601 break;
1602 }
1603 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1604 return -EINVAL;
1605
1606 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1607 *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |
1608 (u64)itv->last_dec_timing[1];
1609 break;
1610 }
1611 *pts = 0;
1612 if (atomic_read(&itv->decoding)) {
1613 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1614 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1615 return -EIO;
1616 }
1617 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1618 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1619 *pts = (u64) ((u64) data[2] << 32) | (u64) data[1];
1620 /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
1621 }
1622 break;
1623 }
1624
1625 case VIDEO_GET_FRAME_COUNT: {
1626 u32 data[CX2341X_MBOX_MAX_DATA];
1627 u64 *frame = arg;
1628
1629 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1630 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1631 *frame = 0;
1632 break;
1633 }
1634 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1635 return -EINVAL;
1636
1637 if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
1638 *frame = itv->last_dec_timing[0];
1639 break;
1640 }
1641 *frame = 0;
1642 if (atomic_read(&itv->decoding)) {
1643 if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
1644 IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
1645 return -EIO;
1646 }
1647 memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
1648 set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
1649 *frame = data[0];
1650 }
1651 break;
1652 }
1653
1654 case VIDEO_PLAY: {
1655 struct video_command vc;
1656
1657 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
1658 memset(&vc, 0, sizeof(vc));
1659 vc.cmd = VIDEO_CMD_PLAY;
1660 return ivtv_video_command(itv, id, &vc, 0);
1661 }
1662
1663 case VIDEO_STOP: {
1664 struct video_command vc;
1665
1666 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
1667 memset(&vc, 0, sizeof(vc));
1668 vc.cmd = VIDEO_CMD_STOP;
1669 vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
1670 return ivtv_video_command(itv, id, &vc, 0);
1671 }
1672
1673 case VIDEO_FREEZE: {
1674 struct video_command vc;
1675
1676 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
1677 memset(&vc, 0, sizeof(vc));
1678 vc.cmd = VIDEO_CMD_FREEZE;
1679 return ivtv_video_command(itv, id, &vc, 0);
1680 }
1681
1682 case VIDEO_CONTINUE: {
1683 struct video_command vc;
1684
1685 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
1686 memset(&vc, 0, sizeof(vc));
1687 vc.cmd = VIDEO_CMD_CONTINUE;
1688 return ivtv_video_command(itv, id, &vc, 0);
1689 }
1690
1691 case VIDEO_COMMAND:
1692 case VIDEO_TRY_COMMAND: {
1693 struct video_command *vc = arg;
1694 int try = (cmd == VIDEO_TRY_COMMAND);
1695
1696 if (try)
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001697 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001698 else
Hans Verkuil1aa32c22007-08-19 06:08:58 -03001699 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001700 return ivtv_video_command(itv, id, vc, try);
1701 }
1702
1703 case VIDEO_GET_EVENT: {
1704 struct video_event *ev = arg;
1705 DEFINE_WAIT(wait);
1706
1707 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1708 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1709 return -EINVAL;
1710 memset(ev, 0, sizeof(*ev));
1711 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1712
1713 while (1) {
1714 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1715 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1716 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1717 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001718 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1719 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1720 if (itv->output_mode == OUT_UDMA_YUV &&
1721 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1722 IVTV_YUV_MODE_PROGRESSIVE) {
1723 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1724 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001725 }
1726 if (ev->type)
1727 return 0;
1728 if (nonblocking)
1729 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001730 /* Wait for event. Note that serialize_lock is locked,
1731 so to allow other processes to access the driver while
1732 we are waiting unlock first and later lock again. */
1733 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001734 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a42009-05-02 11:10:23 -03001735 if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
1736 !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001737 schedule();
1738 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001739 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001740 if (signal_pending(current)) {
1741 /* return if a signal was received */
1742 IVTV_DEBUG_INFO("User stopped wait for event\n");
1743 return -EINTR;
1744 }
1745 }
1746 break;
1747 }
1748
Hans Verkuilce680252010-04-06 15:58:53 -03001749 case VIDEO_SELECT_SOURCE:
1750 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1751 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1752 return -EINVAL;
1753 return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
1754
1755 case AUDIO_SET_MUTE:
1756 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1757 itv->speed_mute_audio = iarg;
1758 return 0;
1759
1760 case AUDIO_CHANNEL_SELECT:
1761 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1762 if (iarg > AUDIO_STEREO_SWAPPED)
1763 return -EINVAL;
1764 itv->audio_stereo_mode = iarg;
1765 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1766 return 0;
1767
1768 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1769 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1770 if (iarg > AUDIO_STEREO_SWAPPED)
1771 return -EINVAL;
1772 itv->audio_bilingual_mode = iarg;
1773 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1774 return 0;
1775
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001776 default:
1777 return -EINVAL;
1778 }
1779 return 0;
1780}
1781
Hans Verkuil069b7472008-12-30 07:04:34 -03001782static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001783{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001784 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001785
Hans Verkuild46c17d2007-03-10 17:59:15 -03001786 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001787 case VIDIOC_INT_RESET: {
1788 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001789
Hans Verkuil3f038d82008-05-29 16:43:54 -03001790 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1791 ivtv_reset_ir_gpio(itv);
1792 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001793 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001794 break;
1795 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001796
Hans Verkuilac9575f2009-02-14 19:58:33 -03001797 case IVTV_IOC_DMA_FRAME:
1798 case VIDEO_GET_PTS:
1799 case VIDEO_GET_FRAME_COUNT:
1800 case VIDEO_GET_EVENT:
1801 case VIDEO_PLAY:
1802 case VIDEO_STOP:
1803 case VIDEO_FREEZE:
1804 case VIDEO_CONTINUE:
1805 case VIDEO_COMMAND:
1806 case VIDEO_TRY_COMMAND:
Hans Verkuilce680252010-04-06 15:58:53 -03001807 case VIDEO_SELECT_SOURCE:
1808 case AUDIO_SET_MUTE:
1809 case AUDIO_CHANNEL_SELECT:
1810 case AUDIO_BILINGUAL_CHANNEL_SELECT:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001811 return ivtv_decoder_ioctls(file, cmd, (void *)arg);
1812
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001813 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -03001814 return -EINVAL;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001815 }
1816 return 0;
1817}
1818
Hans Verkuil09882f02008-10-18 13:42:24 -03001819static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
Hans Verkuilbaa40722007-08-19 07:10:55 -03001820 unsigned int cmd, unsigned long arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001821{
Hans Verkuil37f89f92008-06-22 11:57:31 -03001822 struct video_device *vfd = video_devdata(filp);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001823 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
Hans Verkuil09882f02008-10-18 13:42:24 -03001824 long ret;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001825
Hans Verkuil3f038d82008-05-29 16:43:54 -03001826 /* check priority */
1827 switch (cmd) {
1828 case VIDIOC_S_CTRL:
1829 case VIDIOC_S_STD:
1830 case VIDIOC_S_INPUT:
1831 case VIDIOC_S_OUTPUT:
1832 case VIDIOC_S_TUNER:
1833 case VIDIOC_S_FREQUENCY:
1834 case VIDIOC_S_FMT:
1835 case VIDIOC_S_CROP:
1836 case VIDIOC_S_AUDIO:
1837 case VIDIOC_S_AUDOUT:
1838 case VIDIOC_S_EXT_CTRLS:
1839 case VIDIOC_S_FBUF:
1840 case VIDIOC_OVERLAY:
1841 ret = v4l2_prio_check(&itv->prio, &id->prio);
1842 if (ret)
1843 return ret;
1844 }
1845
Hans Verkuil37f89f92008-06-22 11:57:31 -03001846 if (ivtv_debug & IVTV_DBGFLG_IOCTL)
1847 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Hans Verkuilbec43662008-12-30 06:58:20 -03001848 ret = video_ioctl2(filp, cmd, arg);
Hans Verkuil37f89f92008-06-22 11:57:31 -03001849 vfd->debug = 0;
1850 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001851}
Hans Verkuilbaa40722007-08-19 07:10:55 -03001852
Hans Verkuil09882f02008-10-18 13:42:24 -03001853long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Hans Verkuilbaa40722007-08-19 07:10:55 -03001854{
1855 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1856 struct ivtv *itv = id->itv;
Hans Verkuil09882f02008-10-18 13:42:24 -03001857 long res;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001858
1859 mutex_lock(&itv->serialize_lock);
Hans Verkuil09882f02008-10-18 13:42:24 -03001860 res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001861 mutex_unlock(&itv->serialize_lock);
1862 return res;
1863}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001864
Hans Verkuila3998102008-07-21 02:57:38 -03001865static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1866 .vidioc_querycap = ivtv_querycap,
1867 .vidioc_g_priority = ivtv_g_priority,
1868 .vidioc_s_priority = ivtv_s_priority,
1869 .vidioc_s_audio = ivtv_s_audio,
1870 .vidioc_g_audio = ivtv_g_audio,
1871 .vidioc_enumaudio = ivtv_enumaudio,
1872 .vidioc_s_audout = ivtv_s_audout,
1873 .vidioc_g_audout = ivtv_g_audout,
1874 .vidioc_enum_input = ivtv_enum_input,
1875 .vidioc_enum_output = ivtv_enum_output,
1876 .vidioc_enumaudout = ivtv_enumaudout,
1877 .vidioc_cropcap = ivtv_cropcap,
1878 .vidioc_s_crop = ivtv_s_crop,
1879 .vidioc_g_crop = ivtv_g_crop,
1880 .vidioc_g_input = ivtv_g_input,
1881 .vidioc_s_input = ivtv_s_input,
1882 .vidioc_g_output = ivtv_g_output,
1883 .vidioc_s_output = ivtv_s_output,
1884 .vidioc_g_frequency = ivtv_g_frequency,
1885 .vidioc_s_frequency = ivtv_s_frequency,
1886 .vidioc_s_tuner = ivtv_s_tuner,
1887 .vidioc_g_tuner = ivtv_g_tuner,
1888 .vidioc_g_enc_index = ivtv_g_enc_index,
1889 .vidioc_g_fbuf = ivtv_g_fbuf,
1890 .vidioc_s_fbuf = ivtv_s_fbuf,
1891 .vidioc_g_std = ivtv_g_std,
1892 .vidioc_s_std = ivtv_s_std,
1893 .vidioc_overlay = ivtv_overlay,
1894 .vidioc_log_status = ivtv_log_status,
1895 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1896 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1897 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
1898 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1899 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1900 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1901 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1902 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1903 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1904 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1905 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1906 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1907 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1908 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1909 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1910 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1911 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1912 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1913 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1914 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1915 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1916 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1917 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1918 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1919#ifdef CONFIG_VIDEO_ADV_DEBUG
1920 .vidioc_g_register = ivtv_g_register,
1921 .vidioc_s_register = ivtv_s_register,
1922#endif
1923 .vidioc_default = ivtv_default,
1924 .vidioc_queryctrl = ivtv_queryctrl,
1925 .vidioc_querymenu = ivtv_querymenu,
1926 .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls,
1927 .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls,
1928 .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls,
1929};
1930
Hans Verkuil3f038d82008-05-29 16:43:54 -03001931void ivtv_set_funcs(struct video_device *vdev)
1932{
Hans Verkuila3998102008-07-21 02:57:38 -03001933 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001934}