blob: e5ce970266f33217cdf0b43fde09940b73b045f1 [file] [log] [blame]
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001/*
2 ioctl system call
3 Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com>
4 Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "ivtv-driver.h"
22#include "ivtv-version.h"
23#include "ivtv-mailbox.h"
24#include "ivtv-i2c.h"
25#include "ivtv-queue.h"
26#include "ivtv-fileops.h"
27#include "ivtv-vbi.h"
Hans Verkuil33c0fca2007-08-23 06:32:46 -030028#include "ivtv-routing.h"
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030029#include "ivtv-streams.h"
30#include "ivtv-yuv.h"
31#include "ivtv-ioctl.h"
32#include "ivtv-gpio.h"
33#include "ivtv-controls.h"
34#include "ivtv-cards.h"
35#include <media/saa7127.h>
36#include <media/tveeprom.h>
37#include <media/v4l2-chip-ident.h>
Hans Verkuil09250192010-03-27 14:10:13 -030038#include <media/v4l2-event.h>
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030039#include <linux/dvb/audio.h>
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030040
Hans Verkuilfeb5bce2008-05-01 09:22:13 -030041u16 ivtv_service2vbi(int type)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030042{
43 switch (type) {
44 case V4L2_SLICED_TELETEXT_B:
45 return IVTV_SLICED_TYPE_TELETEXT_B;
46 case V4L2_SLICED_CAPTION_525:
47 return IVTV_SLICED_TYPE_CAPTION_525;
48 case V4L2_SLICED_WSS_625:
49 return IVTV_SLICED_TYPE_WSS_625;
50 case V4L2_SLICED_VPS:
51 return IVTV_SLICED_TYPE_VPS;
52 default:
53 return 0;
54 }
55}
56
57static int valid_service_line(int field, int line, int is_pal)
58{
59 return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
60 (!is_pal && line >= 10 && line < 22);
61}
62
63static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
64{
65 u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
66 int i;
67
68 set = set & valid_set;
69 if (set == 0 || !valid_service_line(field, line, is_pal)) {
70 return 0;
71 }
72 if (!is_pal) {
73 if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
74 return V4L2_SLICED_CAPTION_525;
75 }
76 else {
77 if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
78 return V4L2_SLICED_VPS;
79 if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
80 return V4L2_SLICED_WSS_625;
81 if (line == 23)
82 return 0;
83 }
84 for (i = 0; i < 32; i++) {
85 if ((1 << i) & set)
86 return 1 << i;
87 }
88 return 0;
89}
90
Hans Verkuilfeb5bce2008-05-01 09:22:13 -030091void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030092{
93 u16 set = fmt->service_set;
94 int f, l;
95
96 fmt->service_set = 0;
97 for (f = 0; f < 2; f++) {
98 for (l = 0; l < 24; l++) {
99 fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
100 }
101 }
102}
103
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300104static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300105{
106 int f, l;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300107
108 for (f = 0; f < 2; f++) {
109 for (l = 0; l < 24; l++) {
110 fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300111 }
112 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300113}
114
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300115u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300116{
117 int f, l;
118 u16 set = 0;
119
120 for (f = 0; f < 2; f++) {
121 for (l = 0; l < 24; l++) {
122 set |= fmt->service_lines[f][l];
123 }
124 }
125 return set;
126}
127
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300128void ivtv_set_osd_alpha(struct ivtv *itv)
129{
130 ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
131 itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
Hans Verkuilfd8b2812007-08-23 10:13:15 -0300132 ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300133}
134
135int ivtv_set_speed(struct ivtv *itv, int speed)
136{
137 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300138 int single_step = (speed == 1 || speed == -1);
139 DEFINE_WAIT(wait);
140
141 if (speed == 0) speed = 1000;
142
143 /* No change? */
144 if (speed == itv->speed && !single_step)
145 return 0;
146
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300147 if (single_step && (speed < 0) == (itv->speed < 0)) {
148 /* Single step video and no need to change direction */
149 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
150 itv->speed = speed;
151 return 0;
152 }
153 if (single_step)
154 /* Need to change direction */
155 speed = speed < 0 ? -1000 : 1000;
156
157 data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
158 data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
159 data[1] = (speed < 0);
160 data[2] = speed < 0 ? 3 : 7;
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300161 data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300162 data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
163 data[5] = 0;
164 data[6] = 0;
165
166 if (speed == 1500 || speed == -1500) data[0] |= 1;
167 else if (speed == 2000 || speed == -2000) data[0] |= 2;
168 else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
169 else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
170
171 /* If not decoding, just change speed setting */
172 if (atomic_read(&itv->decoding) > 0) {
173 int got_sig = 0;
174
175 /* Stop all DMA and decoding activity */
176 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
177
178 /* Wait for any DMA to finish */
Hans Verkuilcdc03782011-10-11 06:06:58 -0300179 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300180 prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a422009-05-02 11:10:23 -0300181 while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300182 got_sig = signal_pending(current);
183 if (got_sig)
184 break;
185 got_sig = 0;
186 schedule();
187 }
188 finish_wait(&itv->dma_waitq, &wait);
Hans Verkuilcdc03782011-10-11 06:06:58 -0300189 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300190 if (got_sig)
191 return -EINTR;
192
193 /* Change Speed safely */
194 ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
195 IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
196 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
197 }
198 if (single_step) {
199 speed = (speed < 0) ? -1 : 1;
200 ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
201 }
202 itv->speed = speed;
203 return 0;
204}
205
206static int ivtv_validate_speed(int cur_speed, int new_speed)
207{
208 int fact = new_speed < 0 ? -1 : 1;
209 int s;
210
Hans Verkuil94dee762008-04-26 09:26:13 -0300211 if (cur_speed == 0)
212 cur_speed = 1000;
213 if (new_speed < 0)
214 new_speed = -new_speed;
215 if (cur_speed < 0)
216 cur_speed = -cur_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300217
218 if (cur_speed <= new_speed) {
Hans Verkuil94dee762008-04-26 09:26:13 -0300219 if (new_speed > 1500)
220 return fact * 2000;
221 if (new_speed > 1000)
222 return fact * 1500;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300223 }
224 else {
Hans Verkuil94dee762008-04-26 09:26:13 -0300225 if (new_speed >= 2000)
226 return fact * 2000;
227 if (new_speed >= 1500)
228 return fact * 1500;
229 if (new_speed >= 1000)
230 return fact * 1000;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300231 }
Hans Verkuil94dee762008-04-26 09:26:13 -0300232 if (new_speed == 0)
233 return 1000;
234 if (new_speed == 1 || new_speed == 1000)
235 return fact * new_speed;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300236
237 s = new_speed;
238 new_speed = 1000 / new_speed;
239 if (1000 / cur_speed == new_speed)
240 new_speed += (cur_speed < s) ? -1 : 1;
241 if (new_speed > 60) return 1000 / (fact * 60);
242 return 1000 / (fact * new_speed);
243}
244
245static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
Hans Verkuilda8ec562011-11-24 09:58:53 -0300246 struct v4l2_decoder_cmd *dc, int try)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300247{
248 struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
249
250 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
251 return -EINVAL;
252
Hans Verkuilda8ec562011-11-24 09:58:53 -0300253 switch (dc->cmd) {
254 case V4L2_DEC_CMD_START: {
255 dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
256 dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
257 if (dc->start.speed < 0)
258 dc->start.format = V4L2_DEC_START_FMT_GOP;
259 else
260 dc->start.format = V4L2_DEC_START_FMT_NONE;
261 if (dc->start.speed != 500 && dc->start.speed != 1500)
262 dc->flags = dc->start.speed == 1000 ? 0 :
263 V4L2_DEC_CMD_START_MUTE_AUDIO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300264 if (try) break;
265
Hans Verkuilda8ec562011-11-24 09:58:53 -0300266 itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300267 if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
268 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300269 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
270 /* forces ivtv_set_speed to be called */
271 itv->speed = 0;
272 }
Hans Verkuilda8ec562011-11-24 09:58:53 -0300273 return ivtv_start_decoding(id, dc->start.speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300274 }
275
Hans Verkuilda8ec562011-11-24 09:58:53 -0300276 case V4L2_DEC_CMD_STOP:
277 dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
278 if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
279 dc->stop.pts = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300280 if (try) break;
281 if (atomic_read(&itv->decoding) == 0)
282 return 0;
283 if (itv->output_mode != OUT_MPG)
284 return -EBUSY;
285
286 itv->output_mode = OUT_NONE;
Hans Verkuilda8ec562011-11-24 09:58:53 -0300287 return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300288
Hans Verkuilda8ec562011-11-24 09:58:53 -0300289 case V4L2_DEC_CMD_PAUSE:
290 dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300291 if (try) break;
Hans Verkuil1a806402012-09-05 08:39:48 -0300292 if (!atomic_read(&itv->decoding))
293 return -EPERM;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300294 if (itv->output_mode != OUT_MPG)
295 return -EBUSY;
296 if (atomic_read(&itv->decoding) > 0) {
297 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
Hans Verkuilda8ec562011-11-24 09:58:53 -0300298 (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
Hans Verkuilac425142007-07-22 08:46:38 -0300299 set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300300 }
301 break;
302
Hans Verkuilda8ec562011-11-24 09:58:53 -0300303 case V4L2_DEC_CMD_RESUME:
304 dc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300305 if (try) break;
Hans Verkuil1a806402012-09-05 08:39:48 -0300306 if (!atomic_read(&itv->decoding))
307 return -EPERM;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300308 if (itv->output_mode != OUT_MPG)
309 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300310 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
311 int speed = itv->speed;
312 itv->speed = 0;
313 return ivtv_start_decoding(id, speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300314 }
315 break;
316
317 default:
318 return -EINVAL;
319 }
320 return 0;
321}
322
Hans Verkuil3f038d82008-05-29 16:43:54 -0300323static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300324{
Hans Verkuil2f824412011-03-12 06:43:28 -0300325 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300326 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300327
Hans Verkuile88360c2008-06-21 08:00:56 -0300328 vbifmt->reserved[0] = 0;
329 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300330 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300331 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300332 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil30634e82012-09-05 10:38:10 -0300333 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
Hans Verkuil3f038d82008-05-29 16:43:54 -0300334 if (itv->is_60hz) {
335 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
336 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
337 } else {
338 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
339 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
340 }
341 vbifmt->service_set = ivtv_get_service_set(vbifmt);
342 return 0;
343}
344
345static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
346{
Hans Verkuil2f824412011-03-12 06:43:28 -0300347 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300348 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300349 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300350
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300351 pixfmt->width = itv->cxhdl.width;
352 pixfmt->height = itv->cxhdl.height;
Hans Verkuile88360c2008-06-21 08:00:56 -0300353 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
354 pixfmt->field = V4L2_FIELD_INTERLACED;
355 pixfmt->priv = 0;
356 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
357 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
Hans Verkuila4a78712009-02-06 15:31:59 -0300358 /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
359 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
Hans Verkuile88360c2008-06-21 08:00:56 -0300360 pixfmt->bytesperline = 720;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300361 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300362 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
363 pixfmt->sizeimage = 128 * 1024;
364 pixfmt->bytesperline = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300365 }
366 return 0;
367}
368
Hans Verkuil3f038d82008-05-29 16:43:54 -0300369static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300370{
Hans Verkuil2f824412011-03-12 06:43:28 -0300371 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300372 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300373
Hans Verkuile88360c2008-06-21 08:00:56 -0300374 vbifmt->sampling_rate = 27000000;
375 vbifmt->offset = 248;
376 vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
377 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
378 vbifmt->start[0] = itv->vbi.start[0];
379 vbifmt->start[1] = itv->vbi.start[1];
380 vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
381 vbifmt->flags = 0;
382 vbifmt->reserved[0] = 0;
383 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300384 return 0;
385}
386
387static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
388{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300389 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300390 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300391 struct ivtv *itv = id->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300392
Hans Verkuile88360c2008-06-21 08:00:56 -0300393 vbifmt->reserved[0] = 0;
394 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300395 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300396
Hans Verkuil3f038d82008-05-29 16:43:54 -0300397 if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
398 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
399 V4L2_SLICED_VBI_525;
400 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300401 return 0;
402 }
403
Hans Verkuil4ff07902010-03-14 12:18:18 -0300404 v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300405 vbifmt->service_set = ivtv_get_service_set(vbifmt);
406 return 0;
407}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300408
Hans Verkuil3f038d82008-05-29 16:43:54 -0300409static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
410{
Hans Verkuil2f824412011-03-12 06:43:28 -0300411 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300412 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300413 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300414
Hans Verkuil3f038d82008-05-29 16:43:54 -0300415 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300416 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300417 pixfmt->width = itv->main_rect.width;
418 pixfmt->height = itv->main_rect.height;
419 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
420 pixfmt->field = V4L2_FIELD_INTERLACED;
421 pixfmt->priv = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300422 if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
423 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
424 case IVTV_YUV_MODE_INTERLACED:
Hans Verkuile88360c2008-06-21 08:00:56 -0300425 pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
Hans Verkuil3f038d82008-05-29 16:43:54 -0300426 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
427 break;
428 case IVTV_YUV_MODE_PROGRESSIVE:
Hans Verkuile88360c2008-06-21 08:00:56 -0300429 pixfmt->field = V4L2_FIELD_NONE;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300430 break;
431 default:
Hans Verkuile88360c2008-06-21 08:00:56 -0300432 pixfmt->field = V4L2_FIELD_ANY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300433 break;
434 }
Hans Verkuile88360c2008-06-21 08:00:56 -0300435 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
436 pixfmt->bytesperline = 720;
437 pixfmt->width = itv->yuv_info.v4l2_src_w;
438 pixfmt->height = itv->yuv_info.v4l2_src_h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300439 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
Hans Verkuile88360c2008-06-21 08:00:56 -0300440 pixfmt->sizeimage =
441 1080 * ((pixfmt->height + 31) & ~31);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300442 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300443 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
444 pixfmt->sizeimage = 128 * 1024;
445 pixfmt->bytesperline = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300446 }
447 return 0;
448}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300449
Hans Verkuil3f038d82008-05-29 16:43:54 -0300450static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
451{
Hans Verkuil2f824412011-03-12 06:43:28 -0300452 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300453 struct v4l2_window *winfmt = &fmt->fmt.win;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300454
455 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
456 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300457 winfmt->chromakey = itv->osd_chroma_key;
458 winfmt->global_alpha = itv->osd_global_alpha;
459 winfmt->field = V4L2_FIELD_INTERLACED;
460 winfmt->clips = NULL;
461 winfmt->clipcount = 0;
462 winfmt->bitmap = NULL;
463 winfmt->w.top = winfmt->w.left = 0;
464 winfmt->w.width = itv->osd_rect.width;
465 winfmt->w.height = itv->osd_rect.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300466 return 0;
467}
468
469static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
470{
471 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
472}
473
474static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
475{
Hans Verkuil2f824412011-03-12 06:43:28 -0300476 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300477 struct ivtv *itv = id->itv;
478 int w = fmt->fmt.pix.width;
479 int h = fmt->fmt.pix.height;
Hans Verkuila4a78712009-02-06 15:31:59 -0300480 int min_h = 2;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300481
482 w = min(w, 720);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300483 w = max(w, 2);
Hans Verkuila4a78712009-02-06 15:31:59 -0300484 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
485 /* YUV height must be a multiple of 32 */
486 h &= ~0x1f;
487 min_h = 32;
488 }
Hans Verkuil3f038d82008-05-29 16:43:54 -0300489 h = min(h, itv->is_50hz ? 576 : 480);
Hans Verkuila4a78712009-02-06 15:31:59 -0300490 h = max(h, min_h);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300491 ivtv_g_fmt_vid_cap(file, fh, fmt);
492 fmt->fmt.pix.width = w;
493 fmt->fmt.pix.height = h;
494 return 0;
495}
496
497static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
498{
499 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
500}
501
502static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
503{
504 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300505 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300506 struct ivtv *itv = id->itv;
507
508 if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
509 return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300510
511 /* set sliced VBI capture format */
512 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuile88360c2008-06-21 08:00:56 -0300513 vbifmt->reserved[0] = 0;
514 vbifmt->reserved[1] = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300515
516 if (vbifmt->service_set)
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300517 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300518 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300519 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300520 return 0;
521}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300522
Hans Verkuil3f038d82008-05-29 16:43:54 -0300523static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
524{
Hans Verkuil2f824412011-03-12 06:43:28 -0300525 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuileffc3462008-09-06 08:24:37 -0300526 s32 w = fmt->fmt.pix.width;
527 s32 h = fmt->fmt.pix.height;
528 int field = fmt->fmt.pix.field;
529 int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300530
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300531 w = min(w, 720);
532 w = max(w, 2);
Hans Verkuil962d6992008-10-11 09:00:39 -0300533 /* Why can the height be 576 even when the output is NTSC?
534
535 Internally the buffers of the PVR350 are always set to 720x576. The
536 decoded video frame will always be placed in the top left corner of
537 this buffer. For any video which is not 720x576, the buffer will
538 then be cropped to remove the unused right and lower areas, with
539 the remaining image being scaled by the hardware to fit the display
540 area. The video can be scaled both up and down, so a 720x480 video
541 can be displayed full-screen on PAL and a 720x576 video can be
542 displayed without cropping on NTSC.
543
544 Note that the scaling only occurs on the video stream, the osd
545 resolution is locked to the broadcast standard and not scaled.
546
547 Thanks to Ian Armstrong for this explanation. */
548 h = min(h, 576);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300549 h = max(h, 2);
550 if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300551 fmt->fmt.pix.field = field;
Hans Verkuileffc3462008-09-06 08:24:37 -0300552 fmt->fmt.pix.width = w;
553 fmt->fmt.pix.height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300554 return ret;
555}
556
557static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
558{
Hans Verkuil2f824412011-03-12 06:43:28 -0300559 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300560 u32 chromakey = fmt->fmt.win.chromakey;
561 u8 global_alpha = fmt->fmt.win.global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300562
563 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
564 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300565 ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
566 fmt->fmt.win.chromakey = chromakey;
567 fmt->fmt.win.global_alpha = global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300568 return 0;
569}
570
571static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
572{
573 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
574}
575
576static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
577{
Hans Verkuil2f824412011-03-12 06:43:28 -0300578 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300579 struct ivtv *itv = id->itv;
Hans Verkuil475977a2010-05-08 16:28:51 -0300580 struct v4l2_mbus_framefmt mbus_fmt;
Hans Verkuileffc3462008-09-06 08:24:37 -0300581 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300582 int w = fmt->fmt.pix.width;
583 int h = fmt->fmt.pix.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300584
585 if (ret)
586 return ret;
587
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300588 if (itv->cxhdl.width == w && itv->cxhdl.height == h)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300589 return 0;
590
591 if (atomic_read(&itv->capturing) > 0)
592 return -EBUSY;
593
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300594 itv->cxhdl.width = w;
595 itv->cxhdl.height = h;
596 if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300597 fmt->fmt.pix.width /= 2;
Hans Verkuil475977a2010-05-08 16:28:51 -0300598 mbus_fmt.width = fmt->fmt.pix.width;
599 mbus_fmt.height = h;
600 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
601 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300602 return ivtv_g_fmt_vid_cap(file, fh, fmt);
603}
604
605static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
606{
Hans Verkuil2f824412011-03-12 06:43:28 -0300607 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300608
Hans Verkuila8b86432008-10-04 08:05:30 -0300609 if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
610 return -EBUSY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300611 itv->vbi.sliced_in->service_set = 0;
Hans Verkuila8b86432008-10-04 08:05:30 -0300612 itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
Hans Verkuil4ff07902010-03-14 12:18:18 -0300613 v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300614 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
615}
616
617static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
618{
619 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300620 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300621 struct ivtv *itv = id->itv;
622 int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
623
624 if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
625 return ret;
626
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300627 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuila8b86432008-10-04 08:05:30 -0300628 if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300629 return -EBUSY;
Hans Verkuila8b86432008-10-04 08:05:30 -0300630 itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
Hans Verkuil4ff07902010-03-14 12:18:18 -0300631 v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300632 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
633 return 0;
634}
635
Hans Verkuil3f038d82008-05-29 16:43:54 -0300636static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300637{
Hans Verkuil2f824412011-03-12 06:43:28 -0300638 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300639 struct ivtv *itv = id->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300640 struct yuv_playback_info *yi = &itv->yuv_info;
641 int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300642
Hans Verkuil3f038d82008-05-29 16:43:54 -0300643 if (ret)
644 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300645
Hans Verkuil3f038d82008-05-29 16:43:54 -0300646 if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
647 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300648
Hans Verkuil3f038d82008-05-29 16:43:54 -0300649 /* Return now if we already have some frame data */
650 if (yi->stream_size)
651 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300652
Hans Verkuil3f038d82008-05-29 16:43:54 -0300653 yi->v4l2_src_w = fmt->fmt.pix.width;
654 yi->v4l2_src_h = fmt->fmt.pix.height;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300655
Hans Verkuil3f038d82008-05-29 16:43:54 -0300656 switch (fmt->fmt.pix.field) {
657 case V4L2_FIELD_NONE:
658 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300659 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300660 case V4L2_FIELD_ANY:
661 yi->lace_mode = IVTV_YUV_MODE_AUTO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300662 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300663 case V4L2_FIELD_INTERLACED_BT:
664 yi->lace_mode =
665 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
666 break;
667 case V4L2_FIELD_INTERLACED_TB:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300668 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -0300669 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
670 break;
671 }
672 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
673
674 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
675 itv->dma_data_req_size =
676 1080 * ((yi->v4l2_src_h + 31) & ~31);
677
Hans Verkuil3f038d82008-05-29 16:43:54 -0300678 return 0;
679}
680
681static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
682{
Hans Verkuil2f824412011-03-12 06:43:28 -0300683 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300684 int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
685
686 if (ret == 0) {
687 itv->osd_chroma_key = fmt->fmt.win.chromakey;
688 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
689 ivtv_set_osd_alpha(itv);
690 }
691 return ret;
692}
693
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300694static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300695{
Hans Verkuil2f824412011-03-12 06:43:28 -0300696 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300697
698 chip->ident = V4L2_IDENT_NONE;
699 chip->revision = 0;
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300700 if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
701 if (v4l2_chip_match_host(&chip->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300702 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
703 return 0;
704 }
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300705 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
706 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300707 return -EINVAL;
708 /* TODO: is this correct? */
709 return ivtv_call_all_err(itv, core, g_chip_ident, chip);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300710}
711
Hans Verkuil36ecd492008-06-25 06:00:17 -0300712#ifdef CONFIG_VIDEO_ADV_DEBUG
713static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
714{
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300715 struct v4l2_dbg_register *regs = arg;
Hans Verkuiladb65bc2008-06-25 06:32:44 -0300716 volatile u8 __iomem *reg_start;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300717
718 if (!capable(CAP_SYS_ADMIN))
719 return -EPERM;
720 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
721 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
722 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
723 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
724 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
Roel Kluin223ffe52009-05-02 16:38:47 -0300725 else if (regs->reg < IVTV_ENCODER_SIZE)
Hans Verkuil36ecd492008-06-25 06:00:17 -0300726 reg_start = itv->enc_mem;
727 else
728 return -EINVAL;
729
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300730 regs->size = 4;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300731 if (cmd == VIDIOC_DBG_G_REGISTER)
732 regs->val = readl(regs->reg + reg_start);
733 else
734 writel(regs->val, regs->reg + reg_start);
Hans Verkuil36ecd492008-06-25 06:00:17 -0300735 return 0;
736}
737
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300738static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300739{
Hans Verkuil2f824412011-03-12 06:43:28 -0300740 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300741
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300742 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300743 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300744 /* TODO: subdev errors should not be ignored, this should become a
745 subdev helper function. */
746 ivtv_call_all(itv, core, g_register, reg);
747 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300748}
749
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300750static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300751{
Hans Verkuil2f824412011-03-12 06:43:28 -0300752 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300753
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300754 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300755 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300756 /* TODO: subdev errors should not be ignored, this should become a
757 subdev helper function. */
758 ivtv_call_all(itv, core, s_register, reg);
759 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300760}
Hans Verkuil36ecd492008-06-25 06:00:17 -0300761#endif
Hans Verkuil3f038d82008-05-29 16:43:54 -0300762
Hans Verkuil3f038d82008-05-29 16:43:54 -0300763static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
764{
Hans Verkuild0c8b2d2011-11-07 07:25:10 -0300765 struct ivtv_open_id *id = fh2id(file->private_data);
766 struct ivtv *itv = id->itv;
767 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -0300768
Hans Verkuil3f038d82008-05-29 16:43:54 -0300769 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
770 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
Hans Verkuil8ac05ae2009-02-07 07:02:27 -0300771 snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
Hans Verkuild0c8b2d2011-11-07 07:25:10 -0300772 vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
773 vcap->device_caps = s->caps;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300774 return 0;
775}
776
777static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
778{
Hans Verkuil2f824412011-03-12 06:43:28 -0300779 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300780
781 return ivtv_get_audio_input(itv, vin->index, vin);
782}
783
784static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
785{
Hans Verkuil2f824412011-03-12 06:43:28 -0300786 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300787
788 vin->index = itv->audio_input;
789 return ivtv_get_audio_input(itv, vin->index, vin);
790}
791
Hans Verkuil0e8025b2012-09-04 11:59:31 -0300792static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300793{
Hans Verkuil2f824412011-03-12 06:43:28 -0300794 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300795
796 if (vout->index >= itv->nof_audio_inputs)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300797 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300798
799 itv->audio_input = vout->index;
800 ivtv_audio_set_io(itv);
801
802 return 0;
803}
804
805static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
806{
Hans Verkuil2f824412011-03-12 06:43:28 -0300807 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300808
809 /* set it to defaults from our table */
810 return ivtv_get_audio_output(itv, vin->index, vin);
811}
812
813static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
814{
Hans Verkuil2f824412011-03-12 06:43:28 -0300815 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300816
817 vin->index = 0;
818 return ivtv_get_audio_output(itv, vin->index, vin);
819}
820
Hans Verkuilba9425b2012-09-04 12:03:49 -0300821static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300822{
Hans Verkuil2f824412011-03-12 06:43:28 -0300823 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300824
Hans Verkuilba9425b2012-09-04 12:03:49 -0300825 if (itv->card->video_outputs == NULL || vout->index != 0)
826 return -EINVAL;
827 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300828}
829
830static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
831{
Hans Verkuil2f824412011-03-12 06:43:28 -0300832 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300833
834 /* set it to defaults from our table */
835 return ivtv_get_input(itv, vin->index, vin);
836}
837
838static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
839{
Hans Verkuil2f824412011-03-12 06:43:28 -0300840 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300841
842 return ivtv_get_output(itv, vout->index, vout);
843}
844
845static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
846{
Hans Verkuil2f824412011-03-12 06:43:28 -0300847 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300848 struct ivtv *itv = id->itv;
849 struct yuv_playback_info *yi = &itv->yuv_info;
850 int streamtype;
851
852 streamtype = id->type;
853
854 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
855 return -EINVAL;
856 cropcap->bounds.top = cropcap->bounds.left = 0;
857 cropcap->bounds.width = 720;
858 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
859 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
860 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
861 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
862 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
863 if (yi->track_osd) {
864 cropcap->bounds.width = yi->osd_full_w;
865 cropcap->bounds.height = yi->osd_full_h;
866 } else {
867 cropcap->bounds.width = 720;
868 cropcap->bounds.height =
869 itv->is_out_50hz ? 576 : 480;
870 }
871 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
872 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
873 } else {
874 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
875 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
876 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
877 }
878 cropcap->defrect = cropcap->bounds;
879 return 0;
880}
881
Hans Verkuil4f9965942012-09-05 05:10:48 -0300882static int ivtv_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300883{
Hans Verkuil2f824412011-03-12 06:43:28 -0300884 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300885 struct ivtv *itv = id->itv;
886 struct yuv_playback_info *yi = &itv->yuv_info;
887 int streamtype;
888
889 streamtype = id->type;
890
Hans Verkuil3f038d82008-05-29 16:43:54 -0300891 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
892 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
893 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
894 yi->main_rect = crop->c;
895 return 0;
896 } else {
897 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
898 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
899 itv->main_rect = crop->c;
900 return 0;
901 }
902 }
903 return -EINVAL;
904 }
905 return -EINVAL;
906}
907
908static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
909{
Hans Verkuil2f824412011-03-12 06:43:28 -0300910 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300911 struct ivtv *itv = id->itv;
912 struct yuv_playback_info *yi = &itv->yuv_info;
913 int streamtype;
914
915 streamtype = id->type;
916
917 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
918 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
919 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
920 crop->c = yi->main_rect;
921 else
922 crop->c = itv->main_rect;
923 return 0;
924 }
925 return -EINVAL;
926}
927
928static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
929{
930 static struct v4l2_fmtdesc formats[] = {
931 { 0, 0, 0,
932 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
933 { 0, 0, 0, 0 }
934 },
935 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
936 "MPEG", V4L2_PIX_FMT_MPEG,
937 { 0, 0, 0, 0 }
938 }
939 };
940 enum v4l2_buf_type type = fmt->type;
941
942 if (fmt->index > 1)
943 return -EINVAL;
944
945 *fmt = formats[fmt->index];
946 fmt->type = type;
947 return 0;
948}
949
950static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
951{
Hans Verkuil2f824412011-03-12 06:43:28 -0300952 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300953
954 static struct v4l2_fmtdesc formats[] = {
955 { 0, 0, 0,
956 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
957 { 0, 0, 0, 0 }
958 },
959 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
960 "MPEG", V4L2_PIX_FMT_MPEG,
961 { 0, 0, 0, 0 }
962 }
963 };
964 enum v4l2_buf_type type = fmt->type;
965
966 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
967 return -EINVAL;
968
969 if (fmt->index > 1)
970 return -EINVAL;
971
972 *fmt = formats[fmt->index];
973 fmt->type = type;
974
975 return 0;
976}
977
978static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
979{
Hans Verkuil2f824412011-03-12 06:43:28 -0300980 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300981
982 *i = itv->active_input;
983
984 return 0;
985}
986
987int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
988{
Hans Verkuil2f824412011-03-12 06:43:28 -0300989 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuilf659f0e72012-09-05 08:56:55 -0300990 v4l2_std_id std;
991 int i;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300992
993 if (inp < 0 || inp >= itv->nof_inputs)
994 return -EINVAL;
995
996 if (inp == itv->active_input) {
997 IVTV_DEBUG_INFO("Input unchanged\n");
998 return 0;
999 }
1000
1001 if (atomic_read(&itv->capturing) > 0) {
1002 return -EBUSY;
1003 }
1004
1005 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
1006 itv->active_input, inp);
1007
1008 itv->active_input = inp;
1009 /* Set the audio input to whatever is appropriate for the
1010 input type. */
1011 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1012
Hans Verkuilf659f0e72012-09-05 08:56:55 -03001013 if (itv->card->video_inputs[inp].video_type == IVTV_CARD_INPUT_VID_TUNER)
1014 std = itv->tuner_std;
1015 else
1016 std = V4L2_STD_ALL;
1017 for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++)
1018 itv->streams[i].vdev->tvnorms = std;
1019
Hans Verkuil3f038d82008-05-29 16:43:54 -03001020 /* prevent others from messing with the streams until
1021 we're finished changing inputs. */
1022 ivtv_mute(itv);
1023 ivtv_video_set_io(itv);
1024 ivtv_audio_set_io(itv);
1025 ivtv_unmute(itv);
1026
1027 return 0;
1028}
1029
1030static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1031{
Hans Verkuil2f824412011-03-12 06:43:28 -03001032 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001033
1034 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1035 return -EINVAL;
1036
1037 *i = itv->active_output;
1038
1039 return 0;
1040}
1041
1042static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1043{
Hans Verkuil2f824412011-03-12 06:43:28 -03001044 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001045
1046 if (outp >= itv->card->nof_outputs)
1047 return -EINVAL;
1048
1049 if (outp == itv->active_output) {
1050 IVTV_DEBUG_INFO("Output unchanged\n");
1051 return 0;
1052 }
1053 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1054 itv->active_output, outp);
1055
1056 itv->active_output = outp;
Hans Verkuil5325b422009-04-02 11:26:22 -03001057 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
1058 SAA7127_INPUT_TYPE_NORMAL,
1059 itv->card->video_outputs[outp].video_output, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001060
1061 return 0;
1062}
1063
1064static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1065{
Hans Verkuil2f824412011-03-12 06:43:28 -03001066 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001067
1068 if (vf->tuner != 0)
1069 return -EINVAL;
1070
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001071 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001072 return 0;
1073}
1074
1075int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1076{
Hans Verkuil2f824412011-03-12 06:43:28 -03001077 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001078
1079 if (vf->tuner != 0)
1080 return -EINVAL;
1081
1082 ivtv_mute(itv);
1083 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001084 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001085 ivtv_unmute(itv);
1086 return 0;
1087}
1088
1089static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1090{
Hans Verkuil2f824412011-03-12 06:43:28 -03001091 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001092
1093 *std = itv->std;
1094 return 0;
1095}
1096
Ian Armstrongc5874c92011-05-29 21:33:17 -03001097void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001098{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001099 itv->std = *std;
1100 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
Hans Verkuilf7b80e62010-06-27 06:07:26 -03001101 itv->is_50hz = !itv->is_60hz;
1102 cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
1103 itv->cxhdl.width = 720;
1104 itv->cxhdl.height = itv->is_50hz ? 576 : 480;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001105 itv->vbi.count = itv->is_50hz ? 18 : 12;
1106 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1107 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1108
1109 if (itv->hw_flags & IVTV_HW_CX25840)
1110 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1111
Hans Verkuil3f038d82008-05-29 16:43:54 -03001112 /* Tuner */
Hans Verkuilf41737e2009-04-01 03:52:39 -03001113 ivtv_call_all(itv, core, s_std, itv->std);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001114}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001115
Ian Armstrongc5874c92011-05-29 21:33:17 -03001116void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
1117{
1118 struct yuv_playback_info *yi = &itv->yuv_info;
1119 DEFINE_WAIT(wait);
1120 int f;
Ian Armstrong2443bae2010-03-13 20:22:34 -03001121
Ian Armstrongc5874c92011-05-29 21:33:17 -03001122 /* set display standard */
1123 itv->std_out = *std;
1124 itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1125 itv->is_out_50hz = !itv->is_out_60hz;
1126 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Ian Armstrong2443bae2010-03-13 20:22:34 -03001127
Ian Armstrongc5874c92011-05-29 21:33:17 -03001128 /*
1129 * The next firmware call is time sensitive. Time it to
1130 * avoid risk of a hard lock, by trying to ensure the call
1131 * happens within the first 100 lines of the top field.
1132 * Make 4 attempts to sync to the decoder before giving up.
1133 */
Hans Verkuilcdc03782011-10-11 06:06:58 -03001134 mutex_unlock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001135 for (f = 0; f < 4; f++) {
1136 prepare_to_wait(&itv->vsync_waitq, &wait,
1137 TASK_UNINTERRUPTIBLE);
1138 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
1139 break;
1140 schedule_timeout(msecs_to_jiffies(25));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001141 }
Ian Armstrongc5874c92011-05-29 21:33:17 -03001142 finish_wait(&itv->vsync_waitq, &wait);
Hans Verkuilcdc03782011-10-11 06:06:58 -03001143 mutex_lock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001144
1145 if (f == 4)
1146 IVTV_WARN("Mode change failed to sync to decoder\n");
1147
1148 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1149 itv->main_rect.left = 0;
1150 itv->main_rect.top = 0;
1151 itv->main_rect.width = 720;
1152 itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
1153 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1154 720, itv->main_rect.height, 0, 0);
1155 yi->main_rect = itv->main_rect;
1156 if (!itv->osd_info) {
1157 yi->osd_full_w = 720;
1158 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1159 }
1160}
1161
1162int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1163{
1164 struct ivtv *itv = fh2id(fh)->itv;
1165
1166 if ((*std & V4L2_STD_ALL) == 0)
1167 return -EINVAL;
1168
1169 if (*std == itv->std)
1170 return 0;
1171
1172 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1173 atomic_read(&itv->capturing) > 0 ||
1174 atomic_read(&itv->decoding) > 0) {
1175 /* Switching standard would mess with already running
1176 streams, prevent that by returning EBUSY. */
1177 return -EBUSY;
1178 }
1179
1180 IVTV_DEBUG_INFO("Switching standard to %llx.\n",
1181 (unsigned long long)itv->std);
1182
1183 ivtv_s_std_enc(itv, std);
1184 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
1185 ivtv_s_std_dec(itv, std);
1186
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001187 return 0;
1188}
1189
Hans Verkuil3f038d82008-05-29 16:43:54 -03001190static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001191{
Hans Verkuil2f824412011-03-12 06:43:28 -03001192 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001193 struct ivtv *itv = id->itv;
1194
1195 if (vt->index != 0)
1196 return -EINVAL;
1197
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001198 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001199
1200 return 0;
1201}
1202
1203static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1204{
Hans Verkuil2f824412011-03-12 06:43:28 -03001205 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001206
1207 if (vt->index != 0)
1208 return -EINVAL;
1209
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001210 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001211
Hans Verkuild118e292011-06-25 10:28:21 -03001212 if (vt->type == V4L2_TUNER_RADIO)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001213 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
Hans Verkuild118e292011-06-25 10:28:21 -03001214 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001215 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
Hans Verkuil3f038d82008-05-29 16:43:54 -03001216 return 0;
1217}
1218
1219static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1220{
Hans Verkuil2f824412011-03-12 06:43:28 -03001221 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001222 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1223 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001224
Hans Verkuil79afcb12008-06-21 09:02:36 -03001225 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001226 for (f = 0; f < 2; f++) {
1227 for (l = 0; l < 24; l++) {
1228 if (valid_service_line(f, l, itv->is_50hz))
1229 cap->service_lines[f][l] = set;
1230 }
1231 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001232 } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001233 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1234 return -EINVAL;
1235 if (itv->is_60hz) {
1236 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1237 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1238 } else {
1239 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1240 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1241 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001242 } else {
1243 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001244 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001245
1246 set = 0;
1247 for (f = 0; f < 2; f++)
1248 for (l = 0; l < 24; l++)
1249 set |= cap->service_lines[f][l];
1250 cap->service_set = set;
1251 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001252}
1253
1254static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1255{
Hans Verkuil2f824412011-03-12 06:43:28 -03001256 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001257 struct v4l2_enc_idx_entry *e = idx->entry;
1258 int entries;
1259 int i;
1260
1261 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1262 IVTV_MAX_PGM_INDEX;
1263 if (entries > V4L2_ENC_IDX_ENTRIES)
1264 entries = V4L2_ENC_IDX_ENTRIES;
1265 idx->entries = 0;
Hans Verkuil1a806402012-09-05 08:39:48 -03001266 idx->entries_cap = IVTV_MAX_PGM_INDEX;
1267 if (!atomic_read(&itv->capturing))
1268 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001269 for (i = 0; i < entries; i++) {
1270 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1271 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1272 idx->entries++;
1273 e++;
1274 }
1275 }
1276 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1277 return 0;
1278}
1279
1280static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1281{
Hans Verkuil2f824412011-03-12 06:43:28 -03001282 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001283 struct ivtv *itv = id->itv;
1284
Hans Verkuil3f038d82008-05-29 16:43:54 -03001285
1286 switch (enc->cmd) {
1287 case V4L2_ENC_CMD_START:
1288 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1289 enc->flags = 0;
1290 return ivtv_start_capture(id);
1291
1292 case V4L2_ENC_CMD_STOP:
1293 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1294 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1295 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1296 return 0;
1297
1298 case V4L2_ENC_CMD_PAUSE:
1299 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1300 enc->flags = 0;
1301
1302 if (!atomic_read(&itv->capturing))
1303 return -EPERM;
1304 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1305 return 0;
1306
1307 ivtv_mute(itv);
1308 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1309 break;
1310
1311 case V4L2_ENC_CMD_RESUME:
1312 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1313 enc->flags = 0;
1314
1315 if (!atomic_read(&itv->capturing))
1316 return -EPERM;
1317
1318 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1319 return 0;
1320
1321 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1322 ivtv_unmute(itv);
1323 break;
1324 default:
1325 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1326 return -EINVAL;
1327 }
1328
1329 return 0;
1330}
1331
1332static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1333{
Hans Verkuil2f824412011-03-12 06:43:28 -03001334 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001335
Hans Verkuil3f038d82008-05-29 16:43:54 -03001336 switch (enc->cmd) {
1337 case V4L2_ENC_CMD_START:
1338 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1339 enc->flags = 0;
1340 return 0;
1341
1342 case V4L2_ENC_CMD_STOP:
1343 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1344 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1345 return 0;
1346
1347 case V4L2_ENC_CMD_PAUSE:
1348 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1349 enc->flags = 0;
1350 return 0;
1351
1352 case V4L2_ENC_CMD_RESUME:
1353 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1354 enc->flags = 0;
1355 return 0;
1356 default:
1357 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1358 return -EINVAL;
1359 }
1360}
1361
1362static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1363{
Hans Verkuil2f824412011-03-12 06:43:28 -03001364 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001365 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001366 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001367
Hans Verkuil3f038d82008-05-29 16:43:54 -03001368 int pixfmt;
1369 static u32 pixel_format[16] = {
1370 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1371 V4L2_PIX_FMT_RGB565,
1372 V4L2_PIX_FMT_RGB555,
1373 V4L2_PIX_FMT_RGB444,
1374 V4L2_PIX_FMT_RGB32,
1375 0,
1376 0,
1377 0,
1378 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1379 V4L2_PIX_FMT_YUV565,
1380 V4L2_PIX_FMT_YUV555,
1381 V4L2_PIX_FMT_YUV444,
1382 V4L2_PIX_FMT_YUV32,
1383 0,
1384 0,
1385 0,
1386 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001387
Hans Verkuil3f038d82008-05-29 16:43:54 -03001388 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1389 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001390 if (!itv->osd_video_pbase)
1391 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001392
Hans Verkuil3f038d82008-05-29 16:43:54 -03001393 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1394 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001395
Hans Verkuil3f038d82008-05-29 16:43:54 -03001396 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1397 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1398 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001399
Hans Verkuil3f038d82008-05-29 16:43:54 -03001400 fb->fmt.pixelformat = pixel_format[pixfmt];
1401 fb->fmt.width = itv->osd_rect.width;
1402 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001403 fb->fmt.field = V4L2_FIELD_INTERLACED;
1404 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001405 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1406 fb->fmt.field = V4L2_FIELD_INTERLACED;
1407 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001408 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1409 fb->fmt.bytesperline *= 2;
1410 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1411 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1412 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001413 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001414 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001415 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001416
Hans Verkuil3f038d82008-05-29 16:43:54 -03001417 if (itv->osd_chroma_key_state)
1418 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001419
Hans Verkuil3f038d82008-05-29 16:43:54 -03001420 if (itv->osd_global_alpha_state)
1421 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001422
Ian Armstrongec9faa12008-10-06 03:06:08 -03001423 if (yi->track_osd)
1424 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1425
Hans Verkuil3f038d82008-05-29 16:43:54 -03001426 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001427
Hans Verkuil3f038d82008-05-29 16:43:54 -03001428 /* no local alpha for RGB565 or unknown formats */
1429 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001430 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001431
Hans Verkuil3f038d82008-05-29 16:43:54 -03001432 /* 16-bit formats have inverted local alpha */
1433 if (pixfmt == 2 || pixfmt == 3)
1434 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1435 else
1436 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001437
Hans Verkuil3f038d82008-05-29 16:43:54 -03001438 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001439 /* 16-bit formats have inverted local alpha */
1440 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001441 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001442 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001443 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001444 }
1445
Hans Verkuil3f038d82008-05-29 16:43:54 -03001446 return 0;
1447}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001448
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001449static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001450{
Hans Verkuil2f824412011-03-12 06:43:28 -03001451 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001452 struct ivtv *itv = id->itv;
1453 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001454
Hans Verkuil3f038d82008-05-29 16:43:54 -03001455 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001456 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001457 if (!itv->osd_video_pbase)
1458 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001459
1460 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1461 itv->osd_local_alpha_state =
1462 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1463 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1464 ivtv_set_osd_alpha(itv);
1465 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001466 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001467}
1468
1469static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1470{
Hans Verkuil2f824412011-03-12 06:43:28 -03001471 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001472 struct ivtv *itv = id->itv;
1473
1474 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1475 return -EINVAL;
1476
1477 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1478
1479 return 0;
1480}
1481
Hans Verkuil85f5fe32012-09-04 11:46:09 -03001482static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
Hans Verkuil09250192010-03-27 14:10:13 -03001483{
1484 switch (sub->type) {
1485 case V4L2_EVENT_VSYNC:
1486 case V4L2_EVENT_EOS:
Hans de Goedec53c2542012-04-08 12:59:46 -03001487 return v4l2_event_subscribe(fh, sub, 0, NULL);
Hans de Goede3e3661492012-04-08 12:59:47 -03001488 case V4L2_EVENT_CTRL:
1489 return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
Hans Verkuil09250192010-03-27 14:10:13 -03001490 default:
1491 return -EINVAL;
1492 }
Hans Verkuil09250192010-03-27 14:10:13 -03001493}
1494
Hans Verkuil3f038d82008-05-29 16:43:54 -03001495static int ivtv_log_status(struct file *file, void *fh)
1496{
Hans Verkuil2f824412011-03-12 06:43:28 -03001497 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001498 u32 data[CX2341X_MBOX_MAX_DATA];
1499
1500 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1501 struct v4l2_input vidin;
1502 struct v4l2_audio audin;
1503 int i;
1504
Hans Verkuil3f038d82008-05-29 16:43:54 -03001505 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1506 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1507 struct tveeprom tv;
1508
1509 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001510 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001511 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001512 ivtv_get_input(itv, itv->active_input, &vidin);
1513 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1514 IVTV_INFO("Video Input: %s\n", vidin.name);
1515 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1516 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1517 if (has_output) {
1518 struct v4l2_output vidout;
1519 struct v4l2_audioout audout;
1520 int mode = itv->output_mode;
1521 static const char * const output_modes[5] = {
1522 "None",
1523 "MPEG Streaming",
1524 "YUV Streaming",
1525 "YUV Frames",
1526 "Passthrough",
1527 };
Hans Verkuil3f038d82008-05-29 16:43:54 -03001528 static const char * const alpha_mode[4] = {
1529 "None",
1530 "Global",
1531 "Local",
1532 "Global and Local"
1533 };
1534 static const char * const pixel_format[16] = {
1535 "ARGB Indexed",
1536 "RGB 5:6:5",
1537 "ARGB 1:5:5:5",
1538 "ARGB 1:4:4:4",
1539 "ARGB 8:8:8:8",
1540 "5",
1541 "6",
1542 "7",
1543 "AYUV Indexed",
1544 "YUV 5:6:5",
1545 "AYUV 1:5:5:5",
1546 "AYUV 1:4:4:4",
1547 "AYUV 8:8:8:8",
1548 "13",
1549 "14",
1550 "15",
1551 };
1552
1553 ivtv_get_output(itv, itv->active_output, &vidout);
1554 ivtv_get_audio_output(itv, 0, &audout);
1555 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001556 if (mode < 0 || mode > OUT_PASSTHROUGH)
1557 mode = OUT_NONE;
1558 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1559 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1560 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1561 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1562 data[0] & 1 ? "On" : "Off",
1563 alpha_mode[(data[0] >> 1) & 0x3],
1564 pixel_format[(data[0] >> 3) & 0xf]);
1565 }
1566 IVTV_INFO("Tuner: %s\n",
1567 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuileb2ba852012-03-02 13:02:11 -03001568 v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001569 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1570 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1571 struct ivtv_stream *s = &itv->streams[i];
1572
Hans Verkuil8ac05ae2009-02-07 07:02:27 -03001573 if (s->vdev == NULL || s->buffers == 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001574 continue;
1575 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1576 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1577 (s->buffers * s->buf_size) / 1024, s->buffers);
1578 }
1579
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001580 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1581 (long long)itv->mpg_data_received,
1582 (long long)itv->vbi_data_inserted);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001583 return 0;
1584}
1585
Hans Verkuilda8ec562011-11-24 09:58:53 -03001586static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1587{
1588 struct ivtv_open_id *id = fh2id(file->private_data);
1589 struct ivtv *itv = id->itv;
1590
1591 IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
1592 return ivtv_video_command(itv, id, dec, false);
1593}
1594
1595static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1596{
1597 struct ivtv_open_id *id = fh2id(file->private_data);
1598 struct ivtv *itv = id->itv;
1599
1600 IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
1601 return ivtv_video_command(itv, id, dec, true);
1602}
1603
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001604static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001605{
Hans Verkuil09250192010-03-27 14:10:13 -03001606 struct ivtv_open_id *id = fh2id(filp->private_data);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001607 struct ivtv *itv = id->itv;
1608 int nonblocking = filp->f_flags & O_NONBLOCK;
1609 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuilce680252010-04-06 15:58:53 -03001610 unsigned long iarg = (unsigned long)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001611
1612 switch (cmd) {
1613 case IVTV_IOC_DMA_FRAME: {
1614 struct ivtv_dma_frame *args = arg;
1615
1616 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1617 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1618 return -EINVAL;
1619 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1620 return -EINVAL;
1621 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1622 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001623 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001624 return -EBUSY;
1625 }
1626 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1627 ivtv_release_stream(s);
1628 return -EBUSY;
1629 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001630 /* Mark that this file handle started the UDMA_YUV mode */
1631 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001632 if (args->y_source == NULL)
1633 return 0;
1634 return ivtv_yuv_prep_frame(itv, args);
1635 }
1636
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001637 case IVTV_IOC_PASSTHROUGH_MODE:
1638 IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
1639 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1640 return -EINVAL;
1641 return ivtv_passthrough_mode(itv, *(int *)arg != 0);
1642
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001643 case VIDEO_GET_PTS: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001644 s64 *pts = arg;
1645 s64 frame;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001646
1647 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1648 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1649 *pts = s->dma_pts;
1650 break;
1651 }
1652 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1653 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001654 return ivtv_g_pts_frame(itv, pts, &frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001655 }
1656
1657 case VIDEO_GET_FRAME_COUNT: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001658 s64 *frame = arg;
1659 s64 pts;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001660
1661 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1662 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1663 *frame = 0;
1664 break;
1665 }
1666 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1667 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001668 return ivtv_g_pts_frame(itv, &pts, frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001669 }
1670
1671 case VIDEO_PLAY: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001672 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001673
1674 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001675 memset(&dc, 0, sizeof(dc));
1676 dc.cmd = V4L2_DEC_CMD_START;
1677 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001678 }
1679
1680 case VIDEO_STOP: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001681 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001682
1683 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001684 memset(&dc, 0, sizeof(dc));
1685 dc.cmd = V4L2_DEC_CMD_STOP;
1686 dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
1687 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001688 }
1689
1690 case VIDEO_FREEZE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001691 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001692
1693 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001694 memset(&dc, 0, sizeof(dc));
1695 dc.cmd = V4L2_DEC_CMD_PAUSE;
1696 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001697 }
1698
1699 case VIDEO_CONTINUE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001700 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001701
1702 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001703 memset(&dc, 0, sizeof(dc));
1704 dc.cmd = V4L2_DEC_CMD_RESUME;
1705 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001706 }
1707
1708 case VIDEO_COMMAND:
1709 case VIDEO_TRY_COMMAND: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001710 /* Note: struct v4l2_decoder_cmd has the same layout as
1711 struct video_command */
1712 struct v4l2_decoder_cmd *dc = arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001713 int try = (cmd == VIDEO_TRY_COMMAND);
1714
1715 if (try)
Hans Verkuilda8ec562011-11-24 09:58:53 -03001716 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001717 else
Hans Verkuilda8ec562011-11-24 09:58:53 -03001718 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
1719 return ivtv_video_command(itv, id, dc, try);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001720 }
1721
1722 case VIDEO_GET_EVENT: {
1723 struct video_event *ev = arg;
1724 DEFINE_WAIT(wait);
1725
1726 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1727 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1728 return -EINVAL;
1729 memset(ev, 0, sizeof(*ev));
1730 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1731
1732 while (1) {
1733 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1734 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1735 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1736 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001737 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1738 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1739 if (itv->output_mode == OUT_UDMA_YUV &&
1740 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1741 IVTV_YUV_MODE_PROGRESSIVE) {
1742 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1743 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001744 }
1745 if (ev->type)
1746 return 0;
1747 if (nonblocking)
1748 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001749 /* Wait for event. Note that serialize_lock is locked,
1750 so to allow other processes to access the driver while
1751 we are waiting unlock first and later lock again. */
1752 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001753 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a422009-05-02 11:10:23 -03001754 if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
1755 !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001756 schedule();
1757 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001758 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001759 if (signal_pending(current)) {
1760 /* return if a signal was received */
1761 IVTV_DEBUG_INFO("User stopped wait for event\n");
1762 return -EINTR;
1763 }
1764 }
1765 break;
1766 }
1767
Hans Verkuilce680252010-04-06 15:58:53 -03001768 case VIDEO_SELECT_SOURCE:
1769 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1770 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1771 return -EINVAL;
1772 return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
1773
1774 case AUDIO_SET_MUTE:
1775 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1776 itv->speed_mute_audio = iarg;
1777 return 0;
1778
1779 case AUDIO_CHANNEL_SELECT:
1780 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1781 if (iarg > AUDIO_STEREO_SWAPPED)
1782 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001783 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001784
1785 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1786 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1787 if (iarg > AUDIO_STEREO_SWAPPED)
1788 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001789 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001790
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001791 default:
1792 return -EINVAL;
1793 }
1794 return 0;
1795}
1796
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03001797static long ivtv_default(struct file *file, void *fh, bool valid_prio,
1798 int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001799{
Hans Verkuil2f824412011-03-12 06:43:28 -03001800 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001801
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001802 if (!valid_prio) {
1803 switch (cmd) {
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001804 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001805 case VIDEO_PLAY:
1806 case VIDEO_STOP:
1807 case VIDEO_FREEZE:
1808 case VIDEO_CONTINUE:
1809 case VIDEO_COMMAND:
1810 case VIDEO_SELECT_SOURCE:
1811 case AUDIO_SET_MUTE:
1812 case AUDIO_CHANNEL_SELECT:
1813 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1814 return -EBUSY;
1815 }
1816 }
1817
Hans Verkuild46c17d2007-03-10 17:59:15 -03001818 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001819 case VIDIOC_INT_RESET: {
1820 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001821
Hans Verkuil3f038d82008-05-29 16:43:54 -03001822 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1823 ivtv_reset_ir_gpio(itv);
1824 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001825 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001826 break;
1827 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001828
Hans Verkuilac9575f2009-02-14 19:58:33 -03001829 case IVTV_IOC_DMA_FRAME:
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001830 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001831 case VIDEO_GET_PTS:
1832 case VIDEO_GET_FRAME_COUNT:
1833 case VIDEO_GET_EVENT:
1834 case VIDEO_PLAY:
1835 case VIDEO_STOP:
1836 case VIDEO_FREEZE:
1837 case VIDEO_CONTINUE:
1838 case VIDEO_COMMAND:
1839 case VIDEO_TRY_COMMAND:
Hans Verkuilce680252010-04-06 15:58:53 -03001840 case VIDEO_SELECT_SOURCE:
1841 case AUDIO_SET_MUTE:
1842 case AUDIO_CHANNEL_SELECT:
1843 case AUDIO_BILINGUAL_CHANNEL_SELECT:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001844 return ivtv_decoder_ioctls(file, cmd, (void *)arg);
1845
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001846 default:
Hans Verkuild1c754a2012-04-19 12:36:03 -03001847 return -ENOTTY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001848 }
1849 return 0;
1850}
1851
Hans Verkuila3998102008-07-21 02:57:38 -03001852static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1853 .vidioc_querycap = ivtv_querycap,
Hans Verkuila3998102008-07-21 02:57:38 -03001854 .vidioc_s_audio = ivtv_s_audio,
1855 .vidioc_g_audio = ivtv_g_audio,
1856 .vidioc_enumaudio = ivtv_enumaudio,
1857 .vidioc_s_audout = ivtv_s_audout,
1858 .vidioc_g_audout = ivtv_g_audout,
1859 .vidioc_enum_input = ivtv_enum_input,
1860 .vidioc_enum_output = ivtv_enum_output,
1861 .vidioc_enumaudout = ivtv_enumaudout,
1862 .vidioc_cropcap = ivtv_cropcap,
1863 .vidioc_s_crop = ivtv_s_crop,
1864 .vidioc_g_crop = ivtv_g_crop,
1865 .vidioc_g_input = ivtv_g_input,
1866 .vidioc_s_input = ivtv_s_input,
1867 .vidioc_g_output = ivtv_g_output,
1868 .vidioc_s_output = ivtv_s_output,
1869 .vidioc_g_frequency = ivtv_g_frequency,
1870 .vidioc_s_frequency = ivtv_s_frequency,
1871 .vidioc_s_tuner = ivtv_s_tuner,
1872 .vidioc_g_tuner = ivtv_g_tuner,
1873 .vidioc_g_enc_index = ivtv_g_enc_index,
1874 .vidioc_g_fbuf = ivtv_g_fbuf,
1875 .vidioc_s_fbuf = ivtv_s_fbuf,
1876 .vidioc_g_std = ivtv_g_std,
1877 .vidioc_s_std = ivtv_s_std,
1878 .vidioc_overlay = ivtv_overlay,
1879 .vidioc_log_status = ivtv_log_status,
1880 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1881 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1882 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
Hans Verkuilda8ec562011-11-24 09:58:53 -03001883 .vidioc_decoder_cmd = ivtv_decoder_cmd,
1884 .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd,
Hans Verkuila3998102008-07-21 02:57:38 -03001885 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1886 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1887 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1888 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1889 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1890 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1891 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1892 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1893 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1894 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1895 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1896 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1897 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1898 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1899 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1900 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1901 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1902 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1903 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1904 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1905 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1906#ifdef CONFIG_VIDEO_ADV_DEBUG
1907 .vidioc_g_register = ivtv_g_register,
1908 .vidioc_s_register = ivtv_s_register,
1909#endif
1910 .vidioc_default = ivtv_default,
Hans Verkuil09250192010-03-27 14:10:13 -03001911 .vidioc_subscribe_event = ivtv_subscribe_event,
1912 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001913};
1914
Hans Verkuil3f038d82008-05-29 16:43:54 -03001915void ivtv_set_funcs(struct video_device *vdev)
1916{
Hans Verkuila3998102008-07-21 02:57:38 -03001917 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001918}