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