blob: d73c86aeeaacb9a13e5f190492cb8ad31f419882 [file] [log] [blame]
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001/*
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>
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>
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030029
30#include <media/tuner.h>
31#include <media/cx2341x.h>
32#include <media/v4l2-common.h>
33
34MODULE_DESCRIPTION("cx23415/6 driver");
35MODULE_AUTHOR("Hans Verkuil");
36MODULE_LICENSE("GPL");
37
38static int debug = 0;
39module_param(debug, int, 0644);
40MODULE_PARM_DESC(debug, "Debug level (0-1)");
41
Hans Verkuilcc7bc642006-06-19 17:53:08 -030042const u32 cx2341x_mpeg_ctrls[] = {
43 V4L2_CID_MPEG_CLASS,
44 V4L2_CID_MPEG_STREAM_TYPE,
Hans Verkuil8cbde942006-06-24 14:36:02 -030045 V4L2_CID_MPEG_STREAM_VBI_FMT,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030046 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,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030053 V4L2_CID_MPEG_AUDIO_MUTE,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030054 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,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030059 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
60 V4L2_CID_MPEG_VIDEO_BITRATE,
61 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
62 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030063 V4L2_CID_MPEG_VIDEO_MUTE,
64 V4L2_CID_MPEG_VIDEO_MUTE_YUV,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030065 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
66 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
67 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
68 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
69 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
70 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
71 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
72 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
73 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
74 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
75 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030076 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030077 0
78};
79
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030080
81/* Map the control ID to the correct field in the cx2341x_mpeg_params
82 struct. Return -EINVAL if the ID is unknown, else return 0. */
83static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
84 struct v4l2_ext_control *ctrl)
85{
86 switch (ctrl->id) {
87 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
88 ctrl->value = params->audio_sampling_freq;
89 break;
90 case V4L2_CID_MPEG_AUDIO_ENCODING:
91 ctrl->value = params->audio_encoding;
92 break;
93 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
94 ctrl->value = params->audio_l2_bitrate;
95 break;
96 case V4L2_CID_MPEG_AUDIO_MODE:
97 ctrl->value = params->audio_mode;
98 break;
99 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
100 ctrl->value = params->audio_mode_extension;
101 break;
102 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
103 ctrl->value = params->audio_emphasis;
104 break;
105 case V4L2_CID_MPEG_AUDIO_CRC:
106 ctrl->value = params->audio_crc;
107 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300108 case V4L2_CID_MPEG_AUDIO_MUTE:
109 ctrl->value = params->audio_mute;
110 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300111 case V4L2_CID_MPEG_VIDEO_ENCODING:
112 ctrl->value = params->video_encoding;
113 break;
114 case V4L2_CID_MPEG_VIDEO_ASPECT:
115 ctrl->value = params->video_aspect;
116 break;
117 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
118 ctrl->value = params->video_b_frames;
119 break;
120 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
121 ctrl->value = params->video_gop_size;
122 break;
123 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
124 ctrl->value = params->video_gop_closure;
125 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300126 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
127 ctrl->value = params->video_bitrate_mode;
128 break;
129 case V4L2_CID_MPEG_VIDEO_BITRATE:
130 ctrl->value = params->video_bitrate;
131 break;
132 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
133 ctrl->value = params->video_bitrate_peak;
134 break;
135 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
136 ctrl->value = params->video_temporal_decimation;
137 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300138 case V4L2_CID_MPEG_VIDEO_MUTE:
139 ctrl->value = params->video_mute;
140 break;
141 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
142 ctrl->value = params->video_mute_yuv;
143 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300144 case V4L2_CID_MPEG_STREAM_TYPE:
145 ctrl->value = params->stream_type;
146 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300147 case V4L2_CID_MPEG_STREAM_VBI_FMT:
148 ctrl->value = params->stream_vbi_fmt;
149 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300150 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
151 ctrl->value = params->video_spatial_filter_mode;
152 break;
153 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
154 ctrl->value = params->video_spatial_filter;
155 break;
156 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
157 ctrl->value = params->video_luma_spatial_filter_type;
158 break;
159 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
160 ctrl->value = params->video_chroma_spatial_filter_type;
161 break;
162 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
163 ctrl->value = params->video_temporal_filter_mode;
164 break;
165 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
166 ctrl->value = params->video_temporal_filter;
167 break;
168 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
169 ctrl->value = params->video_median_filter_type;
170 break;
171 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
172 ctrl->value = params->video_luma_median_filter_top;
173 break;
174 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
175 ctrl->value = params->video_luma_median_filter_bottom;
176 break;
177 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
178 ctrl->value = params->video_chroma_median_filter_top;
179 break;
180 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
181 ctrl->value = params->video_chroma_median_filter_bottom;
182 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300183 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
184 ctrl->value = params->stream_insert_nav_packets;
185 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300186 default:
187 return -EINVAL;
188 }
189 return 0;
190}
191
192/* Map the control ID to the correct field in the cx2341x_mpeg_params
193 struct. Return -EINVAL if the ID is unknown, else return 0. */
194static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
195 struct v4l2_ext_control *ctrl)
196{
197 switch (ctrl->id) {
198 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
199 params->audio_sampling_freq = ctrl->value;
200 break;
201 case V4L2_CID_MPEG_AUDIO_ENCODING:
202 params->audio_encoding = ctrl->value;
203 break;
204 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
205 params->audio_l2_bitrate = ctrl->value;
206 break;
207 case V4L2_CID_MPEG_AUDIO_MODE:
208 params->audio_mode = ctrl->value;
209 break;
210 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
211 params->audio_mode_extension = ctrl->value;
212 break;
213 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
214 params->audio_emphasis = ctrl->value;
215 break;
216 case V4L2_CID_MPEG_AUDIO_CRC:
217 params->audio_crc = ctrl->value;
218 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300219 case V4L2_CID_MPEG_AUDIO_MUTE:
220 params->audio_mute = ctrl->value;
221 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300222 case V4L2_CID_MPEG_VIDEO_ASPECT:
223 params->video_aspect = ctrl->value;
224 break;
225 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
226 int b = ctrl->value + 1;
227 int gop = params->video_gop_size;
228 params->video_b_frames = ctrl->value;
229 params->video_gop_size = b * ((gop + b - 1) / b);
230 /* Max GOP size = 34 */
231 while (params->video_gop_size > 34)
232 params->video_gop_size -= b;
233 break;
234 }
235 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
236 int b = params->video_b_frames + 1;
237 int gop = ctrl->value;
238 params->video_gop_size = b * ((gop + b - 1) / b);
239 /* Max GOP size = 34 */
240 while (params->video_gop_size > 34)
241 params->video_gop_size -= b;
242 ctrl->value = params->video_gop_size;
243 break;
244 }
245 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
246 params->video_gop_closure = ctrl->value;
247 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300248 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
249 /* MPEG-1 only allows CBR */
250 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
251 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
252 return -EINVAL;
253 params->video_bitrate_mode = ctrl->value;
254 break;
255 case V4L2_CID_MPEG_VIDEO_BITRATE:
256 params->video_bitrate = ctrl->value;
257 break;
258 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
259 params->video_bitrate_peak = ctrl->value;
260 break;
261 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
262 params->video_temporal_decimation = ctrl->value;
263 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300264 case V4L2_CID_MPEG_VIDEO_MUTE:
265 params->video_mute = (ctrl->value != 0);
266 break;
267 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
268 params->video_mute_yuv = ctrl->value;
269 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300270 case V4L2_CID_MPEG_STREAM_TYPE:
271 params->stream_type = ctrl->value;
272 params->video_encoding =
273 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
274 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
275 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
276 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
277 /* MPEG-1 implies CBR */
278 params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
279 }
280 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300281 case V4L2_CID_MPEG_STREAM_VBI_FMT:
282 params->stream_vbi_fmt = ctrl->value;
283 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300284 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
285 params->video_spatial_filter_mode = ctrl->value;
286 break;
287 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
288 params->video_spatial_filter = ctrl->value;
289 break;
290 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
291 params->video_luma_spatial_filter_type = ctrl->value;
292 break;
293 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
294 params->video_chroma_spatial_filter_type = ctrl->value;
295 break;
296 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
297 params->video_temporal_filter_mode = ctrl->value;
298 break;
299 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
300 params->video_temporal_filter = ctrl->value;
301 break;
302 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
303 params->video_median_filter_type = ctrl->value;
304 break;
305 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
306 params->video_luma_median_filter_top = ctrl->value;
307 break;
308 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
309 params->video_luma_median_filter_bottom = ctrl->value;
310 break;
311 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
312 params->video_chroma_median_filter_top = ctrl->value;
313 break;
314 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
315 params->video_chroma_median_filter_bottom = ctrl->value;
316 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300317 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
318 params->stream_insert_nav_packets = ctrl->value;
319 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300320 default:
321 return -EINVAL;
322 }
323 return 0;
324}
325
326static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
327{
328 const char *name;
329
330 qctrl->flags = 0;
331 switch (qctrl->id) {
332 /* MPEG controls */
333 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
334 name = "Spatial Filter Mode";
335 break;
336 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
337 name = "Spatial Filter";
338 break;
339 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
340 name = "Spatial Luma Filter Type";
341 break;
342 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
343 name = "Spatial Chroma Filter Type";
344 break;
345 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
346 name = "Temporal Filter Mode";
347 break;
348 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
349 name = "Temporal Filter";
350 break;
351 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
352 name = "Median Filter Type";
353 break;
354 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
355 name = "Median Luma Filter Maximum";
356 break;
357 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
358 name = "Median Luma Filter Minimum";
359 break;
360 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
361 name = "Median Chroma Filter Maximum";
362 break;
363 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
364 name = "Median Chroma Filter Minimum";
365 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300366 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
367 name = "Insert Navigation Packets";
368 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300369
370 default:
371 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
372 }
373 switch (qctrl->id) {
374 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
375 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
376 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
377 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
378 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
379 qctrl->type = V4L2_CTRL_TYPE_MENU;
380 min = 0;
381 step = 1;
382 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300383 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
384 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
385 min = 0;
386 max = 1;
387 step = 1;
388 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300389 default:
390 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
391 break;
392 }
393 switch (qctrl->id) {
394 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
395 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
396 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
397 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
398 break;
399 }
400 qctrl->minimum = min;
401 qctrl->maximum = max;
402 qctrl->step = step;
403 qctrl->default_value = def;
404 qctrl->reserved[0] = qctrl->reserved[1] = 0;
405 snprintf(qctrl->name, sizeof(qctrl->name), name);
406 return 0;
407}
408
409int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
410{
411 int err;
412
413 switch (qctrl->id) {
414 case V4L2_CID_MPEG_AUDIO_ENCODING:
415 return v4l2_ctrl_query_fill(qctrl,
416 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
417 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
418 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
419
420 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
421 return v4l2_ctrl_query_fill(qctrl,
422 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
423 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
424 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
425
426 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
427 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
428 return -EINVAL;
429
430 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
431 err = v4l2_ctrl_query_fill_std(qctrl);
432 if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
433 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
434 return err;
435
436 case V4L2_CID_MPEG_VIDEO_ENCODING:
437 /* this setting is read-only for the cx2341x since the
438 V4L2_CID_MPEG_STREAM_TYPE really determines the
439 MPEG-1/2 setting */
440 err = v4l2_ctrl_query_fill_std(qctrl);
441 if (err == 0)
442 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
443 return err;
444
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300445 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
446 err = v4l2_ctrl_query_fill_std(qctrl);
447 if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
448 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
449 return err;
450
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300451 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
452 err = v4l2_ctrl_query_fill_std(qctrl);
453 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
454 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
455 return err;
456
Hans Verkuil8cbde942006-06-24 14:36:02 -0300457 case V4L2_CID_MPEG_STREAM_VBI_FMT:
458 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
459 return v4l2_ctrl_query_fill_std(qctrl);
460 return cx2341x_ctrl_query_fill(qctrl,
461 V4L2_MPEG_STREAM_VBI_FMT_NONE,
462 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
463 V4L2_MPEG_STREAM_VBI_FMT_NONE);
464
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300465 /* CX23415/6 specific */
466 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
467 return cx2341x_ctrl_query_fill(qctrl,
468 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
469 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
470 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
471
472 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
473 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
474 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
475 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
476 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
477 return 0;
478
479 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
480 cx2341x_ctrl_query_fill(qctrl,
481 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
482 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
483 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
484 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
485 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
486 return 0;
487
488 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
489 cx2341x_ctrl_query_fill(qctrl,
490 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
491 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
492 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
493 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
494 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
495 return 0;
496
497 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
498 return cx2341x_ctrl_query_fill(qctrl,
499 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
500 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
501 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
502
503 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
504 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
505 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
506 if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
507 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
508 return 0;
509
510 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
511 return cx2341x_ctrl_query_fill(qctrl,
512 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
513 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
514 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
515
516 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
517 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
518 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
519 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
520 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
521 return 0;
522
523 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
524 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
525 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
526 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
527 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
528 return 0;
529
530 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
531 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
532 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
533 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
534 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
535 return 0;
536
537 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
538 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
539 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
540 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
541 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
542 return 0;
543
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300544 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
545 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
546
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300547 default:
548 return v4l2_ctrl_query_fill_std(qctrl);
549
550 }
551}
552
553const char **cx2341x_ctrl_get_menu(u32 id)
554{
555 static const char *mpeg_stream_type[] = {
556 "MPEG-2 Program Stream",
557 "",
558 "MPEG-1 System Stream",
559 "MPEG-2 DVD-compatible Stream",
560 "MPEG-1 VCD-compatible Stream",
561 "MPEG-2 SVCD-compatible Stream",
562 NULL
563 };
564
565 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
566 "Manual",
567 "Auto",
568 NULL
569 };
570
571 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
572 "Off",
573 "1D Horizontal",
574 "1D Vertical",
575 "2D H/V Separable",
576 "2D Symmetric non-separable",
577 NULL
578 };
579
580 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
581 "Off",
582 "1D Horizontal",
583 NULL
584 };
585
586 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
587 "Manual",
588 "Auto",
589 NULL
590 };
591
592 static const char *cx2341x_video_median_filter_type_menu[] = {
593 "Off",
594 "Horizontal",
595 "Vertical",
596 "Horizontal/Vertical",
597 "Diagonal",
598 NULL
599 };
600
601 switch (id) {
602 case V4L2_CID_MPEG_STREAM_TYPE:
603 return mpeg_stream_type;
604 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
605 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
606 return NULL;
607 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
608 return cx2341x_video_spatial_filter_mode_menu;
609 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
610 return cx2341x_video_luma_spatial_filter_type_menu;
611 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
612 return cx2341x_video_chroma_spatial_filter_type_menu;
613 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
614 return cx2341x_video_temporal_filter_mode_menu;
615 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
616 return cx2341x_video_median_filter_type_menu;
617 default:
618 return v4l2_ctrl_get_menu(id);
619 }
620}
621
622static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
623{
624 params->audio_properties = (params->audio_sampling_freq << 0) |
625 ((3 - params->audio_encoding) << 2) |
626 ((1 + params->audio_l2_bitrate) << 4) |
627 (params->audio_mode << 8) |
628 (params->audio_mode_extension << 10) |
629 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
630 3 :
631 params->audio_emphasis) << 12) |
632 (params->audio_crc << 14);
633}
634
635int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300636 struct v4l2_ext_controls *ctrls, unsigned int cmd)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300637{
638 int err = 0;
639 int i;
640
641 if (cmd == VIDIOC_G_EXT_CTRLS) {
642 for (i = 0; i < ctrls->count; i++) {
643 struct v4l2_ext_control *ctrl = ctrls->controls + i;
644
645 err = cx2341x_get_ctrl(params, ctrl);
646 if (err) {
647 ctrls->error_idx = i;
648 break;
649 }
650 }
651 return err;
652 }
653 for (i = 0; i < ctrls->count; i++) {
654 struct v4l2_ext_control *ctrl = ctrls->controls + i;
655 struct v4l2_queryctrl qctrl;
656 const char **menu_items = NULL;
657
658 qctrl.id = ctrl->id;
659 err = cx2341x_ctrl_query(params, &qctrl);
660 if (err)
661 break;
662 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
663 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
664 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
665 if (err)
666 break;
667 err = cx2341x_set_ctrl(params, ctrl);
668 if (err)
669 break;
670 }
671 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
672 params->video_bitrate_peak < params->video_bitrate) {
673 err = -ERANGE;
674 ctrls->error_idx = ctrls->count;
675 }
676 if (err) {
677 ctrls->error_idx = i;
678 }
679 else {
680 cx2341x_calc_audio_properties(params);
681 }
682 return err;
683}
684
685void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
686{
687 static struct cx2341x_mpeg_params default_params = {
688 /* misc */
Hans Verkuil8cbde942006-06-24 14:36:02 -0300689 .capabilities = 0,
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300690 .port = CX2341X_PORT_MEMORY,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300691 .width = 720,
692 .height = 480,
693 .is_50hz = 0,
694
695 /* stream */
696 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
Hans Verkuil8cbde942006-06-24 14:36:02 -0300697 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300698 .stream_insert_nav_packets = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300699
700 /* audio */
701 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
702 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
703 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
704 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
705 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
706 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
707 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300708 .audio_mute = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300709
710 /* video */
711 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
712 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
713 .video_b_frames = 2,
714 .video_gop_size = 12,
715 .video_gop_closure = 1,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300716 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
717 .video_bitrate = 6000000,
718 .video_bitrate_peak = 8000000,
719 .video_temporal_decimation = 0,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300720 .video_mute = 0,
721 .video_mute_yuv = 0x008080, /* YCbCr value for black */
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300722
723 /* encoding filters */
724 .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
725 .video_spatial_filter = 0,
726 .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
727 .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
728 .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300729 .video_temporal_filter = 8,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300730 .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
731 .video_luma_median_filter_top = 255,
732 .video_luma_median_filter_bottom = 0,
733 .video_chroma_median_filter_top = 255,
734 .video_chroma_median_filter_bottom = 0,
735 };
736
737 *p = default_params;
738 cx2341x_calc_audio_properties(p);
739}
740
741static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
742{
743 u32 data[CX2341X_MBOX_MAX_DATA];
744 va_list vargs;
745 int i;
746
747 va_start(vargs, args);
748
749 for (i = 0; i < args; i++) {
750 data[i] = va_arg(vargs, int);
751 }
752 va_end(vargs);
753 return func(priv, cmd, args, 0, data);
754}
755
756int cx2341x_update(void *priv, cx2341x_mbox_func func,
757 const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
758{
759 static int mpeg_stream_type[] = {
760 0, /* MPEG-2 PS */
761 1, /* MPEG-2 TS */
762 2, /* MPEG-1 SS */
763 14, /* DVD */
764 11, /* VCD */
765 12, /* SVCD */
766 };
767
768 int err = 0;
Hans Verkuil44b579d2006-08-27 19:22:15 -0300769 u16 temporal = new->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300770
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300771 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300772
773 if (old == NULL || old->is_50hz != new->is_50hz) {
774 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
775 if (err) return err;
776 }
777
778 if (old == NULL || old->width != new->width || old->height != new->height ||
779 old->video_encoding != new->video_encoding) {
780 u16 w = new->width;
781 u16 h = new->height;
782
783 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
784 w /= 2;
785 h /= 2;
786 }
787 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
788 if (err) return err;
Hans Verkuil12b896e2006-12-18 13:37:50 -0300789 }
Hans Verkuil44b579d2006-08-27 19:22:15 -0300790
Hans Verkuil12b896e2006-12-18 13:37:50 -0300791 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
Hans Verkuil44b579d2006-08-27 19:22:15 -0300792 /* Adjust temporal filter if necessary. The problem with the temporal
793 filter is that it works well with full resolution capturing, but
794 not when the capture window is scaled (the filter introduces
Hans Verkuil12b896e2006-12-18 13:37:50 -0300795 a ghosting effect). So if the capture window is scaled, then
796 force the filter to 0.
Hans Verkuil44b579d2006-08-27 19:22:15 -0300797
Hans Verkuil12b896e2006-12-18 13:37:50 -0300798 For full resolution the filter really improves the video
Hans Verkuil44b579d2006-08-27 19:22:15 -0300799 quality, especially if the original video quality is suboptimal. */
Hans Verkuil12b896e2006-12-18 13:37:50 -0300800 temporal = 0;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300801 }
802
803 if (old == NULL || old->stream_type != new->stream_type) {
804 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
805 if (err) return err;
806 }
807 if (old == NULL || old->video_aspect != new->video_aspect) {
808 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
809 if (err) return err;
810 }
811 if (old == NULL || old->video_b_frames != new->video_b_frames ||
812 old->video_gop_size != new->video_gop_size) {
813 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
814 new->video_gop_size, new->video_b_frames + 1);
815 if (err) return err;
816 }
817 if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
818 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
819 if (err) return err;
820 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300821 if (old == NULL || old->audio_properties != new->audio_properties) {
822 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
823 if (err) return err;
824 }
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300825 if (old == NULL || old->audio_mute != new->audio_mute) {
826 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, new->audio_mute);
827 if (err) return err;
828 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300829 if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
830 old->video_bitrate != new->video_bitrate ||
831 old->video_bitrate_peak != new->video_bitrate_peak) {
832 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
833 new->video_bitrate_mode, new->video_bitrate,
834 new->video_bitrate_peak / 400, 0, 0);
835 if (err) return err;
836 }
837 if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
838 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
839 old->video_median_filter_type != new->video_median_filter_type) {
840 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
841 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
842 new->video_median_filter_type);
843 if (err) return err;
844 }
845 if (old == NULL ||
846 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
847 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
848 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
849 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
850 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
851 new->video_luma_median_filter_bottom,
852 new->video_luma_median_filter_top,
853 new->video_chroma_median_filter_bottom,
854 new->video_chroma_median_filter_top);
855 if (err) return err;
856 }
857 if (old == NULL ||
858 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
859 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
860 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
861 new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
862 if (err) return err;
863 }
864 if (old == NULL ||
865 old->video_spatial_filter != new->video_spatial_filter ||
Hans Verkuil44b579d2006-08-27 19:22:15 -0300866 old->video_temporal_filter != temporal) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300867 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300868 new->video_spatial_filter, temporal);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300869 if (err) return err;
870 }
871 if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
872 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
873 new->video_temporal_decimation);
874 if (err) return err;
875 }
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300876 if (old == NULL || old->video_mute != new->video_mute ||
877 (new->video_mute && old->video_mute_yuv != new->video_mute_yuv)) {
878 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, new->video_mute | (new->video_mute_yuv << 8));
879 if (err) return err;
880 }
881 if (old == NULL || old->stream_insert_nav_packets != new->stream_insert_nav_packets) {
882 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, 7, new->stream_insert_nav_packets);
883 if (err) return err;
884 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300885 return 0;
886}
887
888static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
889{
890 const char **menu = cx2341x_ctrl_get_menu(id);
891 struct v4l2_ext_control ctrl;
892
893 if (menu == NULL)
894 goto invalid;
895 ctrl.id = id;
896 if (cx2341x_get_ctrl(p, &ctrl))
897 goto invalid;
898 while (ctrl.value-- && *menu) menu++;
899 if (*menu == NULL)
900 goto invalid;
901 return *menu;
902
903invalid:
904 return "<invalid>";
905}
906
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300907void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300908{
909 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
Hans Verkuil83aaf132006-12-18 13:40:23 -0300910 int temporal = p->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300911
912 /* Stream */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300913 printk(KERN_INFO "%s: Stream: %s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300914 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300915 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300916 if (p->stream_insert_nav_packets)
917 printk(" (with navigation packets)");
918 printk("\n");
Hans Verkuil44b579d2006-08-27 19:22:15 -0300919 printk(KERN_INFO "%s: VBI Format: %s\n",
920 prefix,
921 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300922
923 /* Video */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300924 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300925 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300926 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300927 p->is_50hz ? 25 : 30,
928 (p->video_mute) ? " (muted)" : "");
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300929 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
930 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300931 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
932 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
933 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
934 p->video_bitrate);
935 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
936 printk(", Peak %d", p->video_bitrate_peak);
937 }
938 printk("\n");
Hans Verkuil75558ab2006-12-18 22:52:21 -0300939 printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300940 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300941 p->video_gop_size, p->video_b_frames,
Hans Verkuil75558ab2006-12-18 22:52:21 -0300942 p->video_gop_closure ? "" : "No ");
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300943 if (p->video_temporal_decimation) {
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300944 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
945 prefix, p->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300946 }
947
948 /* Audio */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300949 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300950 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300951 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
952 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
953 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300954 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
955 p->audio_mute ? " (muted)" : "");
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300956 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
957 printk(", %s",
958 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
959 }
960 printk(", %s, %s\n",
961 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
962 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
963
964 /* Encoding filters */
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300965 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
966 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300967 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
968 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
969 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
970 p->video_spatial_filter);
Hans Verkuil83aaf132006-12-18 13:40:23 -0300971 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
972 temporal = 0;
973 }
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300974 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
975 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300976 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
Hans Verkuil83aaf132006-12-18 13:40:23 -0300977 temporal);
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300978 printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
979 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300980 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
981 p->video_luma_median_filter_bottom,
982 p->video_luma_median_filter_top,
983 p->video_chroma_median_filter_bottom,
984 p->video_chroma_median_filter_top);
985}
986
987EXPORT_SYMBOL(cx2341x_fill_defaults);
988EXPORT_SYMBOL(cx2341x_ctrl_query);
989EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
990EXPORT_SYMBOL(cx2341x_ext_ctrls);
991EXPORT_SYMBOL(cx2341x_update);
992EXPORT_SYMBOL(cx2341x_log_status);
Hans Verkuilcc7bc642006-06-19 17:53:08 -0300993EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300994
995/*
996 * Local variables:
997 * c-basic-offset: 8
998 * End:
999 */
1000