[MIPS] Save 2k text size in cpu-probe
[linux-2.6/x86.git] / drivers / media / video / cx2341x.c
blob65f00fc08fa961d5671ccfe5a3cf92aa38efb4ab
1 /*
2 * cx2341x - generic code for cx23415/6 based devices
4 * Copyright (C) 2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/errno.h>
25 #include <linux/kernel.h>
26 #include <linux/init.h>
27 #include <linux/types.h>
28 #include <linux/videodev2.h>
29 #include <linux/i2c.h>
31 #include <media/tuner.h>
32 #include <media/cx2341x.h>
33 #include <media/v4l2-common.h>
35 MODULE_DESCRIPTION("cx23415/6 driver");
36 MODULE_AUTHOR("Hans Verkuil");
37 MODULE_LICENSE("GPL");
39 static int debug = 0;
40 module_param(debug, int, 0644);
41 MODULE_PARM_DESC(debug, "Debug level (0-1)");
43 const u32 cx2341x_mpeg_ctrls[] = {
44 V4L2_CID_MPEG_CLASS,
45 V4L2_CID_MPEG_STREAM_TYPE,
46 V4L2_CID_MPEG_STREAM_VBI_FMT,
47 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
48 V4L2_CID_MPEG_AUDIO_ENCODING,
49 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
50 V4L2_CID_MPEG_AUDIO_MODE,
51 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
52 V4L2_CID_MPEG_AUDIO_EMPHASIS,
53 V4L2_CID_MPEG_AUDIO_CRC,
54 V4L2_CID_MPEG_VIDEO_ENCODING,
55 V4L2_CID_MPEG_VIDEO_ASPECT,
56 V4L2_CID_MPEG_VIDEO_B_FRAMES,
57 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
58 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
59 V4L2_CID_MPEG_VIDEO_PULLDOWN,
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,
64 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
65 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
66 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
67 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
68 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
69 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
70 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
71 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
72 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
73 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
74 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
79 /* Map the control ID to the correct field in the cx2341x_mpeg_params
80 struct. Return -EINVAL if the ID is unknown, else return 0. */
81 static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
82 struct v4l2_ext_control *ctrl)
84 switch (ctrl->id) {
85 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
86 ctrl->value = params->audio_sampling_freq;
87 break;
88 case V4L2_CID_MPEG_AUDIO_ENCODING:
89 ctrl->value = params->audio_encoding;
90 break;
91 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
92 ctrl->value = params->audio_l2_bitrate;
93 break;
94 case V4L2_CID_MPEG_AUDIO_MODE:
95 ctrl->value = params->audio_mode;
96 break;
97 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
98 ctrl->value = params->audio_mode_extension;
99 break;
100 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
101 ctrl->value = params->audio_emphasis;
102 break;
103 case V4L2_CID_MPEG_AUDIO_CRC:
104 ctrl->value = params->audio_crc;
105 break;
106 case V4L2_CID_MPEG_VIDEO_ENCODING:
107 ctrl->value = params->video_encoding;
108 break;
109 case V4L2_CID_MPEG_VIDEO_ASPECT:
110 ctrl->value = params->video_aspect;
111 break;
112 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
113 ctrl->value = params->video_b_frames;
114 break;
115 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
116 ctrl->value = params->video_gop_size;
117 break;
118 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
119 ctrl->value = params->video_gop_closure;
120 break;
121 case V4L2_CID_MPEG_VIDEO_PULLDOWN:
122 ctrl->value = params->video_pulldown;
123 break;
124 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
125 ctrl->value = params->video_bitrate_mode;
126 break;
127 case V4L2_CID_MPEG_VIDEO_BITRATE:
128 ctrl->value = params->video_bitrate;
129 break;
130 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
131 ctrl->value = params->video_bitrate_peak;
132 break;
133 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
134 ctrl->value = params->video_temporal_decimation;
135 break;
136 case V4L2_CID_MPEG_STREAM_TYPE:
137 ctrl->value = params->stream_type;
138 break;
139 case V4L2_CID_MPEG_STREAM_VBI_FMT:
140 ctrl->value = params->stream_vbi_fmt;
141 break;
142 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
143 ctrl->value = params->video_spatial_filter_mode;
144 break;
145 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
146 ctrl->value = params->video_spatial_filter;
147 break;
148 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
149 ctrl->value = params->video_luma_spatial_filter_type;
150 break;
151 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
152 ctrl->value = params->video_chroma_spatial_filter_type;
153 break;
154 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
155 ctrl->value = params->video_temporal_filter_mode;
156 break;
157 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
158 ctrl->value = params->video_temporal_filter;
159 break;
160 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
161 ctrl->value = params->video_median_filter_type;
162 break;
163 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
164 ctrl->value = params->video_luma_median_filter_top;
165 break;
166 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
167 ctrl->value = params->video_luma_median_filter_bottom;
168 break;
169 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
170 ctrl->value = params->video_chroma_median_filter_top;
171 break;
172 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
173 ctrl->value = params->video_chroma_median_filter_bottom;
174 break;
175 default:
176 return -EINVAL;
178 return 0;
181 /* Map the control ID to the correct field in the cx2341x_mpeg_params
182 struct. Return -EINVAL if the ID is unknown, else return 0. */
183 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
184 struct v4l2_ext_control *ctrl)
186 switch (ctrl->id) {
187 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
188 params->audio_sampling_freq = ctrl->value;
189 break;
190 case V4L2_CID_MPEG_AUDIO_ENCODING:
191 params->audio_encoding = ctrl->value;
192 break;
193 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
194 params->audio_l2_bitrate = ctrl->value;
195 break;
196 case V4L2_CID_MPEG_AUDIO_MODE:
197 params->audio_mode = ctrl->value;
198 break;
199 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
200 params->audio_mode_extension = ctrl->value;
201 break;
202 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
203 params->audio_emphasis = ctrl->value;
204 break;
205 case V4L2_CID_MPEG_AUDIO_CRC:
206 params->audio_crc = ctrl->value;
207 break;
208 case V4L2_CID_MPEG_VIDEO_ASPECT:
209 params->video_aspect = ctrl->value;
210 break;
211 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
212 int b = ctrl->value + 1;
213 int gop = params->video_gop_size;
214 params->video_b_frames = ctrl->value;
215 params->video_gop_size = b * ((gop + b - 1) / b);
216 /* Max GOP size = 34 */
217 while (params->video_gop_size > 34)
218 params->video_gop_size -= b;
219 break;
221 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
222 int b = params->video_b_frames + 1;
223 int gop = ctrl->value;
224 params->video_gop_size = b * ((gop + b - 1) / b);
225 /* Max GOP size = 34 */
226 while (params->video_gop_size > 34)
227 params->video_gop_size -= b;
228 ctrl->value = params->video_gop_size;
229 break;
231 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
232 params->video_gop_closure = ctrl->value;
233 break;
234 case V4L2_CID_MPEG_VIDEO_PULLDOWN:
235 params->video_pulldown = ctrl->value;
236 break;
237 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
238 /* MPEG-1 only allows CBR */
239 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
240 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
241 return -EINVAL;
242 params->video_bitrate_mode = ctrl->value;
243 break;
244 case V4L2_CID_MPEG_VIDEO_BITRATE:
245 params->video_bitrate = ctrl->value;
246 break;
247 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
248 params->video_bitrate_peak = ctrl->value;
249 break;
250 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
251 params->video_temporal_decimation = ctrl->value;
252 break;
253 case V4L2_CID_MPEG_STREAM_TYPE:
254 params->stream_type = ctrl->value;
255 params->video_encoding =
256 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
257 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
258 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
259 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
260 /* MPEG-1 implies CBR */
261 params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
263 break;
264 case V4L2_CID_MPEG_STREAM_VBI_FMT:
265 params->stream_vbi_fmt = ctrl->value;
266 break;
267 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
268 params->video_spatial_filter_mode = ctrl->value;
269 break;
270 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
271 params->video_spatial_filter = ctrl->value;
272 break;
273 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
274 params->video_luma_spatial_filter_type = ctrl->value;
275 break;
276 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
277 params->video_chroma_spatial_filter_type = ctrl->value;
278 break;
279 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
280 params->video_temporal_filter_mode = ctrl->value;
281 break;
282 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
283 params->video_temporal_filter = ctrl->value;
284 break;
285 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
286 params->video_median_filter_type = ctrl->value;
287 break;
288 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
289 params->video_luma_median_filter_top = ctrl->value;
290 break;
291 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
292 params->video_luma_median_filter_bottom = ctrl->value;
293 break;
294 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
295 params->video_chroma_median_filter_top = ctrl->value;
296 break;
297 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
298 params->video_chroma_median_filter_bottom = ctrl->value;
299 break;
300 default:
301 return -EINVAL;
303 return 0;
306 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
308 const char *name;
310 qctrl->flags = 0;
311 switch (qctrl->id) {
312 /* MPEG controls */
313 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
314 name = "Spatial Filter Mode";
315 break;
316 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
317 name = "Spatial Filter";
318 break;
319 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
320 name = "Spatial Luma Filter Type";
321 break;
322 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
323 name = "Spatial Chroma Filter Type";
324 break;
325 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
326 name = "Temporal Filter Mode";
327 break;
328 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
329 name = "Temporal Filter";
330 break;
331 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
332 name = "Median Filter Type";
333 break;
334 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
335 name = "Median Luma Filter Maximum";
336 break;
337 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
338 name = "Median Luma Filter Minimum";
339 break;
340 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
341 name = "Median Chroma Filter Maximum";
342 break;
343 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
344 name = "Median Chroma Filter Minimum";
345 break;
347 default:
348 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
350 switch (qctrl->id) {
351 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
352 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
353 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
354 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
355 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
356 qctrl->type = V4L2_CTRL_TYPE_MENU;
357 min = 0;
358 step = 1;
359 break;
360 default:
361 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
362 break;
364 switch (qctrl->id) {
365 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
366 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
367 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
368 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
369 break;
371 qctrl->minimum = min;
372 qctrl->maximum = max;
373 qctrl->step = step;
374 qctrl->default_value = def;
375 qctrl->reserved[0] = qctrl->reserved[1] = 0;
376 snprintf(qctrl->name, sizeof(qctrl->name), name);
377 return 0;
380 int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
382 int err;
384 switch (qctrl->id) {
385 case V4L2_CID_MPEG_AUDIO_ENCODING:
386 return v4l2_ctrl_query_fill(qctrl,
387 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
388 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
389 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
391 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
392 return v4l2_ctrl_query_fill(qctrl,
393 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
394 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
395 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
397 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
398 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
399 return -EINVAL;
401 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
402 err = v4l2_ctrl_query_fill_std(qctrl);
403 if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
404 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
405 return err;
407 case V4L2_CID_MPEG_VIDEO_ENCODING:
408 /* this setting is read-only for the cx2341x since the
409 V4L2_CID_MPEG_STREAM_TYPE really determines the
410 MPEG-1/2 setting */
411 err = v4l2_ctrl_query_fill_std(qctrl);
412 if (err == 0)
413 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
414 return err;
416 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
417 err = v4l2_ctrl_query_fill_std(qctrl);
418 if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
419 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
420 return err;
422 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
423 err = v4l2_ctrl_query_fill_std(qctrl);
424 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
425 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
426 return err;
428 case V4L2_CID_MPEG_STREAM_VBI_FMT:
429 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
430 return v4l2_ctrl_query_fill_std(qctrl);
431 return cx2341x_ctrl_query_fill(qctrl,
432 V4L2_MPEG_STREAM_VBI_FMT_NONE,
433 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
434 V4L2_MPEG_STREAM_VBI_FMT_NONE);
436 /* CX23415/6 specific */
437 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
438 return cx2341x_ctrl_query_fill(qctrl,
439 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
440 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
441 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
443 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
444 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
445 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
446 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
447 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
448 return 0;
450 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
451 cx2341x_ctrl_query_fill(qctrl,
452 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
453 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
454 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
455 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
456 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
457 return 0;
459 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
460 cx2341x_ctrl_query_fill(qctrl,
461 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
462 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
463 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
464 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
465 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
466 return 0;
468 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
469 return cx2341x_ctrl_query_fill(qctrl,
470 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
471 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
472 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
474 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
475 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
476 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
477 if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
478 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
479 return 0;
481 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
482 return cx2341x_ctrl_query_fill(qctrl,
483 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
484 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
485 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
487 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
488 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
489 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
490 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
491 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
492 return 0;
494 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
495 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
496 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
497 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
498 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
499 return 0;
501 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
502 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
503 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
504 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
505 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
506 return 0;
508 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
509 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
510 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
511 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
512 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
513 return 0;
515 default:
516 return v4l2_ctrl_query_fill_std(qctrl);
521 const char **cx2341x_ctrl_get_menu(u32 id)
523 static const char *mpeg_stream_type[] = {
524 "MPEG-2 Program Stream",
526 "MPEG-1 System Stream",
527 "MPEG-2 DVD-compatible Stream",
528 "MPEG-1 VCD-compatible Stream",
529 "MPEG-2 SVCD-compatible Stream",
530 NULL
533 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
534 "Manual",
535 "Auto",
536 NULL
539 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
540 "Off",
541 "1D Horizontal",
542 "1D Vertical",
543 "2D H/V Separable",
544 "2D Symmetric non-separable",
545 NULL
548 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
549 "Off",
550 "1D Horizontal",
551 NULL
554 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
555 "Manual",
556 "Auto",
557 NULL
560 static const char *cx2341x_video_median_filter_type_menu[] = {
561 "Off",
562 "Horizontal",
563 "Vertical",
564 "Horizontal/Vertical",
565 "Diagonal",
566 NULL
569 switch (id) {
570 case V4L2_CID_MPEG_STREAM_TYPE:
571 return mpeg_stream_type;
572 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
573 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
574 return NULL;
575 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
576 return cx2341x_video_spatial_filter_mode_menu;
577 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
578 return cx2341x_video_luma_spatial_filter_type_menu;
579 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
580 return cx2341x_video_chroma_spatial_filter_type_menu;
581 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
582 return cx2341x_video_temporal_filter_mode_menu;
583 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
584 return cx2341x_video_median_filter_type_menu;
585 default:
586 return v4l2_ctrl_get_menu(id);
590 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
592 params->audio_properties = (params->audio_sampling_freq << 0) |
593 ((3 - params->audio_encoding) << 2) |
594 ((1 + params->audio_l2_bitrate) << 4) |
595 (params->audio_mode << 8) |
596 (params->audio_mode_extension << 10) |
597 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
599 params->audio_emphasis) << 12) |
600 (params->audio_crc << 14);
603 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
604 struct v4l2_ext_controls *ctrls, unsigned int cmd)
606 int err = 0;
607 int i;
609 if (cmd == VIDIOC_G_EXT_CTRLS) {
610 for (i = 0; i < ctrls->count; i++) {
611 struct v4l2_ext_control *ctrl = ctrls->controls + i;
613 err = cx2341x_get_ctrl(params, ctrl);
614 if (err) {
615 ctrls->error_idx = i;
616 break;
619 return err;
621 for (i = 0; i < ctrls->count; i++) {
622 struct v4l2_ext_control *ctrl = ctrls->controls + i;
623 struct v4l2_queryctrl qctrl;
624 const char **menu_items = NULL;
626 qctrl.id = ctrl->id;
627 err = cx2341x_ctrl_query(params, &qctrl);
628 if (err)
629 break;
630 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
631 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
632 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
633 if (err)
634 break;
635 err = cx2341x_set_ctrl(params, ctrl);
636 if (err)
637 break;
639 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
640 params->video_bitrate_peak < params->video_bitrate) {
641 err = -ERANGE;
642 ctrls->error_idx = ctrls->count;
644 if (err) {
645 ctrls->error_idx = i;
647 else {
648 cx2341x_calc_audio_properties(params);
650 return err;
653 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
655 static struct cx2341x_mpeg_params default_params = {
656 /* misc */
657 .capabilities = 0,
658 .port = CX2341X_PORT_MEMORY,
659 .width = 720,
660 .height = 480,
661 .is_50hz = 0,
663 /* stream */
664 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
665 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
667 /* audio */
668 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
669 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
670 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
671 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
672 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
673 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
674 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
676 /* video */
677 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
678 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
679 .video_b_frames = 2,
680 .video_gop_size = 12,
681 .video_gop_closure = 1,
682 .video_pulldown = 0,
683 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
684 .video_bitrate = 6000000,
685 .video_bitrate_peak = 8000000,
686 .video_temporal_decimation = 0,
688 /* encoding filters */
689 .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
690 .video_spatial_filter = 0,
691 .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
692 .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
693 .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
694 .video_temporal_filter = 0,
695 .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
696 .video_luma_median_filter_top = 255,
697 .video_luma_median_filter_bottom = 0,
698 .video_chroma_median_filter_top = 255,
699 .video_chroma_median_filter_bottom = 0,
702 *p = default_params;
703 cx2341x_calc_audio_properties(p);
706 static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
708 u32 data[CX2341X_MBOX_MAX_DATA];
709 va_list vargs;
710 int i;
712 va_start(vargs, args);
714 for (i = 0; i < args; i++) {
715 data[i] = va_arg(vargs, int);
717 va_end(vargs);
718 return func(priv, cmd, args, 0, data);
721 int cx2341x_update(void *priv, cx2341x_mbox_func func,
722 const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
724 static int mpeg_stream_type[] = {
725 0, /* MPEG-2 PS */
726 1, /* MPEG-2 TS */
727 2, /* MPEG-1 SS */
728 14, /* DVD */
729 11, /* VCD */
730 12, /* SVCD */
733 int err = 0;
735 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
737 if (old == NULL || old->is_50hz != new->is_50hz) {
738 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
739 if (err) return err;
742 if (old == NULL || old->width != new->width || old->height != new->height ||
743 old->video_encoding != new->video_encoding) {
744 u16 w = new->width;
745 u16 h = new->height;
747 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
748 w /= 2;
749 h /= 2;
751 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
752 if (err) return err;
755 if (old == NULL || old->stream_type != new->stream_type) {
756 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
757 if (err) return err;
759 if (old == NULL || old->video_aspect != new->video_aspect) {
760 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
761 if (err) return err;
763 if (old == NULL || old->video_b_frames != new->video_b_frames ||
764 old->video_gop_size != new->video_gop_size) {
765 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
766 new->video_gop_size, new->video_b_frames + 1);
767 if (err) return err;
769 if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
770 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
771 if (err) return err;
773 if (old == NULL || old->video_pulldown != new->video_pulldown) {
774 err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
775 if (err) return err;
777 if (old == NULL || old->audio_properties != new->audio_properties) {
778 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
779 if (err) return err;
781 if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
782 old->video_bitrate != new->video_bitrate ||
783 old->video_bitrate_peak != new->video_bitrate_peak) {
784 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
785 new->video_bitrate_mode, new->video_bitrate,
786 new->video_bitrate_peak / 400, 0, 0);
787 if (err) return err;
789 if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
790 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
791 old->video_median_filter_type != new->video_median_filter_type) {
792 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
793 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
794 new->video_median_filter_type);
795 if (err) return err;
797 if (old == NULL ||
798 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
799 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
800 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
801 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
802 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
803 new->video_luma_median_filter_bottom,
804 new->video_luma_median_filter_top,
805 new->video_chroma_median_filter_bottom,
806 new->video_chroma_median_filter_top);
807 if (err) return err;
809 if (old == NULL ||
810 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
811 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
812 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
813 new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
814 if (err) return err;
816 if (old == NULL ||
817 old->video_spatial_filter != new->video_spatial_filter ||
818 old->video_temporal_filter != new->video_temporal_filter) {
819 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
820 new->video_spatial_filter, new->video_temporal_filter);
821 if (err) return err;
823 if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
824 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
825 new->video_temporal_decimation);
826 if (err) return err;
828 return 0;
831 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
833 const char **menu = cx2341x_ctrl_get_menu(id);
834 struct v4l2_ext_control ctrl;
836 if (menu == NULL)
837 goto invalid;
838 ctrl.id = id;
839 if (cx2341x_get_ctrl(p, &ctrl))
840 goto invalid;
841 while (ctrl.value-- && *menu) menu++;
842 if (*menu == NULL)
843 goto invalid;
844 return *menu;
846 invalid:
847 return "<invalid>";
850 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
852 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
854 /* Stream */
855 printk(KERN_INFO "%s: Stream: %s\n",
856 prefix,
857 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
859 /* Video */
860 printk(KERN_INFO "%s: Video: %dx%d, %d fps\n",
861 prefix,
862 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
863 p->is_50hz ? 25 : 30);
864 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
865 prefix,
866 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
867 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
868 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
869 p->video_bitrate);
870 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
871 printk(", Peak %d", p->video_bitrate_peak);
873 printk("\n");
874 printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
875 prefix,
876 p->video_gop_size, p->video_b_frames,
877 p->video_gop_closure ? "" : "No ",
878 p->video_pulldown ? "" : "No ");
879 if (p->video_temporal_decimation) {
880 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
881 prefix, p->video_temporal_decimation);
884 /* Audio */
885 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s",
886 prefix,
887 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
888 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
889 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
890 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
891 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
892 printk(", %s",
893 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
895 printk(", %s, %s\n",
896 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
897 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
899 /* Encoding filters */
900 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
901 prefix,
902 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
903 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
904 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
905 p->video_spatial_filter);
906 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
907 prefix,
908 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
909 p->video_temporal_filter);
910 printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
911 prefix,
912 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
913 p->video_luma_median_filter_bottom,
914 p->video_luma_median_filter_top,
915 p->video_chroma_median_filter_bottom,
916 p->video_chroma_median_filter_top);
919 EXPORT_SYMBOL(cx2341x_fill_defaults);
920 EXPORT_SYMBOL(cx2341x_ctrl_query);
921 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
922 EXPORT_SYMBOL(cx2341x_ext_ctrls);
923 EXPORT_SYMBOL(cx2341x_update);
924 EXPORT_SYMBOL(cx2341x_log_status);
925 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
928 * Local variables:
929 * c-basic-offset: 8
930 * End: