V4L/DVB (12294): b2c2: Use dvb-pll for Cablestar2
[deliverable/linux.git] / drivers / media / video / cx2341x.c
CommitLineData
5d1a9ae6 1/*
0d82fe80 2 * cx2341x - generic code for cx23415/6/8 based devices
5d1a9ae6
HV
3 *
4 * Copyright (C) 2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21
22#include <linux/module.h>
5d1a9ae6
HV
23#include <linux/errno.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/videodev2.h>
5d1a9ae6
HV
28
29#include <media/tuner.h>
30#include <media/cx2341x.h>
31#include <media/v4l2-common.h>
32
0d82fe80 33MODULE_DESCRIPTION("cx23415/6/8 driver");
5d1a9ae6
HV
34MODULE_AUTHOR("Hans Verkuil");
35MODULE_LICENSE("GPL");
36
737bd410 37static int debug;
5d1a9ae6
HV
38module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "Debug level (0-1)");
40
2ba58894 41/* Must be sorted from low to high control ID! */
cc7bc648
HV
42const u32 cx2341x_mpeg_ctrls[] = {
43 V4L2_CID_MPEG_CLASS,
44 V4L2_CID_MPEG_STREAM_TYPE,
8cbde94b 45 V4L2_CID_MPEG_STREAM_VBI_FMT,
cc7bc648
HV
46 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
47 V4L2_CID_MPEG_AUDIO_ENCODING,
48 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
49 V4L2_CID_MPEG_AUDIO_MODE,
50 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
51 V4L2_CID_MPEG_AUDIO_EMPHASIS,
52 V4L2_CID_MPEG_AUDIO_CRC,
5eee72e8 53 V4L2_CID_MPEG_AUDIO_MUTE,
ee6f78cd 54 V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
cc7bc648
HV
55 V4L2_CID_MPEG_VIDEO_ENCODING,
56 V4L2_CID_MPEG_VIDEO_ASPECT,
57 V4L2_CID_MPEG_VIDEO_B_FRAMES,
58 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
59 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
cc7bc648
HV
60 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
61 V4L2_CID_MPEG_VIDEO_BITRATE,
62 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
63 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
5eee72e8
HV
64 V4L2_CID_MPEG_VIDEO_MUTE,
65 V4L2_CID_MPEG_VIDEO_MUTE_YUV,
cc7bc648
HV
66 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
67 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
68 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
69 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
70 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
71 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
72 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
73 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
74 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
75 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
76 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
5eee72e8 77 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
cc7bc648
HV
78 0
79};
737bd410 80EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
cc7bc648 81
ca130eef
HV
82static const struct cx2341x_mpeg_params default_params = {
83 /* misc */
84 .capabilities = 0,
85 .port = CX2341X_PORT_MEMORY,
86 .width = 720,
87 .height = 480,
88 .is_50hz = 0,
89
90 /* stream */
91 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
92 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
93 .stream_insert_nav_packets = 0,
94
95 /* audio */
96 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
97 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
98 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
0d82fe80 99 .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
ca130eef
HV
100 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
101 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
102 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
103 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
104 .audio_mute = 0,
105
106 /* video */
107 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
108 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
109 .video_b_frames = 2,
110 .video_gop_size = 12,
111 .video_gop_closure = 1,
112 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
113 .video_bitrate = 6000000,
114 .video_bitrate_peak = 8000000,
115 .video_temporal_decimation = 0,
116 .video_mute = 0,
117 .video_mute_yuv = 0x008080, /* YCbCr value for black */
118
119 /* encoding filters */
120 .video_spatial_filter_mode =
121 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
122 .video_spatial_filter = 0,
123 .video_luma_spatial_filter_type =
124 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
125 .video_chroma_spatial_filter_type =
126 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
127 .video_temporal_filter_mode =
128 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
129 .video_temporal_filter = 8,
130 .video_median_filter_type =
131 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
132 .video_luma_median_filter_top = 255,
133 .video_luma_median_filter_bottom = 0,
134 .video_chroma_median_filter_top = 255,
135 .video_chroma_median_filter_bottom = 0,
136};
137
5d1a9ae6
HV
138
139/* Map the control ID to the correct field in the cx2341x_mpeg_params
140 struct. Return -EINVAL if the ID is unknown, else return 0. */
e0e31cdb 141static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
5d1a9ae6
HV
142 struct v4l2_ext_control *ctrl)
143{
144 switch (ctrl->id) {
145 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
146 ctrl->value = params->audio_sampling_freq;
147 break;
148 case V4L2_CID_MPEG_AUDIO_ENCODING:
149 ctrl->value = params->audio_encoding;
150 break;
151 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
152 ctrl->value = params->audio_l2_bitrate;
153 break;
0d82fe80
AW
154 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
155 ctrl->value = params->audio_ac3_bitrate;
156 break;
5d1a9ae6
HV
157 case V4L2_CID_MPEG_AUDIO_MODE:
158 ctrl->value = params->audio_mode;
159 break;
160 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
161 ctrl->value = params->audio_mode_extension;
162 break;
163 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
164 ctrl->value = params->audio_emphasis;
165 break;
166 case V4L2_CID_MPEG_AUDIO_CRC:
167 ctrl->value = params->audio_crc;
168 break;
5eee72e8
HV
169 case V4L2_CID_MPEG_AUDIO_MUTE:
170 ctrl->value = params->audio_mute;
171 break;
5d1a9ae6
HV
172 case V4L2_CID_MPEG_VIDEO_ENCODING:
173 ctrl->value = params->video_encoding;
174 break;
175 case V4L2_CID_MPEG_VIDEO_ASPECT:
176 ctrl->value = params->video_aspect;
177 break;
178 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
179 ctrl->value = params->video_b_frames;
180 break;
181 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
182 ctrl->value = params->video_gop_size;
183 break;
184 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
185 ctrl->value = params->video_gop_closure;
186 break;
5d1a9ae6
HV
187 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
188 ctrl->value = params->video_bitrate_mode;
189 break;
190 case V4L2_CID_MPEG_VIDEO_BITRATE:
191 ctrl->value = params->video_bitrate;
192 break;
193 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
194 ctrl->value = params->video_bitrate_peak;
195 break;
196 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
197 ctrl->value = params->video_temporal_decimation;
198 break;
5eee72e8
HV
199 case V4L2_CID_MPEG_VIDEO_MUTE:
200 ctrl->value = params->video_mute;
201 break;
202 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
203 ctrl->value = params->video_mute_yuv;
204 break;
5d1a9ae6
HV
205 case V4L2_CID_MPEG_STREAM_TYPE:
206 ctrl->value = params->stream_type;
207 break;
8cbde94b
HV
208 case V4L2_CID_MPEG_STREAM_VBI_FMT:
209 ctrl->value = params->stream_vbi_fmt;
210 break;
5d1a9ae6
HV
211 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
212 ctrl->value = params->video_spatial_filter_mode;
213 break;
214 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
215 ctrl->value = params->video_spatial_filter;
216 break;
217 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
218 ctrl->value = params->video_luma_spatial_filter_type;
219 break;
220 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
221 ctrl->value = params->video_chroma_spatial_filter_type;
222 break;
223 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
224 ctrl->value = params->video_temporal_filter_mode;
225 break;
226 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
227 ctrl->value = params->video_temporal_filter;
228 break;
229 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
230 ctrl->value = params->video_median_filter_type;
231 break;
232 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
233 ctrl->value = params->video_luma_median_filter_top;
234 break;
235 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
236 ctrl->value = params->video_luma_median_filter_bottom;
237 break;
238 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
239 ctrl->value = params->video_chroma_median_filter_top;
240 break;
241 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
242 ctrl->value = params->video_chroma_median_filter_bottom;
243 break;
5eee72e8
HV
244 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
245 ctrl->value = params->stream_insert_nav_packets;
246 break;
5d1a9ae6
HV
247 default:
248 return -EINVAL;
249 }
250 return 0;
251}
252
253/* Map the control ID to the correct field in the cx2341x_mpeg_params
254 struct. Return -EINVAL if the ID is unknown, else return 0. */
01f1e44f 255static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
5d1a9ae6
HV
256 struct v4l2_ext_control *ctrl)
257{
258 switch (ctrl->id) {
259 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
01f1e44f
HV
260 if (busy)
261 return -EBUSY;
5d1a9ae6
HV
262 params->audio_sampling_freq = ctrl->value;
263 break;
264 case V4L2_CID_MPEG_AUDIO_ENCODING:
0d82fe80
AW
265 if (busy)
266 return -EBUSY;
31230c5f
AW
267 if (params->capabilities & CX2341X_CAP_HAS_AC3)
268 if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
269 ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
270 return -ERANGE;
5d1a9ae6
HV
271 params->audio_encoding = ctrl->value;
272 break;
273 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
01f1e44f
HV
274 if (busy)
275 return -EBUSY;
5d1a9ae6
HV
276 params->audio_l2_bitrate = ctrl->value;
277 break;
0d82fe80
AW
278 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
279 if (busy)
280 return -EBUSY;
31230c5f
AW
281 if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
282 return -EINVAL;
0d82fe80
AW
283 params->audio_ac3_bitrate = ctrl->value;
284 break;
5d1a9ae6
HV
285 case V4L2_CID_MPEG_AUDIO_MODE:
286 params->audio_mode = ctrl->value;
287 break;
288 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
289 params->audio_mode_extension = ctrl->value;
290 break;
291 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
292 params->audio_emphasis = ctrl->value;
293 break;
294 case V4L2_CID_MPEG_AUDIO_CRC:
295 params->audio_crc = ctrl->value;
296 break;
5eee72e8
HV
297 case V4L2_CID_MPEG_AUDIO_MUTE:
298 params->audio_mute = ctrl->value;
299 break;
5d1a9ae6
HV
300 case V4L2_CID_MPEG_VIDEO_ASPECT:
301 params->video_aspect = ctrl->value;
302 break;
303 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
304 int b = ctrl->value + 1;
305 int gop = params->video_gop_size;
306 params->video_b_frames = ctrl->value;
307 params->video_gop_size = b * ((gop + b - 1) / b);
308 /* Max GOP size = 34 */
309 while (params->video_gop_size > 34)
310 params->video_gop_size -= b;
311 break;
312 }
313 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
314 int b = params->video_b_frames + 1;
315 int gop = ctrl->value;
316 params->video_gop_size = b * ((gop + b - 1) / b);
317 /* Max GOP size = 34 */
318 while (params->video_gop_size > 34)
319 params->video_gop_size -= b;
320 ctrl->value = params->video_gop_size;
321 break;
322 }
323 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
324 params->video_gop_closure = ctrl->value;
325 break;
5d1a9ae6 326 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
01f1e44f
HV
327 if (busy)
328 return -EBUSY;
5d1a9ae6
HV
329 /* MPEG-1 only allows CBR */
330 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
331 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
332 return -EINVAL;
333 params->video_bitrate_mode = ctrl->value;
334 break;
335 case V4L2_CID_MPEG_VIDEO_BITRATE:
01f1e44f
HV
336 if (busy)
337 return -EBUSY;
5d1a9ae6
HV
338 params->video_bitrate = ctrl->value;
339 break;
340 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
01f1e44f
HV
341 if (busy)
342 return -EBUSY;
5d1a9ae6
HV
343 params->video_bitrate_peak = ctrl->value;
344 break;
345 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
346 params->video_temporal_decimation = ctrl->value;
347 break;
5eee72e8
HV
348 case V4L2_CID_MPEG_VIDEO_MUTE:
349 params->video_mute = (ctrl->value != 0);
350 break;
351 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
352 params->video_mute_yuv = ctrl->value;
353 break;
5d1a9ae6 354 case V4L2_CID_MPEG_STREAM_TYPE:
01f1e44f
HV
355 if (busy)
356 return -EBUSY;
5d1a9ae6
HV
357 params->stream_type = ctrl->value;
358 params->video_encoding =
737bd410
HV
359 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
360 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
361 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
362 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
363 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
5d1a9ae6 364 /* MPEG-1 implies CBR */
737bd410
HV
365 params->video_bitrate_mode =
366 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
5d1a9ae6 367 break;
8cbde94b
HV
368 case V4L2_CID_MPEG_STREAM_VBI_FMT:
369 params->stream_vbi_fmt = ctrl->value;
370 break;
5d1a9ae6
HV
371 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
372 params->video_spatial_filter_mode = ctrl->value;
373 break;
374 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
375 params->video_spatial_filter = ctrl->value;
376 break;
377 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
378 params->video_luma_spatial_filter_type = ctrl->value;
379 break;
380 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
381 params->video_chroma_spatial_filter_type = ctrl->value;
382 break;
383 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
384 params->video_temporal_filter_mode = ctrl->value;
385 break;
386 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
387 params->video_temporal_filter = ctrl->value;
388 break;
389 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
390 params->video_median_filter_type = ctrl->value;
391 break;
392 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
393 params->video_luma_median_filter_top = ctrl->value;
394 break;
395 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
396 params->video_luma_median_filter_bottom = ctrl->value;
397 break;
398 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
399 params->video_chroma_median_filter_top = ctrl->value;
400 break;
401 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
402 params->video_chroma_median_filter_bottom = ctrl->value;
403 break;
5eee72e8
HV
404 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
405 params->stream_insert_nav_packets = ctrl->value;
406 break;
5d1a9ae6
HV
407 default:
408 return -EINVAL;
409 }
410 return 0;
411}
412
737bd410
HV
413static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
414 s32 min, s32 max, s32 step, s32 def)
5d1a9ae6
HV
415{
416 const char *name;
417
418 qctrl->flags = 0;
419 switch (qctrl->id) {
420 /* MPEG controls */
421 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
422 name = "Spatial Filter Mode";
423 break;
424 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
425 name = "Spatial Filter";
426 break;
427 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
428 name = "Spatial Luma Filter Type";
429 break;
430 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
431 name = "Spatial Chroma Filter Type";
432 break;
433 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
434 name = "Temporal Filter Mode";
435 break;
436 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
437 name = "Temporal Filter";
438 break;
439 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
440 name = "Median Filter Type";
441 break;
442 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
443 name = "Median Luma Filter Maximum";
444 break;
445 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
446 name = "Median Luma Filter Minimum";
447 break;
448 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
449 name = "Median Chroma Filter Maximum";
450 break;
451 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
452 name = "Median Chroma Filter Minimum";
453 break;
5eee72e8
HV
454 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
455 name = "Insert Navigation Packets";
456 break;
5d1a9ae6
HV
457
458 default:
459 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
460 }
461 switch (qctrl->id) {
462 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
463 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
464 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
465 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
466 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
467 qctrl->type = V4L2_CTRL_TYPE_MENU;
468 min = 0;
469 step = 1;
470 break;
5eee72e8
HV
471 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
472 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
473 min = 0;
474 max = 1;
475 step = 1;
476 break;
5d1a9ae6
HV
477 default:
478 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
479 break;
480 }
481 switch (qctrl->id) {
482 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
483 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
484 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
485 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
486 break;
487 }
488 qctrl->minimum = min;
489 qctrl->maximum = max;
490 qctrl->step = step;
491 qctrl->default_value = def;
492 qctrl->reserved[0] = qctrl->reserved[1] = 0;
493 snprintf(qctrl->name, sizeof(qctrl->name), name);
494 return 0;
495}
496
e0e31cdb 497int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
737bd410 498 struct v4l2_queryctrl *qctrl)
5d1a9ae6
HV
499{
500 int err;
501
502 switch (qctrl->id) {
c6711c3e
HV
503 case V4L2_CID_MPEG_CLASS:
504 return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
10afbef1
HV
505 case V4L2_CID_MPEG_STREAM_TYPE:
506 return v4l2_ctrl_query_fill(qctrl,
507 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
508 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
509 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
510
511 case V4L2_CID_MPEG_STREAM_VBI_FMT:
512 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
513 return v4l2_ctrl_query_fill(qctrl,
514 V4L2_MPEG_STREAM_VBI_FMT_NONE,
515 V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
516 V4L2_MPEG_STREAM_VBI_FMT_NONE);
517 return cx2341x_ctrl_query_fill(qctrl,
518 V4L2_MPEG_STREAM_VBI_FMT_NONE,
519 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
520 default_params.stream_vbi_fmt);
521
522 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
523 return v4l2_ctrl_query_fill(qctrl,
524 V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
525 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
526 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
527
5d1a9ae6 528 case V4L2_CID_MPEG_AUDIO_ENCODING:
31230c5f
AW
529 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
530 /*
531 * The state of L2 & AC3 bitrate controls can change
532 * when this control changes, but v4l2_ctrl_query_fill()
533 * already sets V4L2_CTRL_FLAG_UPDATE for
534 * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
535 */
0d82fe80
AW
536 return v4l2_ctrl_query_fill(qctrl,
537 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
538 V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
539 default_params.audio_encoding);
31230c5f 540 }
0d82fe80 541
5d1a9ae6
HV
542 return v4l2_ctrl_query_fill(qctrl,
543 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
544 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
ca130eef 545 default_params.audio_encoding);
5d1a9ae6
HV
546
547 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
31230c5f 548 err = v4l2_ctrl_query_fill(qctrl,
5d1a9ae6
HV
549 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
550 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
ca130eef 551 default_params.audio_l2_bitrate);
31230c5f
AW
552 if (err)
553 return err;
554 if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
555 params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
556 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
557 return 0;
5d1a9ae6 558
10afbef1
HV
559 case V4L2_CID_MPEG_AUDIO_MODE:
560 return v4l2_ctrl_query_fill(qctrl,
561 V4L2_MPEG_AUDIO_MODE_STEREO,
562 V4L2_MPEG_AUDIO_MODE_MONO, 1,
563 V4L2_MPEG_AUDIO_MODE_STEREO);
564
565 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
566 err = v4l2_ctrl_query_fill(qctrl,
567 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
568 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
569 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
570 if (err == 0 &&
571 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
572 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
573 return err;
574
575 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
576 return v4l2_ctrl_query_fill(qctrl,
577 V4L2_MPEG_AUDIO_EMPHASIS_NONE,
578 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
579 V4L2_MPEG_AUDIO_EMPHASIS_NONE);
580
581 case V4L2_CID_MPEG_AUDIO_CRC:
582 return v4l2_ctrl_query_fill(qctrl,
583 V4L2_MPEG_AUDIO_CRC_NONE,
584 V4L2_MPEG_AUDIO_CRC_CRC16, 1,
585 V4L2_MPEG_AUDIO_CRC_NONE);
586
587 case V4L2_CID_MPEG_AUDIO_MUTE:
588 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
5d1a9ae6 589
0d82fe80 590 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
31230c5f 591 err = v4l2_ctrl_query_fill(qctrl,
0d82fe80
AW
592 V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
593 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
594 default_params.audio_ac3_bitrate);
31230c5f
AW
595 if (err)
596 return err;
597 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
598 if (params->audio_encoding !=
599 V4L2_MPEG_AUDIO_ENCODING_AC3)
600 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
601 } else
602 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
603 return 0;
0d82fe80 604
5d1a9ae6
HV
605 case V4L2_CID_MPEG_VIDEO_ENCODING:
606 /* this setting is read-only for the cx2341x since the
607 V4L2_CID_MPEG_STREAM_TYPE really determines the
608 MPEG-1/2 setting */
188919ac
JG
609 err = v4l2_ctrl_query_fill(qctrl,
610 V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
611 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
612 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
5d1a9ae6
HV
613 if (err == 0)
614 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
615 return err;
616
10afbef1
HV
617 case V4L2_CID_MPEG_VIDEO_ASPECT:
618 return v4l2_ctrl_query_fill(qctrl,
619 V4L2_MPEG_VIDEO_ASPECT_1x1,
620 V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
621 V4L2_MPEG_VIDEO_ASPECT_4x3);
622
623 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
624 return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
625
626 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
627 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
628 params->is_50hz ? 12 : 15);
629
630 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
631 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
632
54aa9a21 633 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
10afbef1
HV
634 err = v4l2_ctrl_query_fill(qctrl,
635 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
636 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
637 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
737bd410
HV
638 if (err == 0 &&
639 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
54aa9a21
HV
640 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
641 return err;
642
10afbef1
HV
643 case V4L2_CID_MPEG_VIDEO_BITRATE:
644 return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
645
5d1a9ae6 646 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
10afbef1 647 err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
737bd410
HV
648 if (err == 0 &&
649 params->video_bitrate_mode ==
650 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
5d1a9ae6
HV
651 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
652 return err;
653
10afbef1
HV
654 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
655 return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
ca130eef 656
10afbef1
HV
657 case V4L2_CID_MPEG_VIDEO_MUTE:
658 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
659
660 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */
661 return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
8cbde94b 662
5d1a9ae6
HV
663 /* CX23415/6 specific */
664 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
665 return cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
666 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
667 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
ca130eef 668 default_params.video_spatial_filter_mode);
5d1a9ae6
HV
669
670 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
ca130eef
HV
671 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
672 default_params.video_spatial_filter);
5d1a9ae6 673 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
674 if (params->video_spatial_filter_mode ==
675 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
676 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
677 return 0;
678
679 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
680 cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
681 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
682 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
683 1,
ca130eef 684 default_params.video_luma_spatial_filter_type);
737bd410
HV
685 if (params->video_spatial_filter_mode ==
686 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
687 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
688 return 0;
689
690 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
691 cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
692 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
693 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
694 1,
ca130eef 695 default_params.video_chroma_spatial_filter_type);
737bd410
HV
696 if (params->video_spatial_filter_mode ==
697 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
698 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
699 return 0;
700
701 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
702 return cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
703 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
704 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
ca130eef 705 default_params.video_temporal_filter_mode);
5d1a9ae6
HV
706
707 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
ca130eef
HV
708 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
709 default_params.video_temporal_filter);
5d1a9ae6 710 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
711 if (params->video_temporal_filter_mode ==
712 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
713 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
714 return 0;
715
716 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
717 return cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
718 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
719 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
ca130eef 720 default_params.video_median_filter_type);
5d1a9ae6
HV
721
722 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
ca130eef
HV
723 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
724 default_params.video_luma_median_filter_top);
5d1a9ae6 725 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
726 if (params->video_median_filter_type ==
727 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
728 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
729 return 0;
730
731 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
ca130eef
HV
732 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
733 default_params.video_luma_median_filter_bottom);
5d1a9ae6 734 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
735 if (params->video_median_filter_type ==
736 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
737 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
738 return 0;
739
740 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
ca130eef
HV
741 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
742 default_params.video_chroma_median_filter_top);
5d1a9ae6 743 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
744 if (params->video_median_filter_type ==
745 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
746 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
747 return 0;
748
749 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
ca130eef
HV
750 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
751 default_params.video_chroma_median_filter_bottom);
5d1a9ae6 752 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
753 if (params->video_median_filter_type ==
754 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
755 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
756 return 0;
757
5eee72e8 758 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
ca130eef
HV
759 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
760 default_params.stream_insert_nav_packets);
5eee72e8 761
5d1a9ae6 762 default:
10afbef1 763 return -EINVAL;
5d1a9ae6
HV
764
765 }
766}
737bd410 767EXPORT_SYMBOL(cx2341x_ctrl_query);
5d1a9ae6 768
e0e31cdb 769const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
5d1a9ae6 770{
e0e31cdb 771 static const char *mpeg_stream_type_without_ts[] = {
5d1a9ae6
HV
772 "MPEG-2 Program Stream",
773 "",
774 "MPEG-1 System Stream",
775 "MPEG-2 DVD-compatible Stream",
776 "MPEG-1 VCD-compatible Stream",
777 "MPEG-2 SVCD-compatible Stream",
778 NULL
779 };
780
e0e31cdb
HV
781 static const char *mpeg_stream_type_with_ts[] = {
782 "MPEG-2 Program Stream",
783 "MPEG-2 Transport Stream",
784 "MPEG-1 System Stream",
785 "MPEG-2 DVD-compatible Stream",
786 "MPEG-1 VCD-compatible Stream",
787 "MPEG-2 SVCD-compatible Stream",
788 NULL
789 };
790
0d82fe80
AW
791 static const char *mpeg_audio_encoding_l2_ac3[] = {
792 "",
793 "MPEG-1/2 Layer II",
794 "",
795 "",
796 "AC-3",
797 NULL
798 };
799
5d1a9ae6
HV
800 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
801 "Manual",
802 "Auto",
803 NULL
804 };
805
806 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
807 "Off",
808 "1D Horizontal",
809 "1D Vertical",
810 "2D H/V Separable",
811 "2D Symmetric non-separable",
812 NULL
813 };
814
815 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
816 "Off",
817 "1D Horizontal",
818 NULL
819 };
820
821 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
822 "Manual",
823 "Auto",
824 NULL
825 };
826
827 static const char *cx2341x_video_median_filter_type_menu[] = {
828 "Off",
829 "Horizontal",
830 "Vertical",
831 "Horizontal/Vertical",
832 "Diagonal",
833 NULL
834 };
835
836 switch (id) {
837 case V4L2_CID_MPEG_STREAM_TYPE:
e0e31cdb
HV
838 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
839 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
0d82fe80
AW
840 case V4L2_CID_MPEG_AUDIO_ENCODING:
841 return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
842 mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
5d1a9ae6
HV
843 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
844 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
845 return NULL;
846 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
847 return cx2341x_video_spatial_filter_mode_menu;
848 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
849 return cx2341x_video_luma_spatial_filter_type_menu;
850 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
851 return cx2341x_video_chroma_spatial_filter_type_menu;
852 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
853 return cx2341x_video_temporal_filter_mode_menu;
854 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
855 return cx2341x_video_median_filter_type_menu;
856 default:
857 return v4l2_ctrl_get_menu(id);
858 }
859}
737bd410 860EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
5d1a9ae6 861
0d82fe80 862/* definitions for audio properties bits 29-28 */
31230c5f
AW
863#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0
864#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1
865#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2
0d82fe80 866
5d1a9ae6
HV
867static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
868{
0d82fe80
AW
869 params->audio_properties =
870 (params->audio_sampling_freq << 0) |
5d1a9ae6
HV
871 (params->audio_mode << 8) |
872 (params->audio_mode_extension << 10) |
737bd410
HV
873 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
874 ? 3 : params->audio_emphasis) << 12) |
5d1a9ae6 875 (params->audio_crc << 14);
0d82fe80
AW
876
877 if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
878 params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
879 params->audio_properties |=
880 /* Not sure if this MPEG Layer II setting is required */
881 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
882 (params->audio_ac3_bitrate << 4) |
31230c5f 883 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
0d82fe80
AW
884 } else {
885 /* Assuming MPEG Layer II */
886 params->audio_properties |=
887 ((3 - params->audio_encoding) << 2) |
888 ((1 + params->audio_l2_bitrate) << 4);
889 }
5d1a9ae6
HV
890}
891
01f1e44f 892int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
4d6b5aee 893 struct v4l2_ext_controls *ctrls, unsigned int cmd)
5d1a9ae6
HV
894{
895 int err = 0;
896 int i;
897
898 if (cmd == VIDIOC_G_EXT_CTRLS) {
899 for (i = 0; i < ctrls->count; i++) {
900 struct v4l2_ext_control *ctrl = ctrls->controls + i;
901
902 err = cx2341x_get_ctrl(params, ctrl);
903 if (err) {
904 ctrls->error_idx = i;
905 break;
906 }
907 }
908 return err;
909 }
910 for (i = 0; i < ctrls->count; i++) {
911 struct v4l2_ext_control *ctrl = ctrls->controls + i;
912 struct v4l2_queryctrl qctrl;
913 const char **menu_items = NULL;
914
915 qctrl.id = ctrl->id;
916 err = cx2341x_ctrl_query(params, &qctrl);
917 if (err)
918 break;
919 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
e0e31cdb 920 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
5d1a9ae6
HV
921 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
922 if (err)
923 break;
01f1e44f 924 err = cx2341x_set_ctrl(params, busy, ctrl);
5d1a9ae6
HV
925 if (err)
926 break;
927 }
737bd410
HV
928 if (err == 0 &&
929 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
930 params->video_bitrate_peak < params->video_bitrate) {
5d1a9ae6
HV
931 err = -ERANGE;
932 ctrls->error_idx = ctrls->count;
933 }
737bd410 934 if (err)
5d1a9ae6 935 ctrls->error_idx = i;
737bd410 936 else
5d1a9ae6 937 cx2341x_calc_audio_properties(params);
5d1a9ae6
HV
938 return err;
939}
737bd410 940EXPORT_SYMBOL(cx2341x_ext_ctrls);
5d1a9ae6
HV
941
942void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
943{
5d1a9ae6
HV
944 *p = default_params;
945 cx2341x_calc_audio_properties(p);
946}
737bd410 947EXPORT_SYMBOL(cx2341x_fill_defaults);
5d1a9ae6 948
737bd410 949static int cx2341x_api(void *priv, cx2341x_mbox_func func,
ea48c13a 950 u32 cmd, int args, ...)
5d1a9ae6
HV
951{
952 u32 data[CX2341X_MBOX_MAX_DATA];
953 va_list vargs;
954 int i;
955
956 va_start(vargs, args);
957
737bd410 958 for (i = 0; i < args; i++)
5d1a9ae6 959 data[i] = va_arg(vargs, int);
5d1a9ae6
HV
960 va_end(vargs);
961 return func(priv, cmd, args, 0, data);
962}
963
737bd410
HV
964#define NEQ(field) (old->field != new->field)
965
5d1a9ae6 966int cx2341x_update(void *priv, cx2341x_mbox_func func,
737bd410
HV
967 const struct cx2341x_mpeg_params *old,
968 const struct cx2341x_mpeg_params *new)
5d1a9ae6
HV
969{
970 static int mpeg_stream_type[] = {
971 0, /* MPEG-2 PS */
972 1, /* MPEG-2 TS */
973 2, /* MPEG-1 SS */
974 14, /* DVD */
975 11, /* VCD */
976 12, /* SVCD */
977 };
978
979 int err = 0;
737bd410 980 int force = (old == NULL);
44b579d6 981 u16 temporal = new->video_temporal_filter;
5d1a9ae6 982
45ad9f8b 983 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
5d1a9ae6 984
737bd410
HV
985 if (force || NEQ(is_50hz)) {
986 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
987 new->is_50hz);
5d1a9ae6
HV
988 if (err) return err;
989 }
990
737bd410 991 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
5d1a9ae6
HV
992 u16 w = new->width;
993 u16 h = new->height;
994
995 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
996 w /= 2;
997 h /= 2;
998 }
737bd410
HV
999 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
1000 h, w);
5d1a9ae6 1001 if (err) return err;
12b896e4 1002 }
44b579d6 1003
12b896e4 1004 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
737bd410
HV
1005 /* Adjust temporal filter if necessary. The problem with the
1006 temporal filter is that it works well with full resolution
1007 capturing, but not when the capture window is scaled (the
1008 filter introduces a ghosting effect). So if the capture
1009 window is scaled, then force the filter to 0.
44b579d6 1010
12b896e4 1011 For full resolution the filter really improves the video
737bd410
HV
1012 quality, especially if the original video quality is
1013 suboptimal. */
12b896e4 1014 temporal = 0;
5d1a9ae6
HV
1015 }
1016
737bd410
HV
1017 if (force || NEQ(stream_type)) {
1018 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1019 mpeg_stream_type[new->stream_type]);
5d1a9ae6
HV
1020 if (err) return err;
1021 }
737bd410
HV
1022 if (force || NEQ(video_aspect)) {
1023 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1024 1 + new->video_aspect);
5d1a9ae6
HV
1025 if (err) return err;
1026 }
737bd410 1027 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
5d1a9ae6
HV
1028 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1029 new->video_gop_size, new->video_b_frames + 1);
1030 if (err) return err;
1031 }
737bd410
HV
1032 if (force || NEQ(video_gop_closure)) {
1033 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1034 new->video_gop_closure);
5d1a9ae6
HV
1035 if (err) return err;
1036 }
737bd410
HV
1037 if (force || NEQ(audio_properties)) {
1038 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1039 1, new->audio_properties);
5d1a9ae6
HV
1040 if (err) return err;
1041 }
737bd410
HV
1042 if (force || NEQ(audio_mute)) {
1043 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1044 new->audio_mute);
5eee72e8
HV
1045 if (err) return err;
1046 }
737bd410
HV
1047 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1048 NEQ(video_bitrate_peak)) {
5d1a9ae6
HV
1049 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1050 new->video_bitrate_mode, new->video_bitrate,
1051 new->video_bitrate_peak / 400, 0, 0);
1052 if (err) return err;
1053 }
737bd410
HV
1054 if (force || NEQ(video_spatial_filter_mode) ||
1055 NEQ(video_temporal_filter_mode) ||
1056 NEQ(video_median_filter_type)) {
1057 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1058 2, new->video_spatial_filter_mode |
1059 (new->video_temporal_filter_mode << 1),
5d1a9ae6
HV
1060 new->video_median_filter_type);
1061 if (err) return err;
1062 }
737bd410
HV
1063 if (force || NEQ(video_luma_median_filter_bottom) ||
1064 NEQ(video_luma_median_filter_top) ||
1065 NEQ(video_chroma_median_filter_bottom) ||
1066 NEQ(video_chroma_median_filter_top)) {
5d1a9ae6
HV
1067 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1068 new->video_luma_median_filter_bottom,
1069 new->video_luma_median_filter_top,
1070 new->video_chroma_median_filter_bottom,
1071 new->video_chroma_median_filter_top);
1072 if (err) return err;
1073 }
737bd410
HV
1074 if (force || NEQ(video_luma_spatial_filter_type) ||
1075 NEQ(video_chroma_spatial_filter_type)) {
1076 err = cx2341x_api(priv, func,
1077 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1078 2, new->video_luma_spatial_filter_type,
1079 new->video_chroma_spatial_filter_type);
5d1a9ae6
HV
1080 if (err) return err;
1081 }
737bd410
HV
1082 if (force || NEQ(video_spatial_filter) ||
1083 old->video_temporal_filter != temporal) {
1084 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1085 2, new->video_spatial_filter, temporal);
5d1a9ae6
HV
1086 if (err) return err;
1087 }
737bd410
HV
1088 if (force || NEQ(video_temporal_decimation)) {
1089 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1090 1, new->video_temporal_decimation);
5d1a9ae6
HV
1091 if (err) return err;
1092 }
737bd410
HV
1093 if (force || NEQ(video_mute) ||
1094 (new->video_mute && NEQ(video_mute_yuv))) {
1095 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1096 new->video_mute | (new->video_mute_yuv << 8));
5eee72e8
HV
1097 if (err) return err;
1098 }
737bd410
HV
1099 if (force || NEQ(stream_insert_nav_packets)) {
1100 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1101 7, new->stream_insert_nav_packets);
5eee72e8
HV
1102 if (err) return err;
1103 }
5d1a9ae6
HV
1104 return 0;
1105}
737bd410 1106EXPORT_SYMBOL(cx2341x_update);
5d1a9ae6 1107
e0e31cdb 1108static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
5d1a9ae6 1109{
e0e31cdb 1110 const char **menu = cx2341x_ctrl_get_menu(p, id);
5d1a9ae6
HV
1111 struct v4l2_ext_control ctrl;
1112
1113 if (menu == NULL)
1114 goto invalid;
1115 ctrl.id = id;
1116 if (cx2341x_get_ctrl(p, &ctrl))
1117 goto invalid;
1118 while (ctrl.value-- && *menu) menu++;
1119 if (*menu == NULL)
1120 goto invalid;
1121 return *menu;
1122
1123invalid:
1124 return "<invalid>";
1125}
1126
e0e31cdb 1127void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
5d1a9ae6
HV
1128{
1129 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
83aaf13c 1130 int temporal = p->video_temporal_filter;
5d1a9ae6
HV
1131
1132 /* Stream */
5eee72e8 1133 printk(KERN_INFO "%s: Stream: %s",
99eb44fe 1134 prefix,
5d1a9ae6 1135 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
5eee72e8
HV
1136 if (p->stream_insert_nav_packets)
1137 printk(" (with navigation packets)");
1138 printk("\n");
44b579d6
HV
1139 printk(KERN_INFO "%s: VBI Format: %s\n",
1140 prefix,
1141 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
5d1a9ae6
HV
1142
1143 /* Video */
5eee72e8 1144 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
99eb44fe 1145 prefix,
5d1a9ae6 1146 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
5eee72e8
HV
1147 p->is_50hz ? 25 : 30,
1148 (p->video_mute) ? " (muted)" : "");
99eb44fe
HV
1149 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
1150 prefix,
5d1a9ae6
HV
1151 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1152 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1153 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1154 p->video_bitrate);
737bd410 1155 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
5d1a9ae6 1156 printk(", Peak %d", p->video_bitrate_peak);
5d1a9ae6 1157 printk("\n");
737bd410
HV
1158 printk(KERN_INFO
1159 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
99eb44fe 1160 prefix,
5d1a9ae6 1161 p->video_gop_size, p->video_b_frames,
75558ab9 1162 p->video_gop_closure ? "" : "No ");
737bd410 1163 if (p->video_temporal_decimation)
99eb44fe
HV
1164 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1165 prefix, p->video_temporal_decimation);
5d1a9ae6
HV
1166
1167 /* Audio */
5eee72e8 1168 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
99eb44fe 1169 prefix,
5d1a9ae6
HV
1170 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1171 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
0d82fe80
AW
1172 cx2341x_menu_item(p,
1173 p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1174 ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1175 : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
5eee72e8
HV
1176 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1177 p->audio_mute ? " (muted)" : "");
737bd410
HV
1178 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1179 printk(", %s", cx2341x_menu_item(p,
1180 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
5d1a9ae6
HV
1181 printk(", %s, %s\n",
1182 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1183 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1184
1185 /* Encoding filters */
99eb44fe
HV
1186 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1187 prefix,
737bd410
HV
1188 cx2341x_menu_item(p,
1189 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1190 cx2341x_menu_item(p,
1191 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1192 cx2341x_menu_item(p,
1193 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
5d1a9ae6 1194 p->video_spatial_filter);
737bd410
HV
1195
1196 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
83aaf13c 1197 temporal = 0;
737bd410 1198
99eb44fe
HV
1199 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1200 prefix,
737bd410
HV
1201 cx2341x_menu_item(p,
1202 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
83aaf13c 1203 temporal);
737bd410
HV
1204 printk(KERN_INFO
1205 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
99eb44fe 1206 prefix,
737bd410
HV
1207 cx2341x_menu_item(p,
1208 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
5d1a9ae6
HV
1209 p->video_luma_median_filter_bottom,
1210 p->video_luma_median_filter_top,
1211 p->video_chroma_median_filter_bottom,
1212 p->video_chroma_median_filter_top);
1213}
5d1a9ae6
HV
1214EXPORT_SYMBOL(cx2341x_log_status);
1215
1216/*
1217 * Local variables:
1218 * c-basic-offset: 8
1219 * End:
1220 */
1221
This page took 0.705825 seconds and 5 git commands to generate.