diff options
Diffstat (limited to 'drivers/media/pci/ivtv/ivtv-ioctl.c')
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-ioctl.c | 1899 |
1 files changed, 1899 insertions, 0 deletions
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c new file mode 100644 index 000000000000..32a591062d0b --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c | |||
@@ -0,0 +1,1899 @@ | |||
1 | /* | ||
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" | ||
28 | #include "ivtv-routing.h" | ||
29 | #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 <media/v4l2-event.h> | ||
39 | #include <linux/dvb/audio.h> | ||
40 | |||
41 | u16 ivtv_service2vbi(int type) | ||
42 | { | ||
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 | |||
57 | static 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 | |||
63 | static 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 | |||
91 | void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | ||
92 | { | ||
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 | |||
104 | static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | ||
105 | { | ||
106 | int f, l; | ||
107 | |||
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); | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) | ||
116 | { | ||
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 | |||
128 | void 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); | ||
132 | ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key); | ||
133 | } | ||
134 | |||
135 | int ivtv_set_speed(struct ivtv *itv, int speed) | ||
136 | { | ||
137 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
138 | 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 | |||
147 | 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; | ||
161 | data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames); | ||
162 | 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 */ | ||
179 | mutex_unlock(&itv->serialize_lock); | ||
180 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | ||
181 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { | ||
182 | 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); | ||
189 | mutex_lock(&itv->serialize_lock); | ||
190 | 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 | |||
206 | static int ivtv_validate_speed(int cur_speed, int new_speed) | ||
207 | { | ||
208 | int fact = new_speed < 0 ? -1 : 1; | ||
209 | int s; | ||
210 | |||
211 | 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; | ||
217 | |||
218 | if (cur_speed <= new_speed) { | ||
219 | if (new_speed > 1500) | ||
220 | return fact * 2000; | ||
221 | if (new_speed > 1000) | ||
222 | return fact * 1500; | ||
223 | } | ||
224 | else { | ||
225 | 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; | ||
231 | } | ||
232 | if (new_speed == 0) | ||
233 | return 1000; | ||
234 | if (new_speed == 1 || new_speed == 1000) | ||
235 | return fact * new_speed; | ||
236 | |||
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 | |||
245 | static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, | ||
246 | struct v4l2_decoder_cmd *dc, int try) | ||
247 | { | ||
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 | |||
253 | 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; | ||
264 | if (try) break; | ||
265 | |||
266 | itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; | ||
267 | if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) | ||
268 | return -EBUSY; | ||
269 | 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 | } | ||
273 | return ivtv_start_decoding(id, dc->start.speed); | ||
274 | } | ||
275 | |||
276 | 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; | ||
280 | 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; | ||
287 | return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); | ||
288 | |||
289 | case V4L2_DEC_CMD_PAUSE: | ||
290 | dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; | ||
291 | if (try) break; | ||
292 | if (itv->output_mode != OUT_MPG) | ||
293 | return -EBUSY; | ||
294 | if (atomic_read(&itv->decoding) > 0) { | ||
295 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, | ||
296 | (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); | ||
297 | set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); | ||
298 | } | ||
299 | break; | ||
300 | |||
301 | case V4L2_DEC_CMD_RESUME: | ||
302 | dc->flags = 0; | ||
303 | if (try) break; | ||
304 | if (itv->output_mode != OUT_MPG) | ||
305 | return -EBUSY; | ||
306 | if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { | ||
307 | int speed = itv->speed; | ||
308 | itv->speed = 0; | ||
309 | return ivtv_start_decoding(id, speed); | ||
310 | } | ||
311 | break; | ||
312 | |||
313 | default: | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) | ||
320 | { | ||
321 | struct ivtv *itv = fh2id(fh)->itv; | ||
322 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
323 | |||
324 | vbifmt->reserved[0] = 0; | ||
325 | vbifmt->reserved[1] = 0; | ||
326 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) | ||
327 | return -EINVAL; | ||
328 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
329 | if (itv->is_60hz) { | ||
330 | vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
331 | vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
332 | } else { | ||
333 | vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
334 | vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; | ||
335 | } | ||
336 | vbifmt->service_set = ivtv_get_service_set(vbifmt); | ||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
341 | { | ||
342 | struct ivtv_open_id *id = fh2id(fh); | ||
343 | struct ivtv *itv = id->itv; | ||
344 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | ||
345 | |||
346 | pixfmt->width = itv->cxhdl.width; | ||
347 | pixfmt->height = itv->cxhdl.height; | ||
348 | pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
349 | pixfmt->field = V4L2_FIELD_INTERLACED; | ||
350 | pixfmt->priv = 0; | ||
351 | if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { | ||
352 | pixfmt->pixelformat = V4L2_PIX_FMT_HM12; | ||
353 | /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ | ||
354 | pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; | ||
355 | pixfmt->bytesperline = 720; | ||
356 | } else { | ||
357 | pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; | ||
358 | pixfmt->sizeimage = 128 * 1024; | ||
359 | pixfmt->bytesperline = 0; | ||
360 | } | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
365 | { | ||
366 | struct ivtv *itv = fh2id(fh)->itv; | ||
367 | struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; | ||
368 | |||
369 | vbifmt->sampling_rate = 27000000; | ||
370 | vbifmt->offset = 248; | ||
371 | vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4; | ||
372 | vbifmt->sample_format = V4L2_PIX_FMT_GREY; | ||
373 | vbifmt->start[0] = itv->vbi.start[0]; | ||
374 | vbifmt->start[1] = itv->vbi.start[1]; | ||
375 | vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count; | ||
376 | vbifmt->flags = 0; | ||
377 | vbifmt->reserved[0] = 0; | ||
378 | vbifmt->reserved[1] = 0; | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
383 | { | ||
384 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
385 | struct ivtv_open_id *id = fh2id(fh); | ||
386 | struct ivtv *itv = id->itv; | ||
387 | |||
388 | vbifmt->reserved[0] = 0; | ||
389 | vbifmt->reserved[1] = 0; | ||
390 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
391 | |||
392 | if (id->type == IVTV_DEC_STREAM_TYPE_VBI) { | ||
393 | vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : | ||
394 | V4L2_SLICED_VBI_525; | ||
395 | ivtv_expand_service_set(vbifmt, itv->is_50hz); | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt); | ||
400 | vbifmt->service_set = ivtv_get_service_set(vbifmt); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) | ||
405 | { | ||
406 | struct ivtv_open_id *id = fh2id(fh); | ||
407 | struct ivtv *itv = id->itv; | ||
408 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | ||
409 | |||
410 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
411 | return -EINVAL; | ||
412 | pixfmt->width = itv->main_rect.width; | ||
413 | pixfmt->height = itv->main_rect.height; | ||
414 | pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
415 | pixfmt->field = V4L2_FIELD_INTERLACED; | ||
416 | pixfmt->priv = 0; | ||
417 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV) { | ||
418 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { | ||
419 | case IVTV_YUV_MODE_INTERLACED: | ||
420 | pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? | ||
421 | V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB; | ||
422 | break; | ||
423 | case IVTV_YUV_MODE_PROGRESSIVE: | ||
424 | pixfmt->field = V4L2_FIELD_NONE; | ||
425 | break; | ||
426 | default: | ||
427 | pixfmt->field = V4L2_FIELD_ANY; | ||
428 | break; | ||
429 | } | ||
430 | pixfmt->pixelformat = V4L2_PIX_FMT_HM12; | ||
431 | pixfmt->bytesperline = 720; | ||
432 | pixfmt->width = itv->yuv_info.v4l2_src_w; | ||
433 | pixfmt->height = itv->yuv_info.v4l2_src_h; | ||
434 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | ||
435 | pixfmt->sizeimage = | ||
436 | 1080 * ((pixfmt->height + 31) & ~31); | ||
437 | } else { | ||
438 | pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; | ||
439 | pixfmt->sizeimage = 128 * 1024; | ||
440 | pixfmt->bytesperline = 0; | ||
441 | } | ||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) | ||
446 | { | ||
447 | struct ivtv *itv = fh2id(fh)->itv; | ||
448 | struct v4l2_window *winfmt = &fmt->fmt.win; | ||
449 | |||
450 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
451 | return -EINVAL; | ||
452 | winfmt->chromakey = itv->osd_chroma_key; | ||
453 | winfmt->global_alpha = itv->osd_global_alpha; | ||
454 | winfmt->field = V4L2_FIELD_INTERLACED; | ||
455 | winfmt->clips = NULL; | ||
456 | winfmt->clipcount = 0; | ||
457 | winfmt->bitmap = NULL; | ||
458 | winfmt->w.top = winfmt->w.left = 0; | ||
459 | winfmt->w.width = itv->osd_rect.width; | ||
460 | winfmt->w.height = itv->osd_rect.height; | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) | ||
465 | { | ||
466 | return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt); | ||
467 | } | ||
468 | |||
469 | static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
470 | { | ||
471 | struct ivtv_open_id *id = fh2id(fh); | ||
472 | struct ivtv *itv = id->itv; | ||
473 | int w = fmt->fmt.pix.width; | ||
474 | int h = fmt->fmt.pix.height; | ||
475 | int min_h = 2; | ||
476 | |||
477 | w = min(w, 720); | ||
478 | w = max(w, 2); | ||
479 | if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { | ||
480 | /* YUV height must be a multiple of 32 */ | ||
481 | h &= ~0x1f; | ||
482 | min_h = 32; | ||
483 | } | ||
484 | h = min(h, itv->is_50hz ? 576 : 480); | ||
485 | h = max(h, min_h); | ||
486 | ivtv_g_fmt_vid_cap(file, fh, fmt); | ||
487 | fmt->fmt.pix.width = w; | ||
488 | fmt->fmt.pix.height = h; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
493 | { | ||
494 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); | ||
495 | } | ||
496 | |||
497 | static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
498 | { | ||
499 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
500 | struct ivtv_open_id *id = fh2id(fh); | ||
501 | struct ivtv *itv = id->itv; | ||
502 | |||
503 | if (id->type == IVTV_DEC_STREAM_TYPE_VBI) | ||
504 | return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt); | ||
505 | |||
506 | /* set sliced VBI capture format */ | ||
507 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
508 | vbifmt->reserved[0] = 0; | ||
509 | vbifmt->reserved[1] = 0; | ||
510 | |||
511 | if (vbifmt->service_set) | ||
512 | ivtv_expand_service_set(vbifmt, itv->is_50hz); | ||
513 | check_service_set(vbifmt, itv->is_50hz); | ||
514 | vbifmt->service_set = ivtv_get_service_set(vbifmt); | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) | ||
519 | { | ||
520 | struct ivtv_open_id *id = fh2id(fh); | ||
521 | s32 w = fmt->fmt.pix.width; | ||
522 | s32 h = fmt->fmt.pix.height; | ||
523 | int field = fmt->fmt.pix.field; | ||
524 | int ret = ivtv_g_fmt_vid_out(file, fh, fmt); | ||
525 | |||
526 | w = min(w, 720); | ||
527 | w = max(w, 2); | ||
528 | /* Why can the height be 576 even when the output is NTSC? | ||
529 | |||
530 | Internally the buffers of the PVR350 are always set to 720x576. The | ||
531 | decoded video frame will always be placed in the top left corner of | ||
532 | this buffer. For any video which is not 720x576, the buffer will | ||
533 | then be cropped to remove the unused right and lower areas, with | ||
534 | the remaining image being scaled by the hardware to fit the display | ||
535 | area. The video can be scaled both up and down, so a 720x480 video | ||
536 | can be displayed full-screen on PAL and a 720x576 video can be | ||
537 | displayed without cropping on NTSC. | ||
538 | |||
539 | Note that the scaling only occurs on the video stream, the osd | ||
540 | resolution is locked to the broadcast standard and not scaled. | ||
541 | |||
542 | Thanks to Ian Armstrong for this explanation. */ | ||
543 | h = min(h, 576); | ||
544 | h = max(h, 2); | ||
545 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV) | ||
546 | fmt->fmt.pix.field = field; | ||
547 | fmt->fmt.pix.width = w; | ||
548 | fmt->fmt.pix.height = h; | ||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) | ||
553 | { | ||
554 | struct ivtv *itv = fh2id(fh)->itv; | ||
555 | u32 chromakey = fmt->fmt.win.chromakey; | ||
556 | u8 global_alpha = fmt->fmt.win.global_alpha; | ||
557 | |||
558 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
559 | return -EINVAL; | ||
560 | ivtv_g_fmt_vid_out_overlay(file, fh, fmt); | ||
561 | fmt->fmt.win.chromakey = chromakey; | ||
562 | fmt->fmt.win.global_alpha = global_alpha; | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) | ||
567 | { | ||
568 | return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt); | ||
569 | } | ||
570 | |||
571 | static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
572 | { | ||
573 | struct ivtv_open_id *id = fh2id(fh); | ||
574 | struct ivtv *itv = id->itv; | ||
575 | struct v4l2_mbus_framefmt mbus_fmt; | ||
576 | int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); | ||
577 | int w = fmt->fmt.pix.width; | ||
578 | int h = fmt->fmt.pix.height; | ||
579 | |||
580 | if (ret) | ||
581 | return ret; | ||
582 | |||
583 | if (itv->cxhdl.width == w && itv->cxhdl.height == h) | ||
584 | return 0; | ||
585 | |||
586 | if (atomic_read(&itv->capturing) > 0) | ||
587 | return -EBUSY; | ||
588 | |||
589 | itv->cxhdl.width = w; | ||
590 | itv->cxhdl.height = h; | ||
591 | if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) | ||
592 | fmt->fmt.pix.width /= 2; | ||
593 | mbus_fmt.width = fmt->fmt.pix.width; | ||
594 | mbus_fmt.height = h; | ||
595 | mbus_fmt.code = V4L2_MBUS_FMT_FIXED; | ||
596 | v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt); | ||
597 | return ivtv_g_fmt_vid_cap(file, fh, fmt); | ||
598 | } | ||
599 | |||
600 | static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
601 | { | ||
602 | struct ivtv *itv = fh2id(fh)->itv; | ||
603 | |||
604 | if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) | ||
605 | return -EBUSY; | ||
606 | itv->vbi.sliced_in->service_set = 0; | ||
607 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
608 | v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi); | ||
609 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); | ||
610 | } | ||
611 | |||
612 | static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
613 | { | ||
614 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
615 | struct ivtv_open_id *id = fh2id(fh); | ||
616 | struct ivtv *itv = id->itv; | ||
617 | int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt); | ||
618 | |||
619 | if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) | ||
620 | return ret; | ||
621 | |||
622 | check_service_set(vbifmt, itv->is_50hz); | ||
623 | if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) | ||
624 | return -EBUSY; | ||
625 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
626 | v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt); | ||
627 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) | ||
632 | { | ||
633 | struct ivtv_open_id *id = fh2id(fh); | ||
634 | struct ivtv *itv = id->itv; | ||
635 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
636 | int ret = ivtv_try_fmt_vid_out(file, fh, fmt); | ||
637 | |||
638 | if (ret) | ||
639 | return ret; | ||
640 | |||
641 | if (id->type != IVTV_DEC_STREAM_TYPE_YUV) | ||
642 | return 0; | ||
643 | |||
644 | /* Return now if we already have some frame data */ | ||
645 | if (yi->stream_size) | ||
646 | return -EBUSY; | ||
647 | |||
648 | yi->v4l2_src_w = fmt->fmt.pix.width; | ||
649 | yi->v4l2_src_h = fmt->fmt.pix.height; | ||
650 | |||
651 | switch (fmt->fmt.pix.field) { | ||
652 | case V4L2_FIELD_NONE: | ||
653 | yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; | ||
654 | break; | ||
655 | case V4L2_FIELD_ANY: | ||
656 | yi->lace_mode = IVTV_YUV_MODE_AUTO; | ||
657 | break; | ||
658 | case V4L2_FIELD_INTERLACED_BT: | ||
659 | yi->lace_mode = | ||
660 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; | ||
661 | break; | ||
662 | case V4L2_FIELD_INTERLACED_TB: | ||
663 | default: | ||
664 | yi->lace_mode = IVTV_YUV_MODE_INTERLACED; | ||
665 | break; | ||
666 | } | ||
667 | yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; | ||
668 | |||
669 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
670 | itv->dma_data_req_size = | ||
671 | 1080 * ((yi->v4l2_src_h + 31) & ~31); | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) | ||
677 | { | ||
678 | struct ivtv *itv = fh2id(fh)->itv; | ||
679 | int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt); | ||
680 | |||
681 | if (ret == 0) { | ||
682 | itv->osd_chroma_key = fmt->fmt.win.chromakey; | ||
683 | itv->osd_global_alpha = fmt->fmt.win.global_alpha; | ||
684 | ivtv_set_osd_alpha(itv); | ||
685 | } | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) | ||
690 | { | ||
691 | struct ivtv *itv = fh2id(fh)->itv; | ||
692 | |||
693 | chip->ident = V4L2_IDENT_NONE; | ||
694 | chip->revision = 0; | ||
695 | if (chip->match.type == V4L2_CHIP_MATCH_HOST) { | ||
696 | if (v4l2_chip_match_host(&chip->match)) | ||
697 | chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; | ||
698 | return 0; | ||
699 | } | ||
700 | if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && | ||
701 | chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
702 | return -EINVAL; | ||
703 | /* TODO: is this correct? */ | ||
704 | return ivtv_call_all_err(itv, core, g_chip_ident, chip); | ||
705 | } | ||
706 | |||
707 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
708 | static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) | ||
709 | { | ||
710 | struct v4l2_dbg_register *regs = arg; | ||
711 | volatile u8 __iomem *reg_start; | ||
712 | |||
713 | if (!capable(CAP_SYS_ADMIN)) | ||
714 | return -EPERM; | ||
715 | if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) | ||
716 | reg_start = itv->reg_mem - IVTV_REG_OFFSET; | ||
717 | else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET && | ||
718 | regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) | ||
719 | reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; | ||
720 | else if (regs->reg < IVTV_ENCODER_SIZE) | ||
721 | reg_start = itv->enc_mem; | ||
722 | else | ||
723 | return -EINVAL; | ||
724 | |||
725 | regs->size = 4; | ||
726 | if (cmd == VIDIOC_DBG_G_REGISTER) | ||
727 | regs->val = readl(regs->reg + reg_start); | ||
728 | else | ||
729 | writel(regs->val, regs->reg + reg_start); | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) | ||
734 | { | ||
735 | struct ivtv *itv = fh2id(fh)->itv; | ||
736 | |||
737 | if (v4l2_chip_match_host(®->match)) | ||
738 | return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg); | ||
739 | /* TODO: subdev errors should not be ignored, this should become a | ||
740 | subdev helper function. */ | ||
741 | ivtv_call_all(itv, core, g_register, reg); | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) | ||
746 | { | ||
747 | struct ivtv *itv = fh2id(fh)->itv; | ||
748 | |||
749 | if (v4l2_chip_match_host(®->match)) | ||
750 | return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg); | ||
751 | /* TODO: subdev errors should not be ignored, this should become a | ||
752 | subdev helper function. */ | ||
753 | ivtv_call_all(itv, core, s_register, reg); | ||
754 | return 0; | ||
755 | } | ||
756 | #endif | ||
757 | |||
758 | static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) | ||
759 | { | ||
760 | struct ivtv_open_id *id = fh2id(file->private_data); | ||
761 | struct ivtv *itv = id->itv; | ||
762 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
763 | |||
764 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); | ||
765 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); | ||
766 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); | ||
767 | vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; | ||
768 | vcap->device_caps = s->caps; | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) | ||
773 | { | ||
774 | struct ivtv *itv = fh2id(fh)->itv; | ||
775 | |||
776 | return ivtv_get_audio_input(itv, vin->index, vin); | ||
777 | } | ||
778 | |||
779 | static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) | ||
780 | { | ||
781 | struct ivtv *itv = fh2id(fh)->itv; | ||
782 | |||
783 | vin->index = itv->audio_input; | ||
784 | return ivtv_get_audio_input(itv, vin->index, vin); | ||
785 | } | ||
786 | |||
787 | static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout) | ||
788 | { | ||
789 | struct ivtv *itv = fh2id(fh)->itv; | ||
790 | |||
791 | if (vout->index >= itv->nof_audio_inputs) | ||
792 | return -EINVAL; | ||
793 | |||
794 | itv->audio_input = vout->index; | ||
795 | ivtv_audio_set_io(itv); | ||
796 | |||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin) | ||
801 | { | ||
802 | struct ivtv *itv = fh2id(fh)->itv; | ||
803 | |||
804 | /* set it to defaults from our table */ | ||
805 | return ivtv_get_audio_output(itv, vin->index, vin); | ||
806 | } | ||
807 | |||
808 | static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin) | ||
809 | { | ||
810 | struct ivtv *itv = fh2id(fh)->itv; | ||
811 | |||
812 | vin->index = 0; | ||
813 | return ivtv_get_audio_output(itv, vin->index, vin); | ||
814 | } | ||
815 | |||
816 | static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout) | ||
817 | { | ||
818 | struct ivtv *itv = fh2id(fh)->itv; | ||
819 | |||
820 | return ivtv_get_audio_output(itv, vout->index, vout); | ||
821 | } | ||
822 | |||
823 | static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin) | ||
824 | { | ||
825 | struct ivtv *itv = fh2id(fh)->itv; | ||
826 | |||
827 | /* set it to defaults from our table */ | ||
828 | return ivtv_get_input(itv, vin->index, vin); | ||
829 | } | ||
830 | |||
831 | static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout) | ||
832 | { | ||
833 | struct ivtv *itv = fh2id(fh)->itv; | ||
834 | |||
835 | return ivtv_get_output(itv, vout->index, vout); | ||
836 | } | ||
837 | |||
838 | static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap) | ||
839 | { | ||
840 | struct ivtv_open_id *id = fh2id(fh); | ||
841 | struct ivtv *itv = id->itv; | ||
842 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
843 | int streamtype; | ||
844 | |||
845 | streamtype = id->type; | ||
846 | |||
847 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
848 | return -EINVAL; | ||
849 | cropcap->bounds.top = cropcap->bounds.left = 0; | ||
850 | cropcap->bounds.width = 720; | ||
851 | if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
852 | cropcap->bounds.height = itv->is_50hz ? 576 : 480; | ||
853 | cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; | ||
854 | cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; | ||
855 | } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
856 | if (yi->track_osd) { | ||
857 | cropcap->bounds.width = yi->osd_full_w; | ||
858 | cropcap->bounds.height = yi->osd_full_h; | ||
859 | } else { | ||
860 | cropcap->bounds.width = 720; | ||
861 | cropcap->bounds.height = | ||
862 | itv->is_out_50hz ? 576 : 480; | ||
863 | } | ||
864 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; | ||
865 | cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; | ||
866 | } else { | ||
867 | cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; | ||
868 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; | ||
869 | cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; | ||
870 | } | ||
871 | cropcap->defrect = cropcap->bounds; | ||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) | ||
876 | { | ||
877 | struct ivtv_open_id *id = fh2id(fh); | ||
878 | struct ivtv *itv = id->itv; | ||
879 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
880 | int streamtype; | ||
881 | |||
882 | streamtype = id->type; | ||
883 | |||
884 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
885 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | ||
886 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
887 | yi->main_rect = crop->c; | ||
888 | return 0; | ||
889 | } else { | ||
890 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | ||
891 | crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { | ||
892 | itv->main_rect = crop->c; | ||
893 | return 0; | ||
894 | } | ||
895 | } | ||
896 | return -EINVAL; | ||
897 | } | ||
898 | return -EINVAL; | ||
899 | } | ||
900 | |||
901 | static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) | ||
902 | { | ||
903 | struct ivtv_open_id *id = fh2id(fh); | ||
904 | struct ivtv *itv = id->itv; | ||
905 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
906 | int streamtype; | ||
907 | |||
908 | streamtype = id->type; | ||
909 | |||
910 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
911 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | ||
912 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) | ||
913 | crop->c = yi->main_rect; | ||
914 | else | ||
915 | crop->c = itv->main_rect; | ||
916 | return 0; | ||
917 | } | ||
918 | return -EINVAL; | ||
919 | } | ||
920 | |||
921 | static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) | ||
922 | { | ||
923 | static struct v4l2_fmtdesc formats[] = { | ||
924 | { 0, 0, 0, | ||
925 | "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, | ||
926 | { 0, 0, 0, 0 } | ||
927 | }, | ||
928 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, | ||
929 | "MPEG", V4L2_PIX_FMT_MPEG, | ||
930 | { 0, 0, 0, 0 } | ||
931 | } | ||
932 | }; | ||
933 | enum v4l2_buf_type type = fmt->type; | ||
934 | |||
935 | if (fmt->index > 1) | ||
936 | return -EINVAL; | ||
937 | |||
938 | *fmt = formats[fmt->index]; | ||
939 | fmt->type = type; | ||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) | ||
944 | { | ||
945 | struct ivtv *itv = fh2id(fh)->itv; | ||
946 | |||
947 | static struct v4l2_fmtdesc formats[] = { | ||
948 | { 0, 0, 0, | ||
949 | "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, | ||
950 | { 0, 0, 0, 0 } | ||
951 | }, | ||
952 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, | ||
953 | "MPEG", V4L2_PIX_FMT_MPEG, | ||
954 | { 0, 0, 0, 0 } | ||
955 | } | ||
956 | }; | ||
957 | enum v4l2_buf_type type = fmt->type; | ||
958 | |||
959 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
960 | return -EINVAL; | ||
961 | |||
962 | if (fmt->index > 1) | ||
963 | return -EINVAL; | ||
964 | |||
965 | *fmt = formats[fmt->index]; | ||
966 | fmt->type = type; | ||
967 | |||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static int ivtv_g_input(struct file *file, void *fh, unsigned int *i) | ||
972 | { | ||
973 | struct ivtv *itv = fh2id(fh)->itv; | ||
974 | |||
975 | *i = itv->active_input; | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | int ivtv_s_input(struct file *file, void *fh, unsigned int inp) | ||
981 | { | ||
982 | struct ivtv *itv = fh2id(fh)->itv; | ||
983 | |||
984 | if (inp < 0 || inp >= itv->nof_inputs) | ||
985 | return -EINVAL; | ||
986 | |||
987 | if (inp == itv->active_input) { | ||
988 | IVTV_DEBUG_INFO("Input unchanged\n"); | ||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | if (atomic_read(&itv->capturing) > 0) { | ||
993 | return -EBUSY; | ||
994 | } | ||
995 | |||
996 | IVTV_DEBUG_INFO("Changing input from %d to %d\n", | ||
997 | itv->active_input, inp); | ||
998 | |||
999 | itv->active_input = inp; | ||
1000 | /* Set the audio input to whatever is appropriate for the | ||
1001 | input type. */ | ||
1002 | itv->audio_input = itv->card->video_inputs[inp].audio_index; | ||
1003 | |||
1004 | /* prevent others from messing with the streams until | ||
1005 | we're finished changing inputs. */ | ||
1006 | ivtv_mute(itv); | ||
1007 | ivtv_video_set_io(itv); | ||
1008 | ivtv_audio_set_io(itv); | ||
1009 | ivtv_unmute(itv); | ||
1010 | |||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | static int ivtv_g_output(struct file *file, void *fh, unsigned int *i) | ||
1015 | { | ||
1016 | struct ivtv *itv = fh2id(fh)->itv; | ||
1017 | |||
1018 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1019 | return -EINVAL; | ||
1020 | |||
1021 | *i = itv->active_output; | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) | ||
1027 | { | ||
1028 | struct ivtv *itv = fh2id(fh)->itv; | ||
1029 | |||
1030 | if (outp >= itv->card->nof_outputs) | ||
1031 | return -EINVAL; | ||
1032 | |||
1033 | if (outp == itv->active_output) { | ||
1034 | IVTV_DEBUG_INFO("Output unchanged\n"); | ||
1035 | return 0; | ||
1036 | } | ||
1037 | IVTV_DEBUG_INFO("Changing output from %d to %d\n", | ||
1038 | itv->active_output, outp); | ||
1039 | |||
1040 | itv->active_output = outp; | ||
1041 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, | ||
1042 | SAA7127_INPUT_TYPE_NORMAL, | ||
1043 | itv->card->video_outputs[outp].video_output, 0); | ||
1044 | |||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) | ||
1049 | { | ||
1050 | struct ivtv *itv = fh2id(fh)->itv; | ||
1051 | |||
1052 | if (vf->tuner != 0) | ||
1053 | return -EINVAL; | ||
1054 | |||
1055 | ivtv_call_all(itv, tuner, g_frequency, vf); | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) | ||
1060 | { | ||
1061 | struct ivtv *itv = fh2id(fh)->itv; | ||
1062 | |||
1063 | if (vf->tuner != 0) | ||
1064 | return -EINVAL; | ||
1065 | |||
1066 | ivtv_mute(itv); | ||
1067 | IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); | ||
1068 | ivtv_call_all(itv, tuner, s_frequency, vf); | ||
1069 | ivtv_unmute(itv); | ||
1070 | return 0; | ||
1071 | } | ||
1072 | |||
1073 | static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) | ||
1074 | { | ||
1075 | struct ivtv *itv = fh2id(fh)->itv; | ||
1076 | |||
1077 | *std = itv->std; | ||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std) | ||
1082 | { | ||
1083 | itv->std = *std; | ||
1084 | itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; | ||
1085 | itv->is_50hz = !itv->is_60hz; | ||
1086 | cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz); | ||
1087 | itv->cxhdl.width = 720; | ||
1088 | itv->cxhdl.height = itv->is_50hz ? 576 : 480; | ||
1089 | itv->vbi.count = itv->is_50hz ? 18 : 12; | ||
1090 | itv->vbi.start[0] = itv->is_50hz ? 6 : 10; | ||
1091 | itv->vbi.start[1] = itv->is_50hz ? 318 : 273; | ||
1092 | |||
1093 | if (itv->hw_flags & IVTV_HW_CX25840) | ||
1094 | itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; | ||
1095 | |||
1096 | /* Tuner */ | ||
1097 | ivtv_call_all(itv, core, s_std, itv->std); | ||
1098 | } | ||
1099 | |||
1100 | void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) | ||
1101 | { | ||
1102 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
1103 | DEFINE_WAIT(wait); | ||
1104 | int f; | ||
1105 | |||
1106 | /* set display standard */ | ||
1107 | itv->std_out = *std; | ||
1108 | itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; | ||
1109 | itv->is_out_50hz = !itv->is_out_60hz; | ||
1110 | ivtv_call_all(itv, video, s_std_output, itv->std_out); | ||
1111 | |||
1112 | /* | ||
1113 | * The next firmware call is time sensitive. Time it to | ||
1114 | * avoid risk of a hard lock, by trying to ensure the call | ||
1115 | * happens within the first 100 lines of the top field. | ||
1116 | * Make 4 attempts to sync to the decoder before giving up. | ||
1117 | */ | ||
1118 | mutex_unlock(&itv->serialize_lock); | ||
1119 | for (f = 0; f < 4; f++) { | ||
1120 | prepare_to_wait(&itv->vsync_waitq, &wait, | ||
1121 | TASK_UNINTERRUPTIBLE); | ||
1122 | if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) | ||
1123 | break; | ||
1124 | schedule_timeout(msecs_to_jiffies(25)); | ||
1125 | } | ||
1126 | finish_wait(&itv->vsync_waitq, &wait); | ||
1127 | mutex_lock(&itv->serialize_lock); | ||
1128 | |||
1129 | if (f == 4) | ||
1130 | IVTV_WARN("Mode change failed to sync to decoder\n"); | ||
1131 | |||
1132 | ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); | ||
1133 | itv->main_rect.left = 0; | ||
1134 | itv->main_rect.top = 0; | ||
1135 | itv->main_rect.width = 720; | ||
1136 | itv->main_rect.height = itv->is_out_50hz ? 576 : 480; | ||
1137 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | ||
1138 | 720, itv->main_rect.height, 0, 0); | ||
1139 | yi->main_rect = itv->main_rect; | ||
1140 | if (!itv->osd_info) { | ||
1141 | yi->osd_full_w = 720; | ||
1142 | yi->osd_full_h = itv->is_out_50hz ? 576 : 480; | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) | ||
1147 | { | ||
1148 | struct ivtv *itv = fh2id(fh)->itv; | ||
1149 | |||
1150 | if ((*std & V4L2_STD_ALL) == 0) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | if (*std == itv->std) | ||
1154 | return 0; | ||
1155 | |||
1156 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || | ||
1157 | atomic_read(&itv->capturing) > 0 || | ||
1158 | atomic_read(&itv->decoding) > 0) { | ||
1159 | /* Switching standard would mess with already running | ||
1160 | streams, prevent that by returning EBUSY. */ | ||
1161 | return -EBUSY; | ||
1162 | } | ||
1163 | |||
1164 | IVTV_DEBUG_INFO("Switching standard to %llx.\n", | ||
1165 | (unsigned long long)itv->std); | ||
1166 | |||
1167 | ivtv_s_std_enc(itv, std); | ||
1168 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) | ||
1169 | ivtv_s_std_dec(itv, std); | ||
1170 | |||
1171 | return 0; | ||
1172 | } | ||
1173 | |||
1174 | static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) | ||
1175 | { | ||
1176 | struct ivtv_open_id *id = fh2id(fh); | ||
1177 | struct ivtv *itv = id->itv; | ||
1178 | |||
1179 | if (vt->index != 0) | ||
1180 | return -EINVAL; | ||
1181 | |||
1182 | ivtv_call_all(itv, tuner, s_tuner, vt); | ||
1183 | |||
1184 | return 0; | ||
1185 | } | ||
1186 | |||
1187 | static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) | ||
1188 | { | ||
1189 | struct ivtv *itv = fh2id(fh)->itv; | ||
1190 | |||
1191 | if (vt->index != 0) | ||
1192 | return -EINVAL; | ||
1193 | |||
1194 | ivtv_call_all(itv, tuner, g_tuner, vt); | ||
1195 | |||
1196 | if (vt->type == V4L2_TUNER_RADIO) | ||
1197 | strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); | ||
1198 | else | ||
1199 | strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); | ||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) | ||
1204 | { | ||
1205 | struct ivtv *itv = fh2id(fh)->itv; | ||
1206 | int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; | ||
1207 | int f, l; | ||
1208 | |||
1209 | if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
1210 | for (f = 0; f < 2; f++) { | ||
1211 | for (l = 0; l < 24; l++) { | ||
1212 | if (valid_service_line(f, l, itv->is_50hz)) | ||
1213 | cap->service_lines[f][l] = set; | ||
1214 | } | ||
1215 | } | ||
1216 | } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { | ||
1217 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) | ||
1218 | return -EINVAL; | ||
1219 | if (itv->is_60hz) { | ||
1220 | cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
1221 | cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
1222 | } else { | ||
1223 | cap->service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
1224 | cap->service_lines[0][16] = V4L2_SLICED_VPS; | ||
1225 | } | ||
1226 | } else { | ||
1227 | return -EINVAL; | ||
1228 | } | ||
1229 | |||
1230 | set = 0; | ||
1231 | for (f = 0; f < 2; f++) | ||
1232 | for (l = 0; l < 24; l++) | ||
1233 | set |= cap->service_lines[f][l]; | ||
1234 | cap->service_set = set; | ||
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1238 | static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx) | ||
1239 | { | ||
1240 | struct ivtv *itv = fh2id(fh)->itv; | ||
1241 | struct v4l2_enc_idx_entry *e = idx->entry; | ||
1242 | int entries; | ||
1243 | int i; | ||
1244 | |||
1245 | entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) % | ||
1246 | IVTV_MAX_PGM_INDEX; | ||
1247 | if (entries > V4L2_ENC_IDX_ENTRIES) | ||
1248 | entries = V4L2_ENC_IDX_ENTRIES; | ||
1249 | idx->entries = 0; | ||
1250 | for (i = 0; i < entries; i++) { | ||
1251 | *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX]; | ||
1252 | if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) { | ||
1253 | idx->entries++; | ||
1254 | e++; | ||
1255 | } | ||
1256 | } | ||
1257 | itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX; | ||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) | ||
1262 | { | ||
1263 | struct ivtv_open_id *id = fh2id(fh); | ||
1264 | struct ivtv *itv = id->itv; | ||
1265 | |||
1266 | |||
1267 | switch (enc->cmd) { | ||
1268 | case V4L2_ENC_CMD_START: | ||
1269 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); | ||
1270 | enc->flags = 0; | ||
1271 | return ivtv_start_capture(id); | ||
1272 | |||
1273 | case V4L2_ENC_CMD_STOP: | ||
1274 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); | ||
1275 | enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; | ||
1276 | ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); | ||
1277 | return 0; | ||
1278 | |||
1279 | case V4L2_ENC_CMD_PAUSE: | ||
1280 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); | ||
1281 | enc->flags = 0; | ||
1282 | |||
1283 | if (!atomic_read(&itv->capturing)) | ||
1284 | return -EPERM; | ||
1285 | if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) | ||
1286 | return 0; | ||
1287 | |||
1288 | ivtv_mute(itv); | ||
1289 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0); | ||
1290 | break; | ||
1291 | |||
1292 | case V4L2_ENC_CMD_RESUME: | ||
1293 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); | ||
1294 | enc->flags = 0; | ||
1295 | |||
1296 | if (!atomic_read(&itv->capturing)) | ||
1297 | return -EPERM; | ||
1298 | |||
1299 | if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) | ||
1300 | return 0; | ||
1301 | |||
1302 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); | ||
1303 | ivtv_unmute(itv); | ||
1304 | break; | ||
1305 | default: | ||
1306 | IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); | ||
1307 | return -EINVAL; | ||
1308 | } | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) | ||
1314 | { | ||
1315 | struct ivtv *itv = fh2id(fh)->itv; | ||
1316 | |||
1317 | switch (enc->cmd) { | ||
1318 | case V4L2_ENC_CMD_START: | ||
1319 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); | ||
1320 | enc->flags = 0; | ||
1321 | return 0; | ||
1322 | |||
1323 | case V4L2_ENC_CMD_STOP: | ||
1324 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); | ||
1325 | enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; | ||
1326 | return 0; | ||
1327 | |||
1328 | case V4L2_ENC_CMD_PAUSE: | ||
1329 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); | ||
1330 | enc->flags = 0; | ||
1331 | return 0; | ||
1332 | |||
1333 | case V4L2_ENC_CMD_RESUME: | ||
1334 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); | ||
1335 | enc->flags = 0; | ||
1336 | return 0; | ||
1337 | default: | ||
1338 | IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); | ||
1339 | return -EINVAL; | ||
1340 | } | ||
1341 | } | ||
1342 | |||
1343 | static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | ||
1344 | { | ||
1345 | struct ivtv *itv = fh2id(fh)->itv; | ||
1346 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
1347 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
1348 | |||
1349 | int pixfmt; | ||
1350 | static u32 pixel_format[16] = { | ||
1351 | V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */ | ||
1352 | V4L2_PIX_FMT_RGB565, | ||
1353 | V4L2_PIX_FMT_RGB555, | ||
1354 | V4L2_PIX_FMT_RGB444, | ||
1355 | V4L2_PIX_FMT_RGB32, | ||
1356 | 0, | ||
1357 | 0, | ||
1358 | 0, | ||
1359 | V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */ | ||
1360 | V4L2_PIX_FMT_YUV565, | ||
1361 | V4L2_PIX_FMT_YUV555, | ||
1362 | V4L2_PIX_FMT_YUV444, | ||
1363 | V4L2_PIX_FMT_YUV32, | ||
1364 | 0, | ||
1365 | 0, | ||
1366 | 0, | ||
1367 | }; | ||
1368 | |||
1369 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | ||
1370 | return -EINVAL; | ||
1371 | if (!itv->osd_video_pbase) | ||
1372 | return -EINVAL; | ||
1373 | |||
1374 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | | ||
1375 | V4L2_FBUF_CAP_GLOBAL_ALPHA; | ||
1376 | |||
1377 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); | ||
1378 | data[0] |= (read_reg(0x2a00) >> 7) & 0x40; | ||
1379 | pixfmt = (data[0] >> 3) & 0xf; | ||
1380 | |||
1381 | fb->fmt.pixelformat = pixel_format[pixfmt]; | ||
1382 | fb->fmt.width = itv->osd_rect.width; | ||
1383 | fb->fmt.height = itv->osd_rect.height; | ||
1384 | fb->fmt.field = V4L2_FIELD_INTERLACED; | ||
1385 | fb->fmt.bytesperline = fb->fmt.width; | ||
1386 | fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1387 | fb->fmt.field = V4L2_FIELD_INTERLACED; | ||
1388 | fb->fmt.priv = 0; | ||
1389 | if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8) | ||
1390 | fb->fmt.bytesperline *= 2; | ||
1391 | if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 || | ||
1392 | fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32) | ||
1393 | fb->fmt.bytesperline *= 2; | ||
1394 | fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height; | ||
1395 | fb->base = (void *)itv->osd_video_pbase; | ||
1396 | fb->flags = 0; | ||
1397 | |||
1398 | if (itv->osd_chroma_key_state) | ||
1399 | fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; | ||
1400 | |||
1401 | if (itv->osd_global_alpha_state) | ||
1402 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; | ||
1403 | |||
1404 | if (yi->track_osd) | ||
1405 | fb->flags |= V4L2_FBUF_FLAG_OVERLAY; | ||
1406 | |||
1407 | pixfmt &= 7; | ||
1408 | |||
1409 | /* no local alpha for RGB565 or unknown formats */ | ||
1410 | if (pixfmt == 1 || pixfmt > 4) | ||
1411 | return 0; | ||
1412 | |||
1413 | /* 16-bit formats have inverted local alpha */ | ||
1414 | if (pixfmt == 2 || pixfmt == 3) | ||
1415 | fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA; | ||
1416 | else | ||
1417 | fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA; | ||
1418 | |||
1419 | if (itv->osd_local_alpha_state) { | ||
1420 | /* 16-bit formats have inverted local alpha */ | ||
1421 | if (pixfmt == 2 || pixfmt == 3) | ||
1422 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA; | ||
1423 | else | ||
1424 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | ||
1425 | } | ||
1426 | |||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | ||
1431 | { | ||
1432 | struct ivtv_open_id *id = fh2id(fh); | ||
1433 | struct ivtv *itv = id->itv; | ||
1434 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
1435 | |||
1436 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | ||
1437 | return -EINVAL; | ||
1438 | if (!itv->osd_video_pbase) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; | ||
1442 | itv->osd_local_alpha_state = | ||
1443 | (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; | ||
1444 | itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; | ||
1445 | ivtv_set_osd_alpha(itv); | ||
1446 | yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0; | ||
1447 | return ivtv_g_fbuf(file, fh, fb); | ||
1448 | } | ||
1449 | |||
1450 | static int ivtv_overlay(struct file *file, void *fh, unsigned int on) | ||
1451 | { | ||
1452 | struct ivtv_open_id *id = fh2id(fh); | ||
1453 | struct ivtv *itv = id->itv; | ||
1454 | |||
1455 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | ||
1456 | return -EINVAL; | ||
1457 | |||
1458 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0); | ||
1459 | |||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub) | ||
1464 | { | ||
1465 | switch (sub->type) { | ||
1466 | case V4L2_EVENT_VSYNC: | ||
1467 | case V4L2_EVENT_EOS: | ||
1468 | return v4l2_event_subscribe(fh, sub, 0, NULL); | ||
1469 | case V4L2_EVENT_CTRL: | ||
1470 | return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); | ||
1471 | default: | ||
1472 | return -EINVAL; | ||
1473 | } | ||
1474 | } | ||
1475 | |||
1476 | static int ivtv_log_status(struct file *file, void *fh) | ||
1477 | { | ||
1478 | struct ivtv *itv = fh2id(fh)->itv; | ||
1479 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
1480 | |||
1481 | int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; | ||
1482 | struct v4l2_input vidin; | ||
1483 | struct v4l2_audio audin; | ||
1484 | int i; | ||
1485 | |||
1486 | IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); | ||
1487 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { | ||
1488 | struct tveeprom tv; | ||
1489 | |||
1490 | ivtv_read_eeprom(itv, &tv); | ||
1491 | } | ||
1492 | ivtv_call_all(itv, core, log_status); | ||
1493 | ivtv_get_input(itv, itv->active_input, &vidin); | ||
1494 | ivtv_get_audio_input(itv, itv->audio_input, &audin); | ||
1495 | IVTV_INFO("Video Input: %s\n", vidin.name); | ||
1496 | IVTV_INFO("Audio Input: %s%s\n", audin.name, | ||
1497 | (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : ""); | ||
1498 | if (has_output) { | ||
1499 | struct v4l2_output vidout; | ||
1500 | struct v4l2_audioout audout; | ||
1501 | int mode = itv->output_mode; | ||
1502 | static const char * const output_modes[5] = { | ||
1503 | "None", | ||
1504 | "MPEG Streaming", | ||
1505 | "YUV Streaming", | ||
1506 | "YUV Frames", | ||
1507 | "Passthrough", | ||
1508 | }; | ||
1509 | static const char * const alpha_mode[4] = { | ||
1510 | "None", | ||
1511 | "Global", | ||
1512 | "Local", | ||
1513 | "Global and Local" | ||
1514 | }; | ||
1515 | static const char * const pixel_format[16] = { | ||
1516 | "ARGB Indexed", | ||
1517 | "RGB 5:6:5", | ||
1518 | "ARGB 1:5:5:5", | ||
1519 | "ARGB 1:4:4:4", | ||
1520 | "ARGB 8:8:8:8", | ||
1521 | "5", | ||
1522 | "6", | ||
1523 | "7", | ||
1524 | "AYUV Indexed", | ||
1525 | "YUV 5:6:5", | ||
1526 | "AYUV 1:5:5:5", | ||
1527 | "AYUV 1:4:4:4", | ||
1528 | "AYUV 8:8:8:8", | ||
1529 | "13", | ||
1530 | "14", | ||
1531 | "15", | ||
1532 | }; | ||
1533 | |||
1534 | ivtv_get_output(itv, itv->active_output, &vidout); | ||
1535 | ivtv_get_audio_output(itv, 0, &audout); | ||
1536 | IVTV_INFO("Video Output: %s\n", vidout.name); | ||
1537 | if (mode < 0 || mode > OUT_PASSTHROUGH) | ||
1538 | mode = OUT_NONE; | ||
1539 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); | ||
1540 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); | ||
1541 | data[0] |= (read_reg(0x2a00) >> 7) & 0x40; | ||
1542 | IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n", | ||
1543 | data[0] & 1 ? "On" : "Off", | ||
1544 | alpha_mode[(data[0] >> 1) & 0x3], | ||
1545 | pixel_format[(data[0] >> 3) & 0xf]); | ||
1546 | } | ||
1547 | IVTV_INFO("Tuner: %s\n", | ||
1548 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); | ||
1549 | v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name); | ||
1550 | IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); | ||
1551 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | ||
1552 | struct ivtv_stream *s = &itv->streams[i]; | ||
1553 | |||
1554 | if (s->vdev == NULL || s->buffers == 0) | ||
1555 | continue; | ||
1556 | IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, | ||
1557 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, | ||
1558 | (s->buffers * s->buf_size) / 1024, s->buffers); | ||
1559 | } | ||
1560 | |||
1561 | IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", | ||
1562 | (long long)itv->mpg_data_received, | ||
1563 | (long long)itv->vbi_data_inserted); | ||
1564 | return 0; | ||
1565 | } | ||
1566 | |||
1567 | static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) | ||
1568 | { | ||
1569 | struct ivtv_open_id *id = fh2id(file->private_data); | ||
1570 | struct ivtv *itv = id->itv; | ||
1571 | |||
1572 | IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); | ||
1573 | return ivtv_video_command(itv, id, dec, false); | ||
1574 | } | ||
1575 | |||
1576 | static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) | ||
1577 | { | ||
1578 | struct ivtv_open_id *id = fh2id(file->private_data); | ||
1579 | struct ivtv *itv = id->itv; | ||
1580 | |||
1581 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); | ||
1582 | return ivtv_video_command(itv, id, dec, true); | ||
1583 | } | ||
1584 | |||
1585 | static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | ||
1586 | { | ||
1587 | struct ivtv_open_id *id = fh2id(filp->private_data); | ||
1588 | struct ivtv *itv = id->itv; | ||
1589 | int nonblocking = filp->f_flags & O_NONBLOCK; | ||
1590 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
1591 | unsigned long iarg = (unsigned long)arg; | ||
1592 | |||
1593 | switch (cmd) { | ||
1594 | case IVTV_IOC_DMA_FRAME: { | ||
1595 | struct ivtv_dma_frame *args = arg; | ||
1596 | |||
1597 | IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n"); | ||
1598 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1599 | return -EINVAL; | ||
1600 | if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
1601 | return -EINVAL; | ||
1602 | if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL) | ||
1603 | return 0; | ||
1604 | if (ivtv_start_decoding(id, id->type)) { | ||
1605 | return -EBUSY; | ||
1606 | } | ||
1607 | if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) { | ||
1608 | ivtv_release_stream(s); | ||
1609 | return -EBUSY; | ||
1610 | } | ||
1611 | /* Mark that this file handle started the UDMA_YUV mode */ | ||
1612 | id->yuv_frames = 1; | ||
1613 | if (args->y_source == NULL) | ||
1614 | return 0; | ||
1615 | return ivtv_yuv_prep_frame(itv, args); | ||
1616 | } | ||
1617 | |||
1618 | case IVTV_IOC_PASSTHROUGH_MODE: | ||
1619 | IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); | ||
1620 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1621 | return -EINVAL; | ||
1622 | return ivtv_passthrough_mode(itv, *(int *)arg != 0); | ||
1623 | |||
1624 | case VIDEO_GET_PTS: { | ||
1625 | s64 *pts = arg; | ||
1626 | s64 frame; | ||
1627 | |||
1628 | IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); | ||
1629 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | ||
1630 | *pts = s->dma_pts; | ||
1631 | break; | ||
1632 | } | ||
1633 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1634 | return -EINVAL; | ||
1635 | return ivtv_g_pts_frame(itv, pts, &frame); | ||
1636 | } | ||
1637 | |||
1638 | case VIDEO_GET_FRAME_COUNT: { | ||
1639 | s64 *frame = arg; | ||
1640 | s64 pts; | ||
1641 | |||
1642 | IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); | ||
1643 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | ||
1644 | *frame = 0; | ||
1645 | break; | ||
1646 | } | ||
1647 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1648 | return -EINVAL; | ||
1649 | return ivtv_g_pts_frame(itv, &pts, frame); | ||
1650 | } | ||
1651 | |||
1652 | case VIDEO_PLAY: { | ||
1653 | struct v4l2_decoder_cmd dc; | ||
1654 | |||
1655 | IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); | ||
1656 | memset(&dc, 0, sizeof(dc)); | ||
1657 | dc.cmd = V4L2_DEC_CMD_START; | ||
1658 | return ivtv_video_command(itv, id, &dc, 0); | ||
1659 | } | ||
1660 | |||
1661 | case VIDEO_STOP: { | ||
1662 | struct v4l2_decoder_cmd dc; | ||
1663 | |||
1664 | IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); | ||
1665 | memset(&dc, 0, sizeof(dc)); | ||
1666 | dc.cmd = V4L2_DEC_CMD_STOP; | ||
1667 | dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; | ||
1668 | return ivtv_video_command(itv, id, &dc, 0); | ||
1669 | } | ||
1670 | |||
1671 | case VIDEO_FREEZE: { | ||
1672 | struct v4l2_decoder_cmd dc; | ||
1673 | |||
1674 | IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); | ||
1675 | memset(&dc, 0, sizeof(dc)); | ||
1676 | dc.cmd = V4L2_DEC_CMD_PAUSE; | ||
1677 | return ivtv_video_command(itv, id, &dc, 0); | ||
1678 | } | ||
1679 | |||
1680 | case VIDEO_CONTINUE: { | ||
1681 | struct v4l2_decoder_cmd dc; | ||
1682 | |||
1683 | IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); | ||
1684 | memset(&dc, 0, sizeof(dc)); | ||
1685 | dc.cmd = V4L2_DEC_CMD_RESUME; | ||
1686 | return ivtv_video_command(itv, id, &dc, 0); | ||
1687 | } | ||
1688 | |||
1689 | case VIDEO_COMMAND: | ||
1690 | case VIDEO_TRY_COMMAND: { | ||
1691 | /* Note: struct v4l2_decoder_cmd has the same layout as | ||
1692 | struct video_command */ | ||
1693 | struct v4l2_decoder_cmd *dc = arg; | ||
1694 | int try = (cmd == VIDEO_TRY_COMMAND); | ||
1695 | |||
1696 | if (try) | ||
1697 | IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); | ||
1698 | else | ||
1699 | IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); | ||
1700 | return ivtv_video_command(itv, id, dc, 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; | ||
1718 | 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 | } | ||
1725 | } | ||
1726 | if (ev->type) | ||
1727 | return 0; | ||
1728 | if (nonblocking) | ||
1729 | return -EAGAIN; | ||
1730 | /* 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); | ||
1734 | prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); | ||
1735 | if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) && | ||
1736 | !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) | ||
1737 | schedule(); | ||
1738 | finish_wait(&itv->event_waitq, &wait); | ||
1739 | mutex_lock(&itv->serialize_lock); | ||
1740 | 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 | |||
1749 | 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 | return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); | ||
1765 | |||
1766 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1767 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); | ||
1768 | if (iarg > AUDIO_STEREO_SWAPPED) | ||
1769 | return -EINVAL; | ||
1770 | return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); | ||
1771 | |||
1772 | default: | ||
1773 | return -EINVAL; | ||
1774 | } | ||
1775 | return 0; | ||
1776 | } | ||
1777 | |||
1778 | static long ivtv_default(struct file *file, void *fh, bool valid_prio, | ||
1779 | int cmd, void *arg) | ||
1780 | { | ||
1781 | struct ivtv *itv = fh2id(fh)->itv; | ||
1782 | |||
1783 | if (!valid_prio) { | ||
1784 | switch (cmd) { | ||
1785 | case IVTV_IOC_PASSTHROUGH_MODE: | ||
1786 | case VIDEO_PLAY: | ||
1787 | case VIDEO_STOP: | ||
1788 | case VIDEO_FREEZE: | ||
1789 | case VIDEO_CONTINUE: | ||
1790 | case VIDEO_COMMAND: | ||
1791 | case VIDEO_SELECT_SOURCE: | ||
1792 | case AUDIO_SET_MUTE: | ||
1793 | case AUDIO_CHANNEL_SELECT: | ||
1794 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1795 | return -EBUSY; | ||
1796 | } | ||
1797 | } | ||
1798 | |||
1799 | switch (cmd) { | ||
1800 | case VIDIOC_INT_RESET: { | ||
1801 | u32 val = *(u32 *)arg; | ||
1802 | |||
1803 | if ((val == 0 && itv->options.newi2c) || (val & 0x01)) | ||
1804 | ivtv_reset_ir_gpio(itv); | ||
1805 | if (val & 0x02) | ||
1806 | v4l2_subdev_call(itv->sd_video, core, reset, 0); | ||
1807 | break; | ||
1808 | } | ||
1809 | |||
1810 | case IVTV_IOC_DMA_FRAME: | ||
1811 | case IVTV_IOC_PASSTHROUGH_MODE: | ||
1812 | case VIDEO_GET_PTS: | ||
1813 | case VIDEO_GET_FRAME_COUNT: | ||
1814 | case VIDEO_GET_EVENT: | ||
1815 | case VIDEO_PLAY: | ||
1816 | case VIDEO_STOP: | ||
1817 | case VIDEO_FREEZE: | ||
1818 | case VIDEO_CONTINUE: | ||
1819 | case VIDEO_COMMAND: | ||
1820 | case VIDEO_TRY_COMMAND: | ||
1821 | case VIDEO_SELECT_SOURCE: | ||
1822 | case AUDIO_SET_MUTE: | ||
1823 | case AUDIO_CHANNEL_SELECT: | ||
1824 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1825 | return ivtv_decoder_ioctls(file, cmd, (void *)arg); | ||
1826 | |||
1827 | default: | ||
1828 | return -ENOTTY; | ||
1829 | } | ||
1830 | return 0; | ||
1831 | } | ||
1832 | |||
1833 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { | ||
1834 | .vidioc_querycap = ivtv_querycap, | ||
1835 | .vidioc_s_audio = ivtv_s_audio, | ||
1836 | .vidioc_g_audio = ivtv_g_audio, | ||
1837 | .vidioc_enumaudio = ivtv_enumaudio, | ||
1838 | .vidioc_s_audout = ivtv_s_audout, | ||
1839 | .vidioc_g_audout = ivtv_g_audout, | ||
1840 | .vidioc_enum_input = ivtv_enum_input, | ||
1841 | .vidioc_enum_output = ivtv_enum_output, | ||
1842 | .vidioc_enumaudout = ivtv_enumaudout, | ||
1843 | .vidioc_cropcap = ivtv_cropcap, | ||
1844 | .vidioc_s_crop = ivtv_s_crop, | ||
1845 | .vidioc_g_crop = ivtv_g_crop, | ||
1846 | .vidioc_g_input = ivtv_g_input, | ||
1847 | .vidioc_s_input = ivtv_s_input, | ||
1848 | .vidioc_g_output = ivtv_g_output, | ||
1849 | .vidioc_s_output = ivtv_s_output, | ||
1850 | .vidioc_g_frequency = ivtv_g_frequency, | ||
1851 | .vidioc_s_frequency = ivtv_s_frequency, | ||
1852 | .vidioc_s_tuner = ivtv_s_tuner, | ||
1853 | .vidioc_g_tuner = ivtv_g_tuner, | ||
1854 | .vidioc_g_enc_index = ivtv_g_enc_index, | ||
1855 | .vidioc_g_fbuf = ivtv_g_fbuf, | ||
1856 | .vidioc_s_fbuf = ivtv_s_fbuf, | ||
1857 | .vidioc_g_std = ivtv_g_std, | ||
1858 | .vidioc_s_std = ivtv_s_std, | ||
1859 | .vidioc_overlay = ivtv_overlay, | ||
1860 | .vidioc_log_status = ivtv_log_status, | ||
1861 | .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, | ||
1862 | .vidioc_encoder_cmd = ivtv_encoder_cmd, | ||
1863 | .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, | ||
1864 | .vidioc_decoder_cmd = ivtv_decoder_cmd, | ||
1865 | .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, | ||
1866 | .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, | ||
1867 | .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, | ||
1868 | .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, | ||
1869 | .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap, | ||
1870 | .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out, | ||
1871 | .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay, | ||
1872 | .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out, | ||
1873 | .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap, | ||
1874 | .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap, | ||
1875 | .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap, | ||
1876 | .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out, | ||
1877 | .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay, | ||
1878 | .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out, | ||
1879 | .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap, | ||
1880 | .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap, | ||
1881 | .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap, | ||
1882 | .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out, | ||
1883 | .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay, | ||
1884 | .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out, | ||
1885 | .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap, | ||
1886 | .vidioc_g_chip_ident = ivtv_g_chip_ident, | ||
1887 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1888 | .vidioc_g_register = ivtv_g_register, | ||
1889 | .vidioc_s_register = ivtv_s_register, | ||
1890 | #endif | ||
1891 | .vidioc_default = ivtv_default, | ||
1892 | .vidioc_subscribe_event = ivtv_subscribe_event, | ||
1893 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
1894 | }; | ||
1895 | |||
1896 | void ivtv_set_funcs(struct video_device *vdev) | ||
1897 | { | ||
1898 | vdev->ioctl_ops = &ivtv_ioctl_ops; | ||
1899 | } | ||