blob: d5cbb617775435075c756dcf27aaa21b89df5b48 [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;
292 if (itv->output_mode != OUT_MPG)
293 return -EBUSY;
294 if (atomic_read(&itv->decoding) > 0) {
295 ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
Hans Verkuilda8ec562011-11-24 09:58:53 -0300296 (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
Hans Verkuilac425142007-07-22 08:46:38 -0300297 set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300298 }
299 break;
300
Hans Verkuilda8ec562011-11-24 09:58:53 -0300301 case V4L2_DEC_CMD_RESUME:
302 dc->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300303 if (try) break;
304 if (itv->output_mode != OUT_MPG)
305 return -EBUSY;
Hans Verkuilac425142007-07-22 08:46:38 -0300306 if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
307 int speed = itv->speed;
308 itv->speed = 0;
309 return ivtv_start_decoding(id, speed);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300310 }
311 break;
312
313 default:
314 return -EINVAL;
315 }
316 return 0;
317}
318
Hans Verkuil3f038d82008-05-29 16:43:54 -0300319static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300320{
Hans Verkuil2f824412011-03-12 06:43:28 -0300321 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300322 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300323
Hans Verkuile88360c2008-06-21 08:00:56 -0300324 vbifmt->reserved[0] = 0;
325 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300326 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300327 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300328 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
329 if (itv->is_60hz) {
330 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
331 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
332 } else {
333 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
334 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
335 }
336 vbifmt->service_set = ivtv_get_service_set(vbifmt);
337 return 0;
338}
339
340static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
341{
Hans Verkuil2f824412011-03-12 06:43:28 -0300342 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300343 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300344 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300345
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300346 pixfmt->width = itv->cxhdl.width;
347 pixfmt->height = itv->cxhdl.height;
Hans Verkuile88360c2008-06-21 08:00:56 -0300348 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
349 pixfmt->field = V4L2_FIELD_INTERLACED;
350 pixfmt->priv = 0;
351 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
352 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
Hans Verkuila4a78712009-02-06 15:31:59 -0300353 /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
354 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
Hans Verkuile88360c2008-06-21 08:00:56 -0300355 pixfmt->bytesperline = 720;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300356 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300357 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
358 pixfmt->sizeimage = 128 * 1024;
359 pixfmt->bytesperline = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300360 }
361 return 0;
362}
363
Hans Verkuil3f038d82008-05-29 16:43:54 -0300364static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300365{
Hans Verkuil2f824412011-03-12 06:43:28 -0300366 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300367 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300368
Hans Verkuile88360c2008-06-21 08:00:56 -0300369 vbifmt->sampling_rate = 27000000;
370 vbifmt->offset = 248;
371 vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
372 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
373 vbifmt->start[0] = itv->vbi.start[0];
374 vbifmt->start[1] = itv->vbi.start[1];
375 vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
376 vbifmt->flags = 0;
377 vbifmt->reserved[0] = 0;
378 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300379 return 0;
380}
381
382static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
383{
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300384 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300385 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300386 struct ivtv *itv = id->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300387
Hans Verkuile88360c2008-06-21 08:00:56 -0300388 vbifmt->reserved[0] = 0;
389 vbifmt->reserved[1] = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300390 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300391
Hans Verkuil3f038d82008-05-29 16:43:54 -0300392 if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
393 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
394 V4L2_SLICED_VBI_525;
395 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300396 return 0;
397 }
398
Hans Verkuil4ff07902010-03-14 12:18:18 -0300399 v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300400 vbifmt->service_set = ivtv_get_service_set(vbifmt);
401 return 0;
402}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300403
Hans Verkuil3f038d82008-05-29 16:43:54 -0300404static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
405{
Hans Verkuil2f824412011-03-12 06:43:28 -0300406 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300407 struct ivtv *itv = id->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300408 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300409
Hans Verkuil3f038d82008-05-29 16:43:54 -0300410 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300411 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300412 pixfmt->width = itv->main_rect.width;
413 pixfmt->height = itv->main_rect.height;
414 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
415 pixfmt->field = V4L2_FIELD_INTERLACED;
416 pixfmt->priv = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300417 if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
418 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
419 case IVTV_YUV_MODE_INTERLACED:
Hans Verkuile88360c2008-06-21 08:00:56 -0300420 pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
Hans Verkuil3f038d82008-05-29 16:43:54 -0300421 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
422 break;
423 case IVTV_YUV_MODE_PROGRESSIVE:
Hans Verkuile88360c2008-06-21 08:00:56 -0300424 pixfmt->field = V4L2_FIELD_NONE;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300425 break;
426 default:
Hans Verkuile88360c2008-06-21 08:00:56 -0300427 pixfmt->field = V4L2_FIELD_ANY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300428 break;
429 }
Hans Verkuile88360c2008-06-21 08:00:56 -0300430 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
431 pixfmt->bytesperline = 720;
432 pixfmt->width = itv->yuv_info.v4l2_src_w;
433 pixfmt->height = itv->yuv_info.v4l2_src_h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300434 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
Hans Verkuile88360c2008-06-21 08:00:56 -0300435 pixfmt->sizeimage =
436 1080 * ((pixfmt->height + 31) & ~31);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300437 } else {
Hans Verkuile88360c2008-06-21 08:00:56 -0300438 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
439 pixfmt->sizeimage = 128 * 1024;
440 pixfmt->bytesperline = 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300441 }
442 return 0;
443}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300444
Hans Verkuil3f038d82008-05-29 16:43:54 -0300445static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
446{
Hans Verkuil2f824412011-03-12 06:43:28 -0300447 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300448 struct v4l2_window *winfmt = &fmt->fmt.win;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300449
450 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
451 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300452 winfmt->chromakey = itv->osd_chroma_key;
453 winfmt->global_alpha = itv->osd_global_alpha;
454 winfmt->field = V4L2_FIELD_INTERLACED;
455 winfmt->clips = NULL;
456 winfmt->clipcount = 0;
457 winfmt->bitmap = NULL;
458 winfmt->w.top = winfmt->w.left = 0;
459 winfmt->w.width = itv->osd_rect.width;
460 winfmt->w.height = itv->osd_rect.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300461 return 0;
462}
463
464static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
465{
466 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
467}
468
469static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
470{
Hans Verkuil2f824412011-03-12 06:43:28 -0300471 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300472 struct ivtv *itv = id->itv;
473 int w = fmt->fmt.pix.width;
474 int h = fmt->fmt.pix.height;
Hans Verkuila4a78712009-02-06 15:31:59 -0300475 int min_h = 2;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300476
477 w = min(w, 720);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300478 w = max(w, 2);
Hans Verkuila4a78712009-02-06 15:31:59 -0300479 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
480 /* YUV height must be a multiple of 32 */
481 h &= ~0x1f;
482 min_h = 32;
483 }
Hans Verkuil3f038d82008-05-29 16:43:54 -0300484 h = min(h, itv->is_50hz ? 576 : 480);
Hans Verkuila4a78712009-02-06 15:31:59 -0300485 h = max(h, min_h);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300486 ivtv_g_fmt_vid_cap(file, fh, fmt);
487 fmt->fmt.pix.width = w;
488 fmt->fmt.pix.height = h;
489 return 0;
490}
491
492static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
493{
494 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
495}
496
497static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
498{
499 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300500 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300501 struct ivtv *itv = id->itv;
502
503 if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
504 return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300505
506 /* set sliced VBI capture format */
507 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
Hans Verkuile88360c2008-06-21 08:00:56 -0300508 vbifmt->reserved[0] = 0;
509 vbifmt->reserved[1] = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300510
511 if (vbifmt->service_set)
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300512 ivtv_expand_service_set(vbifmt, itv->is_50hz);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300513 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300514 vbifmt->service_set = ivtv_get_service_set(vbifmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300515 return 0;
516}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300517
Hans Verkuil3f038d82008-05-29 16:43:54 -0300518static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
519{
Hans Verkuil2f824412011-03-12 06:43:28 -0300520 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuileffc3462008-09-06 08:24:37 -0300521 s32 w = fmt->fmt.pix.width;
522 s32 h = fmt->fmt.pix.height;
523 int field = fmt->fmt.pix.field;
524 int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300525
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300526 w = min(w, 720);
527 w = max(w, 2);
Hans Verkuil962d6992008-10-11 09:00:39 -0300528 /* Why can the height be 576 even when the output is NTSC?
529
530 Internally the buffers of the PVR350 are always set to 720x576. The
531 decoded video frame will always be placed in the top left corner of
532 this buffer. For any video which is not 720x576, the buffer will
533 then be cropped to remove the unused right and lower areas, with
534 the remaining image being scaled by the hardware to fit the display
535 area. The video can be scaled both up and down, so a 720x480 video
536 can be displayed full-screen on PAL and a 720x576 video can be
537 displayed without cropping on NTSC.
538
539 Note that the scaling only occurs on the video stream, the osd
540 resolution is locked to the broadcast standard and not scaled.
541
542 Thanks to Ian Armstrong for this explanation. */
543 h = min(h, 576);
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300544 h = max(h, 2);
545 if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300546 fmt->fmt.pix.field = field;
Hans Verkuileffc3462008-09-06 08:24:37 -0300547 fmt->fmt.pix.width = w;
548 fmt->fmt.pix.height = h;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300549 return ret;
550}
551
552static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
553{
Hans Verkuil2f824412011-03-12 06:43:28 -0300554 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuile88360c2008-06-21 08:00:56 -0300555 u32 chromakey = fmt->fmt.win.chromakey;
556 u8 global_alpha = fmt->fmt.win.global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300557
558 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
559 return -EINVAL;
Hans Verkuile88360c2008-06-21 08:00:56 -0300560 ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
561 fmt->fmt.win.chromakey = chromakey;
562 fmt->fmt.win.global_alpha = global_alpha;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300563 return 0;
564}
565
566static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
567{
568 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
569}
570
571static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
572{
Hans Verkuil2f824412011-03-12 06:43:28 -0300573 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300574 struct ivtv *itv = id->itv;
Hans Verkuil475977a2010-05-08 16:28:51 -0300575 struct v4l2_mbus_framefmt mbus_fmt;
Hans Verkuileffc3462008-09-06 08:24:37 -0300576 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300577 int w = fmt->fmt.pix.width;
578 int h = fmt->fmt.pix.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300579
580 if (ret)
581 return ret;
582
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300583 if (itv->cxhdl.width == w && itv->cxhdl.height == h)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300584 return 0;
585
586 if (atomic_read(&itv->capturing) > 0)
587 return -EBUSY;
588
Hans Verkuilf7b80e62010-06-27 06:07:26 -0300589 itv->cxhdl.width = w;
590 itv->cxhdl.height = h;
591 if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300592 fmt->fmt.pix.width /= 2;
Hans Verkuil475977a2010-05-08 16:28:51 -0300593 mbus_fmt.width = fmt->fmt.pix.width;
594 mbus_fmt.height = h;
595 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
596 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300597 return ivtv_g_fmt_vid_cap(file, fh, fmt);
598}
599
600static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
601{
Hans Verkuil2f824412011-03-12 06:43:28 -0300602 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300603
Hans Verkuila8b86432008-10-04 08:05:30 -0300604 if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
605 return -EBUSY;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300606 itv->vbi.sliced_in->service_set = 0;
Hans Verkuila8b86432008-10-04 08:05:30 -0300607 itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
Hans Verkuil4ff07902010-03-14 12:18:18 -0300608 v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300609 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
610}
611
612static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
613{
614 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
Hans Verkuil2f824412011-03-12 06:43:28 -0300615 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300616 struct ivtv *itv = id->itv;
617 int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
618
619 if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
620 return ret;
621
Hans Verkuil854ad9a2008-09-06 09:56:17 -0300622 check_service_set(vbifmt, itv->is_50hz);
Hans Verkuila8b86432008-10-04 08:05:30 -0300623 if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300624 return -EBUSY;
Hans Verkuila8b86432008-10-04 08:05:30 -0300625 itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
Hans Verkuil4ff07902010-03-14 12:18:18 -0300626 v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300627 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
628 return 0;
629}
630
Hans Verkuil3f038d82008-05-29 16:43:54 -0300631static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300632{
Hans Verkuil2f824412011-03-12 06:43:28 -0300633 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300634 struct ivtv *itv = id->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300635 struct yuv_playback_info *yi = &itv->yuv_info;
636 int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300637
Hans Verkuil3f038d82008-05-29 16:43:54 -0300638 if (ret)
639 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300640
Hans Verkuil3f038d82008-05-29 16:43:54 -0300641 if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
642 return 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300643
Hans Verkuil3f038d82008-05-29 16:43:54 -0300644 /* Return now if we already have some frame data */
645 if (yi->stream_size)
646 return -EBUSY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300647
Hans Verkuil3f038d82008-05-29 16:43:54 -0300648 yi->v4l2_src_w = fmt->fmt.pix.width;
649 yi->v4l2_src_h = fmt->fmt.pix.height;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300650
Hans Verkuil3f038d82008-05-29 16:43:54 -0300651 switch (fmt->fmt.pix.field) {
652 case V4L2_FIELD_NONE:
653 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300654 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300655 case V4L2_FIELD_ANY:
656 yi->lace_mode = IVTV_YUV_MODE_AUTO;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300657 break;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300658 case V4L2_FIELD_INTERLACED_BT:
659 yi->lace_mode =
660 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
661 break;
662 case V4L2_FIELD_INTERLACED_TB:
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300663 default:
Hans Verkuil3f038d82008-05-29 16:43:54 -0300664 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
665 break;
666 }
667 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
668
669 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
670 itv->dma_data_req_size =
671 1080 * ((yi->v4l2_src_h + 31) & ~31);
672
Hans Verkuil3f038d82008-05-29 16:43:54 -0300673 return 0;
674}
675
676static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
677{
Hans Verkuil2f824412011-03-12 06:43:28 -0300678 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300679 int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
680
681 if (ret == 0) {
682 itv->osd_chroma_key = fmt->fmt.win.chromakey;
683 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
684 ivtv_set_osd_alpha(itv);
685 }
686 return ret;
687}
688
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300689static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300690{
Hans Verkuil2f824412011-03-12 06:43:28 -0300691 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300692
693 chip->ident = V4L2_IDENT_NONE;
694 chip->revision = 0;
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300695 if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
696 if (v4l2_chip_match_host(&chip->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300697 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
698 return 0;
699 }
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300700 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
701 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300702 return -EINVAL;
703 /* TODO: is this correct? */
704 return ivtv_call_all_err(itv, core, g_chip_ident, chip);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300705}
706
Hans Verkuil36ecd492008-06-25 06:00:17 -0300707#ifdef CONFIG_VIDEO_ADV_DEBUG
708static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
709{
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300710 struct v4l2_dbg_register *regs = arg;
Hans Verkuiladb65bc2008-06-25 06:32:44 -0300711 volatile u8 __iomem *reg_start;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300712
713 if (!capable(CAP_SYS_ADMIN))
714 return -EPERM;
715 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
716 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
717 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
718 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
719 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
Roel Kluin223ffe52009-05-02 16:38:47 -0300720 else if (regs->reg < IVTV_ENCODER_SIZE)
Hans Verkuil36ecd492008-06-25 06:00:17 -0300721 reg_start = itv->enc_mem;
722 else
723 return -EINVAL;
724
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300725 regs->size = 4;
Hans Verkuil36ecd492008-06-25 06:00:17 -0300726 if (cmd == VIDIOC_DBG_G_REGISTER)
727 regs->val = readl(regs->reg + reg_start);
728 else
729 writel(regs->val, regs->reg + reg_start);
Hans Verkuil36ecd492008-06-25 06:00:17 -0300730 return 0;
731}
732
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300733static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300734{
Hans Verkuil2f824412011-03-12 06:43:28 -0300735 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300736
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300737 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300738 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300739 /* TODO: subdev errors should not be ignored, this should become a
740 subdev helper function. */
741 ivtv_call_all(itv, core, g_register, reg);
742 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300743}
744
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300745static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300746{
Hans Verkuil2f824412011-03-12 06:43:28 -0300747 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300748
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300749 if (v4l2_chip_match_host(&reg->match))
Hans Verkuil3f038d82008-05-29 16:43:54 -0300750 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
Hans Verkuil67ec09f2008-11-29 19:38:23 -0300751 /* TODO: subdev errors should not be ignored, this should become a
752 subdev helper function. */
753 ivtv_call_all(itv, core, s_register, reg);
754 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300755}
Hans Verkuil36ecd492008-06-25 06:00:17 -0300756#endif
Hans Verkuil3f038d82008-05-29 16:43:54 -0300757
Hans Verkuil3f038d82008-05-29 16:43:54 -0300758static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
759{
Hans Verkuild0c8b2d2011-11-07 07:25:10 -0300760 struct ivtv_open_id *id = fh2id(file->private_data);
761 struct ivtv *itv = id->itv;
762 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuil3f038d82008-05-29 16:43:54 -0300763
Hans Verkuil3f038d82008-05-29 16:43:54 -0300764 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
765 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
Hans Verkuil8ac05ae2009-02-07 07:02:27 -0300766 snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
Hans Verkuild0c8b2d2011-11-07 07:25:10 -0300767 vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
768 vcap->device_caps = s->caps;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300769 return 0;
770}
771
772static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
773{
Hans Verkuil2f824412011-03-12 06:43:28 -0300774 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300775
776 return ivtv_get_audio_input(itv, vin->index, vin);
777}
778
779static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
780{
Hans Verkuil2f824412011-03-12 06:43:28 -0300781 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300782
783 vin->index = itv->audio_input;
784 return ivtv_get_audio_input(itv, vin->index, vin);
785}
786
Hans Verkuil0e8025b2012-09-04 11:59:31 -0300787static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300788{
Hans Verkuil2f824412011-03-12 06:43:28 -0300789 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300790
791 if (vout->index >= itv->nof_audio_inputs)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300792 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300793
794 itv->audio_input = vout->index;
795 ivtv_audio_set_io(itv);
796
797 return 0;
798}
799
800static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
801{
Hans Verkuil2f824412011-03-12 06:43:28 -0300802 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300803
804 /* set it to defaults from our table */
805 return ivtv_get_audio_output(itv, vin->index, vin);
806}
807
808static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
809{
Hans Verkuil2f824412011-03-12 06:43:28 -0300810 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300811
812 vin->index = 0;
813 return ivtv_get_audio_output(itv, vin->index, vin);
814}
815
Hans Verkuilba9425b2012-09-04 12:03:49 -0300816static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout)
Hans Verkuil3f038d82008-05-29 16:43:54 -0300817{
Hans Verkuil2f824412011-03-12 06:43:28 -0300818 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300819
Hans Verkuilba9425b2012-09-04 12:03:49 -0300820 if (itv->card->video_outputs == NULL || vout->index != 0)
821 return -EINVAL;
822 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300823}
824
825static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
826{
Hans Verkuil2f824412011-03-12 06:43:28 -0300827 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300828
829 /* set it to defaults from our table */
830 return ivtv_get_input(itv, vin->index, vin);
831}
832
833static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
834{
Hans Verkuil2f824412011-03-12 06:43:28 -0300835 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300836
837 return ivtv_get_output(itv, vout->index, vout);
838}
839
840static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
841{
Hans Verkuil2f824412011-03-12 06:43:28 -0300842 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300843 struct ivtv *itv = id->itv;
844 struct yuv_playback_info *yi = &itv->yuv_info;
845 int streamtype;
846
847 streamtype = id->type;
848
849 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
850 return -EINVAL;
851 cropcap->bounds.top = cropcap->bounds.left = 0;
852 cropcap->bounds.width = 720;
853 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
854 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
855 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
856 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
857 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
858 if (yi->track_osd) {
859 cropcap->bounds.width = yi->osd_full_w;
860 cropcap->bounds.height = yi->osd_full_h;
861 } else {
862 cropcap->bounds.width = 720;
863 cropcap->bounds.height =
864 itv->is_out_50hz ? 576 : 480;
865 }
866 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
867 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
868 } else {
869 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
870 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
871 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
872 }
873 cropcap->defrect = cropcap->bounds;
874 return 0;
875}
876
877static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
878{
Hans Verkuil2f824412011-03-12 06:43:28 -0300879 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300880 struct ivtv *itv = id->itv;
881 struct yuv_playback_info *yi = &itv->yuv_info;
882 int streamtype;
883
884 streamtype = id->type;
885
Hans Verkuil3f038d82008-05-29 16:43:54 -0300886 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
887 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
888 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
889 yi->main_rect = crop->c;
890 return 0;
891 } else {
892 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
893 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
894 itv->main_rect = crop->c;
895 return 0;
896 }
897 }
898 return -EINVAL;
899 }
900 return -EINVAL;
901}
902
903static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
904{
Hans Verkuil2f824412011-03-12 06:43:28 -0300905 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -0300906 struct ivtv *itv = id->itv;
907 struct yuv_playback_info *yi = &itv->yuv_info;
908 int streamtype;
909
910 streamtype = id->type;
911
912 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
913 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
914 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
915 crop->c = yi->main_rect;
916 else
917 crop->c = itv->main_rect;
918 return 0;
919 }
920 return -EINVAL;
921}
922
923static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
924{
925 static struct v4l2_fmtdesc formats[] = {
926 { 0, 0, 0,
927 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
928 { 0, 0, 0, 0 }
929 },
930 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
931 "MPEG", V4L2_PIX_FMT_MPEG,
932 { 0, 0, 0, 0 }
933 }
934 };
935 enum v4l2_buf_type type = fmt->type;
936
937 if (fmt->index > 1)
938 return -EINVAL;
939
940 *fmt = formats[fmt->index];
941 fmt->type = type;
942 return 0;
943}
944
945static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
946{
Hans Verkuil2f824412011-03-12 06:43:28 -0300947 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300948
949 static struct v4l2_fmtdesc formats[] = {
950 { 0, 0, 0,
951 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
952 { 0, 0, 0, 0 }
953 },
954 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
955 "MPEG", V4L2_PIX_FMT_MPEG,
956 { 0, 0, 0, 0 }
957 }
958 };
959 enum v4l2_buf_type type = fmt->type;
960
961 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
962 return -EINVAL;
963
964 if (fmt->index > 1)
965 return -EINVAL;
966
967 *fmt = formats[fmt->index];
968 fmt->type = type;
969
970 return 0;
971}
972
973static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
974{
Hans Verkuil2f824412011-03-12 06:43:28 -0300975 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300976
977 *i = itv->active_input;
978
979 return 0;
980}
981
982int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
983{
Hans Verkuil2f824412011-03-12 06:43:28 -0300984 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -0300985
986 if (inp < 0 || inp >= itv->nof_inputs)
987 return -EINVAL;
988
989 if (inp == itv->active_input) {
990 IVTV_DEBUG_INFO("Input unchanged\n");
991 return 0;
992 }
993
994 if (atomic_read(&itv->capturing) > 0) {
995 return -EBUSY;
996 }
997
998 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
999 itv->active_input, inp);
1000
1001 itv->active_input = inp;
1002 /* Set the audio input to whatever is appropriate for the
1003 input type. */
1004 itv->audio_input = itv->card->video_inputs[inp].audio_index;
1005
1006 /* prevent others from messing with the streams until
1007 we're finished changing inputs. */
1008 ivtv_mute(itv);
1009 ivtv_video_set_io(itv);
1010 ivtv_audio_set_io(itv);
1011 ivtv_unmute(itv);
1012
1013 return 0;
1014}
1015
1016static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
1017{
Hans Verkuil2f824412011-03-12 06:43:28 -03001018 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001019
1020 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1021 return -EINVAL;
1022
1023 *i = itv->active_output;
1024
1025 return 0;
1026}
1027
1028static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
1029{
Hans Verkuil2f824412011-03-12 06:43:28 -03001030 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001031
1032 if (outp >= itv->card->nof_outputs)
1033 return -EINVAL;
1034
1035 if (outp == itv->active_output) {
1036 IVTV_DEBUG_INFO("Output unchanged\n");
1037 return 0;
1038 }
1039 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1040 itv->active_output, outp);
1041
1042 itv->active_output = outp;
Hans Verkuil5325b422009-04-02 11:26:22 -03001043 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
1044 SAA7127_INPUT_TYPE_NORMAL,
1045 itv->card->video_outputs[outp].video_output, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001046
1047 return 0;
1048}
1049
1050static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1051{
Hans Verkuil2f824412011-03-12 06:43:28 -03001052 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001053
1054 if (vf->tuner != 0)
1055 return -EINVAL;
1056
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001057 ivtv_call_all(itv, tuner, g_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001058 return 0;
1059}
1060
1061int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1062{
Hans Verkuil2f824412011-03-12 06:43:28 -03001063 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001064
1065 if (vf->tuner != 0)
1066 return -EINVAL;
1067
1068 ivtv_mute(itv);
1069 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001070 ivtv_call_all(itv, tuner, s_frequency, vf);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001071 ivtv_unmute(itv);
1072 return 0;
1073}
1074
1075static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1076{
Hans Verkuil2f824412011-03-12 06:43:28 -03001077 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001078
1079 *std = itv->std;
1080 return 0;
1081}
1082
Ian Armstrongc5874c92011-05-29 21:33:17 -03001083void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001084{
Hans Verkuil3f038d82008-05-29 16:43:54 -03001085 itv->std = *std;
1086 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
Hans Verkuilf7b80e62010-06-27 06:07:26 -03001087 itv->is_50hz = !itv->is_60hz;
1088 cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
1089 itv->cxhdl.width = 720;
1090 itv->cxhdl.height = itv->is_50hz ? 576 : 480;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001091 itv->vbi.count = itv->is_50hz ? 18 : 12;
1092 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1093 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1094
1095 if (itv->hw_flags & IVTV_HW_CX25840)
1096 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1097
Hans Verkuil3f038d82008-05-29 16:43:54 -03001098 /* Tuner */
Hans Verkuilf41737e2009-04-01 03:52:39 -03001099 ivtv_call_all(itv, core, s_std, itv->std);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001100}
Hans Verkuil3f038d82008-05-29 16:43:54 -03001101
Ian Armstrongc5874c92011-05-29 21:33:17 -03001102void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
1103{
1104 struct yuv_playback_info *yi = &itv->yuv_info;
1105 DEFINE_WAIT(wait);
1106 int f;
Ian Armstrong2443bae2010-03-13 20:22:34 -03001107
Ian Armstrongc5874c92011-05-29 21:33:17 -03001108 /* set display standard */
1109 itv->std_out = *std;
1110 itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1111 itv->is_out_50hz = !itv->is_out_60hz;
1112 ivtv_call_all(itv, video, s_std_output, itv->std_out);
Ian Armstrong2443bae2010-03-13 20:22:34 -03001113
Ian Armstrongc5874c92011-05-29 21:33:17 -03001114 /*
1115 * The next firmware call is time sensitive. Time it to
1116 * avoid risk of a hard lock, by trying to ensure the call
1117 * happens within the first 100 lines of the top field.
1118 * Make 4 attempts to sync to the decoder before giving up.
1119 */
Hans Verkuilcdc03782011-10-11 06:06:58 -03001120 mutex_unlock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001121 for (f = 0; f < 4; f++) {
1122 prepare_to_wait(&itv->vsync_waitq, &wait,
1123 TASK_UNINTERRUPTIBLE);
1124 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
1125 break;
1126 schedule_timeout(msecs_to_jiffies(25));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001127 }
Ian Armstrongc5874c92011-05-29 21:33:17 -03001128 finish_wait(&itv->vsync_waitq, &wait);
Hans Verkuilcdc03782011-10-11 06:06:58 -03001129 mutex_lock(&itv->serialize_lock);
Ian Armstrongc5874c92011-05-29 21:33:17 -03001130
1131 if (f == 4)
1132 IVTV_WARN("Mode change failed to sync to decoder\n");
1133
1134 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1135 itv->main_rect.left = 0;
1136 itv->main_rect.top = 0;
1137 itv->main_rect.width = 720;
1138 itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
1139 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1140 720, itv->main_rect.height, 0, 0);
1141 yi->main_rect = itv->main_rect;
1142 if (!itv->osd_info) {
1143 yi->osd_full_w = 720;
1144 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1145 }
1146}
1147
1148int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1149{
1150 struct ivtv *itv = fh2id(fh)->itv;
1151
1152 if ((*std & V4L2_STD_ALL) == 0)
1153 return -EINVAL;
1154
1155 if (*std == itv->std)
1156 return 0;
1157
1158 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1159 atomic_read(&itv->capturing) > 0 ||
1160 atomic_read(&itv->decoding) > 0) {
1161 /* Switching standard would mess with already running
1162 streams, prevent that by returning EBUSY. */
1163 return -EBUSY;
1164 }
1165
1166 IVTV_DEBUG_INFO("Switching standard to %llx.\n",
1167 (unsigned long long)itv->std);
1168
1169 ivtv_s_std_enc(itv, std);
1170 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
1171 ivtv_s_std_dec(itv, std);
1172
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001173 return 0;
1174}
1175
Hans Verkuil3f038d82008-05-29 16:43:54 -03001176static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001177{
Hans Verkuil2f824412011-03-12 06:43:28 -03001178 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001179 struct ivtv *itv = id->itv;
1180
1181 if (vt->index != 0)
1182 return -EINVAL;
1183
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001184 ivtv_call_all(itv, tuner, s_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001185
1186 return 0;
1187}
1188
1189static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1190{
Hans Verkuil2f824412011-03-12 06:43:28 -03001191 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001192
1193 if (vt->index != 0)
1194 return -EINVAL;
1195
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001196 ivtv_call_all(itv, tuner, g_tuner, vt);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001197
Hans Verkuild118e292011-06-25 10:28:21 -03001198 if (vt->type == V4L2_TUNER_RADIO)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001199 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
Hans Verkuild118e292011-06-25 10:28:21 -03001200 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001201 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
Hans Verkuil3f038d82008-05-29 16:43:54 -03001202 return 0;
1203}
1204
1205static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1206{
Hans Verkuil2f824412011-03-12 06:43:28 -03001207 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001208 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1209 int f, l;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001210
Hans Verkuil79afcb12008-06-21 09:02:36 -03001211 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001212 for (f = 0; f < 2; f++) {
1213 for (l = 0; l < 24; l++) {
1214 if (valid_service_line(f, l, itv->is_50hz))
1215 cap->service_lines[f][l] = set;
1216 }
1217 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001218 } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001219 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1220 return -EINVAL;
1221 if (itv->is_60hz) {
1222 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1223 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1224 } else {
1225 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1226 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1227 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001228 } else {
1229 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001230 }
Hans Verkuil2b5d9482011-07-29 07:21:33 -03001231
1232 set = 0;
1233 for (f = 0; f < 2; f++)
1234 for (l = 0; l < 24; l++)
1235 set |= cap->service_lines[f][l];
1236 cap->service_set = set;
1237 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001238}
1239
1240static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1241{
Hans Verkuil2f824412011-03-12 06:43:28 -03001242 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001243 struct v4l2_enc_idx_entry *e = idx->entry;
1244 int entries;
1245 int i;
1246
1247 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1248 IVTV_MAX_PGM_INDEX;
1249 if (entries > V4L2_ENC_IDX_ENTRIES)
1250 entries = V4L2_ENC_IDX_ENTRIES;
1251 idx->entries = 0;
1252 for (i = 0; i < entries; i++) {
1253 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1254 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1255 idx->entries++;
1256 e++;
1257 }
1258 }
1259 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1260 return 0;
1261}
1262
1263static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1264{
Hans Verkuil2f824412011-03-12 06:43:28 -03001265 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001266 struct ivtv *itv = id->itv;
1267
Hans Verkuil3f038d82008-05-29 16:43:54 -03001268
1269 switch (enc->cmd) {
1270 case V4L2_ENC_CMD_START:
1271 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1272 enc->flags = 0;
1273 return ivtv_start_capture(id);
1274
1275 case V4L2_ENC_CMD_STOP:
1276 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1277 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1278 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1279 return 0;
1280
1281 case V4L2_ENC_CMD_PAUSE:
1282 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1283 enc->flags = 0;
1284
1285 if (!atomic_read(&itv->capturing))
1286 return -EPERM;
1287 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1288 return 0;
1289
1290 ivtv_mute(itv);
1291 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1292 break;
1293
1294 case V4L2_ENC_CMD_RESUME:
1295 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1296 enc->flags = 0;
1297
1298 if (!atomic_read(&itv->capturing))
1299 return -EPERM;
1300
1301 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1302 return 0;
1303
1304 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1305 ivtv_unmute(itv);
1306 break;
1307 default:
1308 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1309 return -EINVAL;
1310 }
1311
1312 return 0;
1313}
1314
1315static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1316{
Hans Verkuil2f824412011-03-12 06:43:28 -03001317 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001318
Hans Verkuil3f038d82008-05-29 16:43:54 -03001319 switch (enc->cmd) {
1320 case V4L2_ENC_CMD_START:
1321 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1322 enc->flags = 0;
1323 return 0;
1324
1325 case V4L2_ENC_CMD_STOP:
1326 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1327 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1328 return 0;
1329
1330 case V4L2_ENC_CMD_PAUSE:
1331 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1332 enc->flags = 0;
1333 return 0;
1334
1335 case V4L2_ENC_CMD_RESUME:
1336 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1337 enc->flags = 0;
1338 return 0;
1339 default:
1340 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1341 return -EINVAL;
1342 }
1343}
1344
1345static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1346{
Hans Verkuil2f824412011-03-12 06:43:28 -03001347 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001348 u32 data[CX2341X_MBOX_MAX_DATA];
Hans Verkuil3f038d82008-05-29 16:43:54 -03001349 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001350
Hans Verkuil3f038d82008-05-29 16:43:54 -03001351 int pixfmt;
1352 static u32 pixel_format[16] = {
1353 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1354 V4L2_PIX_FMT_RGB565,
1355 V4L2_PIX_FMT_RGB555,
1356 V4L2_PIX_FMT_RGB444,
1357 V4L2_PIX_FMT_RGB32,
1358 0,
1359 0,
1360 0,
1361 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1362 V4L2_PIX_FMT_YUV565,
1363 V4L2_PIX_FMT_YUV555,
1364 V4L2_PIX_FMT_YUV444,
1365 V4L2_PIX_FMT_YUV32,
1366 0,
1367 0,
1368 0,
1369 };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001370
Hans Verkuil3f038d82008-05-29 16:43:54 -03001371 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1372 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001373 if (!itv->osd_video_pbase)
1374 return -EINVAL;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001375
Hans Verkuil3f038d82008-05-29 16:43:54 -03001376 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1377 V4L2_FBUF_CAP_GLOBAL_ALPHA;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001378
Hans Verkuil3f038d82008-05-29 16:43:54 -03001379 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1380 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1381 pixfmt = (data[0] >> 3) & 0xf;
Hans Verkuild46c17d2007-03-10 17:59:15 -03001382
Hans Verkuil3f038d82008-05-29 16:43:54 -03001383 fb->fmt.pixelformat = pixel_format[pixfmt];
1384 fb->fmt.width = itv->osd_rect.width;
1385 fb->fmt.height = itv->osd_rect.height;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001386 fb->fmt.field = V4L2_FIELD_INTERLACED;
1387 fb->fmt.bytesperline = fb->fmt.width;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001388 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1389 fb->fmt.field = V4L2_FIELD_INTERLACED;
1390 fb->fmt.priv = 0;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001391 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1392 fb->fmt.bytesperline *= 2;
1393 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1394 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1395 fb->fmt.bytesperline *= 2;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001396 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001397 fb->base = (void *)itv->osd_video_pbase;
Hans Verkuil5cf2cc42008-06-21 09:06:59 -03001398 fb->flags = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001399
Hans Verkuil3f038d82008-05-29 16:43:54 -03001400 if (itv->osd_chroma_key_state)
1401 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001402
Hans Verkuil3f038d82008-05-29 16:43:54 -03001403 if (itv->osd_global_alpha_state)
1404 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001405
Ian Armstrongec9faa12008-10-06 03:06:08 -03001406 if (yi->track_osd)
1407 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1408
Hans Verkuil3f038d82008-05-29 16:43:54 -03001409 pixfmt &= 7;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001410
Hans Verkuil3f038d82008-05-29 16:43:54 -03001411 /* no local alpha for RGB565 or unknown formats */
1412 if (pixfmt == 1 || pixfmt > 4)
Hans Verkuil987e00b2007-05-29 13:03:27 -03001413 return 0;
Hans Verkuil987e00b2007-05-29 13:03:27 -03001414
Hans Verkuil3f038d82008-05-29 16:43:54 -03001415 /* 16-bit formats have inverted local alpha */
1416 if (pixfmt == 2 || pixfmt == 3)
1417 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1418 else
1419 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001420
Hans Verkuil3f038d82008-05-29 16:43:54 -03001421 if (itv->osd_local_alpha_state) {
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001422 /* 16-bit formats have inverted local alpha */
1423 if (pixfmt == 2 || pixfmt == 3)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001424 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
Hans Verkuil2d4d5f12007-08-23 21:15:24 -03001425 else
Hans Verkuil3f038d82008-05-29 16:43:54 -03001426 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001427 }
1428
Hans Verkuil3f038d82008-05-29 16:43:54 -03001429 return 0;
1430}
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001431
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001432static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001433{
Hans Verkuil2f824412011-03-12 06:43:28 -03001434 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001435 struct ivtv *itv = id->itv;
1436 struct yuv_playback_info *yi = &itv->yuv_info;
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001437
Hans Verkuil3f038d82008-05-29 16:43:54 -03001438 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001439 return -EINVAL;
Hans Verkuil37f89f92008-06-22 11:57:31 -03001440 if (!itv->osd_video_pbase)
1441 return -EINVAL;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001442
1443 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1444 itv->osd_local_alpha_state =
1445 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1446 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1447 ivtv_set_osd_alpha(itv);
1448 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
Hans Verkuile6eb28c2012-09-04 10:26:45 -03001449 return 0;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001450}
1451
1452static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1453{
Hans Verkuil2f824412011-03-12 06:43:28 -03001454 struct ivtv_open_id *id = fh2id(fh);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001455 struct ivtv *itv = id->itv;
1456
1457 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1458 return -EINVAL;
1459
1460 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1461
1462 return 0;
1463}
1464
Hans Verkuil85f5fe32012-09-04 11:46:09 -03001465static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
Hans Verkuil09250192010-03-27 14:10:13 -03001466{
1467 switch (sub->type) {
1468 case V4L2_EVENT_VSYNC:
1469 case V4L2_EVENT_EOS:
Hans de Goedec53c2542012-04-08 12:59:46 -03001470 return v4l2_event_subscribe(fh, sub, 0, NULL);
Hans de Goede3e3661492012-04-08 12:59:47 -03001471 case V4L2_EVENT_CTRL:
1472 return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
Hans Verkuil09250192010-03-27 14:10:13 -03001473 default:
1474 return -EINVAL;
1475 }
Hans Verkuil09250192010-03-27 14:10:13 -03001476}
1477
Hans Verkuil3f038d82008-05-29 16:43:54 -03001478static int ivtv_log_status(struct file *file, void *fh)
1479{
Hans Verkuil2f824412011-03-12 06:43:28 -03001480 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001481 u32 data[CX2341X_MBOX_MAX_DATA];
1482
1483 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1484 struct v4l2_input vidin;
1485 struct v4l2_audio audin;
1486 int i;
1487
Hans Verkuil3f038d82008-05-29 16:43:54 -03001488 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1489 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1490 struct tveeprom tv;
1491
1492 ivtv_read_eeprom(itv, &tv);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001493 }
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001494 ivtv_call_all(itv, core, log_status);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001495 ivtv_get_input(itv, itv->active_input, &vidin);
1496 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1497 IVTV_INFO("Video Input: %s\n", vidin.name);
1498 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1499 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1500 if (has_output) {
1501 struct v4l2_output vidout;
1502 struct v4l2_audioout audout;
1503 int mode = itv->output_mode;
1504 static const char * const output_modes[5] = {
1505 "None",
1506 "MPEG Streaming",
1507 "YUV Streaming",
1508 "YUV Frames",
1509 "Passthrough",
1510 };
Hans Verkuil3f038d82008-05-29 16:43:54 -03001511 static const char * const alpha_mode[4] = {
1512 "None",
1513 "Global",
1514 "Local",
1515 "Global and Local"
1516 };
1517 static const char * const pixel_format[16] = {
1518 "ARGB Indexed",
1519 "RGB 5:6:5",
1520 "ARGB 1:5:5:5",
1521 "ARGB 1:4:4:4",
1522 "ARGB 8:8:8:8",
1523 "5",
1524 "6",
1525 "7",
1526 "AYUV Indexed",
1527 "YUV 5:6:5",
1528 "AYUV 1:5:5:5",
1529 "AYUV 1:4:4:4",
1530 "AYUV 8:8:8:8",
1531 "13",
1532 "14",
1533 "15",
1534 };
1535
1536 ivtv_get_output(itv, itv->active_output, &vidout);
1537 ivtv_get_audio_output(itv, 0, &audout);
1538 IVTV_INFO("Video Output: %s\n", vidout.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001539 if (mode < 0 || mode > OUT_PASSTHROUGH)
1540 mode = OUT_NONE;
1541 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1542 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1543 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1544 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1545 data[0] & 1 ? "On" : "Off",
1546 alpha_mode[(data[0] >> 1) & 0x3],
1547 pixel_format[(data[0] >> 3) & 0xf]);
1548 }
1549 IVTV_INFO("Tuner: %s\n",
1550 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
Hans Verkuileb2ba852012-03-02 13:02:11 -03001551 v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001552 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1553 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1554 struct ivtv_stream *s = &itv->streams[i];
1555
Hans Verkuil8ac05ae2009-02-07 07:02:27 -03001556 if (s->vdev == NULL || s->buffers == 0)
Hans Verkuil3f038d82008-05-29 16:43:54 -03001557 continue;
1558 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1559 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1560 (s->buffers * s->buf_size) / 1024, s->buffers);
1561 }
1562
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001563 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
1564 (long long)itv->mpg_data_received,
1565 (long long)itv->vbi_data_inserted);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001566 return 0;
1567}
1568
Hans Verkuilda8ec562011-11-24 09:58:53 -03001569static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1570{
1571 struct ivtv_open_id *id = fh2id(file->private_data);
1572 struct ivtv *itv = id->itv;
1573
1574 IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
1575 return ivtv_video_command(itv, id, dec, false);
1576}
1577
1578static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
1579{
1580 struct ivtv_open_id *id = fh2id(file->private_data);
1581 struct ivtv *itv = id->itv;
1582
1583 IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
1584 return ivtv_video_command(itv, id, dec, true);
1585}
1586
Hans Verkuild4e7ee32007-03-10 18:19:12 -03001587static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001588{
Hans Verkuil09250192010-03-27 14:10:13 -03001589 struct ivtv_open_id *id = fh2id(filp->private_data);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001590 struct ivtv *itv = id->itv;
1591 int nonblocking = filp->f_flags & O_NONBLOCK;
1592 struct ivtv_stream *s = &itv->streams[id->type];
Hans Verkuilce680252010-04-06 15:58:53 -03001593 unsigned long iarg = (unsigned long)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001594
1595 switch (cmd) {
1596 case IVTV_IOC_DMA_FRAME: {
1597 struct ivtv_dma_frame *args = arg;
1598
1599 IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
1600 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1601 return -EINVAL;
1602 if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1603 return -EINVAL;
1604 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1605 return 0;
Ian Armstrong42b03fe2008-06-21 11:09:46 -03001606 if (ivtv_start_decoding(id, id->type)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001607 return -EBUSY;
1608 }
1609 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
1610 ivtv_release_stream(s);
1611 return -EBUSY;
1612 }
Hans Verkuilad8ff0f2007-08-20 16:01:58 -03001613 /* Mark that this file handle started the UDMA_YUV mode */
1614 id->yuv_frames = 1;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001615 if (args->y_source == NULL)
1616 return 0;
1617 return ivtv_yuv_prep_frame(itv, args);
1618 }
1619
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001620 case IVTV_IOC_PASSTHROUGH_MODE:
1621 IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
1622 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1623 return -EINVAL;
1624 return ivtv_passthrough_mode(itv, *(int *)arg != 0);
1625
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001626 case VIDEO_GET_PTS: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001627 s64 *pts = arg;
1628 s64 frame;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001629
1630 IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
1631 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1632 *pts = s->dma_pts;
1633 break;
1634 }
1635 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1636 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001637 return ivtv_g_pts_frame(itv, pts, &frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001638 }
1639
1640 case VIDEO_GET_FRAME_COUNT: {
Hans Verkuildebf8002011-12-15 10:32:53 -03001641 s64 *frame = arg;
1642 s64 pts;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001643
1644 IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
1645 if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
1646 *frame = 0;
1647 break;
1648 }
1649 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1650 return -EINVAL;
Hans Verkuildebf8002011-12-15 10:32:53 -03001651 return ivtv_g_pts_frame(itv, &pts, frame);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001652 }
1653
1654 case VIDEO_PLAY: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001655 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001656
1657 IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001658 memset(&dc, 0, sizeof(dc));
1659 dc.cmd = V4L2_DEC_CMD_START;
1660 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001661 }
1662
1663 case VIDEO_STOP: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001664 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001665
1666 IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001667 memset(&dc, 0, sizeof(dc));
1668 dc.cmd = V4L2_DEC_CMD_STOP;
1669 dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
1670 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001671 }
1672
1673 case VIDEO_FREEZE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001674 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001675
1676 IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001677 memset(&dc, 0, sizeof(dc));
1678 dc.cmd = V4L2_DEC_CMD_PAUSE;
1679 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001680 }
1681
1682 case VIDEO_CONTINUE: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001683 struct v4l2_decoder_cmd dc;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001684
1685 IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
Hans Verkuilda8ec562011-11-24 09:58:53 -03001686 memset(&dc, 0, sizeof(dc));
1687 dc.cmd = V4L2_DEC_CMD_RESUME;
1688 return ivtv_video_command(itv, id, &dc, 0);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001689 }
1690
1691 case VIDEO_COMMAND:
1692 case VIDEO_TRY_COMMAND: {
Hans Verkuilda8ec562011-11-24 09:58:53 -03001693 /* Note: struct v4l2_decoder_cmd has the same layout as
1694 struct video_command */
1695 struct v4l2_decoder_cmd *dc = arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001696 int try = (cmd == VIDEO_TRY_COMMAND);
1697
1698 if (try)
Hans Verkuilda8ec562011-11-24 09:58:53 -03001699 IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001700 else
Hans Verkuilda8ec562011-11-24 09:58:53 -03001701 IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
1702 return ivtv_video_command(itv, id, dc, try);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001703 }
1704
1705 case VIDEO_GET_EVENT: {
1706 struct video_event *ev = arg;
1707 DEFINE_WAIT(wait);
1708
1709 IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
1710 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1711 return -EINVAL;
1712 memset(ev, 0, sizeof(*ev));
1713 set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
1714
1715 while (1) {
1716 if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
1717 ev->type = VIDEO_EVENT_DECODER_STOPPED;
1718 else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
1719 ev->type = VIDEO_EVENT_VSYNC;
Hans Verkuil037c86c2007-03-10 06:30:19 -03001720 ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
1721 VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
1722 if (itv->output_mode == OUT_UDMA_YUV &&
1723 (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
1724 IVTV_YUV_MODE_PROGRESSIVE) {
1725 ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
1726 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001727 }
1728 if (ev->type)
1729 return 0;
1730 if (nonblocking)
1731 return -EAGAIN;
Hans Verkuilbaa40722007-08-19 07:10:55 -03001732 /* Wait for event. Note that serialize_lock is locked,
1733 so to allow other processes to access the driver while
1734 we are waiting unlock first and later lock again. */
1735 mutex_unlock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001736 prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
Hans Verkuilec105a422009-05-02 11:10:23 -03001737 if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
1738 !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001739 schedule();
1740 finish_wait(&itv->event_waitq, &wait);
Hans Verkuilbaa40722007-08-19 07:10:55 -03001741 mutex_lock(&itv->serialize_lock);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001742 if (signal_pending(current)) {
1743 /* return if a signal was received */
1744 IVTV_DEBUG_INFO("User stopped wait for event\n");
1745 return -EINTR;
1746 }
1747 }
1748 break;
1749 }
1750
Hans Verkuilce680252010-04-06 15:58:53 -03001751 case VIDEO_SELECT_SOURCE:
1752 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
1753 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
1754 return -EINVAL;
1755 return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
1756
1757 case AUDIO_SET_MUTE:
1758 IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
1759 itv->speed_mute_audio = iarg;
1760 return 0;
1761
1762 case AUDIO_CHANNEL_SELECT:
1763 IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
1764 if (iarg > AUDIO_STEREO_SWAPPED)
1765 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001766 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001767
1768 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1769 IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
1770 if (iarg > AUDIO_STEREO_SWAPPED)
1771 return -EINVAL;
Hans Verkuilbc169e32012-03-31 05:18:19 -03001772 return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
Hans Verkuilce680252010-04-06 15:58:53 -03001773
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001774 default:
1775 return -EINVAL;
1776 }
1777 return 0;
1778}
1779
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03001780static long ivtv_default(struct file *file, void *fh, bool valid_prio,
1781 int cmd, void *arg)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001782{
Hans Verkuil2f824412011-03-12 06:43:28 -03001783 struct ivtv *itv = fh2id(fh)->itv;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001784
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001785 if (!valid_prio) {
1786 switch (cmd) {
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001787 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilcc0a2d42011-03-11 19:03:41 -03001788 case VIDEO_PLAY:
1789 case VIDEO_STOP:
1790 case VIDEO_FREEZE:
1791 case VIDEO_CONTINUE:
1792 case VIDEO_COMMAND:
1793 case VIDEO_SELECT_SOURCE:
1794 case AUDIO_SET_MUTE:
1795 case AUDIO_CHANNEL_SELECT:
1796 case AUDIO_BILINGUAL_CHANNEL_SELECT:
1797 return -EBUSY;
1798 }
1799 }
1800
Hans Verkuild46c17d2007-03-10 17:59:15 -03001801 switch (cmd) {
Hans Verkuil3f038d82008-05-29 16:43:54 -03001802 case VIDIOC_INT_RESET: {
1803 u32 val = *(u32 *)arg;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001804
Hans Verkuil3f038d82008-05-29 16:43:54 -03001805 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1806 ivtv_reset_ir_gpio(itv);
1807 if (val & 0x02)
Hans Verkuil67ec09f2008-11-29 19:38:23 -03001808 v4l2_subdev_call(itv->sd_video, core, reset, 0);
Hans Verkuil3f038d82008-05-29 16:43:54 -03001809 break;
1810 }
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001811
Hans Verkuilac9575f2009-02-14 19:58:33 -03001812 case IVTV_IOC_DMA_FRAME:
Hans Verkuil6e82a6a22011-12-15 10:40:23 -03001813 case IVTV_IOC_PASSTHROUGH_MODE:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001814 case VIDEO_GET_PTS:
1815 case VIDEO_GET_FRAME_COUNT:
1816 case VIDEO_GET_EVENT:
1817 case VIDEO_PLAY:
1818 case VIDEO_STOP:
1819 case VIDEO_FREEZE:
1820 case VIDEO_CONTINUE:
1821 case VIDEO_COMMAND:
1822 case VIDEO_TRY_COMMAND:
Hans Verkuilce680252010-04-06 15:58:53 -03001823 case VIDEO_SELECT_SOURCE:
1824 case AUDIO_SET_MUTE:
1825 case AUDIO_CHANNEL_SELECT:
1826 case AUDIO_BILINGUAL_CHANNEL_SELECT:
Hans Verkuilac9575f2009-02-14 19:58:33 -03001827 return ivtv_decoder_ioctls(file, cmd, (void *)arg);
1828
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001829 default:
Hans Verkuild1c754a2012-04-19 12:36:03 -03001830 return -ENOTTY;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001831 }
1832 return 0;
1833}
1834
Hans Verkuila3998102008-07-21 02:57:38 -03001835static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1836 .vidioc_querycap = ivtv_querycap,
Hans Verkuila3998102008-07-21 02:57:38 -03001837 .vidioc_s_audio = ivtv_s_audio,
1838 .vidioc_g_audio = ivtv_g_audio,
1839 .vidioc_enumaudio = ivtv_enumaudio,
1840 .vidioc_s_audout = ivtv_s_audout,
1841 .vidioc_g_audout = ivtv_g_audout,
1842 .vidioc_enum_input = ivtv_enum_input,
1843 .vidioc_enum_output = ivtv_enum_output,
1844 .vidioc_enumaudout = ivtv_enumaudout,
1845 .vidioc_cropcap = ivtv_cropcap,
1846 .vidioc_s_crop = ivtv_s_crop,
1847 .vidioc_g_crop = ivtv_g_crop,
1848 .vidioc_g_input = ivtv_g_input,
1849 .vidioc_s_input = ivtv_s_input,
1850 .vidioc_g_output = ivtv_g_output,
1851 .vidioc_s_output = ivtv_s_output,
1852 .vidioc_g_frequency = ivtv_g_frequency,
1853 .vidioc_s_frequency = ivtv_s_frequency,
1854 .vidioc_s_tuner = ivtv_s_tuner,
1855 .vidioc_g_tuner = ivtv_g_tuner,
1856 .vidioc_g_enc_index = ivtv_g_enc_index,
1857 .vidioc_g_fbuf = ivtv_g_fbuf,
1858 .vidioc_s_fbuf = ivtv_s_fbuf,
1859 .vidioc_g_std = ivtv_g_std,
1860 .vidioc_s_std = ivtv_s_std,
1861 .vidioc_overlay = ivtv_overlay,
1862 .vidioc_log_status = ivtv_log_status,
1863 .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
1864 .vidioc_encoder_cmd = ivtv_encoder_cmd,
1865 .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
Hans Verkuilda8ec562011-11-24 09:58:53 -03001866 .vidioc_decoder_cmd = ivtv_decoder_cmd,
1867 .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd,
Hans Verkuila3998102008-07-21 02:57:38 -03001868 .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
1869 .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
1870 .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
1871 .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,
1872 .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,
1873 .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,
1874 .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,
1875 .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,
1876 .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,
1877 .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,
1878 .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,
1879 .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,
1880 .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,
1881 .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,
1882 .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,
1883 .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,
1884 .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,
1885 .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,
1886 .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,
1887 .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,
1888 .vidioc_g_chip_ident = ivtv_g_chip_ident,
1889#ifdef CONFIG_VIDEO_ADV_DEBUG
1890 .vidioc_g_register = ivtv_g_register,
1891 .vidioc_s_register = ivtv_s_register,
1892#endif
1893 .vidioc_default = ivtv_default,
Hans Verkuil09250192010-03-27 14:10:13 -03001894 .vidioc_subscribe_event = ivtv_subscribe_event,
1895 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001896};
1897
Hans Verkuil3f038d82008-05-29 16:43:54 -03001898void ivtv_set_funcs(struct video_device *vdev)
1899{
Hans Verkuila3998102008-07-21 02:57:38 -03001900 vdev->ioctl_ops = &ivtv_ioctl_ops;
Hans Verkuil3f038d82008-05-29 16:43:54 -03001901}