blob: 0b0250a7583f5699f6fdcf0402c24d16e4154648 [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 Verkuil3f038d82008-05-29 16:43:54 -0300990
991 if (inp < 0 || inp >= itv->nof_inputs)
992 return -EINVAL;
993
994 if (inp == itv->active_input) {
995 IVTV_DEBUG_INFO("Input unchanged\n");
996 return 0;
997 }
998
999 if (atomic_read(&itv->capturing) > 0) {
1000 return -EBUSY;
1001 }
1002
1003 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
1004 itv->active_input, inp);
1005
1006 itv->active_input = inp;
1007 /* Set the audio input to whatever is appropriate for the
1008 input type. */
1009 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1010
1011 /* prevent others from messing with the streams until
1012 we're finished changing inputs. */
1013 ivtv_mute(itv);
1014 ivtv_video_set_io(itv);
1015 ivtv_audio_set_io(itv);
1016 ivtv_unmute(itv);
1017
1018 return 0;
1019}
1020
1021static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1022{
Hans Verkuil2f824412011-03-12 06:43:28 -03001023 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001024
1025 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1026 return -EINVAL;
1027
1028 *i = itv->active_output;
1029
1030 return 0;
1031}
1032
1033static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1034{
Hans Verkuil2f824412011-03-12 06:43:28 -03001035 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001036
1037 if (outp >= itv->card->nof_outputs)
1038 return -EINVAL;
1039
1040 if (outp == itv->active_output) {
1041 IVTV_DEBUG_INFO("Output unchanged\n");
1042 return 0;
1043 }
1044 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1045 itv->active_output, outp);
1046
1047 itv->active_output = outp;
Hans Verkuil5325b422009-04-02 11:26:22 -03001048 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
1049 SAA7127_INPUT_TYPE_NORMAL,
1050 itv->card->video_outputs[outp].video_output, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001051
1052 return 0;
1053}
1054
1055static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1056{
Hans Verkuil2f824412011-03-12 06:43:28 -03001057 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001058
1059 if (vf->tuner != 0)
1060 return -EINVAL;
1061
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001062 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001063 return 0;
1064}
1065
1066int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1067{
Hans Verkuil2f824412011-03-12 06:43:28 -03001068 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001069
1070 if (vf->tuner != 0)
1071 return -EINVAL;
1072
1073 ivtv_mute(itv);
1074 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001075 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001076 ivtv_unmute(itv);
1077 return 0;
1078}
1079
1080static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1081{
Hans Verkuil2f824412011-03-12 06:43:28 -03001082 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001083
1084 *std = itv->std;
1085 return 0;
1086}
1087
Ian Armstrongc5874c92011-05-29 21:33:17 -03001088void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001089{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001090 itv->std = *std;
1091 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
Hans Verkuilf7b80e62010-06-27 06:07:26 -03001092 itv->is_50hz = !itv->is_60hz;
1093 cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
1094 itv->cxhdl.width = 720;
1095 itv->cxhdl.height = itv->is_50hz ? 576 : 480;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001096 itv->vbi.count = itv->is_50hz ? 18 : 12;
1097 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1098 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1099
1100 if (itv->hw_flags & IVTV_HW_CX25840)
1101 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1102
Hans Verkuil3f038d82008-05-29 16:43:54 -03001103 /* Tuner */
Hans Verkuilf41737e2009-04-01 03:52:39 -03001104 ivtv_call_all(itv, core, s_std, itv->std);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001105}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001106
Ian Armstrongc5874c92011-05-29 21:33:17 -03001107void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
1108{
1109 struct yuv_playback_info *yi = &itv->yuv_info;
1110 DEFINE_WAIT(wait);
1111 int f;
Ian Armstrong2443bae2010-03-13 20:22:34 -03001112
Ian Armstrongc5874c92011-05-29 21:33:17 -03001113 /* set display standard */
1114 itv->std_out = *std;
1115 itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1116 itv->is_out_50hz = !itv->is_out_60hz;
1117 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Ian Armstrong2443bae2010-03-13 20:22:34 -03001118
Ian Armstrongc5874c92011-05-29 21:33:17 -03001119 /*
1120 * The next firmware call is time sensitive. Time it to
1121 * avoid risk of a hard lock, by trying to ensure the call
1122 * happens within the first 100 lines of the top field.
1123 * Make 4 attempts to sync to the decoder before giving up.
1124 */
Hans Verkuilcdc03782011-10-11 06:06:58 -03001125 mutex_unlock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001126 for (f = 0; f < 4; f++) {
1127 prepare_to_wait(&itv->vsync_waitq, &wait,
1128 TASK_UNINTERRUPTIBLE);
1129 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
1130 break;
1131 schedule_timeout(msecs_to_jiffies(25));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001132 }
Ian Armstrongc5874c92011-05-29 21:33:17 -03001133 finish_wait(&itv->vsync_waitq, &wait);
Hans Verkuilcdc03782011-10-11 06:06:58 -03001134 mutex_lock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001135
1136 if (f == 4)
1137 IVTV_WARN("Mode change failed to sync to decoder\n");
1138
1139 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1140 itv->main_rect.left = 0;
1141 itv->main_rect.top = 0;
1142 itv->main_rect.width = 720;
1143 itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
1144 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1145 720, itv->main_rect.height, 0, 0);
1146 yi->main_rect = itv->main_rect;
1147 if (!itv->osd_info) {
1148 yi->osd_full_w = 720;
1149 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1150 }
1151}
1152
1153int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1154{
1155 struct ivtv *itv = fh2id(fh)->itv;
1156
1157 if ((*std & V4L2_STD_ALL) == 0)
1158 return -EINVAL;
1159
1160 if (*std == itv->std)
1161 return 0;
1162
1163 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1164 atomic_read(&itv->capturing) > 0 ||
1165 atomic_read(&itv->decoding) > 0) {
1166 /* Switching standard would mess with already running
1167 streams, prevent that by returning EBUSY. */
1168 return -EBUSY;
1169 }
1170
1171 IVTV_DEBUG_INFO("Switching standard to %llx.\n",
1172 (unsigned long long)itv->std);
1173
1174 ivtv_s_std_enc(itv, std);
1175 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
1176 ivtv_s_std_dec(itv, std);
1177
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001178 return 0;
1179}
1180
Hans Verkuil3f038d82008-05-29 16:43:54 -03001181static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001182{
Hans Verkuil2f824412011-03-12 06:43:28 -03001183 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001184 struct ivtv *itv = id->itv;
1185
1186 if (vt->index != 0)
1187 return -EINVAL;
1188
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001189 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001190
1191 return 0;
1192}
1193
1194static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1195{
Hans Verkuil2f824412011-03-12 06:43:28 -03001196 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001197
1198 if (vt->index != 0)
1199 return -EINVAL;
1200
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001201 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001202
Hans Verkuild118e292011-06-25 10:28:21 -03001203 if (vt->type == V4L2_TUNER_RADIO)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001204 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
Hans Verkuild118e292011-06-25 10:28:21 -03001205 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001206 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
Hans Verkuil3f038d82008-05-29 16:43:54 -03001207 return 0;
1208}
1209
1210static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1211{
Hans Verkuil2f824412011-03-12 06:43:28 -03001212 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001213 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1214 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001215
Hans Verkuil79afcb12008-06-21 09:02:36 -03001216 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001217 for (f = 0; f < 2; f++) {
1218 for (l = 0; l < 24; l++) {
1219 if (valid_service_line(f, l, itv->is_50hz))
1220 cap->service_lines[f][l] = set;
1221 }
1222 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001223 } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001224 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1225 return -EINVAL;
1226 if (itv->is_60hz) {
1227 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1228 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1229 } else {
1230 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1231 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1232 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001233 } else {
1234 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001235 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001236
1237 set = 0;
1238 for (f = 0; f < 2; f++)
1239 for (l = 0; l < 24; l++)
1240 set |= cap->service_lines[f][l];
1241 cap->service_set = set;
1242 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001243}
1244
1245static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1246{
Hans Verkuil2f824412011-03-12 06:43:28 -03001247 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001248 struct v4l2_enc_idx_entry *e = idx->entry;
1249 int entries;
1250 int i;
1251
1252 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1253 IVTV_MAX_PGM_INDEX;
1254 if (entries > V4L2_ENC_IDX_ENTRIES)
1255 entries = V4L2_ENC_IDX_ENTRIES;
1256 idx->entries = 0;
Hans Verkuil1a806402012-09-05 08:39:48 -03001257 idx->entries_cap = IVTV_MAX_PGM_INDEX;
1258 if (!atomic_read(&itv->capturing))
1259 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001260 for (i = 0; i < entries; i++) {
1261 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1262 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1263 idx->entries++;
1264 e++;
1265 }
1266 }
1267 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1268 return 0;
1269}
1270
1271static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1272{
Hans Verkuil2f824412011-03-12 06:43:28 -03001273 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001274 struct ivtv *itv = id->itv;
1275
Hans Verkuil3f038d82008-05-29 16:43:54 -03001276
1277 switch (enc->cmd) {
1278 case V4L2_ENC_CMD_START:
1279 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1280 enc->flags = 0;
1281 return ivtv_start_capture(id);
1282
1283 case V4L2_ENC_CMD_STOP:
1284 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1285 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1286 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1287 return 0;
1288
1289 case V4L2_ENC_CMD_PAUSE:
1290 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1291 enc->flags = 0;
1292
1293 if (!atomic_read(&itv->capturing))
1294 return -EPERM;
1295 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1296 return 0;
1297
1298 ivtv_mute(itv);
1299 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1300 break;
1301
1302 case V4L2_ENC_CMD_RESUME:
1303 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1304 enc->flags = 0;
1305
1306 if (!atomic_read(&itv->capturing))
1307 return -EPERM;
1308
1309 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1310 return 0;
1311
1312 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1313 ivtv_unmute(itv);
1314 break;
1315 default:
1316 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1317 return -EINVAL;
1318 }
1319
1320 return 0;
1321}
1322
1323static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1324{
Hans Verkuil2f824412011-03-12 06:43:28 -03001325 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001326
Hans Verkuil3f038d82008-05-29 16:43:54 -03001327 switch (enc->cmd) {
1328 case V4L2_ENC_CMD_START:
1329 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1330 enc->flags = 0;
1331 return 0;
1332
1333 case V4L2_ENC_CMD_STOP:
1334 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1335 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1336 return 0;
1337
1338 case V4L2_ENC_CMD_PAUSE:
1339 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1340 enc->flags = 0;
1341 return 0;
1342
1343 case V4L2_ENC_CMD_RESUME:
1344 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1345 enc->flags = 0;
1346 return 0;
1347 default:
1348 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1349 return -EINVAL;
1350 }
1351}
1352
1353static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1354{
Hans Verkuil2f824412011-03-12 06:43:28 -03001355 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001356 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001357 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001358
Hans Verkuil3f038d82008-05-29 16:43:54 -03001359 int pixfmt;
1360 static u32 pixel_format[16] = {
1361 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1362 V4L2_PIX_FMT_RGB565,
1363 V4L2_PIX_FMT_RGB555,
1364 V4L2_PIX_FMT_RGB444,
1365 V4L2_PIX_FMT_RGB32,
1366 0,
1367 0,
1368 0,
1369 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1370 V4L2_PIX_FMT_YUV565,
1371 V4L2_PIX_FMT_YUV555,
1372 V4L2_PIX_FMT_YUV444,
1373 V4L2_PIX_FMT_YUV32,
1374 0,
1375 0,
1376 0,
1377 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001378
Hans Verkuil3f038d82008-05-29 16:43:54 -03001379 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1380 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001381 if (!itv->osd_video_pbase)
1382 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001383
Hans Verkuil3f038d82008-05-29 16:43:54 -03001384 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1385 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001386
Hans Verkuil3f038d82008-05-29 16:43:54 -03001387 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1388 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1389 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001390
Hans Verkuil3f038d82008-05-29 16:43:54 -03001391 fb->fmt.pixelformat = pixel_format[pixfmt];
1392 fb->fmt.width = itv->osd_rect.width;
1393 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001394 fb->fmt.field = V4L2_FIELD_INTERLACED;
1395 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001396 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1397 fb->fmt.field = V4L2_FIELD_INTERLACED;
1398 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001399 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1400 fb->fmt.bytesperline *= 2;
1401 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1402 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1403 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001404 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001405 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001406 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001407
Hans Verkuil3f038d82008-05-29 16:43:54 -03001408 if (itv->osd_chroma_key_state)
1409 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001410
Hans Verkuil3f038d82008-05-29 16:43:54 -03001411 if (itv->osd_global_alpha_state)
1412 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001413
Ian Armstrongec9faa12008-10-06 03:06:08 -03001414 if (yi->track_osd)
1415 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1416
Hans Verkuil3f038d82008-05-29 16:43:54 -03001417 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001418
Hans Verkuil3f038d82008-05-29 16:43:54 -03001419 /* no local alpha for RGB565 or unknown formats */
1420 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001421 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001422
Hans Verkuil3f038d82008-05-29 16:43:54 -03001423 /* 16-bit formats have inverted local alpha */
1424 if (pixfmt == 2 || pixfmt == 3)
1425 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1426 else
1427 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001428
Hans Verkuil3f038d82008-05-29 16:43:54 -03001429 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001430 /* 16-bit formats have inverted local alpha */
1431 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001432 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001433 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001434 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001435 }
1436
Hans Verkuil3f038d82008-05-29 16:43:54 -03001437 return 0;
1438}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001439
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001440static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001441{
Hans Verkuil2f824412011-03-12 06:43:28 -03001442 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001443 struct ivtv *itv = id->itv;
1444 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001445
Hans Verkuil3f038d82008-05-29 16:43:54 -03001446 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001447 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001448 if (!itv->osd_video_pbase)
1449 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001450
1451 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1452 itv->osd_local_alpha_state =
1453 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1454 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1455 ivtv_set_osd_alpha(itv);
1456 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001457 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001458}
1459
1460static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1461{
Hans Verkuil2f824412011-03-12 06:43:28 -03001462 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001463 struct ivtv *itv = id->itv;
1464
1465 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1466 return -EINVAL;
1467
1468 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1469
1470 return 0;
1471}
1472
Hans Verkuil85f5fe32012-09-04 11:46:09 -03001473static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
Hans Verkuil09250192010-03-27 14:10:13 -03001474{
1475 switch (sub->type) {
1476 case V4L2_EVENT_VSYNC:
1477 case V4L2_EVENT_EOS:
Hans de Goedec53c2542012-04-08 12:59:46 -03001478 return v4l2_event_subscribe(fh, sub, 0, NULL);
Hans de Goede3e3661492012-04-08 12:59:47 -03001479 case V4L2_EVENT_CTRL:
1480 return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
Hans Verkuil09250192010-03-27 14:10:13 -03001481 default:
1482 return -EINVAL;
1483 }
Hans Verkuil09250192010-03-27 14:10:13 -03001484}
1485
Hans Verkuil3f038d82008-05-29 16:43:54 -03001486static int ivtv_log_status(struct file *file, void *fh)
1487{
Hans Verkuil2f824412011-03-12 06:43:28 -03001488 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001489 u32 data[CX2341X_MBOX_MAX_DATA];
1490
1491 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1492 struct v4l2_input vidin;
1493 struct v4l2_audio audin;
1494 int i;
1495
Hans Verkuil3f038d82008-05-29 16:43:54 -03001496 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1497 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1498 struct tveeprom tv;
1499
1500 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001501 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001502 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001503 ivtv_get_input(itv, itv->active_input, &vidin);
1504 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1505 IVTV_INFO("Video Input: %s\n", vidin.name);
1506 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1507 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1508 if (has_output) {
1509 struct v4l2_output vidout;
1510 struct v4l2_audioout audout;
1511 int mode = itv->output_mode;
1512 static const char * const output_modes[5] = {
1513 "None",
1514 "MPEG Streaming",
1515 "YUV Streaming",
1516 "YUV Frames",
1517 "Passthrough",
1518 };
Hans Verkuil3f038d82008-05-29 16:43:54 -03001519 static const char * const alpha_mode[4] = {
1520 "None",
1521 "Global",
1522 "Local",
1523 "Global and Local"
1524 };
1525 static const char * const pixel_format[16] = {
1526 "ARGB Indexed",
1527 "RGB 5:6:5",
1528 "ARGB 1:5:5:5",
1529 "ARGB 1:4:4:4",
1530 "ARGB 8:8:8:8",
1531 "5",
1532 "6",
1533 "7",
1534 "AYUV Indexed",
1535 "YUV 5:6:5",
1536 "AYUV 1:5:5:5",
1537 "AYUV 1:4:4:4",
1538 "AYUV 8:8:8:8",
1539 "13",
1540 "14",
1541 "15",
1542 };
1543
1544 ivtv_get_output(itv, itv->active_output, &vidout);
1545 ivtv_get_audio_output(itv, 0, &audout);
1546 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001547 if (mode < 0 || mode > OUT_PASSTHROUGH)
1548 mode = OUT_NONE;
1549 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1550 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1551 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1552 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1553 data[0] & 1 ? "On" : "Off",
1554 alpha_mode[(data[0] >> 1) & 0x3],
1555 pixel_format[(data[0] >> 3) & 0xf]);
1556 }
1557 IVTV_INFO("Tuner: %s\n",
1558 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuileb2ba852012-03-02 13:02:11 -03001559 v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001560 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1561 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1562 struct ivtv_stream *s = &itv->streams[i];
1563
Hans Verkuil8ac05ae2009-02-07 07:02:27 -03001564 if (s->vdev == NULL || s->buffers == 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001565 continue;
1566 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1567 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1568 (s->buffers * s->buf_size) / 1024, s->buffers);
1569 }
1570
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001571 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1572 (long long)itv->mpg_data_received,
1573 (long long)itv->vbi_data_inserted);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001574 return 0;
1575}
1576
Hans Verkuilda8ec562011-11-24 09:58:53 -03001577static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1578{
1579 struct ivtv_open_id *id = fh2id(file->private_data);
1580 struct ivtv *itv = id->itv;
1581
1582 IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
1583 return ivtv_video_command(itv, id, dec, false);
1584}
1585
1586static int ivtv_try_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_TRY_DECODER_CMD %d\n", dec->cmd);
1592 return ivtv_video_command(itv, id, dec, true);
1593}
1594
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001595static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001596{
Hans Verkuil09250192010-03-27 14:10:13 -03001597 struct ivtv_open_id *id = fh2id(filp->private_data);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001598 struct ivtv *itv = id->itv;
1599 int nonblocking = filp->f_flags & O_NONBLOCK;
1600 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuilce680252010-04-06 15:58:53 -03001601 unsigned long iarg = (unsigned long)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001602
1603 switch (cmd) {
1604 case IVTV_IOC_DMA_FRAME: {
1605 struct ivtv_dma_frame *args = arg;
1606
1607 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1608 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1609 return -EINVAL;
1610 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1611 return -EINVAL;
1612 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1613 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001614 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001615 return -EBUSY;
1616 }
1617 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1618 ivtv_release_stream(s);
1619 return -EBUSY;
1620 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001621 /* Mark that this file handle started the UDMA_YUV mode */
1622 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001623 if (args->y_source == NULL)
1624 return 0;
1625 return ivtv_yuv_prep_frame(itv, args);
1626 }
1627
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001628 case IVTV_IOC_PASSTHROUGH_MODE:
1629 IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
1630 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1631 return -EINVAL;
1632 return ivtv_passthrough_mode(itv, *(int *)arg != 0);
1633
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001634 case VIDEO_GET_PTS: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001635 s64 *pts = arg;
1636 s64 frame;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001637
1638 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1639 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1640 *pts = s->dma_pts;
1641 break;
1642 }
1643 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1644 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001645 return ivtv_g_pts_frame(itv, pts, &frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001646 }
1647
1648 case VIDEO_GET_FRAME_COUNT: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001649 s64 *frame = arg;
1650 s64 pts;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001651
1652 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1653 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1654 *frame = 0;
1655 break;
1656 }
1657 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1658 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001659 return ivtv_g_pts_frame(itv, &pts, frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001660 }
1661
1662 case VIDEO_PLAY: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001663 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001664
1665 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001666 memset(&dc, 0, sizeof(dc));
1667 dc.cmd = V4L2_DEC_CMD_START;
1668 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001669 }
1670
1671 case VIDEO_STOP: {
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_STOP\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001675 memset(&dc, 0, sizeof(dc));
1676 dc.cmd = V4L2_DEC_CMD_STOP;
1677 dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
1678 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001679 }
1680
1681 case VIDEO_FREEZE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001682 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001683
1684 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001685 memset(&dc, 0, sizeof(dc));
1686 dc.cmd = V4L2_DEC_CMD_PAUSE;
1687 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001688 }
1689
1690 case VIDEO_CONTINUE: {
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_CONTINUE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001694 memset(&dc, 0, sizeof(dc));
1695 dc.cmd = V4L2_DEC_CMD_RESUME;
1696 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001697 }
1698
1699 case VIDEO_COMMAND:
1700 case VIDEO_TRY_COMMAND: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001701 /* Note: struct v4l2_decoder_cmd has the same layout as
1702 struct video_command */
1703 struct v4l2_decoder_cmd *dc = arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001704 int try = (cmd == VIDEO_TRY_COMMAND);
1705
1706 if (try)
Hans Verkuilda8ec562011-11-24 09:58:53 -03001707 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001708 else
Hans Verkuilda8ec562011-11-24 09:58:53 -03001709 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
1710 return ivtv_video_command(itv, id, dc, try);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001711 }
1712
1713 case VIDEO_GET_EVENT: {
1714 struct video_event *ev = arg;
1715 DEFINE_WAIT(wait);
1716
1717 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1718 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1719 return -EINVAL;
1720 memset(ev, 0, sizeof(*ev));
1721 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1722
1723 while (1) {
1724 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1725 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1726 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1727 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001728 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1729 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1730 if (itv->output_mode == OUT_UDMA_YUV &&
1731 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1732 IVTV_YUV_MODE_PROGRESSIVE) {
1733 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1734 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001735 }
1736 if (ev->type)
1737 return 0;
1738 if (nonblocking)
1739 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001740 /* Wait for event. Note that serialize_lock is locked,
1741 so to allow other processes to access the driver while
1742 we are waiting unlock first and later lock again. */
1743 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001744 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a422009-05-02 11:10:23 -03001745 if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
1746 !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001747 schedule();
1748 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001749 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001750 if (signal_pending(current)) {
1751 /* return if a signal was received */
1752 IVTV_DEBUG_INFO("User stopped wait for event\n");
1753 return -EINTR;
1754 }
1755 }
1756 break;
1757 }
1758
Hans Verkuilce680252010-04-06 15:58:53 -03001759 case VIDEO_SELECT_SOURCE:
1760 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1761 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1762 return -EINVAL;
1763 return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
1764
1765 case AUDIO_SET_MUTE:
1766 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1767 itv->speed_mute_audio = iarg;
1768 return 0;
1769
1770 case AUDIO_CHANNEL_SELECT:
1771 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1772 if (iarg > AUDIO_STEREO_SWAPPED)
1773 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001774 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001775
1776 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1777 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1778 if (iarg > AUDIO_STEREO_SWAPPED)
1779 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001780 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001781
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001782 default:
1783 return -EINVAL;
1784 }
1785 return 0;
1786}
1787
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03001788static long ivtv_default(struct file *file, void *fh, bool valid_prio,
1789 int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001790{
Hans Verkuil2f824412011-03-12 06:43:28 -03001791 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001792
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001793 if (!valid_prio) {
1794 switch (cmd) {
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001795 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001796 case VIDEO_PLAY:
1797 case VIDEO_STOP:
1798 case VIDEO_FREEZE:
1799 case VIDEO_CONTINUE:
1800 case VIDEO_COMMAND:
1801 case VIDEO_SELECT_SOURCE:
1802 case AUDIO_SET_MUTE:
1803 case AUDIO_CHANNEL_SELECT:
1804 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1805 return -EBUSY;
1806 }
1807 }
1808
Hans Verkuild46c17d2007-03-10 17:59:15 -03001809 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001810 case VIDIOC_INT_RESET: {
1811 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001812
Hans Verkuil3f038d82008-05-29 16:43:54 -03001813 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1814 ivtv_reset_ir_gpio(itv);
1815 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001816 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001817 break;
1818 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001819
Hans Verkuilac9575f2009-02-14 19:58:33 -03001820 case IVTV_IOC_DMA_FRAME:
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001821 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001822 case VIDEO_GET_PTS:
1823 case VIDEO_GET_FRAME_COUNT:
1824 case VIDEO_GET_EVENT:
1825 case VIDEO_PLAY:
1826 case VIDEO_STOP:
1827 case VIDEO_FREEZE:
1828 case VIDEO_CONTINUE:
1829 case VIDEO_COMMAND:
1830 case VIDEO_TRY_COMMAND:
Hans Verkuilce680252010-04-06 15:58:53 -03001831 case VIDEO_SELECT_SOURCE:
1832 case AUDIO_SET_MUTE:
1833 case AUDIO_CHANNEL_SELECT:
1834 case AUDIO_BILINGUAL_CHANNEL_SELECT:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001835 return ivtv_decoder_ioctls(file, cmd, (void *)arg);
1836
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001837 default:
Hans Verkuild1c754a2012-04-19 12:36:03 -03001838 return -ENOTTY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001839 }
1840 return 0;
1841}
1842
Hans Verkuila3998102008-07-21 02:57:38 -03001843static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1844 .vidioc_querycap = ivtv_querycap,
Hans Verkuila3998102008-07-21 02:57:38 -03001845 .vidioc_s_audio = ivtv_s_audio,
1846 .vidioc_g_audio = ivtv_g_audio,
1847 .vidioc_enumaudio = ivtv_enumaudio,
1848 .vidioc_s_audout = ivtv_s_audout,
1849 .vidioc_g_audout = ivtv_g_audout,
1850 .vidioc_enum_input = ivtv_enum_input,
1851 .vidioc_enum_output = ivtv_enum_output,
1852 .vidioc_enumaudout = ivtv_enumaudout,
1853 .vidioc_cropcap = ivtv_cropcap,
1854 .vidioc_s_crop = ivtv_s_crop,
1855 .vidioc_g_crop = ivtv_g_crop,
1856 .vidioc_g_input = ivtv_g_input,
1857 .vidioc_s_input = ivtv_s_input,
1858 .vidioc_g_output = ivtv_g_output,
1859 .vidioc_s_output = ivtv_s_output,
1860 .vidioc_g_frequency = ivtv_g_frequency,
1861 .vidioc_s_frequency = ivtv_s_frequency,
1862 .vidioc_s_tuner = ivtv_s_tuner,
1863 .vidioc_g_tuner = ivtv_g_tuner,
1864 .vidioc_g_enc_index = ivtv_g_enc_index,
1865 .vidioc_g_fbuf = ivtv_g_fbuf,
1866 .vidioc_s_fbuf = ivtv_s_fbuf,
1867 .vidioc_g_std = ivtv_g_std,
1868 .vidioc_s_std = ivtv_s_std,
1869 .vidioc_overlay = ivtv_overlay,
1870 .vidioc_log_status = ivtv_log_status,
1871 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1872 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1873 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
Hans Verkuilda8ec562011-11-24 09:58:53 -03001874 .vidioc_decoder_cmd = ivtv_decoder_cmd,
1875 .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd,
Hans Verkuila3998102008-07-21 02:57:38 -03001876 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1877 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1878 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1879 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1880 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1881 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1882 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1883 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1884 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1885 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1886 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1887 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1888 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1889 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1890 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1891 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1892 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1893 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1894 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1895 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1896 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1897#ifdef CONFIG_VIDEO_ADV_DEBUG
1898 .vidioc_g_register = ivtv_g_register,
1899 .vidioc_s_register = ivtv_s_register,
1900#endif
1901 .vidioc_default = ivtv_default,
Hans Verkuil09250192010-03-27 14:10:13 -03001902 .vidioc_subscribe_event = ivtv_subscribe_event,
1903 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001904};
1905
Hans Verkuil3f038d82008-05-29 16:43:54 -03001906void ivtv_set_funcs(struct video_device *vdev)
1907{
Hans Verkuila3998102008-07-21 02:57:38 -03001908 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001909}