blob: 7a8b0d0b6127aefbc1281e30108c2ef1050e9e79 [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>
Hans Verkuil09250192010-03-27 14:10:13 -030038#include <media/v4l2-event.h>
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030039#include <linux/dvb/audio.h>
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030040
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];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300138 int single_step = (speed == 1 || speed == -1);
139 DEFINE_WAIT(wait);
140
141 if (speed == 0) speed = 1000;
142
143 /* No change? */
144 if (speed == itv->speed && !single_step)
145 return 0;
146
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300147 if (single_step && (speed < 0) == (itv->speed < 0)) {
148 /* Single step video and no need to change direction */
149 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
150 itv->speed = speed;
151 return 0;
152 }
153 if (single_step)
154 /* Need to change direction */
155 speed = speed < 0 ? -1000 : 1000;
156
157 data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
158 data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
159 data[1] = (speed < 0);
160 data[2] = speed < 0 ? 3 : 7;
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300161 data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300162 data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
163 data[5] = 0;
164 data[6] = 0;
165
166 if (speed == 1500 || speed == -1500) data[0] |= 1;
167 else if (speed == 2000 || speed == -2000) data[0] |= 2;
168 else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
169 else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
170
171 /* If not decoding, just change speed setting */
172 if (atomic_read(&itv->decoding) > 0) {
173 int got_sig = 0;
174
175 /* Stop all DMA and decoding activity */
176 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
177
178 /* Wait for any DMA to finish */
Hans Verkuilcdc03782011-10-11 06:06:58 -0300179 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300180 prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a42009-05-02 11:10:23 -0300181 while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300182 got_sig = signal_pending(current);
183 if (got_sig)
184 break;
185 got_sig = 0;
186 schedule();
187 }
188 finish_wait(&itv->dma_waitq, &wait);
Hans Verkuilcdc03782011-10-11 06:06:58 -0300189 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300190 if (got_sig)
191 return -EINTR;
192
193 /* Change Speed safely */
194 ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
195 IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
196 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
197 }
198 if (single_step) {
199 speed = (speed < 0) ? -1 : 1;
200 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
201 }
202 itv->speed = speed;
203 return 0;
204}
205
206static int ivtv_validate_speed(int cur_speed, int new_speed)
207{
208 int fact = new_speed < 0 ? -1 : 1;
209 int s;
210
Hans Verkuil94dee762008-04-26 09:26:13 -0300211 if (cur_speed == 0)
212 cur_speed = 1000;
213 if (new_speed < 0)
214 new_speed = -new_speed;
215 if (cur_speed < 0)
216 cur_speed = -cur_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300217
218 if (cur_speed <= new_speed) {
Hans Verkuil94dee762008-04-26 09:26:13 -0300219 if (new_speed > 1500)
220 return fact * 2000;
221 if (new_speed > 1000)
222 return fact * 1500;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300223 }
224 else {
Hans Verkuil94dee762008-04-26 09:26:13 -0300225 if (new_speed >= 2000)
226 return fact * 2000;
227 if (new_speed >= 1500)
228 return fact * 1500;
229 if (new_speed >= 1000)
230 return fact * 1000;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300231 }
Hans Verkuil94dee762008-04-26 09:26:13 -0300232 if (new_speed == 0)
233 return 1000;
234 if (new_speed == 1 || new_speed == 1000)
235 return fact * new_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300236
237 s = new_speed;
238 new_speed = 1000 / new_speed;
239 if (1000 / cur_speed == new_speed)
240 new_speed += (cur_speed < s) ? -1 : 1;
241 if (new_speed > 60) return 1000 / (fact * 60);
242 return 1000 / (fact * new_speed);
243}
244
245static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
Hans Verkuilda8ec562011-11-24 09:58:53 -0300246 struct v4l2_decoder_cmd *dc, int try)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300247{
248 struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
249
250 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
251 return -EINVAL;
252
Hans Verkuilda8ec562011-11-24 09:58:53 -0300253 switch (dc->cmd) {
254 case V4L2_DEC_CMD_START: {
255 dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
256 dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
257 if (dc->start.speed < 0)
258 dc->start.format = V4L2_DEC_START_FMT_GOP;
259 else
260 dc->start.format = V4L2_DEC_START_FMT_NONE;
261 if (dc->start.speed != 500 && dc->start.speed != 1500)
262 dc->flags = dc->start.speed == 1000 ? 0 :
263 V4L2_DEC_CMD_START_MUTE_AUDIO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300264 if (try) break;
265
Hans Verkuilda8ec562011-11-24 09:58:53 -0300266 itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300267 if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
268 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300269 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
270 /* forces ivtv_set_speed to be called */
271 itv->speed = 0;
272 }
Hans Verkuilda8ec562011-11-24 09:58:53 -0300273 return ivtv_start_decoding(id, dc->start.speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300274 }
275
Hans Verkuilda8ec562011-11-24 09:58:53 -0300276 case V4L2_DEC_CMD_STOP:
277 dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
278 if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
279 dc->stop.pts = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300280 if (try) break;
281 if (atomic_read(&itv->decoding) == 0)
282 return 0;
283 if (itv->output_mode != OUT_MPG)
284 return -EBUSY;
285
286 itv->output_mode = OUT_NONE;
Hans Verkuilda8ec562011-11-24 09:58:53 -0300287 return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300288
Hans Verkuilda8ec562011-11-24 09:58:53 -0300289 case V4L2_DEC_CMD_PAUSE:
290 dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300291 if (try) break;
Hans Verkuil1a806402012-09-05 08:39:48 -0300292 if (!atomic_read(&itv->decoding))
293 return -EPERM;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300294 if (itv->output_mode != OUT_MPG)
295 return -EBUSY;
296 if (atomic_read(&itv->decoding) > 0) {
297 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
Hans Verkuilda8ec562011-11-24 09:58:53 -0300298 (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
Hans Verkuilac425142007-07-22 08:46:38 -0300299 set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300300 }
301 break;
302
Hans Verkuilda8ec562011-11-24 09:58:53 -0300303 case V4L2_DEC_CMD_RESUME:
304 dc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300305 if (try) break;
Hans Verkuil1a806402012-09-05 08:39:48 -0300306 if (!atomic_read(&itv->decoding))
307 return -EPERM;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300308 if (itv->output_mode != OUT_MPG)
309 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300310 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
311 int speed = itv->speed;
312 itv->speed = 0;
313 return ivtv_start_decoding(id, speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300314 }
315 break;
316
317 default:
318 return -EINVAL;
319 }
320 return 0;
321}
322
Hans Verkuil3f038d82008-05-29 16:43:54 -0300323static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300324{
Hans Verkuil2f824412011-03-12 06:43:28 -0300325 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300326 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300327
Hans Verkuile88360c2008-06-21 08:00:56 -0300328 vbifmt->reserved[0] = 0;
329 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300330 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300331 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300332 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil30634e82012-09-05 10:38:10 -0300333 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
Hans Verkuil3f038d82008-05-29 16:43:54 -0300334 if (itv->is_60hz) {
335 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
336 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
337 } else {
338 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
339 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
340 }
341 vbifmt->service_set = ivtv_get_service_set(vbifmt);
342 return 0;
343}
344
345static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
346{
Hans Verkuil2f824412011-03-12 06:43:28 -0300347 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300348 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300349 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300350
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300351 pixfmt->width = itv->cxhdl.width;
352 pixfmt->height = itv->cxhdl.height;
Hans Verkuile88360c2008-06-21 08:00:56 -0300353 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
354 pixfmt->field = V4L2_FIELD_INTERLACED;
355 pixfmt->priv = 0;
356 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
357 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
Hans Verkuila4a78712009-02-06 15:31:59 -0300358 /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
359 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
Hans Verkuile88360c2008-06-21 08:00:56 -0300360 pixfmt->bytesperline = 720;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300361 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300362 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
363 pixfmt->sizeimage = 128 * 1024;
364 pixfmt->bytesperline = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300365 }
366 return 0;
367}
368
Hans Verkuil3f038d82008-05-29 16:43:54 -0300369static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300370{
Hans Verkuil2f824412011-03-12 06:43:28 -0300371 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300372 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300373
Hans Verkuile88360c2008-06-21 08:00:56 -0300374 vbifmt->sampling_rate = 27000000;
375 vbifmt->offset = 248;
376 vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
377 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
378 vbifmt->start[0] = itv->vbi.start[0];
379 vbifmt->start[1] = itv->vbi.start[1];
380 vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
381 vbifmt->flags = 0;
382 vbifmt->reserved[0] = 0;
383 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300384 return 0;
385}
386
387static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
388{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300389 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300390 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300391 struct ivtv *itv = id->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300392
Hans Verkuile88360c2008-06-21 08:00:56 -0300393 vbifmt->reserved[0] = 0;
394 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300395 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300396
Hans Verkuil3f038d82008-05-29 16:43:54 -0300397 if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
398 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
399 V4L2_SLICED_VBI_525;
400 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuilc5c46f22012-09-05 12:27:19 -0300401 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300402 return 0;
403 }
404
Hans Verkuil4ff07902010-03-14 12:18:18 -0300405 v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300406 vbifmt->service_set = ivtv_get_service_set(vbifmt);
407 return 0;
408}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300409
Hans Verkuil3f038d82008-05-29 16:43:54 -0300410static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
411{
Hans Verkuil2f824412011-03-12 06:43:28 -0300412 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300413 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300414 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300415
Hans Verkuil3f038d82008-05-29 16:43:54 -0300416 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300417 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300418 pixfmt->width = itv->main_rect.width;
419 pixfmt->height = itv->main_rect.height;
420 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
421 pixfmt->field = V4L2_FIELD_INTERLACED;
422 pixfmt->priv = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300423 if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
424 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
425 case IVTV_YUV_MODE_INTERLACED:
Hans Verkuile88360c2008-06-21 08:00:56 -0300426 pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
Hans Verkuil3f038d82008-05-29 16:43:54 -0300427 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
428 break;
429 case IVTV_YUV_MODE_PROGRESSIVE:
Hans Verkuile88360c2008-06-21 08:00:56 -0300430 pixfmt->field = V4L2_FIELD_NONE;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300431 break;
432 default:
Hans Verkuile88360c2008-06-21 08:00:56 -0300433 pixfmt->field = V4L2_FIELD_ANY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300434 break;
435 }
Hans Verkuile88360c2008-06-21 08:00:56 -0300436 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
437 pixfmt->bytesperline = 720;
438 pixfmt->width = itv->yuv_info.v4l2_src_w;
439 pixfmt->height = itv->yuv_info.v4l2_src_h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300440 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
Hans Verkuile88360c2008-06-21 08:00:56 -0300441 pixfmt->sizeimage =
442 1080 * ((pixfmt->height + 31) & ~31);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300443 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300444 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
445 pixfmt->sizeimage = 128 * 1024;
446 pixfmt->bytesperline = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300447 }
448 return 0;
449}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300450
Hans Verkuil3f038d82008-05-29 16:43:54 -0300451static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
452{
Hans Verkuil2f824412011-03-12 06:43:28 -0300453 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300454 struct v4l2_window *winfmt = &fmt->fmt.win;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300455
456 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
457 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300458 winfmt->chromakey = itv->osd_chroma_key;
459 winfmt->global_alpha = itv->osd_global_alpha;
460 winfmt->field = V4L2_FIELD_INTERLACED;
461 winfmt->clips = NULL;
462 winfmt->clipcount = 0;
463 winfmt->bitmap = NULL;
464 winfmt->w.top = winfmt->w.left = 0;
465 winfmt->w.width = itv->osd_rect.width;
466 winfmt->w.height = itv->osd_rect.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300467 return 0;
468}
469
470static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
471{
472 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
473}
474
475static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
476{
Hans Verkuil2f824412011-03-12 06:43:28 -0300477 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300478 struct ivtv *itv = id->itv;
479 int w = fmt->fmt.pix.width;
480 int h = fmt->fmt.pix.height;
Hans Verkuila4a78712009-02-06 15:31:59 -0300481 int min_h = 2;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300482
483 w = min(w, 720);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300484 w = max(w, 2);
Hans Verkuila4a78712009-02-06 15:31:59 -0300485 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
486 /* YUV height must be a multiple of 32 */
487 h &= ~0x1f;
488 min_h = 32;
489 }
Hans Verkuil3f038d82008-05-29 16:43:54 -0300490 h = min(h, itv->is_50hz ? 576 : 480);
Hans Verkuila4a78712009-02-06 15:31:59 -0300491 h = max(h, min_h);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300492 ivtv_g_fmt_vid_cap(file, fh, fmt);
493 fmt->fmt.pix.width = w;
494 fmt->fmt.pix.height = h;
495 return 0;
496}
497
498static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
499{
500 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
501}
502
503static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
504{
505 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300506 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300507 struct ivtv *itv = id->itv;
508
509 if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
510 return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300511
512 /* set sliced VBI capture format */
513 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuile88360c2008-06-21 08:00:56 -0300514 vbifmt->reserved[0] = 0;
515 vbifmt->reserved[1] = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300516
517 if (vbifmt->service_set)
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300518 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300519 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300520 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300521 return 0;
522}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300523
Hans Verkuil3f038d82008-05-29 16:43:54 -0300524static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
525{
Hans Verkuil2f824412011-03-12 06:43:28 -0300526 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuileffc3462008-09-06 08:24:37 -0300527 s32 w = fmt->fmt.pix.width;
528 s32 h = fmt->fmt.pix.height;
529 int field = fmt->fmt.pix.field;
530 int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300531
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300532 w = min(w, 720);
533 w = max(w, 2);
Hans Verkuil962d6992008-10-11 09:00:39 -0300534 /* Why can the height be 576 even when the output is NTSC?
535
536 Internally the buffers of the PVR350 are always set to 720x576. The
537 decoded video frame will always be placed in the top left corner of
538 this buffer. For any video which is not 720x576, the buffer will
539 then be cropped to remove the unused right and lower areas, with
540 the remaining image being scaled by the hardware to fit the display
541 area. The video can be scaled both up and down, so a 720x480 video
542 can be displayed full-screen on PAL and a 720x576 video can be
543 displayed without cropping on NTSC.
544
545 Note that the scaling only occurs on the video stream, the osd
546 resolution is locked to the broadcast standard and not scaled.
547
548 Thanks to Ian Armstrong for this explanation. */
549 h = min(h, 576);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300550 h = max(h, 2);
551 if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300552 fmt->fmt.pix.field = field;
Hans Verkuileffc3462008-09-06 08:24:37 -0300553 fmt->fmt.pix.width = w;
554 fmt->fmt.pix.height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300555 return ret;
556}
557
558static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
559{
Hans Verkuil2f824412011-03-12 06:43:28 -0300560 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300561 u32 chromakey = fmt->fmt.win.chromakey;
562 u8 global_alpha = fmt->fmt.win.global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300563
564 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
565 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300566 ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
567 fmt->fmt.win.chromakey = chromakey;
568 fmt->fmt.win.global_alpha = global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300569 return 0;
570}
571
572static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
573{
574 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
575}
576
577static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
578{
Hans Verkuil2f824412011-03-12 06:43:28 -0300579 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300580 struct ivtv *itv = id->itv;
Hans Verkuil475977a2010-05-08 16:28:51 -0300581 struct v4l2_mbus_framefmt mbus_fmt;
Hans Verkuileffc3462008-09-06 08:24:37 -0300582 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300583 int w = fmt->fmt.pix.width;
584 int h = fmt->fmt.pix.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300585
586 if (ret)
587 return ret;
588
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300589 if (itv->cxhdl.width == w && itv->cxhdl.height == h)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300590 return 0;
591
592 if (atomic_read(&itv->capturing) > 0)
593 return -EBUSY;
594
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300595 itv->cxhdl.width = w;
596 itv->cxhdl.height = h;
597 if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300598 fmt->fmt.pix.width /= 2;
Hans Verkuil475977a2010-05-08 16:28:51 -0300599 mbus_fmt.width = fmt->fmt.pix.width;
600 mbus_fmt.height = h;
601 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
602 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300603 return ivtv_g_fmt_vid_cap(file, fh, fmt);
604}
605
606static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
607{
Hans Verkuil2f824412011-03-12 06:43:28 -0300608 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300609
Hans Verkuila8b86432008-10-04 08:05:30 -0300610 if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
611 return -EBUSY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300612 itv->vbi.sliced_in->service_set = 0;
Hans Verkuila8b86432008-10-04 08:05:30 -0300613 itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
Hans Verkuil4ff07902010-03-14 12:18:18 -0300614 v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300615 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
616}
617
618static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
619{
620 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300621 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300622 struct ivtv *itv = id->itv;
623 int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
624
625 if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
626 return ret;
627
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300628 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuila8b86432008-10-04 08:05:30 -0300629 if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300630 return -EBUSY;
Hans Verkuila8b86432008-10-04 08:05:30 -0300631 itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
Hans Verkuil4ff07902010-03-14 12:18:18 -0300632 v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300633 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
634 return 0;
635}
636
Hans Verkuil3f038d82008-05-29 16:43:54 -0300637static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300638{
Hans Verkuil2f824412011-03-12 06:43:28 -0300639 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300640 struct ivtv *itv = id->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300641 struct yuv_playback_info *yi = &itv->yuv_info;
642 int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300643
Hans Verkuil3f038d82008-05-29 16:43:54 -0300644 if (ret)
645 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300646
Hans Verkuil3f038d82008-05-29 16:43:54 -0300647 if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
648 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300649
Hans Verkuil3f038d82008-05-29 16:43:54 -0300650 /* Return now if we already have some frame data */
651 if (yi->stream_size)
652 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300653
Hans Verkuil3f038d82008-05-29 16:43:54 -0300654 yi->v4l2_src_w = fmt->fmt.pix.width;
655 yi->v4l2_src_h = fmt->fmt.pix.height;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300656
Hans Verkuil3f038d82008-05-29 16:43:54 -0300657 switch (fmt->fmt.pix.field) {
658 case V4L2_FIELD_NONE:
659 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300660 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300661 case V4L2_FIELD_ANY:
662 yi->lace_mode = IVTV_YUV_MODE_AUTO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300663 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300664 case V4L2_FIELD_INTERLACED_BT:
665 yi->lace_mode =
666 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
667 break;
668 case V4L2_FIELD_INTERLACED_TB:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300669 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -0300670 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
671 break;
672 }
673 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
674
675 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
676 itv->dma_data_req_size =
677 1080 * ((yi->v4l2_src_h + 31) & ~31);
678
Hans Verkuil3f038d82008-05-29 16:43:54 -0300679 return 0;
680}
681
682static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
683{
Hans Verkuil2f824412011-03-12 06:43:28 -0300684 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300685 int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
686
687 if (ret == 0) {
688 itv->osd_chroma_key = fmt->fmt.win.chromakey;
689 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
690 ivtv_set_osd_alpha(itv);
691 }
692 return ret;
693}
694
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300695static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300696{
Hans Verkuil2f824412011-03-12 06:43:28 -0300697 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300698
699 chip->ident = V4L2_IDENT_NONE;
700 chip->revision = 0;
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300701 if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
702 if (v4l2_chip_match_host(&chip->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300703 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
704 return 0;
705 }
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300706 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
707 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300708 return -EINVAL;
709 /* TODO: is this correct? */
710 return ivtv_call_all_err(itv, core, g_chip_ident, chip);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300711}
712
Hans Verkuil36ecd492008-06-25 06:00:17 -0300713#ifdef CONFIG_VIDEO_ADV_DEBUG
714static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
715{
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300716 struct v4l2_dbg_register *regs = arg;
Hans Verkuiladb65bc2008-06-25 06:32:44 -0300717 volatile u8 __iomem *reg_start;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300718
719 if (!capable(CAP_SYS_ADMIN))
720 return -EPERM;
721 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
722 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
723 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
724 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
725 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
Roel Kluin223ffe52009-05-02 16:38:47 -0300726 else if (regs->reg < IVTV_ENCODER_SIZE)
Hans Verkuil36ecd492008-06-25 06:00:17 -0300727 reg_start = itv->enc_mem;
728 else
729 return -EINVAL;
730
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300731 regs->size = 4;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300732 if (cmd == VIDIOC_DBG_G_REGISTER)
733 regs->val = readl(regs->reg + reg_start);
734 else
735 writel(regs->val, regs->reg + reg_start);
Hans Verkuil36ecd492008-06-25 06:00:17 -0300736 return 0;
737}
738
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300739static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300740{
Hans Verkuil2f824412011-03-12 06:43:28 -0300741 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300742
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300743 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300744 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300745 /* TODO: subdev errors should not be ignored, this should become a
746 subdev helper function. */
747 ivtv_call_all(itv, core, g_register, reg);
748 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300749}
750
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300751static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300752{
Hans Verkuil2f824412011-03-12 06:43:28 -0300753 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300754
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300755 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300756 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300757 /* TODO: subdev errors should not be ignored, this should become a
758 subdev helper function. */
759 ivtv_call_all(itv, core, s_register, reg);
760 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300761}
Hans Verkuil36ecd492008-06-25 06:00:17 -0300762#endif
Hans Verkuil3f038d82008-05-29 16:43:54 -0300763
Hans Verkuil3f038d82008-05-29 16:43:54 -0300764static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
765{
Hans Verkuild0c8b2d2011-11-07 07:25:10 -0300766 struct ivtv_open_id *id = fh2id(file->private_data);
767 struct ivtv *itv = id->itv;
768 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -0300769
Hans Verkuil3f038d82008-05-29 16:43:54 -0300770 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
771 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
Hans Verkuil8ac05ae2009-02-07 07:02:27 -0300772 snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
Hans Verkuild0c8b2d2011-11-07 07:25:10 -0300773 vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
774 vcap->device_caps = s->caps;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300775 return 0;
776}
777
778static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
779{
Hans Verkuil2f824412011-03-12 06:43:28 -0300780 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300781
782 return ivtv_get_audio_input(itv, vin->index, vin);
783}
784
785static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
786{
Hans Verkuil2f824412011-03-12 06:43:28 -0300787 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300788
789 vin->index = itv->audio_input;
790 return ivtv_get_audio_input(itv, vin->index, vin);
791}
792
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300793static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300794{
Hans Verkuil2f824412011-03-12 06:43:28 -0300795 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300796
797 if (vout->index >= itv->nof_audio_inputs)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300798 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300799
800 itv->audio_input = vout->index;
801 ivtv_audio_set_io(itv);
802
803 return 0;
804}
805
806static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
807{
Hans Verkuil2f824412011-03-12 06:43:28 -0300808 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300809
810 /* set it to defaults from our table */
811 return ivtv_get_audio_output(itv, vin->index, vin);
812}
813
814static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
815{
Hans Verkuil2f824412011-03-12 06:43:28 -0300816 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300817
818 vin->index = 0;
819 return ivtv_get_audio_output(itv, vin->index, vin);
820}
821
Hans Verkuilba9425b2012-09-04 12:03:49 -0300822static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300823{
Hans Verkuil2f824412011-03-12 06:43:28 -0300824 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300825
Hans Verkuilba9425b2012-09-04 12:03:49 -0300826 if (itv->card->video_outputs == NULL || vout->index != 0)
827 return -EINVAL;
828 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300829}
830
831static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
832{
Hans Verkuil2f824412011-03-12 06:43:28 -0300833 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300834
835 /* set it to defaults from our table */
836 return ivtv_get_input(itv, vin->index, vin);
837}
838
839static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
840{
Hans Verkuil2f824412011-03-12 06:43:28 -0300841 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300842
843 return ivtv_get_output(itv, vout->index, vout);
844}
845
846static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
847{
Hans Verkuil2f824412011-03-12 06:43:28 -0300848 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300849 struct ivtv *itv = id->itv;
850 struct yuv_playback_info *yi = &itv->yuv_info;
851 int streamtype;
852
853 streamtype = id->type;
854
855 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
856 return -EINVAL;
857 cropcap->bounds.top = cropcap->bounds.left = 0;
858 cropcap->bounds.width = 720;
859 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
860 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
861 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
862 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
863 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
864 if (yi->track_osd) {
865 cropcap->bounds.width = yi->osd_full_w;
866 cropcap->bounds.height = yi->osd_full_h;
867 } else {
868 cropcap->bounds.width = 720;
869 cropcap->bounds.height =
870 itv->is_out_50hz ? 576 : 480;
871 }
872 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
873 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
874 } else {
875 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
876 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
877 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
878 }
879 cropcap->defrect = cropcap->bounds;
880 return 0;
881}
882
Hans Verkuil4f996592012-09-05 05:10:48 -0300883static int ivtv_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300884{
Hans Verkuil2f824412011-03-12 06:43:28 -0300885 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300886 struct ivtv *itv = id->itv;
887 struct yuv_playback_info *yi = &itv->yuv_info;
888 int streamtype;
889
890 streamtype = id->type;
891
Hans Verkuil3f038d82008-05-29 16:43:54 -0300892 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
893 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
894 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
895 yi->main_rect = crop->c;
896 return 0;
897 } else {
898 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
899 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
900 itv->main_rect = crop->c;
901 return 0;
902 }
903 }
904 return -EINVAL;
905 }
906 return -EINVAL;
907}
908
909static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
910{
Hans Verkuil2f824412011-03-12 06:43:28 -0300911 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300912 struct ivtv *itv = id->itv;
913 struct yuv_playback_info *yi = &itv->yuv_info;
914 int streamtype;
915
916 streamtype = id->type;
917
918 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
919 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
920 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
921 crop->c = yi->main_rect;
922 else
923 crop->c = itv->main_rect;
924 return 0;
925 }
926 return -EINVAL;
927}
928
929static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
930{
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300931 static const struct v4l2_fmtdesc hm12 = {
932 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
933 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
934 { 0, 0, 0, 0 }
Hans Verkuil3f038d82008-05-29 16:43:54 -0300935 };
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300936 static const struct v4l2_fmtdesc mpeg = {
937 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
938 "MPEG", V4L2_PIX_FMT_MPEG,
939 { 0, 0, 0, 0 }
940 };
941 struct ivtv *itv = fh2id(fh)->itv;
942 struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -0300943
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300944 if (fmt->index)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300945 return -EINVAL;
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300946 if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
947 *fmt = mpeg;
948 else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
949 *fmt = hm12;
950 else
951 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300952 return 0;
953}
954
955static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
956{
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300957 static const struct v4l2_fmtdesc hm12 = {
958 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0,
959 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
960 { 0, 0, 0, 0 }
Hans Verkuil3f038d82008-05-29 16:43:54 -0300961 };
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300962 static const struct v4l2_fmtdesc mpeg = {
963 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_FMT_FLAG_COMPRESSED,
964 "MPEG", V4L2_PIX_FMT_MPEG,
965 { 0, 0, 0, 0 }
966 };
967 struct ivtv *itv = fh2id(fh)->itv;
968 struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -0300969
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300970 if (fmt->index)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300971 return -EINVAL;
Hans Verkuilbfd063c2012-10-01 07:22:06 -0300972 if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
973 *fmt = mpeg;
974 else if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
975 *fmt = hm12;
976 else
Hans Verkuil3f038d82008-05-29 16:43:54 -0300977 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300978 return 0;
979}
980
981static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
982{
Hans Verkuil2f824412011-03-12 06:43:28 -0300983 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300984
985 *i = itv->active_input;
986
987 return 0;
988}
989
990int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
991{
Hans Verkuil2f824412011-03-12 06:43:28 -0300992 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuilf659f0e72012-09-05 08:56:55 -0300993 v4l2_std_id std;
994 int i;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300995
Mauro Carvalho Chehabd6eb0b92012-10-27 12:52:19 -0300996 if (inp >= itv->nof_inputs)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300997 return -EINVAL;
998
999 if (inp == itv->active_input) {
1000 IVTV_DEBUG_INFO("Input unchanged\n");
1001 return 0;
1002 }
1003
1004 if (atomic_read(&itv->capturing) > 0) {
1005 return -EBUSY;
1006 }
1007
1008 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
1009 itv->active_input, inp);
1010
1011 itv->active_input = inp;
1012 /* Set the audio input to whatever is appropriate for the
1013 input type. */
1014 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1015
Hans Verkuilf659f0e72012-09-05 08:56:55 -03001016 if (itv->card->video_inputs[inp].video_type == IVTV_CARD_INPUT_VID_TUNER)
1017 std = itv->tuner_std;
1018 else
1019 std = V4L2_STD_ALL;
1020 for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++)
1021 itv->streams[i].vdev->tvnorms = std;
1022
Hans Verkuil3f038d82008-05-29 16:43:54 -03001023 /* prevent others from messing with the streams until
1024 we're finished changing inputs. */
1025 ivtv_mute(itv);
1026 ivtv_video_set_io(itv);
1027 ivtv_audio_set_io(itv);
1028 ivtv_unmute(itv);
1029
1030 return 0;
1031}
1032
1033static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1034{
Hans Verkuil2f824412011-03-12 06:43:28 -03001035 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001036
1037 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1038 return -EINVAL;
1039
1040 *i = itv->active_output;
1041
1042 return 0;
1043}
1044
1045static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1046{
Hans Verkuil2f824412011-03-12 06:43:28 -03001047 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001048
1049 if (outp >= itv->card->nof_outputs)
1050 return -EINVAL;
1051
1052 if (outp == itv->active_output) {
1053 IVTV_DEBUG_INFO("Output unchanged\n");
1054 return 0;
1055 }
1056 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1057 itv->active_output, outp);
1058
1059 itv->active_output = outp;
Hans Verkuil5325b422009-04-02 11:26:22 -03001060 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
1061 SAA7127_INPUT_TYPE_NORMAL,
1062 itv->card->video_outputs[outp].video_output, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001063
1064 return 0;
1065}
1066
1067static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1068{
Hans Verkuil2f824412011-03-12 06:43:28 -03001069 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuildff274f2012-10-01 06:45:36 -03001070 struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001071
Hans Verkuildff274f2012-10-01 06:45:36 -03001072 if (s->vdev->vfl_dir)
1073 return -ENOTTY;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001074 if (vf->tuner != 0)
1075 return -EINVAL;
1076
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001077 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001078 return 0;
1079}
1080
1081int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1082{
Hans Verkuil2f824412011-03-12 06:43:28 -03001083 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuildff274f2012-10-01 06:45:36 -03001084 struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001085
Hans Verkuildff274f2012-10-01 06:45:36 -03001086 if (s->vdev->vfl_dir)
1087 return -ENOTTY;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001088 if (vf->tuner != 0)
1089 return -EINVAL;
1090
1091 ivtv_mute(itv);
1092 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001093 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001094 ivtv_unmute(itv);
1095 return 0;
1096}
1097
1098static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1099{
Hans Verkuil2f824412011-03-12 06:43:28 -03001100 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001101
1102 *std = itv->std;
1103 return 0;
1104}
1105
Ian Armstrongc5874c92011-05-29 21:33:17 -03001106void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001107{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001108 itv->std = *std;
1109 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
Hans Verkuilf7b80e62010-06-27 06:07:26 -03001110 itv->is_50hz = !itv->is_60hz;
1111 cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
1112 itv->cxhdl.width = 720;
1113 itv->cxhdl.height = itv->is_50hz ? 576 : 480;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001114 itv->vbi.count = itv->is_50hz ? 18 : 12;
1115 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1116 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1117
1118 if (itv->hw_flags & IVTV_HW_CX25840)
1119 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1120
Hans Verkuil3f038d82008-05-29 16:43:54 -03001121 /* Tuner */
Hans Verkuilf41737e2009-04-01 03:52:39 -03001122 ivtv_call_all(itv, core, s_std, itv->std);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001123}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001124
Ian Armstrongc5874c92011-05-29 21:33:17 -03001125void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
1126{
1127 struct yuv_playback_info *yi = &itv->yuv_info;
1128 DEFINE_WAIT(wait);
1129 int f;
Ian Armstrong2443bae2010-03-13 20:22:34 -03001130
Ian Armstrongc5874c92011-05-29 21:33:17 -03001131 /* set display standard */
1132 itv->std_out = *std;
1133 itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1134 itv->is_out_50hz = !itv->is_out_60hz;
1135 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Ian Armstrong2443bae2010-03-13 20:22:34 -03001136
Ian Armstrongc5874c92011-05-29 21:33:17 -03001137 /*
1138 * The next firmware call is time sensitive. Time it to
1139 * avoid risk of a hard lock, by trying to ensure the call
1140 * happens within the first 100 lines of the top field.
1141 * Make 4 attempts to sync to the decoder before giving up.
1142 */
Hans Verkuilcdc03782011-10-11 06:06:58 -03001143 mutex_unlock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001144 for (f = 0; f < 4; f++) {
1145 prepare_to_wait(&itv->vsync_waitq, &wait,
1146 TASK_UNINTERRUPTIBLE);
1147 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
1148 break;
1149 schedule_timeout(msecs_to_jiffies(25));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001150 }
Ian Armstrongc5874c92011-05-29 21:33:17 -03001151 finish_wait(&itv->vsync_waitq, &wait);
Hans Verkuilcdc03782011-10-11 06:06:58 -03001152 mutex_lock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001153
1154 if (f == 4)
1155 IVTV_WARN("Mode change failed to sync to decoder\n");
1156
1157 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1158 itv->main_rect.left = 0;
1159 itv->main_rect.top = 0;
1160 itv->main_rect.width = 720;
1161 itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
1162 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1163 720, itv->main_rect.height, 0, 0);
1164 yi->main_rect = itv->main_rect;
1165 if (!itv->osd_info) {
1166 yi->osd_full_w = 720;
1167 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1168 }
1169}
1170
Mauro Carvalho Chehab2aebbf62012-10-27 12:51:29 -03001171static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
Ian Armstrongc5874c92011-05-29 21:33:17 -03001172{
1173 struct ivtv *itv = fh2id(fh)->itv;
1174
1175 if ((*std & V4L2_STD_ALL) == 0)
1176 return -EINVAL;
1177
1178 if (*std == itv->std)
1179 return 0;
1180
1181 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1182 atomic_read(&itv->capturing) > 0 ||
1183 atomic_read(&itv->decoding) > 0) {
1184 /* Switching standard would mess with already running
1185 streams, prevent that by returning EBUSY. */
1186 return -EBUSY;
1187 }
1188
1189 IVTV_DEBUG_INFO("Switching standard to %llx.\n",
1190 (unsigned long long)itv->std);
1191
1192 ivtv_s_std_enc(itv, std);
1193 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
1194 ivtv_s_std_dec(itv, std);
1195
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001196 return 0;
1197}
1198
Hans Verkuil3f038d82008-05-29 16:43:54 -03001199static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001200{
Hans Verkuil2f824412011-03-12 06:43:28 -03001201 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001202 struct ivtv *itv = id->itv;
1203
1204 if (vt->index != 0)
1205 return -EINVAL;
1206
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001207 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001208
1209 return 0;
1210}
1211
1212static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1213{
Hans Verkuil2f824412011-03-12 06:43:28 -03001214 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001215
1216 if (vt->index != 0)
1217 return -EINVAL;
1218
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001219 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001220
Hans Verkuild118e292011-06-25 10:28:21 -03001221 if (vt->type == V4L2_TUNER_RADIO)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001222 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
Hans Verkuild118e292011-06-25 10:28:21 -03001223 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001224 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
Hans Verkuil3f038d82008-05-29 16:43:54 -03001225 return 0;
1226}
1227
1228static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1229{
Hans Verkuil2f824412011-03-12 06:43:28 -03001230 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001231 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1232 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001233
Hans Verkuil79afcb12008-06-21 09:02:36 -03001234 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001235 for (f = 0; f < 2; f++) {
1236 for (l = 0; l < 24; l++) {
1237 if (valid_service_line(f, l, itv->is_50hz))
1238 cap->service_lines[f][l] = set;
1239 }
1240 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001241 } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001242 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1243 return -EINVAL;
1244 if (itv->is_60hz) {
1245 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1246 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1247 } else {
1248 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1249 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1250 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001251 } else {
1252 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001253 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001254
1255 set = 0;
1256 for (f = 0; f < 2; f++)
1257 for (l = 0; l < 24; l++)
1258 set |= cap->service_lines[f][l];
1259 cap->service_set = set;
1260 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001261}
1262
1263static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1264{
Hans Verkuil2f824412011-03-12 06:43:28 -03001265 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001266 struct v4l2_enc_idx_entry *e = idx->entry;
1267 int entries;
1268 int i;
1269
1270 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1271 IVTV_MAX_PGM_INDEX;
1272 if (entries > V4L2_ENC_IDX_ENTRIES)
1273 entries = V4L2_ENC_IDX_ENTRIES;
1274 idx->entries = 0;
Hans Verkuil1a806402012-09-05 08:39:48 -03001275 idx->entries_cap = IVTV_MAX_PGM_INDEX;
1276 if (!atomic_read(&itv->capturing))
1277 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001278 for (i = 0; i < entries; i++) {
1279 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1280 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1281 idx->entries++;
1282 e++;
1283 }
1284 }
1285 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1286 return 0;
1287}
1288
1289static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1290{
Hans Verkuil2f824412011-03-12 06:43:28 -03001291 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001292 struct ivtv *itv = id->itv;
1293
Hans Verkuil3f038d82008-05-29 16:43:54 -03001294
1295 switch (enc->cmd) {
1296 case V4L2_ENC_CMD_START:
1297 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1298 enc->flags = 0;
1299 return ivtv_start_capture(id);
1300
1301 case V4L2_ENC_CMD_STOP:
1302 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1303 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1304 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1305 return 0;
1306
1307 case V4L2_ENC_CMD_PAUSE:
1308 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1309 enc->flags = 0;
1310
1311 if (!atomic_read(&itv->capturing))
1312 return -EPERM;
1313 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1314 return 0;
1315
1316 ivtv_mute(itv);
1317 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1318 break;
1319
1320 case V4L2_ENC_CMD_RESUME:
1321 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1322 enc->flags = 0;
1323
1324 if (!atomic_read(&itv->capturing))
1325 return -EPERM;
1326
1327 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1328 return 0;
1329
1330 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1331 ivtv_unmute(itv);
1332 break;
1333 default:
1334 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1335 return -EINVAL;
1336 }
1337
1338 return 0;
1339}
1340
1341static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1342{
Hans Verkuil2f824412011-03-12 06:43:28 -03001343 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001344
Hans Verkuil3f038d82008-05-29 16:43:54 -03001345 switch (enc->cmd) {
1346 case V4L2_ENC_CMD_START:
1347 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1348 enc->flags = 0;
1349 return 0;
1350
1351 case V4L2_ENC_CMD_STOP:
1352 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1353 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1354 return 0;
1355
1356 case V4L2_ENC_CMD_PAUSE:
1357 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1358 enc->flags = 0;
1359 return 0;
1360
1361 case V4L2_ENC_CMD_RESUME:
1362 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1363 enc->flags = 0;
1364 return 0;
1365 default:
1366 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1367 return -EINVAL;
1368 }
1369}
1370
1371static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1372{
Hans Verkuil2f824412011-03-12 06:43:28 -03001373 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001374 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001375 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001376
Hans Verkuil3f038d82008-05-29 16:43:54 -03001377 int pixfmt;
1378 static u32 pixel_format[16] = {
1379 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1380 V4L2_PIX_FMT_RGB565,
1381 V4L2_PIX_FMT_RGB555,
1382 V4L2_PIX_FMT_RGB444,
1383 V4L2_PIX_FMT_RGB32,
1384 0,
1385 0,
1386 0,
1387 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1388 V4L2_PIX_FMT_YUV565,
1389 V4L2_PIX_FMT_YUV555,
1390 V4L2_PIX_FMT_YUV444,
1391 V4L2_PIX_FMT_YUV32,
1392 0,
1393 0,
1394 0,
1395 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001396
Hans Verkuil3f038d82008-05-29 16:43:54 -03001397 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1398 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001399 if (!itv->osd_video_pbase)
1400 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001401
Hans Verkuil3f038d82008-05-29 16:43:54 -03001402 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1403 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001404
Hans Verkuil3f038d82008-05-29 16:43:54 -03001405 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1406 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1407 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001408
Hans Verkuil3f038d82008-05-29 16:43:54 -03001409 fb->fmt.pixelformat = pixel_format[pixfmt];
1410 fb->fmt.width = itv->osd_rect.width;
1411 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001412 fb->fmt.field = V4L2_FIELD_INTERLACED;
1413 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001414 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1415 fb->fmt.field = V4L2_FIELD_INTERLACED;
1416 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001417 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1418 fb->fmt.bytesperline *= 2;
1419 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1420 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1421 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001422 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001423 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001424 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001425
Hans Verkuil3f038d82008-05-29 16:43:54 -03001426 if (itv->osd_chroma_key_state)
1427 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001428
Hans Verkuil3f038d82008-05-29 16:43:54 -03001429 if (itv->osd_global_alpha_state)
1430 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001431
Ian Armstrongec9faa12008-10-06 03:06:08 -03001432 if (yi->track_osd)
1433 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1434
Hans Verkuil3f038d82008-05-29 16:43:54 -03001435 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001436
Hans Verkuil3f038d82008-05-29 16:43:54 -03001437 /* no local alpha for RGB565 or unknown formats */
1438 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001439 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001440
Hans Verkuil3f038d82008-05-29 16:43:54 -03001441 /* 16-bit formats have inverted local alpha */
1442 if (pixfmt == 2 || pixfmt == 3)
1443 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1444 else
1445 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001446
Hans Verkuil3f038d82008-05-29 16:43:54 -03001447 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001448 /* 16-bit formats have inverted local alpha */
1449 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001450 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001451 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001452 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001453 }
1454
Hans Verkuil3f038d82008-05-29 16:43:54 -03001455 return 0;
1456}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001457
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001458static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001459{
Hans Verkuil2f824412011-03-12 06:43:28 -03001460 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001461 struct ivtv *itv = id->itv;
1462 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001463
Hans Verkuil3f038d82008-05-29 16:43:54 -03001464 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001465 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001466 if (!itv->osd_video_pbase)
1467 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001468
1469 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1470 itv->osd_local_alpha_state =
1471 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1472 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1473 ivtv_set_osd_alpha(itv);
1474 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001475 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001476}
1477
1478static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1479{
Hans Verkuil2f824412011-03-12 06:43:28 -03001480 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001481 struct ivtv *itv = id->itv;
1482
1483 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1484 return -EINVAL;
1485
1486 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1487
1488 return 0;
1489}
1490
Hans Verkuil85f5fe32012-09-04 11:46:09 -03001491static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
Hans Verkuil09250192010-03-27 14:10:13 -03001492{
1493 switch (sub->type) {
1494 case V4L2_EVENT_VSYNC:
1495 case V4L2_EVENT_EOS:
Hans de Goedec53c2542012-04-08 12:59:46 -03001496 return v4l2_event_subscribe(fh, sub, 0, NULL);
Hans de Goede3e3661492012-04-08 12:59:47 -03001497 case V4L2_EVENT_CTRL:
1498 return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
Hans Verkuil09250192010-03-27 14:10:13 -03001499 default:
1500 return -EINVAL;
1501 }
Hans Verkuil09250192010-03-27 14:10:13 -03001502}
1503
Hans Verkuil3f038d82008-05-29 16:43:54 -03001504static int ivtv_log_status(struct file *file, void *fh)
1505{
Hans Verkuil2f824412011-03-12 06:43:28 -03001506 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001507 u32 data[CX2341X_MBOX_MAX_DATA];
1508
1509 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1510 struct v4l2_input vidin;
1511 struct v4l2_audio audin;
1512 int i;
1513
Hans Verkuil3f038d82008-05-29 16:43:54 -03001514 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1515 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1516 struct tveeprom tv;
1517
1518 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001519 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001520 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001521 ivtv_get_input(itv, itv->active_input, &vidin);
1522 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1523 IVTV_INFO("Video Input: %s\n", vidin.name);
1524 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1525 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1526 if (has_output) {
1527 struct v4l2_output vidout;
1528 struct v4l2_audioout audout;
1529 int mode = itv->output_mode;
1530 static const char * const output_modes[5] = {
1531 "None",
1532 "MPEG Streaming",
1533 "YUV Streaming",
1534 "YUV Frames",
1535 "Passthrough",
1536 };
Hans Verkuil3f038d82008-05-29 16:43:54 -03001537 static const char * const alpha_mode[4] = {
1538 "None",
1539 "Global",
1540 "Local",
1541 "Global and Local"
1542 };
1543 static const char * const pixel_format[16] = {
1544 "ARGB Indexed",
1545 "RGB 5:6:5",
1546 "ARGB 1:5:5:5",
1547 "ARGB 1:4:4:4",
1548 "ARGB 8:8:8:8",
1549 "5",
1550 "6",
1551 "7",
1552 "AYUV Indexed",
1553 "YUV 5:6:5",
1554 "AYUV 1:5:5:5",
1555 "AYUV 1:4:4:4",
1556 "AYUV 8:8:8:8",
1557 "13",
1558 "14",
1559 "15",
1560 };
1561
1562 ivtv_get_output(itv, itv->active_output, &vidout);
1563 ivtv_get_audio_output(itv, 0, &audout);
1564 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001565 if (mode < 0 || mode > OUT_PASSTHROUGH)
1566 mode = OUT_NONE;
1567 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1568 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1569 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1570 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1571 data[0] & 1 ? "On" : "Off",
1572 alpha_mode[(data[0] >> 1) & 0x3],
1573 pixel_format[(data[0] >> 3) & 0xf]);
1574 }
1575 IVTV_INFO("Tuner: %s\n",
1576 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuileb2ba852012-03-02 13:02:11 -03001577 v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001578 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1579 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1580 struct ivtv_stream *s = &itv->streams[i];
1581
Hans Verkuil8ac05ae2009-02-07 07:02:27 -03001582 if (s->vdev == NULL || s->buffers == 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001583 continue;
1584 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1585 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1586 (s->buffers * s->buf_size) / 1024, s->buffers);
1587 }
1588
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001589 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1590 (long long)itv->mpg_data_received,
1591 (long long)itv->vbi_data_inserted);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001592 return 0;
1593}
1594
Hans Verkuilda8ec562011-11-24 09:58:53 -03001595static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1596{
1597 struct ivtv_open_id *id = fh2id(file->private_data);
1598 struct ivtv *itv = id->itv;
1599
1600 IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
1601 return ivtv_video_command(itv, id, dec, false);
1602}
1603
1604static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1605{
1606 struct ivtv_open_id *id = fh2id(file->private_data);
1607 struct ivtv *itv = id->itv;
1608
1609 IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
1610 return ivtv_video_command(itv, id, dec, true);
1611}
1612
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001613static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001614{
Hans Verkuil09250192010-03-27 14:10:13 -03001615 struct ivtv_open_id *id = fh2id(filp->private_data);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001616 struct ivtv *itv = id->itv;
1617 int nonblocking = filp->f_flags & O_NONBLOCK;
1618 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuilce680252010-04-06 15:58:53 -03001619 unsigned long iarg = (unsigned long)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001620
1621 switch (cmd) {
1622 case IVTV_IOC_DMA_FRAME: {
1623 struct ivtv_dma_frame *args = arg;
1624
1625 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1626 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1627 return -EINVAL;
1628 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1629 return -EINVAL;
1630 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1631 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001632 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001633 return -EBUSY;
1634 }
1635 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1636 ivtv_release_stream(s);
1637 return -EBUSY;
1638 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001639 /* Mark that this file handle started the UDMA_YUV mode */
1640 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001641 if (args->y_source == NULL)
1642 return 0;
1643 return ivtv_yuv_prep_frame(itv, args);
1644 }
1645
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001646 case IVTV_IOC_PASSTHROUGH_MODE:
1647 IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
1648 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1649 return -EINVAL;
1650 return ivtv_passthrough_mode(itv, *(int *)arg != 0);
1651
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001652 case VIDEO_GET_PTS: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001653 s64 *pts = arg;
1654 s64 frame;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001655
1656 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1657 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1658 *pts = s->dma_pts;
1659 break;
1660 }
1661 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1662 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001663 return ivtv_g_pts_frame(itv, pts, &frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001664 }
1665
1666 case VIDEO_GET_FRAME_COUNT: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001667 s64 *frame = arg;
1668 s64 pts;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001669
1670 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1671 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1672 *frame = 0;
1673 break;
1674 }
1675 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1676 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001677 return ivtv_g_pts_frame(itv, &pts, frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001678 }
1679
1680 case VIDEO_PLAY: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001681 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001682
1683 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001684 memset(&dc, 0, sizeof(dc));
1685 dc.cmd = V4L2_DEC_CMD_START;
1686 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001687 }
1688
1689 case VIDEO_STOP: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001690 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001691
1692 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001693 memset(&dc, 0, sizeof(dc));
1694 dc.cmd = V4L2_DEC_CMD_STOP;
1695 dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
1696 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001697 }
1698
1699 case VIDEO_FREEZE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001700 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001701
1702 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001703 memset(&dc, 0, sizeof(dc));
1704 dc.cmd = V4L2_DEC_CMD_PAUSE;
1705 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001706 }
1707
1708 case VIDEO_CONTINUE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001709 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001710
1711 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001712 memset(&dc, 0, sizeof(dc));
1713 dc.cmd = V4L2_DEC_CMD_RESUME;
1714 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001715 }
1716
1717 case VIDEO_COMMAND:
1718 case VIDEO_TRY_COMMAND: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001719 /* Note: struct v4l2_decoder_cmd has the same layout as
1720 struct video_command */
1721 struct v4l2_decoder_cmd *dc = arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001722 int try = (cmd == VIDEO_TRY_COMMAND);
1723
1724 if (try)
Hans Verkuilda8ec562011-11-24 09:58:53 -03001725 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001726 else
Hans Verkuilda8ec562011-11-24 09:58:53 -03001727 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
1728 return ivtv_video_command(itv, id, dc, try);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001729 }
1730
1731 case VIDEO_GET_EVENT: {
1732 struct video_event *ev = arg;
1733 DEFINE_WAIT(wait);
1734
1735 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1736 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1737 return -EINVAL;
1738 memset(ev, 0, sizeof(*ev));
1739 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1740
1741 while (1) {
1742 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1743 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1744 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1745 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001746 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1747 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1748 if (itv->output_mode == OUT_UDMA_YUV &&
1749 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1750 IVTV_YUV_MODE_PROGRESSIVE) {
1751 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1752 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001753 }
1754 if (ev->type)
1755 return 0;
1756 if (nonblocking)
1757 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001758 /* Wait for event. Note that serialize_lock is locked,
1759 so to allow other processes to access the driver while
1760 we are waiting unlock first and later lock again. */
1761 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001762 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a42009-05-02 11:10:23 -03001763 if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
1764 !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001765 schedule();
1766 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001767 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001768 if (signal_pending(current)) {
1769 /* return if a signal was received */
1770 IVTV_DEBUG_INFO("User stopped wait for event\n");
1771 return -EINTR;
1772 }
1773 }
1774 break;
1775 }
1776
Hans Verkuilce680252010-04-06 15:58:53 -03001777 case VIDEO_SELECT_SOURCE:
1778 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1779 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1780 return -EINVAL;
1781 return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
1782
1783 case AUDIO_SET_MUTE:
1784 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1785 itv->speed_mute_audio = iarg;
1786 return 0;
1787
1788 case AUDIO_CHANNEL_SELECT:
1789 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1790 if (iarg > AUDIO_STEREO_SWAPPED)
1791 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001792 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001793
1794 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1795 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1796 if (iarg > AUDIO_STEREO_SWAPPED)
1797 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001798 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001799
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001800 default:
1801 return -EINVAL;
1802 }
1803 return 0;
1804}
1805
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03001806static long ivtv_default(struct file *file, void *fh, bool valid_prio,
1807 int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001808{
Hans Verkuil2f824412011-03-12 06:43:28 -03001809 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001810
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001811 if (!valid_prio) {
1812 switch (cmd) {
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001813 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001814 case VIDEO_PLAY:
1815 case VIDEO_STOP:
1816 case VIDEO_FREEZE:
1817 case VIDEO_CONTINUE:
1818 case VIDEO_COMMAND:
1819 case VIDEO_SELECT_SOURCE:
1820 case AUDIO_SET_MUTE:
1821 case AUDIO_CHANNEL_SELECT:
1822 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1823 return -EBUSY;
1824 }
1825 }
1826
Hans Verkuild46c17d2007-03-10 17:59:15 -03001827 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001828 case VIDIOC_INT_RESET: {
1829 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001830
Hans Verkuil3f038d82008-05-29 16:43:54 -03001831 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1832 ivtv_reset_ir_gpio(itv);
1833 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001834 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001835 break;
1836 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001837
Hans Verkuilac9575f2009-02-14 19:58:33 -03001838 case IVTV_IOC_DMA_FRAME:
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001839 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001840 case VIDEO_GET_PTS:
1841 case VIDEO_GET_FRAME_COUNT:
1842 case VIDEO_GET_EVENT:
1843 case VIDEO_PLAY:
1844 case VIDEO_STOP:
1845 case VIDEO_FREEZE:
1846 case VIDEO_CONTINUE:
1847 case VIDEO_COMMAND:
1848 case VIDEO_TRY_COMMAND:
Hans Verkuilce680252010-04-06 15:58:53 -03001849 case VIDEO_SELECT_SOURCE:
1850 case AUDIO_SET_MUTE:
1851 case AUDIO_CHANNEL_SELECT:
1852 case AUDIO_BILINGUAL_CHANNEL_SELECT:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001853 return ivtv_decoder_ioctls(file, cmd, (void *)arg);
1854
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001855 default:
Hans Verkuild1c754a2012-04-19 12:36:03 -03001856 return -ENOTTY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001857 }
1858 return 0;
1859}
1860
Hans Verkuila3998102008-07-21 02:57:38 -03001861static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1862 .vidioc_querycap = ivtv_querycap,
Hans Verkuila3998102008-07-21 02:57:38 -03001863 .vidioc_s_audio = ivtv_s_audio,
1864 .vidioc_g_audio = ivtv_g_audio,
1865 .vidioc_enumaudio = ivtv_enumaudio,
1866 .vidioc_s_audout = ivtv_s_audout,
1867 .vidioc_g_audout = ivtv_g_audout,
1868 .vidioc_enum_input = ivtv_enum_input,
1869 .vidioc_enum_output = ivtv_enum_output,
1870 .vidioc_enumaudout = ivtv_enumaudout,
1871 .vidioc_cropcap = ivtv_cropcap,
1872 .vidioc_s_crop = ivtv_s_crop,
1873 .vidioc_g_crop = ivtv_g_crop,
1874 .vidioc_g_input = ivtv_g_input,
1875 .vidioc_s_input = ivtv_s_input,
1876 .vidioc_g_output = ivtv_g_output,
1877 .vidioc_s_output = ivtv_s_output,
1878 .vidioc_g_frequency = ivtv_g_frequency,
1879 .vidioc_s_frequency = ivtv_s_frequency,
1880 .vidioc_s_tuner = ivtv_s_tuner,
1881 .vidioc_g_tuner = ivtv_g_tuner,
1882 .vidioc_g_enc_index = ivtv_g_enc_index,
1883 .vidioc_g_fbuf = ivtv_g_fbuf,
1884 .vidioc_s_fbuf = ivtv_s_fbuf,
1885 .vidioc_g_std = ivtv_g_std,
1886 .vidioc_s_std = ivtv_s_std,
1887 .vidioc_overlay = ivtv_overlay,
1888 .vidioc_log_status = ivtv_log_status,
1889 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1890 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1891 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
Hans Verkuilda8ec562011-11-24 09:58:53 -03001892 .vidioc_decoder_cmd = ivtv_decoder_cmd,
1893 .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd,
Hans Verkuila3998102008-07-21 02:57:38 -03001894 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1895 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1896 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1897 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1898 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1899 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1900 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1901 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1902 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1903 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1904 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1905 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1906 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1907 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1908 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1909 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1910 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1911 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1912 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1913 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1914 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1915#ifdef CONFIG_VIDEO_ADV_DEBUG
1916 .vidioc_g_register = ivtv_g_register,
1917 .vidioc_s_register = ivtv_s_register,
1918#endif
1919 .vidioc_default = ivtv_default,
Hans Verkuil09250192010-03-27 14:10:13 -03001920 .vidioc_subscribe_event = ivtv_subscribe_event,
1921 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001922};
1923
Hans Verkuil3f038d82008-05-29 16:43:54 -03001924void ivtv_set_funcs(struct video_device *vdev)
1925{
Hans Verkuila3998102008-07-21 02:57:38 -03001926 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001927}