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