2 ioctl control functions
3 Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com>
4 Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl>
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.
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.
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
20 #include <linux/kernel.h>
22 #include "ivtv-driver.h"
23 #include "ivtv-cards.h"
24 #include "ivtv-ioctl.h"
25 #include "ivtv-routing.h"
27 #include "ivtv-mailbox.h"
28 #include "ivtv-controls.h"
30 /* Must be sorted from low to high control ID! */
31 static const u32 user_ctrls
[] = {
37 V4L2_CID_AUDIO_VOLUME
,
38 V4L2_CID_AUDIO_BALANCE
,
40 V4L2_CID_AUDIO_TREBLE
,
42 V4L2_CID_AUDIO_LOUDNESS
,
46 static const u32
*ctrl_classes
[] = {
53 int ivtv_queryctrl(struct file
*file
, void *fh
, struct v4l2_queryctrl
*qctrl
)
55 struct ivtv
*itv
= ((struct ivtv_open_id
*)fh
)->itv
;
58 qctrl
->id
= v4l2_ctrl_next(ctrl_classes
, qctrl
->id
);
63 /* Standard V4L2 controls */
64 case V4L2_CID_USER_CLASS
:
65 return v4l2_ctrl_query_fill(qctrl
, 0, 0, 0, 0);
66 case V4L2_CID_BRIGHTNESS
:
68 case V4L2_CID_SATURATION
:
69 case V4L2_CID_CONTRAST
:
70 if (v4l2_subdev_call(itv
->sd_video
, core
, queryctrl
, qctrl
))
71 qctrl
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
74 case V4L2_CID_AUDIO_VOLUME
:
75 case V4L2_CID_AUDIO_MUTE
:
76 case V4L2_CID_AUDIO_BALANCE
:
77 case V4L2_CID_AUDIO_BASS
:
78 case V4L2_CID_AUDIO_TREBLE
:
79 case V4L2_CID_AUDIO_LOUDNESS
:
80 if (v4l2_subdev_call(itv
->sd_audio
, core
, queryctrl
, qctrl
))
81 qctrl
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
85 if (cx2341x_ctrl_query(&itv
->params
, qctrl
))
86 qctrl
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
89 strncpy(qctrl
->name
, name
, sizeof(qctrl
->name
) - 1);
90 qctrl
->name
[sizeof(qctrl
->name
) - 1] = 0;
94 int ivtv_querymenu(struct file
*file
, void *fh
, struct v4l2_querymenu
*qmenu
)
96 struct ivtv
*itv
= ((struct ivtv_open_id
*)fh
)->itv
;
97 struct v4l2_queryctrl qctrl
;
100 ivtv_queryctrl(file
, fh
, &qctrl
);
101 return v4l2_ctrl_query_menu(qmenu
, &qctrl
,
102 cx2341x_ctrl_get_menu(&itv
->params
, qmenu
->id
));
105 static int ivtv_try_ctrl(struct file
*file
, void *fh
,
106 struct v4l2_ext_control
*vctrl
)
108 struct v4l2_queryctrl qctrl
;
109 const char **menu_items
= NULL
;
112 qctrl
.id
= vctrl
->id
;
113 err
= ivtv_queryctrl(file
, fh
, &qctrl
);
116 if (qctrl
.type
== V4L2_CTRL_TYPE_MENU
)
117 menu_items
= v4l2_ctrl_get_menu(qctrl
.id
);
118 return v4l2_ctrl_check(vctrl
, &qctrl
, menu_items
);
121 static int ivtv_s_ctrl(struct ivtv
*itv
, struct v4l2_control
*vctrl
)
124 /* Standard V4L2 controls */
125 case V4L2_CID_BRIGHTNESS
:
127 case V4L2_CID_SATURATION
:
128 case V4L2_CID_CONTRAST
:
129 return v4l2_subdev_call(itv
->sd_video
, core
, s_ctrl
, vctrl
);
131 case V4L2_CID_AUDIO_VOLUME
:
132 case V4L2_CID_AUDIO_MUTE
:
133 case V4L2_CID_AUDIO_BALANCE
:
134 case V4L2_CID_AUDIO_BASS
:
135 case V4L2_CID_AUDIO_TREBLE
:
136 case V4L2_CID_AUDIO_LOUDNESS
:
137 return v4l2_subdev_call(itv
->sd_audio
, core
, s_ctrl
, vctrl
);
140 IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl
->id
);
146 static int ivtv_g_ctrl(struct ivtv
*itv
, struct v4l2_control
*vctrl
)
149 /* Standard V4L2 controls */
150 case V4L2_CID_BRIGHTNESS
:
152 case V4L2_CID_SATURATION
:
153 case V4L2_CID_CONTRAST
:
154 return v4l2_subdev_call(itv
->sd_video
, core
, g_ctrl
, vctrl
);
156 case V4L2_CID_AUDIO_VOLUME
:
157 case V4L2_CID_AUDIO_MUTE
:
158 case V4L2_CID_AUDIO_BALANCE
:
159 case V4L2_CID_AUDIO_BASS
:
160 case V4L2_CID_AUDIO_TREBLE
:
161 case V4L2_CID_AUDIO_LOUDNESS
:
162 return v4l2_subdev_call(itv
->sd_audio
, core
, g_ctrl
, vctrl
);
164 IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl
->id
);
170 static int ivtv_setup_vbi_fmt(struct ivtv
*itv
, enum v4l2_mpeg_stream_vbi_fmt fmt
)
172 if (!(itv
->v4l2_cap
& V4L2_CAP_SLICED_VBI_CAPTURE
))
174 if (atomic_read(&itv
->capturing
) > 0)
177 /* First try to allocate sliced VBI buffers if needed. */
178 if (fmt
&& itv
->vbi
.sliced_mpeg_data
[0] == NULL
) {
181 for (i
= 0; i
< IVTV_VBI_FRAMES
; i
++) {
182 /* Yuck, hardcoded. Needs to be a define */
183 itv
->vbi
.sliced_mpeg_data
[i
] = kmalloc(2049, GFP_KERNEL
);
184 if (itv
->vbi
.sliced_mpeg_data
[i
] == NULL
) {
186 kfree(itv
->vbi
.sliced_mpeg_data
[i
]);
187 itv
->vbi
.sliced_mpeg_data
[i
] = NULL
;
194 itv
->vbi
.insert_mpeg
= fmt
;
196 if (itv
->vbi
.insert_mpeg
== 0) {
199 /* Need sliced data for mpeg insertion */
200 if (ivtv_get_service_set(itv
->vbi
.sliced_in
) == 0) {
202 itv
->vbi
.sliced_in
->service_set
= V4L2_SLICED_CAPTION_525
;
204 itv
->vbi
.sliced_in
->service_set
= V4L2_SLICED_WSS_625
;
205 ivtv_expand_service_set(itv
->vbi
.sliced_in
, itv
->is_50hz
);
210 int ivtv_g_ext_ctrls(struct file
*file
, void *fh
, struct v4l2_ext_controls
*c
)
212 struct ivtv
*itv
= ((struct ivtv_open_id
*)fh
)->itv
;
213 struct v4l2_control ctrl
;
215 if (c
->ctrl_class
== V4L2_CTRL_CLASS_USER
) {
219 for (i
= 0; i
< c
->count
; i
++) {
220 ctrl
.id
= c
->controls
[i
].id
;
221 ctrl
.value
= c
->controls
[i
].value
;
222 err
= ivtv_g_ctrl(itv
, &ctrl
);
223 c
->controls
[i
].value
= ctrl
.value
;
231 if (c
->ctrl_class
== V4L2_CTRL_CLASS_MPEG
)
232 return cx2341x_ext_ctrls(&itv
->params
, 0, c
, VIDIOC_G_EXT_CTRLS
);
236 int ivtv_s_ext_ctrls(struct file
*file
, void *fh
, struct v4l2_ext_controls
*c
)
238 struct ivtv
*itv
= ((struct ivtv_open_id
*)fh
)->itv
;
239 struct v4l2_control ctrl
;
241 if (c
->ctrl_class
== V4L2_CTRL_CLASS_USER
) {
245 for (i
= 0; i
< c
->count
; i
++) {
246 ctrl
.id
= c
->controls
[i
].id
;
247 ctrl
.value
= c
->controls
[i
].value
;
248 err
= ivtv_s_ctrl(itv
, &ctrl
);
249 c
->controls
[i
].value
= ctrl
.value
;
257 if (c
->ctrl_class
== V4L2_CTRL_CLASS_MPEG
) {
258 static u32 freqs
[3] = { 44100, 48000, 32000 };
259 struct cx2341x_mpeg_params p
= itv
->params
;
260 int err
= cx2341x_ext_ctrls(&p
, atomic_read(&itv
->capturing
), c
, VIDIOC_S_EXT_CTRLS
);
266 if (p
.video_encoding
!= itv
->params
.video_encoding
) {
267 int is_mpeg1
= p
.video_encoding
==
268 V4L2_MPEG_VIDEO_ENCODING_MPEG_1
;
269 struct v4l2_format fmt
;
271 /* fix videodecoder resolution */
272 fmt
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
273 fmt
.fmt
.pix
.width
= itv
->params
.width
/ (is_mpeg1
? 2 : 1);
274 fmt
.fmt
.pix
.height
= itv
->params
.height
;
275 v4l2_subdev_call(itv
->sd_video
, video
, s_fmt
, &fmt
);
277 err
= cx2341x_update(itv
, ivtv_api_func
, &itv
->params
, &p
);
278 if (!err
&& itv
->params
.stream_vbi_fmt
!= p
.stream_vbi_fmt
)
279 err
= ivtv_setup_vbi_fmt(itv
, p
.stream_vbi_fmt
);
281 itv
->dualwatch_stereo_mode
= p
.audio_properties
& 0x0300;
282 idx
= p
.audio_properties
& 0x03;
283 /* The audio clock of the digitizer must match the codec sample
284 rate otherwise you get some very strange effects. */
285 if (idx
< ARRAY_SIZE(freqs
))
286 ivtv_call_all(itv
, audio
, s_clock_freq
, freqs
[idx
]);
292 int ivtv_try_ext_ctrls(struct file
*file
, void *fh
, struct v4l2_ext_controls
*c
)
294 struct ivtv
*itv
= ((struct ivtv_open_id
*)fh
)->itv
;
296 if (c
->ctrl_class
== V4L2_CTRL_CLASS_USER
) {
300 for (i
= 0; i
< c
->count
; i
++) {
301 err
= ivtv_try_ctrl(file
, fh
, &c
->controls
[i
]);
309 if (c
->ctrl_class
== V4L2_CTRL_CLASS_MPEG
)
310 return cx2341x_ext_ctrls(&itv
->params
, atomic_read(&itv
->capturing
), c
, VIDIOC_TRY_EXT_CTRLS
);