blob: 5e40c6bd69b6f4b6b58c531b277122849249ed9f [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 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. */
Hans Verkuile0e31cd2008-06-22 12:03:28 -030083static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030084 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. */
Hans Verkuil01f1e442007-08-21 18:32:42 -0300194static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300195 struct v4l2_ext_control *ctrl)
196{
197 switch (ctrl->id) {
198 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300199 if (busy)
200 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300201 params->audio_sampling_freq = ctrl->value;
202 break;
203 case V4L2_CID_MPEG_AUDIO_ENCODING:
204 params->audio_encoding = ctrl->value;
205 break;
206 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300207 if (busy)
208 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300209 params->audio_l2_bitrate = ctrl->value;
210 break;
211 case V4L2_CID_MPEG_AUDIO_MODE:
212 params->audio_mode = ctrl->value;
213 break;
214 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
215 params->audio_mode_extension = ctrl->value;
216 break;
217 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
218 params->audio_emphasis = ctrl->value;
219 break;
220 case V4L2_CID_MPEG_AUDIO_CRC:
221 params->audio_crc = ctrl->value;
222 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300223 case V4L2_CID_MPEG_AUDIO_MUTE:
224 params->audio_mute = ctrl->value;
225 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300226 case V4L2_CID_MPEG_VIDEO_ASPECT:
227 params->video_aspect = ctrl->value;
228 break;
229 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
230 int b = ctrl->value + 1;
231 int gop = params->video_gop_size;
232 params->video_b_frames = ctrl->value;
233 params->video_gop_size = b * ((gop + b - 1) / b);
234 /* Max GOP size = 34 */
235 while (params->video_gop_size > 34)
236 params->video_gop_size -= b;
237 break;
238 }
239 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
240 int b = params->video_b_frames + 1;
241 int gop = ctrl->value;
242 params->video_gop_size = b * ((gop + b - 1) / b);
243 /* Max GOP size = 34 */
244 while (params->video_gop_size > 34)
245 params->video_gop_size -= b;
246 ctrl->value = params->video_gop_size;
247 break;
248 }
249 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
250 params->video_gop_closure = ctrl->value;
251 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300252 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300253 if (busy)
254 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300255 /* MPEG-1 only allows CBR */
256 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
257 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
258 return -EINVAL;
259 params->video_bitrate_mode = ctrl->value;
260 break;
261 case V4L2_CID_MPEG_VIDEO_BITRATE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300262 if (busy)
263 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300264 params->video_bitrate = ctrl->value;
265 break;
266 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300267 if (busy)
268 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300269 params->video_bitrate_peak = ctrl->value;
270 break;
271 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
272 params->video_temporal_decimation = ctrl->value;
273 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300274 case V4L2_CID_MPEG_VIDEO_MUTE:
275 params->video_mute = (ctrl->value != 0);
276 break;
277 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
278 params->video_mute_yuv = ctrl->value;
279 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300280 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300281 if (busy)
282 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300283 params->stream_type = ctrl->value;
284 params->video_encoding =
Hans Verkuil737bd412007-11-01 13:38:12 -0300285 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
286 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
287 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
288 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
289 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300290 /* MPEG-1 implies CBR */
Hans Verkuil737bd412007-11-01 13:38:12 -0300291 params->video_bitrate_mode =
292 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300293 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300294 case V4L2_CID_MPEG_STREAM_VBI_FMT:
295 params->stream_vbi_fmt = ctrl->value;
296 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300297 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
298 params->video_spatial_filter_mode = ctrl->value;
299 break;
300 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
301 params->video_spatial_filter = ctrl->value;
302 break;
303 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
304 params->video_luma_spatial_filter_type = ctrl->value;
305 break;
306 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
307 params->video_chroma_spatial_filter_type = ctrl->value;
308 break;
309 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
310 params->video_temporal_filter_mode = ctrl->value;
311 break;
312 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
313 params->video_temporal_filter = ctrl->value;
314 break;
315 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
316 params->video_median_filter_type = ctrl->value;
317 break;
318 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
319 params->video_luma_median_filter_top = ctrl->value;
320 break;
321 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
322 params->video_luma_median_filter_bottom = ctrl->value;
323 break;
324 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
325 params->video_chroma_median_filter_top = ctrl->value;
326 break;
327 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
328 params->video_chroma_median_filter_bottom = ctrl->value;
329 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300330 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
331 params->stream_insert_nav_packets = ctrl->value;
332 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300333 default:
334 return -EINVAL;
335 }
336 return 0;
337}
338
Hans Verkuil737bd412007-11-01 13:38:12 -0300339static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
340 s32 min, s32 max, s32 step, s32 def)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300341{
342 const char *name;
343
344 qctrl->flags = 0;
345 switch (qctrl->id) {
346 /* MPEG controls */
347 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
348 name = "Spatial Filter Mode";
349 break;
350 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
351 name = "Spatial Filter";
352 break;
353 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
354 name = "Spatial Luma Filter Type";
355 break;
356 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
357 name = "Spatial Chroma Filter Type";
358 break;
359 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
360 name = "Temporal Filter Mode";
361 break;
362 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
363 name = "Temporal Filter";
364 break;
365 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
366 name = "Median Filter Type";
367 break;
368 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
369 name = "Median Luma Filter Maximum";
370 break;
371 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
372 name = "Median Luma Filter Minimum";
373 break;
374 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
375 name = "Median Chroma Filter Maximum";
376 break;
377 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
378 name = "Median Chroma Filter Minimum";
379 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300380 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
381 name = "Insert Navigation Packets";
382 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300383
384 default:
385 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
386 }
387 switch (qctrl->id) {
388 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
389 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
390 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
391 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
392 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
393 qctrl->type = V4L2_CTRL_TYPE_MENU;
394 min = 0;
395 step = 1;
396 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300397 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
398 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
399 min = 0;
400 max = 1;
401 step = 1;
402 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300403 default:
404 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
405 break;
406 }
407 switch (qctrl->id) {
408 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
409 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
410 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
411 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
412 break;
413 }
414 qctrl->minimum = min;
415 qctrl->maximum = max;
416 qctrl->step = step;
417 qctrl->default_value = def;
418 qctrl->reserved[0] = qctrl->reserved[1] = 0;
419 snprintf(qctrl->name, sizeof(qctrl->name), name);
420 return 0;
421}
422
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300423int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
Hans Verkuil737bd412007-11-01 13:38:12 -0300424 struct v4l2_queryctrl *qctrl)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300425{
426 int err;
427
428 switch (qctrl->id) {
429 case V4L2_CID_MPEG_AUDIO_ENCODING:
430 return v4l2_ctrl_query_fill(qctrl,
431 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
432 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
433 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
434
435 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
436 return v4l2_ctrl_query_fill(qctrl,
437 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
438 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
439 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
440
441 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
442 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
443 return -EINVAL;
444
445 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
446 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300447 if (err == 0 &&
448 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300449 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
450 return err;
451
452 case V4L2_CID_MPEG_VIDEO_ENCODING:
453 /* this setting is read-only for the cx2341x since the
454 V4L2_CID_MPEG_STREAM_TYPE really determines the
455 MPEG-1/2 setting */
456 err = v4l2_ctrl_query_fill_std(qctrl);
457 if (err == 0)
458 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
459 return err;
460
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300461 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
462 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300463 if (err == 0 &&
464 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300465 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
466 return err;
467
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300468 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
469 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300470 if (err == 0 &&
471 params->video_bitrate_mode ==
472 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300473 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
474 return err;
475
Hans Verkuil8cbde942006-06-24 14:36:02 -0300476 case V4L2_CID_MPEG_STREAM_VBI_FMT:
477 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
478 return v4l2_ctrl_query_fill_std(qctrl);
479 return cx2341x_ctrl_query_fill(qctrl,
480 V4L2_MPEG_STREAM_VBI_FMT_NONE,
481 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
482 V4L2_MPEG_STREAM_VBI_FMT_NONE);
483
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300484 /* CX23415/6 specific */
485 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
486 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300487 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
488 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
489 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300490
491 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
492 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
493 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300494 if (params->video_spatial_filter_mode ==
495 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
496 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300497 return 0;
498
499 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
500 cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300501 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
502 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
503 1,
504 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
505 if (params->video_spatial_filter_mode ==
506 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
507 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300508 return 0;
509
510 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
511 cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300512 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
513 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
514 1,
515 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
516 if (params->video_spatial_filter_mode ==
517 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
518 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300519 return 0;
520
521 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
522 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300523 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
524 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
525 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300526
527 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
528 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
529 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300530 if (params->video_temporal_filter_mode ==
531 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
532 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300533 return 0;
534
535 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
536 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300537 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
538 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
539 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300540
541 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
542 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
543 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300544 if (params->video_median_filter_type ==
545 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
546 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300547 return 0;
548
549 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
550 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
551 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300552 if (params->video_median_filter_type ==
553 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
554 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300555 return 0;
556
557 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
558 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
559 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300560 if (params->video_median_filter_type ==
561 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
562 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300563 return 0;
564
565 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
566 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
567 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300568 if (params->video_median_filter_type ==
569 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
570 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300571 return 0;
572
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300573 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
574 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
575
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300576 default:
577 return v4l2_ctrl_query_fill_std(qctrl);
578
579 }
580}
Hans Verkuil737bd412007-11-01 13:38:12 -0300581EXPORT_SYMBOL(cx2341x_ctrl_query);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300582
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300583const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300584{
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300585 static const char *mpeg_stream_type_without_ts[] = {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300586 "MPEG-2 Program Stream",
587 "",
588 "MPEG-1 System Stream",
589 "MPEG-2 DVD-compatible Stream",
590 "MPEG-1 VCD-compatible Stream",
591 "MPEG-2 SVCD-compatible Stream",
592 NULL
593 };
594
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300595 static const char *mpeg_stream_type_with_ts[] = {
596 "MPEG-2 Program Stream",
597 "MPEG-2 Transport Stream",
598 "MPEG-1 System Stream",
599 "MPEG-2 DVD-compatible Stream",
600 "MPEG-1 VCD-compatible Stream",
601 "MPEG-2 SVCD-compatible Stream",
602 NULL
603 };
604
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300605 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
606 "Manual",
607 "Auto",
608 NULL
609 };
610
611 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
612 "Off",
613 "1D Horizontal",
614 "1D Vertical",
615 "2D H/V Separable",
616 "2D Symmetric non-separable",
617 NULL
618 };
619
620 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
621 "Off",
622 "1D Horizontal",
623 NULL
624 };
625
626 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
627 "Manual",
628 "Auto",
629 NULL
630 };
631
632 static const char *cx2341x_video_median_filter_type_menu[] = {
633 "Off",
634 "Horizontal",
635 "Vertical",
636 "Horizontal/Vertical",
637 "Diagonal",
638 NULL
639 };
640
641 switch (id) {
642 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300643 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
644 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300645 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
646 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
647 return NULL;
648 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
649 return cx2341x_video_spatial_filter_mode_menu;
650 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
651 return cx2341x_video_luma_spatial_filter_type_menu;
652 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
653 return cx2341x_video_chroma_spatial_filter_type_menu;
654 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
655 return cx2341x_video_temporal_filter_mode_menu;
656 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
657 return cx2341x_video_median_filter_type_menu;
658 default:
659 return v4l2_ctrl_get_menu(id);
660 }
661}
Hans Verkuil737bd412007-11-01 13:38:12 -0300662EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300663
664static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
665{
666 params->audio_properties = (params->audio_sampling_freq << 0) |
667 ((3 - params->audio_encoding) << 2) |
668 ((1 + params->audio_l2_bitrate) << 4) |
669 (params->audio_mode << 8) |
670 (params->audio_mode_extension << 10) |
Hans Verkuil737bd412007-11-01 13:38:12 -0300671 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
672 ? 3 : params->audio_emphasis) << 12) |
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300673 (params->audio_crc << 14);
674}
675
Hans Verkuil01f1e442007-08-21 18:32:42 -0300676int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300677 struct v4l2_ext_controls *ctrls, unsigned int cmd)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300678{
679 int err = 0;
680 int i;
681
682 if (cmd == VIDIOC_G_EXT_CTRLS) {
683 for (i = 0; i < ctrls->count; i++) {
684 struct v4l2_ext_control *ctrl = ctrls->controls + i;
685
686 err = cx2341x_get_ctrl(params, ctrl);
687 if (err) {
688 ctrls->error_idx = i;
689 break;
690 }
691 }
692 return err;
693 }
694 for (i = 0; i < ctrls->count; i++) {
695 struct v4l2_ext_control *ctrl = ctrls->controls + i;
696 struct v4l2_queryctrl qctrl;
697 const char **menu_items = NULL;
698
699 qctrl.id = ctrl->id;
700 err = cx2341x_ctrl_query(params, &qctrl);
701 if (err)
702 break;
703 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300704 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300705 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
706 if (err)
707 break;
Hans Verkuil01f1e442007-08-21 18:32:42 -0300708 err = cx2341x_set_ctrl(params, busy, ctrl);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300709 if (err)
710 break;
711 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300712 if (err == 0 &&
713 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
714 params->video_bitrate_peak < params->video_bitrate) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300715 err = -ERANGE;
716 ctrls->error_idx = ctrls->count;
717 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300718 if (err)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300719 ctrls->error_idx = i;
Hans Verkuil737bd412007-11-01 13:38:12 -0300720 else
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300721 cx2341x_calc_audio_properties(params);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300722 return err;
723}
Hans Verkuil737bd412007-11-01 13:38:12 -0300724EXPORT_SYMBOL(cx2341x_ext_ctrls);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300725
726void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
727{
728 static struct cx2341x_mpeg_params default_params = {
729 /* misc */
Hans Verkuil8cbde942006-06-24 14:36:02 -0300730 .capabilities = 0,
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300731 .port = CX2341X_PORT_MEMORY,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300732 .width = 720,
733 .height = 480,
734 .is_50hz = 0,
735
736 /* stream */
737 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
Hans Verkuil8cbde942006-06-24 14:36:02 -0300738 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300739 .stream_insert_nav_packets = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300740
741 /* audio */
742 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
743 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
744 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
745 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
746 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
747 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
748 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300749 .audio_mute = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300750
751 /* video */
752 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
753 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
754 .video_b_frames = 2,
755 .video_gop_size = 12,
756 .video_gop_closure = 1,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300757 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
758 .video_bitrate = 6000000,
759 .video_bitrate_peak = 8000000,
760 .video_temporal_decimation = 0,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300761 .video_mute = 0,
762 .video_mute_yuv = 0x008080, /* YCbCr value for black */
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300763
764 /* encoding filters */
Hans Verkuil737bd412007-11-01 13:38:12 -0300765 .video_spatial_filter_mode =
766 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300767 .video_spatial_filter = 0,
Hans Verkuil737bd412007-11-01 13:38:12 -0300768 .video_luma_spatial_filter_type =
769 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
770 .video_chroma_spatial_filter_type =
771 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
772 .video_temporal_filter_mode =
773 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300774 .video_temporal_filter = 8,
Hans Verkuil737bd412007-11-01 13:38:12 -0300775 .video_median_filter_type =
776 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300777 .video_luma_median_filter_top = 255,
778 .video_luma_median_filter_bottom = 0,
779 .video_chroma_median_filter_top = 255,
780 .video_chroma_median_filter_bottom = 0,
781 };
782
783 *p = default_params;
784 cx2341x_calc_audio_properties(p);
785}
Hans Verkuil737bd412007-11-01 13:38:12 -0300786EXPORT_SYMBOL(cx2341x_fill_defaults);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300787
Hans Verkuil737bd412007-11-01 13:38:12 -0300788static int cx2341x_api(void *priv, cx2341x_mbox_func func,
Hans Verkuilea48c132007-12-12 07:04:58 -0300789 u32 cmd, int args, ...)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300790{
791 u32 data[CX2341X_MBOX_MAX_DATA];
792 va_list vargs;
793 int i;
794
795 va_start(vargs, args);
796
Hans Verkuil737bd412007-11-01 13:38:12 -0300797 for (i = 0; i < args; i++)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300798 data[i] = va_arg(vargs, int);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300799 va_end(vargs);
800 return func(priv, cmd, args, 0, data);
801}
802
Hans Verkuil737bd412007-11-01 13:38:12 -0300803#define NEQ(field) (old->field != new->field)
804
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300805int cx2341x_update(void *priv, cx2341x_mbox_func func,
Hans Verkuil737bd412007-11-01 13:38:12 -0300806 const struct cx2341x_mpeg_params *old,
807 const struct cx2341x_mpeg_params *new)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300808{
809 static int mpeg_stream_type[] = {
810 0, /* MPEG-2 PS */
811 1, /* MPEG-2 TS */
812 2, /* MPEG-1 SS */
813 14, /* DVD */
814 11, /* VCD */
815 12, /* SVCD */
816 };
817
818 int err = 0;
Hans Verkuil737bd412007-11-01 13:38:12 -0300819 int force = (old == NULL);
Hans Verkuil44b579d2006-08-27 19:22:15 -0300820 u16 temporal = new->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300821
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300822 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300823
Hans Verkuil737bd412007-11-01 13:38:12 -0300824 if (force || NEQ(is_50hz)) {
825 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
826 new->is_50hz);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300827 if (err) return err;
828 }
829
Hans Verkuil737bd412007-11-01 13:38:12 -0300830 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300831 u16 w = new->width;
832 u16 h = new->height;
833
834 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
835 w /= 2;
836 h /= 2;
837 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300838 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
839 h, w);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300840 if (err) return err;
Hans Verkuil12b896e2006-12-18 13:37:50 -0300841 }
Hans Verkuil44b579d2006-08-27 19:22:15 -0300842
Hans Verkuil12b896e2006-12-18 13:37:50 -0300843 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
Hans Verkuil737bd412007-11-01 13:38:12 -0300844 /* Adjust temporal filter if necessary. The problem with the
845 temporal filter is that it works well with full resolution
846 capturing, but not when the capture window is scaled (the
847 filter introduces a ghosting effect). So if the capture
848 window is scaled, then force the filter to 0.
Hans Verkuil44b579d2006-08-27 19:22:15 -0300849
Hans Verkuil12b896e2006-12-18 13:37:50 -0300850 For full resolution the filter really improves the video
Hans Verkuil737bd412007-11-01 13:38:12 -0300851 quality, especially if the original video quality is
852 suboptimal. */
Hans Verkuil12b896e2006-12-18 13:37:50 -0300853 temporal = 0;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300854 }
855
Hans Verkuil737bd412007-11-01 13:38:12 -0300856 if (force || NEQ(stream_type)) {
857 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
858 mpeg_stream_type[new->stream_type]);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300859 if (err) return err;
860 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300861 if (force || NEQ(video_aspect)) {
862 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
863 1 + new->video_aspect);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300864 if (err) return err;
865 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300866 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300867 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
868 new->video_gop_size, new->video_b_frames + 1);
869 if (err) return err;
870 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300871 if (force || NEQ(video_gop_closure)) {
872 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
873 new->video_gop_closure);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300874 if (err) return err;
875 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300876 if (force || NEQ(audio_properties)) {
877 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
878 1, new->audio_properties);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300879 if (err) return err;
880 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300881 if (force || NEQ(audio_mute)) {
882 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
883 new->audio_mute);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300884 if (err) return err;
885 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300886 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
887 NEQ(video_bitrate_peak)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300888 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
889 new->video_bitrate_mode, new->video_bitrate,
890 new->video_bitrate_peak / 400, 0, 0);
891 if (err) return err;
892 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300893 if (force || NEQ(video_spatial_filter_mode) ||
894 NEQ(video_temporal_filter_mode) ||
895 NEQ(video_median_filter_type)) {
896 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
897 2, new->video_spatial_filter_mode |
898 (new->video_temporal_filter_mode << 1),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300899 new->video_median_filter_type);
900 if (err) return err;
901 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300902 if (force || NEQ(video_luma_median_filter_bottom) ||
903 NEQ(video_luma_median_filter_top) ||
904 NEQ(video_chroma_median_filter_bottom) ||
905 NEQ(video_chroma_median_filter_top)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300906 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
907 new->video_luma_median_filter_bottom,
908 new->video_luma_median_filter_top,
909 new->video_chroma_median_filter_bottom,
910 new->video_chroma_median_filter_top);
911 if (err) return err;
912 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300913 if (force || NEQ(video_luma_spatial_filter_type) ||
914 NEQ(video_chroma_spatial_filter_type)) {
915 err = cx2341x_api(priv, func,
916 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
917 2, new->video_luma_spatial_filter_type,
918 new->video_chroma_spatial_filter_type);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300919 if (err) return err;
920 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300921 if (force || NEQ(video_spatial_filter) ||
922 old->video_temporal_filter != temporal) {
923 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
924 2, new->video_spatial_filter, temporal);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300925 if (err) return err;
926 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300927 if (force || NEQ(video_temporal_decimation)) {
928 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
929 1, new->video_temporal_decimation);
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_mute) ||
933 (new->video_mute && NEQ(video_mute_yuv))) {
934 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
935 new->video_mute | (new->video_mute_yuv << 8));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300936 if (err) return err;
937 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300938 if (force || NEQ(stream_insert_nav_packets)) {
939 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
940 7, new->stream_insert_nav_packets);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300941 if (err) return err;
942 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300943 return 0;
944}
Hans Verkuil737bd412007-11-01 13:38:12 -0300945EXPORT_SYMBOL(cx2341x_update);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300946
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300947static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300948{
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300949 const char **menu = cx2341x_ctrl_get_menu(p, id);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300950 struct v4l2_ext_control ctrl;
951
952 if (menu == NULL)
953 goto invalid;
954 ctrl.id = id;
955 if (cx2341x_get_ctrl(p, &ctrl))
956 goto invalid;
957 while (ctrl.value-- && *menu) menu++;
958 if (*menu == NULL)
959 goto invalid;
960 return *menu;
961
962invalid:
963 return "<invalid>";
964}
965
Hans Verkuile0e31cd2008-06-22 12:03:28 -0300966void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300967{
968 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
Hans Verkuil83aaf132006-12-18 13:40:23 -0300969 int temporal = p->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300970
971 /* Stream */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300972 printk(KERN_INFO "%s: Stream: %s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300973 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300974 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300975 if (p->stream_insert_nav_packets)
976 printk(" (with navigation packets)");
977 printk("\n");
Hans Verkuil44b579d2006-08-27 19:22:15 -0300978 printk(KERN_INFO "%s: VBI Format: %s\n",
979 prefix,
980 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300981
982 /* Video */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300983 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300984 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300985 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300986 p->is_50hz ? 25 : 30,
987 (p->video_mute) ? " (muted)" : "");
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300988 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
989 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300990 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
991 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
992 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
993 p->video_bitrate);
Hans Verkuil737bd412007-11-01 13:38:12 -0300994 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300995 printk(", Peak %d", p->video_bitrate_peak);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300996 printk("\n");
Hans Verkuil737bd412007-11-01 13:38:12 -0300997 printk(KERN_INFO
998 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300999 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001000 p->video_gop_size, p->video_b_frames,
Hans Verkuil75558ab2006-12-18 22:52:21 -03001001 p->video_gop_closure ? "" : "No ");
Hans Verkuil737bd412007-11-01 13:38:12 -03001002 if (p->video_temporal_decimation)
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001003 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1004 prefix, p->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001005
1006 /* Audio */
Hans Verkuil5eee72e2007-04-27 12:31:00 -03001007 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001008 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001009 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1010 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1011 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
Hans Verkuil5eee72e2007-04-27 12:31:00 -03001012 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1013 p->audio_mute ? " (muted)" : "");
Hans Verkuil737bd412007-11-01 13:38:12 -03001014 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1015 printk(", %s", cx2341x_menu_item(p,
1016 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001017 printk(", %s, %s\n",
1018 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1019 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1020
1021 /* Encoding filters */
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001022 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1023 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001024 cx2341x_menu_item(p,
1025 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1026 cx2341x_menu_item(p,
1027 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1028 cx2341x_menu_item(p,
1029 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001030 p->video_spatial_filter);
Hans Verkuil737bd412007-11-01 13:38:12 -03001031
1032 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
Hans Verkuil83aaf132006-12-18 13:40:23 -03001033 temporal = 0;
Hans Verkuil737bd412007-11-01 13:38:12 -03001034
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001035 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1036 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001037 cx2341x_menu_item(p,
1038 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
Hans Verkuil83aaf132006-12-18 13:40:23 -03001039 temporal);
Hans Verkuil737bd412007-11-01 13:38:12 -03001040 printk(KERN_INFO
1041 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001042 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001043 cx2341x_menu_item(p,
1044 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001045 p->video_luma_median_filter_bottom,
1046 p->video_luma_median_filter_top,
1047 p->video_chroma_median_filter_bottom,
1048 p->video_chroma_median_filter_top);
1049}
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001050EXPORT_SYMBOL(cx2341x_log_status);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001051
1052/*
1053 * Local variables:
1054 * c-basic-offset: 8
1055 * End:
1056 */
1057