1/* 2 * cx2341x - generic code for cx23415/6/8 based devices 3 * 4 * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 22#include <linux/module.h> 23#include <linux/errno.h> 24#include <linux/kernel.h> 25#include <linux/init.h> 26#include <linux/types.h> 27#include <linux/videodev2.h> 28 29#include <media/tuner.h> 30#include <media/cx2341x.h> 31#include <media/v4l2-common.h> 32 33MODULE_DESCRIPTION("cx23415/6/8 driver"); 34MODULE_AUTHOR("Hans Verkuil"); 35MODULE_LICENSE("GPL"); 36 37static int debug; 38module_param(debug, int, 0644); 39MODULE_PARM_DESC(debug, "Debug level (0-1)"); 40 41/********************** COMMON CODE *********************/ 42 43/* definitions for audio properties bits 29-28 */ 44#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0 45#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1 46#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2 47 48static const char *cx2341x_get_name(u32 id) 49{ 50 switch (id) { 51 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 52 return "Spatial Filter Mode"; 53 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 54 return "Spatial Filter"; 55 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 56 return "Spatial Luma Filter Type"; 57 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 58 return "Spatial Chroma Filter Type"; 59 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 60 return "Temporal Filter Mode"; 61 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 62 return "Temporal Filter"; 63 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 64 return "Median Filter Type"; 65 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 66 return "Median Luma Filter Maximum"; 67 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 68 return "Median Luma Filter Minimum"; 69 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 70 return "Median Chroma Filter Maximum"; 71 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 72 return "Median Chroma Filter Minimum"; 73 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 74 return "Insert Navigation Packets"; 75 } 76 return NULL; 77} 78 79static const char **cx2341x_get_menu(u32 id) 80{ 81 static const char *cx2341x_video_spatial_filter_mode_menu[] = { 82 "Manual", 83 "Auto", 84 NULL 85 }; 86 87 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { 88 "Off", 89 "1D Horizontal", 90 "1D Vertical", 91 "2D H/V Separable", 92 "2D Symmetric non-separable", 93 NULL 94 }; 95 96 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { 97 "Off", 98 "1D Horizontal", 99 NULL 100 }; 101 102 static const char *cx2341x_video_temporal_filter_mode_menu[] = { 103 "Manual", 104 "Auto", 105 NULL 106 }; 107 108 static const char *cx2341x_video_median_filter_type_menu[] = { 109 "Off", 110 "Horizontal", 111 "Vertical", 112 "Horizontal/Vertical", 113 "Diagonal", 114 NULL 115 }; 116 117 switch (id) { 118 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 119 return cx2341x_video_spatial_filter_mode_menu; 120 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 121 return cx2341x_video_luma_spatial_filter_type_menu; 122 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 123 return cx2341x_video_chroma_spatial_filter_type_menu; 124 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 125 return cx2341x_video_temporal_filter_mode_menu; 126 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 127 return cx2341x_video_median_filter_type_menu; 128 } 129 return NULL; 130} 131 132static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, 133 s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags) 134{ 135 *name = cx2341x_get_name(id); 136 *flags = 0; 137 138 switch (id) { 139 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 140 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 141 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 142 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 143 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 144 *type = V4L2_CTRL_TYPE_MENU; 145 *min = 0; 146 *step = 0; 147 break; 148 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 149 *type = V4L2_CTRL_TYPE_BOOLEAN; 150 *min = 0; 151 *max = *step = 1; 152 break; 153 default: 154 *type = V4L2_CTRL_TYPE_INTEGER; 155 break; 156 } 157 switch (id) { 158 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 159 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 160 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 161 *flags |= V4L2_CTRL_FLAG_UPDATE; 162 break; 163 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 164 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 165 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 166 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 167 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 168 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 169 *flags |= V4L2_CTRL_FLAG_SLIDER; 170 break; 171 case V4L2_CID_MPEG_VIDEO_ENCODING: 172 *flags |= V4L2_CTRL_FLAG_READ_ONLY; 173 break; 174 } 175} 176 177 178/********************** OLD CODE *********************/ 179 180/* Must be sorted from low to high control ID! */ 181const u32 cx2341x_mpeg_ctrls[] = { 182 V4L2_CID_MPEG_CLASS, 183 V4L2_CID_MPEG_STREAM_TYPE, 184 V4L2_CID_MPEG_STREAM_VBI_FMT, 185 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, 186 V4L2_CID_MPEG_AUDIO_ENCODING, 187 V4L2_CID_MPEG_AUDIO_L2_BITRATE, 188 V4L2_CID_MPEG_AUDIO_MODE, 189 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, 190 V4L2_CID_MPEG_AUDIO_EMPHASIS, 191 V4L2_CID_MPEG_AUDIO_CRC, 192 V4L2_CID_MPEG_AUDIO_MUTE, 193 V4L2_CID_MPEG_AUDIO_AC3_BITRATE, 194 V4L2_CID_MPEG_VIDEO_ENCODING, 195 V4L2_CID_MPEG_VIDEO_ASPECT, 196 V4L2_CID_MPEG_VIDEO_B_FRAMES, 197 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 198 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 199 V4L2_CID_MPEG_VIDEO_BITRATE_MODE, 200 V4L2_CID_MPEG_VIDEO_BITRATE, 201 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 202 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 203 V4L2_CID_MPEG_VIDEO_MUTE, 204 V4L2_CID_MPEG_VIDEO_MUTE_YUV, 205 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, 206 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, 207 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, 208 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, 209 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, 210 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, 211 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, 212 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, 213 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, 214 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, 215 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, 216 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS, 217 0 218}; 219EXPORT_SYMBOL(cx2341x_mpeg_ctrls); 220 221static const struct cx2341x_mpeg_params default_params = { 222 /* misc */ 223 .capabilities = 0, 224 .port = CX2341X_PORT_MEMORY, 225 .width = 720, 226 .height = 480, 227 .is_50hz = 0, 228 229 /* stream */ 230 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS, 231 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE, 232 .stream_insert_nav_packets = 0, 233 234 /* audio */ 235 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 236 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 237 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K, 238 .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K, 239 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO, 240 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, 241 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE, 242 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE, 243 .audio_mute = 0, 244 245 /* video */ 246 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 247 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, 248 .video_b_frames = 2, 249 .video_gop_size = 12, 250 .video_gop_closure = 1, 251 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, 252 .video_bitrate = 6000000, 253 .video_bitrate_peak = 8000000, 254 .video_temporal_decimation = 0, 255 .video_mute = 0, 256 .video_mute_yuv = 0x008080, /* YCbCr value for black */ 257 258 /* encoding filters */ 259 .video_spatial_filter_mode = 260 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 261 .video_spatial_filter = 0, 262 .video_luma_spatial_filter_type = 263 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR, 264 .video_chroma_spatial_filter_type = 265 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 266 .video_temporal_filter_mode = 267 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 268 .video_temporal_filter = 8, 269 .video_median_filter_type = 270 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 271 .video_luma_median_filter_top = 255, 272 .video_luma_median_filter_bottom = 0, 273 .video_chroma_median_filter_top = 255, 274 .video_chroma_median_filter_bottom = 0, 275}; 276/* Map the control ID to the correct field in the cx2341x_mpeg_params 277 struct. Return -EINVAL if the ID is unknown, else return 0. */ 278static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params, 279 struct v4l2_ext_control *ctrl) 280{ 281 switch (ctrl->id) { 282 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 283 ctrl->value = params->audio_sampling_freq; 284 break; 285 case V4L2_CID_MPEG_AUDIO_ENCODING: 286 ctrl->value = params->audio_encoding; 287 break; 288 case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 289 ctrl->value = params->audio_l2_bitrate; 290 break; 291 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 292 ctrl->value = params->audio_ac3_bitrate; 293 break; 294 case V4L2_CID_MPEG_AUDIO_MODE: 295 ctrl->value = params->audio_mode; 296 break; 297 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 298 ctrl->value = params->audio_mode_extension; 299 break; 300 case V4L2_CID_MPEG_AUDIO_EMPHASIS: 301 ctrl->value = params->audio_emphasis; 302 break; 303 case V4L2_CID_MPEG_AUDIO_CRC: 304 ctrl->value = params->audio_crc; 305 break; 306 case V4L2_CID_MPEG_AUDIO_MUTE: 307 ctrl->value = params->audio_mute; 308 break; 309 case V4L2_CID_MPEG_VIDEO_ENCODING: 310 ctrl->value = params->video_encoding; 311 break; 312 case V4L2_CID_MPEG_VIDEO_ASPECT: 313 ctrl->value = params->video_aspect; 314 break; 315 case V4L2_CID_MPEG_VIDEO_B_FRAMES: 316 ctrl->value = params->video_b_frames; 317 break; 318 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 319 ctrl->value = params->video_gop_size; 320 break; 321 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 322 ctrl->value = params->video_gop_closure; 323 break; 324 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 325 ctrl->value = params->video_bitrate_mode; 326 break; 327 case V4L2_CID_MPEG_VIDEO_BITRATE: 328 ctrl->value = params->video_bitrate; 329 break; 330 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 331 ctrl->value = params->video_bitrate_peak; 332 break; 333 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 334 ctrl->value = params->video_temporal_decimation; 335 break; 336 case V4L2_CID_MPEG_VIDEO_MUTE: 337 ctrl->value = params->video_mute; 338 break; 339 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: 340 ctrl->value = params->video_mute_yuv; 341 break; 342 case V4L2_CID_MPEG_STREAM_TYPE: 343 ctrl->value = params->stream_type; 344 break; 345 case V4L2_CID_MPEG_STREAM_VBI_FMT: 346 ctrl->value = params->stream_vbi_fmt; 347 break; 348 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 349 ctrl->value = params->video_spatial_filter_mode; 350 break; 351 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 352 ctrl->value = params->video_spatial_filter; 353 break; 354 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 355 ctrl->value = params->video_luma_spatial_filter_type; 356 break; 357 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 358 ctrl->value = params->video_chroma_spatial_filter_type; 359 break; 360 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 361 ctrl->value = params->video_temporal_filter_mode; 362 break; 363 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 364 ctrl->value = params->video_temporal_filter; 365 break; 366 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 367 ctrl->value = params->video_median_filter_type; 368 break; 369 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 370 ctrl->value = params->video_luma_median_filter_top; 371 break; 372 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 373 ctrl->value = params->video_luma_median_filter_bottom; 374 break; 375 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 376 ctrl->value = params->video_chroma_median_filter_top; 377 break; 378 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 379 ctrl->value = params->video_chroma_median_filter_bottom; 380 break; 381 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 382 ctrl->value = params->stream_insert_nav_packets; 383 break; 384 default: 385 return -EINVAL; 386 } 387 return 0; 388} 389 390/* Map the control ID to the correct field in the cx2341x_mpeg_params 391 struct. Return -EINVAL if the ID is unknown, else return 0. */ 392static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, 393 struct v4l2_ext_control *ctrl) 394{ 395 switch (ctrl->id) { 396 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 397 if (busy) 398 return -EBUSY; 399 params->audio_sampling_freq = ctrl->value; 400 break; 401 case V4L2_CID_MPEG_AUDIO_ENCODING: 402 if (busy) 403 return -EBUSY; 404 if (params->capabilities & CX2341X_CAP_HAS_AC3) 405 if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && 406 ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3) 407 return -ERANGE; 408 params->audio_encoding = ctrl->value; 409 break; 410 case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 411 if (busy) 412 return -EBUSY; 413 params->audio_l2_bitrate = ctrl->value; 414 break; 415 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 416 if (busy) 417 return -EBUSY; 418 if (!(params->capabilities & CX2341X_CAP_HAS_AC3)) 419 return -EINVAL; 420 params->audio_ac3_bitrate = ctrl->value; 421 break; 422 case V4L2_CID_MPEG_AUDIO_MODE: 423 params->audio_mode = ctrl->value; 424 break; 425 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 426 params->audio_mode_extension = ctrl->value; 427 break; 428 case V4L2_CID_MPEG_AUDIO_EMPHASIS: 429 params->audio_emphasis = ctrl->value; 430 break; 431 case V4L2_CID_MPEG_AUDIO_CRC: 432 params->audio_crc = ctrl->value; 433 break; 434 case V4L2_CID_MPEG_AUDIO_MUTE: 435 params->audio_mute = ctrl->value; 436 break; 437 case V4L2_CID_MPEG_VIDEO_ASPECT: 438 params->video_aspect = ctrl->value; 439 break; 440 case V4L2_CID_MPEG_VIDEO_B_FRAMES: { 441 int b = ctrl->value + 1; 442 int gop = params->video_gop_size; 443 params->video_b_frames = ctrl->value; 444 params->video_gop_size = b * ((gop + b - 1) / b); 445 /* Max GOP size = 34 */ 446 while (params->video_gop_size > 34) 447 params->video_gop_size -= b; 448 break; 449 } 450 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: { 451 int b = params->video_b_frames + 1; 452 int gop = ctrl->value; 453 params->video_gop_size = b * ((gop + b - 1) / b); 454 /* Max GOP size = 34 */ 455 while (params->video_gop_size > 34) 456 params->video_gop_size -= b; 457 ctrl->value = params->video_gop_size; 458 break; 459 } 460 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 461 params->video_gop_closure = ctrl->value; 462 break; 463 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 464 if (busy) 465 return -EBUSY; 466 /* MPEG-1 only allows CBR */ 467 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && 468 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) 469 return -EINVAL; 470 params->video_bitrate_mode = ctrl->value; 471 break; 472 case V4L2_CID_MPEG_VIDEO_BITRATE: 473 if (busy) 474 return -EBUSY; 475 params->video_bitrate = ctrl->value; 476 break; 477 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 478 if (busy) 479 return -EBUSY; 480 params->video_bitrate_peak = ctrl->value; 481 break; 482 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 483 params->video_temporal_decimation = ctrl->value; 484 break; 485 case V4L2_CID_MPEG_VIDEO_MUTE: 486 params->video_mute = (ctrl->value != 0); 487 break; 488 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: 489 params->video_mute_yuv = ctrl->value; 490 break; 491 case V4L2_CID_MPEG_STREAM_TYPE: 492 if (busy) 493 return -EBUSY; 494 params->stream_type = ctrl->value; 495 params->video_encoding = 496 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || 497 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? 498 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : 499 V4L2_MPEG_VIDEO_ENCODING_MPEG_2; 500 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 501 /* MPEG-1 implies CBR */ 502 params->video_bitrate_mode = 503 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; 504 break; 505 case V4L2_CID_MPEG_STREAM_VBI_FMT: 506 params->stream_vbi_fmt = ctrl->value; 507 break; 508 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 509 params->video_spatial_filter_mode = ctrl->value; 510 break; 511 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 512 params->video_spatial_filter = ctrl->value; 513 break; 514 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 515 params->video_luma_spatial_filter_type = ctrl->value; 516 break; 517 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 518 params->video_chroma_spatial_filter_type = ctrl->value; 519 break; 520 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 521 params->video_temporal_filter_mode = ctrl->value; 522 break; 523 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 524 params->video_temporal_filter = ctrl->value; 525 break; 526 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 527 params->video_median_filter_type = ctrl->value; 528 break; 529 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 530 params->video_luma_median_filter_top = ctrl->value; 531 break; 532 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 533 params->video_luma_median_filter_bottom = ctrl->value; 534 break; 535 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 536 params->video_chroma_median_filter_top = ctrl->value; 537 break; 538 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 539 params->video_chroma_median_filter_bottom = ctrl->value; 540 break; 541 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 542 params->stream_insert_nav_packets = ctrl->value; 543 break; 544 default: 545 return -EINVAL; 546 } 547 return 0; 548} 549 550static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, 551 s32 min, s32 max, s32 step, s32 def) 552{ 553 const char *name; 554 555 switch (qctrl->id) { 556 /* MPEG controls */ 557 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 558 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 559 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 560 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 561 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 562 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 563 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 564 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 565 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 566 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 567 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 568 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 569 cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type, 570 &min, &max, &step, &def, &qctrl->flags); 571 qctrl->minimum = min; 572 qctrl->maximum = max; 573 qctrl->step = step; 574 qctrl->default_value = def; 575 qctrl->reserved[0] = qctrl->reserved[1] = 0; 576 strlcpy(qctrl->name, name, sizeof(qctrl->name)); 577 return 0; 578 579 default: 580 return v4l2_ctrl_query_fill(qctrl, min, max, step, def); 581 } 582} 583 584int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, 585 struct v4l2_queryctrl *qctrl) 586{ 587 int err; 588 589 switch (qctrl->id) { 590 case V4L2_CID_MPEG_CLASS: 591 return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); 592 case V4L2_CID_MPEG_STREAM_TYPE: 593 return v4l2_ctrl_query_fill(qctrl, 594 V4L2_MPEG_STREAM_TYPE_MPEG2_PS, 595 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, 596 V4L2_MPEG_STREAM_TYPE_MPEG2_PS); 597 598 case V4L2_CID_MPEG_STREAM_VBI_FMT: 599 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) 600 return v4l2_ctrl_query_fill(qctrl, 601 V4L2_MPEG_STREAM_VBI_FMT_NONE, 602 V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, 603 V4L2_MPEG_STREAM_VBI_FMT_NONE); 604 return cx2341x_ctrl_query_fill(qctrl, 605 V4L2_MPEG_STREAM_VBI_FMT_NONE, 606 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, 607 default_params.stream_vbi_fmt); 608 609 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 610 return v4l2_ctrl_query_fill(qctrl, 611 V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, 612 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, 613 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); 614 615 case V4L2_CID_MPEG_AUDIO_ENCODING: 616 if (params->capabilities & CX2341X_CAP_HAS_AC3) { 617 /* 618 * The state of L2 & AC3 bitrate controls can change 619 * when this control changes, but v4l2_ctrl_query_fill() 620 * already sets V4L2_CTRL_FLAG_UPDATE for 621 * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here. 622 */ 623 return v4l2_ctrl_query_fill(qctrl, 624 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 625 V4L2_MPEG_AUDIO_ENCODING_AC3, 1, 626 default_params.audio_encoding); 627 } 628 629 return v4l2_ctrl_query_fill(qctrl, 630 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 631 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, 632 default_params.audio_encoding); 633 634 case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 635 err = v4l2_ctrl_query_fill(qctrl, 636 V4L2_MPEG_AUDIO_L2_BITRATE_192K, 637 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, 638 default_params.audio_l2_bitrate); 639 if (err) 640 return err; 641 if (params->capabilities & CX2341X_CAP_HAS_AC3 && 642 params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2) 643 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 644 return 0; 645 646 case V4L2_CID_MPEG_AUDIO_MODE: 647 return v4l2_ctrl_query_fill(qctrl, 648 V4L2_MPEG_AUDIO_MODE_STEREO, 649 V4L2_MPEG_AUDIO_MODE_MONO, 1, 650 V4L2_MPEG_AUDIO_MODE_STEREO); 651 652 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 653 err = v4l2_ctrl_query_fill(qctrl, 654 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, 655 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, 656 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); 657 if (err == 0 && 658 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) 659 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 660 return err; 661 662 case V4L2_CID_MPEG_AUDIO_EMPHASIS: 663 return v4l2_ctrl_query_fill(qctrl, 664 V4L2_MPEG_AUDIO_EMPHASIS_NONE, 665 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, 666 V4L2_MPEG_AUDIO_EMPHASIS_NONE); 667 668 case V4L2_CID_MPEG_AUDIO_CRC: 669 return v4l2_ctrl_query_fill(qctrl, 670 V4L2_MPEG_AUDIO_CRC_NONE, 671 V4L2_MPEG_AUDIO_CRC_CRC16, 1, 672 V4L2_MPEG_AUDIO_CRC_NONE); 673 674 case V4L2_CID_MPEG_AUDIO_MUTE: 675 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); 676 677 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 678 err = v4l2_ctrl_query_fill(qctrl, 679 V4L2_MPEG_AUDIO_AC3_BITRATE_48K, 680 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1, 681 default_params.audio_ac3_bitrate); 682 if (err) 683 return err; 684 if (params->capabilities & CX2341X_CAP_HAS_AC3) { 685 if (params->audio_encoding != 686 V4L2_MPEG_AUDIO_ENCODING_AC3) 687 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 688 } else 689 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; 690 return 0; 691 692 case V4L2_CID_MPEG_VIDEO_ENCODING: 693 /* this setting is read-only for the cx2341x since the 694 V4L2_CID_MPEG_STREAM_TYPE really determines the 695 MPEG-1/2 setting */ 696 err = v4l2_ctrl_query_fill(qctrl, 697 V4L2_MPEG_VIDEO_ENCODING_MPEG_1, 698 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, 699 V4L2_MPEG_VIDEO_ENCODING_MPEG_2); 700 if (err == 0) 701 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 702 return err; 703 704 case V4L2_CID_MPEG_VIDEO_ASPECT: 705 return v4l2_ctrl_query_fill(qctrl, 706 V4L2_MPEG_VIDEO_ASPECT_1x1, 707 V4L2_MPEG_VIDEO_ASPECT_221x100, 1, 708 V4L2_MPEG_VIDEO_ASPECT_4x3); 709 710 case V4L2_CID_MPEG_VIDEO_B_FRAMES: 711 return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); 712 713 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 714 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 715 params->is_50hz ? 12 : 15); 716 717 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 718 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); 719 720 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 721 err = v4l2_ctrl_query_fill(qctrl, 722 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, 723 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, 724 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 725 if (err == 0 && 726 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 727 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 728 return err; 729 730 case V4L2_CID_MPEG_VIDEO_BITRATE: 731 return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); 732 733 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 734 err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); 735 if (err == 0 && 736 params->video_bitrate_mode == 737 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) 738 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 739 return err; 740 741 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 742 return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); 743 744 case V4L2_CID_MPEG_VIDEO_MUTE: 745 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); 746 747 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */ 748 return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080); 749 750 /* CX23415/6 specific */ 751 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 752 return cx2341x_ctrl_query_fill(qctrl, 753 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 754 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1, 755 default_params.video_spatial_filter_mode); 756 757 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 758 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 759 default_params.video_spatial_filter); 760 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 761 if (params->video_spatial_filter_mode == 762 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 763 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 764 return 0; 765 766 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 767 cx2341x_ctrl_query_fill(qctrl, 768 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, 769 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 770 1, 771 default_params.video_luma_spatial_filter_type); 772 if (params->video_spatial_filter_mode == 773 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 774 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 775 return 0; 776 777 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 778 cx2341x_ctrl_query_fill(qctrl, 779 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, 780 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 781 1, 782 default_params.video_chroma_spatial_filter_type); 783 if (params->video_spatial_filter_mode == 784 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 785 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 786 return 0; 787 788 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 789 return cx2341x_ctrl_query_fill(qctrl, 790 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 791 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1, 792 default_params.video_temporal_filter_mode); 793 794 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 795 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 796 default_params.video_temporal_filter); 797 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 798 if (params->video_temporal_filter_mode == 799 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO) 800 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 801 return 0; 802 803 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 804 return cx2341x_ctrl_query_fill(qctrl, 805 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 806 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1, 807 default_params.video_median_filter_type); 808 809 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 810 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 811 default_params.video_luma_median_filter_top); 812 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 813 if (params->video_median_filter_type == 814 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 815 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 816 return 0; 817 818 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 819 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 820 default_params.video_luma_median_filter_bottom); 821 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 822 if (params->video_median_filter_type == 823 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 824 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 825 return 0; 826 827 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 828 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 829 default_params.video_chroma_median_filter_top); 830 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 831 if (params->video_median_filter_type == 832 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 833 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 834 return 0; 835 836 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 837 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 838 default_params.video_chroma_median_filter_bottom); 839 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 840 if (params->video_median_filter_type == 841 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 842 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 843 return 0; 844 845 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 846 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 847 default_params.stream_insert_nav_packets); 848 849 default: 850 return -EINVAL; 851 852 } 853} 854EXPORT_SYMBOL(cx2341x_ctrl_query); 855 856const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) 857{ 858 static const char * const mpeg_stream_type_without_ts[] = { 859 "MPEG-2 Program Stream", 860 "", 861 "MPEG-1 System Stream", 862 "MPEG-2 DVD-compatible Stream", 863 "MPEG-1 VCD-compatible Stream", 864 "MPEG-2 SVCD-compatible Stream", 865 NULL 866 }; 867 868 static const char *mpeg_stream_type_with_ts[] = { 869 "MPEG-2 Program Stream", 870 "MPEG-2 Transport Stream", 871 "MPEG-1 System Stream", 872 "MPEG-2 DVD-compatible Stream", 873 "MPEG-1 VCD-compatible Stream", 874 "MPEG-2 SVCD-compatible Stream", 875 NULL 876 }; 877 878 static const char *mpeg_audio_encoding_l2_ac3[] = { 879 "", 880 "MPEG-1/2 Layer II", 881 "", 882 "", 883 "AC-3", 884 NULL 885 }; 886 887 switch (id) { 888 case V4L2_CID_MPEG_STREAM_TYPE: 889 return (p->capabilities & CX2341X_CAP_HAS_TS) ? 890 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts; 891 case V4L2_CID_MPEG_AUDIO_ENCODING: 892 return (p->capabilities & CX2341X_CAP_HAS_AC3) ? 893 mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id); 894 case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 895 case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 896 return NULL; 897 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 898 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 899 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 900 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 901 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 902 return cx2341x_get_menu(id); 903 default: 904 return v4l2_ctrl_get_menu(id); 905 } 906} 907EXPORT_SYMBOL(cx2341x_ctrl_get_menu); 908 909static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) 910{ 911 params->audio_properties = 912 (params->audio_sampling_freq << 0) | 913 (params->audio_mode << 8) | 914 (params->audio_mode_extension << 10) | 915 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) 916 ? 3 : params->audio_emphasis) << 12) | 917 (params->audio_crc << 14); 918 919 if ((params->capabilities & CX2341X_CAP_HAS_AC3) && 920 params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { 921 params->audio_properties |= 922 /* Not sure if this MPEG Layer II setting is required */ 923 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | 924 (params->audio_ac3_bitrate << 4) | 925 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28); 926 } else { 927 /* Assuming MPEG Layer II */ 928 params->audio_properties |= 929 ((3 - params->audio_encoding) << 2) | 930 ((1 + params->audio_l2_bitrate) << 4); 931 } 932} 933 934/* Check for correctness of the ctrl's value based on the data from 935 struct v4l2_queryctrl and the available menu items. Note that 936 menu_items may be NULL, in that case it is ignored. */ 937static int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, 938 const char * const *menu_items) 939{ 940 if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) 941 return -EINVAL; 942 if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) 943 return -EBUSY; 944 if (qctrl->type == V4L2_CTRL_TYPE_STRING) 945 return 0; 946 if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || 947 qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || 948 qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) 949 return 0; 950 if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum) 951 return -ERANGE; 952 if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) { 953 if (menu_items[ctrl->value] == NULL || 954 menu_items[ctrl->value][0] == '\0') 955 return -EINVAL; 956 } 957 if (qctrl->type == V4L2_CTRL_TYPE_BITMASK && 958 (ctrl->value & ~qctrl->maximum)) 959 return -ERANGE; 960 return 0; 961} 962 963int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, 964 struct v4l2_ext_controls *ctrls, unsigned int cmd) 965{ 966 int err = 0; 967 int i; 968 969 if (cmd == VIDIOC_G_EXT_CTRLS) { 970 for (i = 0; i < ctrls->count; i++) { 971 struct v4l2_ext_control *ctrl = ctrls->controls + i; 972 973 err = cx2341x_get_ctrl(params, ctrl); 974 if (err) { 975 ctrls->error_idx = i; 976 break; 977 } 978 } 979 return err; 980 } 981 for (i = 0; i < ctrls->count; i++) { 982 struct v4l2_ext_control *ctrl = ctrls->controls + i; 983 struct v4l2_queryctrl qctrl; 984 const char * const *menu_items = NULL; 985 986 qctrl.id = ctrl->id; 987 err = cx2341x_ctrl_query(params, &qctrl); 988 if (err) 989 break; 990 if (qctrl.type == V4L2_CTRL_TYPE_MENU) 991 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id); 992 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); 993 if (err) 994 break; 995 err = cx2341x_set_ctrl(params, busy, ctrl); 996 if (err) 997 break; 998 } 999 if (err == 0 && 1000 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && 1001 params->video_bitrate_peak < params->video_bitrate) { 1002 err = -ERANGE; 1003 ctrls->error_idx = ctrls->count; 1004 } 1005 if (err) 1006 ctrls->error_idx = i; 1007 else 1008 cx2341x_calc_audio_properties(params); 1009 return err; 1010} 1011EXPORT_SYMBOL(cx2341x_ext_ctrls); 1012 1013void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) 1014{ 1015 *p = default_params; 1016 cx2341x_calc_audio_properties(p); 1017} 1018EXPORT_SYMBOL(cx2341x_fill_defaults); 1019 1020static int cx2341x_api(void *priv, cx2341x_mbox_func func, 1021 u32 cmd, int args, ...) 1022{ 1023 u32 data[CX2341X_MBOX_MAX_DATA]; 1024 va_list vargs; 1025 int i; 1026 1027 va_start(vargs, args); 1028 1029 for (i = 0; i < args; i++) 1030 data[i] = va_arg(vargs, int); 1031 va_end(vargs); 1032 return func(priv, cmd, args, 0, data); 1033} 1034 1035#define NEQ(field) (old->field != new->field) 1036 1037int cx2341x_update(void *priv, cx2341x_mbox_func func, 1038 const struct cx2341x_mpeg_params *old, 1039 const struct cx2341x_mpeg_params *new) 1040{ 1041 static int mpeg_stream_type[] = { 1042 0, /* MPEG-2 PS */ 1043 1, /* MPEG-2 TS */ 1044 2, /* MPEG-1 SS */ 1045 14, /* DVD */ 1046 11, /* VCD */ 1047 12, /* SVCD */ 1048 }; 1049 1050 int err = 0; 1051 int force = (old == NULL); 1052 u16 temporal = new->video_temporal_filter; 1053 1054 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0); 1055 1056 if (force || NEQ(is_50hz)) { 1057 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, 1058 new->is_50hz); 1059 if (err) return err; 1060 } 1061 1062 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) { 1063 u16 w = new->width; 1064 u16 h = new->height; 1065 1066 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { 1067 w /= 2; 1068 h /= 2; 1069 } 1070 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, 1071 h, w); 1072 if (err) return err; 1073 } 1074 if (force || NEQ(stream_type)) { 1075 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, 1076 mpeg_stream_type[new->stream_type]); 1077 if (err) return err; 1078 } 1079 if (force || NEQ(video_aspect)) { 1080 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1081 1 + new->video_aspect); 1082 if (err) return err; 1083 } 1084 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) { 1085 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2, 1086 new->video_gop_size, new->video_b_frames + 1); 1087 if (err) return err; 1088 } 1089 if (force || NEQ(video_gop_closure)) { 1090 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, 1091 new->video_gop_closure); 1092 if (err) return err; 1093 } 1094 if (force || NEQ(audio_properties)) { 1095 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1096 1, new->audio_properties); 1097 if (err) return err; 1098 } 1099 if (force || NEQ(audio_mute)) { 1100 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, 1101 new->audio_mute); 1102 if (err) return err; 1103 } 1104 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) || 1105 NEQ(video_bitrate_peak)) { 1106 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5, 1107 new->video_bitrate_mode, new->video_bitrate, 1108 new->video_bitrate_peak / 400, 0, 0); 1109 if (err) return err; 1110 } 1111 if (force || NEQ(video_spatial_filter_mode) || 1112 NEQ(video_temporal_filter_mode) || 1113 NEQ(video_median_filter_type)) { 1114 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 1115 2, new->video_spatial_filter_mode | 1116 (new->video_temporal_filter_mode << 1), 1117 new->video_median_filter_type); 1118 if (err) return err; 1119 } 1120 if (force || NEQ(video_luma_median_filter_bottom) || 1121 NEQ(video_luma_median_filter_top) || 1122 NEQ(video_chroma_median_filter_bottom) || 1123 NEQ(video_chroma_median_filter_top)) { 1124 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4, 1125 new->video_luma_median_filter_bottom, 1126 new->video_luma_median_filter_top, 1127 new->video_chroma_median_filter_bottom, 1128 new->video_chroma_median_filter_top); 1129 if (err) return err; 1130 } 1131 if (force || NEQ(video_luma_spatial_filter_type) || 1132 NEQ(video_chroma_spatial_filter_type)) { 1133 err = cx2341x_api(priv, func, 1134 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 1135 2, new->video_luma_spatial_filter_type, 1136 new->video_chroma_spatial_filter_type); 1137 if (err) return err; 1138 } 1139 if (force || NEQ(video_spatial_filter) || 1140 old->video_temporal_filter != temporal) { 1141 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 1142 2, new->video_spatial_filter, temporal); 1143 if (err) return err; 1144 } 1145 if (force || NEQ(video_temporal_decimation)) { 1146 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1147 1, new->video_temporal_decimation); 1148 if (err) return err; 1149 } 1150 if (force || NEQ(video_mute) || 1151 (new->video_mute && NEQ(video_mute_yuv))) { 1152 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, 1153 new->video_mute | (new->video_mute_yuv << 8)); 1154 if (err) return err; 1155 } 1156 if (force || NEQ(stream_insert_nav_packets)) { 1157 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, 1158 7, new->stream_insert_nav_packets); 1159 if (err) return err; 1160 } 1161 return 0; 1162} 1163EXPORT_SYMBOL(cx2341x_update); 1164 1165static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id) 1166{ 1167 const char * const *menu = cx2341x_ctrl_get_menu(p, id); 1168 struct v4l2_ext_control ctrl; 1169 1170 if (menu == NULL) 1171 goto invalid; 1172 ctrl.id = id; 1173 if (cx2341x_get_ctrl(p, &ctrl)) 1174 goto invalid; 1175 while (ctrl.value-- && *menu) menu++; 1176 if (*menu == NULL) 1177 goto invalid; 1178 return *menu; 1179 1180invalid: 1181 return "<invalid>"; 1182} 1183 1184void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) 1185{ 1186 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 1187 1188 /* Stream */ 1189 printk(KERN_INFO "%s: Stream: %s", 1190 prefix, 1191 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE)); 1192 if (p->stream_insert_nav_packets) 1193 printk(" (with navigation packets)"); 1194 printk("\n"); 1195 printk(KERN_INFO "%s: VBI Format: %s\n", 1196 prefix, 1197 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT)); 1198 1199 /* Video */ 1200 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n", 1201 prefix, 1202 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1), 1203 p->is_50hz ? 25 : 30, 1204 (p->video_mute) ? " (muted)" : ""); 1205 printk(KERN_INFO "%s: Video: %s, %s, %s, %d", 1206 prefix, 1207 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING), 1208 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT), 1209 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE), 1210 p->video_bitrate); 1211 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) 1212 printk(", Peak %d", p->video_bitrate_peak); 1213 printk("\n"); 1214 printk(KERN_INFO 1215 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n", 1216 prefix, 1217 p->video_gop_size, p->video_b_frames, 1218 p->video_gop_closure ? "" : "No "); 1219 if (p->video_temporal_decimation) 1220 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n", 1221 prefix, p->video_temporal_decimation); 1222 1223 /* Audio */ 1224 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s", 1225 prefix, 1226 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), 1227 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), 1228 cx2341x_menu_item(p, 1229 p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3 1230 ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE 1231 : V4L2_CID_MPEG_AUDIO_L2_BITRATE), 1232 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE), 1233 p->audio_mute ? " (muted)" : ""); 1234 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) 1235 printk(", %s", cx2341x_menu_item(p, 1236 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION)); 1237 printk(", %s, %s\n", 1238 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS), 1239 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC)); 1240 1241 /* Encoding filters */ 1242 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", 1243 prefix, 1244 cx2341x_menu_item(p, 1245 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE), 1246 cx2341x_menu_item(p, 1247 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE), 1248 cx2341x_menu_item(p, 1249 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), 1250 p->video_spatial_filter); 1251 1252 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", 1253 prefix, 1254 cx2341x_menu_item(p, 1255 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), 1256 p->video_temporal_filter); 1257 printk(KERN_INFO 1258 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", 1259 prefix, 1260 cx2341x_menu_item(p, 1261 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE), 1262 p->video_luma_median_filter_bottom, 1263 p->video_luma_median_filter_top, 1264 p->video_chroma_median_filter_bottom, 1265 p->video_chroma_median_filter_top); 1266} 1267EXPORT_SYMBOL(cx2341x_log_status); 1268 1269 1270 1271/********************** NEW CODE *********************/ 1272 1273static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl) 1274{ 1275 return container_of(ctrl->handler, struct cx2341x_handler, hdl); 1276} 1277 1278static int cx2341x_hdl_api(struct cx2341x_handler *hdl, 1279 u32 cmd, int args, ...) 1280{ 1281 u32 data[CX2341X_MBOX_MAX_DATA]; 1282 va_list vargs; 1283 int i; 1284 1285 va_start(vargs, args); 1286 1287 for (i = 0; i < args; i++) 1288 data[i] = va_arg(vargs, int); 1289 va_end(vargs); 1290 return hdl->func(hdl->priv, cmd, args, 0, data); 1291} 1292 1293/* ctrl->handler->lock is held, so it is safe to access cur.val */ 1294static inline int cx2341x_neq(struct v4l2_ctrl *ctrl) 1295{ 1296 return ctrl && ctrl->val != ctrl->cur.val; 1297} 1298 1299static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl) 1300{ 1301 struct cx2341x_handler *hdl = to_cxhdl(ctrl); 1302 s32 val = ctrl->val; 1303 1304 switch (ctrl->id) { 1305 case V4L2_CID_MPEG_VIDEO_B_FRAMES: { 1306 /* video gop cluster */ 1307 int b = val + 1; 1308 int gop = hdl->video_gop_size->val; 1309 1310 gop = b * ((gop + b - 1) / b); 1311 1312 /* Max GOP size = 34 */ 1313 while (gop > 34) 1314 gop -= b; 1315 hdl->video_gop_size->val = gop; 1316 break; 1317 } 1318 1319 case V4L2_CID_MPEG_STREAM_TYPE: 1320 /* stream type cluster */ 1321 hdl->video_encoding->val = 1322 (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || 1323 hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? 1324 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : 1325 V4L2_MPEG_VIDEO_ENCODING_MPEG_2; 1326 if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 1327 /* MPEG-1 implies CBR */ 1328 hdl->video_bitrate_mode->val = 1329 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; 1330 /* peak bitrate shall be >= normal bitrate */ 1331 if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && 1332 hdl->video_bitrate_peak->val < hdl->video_bitrate->val) 1333 hdl->video_bitrate_peak->val = hdl->video_bitrate->val; 1334 break; 1335 } 1336 return 0; 1337} 1338 1339static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl) 1340{ 1341 static const int mpeg_stream_type[] = { 1342 0, /* MPEG-2 PS */ 1343 1, /* MPEG-2 TS */ 1344 2, /* MPEG-1 SS */ 1345 14, /* DVD */ 1346 11, /* VCD */ 1347 12, /* SVCD */ 1348 }; 1349 struct cx2341x_handler *hdl = to_cxhdl(ctrl); 1350 s32 val = ctrl->val; 1351 u32 props; 1352 int err; 1353 1354 switch (ctrl->id) { 1355 case V4L2_CID_MPEG_STREAM_VBI_FMT: 1356 if (hdl->ops && hdl->ops->s_stream_vbi_fmt) 1357 return hdl->ops->s_stream_vbi_fmt(hdl, val); 1358 return 0; 1359 1360 case V4L2_CID_MPEG_VIDEO_ASPECT: 1361 return cx2341x_hdl_api(hdl, 1362 CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1); 1363 1364 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 1365 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val); 1366 1367 case V4L2_CID_MPEG_AUDIO_MUTE: 1368 return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val); 1369 1370 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 1371 return cx2341x_hdl_api(hdl, 1372 CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val); 1373 1374 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 1375 return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val); 1376 1377 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 1378 /* audio properties cluster */ 1379 props = (hdl->audio_sampling_freq->val << 0) | 1380 (hdl->audio_mode->val << 8) | 1381 (hdl->audio_mode_extension->val << 10) | 1382 (hdl->audio_crc->val << 14); 1383 if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) 1384 props |= 3 << 12; 1385 else 1386 props |= hdl->audio_emphasis->val << 12; 1387 1388 if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) { 1389 props |= 1390#if 1 1391 /* Not sure if this MPEG Layer II setting is required */ 1392 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | 1393#endif 1394 (hdl->audio_ac3_bitrate->val << 4) | 1395 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28); 1396 } else { 1397 /* Assuming MPEG Layer II */ 1398 props |= 1399 ((3 - hdl->audio_encoding->val) << 2) | 1400 ((1 + hdl->audio_l2_bitrate->val) << 4); 1401 } 1402 err = cx2341x_hdl_api(hdl, 1403 CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props); 1404 if (err) 1405 return err; 1406 1407 hdl->audio_properties = props; 1408 if (hdl->audio_ac3_bitrate) { 1409 int is_ac3 = hdl->audio_encoding->val == 1410 V4L2_MPEG_AUDIO_ENCODING_AC3; 1411 1412 v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3); 1413 v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3); 1414 } 1415 v4l2_ctrl_activate(hdl->audio_mode_extension, 1416 hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO); 1417 if (cx2341x_neq(hdl->audio_sampling_freq) && 1418 hdl->ops && hdl->ops->s_audio_sampling_freq) 1419 return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val); 1420 if (cx2341x_neq(hdl->audio_mode) && 1421 hdl->ops && hdl->ops->s_audio_mode) 1422 return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val); 1423 return 0; 1424 1425 case V4L2_CID_MPEG_VIDEO_B_FRAMES: 1426 /* video gop cluster */ 1427 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2, 1428 hdl->video_gop_size->val, 1429 hdl->video_b_frames->val + 1); 1430 1431 case V4L2_CID_MPEG_STREAM_TYPE: 1432 /* stream type cluster */ 1433 err = cx2341x_hdl_api(hdl, 1434 CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]); 1435 if (err) 1436 return err; 1437 1438 err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5, 1439 hdl->video_bitrate_mode->val, 1440 hdl->video_bitrate->val, 1441 hdl->video_bitrate_peak->val / 400, 0, 0); 1442 if (err) 1443 return err; 1444 1445 v4l2_ctrl_activate(hdl->video_bitrate_mode, 1446 hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1); 1447 v4l2_ctrl_activate(hdl->video_bitrate_peak, 1448 hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); 1449 if (cx2341x_neq(hdl->video_encoding) && 1450 hdl->ops && hdl->ops->s_video_encoding) 1451 return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val); 1452 return 0; 1453 1454 case V4L2_CID_MPEG_VIDEO_MUTE: 1455 /* video mute cluster */ 1456 return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1, 1457 hdl->video_mute->val | 1458 (hdl->video_mute_yuv->val << 8)); 1459 1460 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: { 1461 int active_filter; 1462 1463 /* video filter mode */ 1464 err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, 1465 hdl->video_spatial_filter_mode->val | 1466 (hdl->video_temporal_filter_mode->val << 1), 1467 hdl->video_median_filter_type->val); 1468 if (err) 1469 return err; 1470 1471 active_filter = hdl->video_spatial_filter_mode->val != 1472 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO; 1473 v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter); 1474 v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter); 1475 v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter); 1476 active_filter = hdl->video_temporal_filter_mode->val != 1477 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO; 1478 v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter); 1479 active_filter = hdl->video_median_filter_type->val != 1480 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF; 1481 v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter); 1482 v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter); 1483 v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter); 1484 v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter); 1485 return 0; 1486 } 1487 1488 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 1489 /* video filter type cluster */ 1490 return cx2341x_hdl_api(hdl, 1491 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, 1492 hdl->video_luma_spatial_filter_type->val, 1493 hdl->video_chroma_spatial_filter_type->val); 1494 1495 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 1496 /* video filter cluster */ 1497 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, 1498 hdl->video_spatial_filter->val, 1499 hdl->video_temporal_filter->val); 1500 1501 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 1502 /* video median cluster */ 1503 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4, 1504 hdl->video_luma_median_filter_bottom->val, 1505 hdl->video_luma_median_filter_top->val, 1506 hdl->video_chroma_median_filter_bottom->val, 1507 hdl->video_chroma_median_filter_top->val); 1508 } 1509 return -EINVAL; 1510} 1511 1512static const struct v4l2_ctrl_ops cx2341x_ops = { 1513 .try_ctrl = cx2341x_try_ctrl, 1514 .s_ctrl = cx2341x_s_ctrl, 1515}; 1516 1517static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, 1518 u32 id, s32 min, s32 max, s32 step, s32 def) 1519{ 1520 struct v4l2_ctrl_config cfg; 1521 1522 memset(&cfg, 0, sizeof(cfg)); 1523 cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags); 1524 cfg.ops = &cx2341x_ops; 1525 cfg.id = id; 1526 cfg.min = min; 1527 cfg.max = max; 1528 cfg.def = def; 1529 if (cfg.type == V4L2_CTRL_TYPE_MENU) { 1530 cfg.step = 0; 1531 cfg.menu_skip_mask = step; 1532 cfg.qmenu = cx2341x_get_menu(id); 1533 } else { 1534 cfg.step = step; 1535 cfg.menu_skip_mask = 0; 1536 } 1537 return v4l2_ctrl_new_custom(hdl, &cfg, NULL); 1538} 1539 1540static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl, 1541 u32 id, s32 min, s32 max, s32 step, s32 def) 1542{ 1543 return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def); 1544} 1545 1546static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl, 1547 u32 id, s32 max, s32 mask, s32 def) 1548{ 1549 return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def); 1550} 1551 1552int cx2341x_handler_init(struct cx2341x_handler *cxhdl, 1553 unsigned nr_of_controls_hint) 1554{ 1555 struct v4l2_ctrl_handler *hdl = &cxhdl->hdl; 1556 u32 caps = cxhdl->capabilities; 1557 int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI; 1558 int has_ac3 = caps & CX2341X_CAP_HAS_AC3; 1559 int has_ts = caps & CX2341X_CAP_HAS_TS; 1560 1561 cxhdl->width = 720; 1562 cxhdl->height = 480; 1563 1564 v4l2_ctrl_handler_init(hdl, nr_of_controls_hint); 1565 1566 /* Add controls in ascending control ID order for fastest 1567 insertion time. */ 1568 cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl, 1569 V4L2_CID_MPEG_STREAM_TYPE, 1570 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2, 1571 V4L2_MPEG_STREAM_TYPE_MPEG2_PS); 1572 cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl, 1573 V4L2_CID_MPEG_STREAM_VBI_FMT, 1574 V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2, 1575 V4L2_MPEG_STREAM_VBI_FMT_NONE); 1576 cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl, 1577 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, 1578 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0, 1579 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); 1580 cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl, 1581 V4L2_CID_MPEG_AUDIO_ENCODING, 1582 V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2, 1583 V4L2_MPEG_AUDIO_ENCODING_LAYER_2); 1584 cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl, 1585 V4L2_CID_MPEG_AUDIO_L2_BITRATE, 1586 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff, 1587 V4L2_MPEG_AUDIO_L2_BITRATE_224K); 1588 cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl, 1589 V4L2_CID_MPEG_AUDIO_MODE, 1590 V4L2_MPEG_AUDIO_MODE_MONO, 0, 1591 V4L2_MPEG_AUDIO_MODE_STEREO); 1592 cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl, 1593 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, 1594 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0, 1595 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); 1596 cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl, 1597 V4L2_CID_MPEG_AUDIO_EMPHASIS, 1598 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0, 1599 V4L2_MPEG_AUDIO_EMPHASIS_NONE); 1600 cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl, 1601 V4L2_CID_MPEG_AUDIO_CRC, 1602 V4L2_MPEG_AUDIO_CRC_CRC16, 0, 1603 V4L2_MPEG_AUDIO_CRC_NONE); 1604 1605 cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0); 1606 if (has_ac3) 1607 cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl, 1608 V4L2_CID_MPEG_AUDIO_AC3_BITRATE, 1609 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03, 1610 V4L2_MPEG_AUDIO_AC3_BITRATE_224K); 1611 cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl, 1612 V4L2_CID_MPEG_VIDEO_ENCODING, 1613 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0, 1614 V4L2_MPEG_VIDEO_ENCODING_MPEG_2); 1615 cx2341x_ctrl_new_menu(hdl, 1616 V4L2_CID_MPEG_VIDEO_ASPECT, 1617 V4L2_MPEG_VIDEO_ASPECT_221x100, 0, 1618 V4L2_MPEG_VIDEO_ASPECT_4x3); 1619 cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl, 1620 V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2); 1621 cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl, 1622 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1623 1, 34, 1, cxhdl->is_50hz ? 12 : 15); 1624 cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1); 1625 cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl, 1626 V4L2_CID_MPEG_VIDEO_BITRATE_MODE, 1627 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, 1628 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 1629 cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl, 1630 V4L2_CID_MPEG_VIDEO_BITRATE, 1631 0, 27000000, 1, 6000000); 1632 cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl, 1633 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 1634 0, 27000000, 1, 8000000); 1635 cx2341x_ctrl_new_std(hdl, 1636 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0); 1637 cxhdl->video_mute = cx2341x_ctrl_new_std(hdl, 1638 V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0); 1639 cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl, 1640 V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080); 1641 1642 /* CX23415/6 specific */ 1643 cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl, 1644 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, 1645 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 1646 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0, 1647 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); 1648 cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl, 1649 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, 1650 0, 15, 1, 0); 1651 cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl, 1652 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, 1653 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, 1654 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1655 0, 1656 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR); 1657 cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl, 1658 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, 1659 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, 1660 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1661 0, 1662 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR); 1663 cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl, 1664 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, 1665 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 1666 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1667 0, 1668 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); 1669 cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl, 1670 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, 1671 0, 31, 1, 8); 1672 cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl, 1673 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, 1674 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 1675 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1676 0, 1677 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); 1678 cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl, 1679 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, 1680 0, 255, 1, 0); 1681 cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl, 1682 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, 1683 0, 255, 1, 255); 1684 cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl, 1685 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, 1686 0, 255, 1, 0); 1687 cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl, 1688 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, 1689 0, 255, 1, 255); 1690 cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS, 1691 0, 1, 1, 0); 1692 1693 if (hdl->error) { 1694 int err = hdl->error; 1695 1696 v4l2_ctrl_handler_free(hdl); 1697 return err; 1698 } 1699 1700 v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq); 1701 v4l2_ctrl_cluster(2, &cxhdl->video_b_frames); 1702 v4l2_ctrl_cluster(5, &cxhdl->stream_type); 1703 v4l2_ctrl_cluster(2, &cxhdl->video_mute); 1704 v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode); 1705 v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type); 1706 v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter); 1707 v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top); 1708 1709 return 0; 1710} 1711EXPORT_SYMBOL(cx2341x_handler_init); 1712 1713void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz) 1714{ 1715 cxhdl->is_50hz = is_50hz; 1716 cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15; 1717} 1718EXPORT_SYMBOL(cx2341x_handler_set_50hz); 1719 1720int cx2341x_handler_setup(struct cx2341x_handler *cxhdl) 1721{ 1722 int h = cxhdl->height; 1723 int w = cxhdl->width; 1724 int err; 1725 1726 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0); 1727 if (err) 1728 return err; 1729 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz); 1730 if (err) 1731 return err; 1732 1733 if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { 1734 w /= 2; 1735 h /= 2; 1736 } 1737 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); 1738 if (err) 1739 return err; 1740 return v4l2_ctrl_handler_setup(&cxhdl->hdl); 1741} 1742EXPORT_SYMBOL(cx2341x_handler_setup); 1743 1744void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy) 1745{ 1746 v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy); 1747 v4l2_ctrl_grab(cxhdl->audio_encoding, busy); 1748 v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy); 1749 v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy); 1750 v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy); 1751 v4l2_ctrl_grab(cxhdl->stream_type, busy); 1752 v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy); 1753 v4l2_ctrl_grab(cxhdl->video_bitrate, busy); 1754 v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy); 1755} 1756EXPORT_SYMBOL(cx2341x_handler_set_busy); 1757