1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | ioctl system call |
4 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> |
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> |
6 | |
7 | */ |
8 | |
9 | #include "ivtv-driver.h" |
10 | #include "ivtv-version.h" |
11 | #include "ivtv-mailbox.h" |
12 | #include "ivtv-i2c.h" |
13 | #include "ivtv-queue.h" |
14 | #include "ivtv-fileops.h" |
15 | #include "ivtv-vbi.h" |
16 | #include "ivtv-routing.h" |
17 | #include "ivtv-streams.h" |
18 | #include "ivtv-yuv.h" |
19 | #include "ivtv-ioctl.h" |
20 | #include "ivtv-gpio.h" |
21 | #include "ivtv-controls.h" |
22 | #include "ivtv-cards.h" |
23 | #include <media/i2c/saa7127.h> |
24 | #include <media/tveeprom.h> |
25 | #include <media/v4l2-event.h> |
26 | |
27 | u16 ivtv_service2vbi(int type) |
28 | { |
29 | switch (type) { |
30 | case V4L2_SLICED_TELETEXT_B: |
31 | return IVTV_SLICED_TYPE_TELETEXT_B; |
32 | case V4L2_SLICED_CAPTION_525: |
33 | return IVTV_SLICED_TYPE_CAPTION_525; |
34 | case V4L2_SLICED_WSS_625: |
35 | return IVTV_SLICED_TYPE_WSS_625; |
36 | case V4L2_SLICED_VPS: |
37 | return IVTV_SLICED_TYPE_VPS; |
38 | default: |
39 | return 0; |
40 | } |
41 | } |
42 | |
43 | static int valid_service_line(int field, int line, int is_pal) |
44 | { |
45 | return (is_pal && line >= 6 && (line != 23 || field == 0)) || |
46 | (!is_pal && line >= 10 && line < 22); |
47 | } |
48 | |
49 | static u16 select_service_from_set(int field, int line, u16 set, int is_pal) |
50 | { |
51 | u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525); |
52 | int i; |
53 | |
54 | set = set & valid_set; |
55 | if (set == 0 || !valid_service_line(field, line, is_pal)) { |
56 | return 0; |
57 | } |
58 | if (!is_pal) { |
59 | if (line == 21 && (set & V4L2_SLICED_CAPTION_525)) |
60 | return V4L2_SLICED_CAPTION_525; |
61 | } |
62 | else { |
63 | if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS)) |
64 | return V4L2_SLICED_VPS; |
65 | if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625)) |
66 | return V4L2_SLICED_WSS_625; |
67 | if (line == 23) |
68 | return 0; |
69 | } |
70 | for (i = 0; i < 32; i++) { |
71 | if (BIT(i) & set) |
72 | return BIT(i); |
73 | } |
74 | return 0; |
75 | } |
76 | |
77 | void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) |
78 | { |
79 | u16 set = fmt->service_set; |
80 | int f, l; |
81 | |
82 | fmt->service_set = 0; |
83 | for (f = 0; f < 2; f++) { |
84 | for (l = 0; l < 24; l++) { |
85 | fmt->service_lines[f][l] = select_service_from_set(field: f, line: l, set, is_pal); |
86 | } |
87 | } |
88 | } |
89 | |
90 | static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) |
91 | { |
92 | int f, l; |
93 | |
94 | for (f = 0; f < 2; f++) { |
95 | for (l = 0; l < 24; l++) { |
96 | fmt->service_lines[f][l] = select_service_from_set(field: f, line: l, set: fmt->service_lines[f][l], is_pal); |
97 | } |
98 | } |
99 | } |
100 | |
101 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) |
102 | { |
103 | int f, l; |
104 | u16 set = 0; |
105 | |
106 | for (f = 0; f < 2; f++) { |
107 | for (l = 0; l < 24; l++) { |
108 | set |= fmt->service_lines[f][l]; |
109 | } |
110 | } |
111 | return set; |
112 | } |
113 | |
114 | void ivtv_set_osd_alpha(struct ivtv *itv) |
115 | { |
116 | ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, args: 3, |
117 | itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state); |
118 | ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, args: 2, itv->osd_chroma_key_state, itv->osd_chroma_key); |
119 | } |
120 | |
121 | int ivtv_set_speed(struct ivtv *itv, int speed) |
122 | { |
123 | u32 data[CX2341X_MBOX_MAX_DATA]; |
124 | int single_step = (speed == 1 || speed == -1); |
125 | DEFINE_WAIT(wait); |
126 | |
127 | if (speed == 0) speed = 1000; |
128 | |
129 | /* No change? */ |
130 | if (speed == itv->speed && !single_step) |
131 | return 0; |
132 | |
133 | if (single_step && (speed < 0) == (itv->speed < 0)) { |
134 | /* Single step video and no need to change direction */ |
135 | ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, args: 1, 0); |
136 | itv->speed = speed; |
137 | return 0; |
138 | } |
139 | if (single_step) |
140 | /* Need to change direction */ |
141 | speed = speed < 0 ? -1000 : 1000; |
142 | |
143 | data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0; |
144 | data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0; |
145 | data[1] = (speed < 0); |
146 | data[2] = speed < 0 ? 3 : 7; |
147 | data[3] = v4l2_ctrl_g_ctrl(ctrl: itv->cxhdl.video_b_frames); |
148 | data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0; |
149 | data[5] = 0; |
150 | data[6] = 0; |
151 | |
152 | if (speed == 1500 || speed == -1500) data[0] |= 1; |
153 | else if (speed == 2000 || speed == -2000) data[0] |= 2; |
154 | else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed); |
155 | else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed); |
156 | |
157 | /* If not decoding, just change speed setting */ |
158 | if (atomic_read(v: &itv->decoding) > 0) { |
159 | int got_sig = 0; |
160 | |
161 | /* Stop all DMA and decoding activity */ |
162 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, args: 1, 0); |
163 | |
164 | /* Wait for any DMA to finish */ |
165 | mutex_unlock(lock: &itv->serialize_lock); |
166 | prepare_to_wait(wq_head: &itv->dma_waitq, wq_entry: &wait, TASK_INTERRUPTIBLE); |
167 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { |
168 | got_sig = signal_pending(current); |
169 | if (got_sig) |
170 | break; |
171 | got_sig = 0; |
172 | schedule(); |
173 | } |
174 | finish_wait(wq_head: &itv->dma_waitq, wq_entry: &wait); |
175 | mutex_lock(&itv->serialize_lock); |
176 | if (got_sig) |
177 | return -EINTR; |
178 | |
179 | /* Change Speed safely */ |
180 | ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, args: 7, data); |
181 | IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n" , |
182 | data[0], data[1], data[2], data[3], data[4], data[5], data[6]); |
183 | } |
184 | if (single_step) { |
185 | speed = (speed < 0) ? -1 : 1; |
186 | ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, args: 1, 0); |
187 | } |
188 | itv->speed = speed; |
189 | return 0; |
190 | } |
191 | |
192 | static int ivtv_validate_speed(int cur_speed, int new_speed) |
193 | { |
194 | int fact = new_speed < 0 ? -1 : 1; |
195 | int s; |
196 | |
197 | if (cur_speed == 0) |
198 | cur_speed = 1000; |
199 | if (new_speed < 0) |
200 | new_speed = -new_speed; |
201 | if (cur_speed < 0) |
202 | cur_speed = -cur_speed; |
203 | |
204 | if (cur_speed <= new_speed) { |
205 | if (new_speed > 1500) |
206 | return fact * 2000; |
207 | if (new_speed > 1000) |
208 | return fact * 1500; |
209 | } |
210 | else { |
211 | if (new_speed >= 2000) |
212 | return fact * 2000; |
213 | if (new_speed >= 1500) |
214 | return fact * 1500; |
215 | if (new_speed >= 1000) |
216 | return fact * 1000; |
217 | } |
218 | if (new_speed == 0) |
219 | return 1000; |
220 | if (new_speed == 1 || new_speed == 1000) |
221 | return fact * new_speed; |
222 | |
223 | s = new_speed; |
224 | new_speed = 1000 / new_speed; |
225 | if (1000 / cur_speed == new_speed) |
226 | new_speed += (cur_speed < s) ? -1 : 1; |
227 | if (new_speed > 60) return 1000 / (fact * 60); |
228 | return 1000 / (fact * new_speed); |
229 | } |
230 | |
231 | static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, |
232 | struct v4l2_decoder_cmd *dc, int try) |
233 | { |
234 | struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; |
235 | |
236 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
237 | return -EINVAL; |
238 | |
239 | switch (dc->cmd) { |
240 | case V4L2_DEC_CMD_START: { |
241 | dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; |
242 | dc->start.speed = ivtv_validate_speed(cur_speed: itv->speed, new_speed: dc->start.speed); |
243 | if (dc->start.speed < 0) |
244 | dc->start.format = V4L2_DEC_START_FMT_GOP; |
245 | else |
246 | dc->start.format = V4L2_DEC_START_FMT_NONE; |
247 | if (dc->start.speed != 500 && dc->start.speed != 1500) |
248 | dc->flags = dc->start.speed == 1000 ? 0 : |
249 | V4L2_DEC_CMD_START_MUTE_AUDIO; |
250 | if (try) break; |
251 | |
252 | itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; |
253 | if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) |
254 | return -EBUSY; |
255 | if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, addr: &itv->i_flags)) { |
256 | /* forces ivtv_set_speed to be called */ |
257 | itv->speed = 0; |
258 | } |
259 | return ivtv_start_decoding(id, speed: dc->start.speed); |
260 | } |
261 | |
262 | case V4L2_DEC_CMD_STOP: |
263 | dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; |
264 | if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) |
265 | dc->stop.pts = 0; |
266 | if (try) break; |
267 | if (atomic_read(v: &itv->decoding) == 0) |
268 | return 0; |
269 | if (itv->output_mode != OUT_MPG) |
270 | return -EBUSY; |
271 | |
272 | itv->output_mode = OUT_NONE; |
273 | return ivtv_stop_v4l2_decode_stream(s, flags: dc->flags, pts: dc->stop.pts); |
274 | |
275 | case V4L2_DEC_CMD_PAUSE: |
276 | dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; |
277 | if (try) break; |
278 | if (!atomic_read(v: &itv->decoding)) |
279 | return -EPERM; |
280 | if (itv->output_mode != OUT_MPG) |
281 | return -EBUSY; |
282 | if (atomic_read(v: &itv->decoding) > 0) { |
283 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, args: 1, |
284 | (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); |
285 | set_bit(IVTV_F_I_DEC_PAUSED, addr: &itv->i_flags); |
286 | } |
287 | break; |
288 | |
289 | case V4L2_DEC_CMD_RESUME: |
290 | dc->flags = 0; |
291 | if (try) break; |
292 | if (!atomic_read(v: &itv->decoding)) |
293 | return -EPERM; |
294 | if (itv->output_mode != OUT_MPG) |
295 | return -EBUSY; |
296 | if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, addr: &itv->i_flags)) { |
297 | int speed = itv->speed; |
298 | itv->speed = 0; |
299 | return ivtv_start_decoding(id, speed); |
300 | } |
301 | break; |
302 | |
303 | default: |
304 | return -EINVAL; |
305 | } |
306 | return 0; |
307 | } |
308 | |
309 | static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) |
310 | { |
311 | struct ivtv *itv = fh2id(fh)->itv; |
312 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
313 | |
314 | vbifmt->reserved[0] = 0; |
315 | vbifmt->reserved[1] = 0; |
316 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) |
317 | return -EINVAL; |
318 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; |
319 | memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); |
320 | if (itv->is_60hz) { |
321 | vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; |
322 | vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; |
323 | } else { |
324 | vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; |
325 | vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; |
326 | } |
327 | vbifmt->service_set = ivtv_get_service_set(fmt: vbifmt); |
328 | return 0; |
329 | } |
330 | |
331 | static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
332 | { |
333 | struct ivtv_open_id *id = fh2id(fh); |
334 | struct ivtv *itv = id->itv; |
335 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
336 | |
337 | pixfmt->width = itv->cxhdl.width; |
338 | pixfmt->height = itv->cxhdl.height; |
339 | pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; |
340 | pixfmt->field = V4L2_FIELD_INTERLACED; |
341 | if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { |
342 | pixfmt->pixelformat = V4L2_PIX_FMT_NV12_16L16; |
343 | /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ |
344 | pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; |
345 | pixfmt->bytesperline = 720; |
346 | } else { |
347 | pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; |
348 | pixfmt->sizeimage = 128 * 1024; |
349 | pixfmt->bytesperline = 0; |
350 | } |
351 | return 0; |
352 | } |
353 | |
354 | static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
355 | { |
356 | struct ivtv *itv = fh2id(fh)->itv; |
357 | struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; |
358 | |
359 | vbifmt->sampling_rate = 27000000; |
360 | vbifmt->offset = 248; |
361 | vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4; |
362 | vbifmt->sample_format = V4L2_PIX_FMT_GREY; |
363 | vbifmt->start[0] = itv->vbi.start[0]; |
364 | vbifmt->start[1] = itv->vbi.start[1]; |
365 | vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count; |
366 | vbifmt->flags = 0; |
367 | vbifmt->reserved[0] = 0; |
368 | vbifmt->reserved[1] = 0; |
369 | return 0; |
370 | } |
371 | |
372 | static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
373 | { |
374 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
375 | struct ivtv_open_id *id = fh2id(fh); |
376 | struct ivtv *itv = id->itv; |
377 | |
378 | vbifmt->reserved[0] = 0; |
379 | vbifmt->reserved[1] = 0; |
380 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; |
381 | |
382 | if (id->type == IVTV_DEC_STREAM_TYPE_VBI) { |
383 | vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : |
384 | V4L2_SLICED_VBI_525; |
385 | ivtv_expand_service_set(fmt: vbifmt, is_pal: itv->is_50hz); |
386 | vbifmt->service_set = ivtv_get_service_set(fmt: vbifmt); |
387 | return 0; |
388 | } |
389 | |
390 | v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt); |
391 | vbifmt->service_set = ivtv_get_service_set(fmt: vbifmt); |
392 | return 0; |
393 | } |
394 | |
395 | static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) |
396 | { |
397 | struct ivtv_open_id *id = fh2id(fh); |
398 | struct ivtv *itv = id->itv; |
399 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
400 | |
401 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
402 | return -EINVAL; |
403 | pixfmt->width = itv->main_rect.width; |
404 | pixfmt->height = itv->main_rect.height; |
405 | pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; |
406 | pixfmt->field = V4L2_FIELD_INTERLACED; |
407 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV) { |
408 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { |
409 | case IVTV_YUV_MODE_INTERLACED: |
410 | pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? |
411 | V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB; |
412 | break; |
413 | case IVTV_YUV_MODE_PROGRESSIVE: |
414 | pixfmt->field = V4L2_FIELD_NONE; |
415 | break; |
416 | default: |
417 | pixfmt->field = V4L2_FIELD_ANY; |
418 | break; |
419 | } |
420 | pixfmt->pixelformat = V4L2_PIX_FMT_NV12_16L16; |
421 | pixfmt->bytesperline = 720; |
422 | pixfmt->width = itv->yuv_info.v4l2_src_w; |
423 | pixfmt->height = itv->yuv_info.v4l2_src_h; |
424 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ |
425 | pixfmt->sizeimage = |
426 | 1080 * ((pixfmt->height + 31) & ~31); |
427 | } else { |
428 | pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; |
429 | pixfmt->sizeimage = 128 * 1024; |
430 | pixfmt->bytesperline = 0; |
431 | } |
432 | return 0; |
433 | } |
434 | |
435 | static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) |
436 | { |
437 | struct ivtv *itv = fh2id(fh)->itv; |
438 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
439 | struct v4l2_window *winfmt = &fmt->fmt.win; |
440 | |
441 | if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
442 | return -EINVAL; |
443 | if (!itv->osd_video_pbase) |
444 | return -EINVAL; |
445 | winfmt->chromakey = itv->osd_chroma_key; |
446 | winfmt->global_alpha = itv->osd_global_alpha; |
447 | winfmt->field = V4L2_FIELD_INTERLACED; |
448 | winfmt->clips = NULL; |
449 | winfmt->clipcount = 0; |
450 | winfmt->bitmap = NULL; |
451 | winfmt->w.top = winfmt->w.left = 0; |
452 | winfmt->w.width = itv->osd_rect.width; |
453 | winfmt->w.height = itv->osd_rect.height; |
454 | return 0; |
455 | } |
456 | |
457 | static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) |
458 | { |
459 | return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt); |
460 | } |
461 | |
462 | static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
463 | { |
464 | struct ivtv_open_id *id = fh2id(fh); |
465 | struct ivtv *itv = id->itv; |
466 | int w = fmt->fmt.pix.width; |
467 | int h = fmt->fmt.pix.height; |
468 | int min_h = 2; |
469 | |
470 | w = min(w, 720); |
471 | w = max(w, 2); |
472 | if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { |
473 | /* YUV height must be a multiple of 32 */ |
474 | h &= ~0x1f; |
475 | min_h = 32; |
476 | } |
477 | h = min(h, itv->is_50hz ? 576 : 480); |
478 | h = max(h, min_h); |
479 | ivtv_g_fmt_vid_cap(file, fh, fmt); |
480 | fmt->fmt.pix.width = w; |
481 | fmt->fmt.pix.height = h; |
482 | return 0; |
483 | } |
484 | |
485 | static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
486 | { |
487 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); |
488 | } |
489 | |
490 | static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
491 | { |
492 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
493 | struct ivtv_open_id *id = fh2id(fh); |
494 | struct ivtv *itv = id->itv; |
495 | |
496 | if (id->type == IVTV_DEC_STREAM_TYPE_VBI) |
497 | return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt); |
498 | |
499 | /* set sliced VBI capture format */ |
500 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; |
501 | vbifmt->reserved[0] = 0; |
502 | vbifmt->reserved[1] = 0; |
503 | |
504 | if (vbifmt->service_set) |
505 | ivtv_expand_service_set(fmt: vbifmt, is_pal: itv->is_50hz); |
506 | check_service_set(fmt: vbifmt, is_pal: itv->is_50hz); |
507 | vbifmt->service_set = ivtv_get_service_set(fmt: vbifmt); |
508 | return 0; |
509 | } |
510 | |
511 | static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) |
512 | { |
513 | struct ivtv_open_id *id = fh2id(fh); |
514 | s32 w = fmt->fmt.pix.width; |
515 | s32 h = fmt->fmt.pix.height; |
516 | int field = fmt->fmt.pix.field; |
517 | int ret = ivtv_g_fmt_vid_out(file, fh, fmt); |
518 | |
519 | w = min(w, 720); |
520 | w = max(w, 2); |
521 | /* Why can the height be 576 even when the output is NTSC? |
522 | |
523 | Internally the buffers of the PVR350 are always set to 720x576. The |
524 | decoded video frame will always be placed in the top left corner of |
525 | this buffer. For any video which is not 720x576, the buffer will |
526 | then be cropped to remove the unused right and lower areas, with |
527 | the remaining image being scaled by the hardware to fit the display |
528 | area. The video can be scaled both up and down, so a 720x480 video |
529 | can be displayed full-screen on PAL and a 720x576 video can be |
530 | displayed without cropping on NTSC. |
531 | |
532 | Note that the scaling only occurs on the video stream, the osd |
533 | resolution is locked to the broadcast standard and not scaled. |
534 | |
535 | Thanks to Ian Armstrong for this explanation. */ |
536 | h = min(h, 576); |
537 | h = max(h, 2); |
538 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV) |
539 | fmt->fmt.pix.field = field; |
540 | fmt->fmt.pix.width = w; |
541 | fmt->fmt.pix.height = h; |
542 | return ret; |
543 | } |
544 | |
545 | static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) |
546 | { |
547 | struct ivtv *itv = fh2id(fh)->itv; |
548 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
549 | u32 chromakey = fmt->fmt.win.chromakey; |
550 | u8 global_alpha = fmt->fmt.win.global_alpha; |
551 | |
552 | if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
553 | return -EINVAL; |
554 | if (!itv->osd_video_pbase) |
555 | return -EINVAL; |
556 | ivtv_g_fmt_vid_out_overlay(file, fh, fmt); |
557 | fmt->fmt.win.chromakey = chromakey; |
558 | fmt->fmt.win.global_alpha = global_alpha; |
559 | return 0; |
560 | } |
561 | |
562 | static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) |
563 | { |
564 | return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt); |
565 | } |
566 | |
567 | static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
568 | { |
569 | struct ivtv_open_id *id = fh2id(fh); |
570 | struct ivtv *itv = id->itv; |
571 | struct v4l2_subdev_format format = { |
572 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, |
573 | }; |
574 | int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); |
575 | int w = fmt->fmt.pix.width; |
576 | int h = fmt->fmt.pix.height; |
577 | |
578 | if (ret) |
579 | return ret; |
580 | |
581 | if (itv->cxhdl.width == w && itv->cxhdl.height == h) |
582 | return 0; |
583 | |
584 | if (atomic_read(v: &itv->capturing) > 0) |
585 | return -EBUSY; |
586 | |
587 | itv->cxhdl.width = w; |
588 | itv->cxhdl.height = h; |
589 | if (v4l2_ctrl_g_ctrl(ctrl: itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) |
590 | fmt->fmt.pix.width /= 2; |
591 | format.format.width = fmt->fmt.pix.width; |
592 | format.format.height = h; |
593 | format.format.code = MEDIA_BUS_FMT_FIXED; |
594 | v4l2_subdev_call(itv->sd_video, pad, set_fmt, NULL, &format); |
595 | return ivtv_g_fmt_vid_cap(file, fh, fmt); |
596 | } |
597 | |
598 | static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
599 | { |
600 | struct ivtv *itv = fh2id(fh)->itv; |
601 | |
602 | if (!ivtv_raw_vbi(itv) && atomic_read(v: &itv->capturing) > 0) |
603 | return -EBUSY; |
604 | itv->vbi.sliced_in->service_set = 0; |
605 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
606 | v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi); |
607 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); |
608 | } |
609 | |
610 | static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
611 | { |
612 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
613 | struct ivtv_open_id *id = fh2id(fh); |
614 | struct ivtv *itv = id->itv; |
615 | int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt); |
616 | |
617 | if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) |
618 | return ret; |
619 | |
620 | check_service_set(fmt: vbifmt, is_pal: itv->is_50hz); |
621 | if (ivtv_raw_vbi(itv) && atomic_read(v: &itv->capturing) > 0) |
622 | return -EBUSY; |
623 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; |
624 | v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt); |
625 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); |
626 | return 0; |
627 | } |
628 | |
629 | static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) |
630 | { |
631 | struct ivtv_open_id *id = fh2id(fh); |
632 | struct ivtv *itv = id->itv; |
633 | struct yuv_playback_info *yi = &itv->yuv_info; |
634 | int ret = ivtv_try_fmt_vid_out(file, fh, fmt); |
635 | |
636 | if (ret) |
637 | return ret; |
638 | |
639 | if (id->type != IVTV_DEC_STREAM_TYPE_YUV) |
640 | return 0; |
641 | |
642 | /* Return now if we already have some frame data */ |
643 | if (yi->stream_size) |
644 | return -EBUSY; |
645 | |
646 | yi->v4l2_src_w = fmt->fmt.pix.width; |
647 | yi->v4l2_src_h = fmt->fmt.pix.height; |
648 | |
649 | switch (fmt->fmt.pix.field) { |
650 | case V4L2_FIELD_NONE: |
651 | yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; |
652 | break; |
653 | case V4L2_FIELD_ANY: |
654 | yi->lace_mode = IVTV_YUV_MODE_AUTO; |
655 | break; |
656 | case V4L2_FIELD_INTERLACED_BT: |
657 | yi->lace_mode = |
658 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; |
659 | break; |
660 | case V4L2_FIELD_INTERLACED_TB: |
661 | default: |
662 | yi->lace_mode = IVTV_YUV_MODE_INTERLACED; |
663 | break; |
664 | } |
665 | yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; |
666 | |
667 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) |
668 | itv->dma_data_req_size = |
669 | 1080 * ((yi->v4l2_src_h + 31) & ~31); |
670 | |
671 | return 0; |
672 | } |
673 | |
674 | static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) |
675 | { |
676 | struct ivtv *itv = fh2id(fh)->itv; |
677 | int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt); |
678 | |
679 | if (ret == 0) { |
680 | itv->osd_chroma_key = fmt->fmt.win.chromakey; |
681 | itv->osd_global_alpha = fmt->fmt.win.global_alpha; |
682 | ivtv_set_osd_alpha(itv); |
683 | } |
684 | return ret; |
685 | } |
686 | |
687 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
688 | static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val) |
689 | { |
690 | volatile u8 __iomem *reg_start; |
691 | |
692 | if (reg & 0x3) |
693 | return -EINVAL; |
694 | if (reg >= IVTV_REG_OFFSET && reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) |
695 | reg_start = itv->reg_mem - IVTV_REG_OFFSET; |
696 | else if (itv->has_cx23415 && reg >= IVTV_DECODER_OFFSET && |
697 | reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) |
698 | reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; |
699 | else if (reg < IVTV_ENCODER_SIZE) |
700 | reg_start = itv->enc_mem; |
701 | else |
702 | return -EINVAL; |
703 | |
704 | if (get) |
705 | *val = readl(addr: reg + reg_start); |
706 | else |
707 | writel(val: *val, addr: reg + reg_start); |
708 | return 0; |
709 | } |
710 | |
711 | static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) |
712 | { |
713 | struct ivtv *itv = fh2id(fh)->itv; |
714 | |
715 | reg->size = 4; |
716 | return ivtv_itvc(itv, get: true, reg: reg->reg, val: ®->val); |
717 | } |
718 | |
719 | static int ivtv_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg) |
720 | { |
721 | struct ivtv *itv = fh2id(fh)->itv; |
722 | u64 val = reg->val; |
723 | |
724 | return ivtv_itvc(itv, get: false, reg: reg->reg, val: &val); |
725 | } |
726 | #endif |
727 | |
728 | static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) |
729 | { |
730 | struct ivtv_open_id *id = fh2id(fh: file->private_data); |
731 | struct ivtv *itv = id->itv; |
732 | |
733 | strscpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); |
734 | strscpy(vcap->card, itv->card_name, sizeof(vcap->card)); |
735 | vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; |
736 | return 0; |
737 | } |
738 | |
739 | static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) |
740 | { |
741 | struct ivtv *itv = fh2id(fh)->itv; |
742 | |
743 | return ivtv_get_audio_input(itv, index: vin->index, input: vin); |
744 | } |
745 | |
746 | static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) |
747 | { |
748 | struct ivtv *itv = fh2id(fh)->itv; |
749 | |
750 | vin->index = itv->audio_input; |
751 | return ivtv_get_audio_input(itv, index: vin->index, input: vin); |
752 | } |
753 | |
754 | static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout) |
755 | { |
756 | struct ivtv *itv = fh2id(fh)->itv; |
757 | |
758 | if (vout->index >= itv->nof_audio_inputs) |
759 | return -EINVAL; |
760 | |
761 | itv->audio_input = vout->index; |
762 | ivtv_audio_set_io(itv); |
763 | |
764 | return 0; |
765 | } |
766 | |
767 | static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin) |
768 | { |
769 | struct ivtv *itv = fh2id(fh)->itv; |
770 | |
771 | /* set it to defaults from our table */ |
772 | return ivtv_get_audio_output(itv, index: vin->index, output: vin); |
773 | } |
774 | |
775 | static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin) |
776 | { |
777 | struct ivtv *itv = fh2id(fh)->itv; |
778 | |
779 | vin->index = 0; |
780 | return ivtv_get_audio_output(itv, index: vin->index, output: vin); |
781 | } |
782 | |
783 | static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout) |
784 | { |
785 | struct ivtv *itv = fh2id(fh)->itv; |
786 | |
787 | if (itv->card->video_outputs == NULL || vout->index != 0) |
788 | return -EINVAL; |
789 | return 0; |
790 | } |
791 | |
792 | static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin) |
793 | { |
794 | struct ivtv *itv = fh2id(fh)->itv; |
795 | |
796 | /* set it to defaults from our table */ |
797 | return ivtv_get_input(itv, index: vin->index, input: vin); |
798 | } |
799 | |
800 | static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout) |
801 | { |
802 | struct ivtv *itv = fh2id(fh)->itv; |
803 | |
804 | return ivtv_get_output(itv, index: vout->index, output: vout); |
805 | } |
806 | |
807 | static int ivtv_g_pixelaspect(struct file *file, void *fh, |
808 | int type, struct v4l2_fract *f) |
809 | { |
810 | struct ivtv_open_id *id = fh2id(fh); |
811 | struct ivtv *itv = id->itv; |
812 | |
813 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
814 | f->numerator = itv->is_50hz ? 54 : 11; |
815 | f->denominator = itv->is_50hz ? 59 : 10; |
816 | } else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
817 | f->numerator = itv->is_out_50hz ? 54 : 11; |
818 | f->denominator = itv->is_out_50hz ? 59 : 10; |
819 | } else { |
820 | return -EINVAL; |
821 | } |
822 | return 0; |
823 | } |
824 | |
825 | static int ivtv_s_selection(struct file *file, void *fh, |
826 | struct v4l2_selection *sel) |
827 | { |
828 | struct ivtv_open_id *id = fh2id(fh); |
829 | struct ivtv *itv = id->itv; |
830 | struct yuv_playback_info *yi = &itv->yuv_info; |
831 | struct v4l2_rect r = { 0, 0, 720, 0 }; |
832 | int streamtype = id->type; |
833 | |
834 | if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || |
835 | !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
836 | return -EINVAL; |
837 | |
838 | if (sel->target != V4L2_SEL_TGT_COMPOSE) |
839 | return -EINVAL; |
840 | |
841 | |
842 | if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || |
843 | !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
844 | return -EINVAL; |
845 | |
846 | r.height = itv->is_out_50hz ? 576 : 480; |
847 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV && yi->track_osd) { |
848 | r.width = yi->osd_full_w; |
849 | r.height = yi->osd_full_h; |
850 | } |
851 | sel->r.width = clamp(sel->r.width, 16U, r.width); |
852 | sel->r.height = clamp(sel->r.height, 16U, r.height); |
853 | sel->r.left = clamp_t(unsigned, sel->r.left, 0, r.width - sel->r.width); |
854 | sel->r.top = clamp_t(unsigned, sel->r.top, 0, r.height - sel->r.height); |
855 | |
856 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
857 | yi->main_rect = sel->r; |
858 | return 0; |
859 | } |
860 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, args: 4, |
861 | sel->r.width, sel->r.height, sel->r.left, sel->r.top)) { |
862 | itv->main_rect = sel->r; |
863 | return 0; |
864 | } |
865 | return -EINVAL; |
866 | } |
867 | |
868 | static int ivtv_g_selection(struct file *file, void *fh, |
869 | struct v4l2_selection *sel) |
870 | { |
871 | struct ivtv_open_id *id = fh2id(fh); |
872 | struct ivtv *itv = id->itv; |
873 | struct yuv_playback_info *yi = &itv->yuv_info; |
874 | struct v4l2_rect r = { 0, 0, 720, 0 }; |
875 | int streamtype = id->type; |
876 | |
877 | if (sel->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
878 | switch (sel->target) { |
879 | case V4L2_SEL_TGT_CROP_DEFAULT: |
880 | case V4L2_SEL_TGT_CROP_BOUNDS: |
881 | sel->r.top = sel->r.left = 0; |
882 | sel->r.width = 720; |
883 | sel->r.height = itv->is_50hz ? 576 : 480; |
884 | return 0; |
885 | default: |
886 | return -EINVAL; |
887 | } |
888 | } |
889 | |
890 | if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || |
891 | !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
892 | return -EINVAL; |
893 | |
894 | switch (sel->target) { |
895 | case V4L2_SEL_TGT_COMPOSE: |
896 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) |
897 | sel->r = yi->main_rect; |
898 | else |
899 | sel->r = itv->main_rect; |
900 | return 0; |
901 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: |
902 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
903 | r.height = itv->is_out_50hz ? 576 : 480; |
904 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV && yi->track_osd) { |
905 | r.width = yi->osd_full_w; |
906 | r.height = yi->osd_full_h; |
907 | } |
908 | sel->r = r; |
909 | return 0; |
910 | } |
911 | return -EINVAL; |
912 | } |
913 | |
914 | static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) |
915 | { |
916 | static const struct v4l2_fmtdesc hm12 = { |
917 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, |
918 | .description = "HM12 (YUV 4:2:0)" , |
919 | .pixelformat = V4L2_PIX_FMT_NV12_16L16, |
920 | }; |
921 | static const struct v4l2_fmtdesc mpeg = { |
922 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, |
923 | .flags = V4L2_FMT_FLAG_COMPRESSED, |
924 | .description = "MPEG" , |
925 | .pixelformat = V4L2_PIX_FMT_MPEG, |
926 | }; |
927 | struct ivtv *itv = fh2id(fh)->itv; |
928 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
929 | |
930 | if (fmt->index) |
931 | return -EINVAL; |
932 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG) |
933 | *fmt = mpeg; |
934 | else if (s->type == IVTV_ENC_STREAM_TYPE_YUV) |
935 | *fmt = hm12; |
936 | else |
937 | return -EINVAL; |
938 | return 0; |
939 | } |
940 | |
941 | static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) |
942 | { |
943 | static const struct v4l2_fmtdesc hm12 = { |
944 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, |
945 | .description = "HM12 (YUV 4:2:0)" , |
946 | .pixelformat = V4L2_PIX_FMT_NV12_16L16, |
947 | }; |
948 | static const struct v4l2_fmtdesc mpeg = { |
949 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, |
950 | .flags = V4L2_FMT_FLAG_COMPRESSED, |
951 | .description = "MPEG" , |
952 | .pixelformat = V4L2_PIX_FMT_MPEG, |
953 | }; |
954 | struct ivtv *itv = fh2id(fh)->itv; |
955 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
956 | |
957 | if (fmt->index) |
958 | return -EINVAL; |
959 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) |
960 | *fmt = mpeg; |
961 | else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) |
962 | *fmt = hm12; |
963 | else |
964 | return -EINVAL; |
965 | return 0; |
966 | } |
967 | |
968 | static int ivtv_g_input(struct file *file, void *fh, unsigned int *i) |
969 | { |
970 | struct ivtv *itv = fh2id(fh)->itv; |
971 | |
972 | *i = itv->active_input; |
973 | |
974 | return 0; |
975 | } |
976 | |
977 | int ivtv_s_input(struct file *file, void *fh, unsigned int inp) |
978 | { |
979 | struct ivtv *itv = fh2id(fh)->itv; |
980 | v4l2_std_id std; |
981 | int i; |
982 | |
983 | if (inp >= itv->nof_inputs) |
984 | return -EINVAL; |
985 | |
986 | if (inp == itv->active_input) { |
987 | IVTV_DEBUG_INFO("Input unchanged\n" ); |
988 | return 0; |
989 | } |
990 | |
991 | if (atomic_read(v: &itv->capturing) > 0) { |
992 | return -EBUSY; |
993 | } |
994 | |
995 | IVTV_DEBUG_INFO("Changing input from %d to %d\n" , |
996 | itv->active_input, inp); |
997 | |
998 | itv->active_input = inp; |
999 | /* Set the audio input to whatever is appropriate for the |
1000 | input type. */ |
1001 | itv->audio_input = itv->card->video_inputs[inp].audio_index; |
1002 | |
1003 | if (itv->card->video_inputs[inp].video_type == IVTV_CARD_INPUT_VID_TUNER) |
1004 | std = itv->tuner_std; |
1005 | else |
1006 | std = V4L2_STD_ALL; |
1007 | for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++) |
1008 | itv->streams[i].vdev.tvnorms = std; |
1009 | |
1010 | /* prevent others from messing with the streams until |
1011 | we're finished changing inputs. */ |
1012 | ivtv_mute(itv); |
1013 | ivtv_video_set_io(itv); |
1014 | ivtv_audio_set_io(itv); |
1015 | ivtv_unmute(itv); |
1016 | |
1017 | return 0; |
1018 | } |
1019 | |
1020 | static int ivtv_g_output(struct file *file, void *fh, unsigned int *i) |
1021 | { |
1022 | struct ivtv *itv = fh2id(fh)->itv; |
1023 | |
1024 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1025 | return -EINVAL; |
1026 | |
1027 | *i = itv->active_output; |
1028 | |
1029 | return 0; |
1030 | } |
1031 | |
1032 | static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) |
1033 | { |
1034 | struct ivtv *itv = fh2id(fh)->itv; |
1035 | |
1036 | if (outp >= itv->card->nof_outputs) |
1037 | return -EINVAL; |
1038 | |
1039 | if (outp == itv->active_output) { |
1040 | IVTV_DEBUG_INFO("Output unchanged\n" ); |
1041 | return 0; |
1042 | } |
1043 | IVTV_DEBUG_INFO("Changing output from %d to %d\n" , |
1044 | itv->active_output, outp); |
1045 | |
1046 | itv->active_output = outp; |
1047 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, |
1048 | SAA7127_INPUT_TYPE_NORMAL, |
1049 | itv->card->video_outputs[outp].video_output, 0); |
1050 | |
1051 | return 0; |
1052 | } |
1053 | |
1054 | static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) |
1055 | { |
1056 | struct ivtv *itv = fh2id(fh)->itv; |
1057 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
1058 | |
1059 | if (s->vdev.vfl_dir) |
1060 | return -ENOTTY; |
1061 | if (vf->tuner != 0) |
1062 | return -EINVAL; |
1063 | |
1064 | ivtv_call_all(itv, tuner, g_frequency, vf); |
1065 | return 0; |
1066 | } |
1067 | |
1068 | int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf) |
1069 | { |
1070 | struct ivtv *itv = fh2id(fh)->itv; |
1071 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
1072 | |
1073 | if (s->vdev.vfl_dir) |
1074 | return -ENOTTY; |
1075 | if (vf->tuner != 0) |
1076 | return -EINVAL; |
1077 | |
1078 | ivtv_mute(itv); |
1079 | IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n" , vf->frequency); |
1080 | ivtv_call_all(itv, tuner, s_frequency, vf); |
1081 | ivtv_unmute(itv); |
1082 | return 0; |
1083 | } |
1084 | |
1085 | static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) |
1086 | { |
1087 | struct ivtv *itv = fh2id(fh)->itv; |
1088 | |
1089 | *std = itv->std; |
1090 | return 0; |
1091 | } |
1092 | |
1093 | void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id std) |
1094 | { |
1095 | itv->std = std; |
1096 | itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0; |
1097 | itv->is_50hz = !itv->is_60hz; |
1098 | cx2341x_handler_set_50hz(cxhdl: &itv->cxhdl, is_50hz: itv->is_50hz); |
1099 | itv->cxhdl.width = 720; |
1100 | itv->cxhdl.height = itv->is_50hz ? 576 : 480; |
1101 | itv->vbi.count = itv->is_50hz ? 18 : 12; |
1102 | itv->vbi.start[0] = itv->is_50hz ? 6 : 10; |
1103 | itv->vbi.start[1] = itv->is_50hz ? 318 : 273; |
1104 | |
1105 | if (itv->hw_flags & IVTV_HW_CX25840) |
1106 | itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; |
1107 | |
1108 | /* Tuner */ |
1109 | ivtv_call_all(itv, video, s_std, itv->std); |
1110 | } |
1111 | |
1112 | void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id std) |
1113 | { |
1114 | struct yuv_playback_info *yi = &itv->yuv_info; |
1115 | DEFINE_WAIT(wait); |
1116 | int f; |
1117 | |
1118 | /* set display standard */ |
1119 | itv->std_out = std; |
1120 | itv->is_out_60hz = (std & V4L2_STD_525_60) ? 1 : 0; |
1121 | itv->is_out_50hz = !itv->is_out_60hz; |
1122 | ivtv_call_all(itv, video, s_std_output, itv->std_out); |
1123 | |
1124 | /* |
1125 | * The next firmware call is time sensitive. Time it to |
1126 | * avoid risk of a hard lock, by trying to ensure the call |
1127 | * happens within the first 100 lines of the top field. |
1128 | * Make 4 attempts to sync to the decoder before giving up. |
1129 | */ |
1130 | mutex_unlock(lock: &itv->serialize_lock); |
1131 | for (f = 0; f < 4; f++) { |
1132 | prepare_to_wait(wq_head: &itv->vsync_waitq, wq_entry: &wait, |
1133 | TASK_UNINTERRUPTIBLE); |
1134 | if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) |
1135 | break; |
1136 | schedule_timeout(timeout: msecs_to_jiffies(m: 25)); |
1137 | } |
1138 | finish_wait(wq_head: &itv->vsync_waitq, wq_entry: &wait); |
1139 | mutex_lock(&itv->serialize_lock); |
1140 | |
1141 | if (f == 4) |
1142 | IVTV_WARN("Mode change failed to sync to decoder\n" ); |
1143 | |
1144 | ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, args: 1, itv->is_out_50hz); |
1145 | itv->main_rect.left = 0; |
1146 | itv->main_rect.top = 0; |
1147 | itv->main_rect.width = 720; |
1148 | itv->main_rect.height = itv->is_out_50hz ? 576 : 480; |
1149 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, args: 4, |
1150 | 720, itv->main_rect.height, 0, 0); |
1151 | yi->main_rect = itv->main_rect; |
1152 | if (!itv->osd_info) { |
1153 | yi->osd_full_w = 720; |
1154 | yi->osd_full_h = itv->is_out_50hz ? 576 : 480; |
1155 | } |
1156 | } |
1157 | |
1158 | static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id std) |
1159 | { |
1160 | struct ivtv *itv = fh2id(fh)->itv; |
1161 | |
1162 | if ((std & V4L2_STD_ALL) == 0) |
1163 | return -EINVAL; |
1164 | |
1165 | if (std == itv->std) |
1166 | return 0; |
1167 | |
1168 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || |
1169 | atomic_read(v: &itv->capturing) > 0 || |
1170 | atomic_read(v: &itv->decoding) > 0) { |
1171 | /* Switching standard would mess with already running |
1172 | streams, prevent that by returning EBUSY. */ |
1173 | return -EBUSY; |
1174 | } |
1175 | |
1176 | IVTV_DEBUG_INFO("Switching standard to %llx.\n" , |
1177 | (unsigned long long)itv->std); |
1178 | |
1179 | ivtv_s_std_enc(itv, std); |
1180 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) |
1181 | ivtv_s_std_dec(itv, std); |
1182 | |
1183 | return 0; |
1184 | } |
1185 | |
1186 | static int ivtv_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) |
1187 | { |
1188 | struct ivtv_open_id *id = fh2id(fh); |
1189 | struct ivtv *itv = id->itv; |
1190 | |
1191 | if (vt->index != 0) |
1192 | return -EINVAL; |
1193 | |
1194 | ivtv_call_all(itv, tuner, s_tuner, vt); |
1195 | |
1196 | return 0; |
1197 | } |
1198 | |
1199 | static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) |
1200 | { |
1201 | struct ivtv *itv = fh2id(fh)->itv; |
1202 | |
1203 | if (vt->index != 0) |
1204 | return -EINVAL; |
1205 | |
1206 | ivtv_call_all(itv, tuner, g_tuner, vt); |
1207 | |
1208 | if (vt->type == V4L2_TUNER_RADIO) |
1209 | strscpy(vt->name, "ivtv Radio Tuner" , sizeof(vt->name)); |
1210 | else |
1211 | strscpy(vt->name, "ivtv TV Tuner" , sizeof(vt->name)); |
1212 | return 0; |
1213 | } |
1214 | |
1215 | static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) |
1216 | { |
1217 | struct ivtv *itv = fh2id(fh)->itv; |
1218 | int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; |
1219 | int f, l; |
1220 | |
1221 | if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { |
1222 | for (f = 0; f < 2; f++) { |
1223 | for (l = 0; l < 24; l++) { |
1224 | if (valid_service_line(field: f, line: l, is_pal: itv->is_50hz)) |
1225 | cap->service_lines[f][l] = set; |
1226 | } |
1227 | } |
1228 | } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { |
1229 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) |
1230 | return -EINVAL; |
1231 | if (itv->is_60hz) { |
1232 | cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525; |
1233 | cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525; |
1234 | } else { |
1235 | cap->service_lines[0][23] = V4L2_SLICED_WSS_625; |
1236 | cap->service_lines[0][16] = V4L2_SLICED_VPS; |
1237 | } |
1238 | } else { |
1239 | return -EINVAL; |
1240 | } |
1241 | |
1242 | set = 0; |
1243 | for (f = 0; f < 2; f++) |
1244 | for (l = 0; l < 24; l++) |
1245 | set |= cap->service_lines[f][l]; |
1246 | cap->service_set = set; |
1247 | return 0; |
1248 | } |
1249 | |
1250 | static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx) |
1251 | { |
1252 | struct ivtv *itv = fh2id(fh)->itv; |
1253 | struct v4l2_enc_idx_entry *e = idx->entry; |
1254 | int entries; |
1255 | int i; |
1256 | |
1257 | entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) % |
1258 | IVTV_MAX_PGM_INDEX; |
1259 | if (entries > V4L2_ENC_IDX_ENTRIES) |
1260 | entries = V4L2_ENC_IDX_ENTRIES; |
1261 | idx->entries = 0; |
1262 | idx->entries_cap = IVTV_MAX_PGM_INDEX; |
1263 | if (!atomic_read(v: &itv->capturing)) |
1264 | return 0; |
1265 | for (i = 0; i < entries; i++) { |
1266 | *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX]; |
1267 | if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) { |
1268 | idx->entries++; |
1269 | e++; |
1270 | } |
1271 | } |
1272 | itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX; |
1273 | return 0; |
1274 | } |
1275 | |
1276 | static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) |
1277 | { |
1278 | struct ivtv_open_id *id = fh2id(fh); |
1279 | struct ivtv *itv = id->itv; |
1280 | |
1281 | |
1282 | switch (enc->cmd) { |
1283 | case V4L2_ENC_CMD_START: |
1284 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n" ); |
1285 | enc->flags = 0; |
1286 | return ivtv_start_capture(id); |
1287 | |
1288 | case V4L2_ENC_CMD_STOP: |
1289 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n" ); |
1290 | enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; |
1291 | ivtv_stop_capture(id, gop_end: enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); |
1292 | return 0; |
1293 | |
1294 | case V4L2_ENC_CMD_PAUSE: |
1295 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n" ); |
1296 | enc->flags = 0; |
1297 | |
1298 | if (!atomic_read(v: &itv->capturing)) |
1299 | return -EPERM; |
1300 | if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, addr: &itv->i_flags)) |
1301 | return 0; |
1302 | |
1303 | ivtv_mute(itv); |
1304 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, args: 1, 0); |
1305 | break; |
1306 | |
1307 | case V4L2_ENC_CMD_RESUME: |
1308 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n" ); |
1309 | enc->flags = 0; |
1310 | |
1311 | if (!atomic_read(v: &itv->capturing)) |
1312 | return -EPERM; |
1313 | |
1314 | if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, addr: &itv->i_flags)) |
1315 | return 0; |
1316 | |
1317 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, args: 1, 1); |
1318 | ivtv_unmute(itv); |
1319 | break; |
1320 | default: |
1321 | IVTV_DEBUG_IOCTL("Unknown cmd %d\n" , enc->cmd); |
1322 | return -EINVAL; |
1323 | } |
1324 | |
1325 | return 0; |
1326 | } |
1327 | |
1328 | static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) |
1329 | { |
1330 | struct ivtv *itv = fh2id(fh)->itv; |
1331 | |
1332 | switch (enc->cmd) { |
1333 | case V4L2_ENC_CMD_START: |
1334 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n" ); |
1335 | enc->flags = 0; |
1336 | return 0; |
1337 | |
1338 | case V4L2_ENC_CMD_STOP: |
1339 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n" ); |
1340 | enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; |
1341 | return 0; |
1342 | |
1343 | case V4L2_ENC_CMD_PAUSE: |
1344 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n" ); |
1345 | enc->flags = 0; |
1346 | return 0; |
1347 | |
1348 | case V4L2_ENC_CMD_RESUME: |
1349 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n" ); |
1350 | enc->flags = 0; |
1351 | return 0; |
1352 | default: |
1353 | IVTV_DEBUG_IOCTL("Unknown cmd %d\n" , enc->cmd); |
1354 | return -EINVAL; |
1355 | } |
1356 | } |
1357 | |
1358 | static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) |
1359 | { |
1360 | struct ivtv *itv = fh2id(fh)->itv; |
1361 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
1362 | u32 data[CX2341X_MBOX_MAX_DATA]; |
1363 | struct yuv_playback_info *yi = &itv->yuv_info; |
1364 | |
1365 | int pixfmt; |
1366 | static u32 pixel_format[16] = { |
1367 | V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */ |
1368 | V4L2_PIX_FMT_RGB565, |
1369 | V4L2_PIX_FMT_RGB555, |
1370 | V4L2_PIX_FMT_RGB444, |
1371 | V4L2_PIX_FMT_RGB32, |
1372 | 0, |
1373 | 0, |
1374 | 0, |
1375 | V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */ |
1376 | V4L2_PIX_FMT_YUV565, |
1377 | V4L2_PIX_FMT_YUV555, |
1378 | V4L2_PIX_FMT_YUV444, |
1379 | V4L2_PIX_FMT_YUV32, |
1380 | 0, |
1381 | 0, |
1382 | 0, |
1383 | }; |
1384 | |
1385 | if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
1386 | return -ENOTTY; |
1387 | if (!itv->osd_video_pbase) |
1388 | return -ENOTTY; |
1389 | |
1390 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | |
1391 | V4L2_FBUF_CAP_GLOBAL_ALPHA; |
1392 | |
1393 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, args: 0); |
1394 | data[0] |= (read_reg(0x2a00) >> 7) & 0x40; |
1395 | pixfmt = (data[0] >> 3) & 0xf; |
1396 | |
1397 | fb->fmt.pixelformat = pixel_format[pixfmt]; |
1398 | fb->fmt.width = itv->osd_rect.width; |
1399 | fb->fmt.height = itv->osd_rect.height; |
1400 | fb->fmt.field = V4L2_FIELD_INTERLACED; |
1401 | fb->fmt.bytesperline = fb->fmt.width; |
1402 | fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; |
1403 | fb->fmt.field = V4L2_FIELD_INTERLACED; |
1404 | if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8) |
1405 | fb->fmt.bytesperline *= 2; |
1406 | if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 || |
1407 | fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32) |
1408 | fb->fmt.bytesperline *= 2; |
1409 | fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height; |
1410 | fb->base = (void *)itv->osd_video_pbase; |
1411 | fb->flags = 0; |
1412 | |
1413 | if (itv->osd_chroma_key_state) |
1414 | fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; |
1415 | |
1416 | if (itv->osd_global_alpha_state) |
1417 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; |
1418 | |
1419 | if (yi->track_osd) |
1420 | fb->flags |= V4L2_FBUF_FLAG_OVERLAY; |
1421 | |
1422 | pixfmt &= 7; |
1423 | |
1424 | /* no local alpha for RGB565 or unknown formats */ |
1425 | if (pixfmt == 1 || pixfmt > 4) |
1426 | return 0; |
1427 | |
1428 | /* 16-bit formats have inverted local alpha */ |
1429 | if (pixfmt == 2 || pixfmt == 3) |
1430 | fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA; |
1431 | else |
1432 | fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA; |
1433 | |
1434 | if (itv->osd_local_alpha_state) { |
1435 | /* 16-bit formats have inverted local alpha */ |
1436 | if (pixfmt == 2 || pixfmt == 3) |
1437 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA; |
1438 | else |
1439 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; |
1440 | } |
1441 | |
1442 | return 0; |
1443 | } |
1444 | |
1445 | static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb) |
1446 | { |
1447 | struct ivtv_open_id *id = fh2id(fh); |
1448 | struct ivtv *itv = id->itv; |
1449 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
1450 | struct yuv_playback_info *yi = &itv->yuv_info; |
1451 | |
1452 | if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
1453 | return -ENOTTY; |
1454 | if (!itv->osd_video_pbase) |
1455 | return -ENOTTY; |
1456 | |
1457 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; |
1458 | itv->osd_local_alpha_state = |
1459 | (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; |
1460 | itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; |
1461 | ivtv_set_osd_alpha(itv); |
1462 | yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0; |
1463 | return 0; |
1464 | } |
1465 | |
1466 | static int ivtv_overlay(struct file *file, void *fh, unsigned int on) |
1467 | { |
1468 | struct ivtv_open_id *id = fh2id(fh); |
1469 | struct ivtv *itv = id->itv; |
1470 | struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; |
1471 | |
1472 | if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
1473 | return -ENOTTY; |
1474 | if (!itv->osd_video_pbase) |
1475 | return -ENOTTY; |
1476 | |
1477 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, args: 1, on != 0); |
1478 | |
1479 | return 0; |
1480 | } |
1481 | |
1482 | static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) |
1483 | { |
1484 | switch (sub->type) { |
1485 | case V4L2_EVENT_VSYNC: |
1486 | case V4L2_EVENT_EOS: |
1487 | return v4l2_event_subscribe(fh, sub, elems: 0, NULL); |
1488 | default: |
1489 | return v4l2_ctrl_subscribe_event(fh, sub); |
1490 | } |
1491 | } |
1492 | |
1493 | static int ivtv_log_status(struct file *file, void *fh) |
1494 | { |
1495 | struct ivtv *itv = fh2id(fh)->itv; |
1496 | u32 data[CX2341X_MBOX_MAX_DATA]; |
1497 | |
1498 | int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; |
1499 | struct v4l2_input vidin; |
1500 | struct v4l2_audio audin; |
1501 | int i; |
1502 | |
1503 | IVTV_INFO("Version: %s Card: %s\n" , IVTV_VERSION, itv->card_name); |
1504 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { |
1505 | struct tveeprom tv; |
1506 | |
1507 | ivtv_read_eeprom(itv, tv: &tv); |
1508 | } |
1509 | ivtv_call_all(itv, core, log_status); |
1510 | ivtv_get_input(itv, index: itv->active_input, input: &vidin); |
1511 | ivtv_get_audio_input(itv, index: itv->audio_input, input: &audin); |
1512 | IVTV_INFO("Video Input: %s\n" , vidin.name); |
1513 | IVTV_INFO("Audio Input: %s%s\n" , audin.name, |
1514 | itv->dualwatch_stereo_mode == V4L2_MPEG_AUDIO_MODE_DUAL ? |
1515 | " (Bilingual)" : "" ); |
1516 | if (has_output) { |
1517 | struct v4l2_output vidout; |
1518 | struct v4l2_audioout audout; |
1519 | int mode = itv->output_mode; |
1520 | static const char * const output_modes[5] = { |
1521 | "None" , |
1522 | "MPEG Streaming" , |
1523 | "YUV Streaming" , |
1524 | "YUV Frames" , |
1525 | "Passthrough" , |
1526 | }; |
1527 | static const char * const alpha_mode[4] = { |
1528 | "None" , |
1529 | "Global" , |
1530 | "Local" , |
1531 | "Global and Local" |
1532 | }; |
1533 | static const char * const pixel_format[16] = { |
1534 | "ARGB Indexed" , |
1535 | "RGB 5:6:5" , |
1536 | "ARGB 1:5:5:5" , |
1537 | "ARGB 1:4:4:4" , |
1538 | "ARGB 8:8:8:8" , |
1539 | "5" , |
1540 | "6" , |
1541 | "7" , |
1542 | "AYUV Indexed" , |
1543 | "YUV 5:6:5" , |
1544 | "AYUV 1:5:5:5" , |
1545 | "AYUV 1:4:4:4" , |
1546 | "AYUV 8:8:8:8" , |
1547 | "13" , |
1548 | "14" , |
1549 | "15" , |
1550 | }; |
1551 | |
1552 | ivtv_get_output(itv, index: itv->active_output, output: &vidout); |
1553 | ivtv_get_audio_output(itv, index: 0, output: &audout); |
1554 | IVTV_INFO("Video Output: %s\n" , vidout.name); |
1555 | if (mode < 0 || mode > OUT_PASSTHROUGH) |
1556 | mode = OUT_NONE; |
1557 | IVTV_INFO("Output Mode: %s\n" , output_modes[mode]); |
1558 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, args: 0); |
1559 | data[0] |= (read_reg(0x2a00) >> 7) & 0x40; |
1560 | IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n" , |
1561 | data[0] & 1 ? "On" : "Off" , |
1562 | alpha_mode[(data[0] >> 1) & 0x3], |
1563 | pixel_format[(data[0] >> 3) & 0xf]); |
1564 | } |
1565 | IVTV_INFO("Tuner: %s\n" , |
1566 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV" ); |
1567 | v4l2_ctrl_handler_log_status(hdl: &itv->cxhdl.hdl, prefix: itv->v4l2_dev.name); |
1568 | IVTV_INFO("Status flags: 0x%08lx\n" , itv->i_flags); |
1569 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { |
1570 | struct ivtv_stream *s = &itv->streams[i]; |
1571 | |
1572 | if (s->vdev.v4l2_dev == NULL || s->buffers == 0) |
1573 | continue; |
1574 | IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n" , s->name, s->s_flags, |
1575 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, |
1576 | (s->buffers * s->buf_size) / 1024, s->buffers); |
1577 | } |
1578 | |
1579 | IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n" , |
1580 | (long long)itv->mpg_data_received, |
1581 | (long long)itv->vbi_data_inserted); |
1582 | return 0; |
1583 | } |
1584 | |
1585 | static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) |
1586 | { |
1587 | struct ivtv_open_id *id = fh2id(fh: file->private_data); |
1588 | struct ivtv *itv = id->itv; |
1589 | |
1590 | IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n" , dec->cmd); |
1591 | return ivtv_video_command(itv, id, dc: dec, try: false); |
1592 | } |
1593 | |
1594 | static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) |
1595 | { |
1596 | struct ivtv_open_id *id = fh2id(fh: file->private_data); |
1597 | struct ivtv *itv = id->itv; |
1598 | |
1599 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n" , dec->cmd); |
1600 | return ivtv_video_command(itv, id, dc: dec, try: true); |
1601 | } |
1602 | |
1603 | static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) |
1604 | { |
1605 | struct ivtv_open_id *id = fh2id(fh: filp->private_data); |
1606 | struct ivtv *itv = id->itv; |
1607 | struct ivtv_stream *s = &itv->streams[id->type]; |
1608 | |
1609 | switch (cmd) { |
1610 | case IVTV_IOC_DMA_FRAME: { |
1611 | struct ivtv_dma_frame *args = arg; |
1612 | |
1613 | IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n" ); |
1614 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1615 | return -EINVAL; |
1616 | if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) |
1617 | return -EINVAL; |
1618 | if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL) |
1619 | return 0; |
1620 | if (ivtv_start_decoding(id, speed: id->type)) { |
1621 | return -EBUSY; |
1622 | } |
1623 | if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) { |
1624 | ivtv_release_stream(s); |
1625 | return -EBUSY; |
1626 | } |
1627 | /* Mark that this file handle started the UDMA_YUV mode */ |
1628 | id->yuv_frames = 1; |
1629 | if (args->y_source == NULL) |
1630 | return 0; |
1631 | return ivtv_yuv_prep_frame(itv, args); |
1632 | } |
1633 | |
1634 | case IVTV_IOC_PASSTHROUGH_MODE: |
1635 | IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n" ); |
1636 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1637 | return -EINVAL; |
1638 | return ivtv_passthrough_mode(itv, enable: *(int *)arg != 0); |
1639 | default: |
1640 | return -EINVAL; |
1641 | } |
1642 | return 0; |
1643 | } |
1644 | |
1645 | static long ivtv_default(struct file *file, void *fh, bool valid_prio, |
1646 | unsigned int cmd, void *arg) |
1647 | { |
1648 | struct ivtv *itv = fh2id(fh)->itv; |
1649 | |
1650 | if (!valid_prio) { |
1651 | switch (cmd) { |
1652 | case IVTV_IOC_PASSTHROUGH_MODE: |
1653 | return -EBUSY; |
1654 | } |
1655 | } |
1656 | |
1657 | switch (cmd) { |
1658 | case VIDIOC_INT_RESET: { |
1659 | u32 val = *(u32 *)arg; |
1660 | |
1661 | if ((val == 0 && itv->options.newi2c) || (val & 0x01)) |
1662 | ivtv_reset_ir_gpio(itv); |
1663 | if (val & 0x02) |
1664 | v4l2_subdev_call(itv->sd_video, core, reset, 0); |
1665 | break; |
1666 | } |
1667 | |
1668 | case IVTV_IOC_DMA_FRAME: |
1669 | case IVTV_IOC_PASSTHROUGH_MODE: |
1670 | return ivtv_decoder_ioctls(filp: file, cmd, arg: (void *)arg); |
1671 | |
1672 | default: |
1673 | return -ENOTTY; |
1674 | } |
1675 | return 0; |
1676 | } |
1677 | |
1678 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { |
1679 | .vidioc_querycap = ivtv_querycap, |
1680 | .vidioc_s_audio = ivtv_s_audio, |
1681 | .vidioc_g_audio = ivtv_g_audio, |
1682 | .vidioc_enumaudio = ivtv_enumaudio, |
1683 | .vidioc_s_audout = ivtv_s_audout, |
1684 | .vidioc_g_audout = ivtv_g_audout, |
1685 | .vidioc_enum_input = ivtv_enum_input, |
1686 | .vidioc_enum_output = ivtv_enum_output, |
1687 | .vidioc_enumaudout = ivtv_enumaudout, |
1688 | .vidioc_g_pixelaspect = ivtv_g_pixelaspect, |
1689 | .vidioc_s_selection = ivtv_s_selection, |
1690 | .vidioc_g_selection = ivtv_g_selection, |
1691 | .vidioc_g_input = ivtv_g_input, |
1692 | .vidioc_s_input = ivtv_s_input, |
1693 | .vidioc_g_output = ivtv_g_output, |
1694 | .vidioc_s_output = ivtv_s_output, |
1695 | .vidioc_g_frequency = ivtv_g_frequency, |
1696 | .vidioc_s_frequency = ivtv_s_frequency, |
1697 | .vidioc_s_tuner = ivtv_s_tuner, |
1698 | .vidioc_g_tuner = ivtv_g_tuner, |
1699 | .vidioc_g_enc_index = ivtv_g_enc_index, |
1700 | .vidioc_g_fbuf = ivtv_g_fbuf, |
1701 | .vidioc_s_fbuf = ivtv_s_fbuf, |
1702 | .vidioc_g_std = ivtv_g_std, |
1703 | .vidioc_s_std = ivtv_s_std, |
1704 | .vidioc_overlay = ivtv_overlay, |
1705 | .vidioc_log_status = ivtv_log_status, |
1706 | .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, |
1707 | .vidioc_encoder_cmd = ivtv_encoder_cmd, |
1708 | .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, |
1709 | .vidioc_decoder_cmd = ivtv_decoder_cmd, |
1710 | .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, |
1711 | .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, |
1712 | .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, |
1713 | .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, |
1714 | .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap, |
1715 | .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out, |
1716 | .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay, |
1717 | .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out, |
1718 | .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap, |
1719 | .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap, |
1720 | .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap, |
1721 | .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out, |
1722 | .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay, |
1723 | .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out, |
1724 | .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap, |
1725 | .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap, |
1726 | .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap, |
1727 | .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out, |
1728 | .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay, |
1729 | .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out, |
1730 | .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap, |
1731 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1732 | .vidioc_g_register = ivtv_g_register, |
1733 | .vidioc_s_register = ivtv_s_register, |
1734 | #endif |
1735 | .vidioc_default = ivtv_default, |
1736 | .vidioc_subscribe_event = ivtv_subscribe_event, |
1737 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
1738 | }; |
1739 | |
1740 | void ivtv_set_funcs(struct video_device *vdev) |
1741 | { |
1742 | vdev->ioctl_ops = &ivtv_ioctl_ops; |
1743 | } |
1744 | |