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
21 #include "ivtv-driver.h"
22 #include "ivtv-cards.h"
23 #include "ivtv-ioctl.h"
24 #include "ivtv-audio.h"
26 #include "ivtv-mailbox.h"
27 #include "ivtv-controls.h"
29 static const u32 user_ctrls
[] = {
35 V4L2_CID_AUDIO_VOLUME
,
36 V4L2_CID_AUDIO_BALANCE
,
38 V4L2_CID_AUDIO_TREBLE
,
40 V4L2_CID_AUDIO_LOUDNESS
,
44 static const u32
*ctrl_classes
[] = {
50 static int ivtv_queryctrl(struct ivtv
*itv
, struct v4l2_queryctrl
*qctrl
)
54 IVTV_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl
->id
);
56 qctrl
->id
= v4l2_ctrl_next(ctrl_classes
, qctrl
->id
);
61 /* Standard V4L2 controls */
62 case V4L2_CID_BRIGHTNESS
:
64 case V4L2_CID_SATURATION
:
65 case V4L2_CID_CONTRAST
:
66 if (itv
->video_dec_func(itv
, VIDIOC_QUERYCTRL
, qctrl
))
67 qctrl
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
70 case V4L2_CID_AUDIO_VOLUME
:
71 case V4L2_CID_AUDIO_MUTE
:
72 case V4L2_CID_AUDIO_BALANCE
:
73 case V4L2_CID_AUDIO_BASS
:
74 case V4L2_CID_AUDIO_TREBLE
:
75 case V4L2_CID_AUDIO_LOUDNESS
:
76 if (ivtv_i2c_hw(itv
, itv
->card
->hw_audio_ctrl
, VIDIOC_QUERYCTRL
, qctrl
))
77 qctrl
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
81 if (cx2341x_ctrl_query(&itv
->params
, qctrl
))
82 qctrl
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
85 strncpy(qctrl
->name
, name
, sizeof(qctrl
->name
) - 1);
86 qctrl
->name
[sizeof(qctrl
->name
) - 1] = 0;
90 static int ivtv_querymenu(struct ivtv
*itv
, struct v4l2_querymenu
*qmenu
)
92 struct v4l2_queryctrl qctrl
;
95 ivtv_queryctrl(itv
, &qctrl
);
96 return v4l2_ctrl_query_menu(qmenu
, &qctrl
, cx2341x_ctrl_get_menu(qmenu
->id
));
99 static int ivtv_s_ctrl(struct ivtv
*itv
, struct v4l2_control
*vctrl
)
101 s32 v
= vctrl
->value
;
103 IVTV_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl
->id
, v
);
106 /* Standard V4L2 controls */
107 case V4L2_CID_BRIGHTNESS
:
109 case V4L2_CID_SATURATION
:
110 case V4L2_CID_CONTRAST
:
111 return itv
->video_dec_func(itv
, VIDIOC_S_CTRL
, vctrl
);
113 case V4L2_CID_AUDIO_VOLUME
:
114 case V4L2_CID_AUDIO_MUTE
:
115 case V4L2_CID_AUDIO_BALANCE
:
116 case V4L2_CID_AUDIO_BASS
:
117 case V4L2_CID_AUDIO_TREBLE
:
118 case V4L2_CID_AUDIO_LOUDNESS
:
119 return ivtv_i2c_hw(itv
, itv
->card
->hw_audio_ctrl
, VIDIOC_S_CTRL
, vctrl
);
122 IVTV_DEBUG_IOCTL("invalid control %x\n", vctrl
->id
);
128 static int ivtv_g_ctrl(struct ivtv
*itv
, struct v4l2_control
*vctrl
)
130 IVTV_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl
->id
);
133 /* Standard V4L2 controls */
134 case V4L2_CID_BRIGHTNESS
:
136 case V4L2_CID_SATURATION
:
137 case V4L2_CID_CONTRAST
:
138 return itv
->video_dec_func(itv
, VIDIOC_G_CTRL
, vctrl
);
140 case V4L2_CID_AUDIO_VOLUME
:
141 case V4L2_CID_AUDIO_MUTE
:
142 case V4L2_CID_AUDIO_BALANCE
:
143 case V4L2_CID_AUDIO_BASS
:
144 case V4L2_CID_AUDIO_TREBLE
:
145 case V4L2_CID_AUDIO_LOUDNESS
:
146 return ivtv_i2c_hw(itv
, itv
->card
->hw_audio_ctrl
, VIDIOC_G_CTRL
, vctrl
);
148 IVTV_DEBUG_IOCTL("invalid control %x\n", vctrl
->id
);
154 static int ivtv_setup_vbi_fmt(struct ivtv
*itv
, enum v4l2_mpeg_stream_vbi_fmt fmt
)
156 if (!(itv
->v4l2_cap
& V4L2_CAP_SLICED_VBI_CAPTURE
))
158 if (atomic_read(&itv
->capturing
) > 0)
161 /* First try to allocate sliced VBI buffers if needed. */
162 if (fmt
&& itv
->vbi
.sliced_mpeg_data
[0] == NULL
) {
165 for (i
= 0; i
< IVTV_VBI_FRAMES
; i
++) {
166 /* Yuck, hardcoded. Needs to be a define */
167 itv
->vbi
.sliced_mpeg_data
[i
] = kmalloc(2049, GFP_KERNEL
);
168 if (itv
->vbi
.sliced_mpeg_data
[i
] == NULL
) {
170 kfree(itv
->vbi
.sliced_mpeg_data
[i
]);
171 itv
->vbi
.sliced_mpeg_data
[i
] = NULL
;
178 itv
->vbi
.insert_mpeg
= fmt
;
180 if (itv
->vbi
.insert_mpeg
== 0) {
183 /* Need sliced data for mpeg insertion */
184 if (get_service_set(itv
->vbi
.sliced_in
) == 0) {
186 itv
->vbi
.sliced_in
->service_set
= V4L2_SLICED_CAPTION_525
;
188 itv
->vbi
.sliced_in
->service_set
= V4L2_SLICED_WSS_625
;
189 expand_service_set(itv
->vbi
.sliced_in
, itv
->is_50hz
);
194 int ivtv_control_ioctls(struct ivtv
*itv
, unsigned int cmd
, void *arg
)
196 struct v4l2_control ctrl
;
199 case VIDIOC_QUERYMENU
:
200 IVTV_DEBUG_IOCTL("VIDIOC_QUERYMENU\n");
201 return ivtv_querymenu(itv
, arg
);
203 case VIDIOC_QUERYCTRL
:
204 return ivtv_queryctrl(itv
, arg
);
207 return ivtv_s_ctrl(itv
, arg
);
210 return ivtv_g_ctrl(itv
, arg
);
212 case VIDIOC_S_EXT_CTRLS
:
214 struct v4l2_ext_controls
*c
= arg
;
216 if (c
->ctrl_class
== V4L2_CTRL_CLASS_USER
) {
220 for (i
= 0; i
< c
->count
; i
++) {
221 ctrl
.id
= c
->controls
[i
].id
;
222 ctrl
.value
= c
->controls
[i
].value
;
223 err
= ivtv_s_ctrl(itv
, &ctrl
);
224 c
->controls
[i
].value
= ctrl
.value
;
232 IVTV_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
233 if (c
->ctrl_class
== V4L2_CTRL_CLASS_MPEG
) {
234 struct cx2341x_mpeg_params p
= itv
->params
;
235 int err
= cx2341x_ext_ctrls(&p
, arg
, cmd
);
240 if (p
.video_encoding
!= itv
->params
.video_encoding
) {
241 int is_mpeg1
= p
.video_encoding
==
242 V4L2_MPEG_VIDEO_ENCODING_MPEG_1
;
243 struct v4l2_format fmt
;
245 /* fix videodecoder resolution */
246 fmt
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
247 fmt
.fmt
.pix
.width
= itv
->params
.width
/ (is_mpeg1
? 2 : 1);
248 fmt
.fmt
.pix
.height
= itv
->params
.height
;
249 itv
->video_dec_func(itv
, VIDIOC_S_FMT
, &fmt
);
251 err
= cx2341x_update(itv
, ivtv_api_func
, &itv
->params
, &p
);
252 if (!err
&& itv
->params
.stream_vbi_fmt
!= p
.stream_vbi_fmt
) {
253 err
= ivtv_setup_vbi_fmt(itv
, p
.stream_vbi_fmt
);
256 itv
->dualwatch_stereo_mode
= p
.audio_properties
& 0x0300;
257 ivtv_audio_set_audio_clock_freq(itv
, p
.audio_properties
& 0x03);
263 case VIDIOC_G_EXT_CTRLS
:
265 struct v4l2_ext_controls
*c
= arg
;
267 if (c
->ctrl_class
== V4L2_CTRL_CLASS_USER
) {
271 for (i
= 0; i
< c
->count
; i
++) {
272 ctrl
.id
= c
->controls
[i
].id
;
273 ctrl
.value
= c
->controls
[i
].value
;
274 err
= ivtv_g_ctrl(itv
, &ctrl
);
275 c
->controls
[i
].value
= ctrl
.value
;
283 IVTV_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n");
284 if (c
->ctrl_class
== V4L2_CTRL_CLASS_MPEG
)
285 return cx2341x_ext_ctrls(&itv
->params
, arg
, cmd
);
289 case VIDIOC_TRY_EXT_CTRLS
:
291 struct v4l2_ext_controls
*c
= arg
;
293 IVTV_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
294 if (c
->ctrl_class
== V4L2_CTRL_CLASS_MPEG
)
295 return cx2341x_ext_ctrls(&itv
->params
, arg
, cmd
);