blob: 22847a0444f59d051acd3e3d68bcbc2ad6852c50 [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>
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030023#include <linux/errno.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/videodev2.h>
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030028
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
Hans Verkuil737bd412007-11-01 13:38:12 -030037static int debug;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030038module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "Debug level (0-1)");
40
Hans Verkuilcc7bc642006-06-19 17:53:08 -030041const u32 cx2341x_mpeg_ctrls[] = {
42 V4L2_CID_MPEG_CLASS,
43 V4L2_CID_MPEG_STREAM_TYPE,
Hans Verkuil8cbde942006-06-24 14:36:02 -030044 V4L2_CID_MPEG_STREAM_VBI_FMT,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030045 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,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030052 V4L2_CID_MPEG_AUDIO_MUTE,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030053 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,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030058 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,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030062 V4L2_CID_MPEG_VIDEO_MUTE,
63 V4L2_CID_MPEG_VIDEO_MUTE_YUV,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030064 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,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030075 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030076 0
77};
Hans Verkuil737bd412007-11-01 13:38:12 -030078EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
Hans Verkuilcc7bc642006-06-19 17:53:08 -030079
Hans Verkuilca130ee2008-07-17 12:26:45 -030080static 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
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300135
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. */
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300138static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300139 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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300163 case V4L2_CID_MPEG_AUDIO_MUTE:
164 ctrl->value = params->audio_mute;
165 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300166 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;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300181 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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300193 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;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300199 case V4L2_CID_MPEG_STREAM_TYPE:
200 ctrl->value = params->stream_type;
201 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300202 case V4L2_CID_MPEG_STREAM_VBI_FMT:
203 ctrl->value = params->stream_vbi_fmt;
204 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300205 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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300238 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
239 ctrl->value = params->stream_insert_nav_packets;
240 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300241 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. */
Hans Verkuil01f1e442007-08-21 18:32:42 -0300249static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300250 struct v4l2_ext_control *ctrl)
251{
252 switch (ctrl->id) {
253 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300254 if (busy)
255 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300256 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:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300262 if (busy)
263 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300264 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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300278 case V4L2_CID_MPEG_AUDIO_MUTE:
279 params->audio_mute = ctrl->value;
280 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300281 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;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300307 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300308 if (busy)
309 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300310 /* 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:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300317 if (busy)
318 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300319 params->video_bitrate = ctrl->value;
320 break;
321 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300322 if (busy)
323 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300324 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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300329 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;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300335 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300336 if (busy)
337 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300338 params->stream_type = ctrl->value;
339 params->video_encoding =
Hans Verkuil737bd412007-11-01 13:38:12 -0300340 (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)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300345 /* MPEG-1 implies CBR */
Hans Verkuil737bd412007-11-01 13:38:12 -0300346 params->video_bitrate_mode =
347 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300348 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300349 case V4L2_CID_MPEG_STREAM_VBI_FMT:
350 params->stream_vbi_fmt = ctrl->value;
351 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300352 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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300385 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
386 params->stream_insert_nav_packets = ctrl->value;
387 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300388 default:
389 return -EINVAL;
390 }
391 return 0;
392}
393
Hans Verkuil737bd412007-11-01 13:38:12 -0300394static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
395 s32 min, s32 max, s32 step, s32 def)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300396{
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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300435 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
436 name = "Insert Navigation Packets";
437 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300438
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;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300452 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;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300458 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
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300478int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
Hans Verkuil737bd412007-11-01 13:38:12 -0300479 struct v4l2_queryctrl *qctrl)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300480{
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,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300488 default_params.audio_encoding);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300489
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,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300494 default_params.audio_l2_bitrate);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300495
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);
Hans Verkuil737bd412007-11-01 13:38:12 -0300502 if (err == 0 &&
503 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300504 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 */
511 err = v4l2_ctrl_query_fill_std(qctrl);
512 if (err == 0)
513 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
514 return err;
515
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300516 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
517 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300518 if (err == 0 &&
519 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300520 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
521 return err;
522
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300523 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
524 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300525 if (err == 0 &&
526 params->video_bitrate_mode ==
527 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300528 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
529 return err;
530
Hans Verkuil8cbde942006-06-24 14:36:02 -0300531 case V4L2_CID_MPEG_STREAM_VBI_FMT:
532 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
533 return v4l2_ctrl_query_fill_std(qctrl);
534 return cx2341x_ctrl_query_fill(qctrl,
535 V4L2_MPEG_STREAM_VBI_FMT_NONE,
536 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300537 default_params.stream_vbi_fmt);
538
539 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
540 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
541 params->is_50hz ? 12 : 15);
Hans Verkuil8cbde942006-06-24 14:36:02 -0300542
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300543 /* CX23415/6 specific */
544 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
545 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300546 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
547 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300548 default_params.video_spatial_filter_mode);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300549
550 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300551 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
552 default_params.video_spatial_filter);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300553 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300554 if (params->video_spatial_filter_mode ==
555 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
556 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300557 return 0;
558
559 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
560 cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300561 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
562 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
563 1,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300564 default_params.video_luma_spatial_filter_type);
Hans Verkuil737bd412007-11-01 13:38:12 -0300565 if (params->video_spatial_filter_mode ==
566 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
567 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300568 return 0;
569
570 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
571 cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300572 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
573 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
574 1,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300575 default_params.video_chroma_spatial_filter_type);
Hans Verkuil737bd412007-11-01 13:38:12 -0300576 if (params->video_spatial_filter_mode ==
577 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
578 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300579 return 0;
580
581 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
582 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300583 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
584 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300585 default_params.video_temporal_filter_mode);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300586
587 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300588 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
589 default_params.video_temporal_filter);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300590 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300591 if (params->video_temporal_filter_mode ==
592 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
593 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300594 return 0;
595
596 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
597 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300598 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
599 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
Hans Verkuilca130ee2008-07-17 12:26:45 -0300600 default_params.video_median_filter_type);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300601
602 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300603 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
604 default_params.video_luma_median_filter_top);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300605 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300606 if (params->video_median_filter_type ==
607 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
608 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300609 return 0;
610
611 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300612 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
613 default_params.video_luma_median_filter_bottom);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300614 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300615 if (params->video_median_filter_type ==
616 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
617 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300618 return 0;
619
620 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300621 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
622 default_params.video_chroma_median_filter_top);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300623 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300624 if (params->video_median_filter_type ==
625 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
626 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300627 return 0;
628
629 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300630 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
631 default_params.video_chroma_median_filter_bottom);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300632 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300633 if (params->video_median_filter_type ==
634 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
635 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300636 return 0;
637
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300638 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
Hans Verkuilca130ee2008-07-17 12:26:45 -0300639 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
640 default_params.stream_insert_nav_packets);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300641
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300642 default:
643 return v4l2_ctrl_query_fill_std(qctrl);
644
645 }
646}
Hans Verkuil737bd412007-11-01 13:38:12 -0300647EXPORT_SYMBOL(cx2341x_ctrl_query);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300648
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300649const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300650{
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300651 static const char *mpeg_stream_type_without_ts[] = {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300652 "MPEG-2 Program Stream",
653 "",
654 "MPEG-1 System Stream",
655 "MPEG-2 DVD-compatible Stream",
656 "MPEG-1 VCD-compatible Stream",
657 "MPEG-2 SVCD-compatible Stream",
658 NULL
659 };
660
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300661 static const char *mpeg_stream_type_with_ts[] = {
662 "MPEG-2 Program Stream",
663 "MPEG-2 Transport Stream",
664 "MPEG-1 System Stream",
665 "MPEG-2 DVD-compatible Stream",
666 "MPEG-1 VCD-compatible Stream",
667 "MPEG-2 SVCD-compatible Stream",
668 NULL
669 };
670
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300671 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
672 "Manual",
673 "Auto",
674 NULL
675 };
676
677 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
678 "Off",
679 "1D Horizontal",
680 "1D Vertical",
681 "2D H/V Separable",
682 "2D Symmetric non-separable",
683 NULL
684 };
685
686 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
687 "Off",
688 "1D Horizontal",
689 NULL
690 };
691
692 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
693 "Manual",
694 "Auto",
695 NULL
696 };
697
698 static const char *cx2341x_video_median_filter_type_menu[] = {
699 "Off",
700 "Horizontal",
701 "Vertical",
702 "Horizontal/Vertical",
703 "Diagonal",
704 NULL
705 };
706
707 switch (id) {
708 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300709 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
710 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300711 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
712 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
713 return NULL;
714 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
715 return cx2341x_video_spatial_filter_mode_menu;
716 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
717 return cx2341x_video_luma_spatial_filter_type_menu;
718 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
719 return cx2341x_video_chroma_spatial_filter_type_menu;
720 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
721 return cx2341x_video_temporal_filter_mode_menu;
722 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
723 return cx2341x_video_median_filter_type_menu;
724 default:
725 return v4l2_ctrl_get_menu(id);
726 }
727}
Hans Verkuil737bd412007-11-01 13:38:12 -0300728EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300729
730static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
731{
732 params->audio_properties = (params->audio_sampling_freq << 0) |
733 ((3 - params->audio_encoding) << 2) |
734 ((1 + params->audio_l2_bitrate) << 4) |
735 (params->audio_mode << 8) |
736 (params->audio_mode_extension << 10) |
Hans Verkuil737bd412007-11-01 13:38:12 -0300737 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
738 ? 3 : params->audio_emphasis) << 12) |
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300739 (params->audio_crc << 14);
740}
741
Hans Verkuil01f1e442007-08-21 18:32:42 -0300742int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300743 struct v4l2_ext_controls *ctrls, unsigned int cmd)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300744{
745 int err = 0;
746 int i;
747
748 if (cmd == VIDIOC_G_EXT_CTRLS) {
749 for (i = 0; i < ctrls->count; i++) {
750 struct v4l2_ext_control *ctrl = ctrls->controls + i;
751
752 err = cx2341x_get_ctrl(params, ctrl);
753 if (err) {
754 ctrls->error_idx = i;
755 break;
756 }
757 }
758 return err;
759 }
760 for (i = 0; i < ctrls->count; i++) {
761 struct v4l2_ext_control *ctrl = ctrls->controls + i;
762 struct v4l2_queryctrl qctrl;
763 const char **menu_items = NULL;
764
765 qctrl.id = ctrl->id;
766 err = cx2341x_ctrl_query(params, &qctrl);
767 if (err)
768 break;
769 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300770 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300771 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
772 if (err)
773 break;
Hans Verkuil01f1e442007-08-21 18:32:42 -0300774 err = cx2341x_set_ctrl(params, busy, ctrl);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300775 if (err)
776 break;
777 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300778 if (err == 0 &&
779 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
780 params->video_bitrate_peak < params->video_bitrate) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300781 err = -ERANGE;
782 ctrls->error_idx = ctrls->count;
783 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300784 if (err)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300785 ctrls->error_idx = i;
Hans Verkuil737bd412007-11-01 13:38:12 -0300786 else
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300787 cx2341x_calc_audio_properties(params);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300788 return err;
789}
Hans Verkuil737bd412007-11-01 13:38:12 -0300790EXPORT_SYMBOL(cx2341x_ext_ctrls);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300791
792void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
793{
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300794 *p = default_params;
795 cx2341x_calc_audio_properties(p);
796}
Hans Verkuil737bd412007-11-01 13:38:12 -0300797EXPORT_SYMBOL(cx2341x_fill_defaults);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300798
Hans Verkuil737bd412007-11-01 13:38:12 -0300799static int cx2341x_api(void *priv, cx2341x_mbox_func func,
Hans Verkuilea48c132007-12-12 07:04:58 -0300800 u32 cmd, int args, ...)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300801{
802 u32 data[CX2341X_MBOX_MAX_DATA];
803 va_list vargs;
804 int i;
805
806 va_start(vargs, args);
807
Hans Verkuil737bd412007-11-01 13:38:12 -0300808 for (i = 0; i < args; i++)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300809 data[i] = va_arg(vargs, int);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300810 va_end(vargs);
811 return func(priv, cmd, args, 0, data);
812}
813
Hans Verkuil737bd412007-11-01 13:38:12 -0300814#define NEQ(field) (old->field != new->field)
815
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300816int cx2341x_update(void *priv, cx2341x_mbox_func func,
Hans Verkuil737bd412007-11-01 13:38:12 -0300817 const struct cx2341x_mpeg_params *old,
818 const struct cx2341x_mpeg_params *new)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300819{
820 static int mpeg_stream_type[] = {
821 0, /* MPEG-2 PS */
822 1, /* MPEG-2 TS */
823 2, /* MPEG-1 SS */
824 14, /* DVD */
825 11, /* VCD */
826 12, /* SVCD */
827 };
828
829 int err = 0;
Hans Verkuil737bd412007-11-01 13:38:12 -0300830 int force = (old == NULL);
Hans Verkuil44b579d2006-08-27 19:22:15 -0300831 u16 temporal = new->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300832
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300833 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300834
Hans Verkuil737bd412007-11-01 13:38:12 -0300835 if (force || NEQ(is_50hz)) {
836 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
837 new->is_50hz);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300838 if (err) return err;
839 }
840
Hans Verkuil737bd412007-11-01 13:38:12 -0300841 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300842 u16 w = new->width;
843 u16 h = new->height;
844
845 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
846 w /= 2;
847 h /= 2;
848 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300849 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
850 h, w);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300851 if (err) return err;
Hans Verkuil12b896e2006-12-18 13:37:50 -0300852 }
Hans Verkuil44b579d2006-08-27 19:22:15 -0300853
Hans Verkuil12b896e2006-12-18 13:37:50 -0300854 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
Hans Verkuil737bd412007-11-01 13:38:12 -0300855 /* Adjust temporal filter if necessary. The problem with the
856 temporal filter is that it works well with full resolution
857 capturing, but not when the capture window is scaled (the
858 filter introduces a ghosting effect). So if the capture
859 window is scaled, then force the filter to 0.
Hans Verkuil44b579d2006-08-27 19:22:15 -0300860
Hans Verkuil12b896e2006-12-18 13:37:50 -0300861 For full resolution the filter really improves the video
Hans Verkuil737bd412007-11-01 13:38:12 -0300862 quality, especially if the original video quality is
863 suboptimal. */
Hans Verkuil12b896e2006-12-18 13:37:50 -0300864 temporal = 0;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300865 }
866
Hans Verkuil737bd412007-11-01 13:38:12 -0300867 if (force || NEQ(stream_type)) {
868 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
869 mpeg_stream_type[new->stream_type]);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300870 if (err) return err;
871 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300872 if (force || NEQ(video_aspect)) {
873 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
874 1 + new->video_aspect);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300875 if (err) return err;
876 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300877 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300878 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
879 new->video_gop_size, new->video_b_frames + 1);
880 if (err) return err;
881 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300882 if (force || NEQ(video_gop_closure)) {
883 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
884 new->video_gop_closure);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300885 if (err) return err;
886 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300887 if (force || NEQ(audio_properties)) {
888 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
889 1, new->audio_properties);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300890 if (err) return err;
891 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300892 if (force || NEQ(audio_mute)) {
893 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
894 new->audio_mute);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300895 if (err) return err;
896 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300897 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
898 NEQ(video_bitrate_peak)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300899 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
900 new->video_bitrate_mode, new->video_bitrate,
901 new->video_bitrate_peak / 400, 0, 0);
902 if (err) return err;
903 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300904 if (force || NEQ(video_spatial_filter_mode) ||
905 NEQ(video_temporal_filter_mode) ||
906 NEQ(video_median_filter_type)) {
907 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
908 2, new->video_spatial_filter_mode |
909 (new->video_temporal_filter_mode << 1),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300910 new->video_median_filter_type);
911 if (err) return err;
912 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300913 if (force || NEQ(video_luma_median_filter_bottom) ||
914 NEQ(video_luma_median_filter_top) ||
915 NEQ(video_chroma_median_filter_bottom) ||
916 NEQ(video_chroma_median_filter_top)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300917 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
918 new->video_luma_median_filter_bottom,
919 new->video_luma_median_filter_top,
920 new->video_chroma_median_filter_bottom,
921 new->video_chroma_median_filter_top);
922 if (err) return err;
923 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300924 if (force || NEQ(video_luma_spatial_filter_type) ||
925 NEQ(video_chroma_spatial_filter_type)) {
926 err = cx2341x_api(priv, func,
927 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
928 2, new->video_luma_spatial_filter_type,
929 new->video_chroma_spatial_filter_type);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300930 if (err) return err;
931 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300932 if (force || NEQ(video_spatial_filter) ||
933 old->video_temporal_filter != temporal) {
934 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
935 2, new->video_spatial_filter, temporal);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300936 if (err) return err;
937 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300938 if (force || NEQ(video_temporal_decimation)) {
939 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
940 1, new->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300941 if (err) return err;
942 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300943 if (force || NEQ(video_mute) ||
944 (new->video_mute && NEQ(video_mute_yuv))) {
945 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
946 new->video_mute | (new->video_mute_yuv << 8));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300947 if (err) return err;
948 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300949 if (force || NEQ(stream_insert_nav_packets)) {
950 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
951 7, new->stream_insert_nav_packets);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300952 if (err) return err;
953 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300954 return 0;
955}
Hans Verkuil737bd412007-11-01 13:38:12 -0300956EXPORT_SYMBOL(cx2341x_update);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300957
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300958static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300959{
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300960 const char **menu = cx2341x_ctrl_get_menu(p, id);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300961 struct v4l2_ext_control ctrl;
962
963 if (menu == NULL)
964 goto invalid;
965 ctrl.id = id;
966 if (cx2341x_get_ctrl(p, &ctrl))
967 goto invalid;
968 while (ctrl.value-- && *menu) menu++;
969 if (*menu == NULL)
970 goto invalid;
971 return *menu;
972
973invalid:
974 return "<invalid>";
975}
976
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300977void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300978{
979 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
Hans Verkuil83aaf132006-12-18 13:40:23 -0300980 int temporal = p->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300981
982 /* Stream */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300983 printk(KERN_INFO "%s: Stream: %s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300984 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300985 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300986 if (p->stream_insert_nav_packets)
987 printk(" (with navigation packets)");
988 printk("\n");
Hans Verkuil44b579d2006-08-27 19:22:15 -0300989 printk(KERN_INFO "%s: VBI Format: %s\n",
990 prefix,
991 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300992
993 /* Video */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300994 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300995 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300996 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300997 p->is_50hz ? 25 : 30,
998 (p->video_mute) ? " (muted)" : "");
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300999 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
1000 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001001 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1002 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1003 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1004 p->video_bitrate);
Hans Verkuil737bd412007-11-01 13:38:12 -03001005 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001006 printk(", Peak %d", p->video_bitrate_peak);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001007 printk("\n");
Hans Verkuil737bd412007-11-01 13:38:12 -03001008 printk(KERN_INFO
1009 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001010 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001011 p->video_gop_size, p->video_b_frames,
Hans Verkuil75558ab2006-12-18 22:52:21 -03001012 p->video_gop_closure ? "" : "No ");
Hans Verkuil737bd412007-11-01 13:38:12 -03001013 if (p->video_temporal_decimation)
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001014 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1015 prefix, p->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001016
1017 /* Audio */
Hans Verkuil5eee72e2007-04-27 12:31:00 -03001018 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001019 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001020 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1021 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1022 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
Hans Verkuil5eee72e2007-04-27 12:31:00 -03001023 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1024 p->audio_mute ? " (muted)" : "");
Hans Verkuil737bd412007-11-01 13:38:12 -03001025 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1026 printk(", %s", cx2341x_menu_item(p,
1027 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001028 printk(", %s, %s\n",
1029 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1030 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1031
1032 /* Encoding filters */
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001033 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1034 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001035 cx2341x_menu_item(p,
1036 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1037 cx2341x_menu_item(p,
1038 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1039 cx2341x_menu_item(p,
1040 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001041 p->video_spatial_filter);
Hans Verkuil737bd412007-11-01 13:38:12 -03001042
1043 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
Hans Verkuil83aaf132006-12-18 13:40:23 -03001044 temporal = 0;
Hans Verkuil737bd412007-11-01 13:38:12 -03001045
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001046 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1047 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001048 cx2341x_menu_item(p,
1049 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
Hans Verkuil83aaf132006-12-18 13:40:23 -03001050 temporal);
Hans Verkuil737bd412007-11-01 13:38:12 -03001051 printk(KERN_INFO
1052 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001053 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001054 cx2341x_menu_item(p,
1055 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001056 p->video_luma_median_filter_bottom,
1057 p->video_luma_median_filter_top,
1058 p->video_chroma_median_filter_bottom,
1059 p->video_chroma_median_filter_top);
1060}
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001061EXPORT_SYMBOL(cx2341x_log_status);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001062
1063/*
1064 * Local variables:
1065 * c-basic-offset: 8
1066 * End:
1067 */
1068