162595820SHans Verkuil /* 262595820SHans Verkuil * cx2341x - generic code for cx23415/6/8 based devices 362595820SHans Verkuil * 462595820SHans Verkuil * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl> 562595820SHans Verkuil * 662595820SHans Verkuil * This program is free software; you can redistribute it and/or modify 762595820SHans Verkuil * it under the terms of the GNU General Public License as published by 862595820SHans Verkuil * the Free Software Foundation; either version 2 of the License, or 962595820SHans Verkuil * (at your option) any later version. 1062595820SHans Verkuil * 1162595820SHans Verkuil * This program is distributed in the hope that it will be useful, 1262595820SHans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of 1362595820SHans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1462595820SHans Verkuil * GNU General Public License for more details. 1562595820SHans Verkuil */ 1662595820SHans Verkuil 1762595820SHans Verkuil 1862595820SHans Verkuil #include <linux/module.h> 1962595820SHans Verkuil #include <linux/errno.h> 2062595820SHans Verkuil #include <linux/kernel.h> 2162595820SHans Verkuil #include <linux/init.h> 2262595820SHans Verkuil #include <linux/types.h> 2362595820SHans Verkuil #include <linux/videodev2.h> 2462595820SHans Verkuil 2562595820SHans Verkuil #include <media/tuner.h> 26d647f0b7SMauro Carvalho Chehab #include <media/drv-intf/cx2341x.h> 2762595820SHans Verkuil #include <media/v4l2-common.h> 2862595820SHans Verkuil 2962595820SHans Verkuil MODULE_DESCRIPTION("cx23415/6/8 driver"); 3062595820SHans Verkuil MODULE_AUTHOR("Hans Verkuil"); 3162595820SHans Verkuil MODULE_LICENSE("GPL"); 3262595820SHans Verkuil 3362595820SHans Verkuil static int debug; 3462595820SHans Verkuil module_param(debug, int, 0644); 3562595820SHans Verkuil MODULE_PARM_DESC(debug, "Debug level (0-1)"); 3662595820SHans Verkuil 3762595820SHans Verkuil /********************** COMMON CODE *********************/ 3862595820SHans Verkuil 3962595820SHans Verkuil /* definitions for audio properties bits 29-28 */ 4062595820SHans Verkuil #define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0 4162595820SHans Verkuil #define CX2341X_AUDIO_ENCODING_METHOD_AC3 1 4262595820SHans Verkuil #define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2 4362595820SHans Verkuil 4462595820SHans Verkuil static const char *cx2341x_get_name(u32 id) 4562595820SHans Verkuil { 4662595820SHans Verkuil switch (id) { 4762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 4862595820SHans Verkuil return "Spatial Filter Mode"; 4962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 5062595820SHans Verkuil return "Spatial Filter"; 5162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 5262595820SHans Verkuil return "Spatial Luma Filter Type"; 5362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 5462595820SHans Verkuil return "Spatial Chroma Filter Type"; 5562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 5662595820SHans Verkuil return "Temporal Filter Mode"; 5762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 5862595820SHans Verkuil return "Temporal Filter"; 5962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 6062595820SHans Verkuil return "Median Filter Type"; 6162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 6262595820SHans Verkuil return "Median Luma Filter Maximum"; 6362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 6462595820SHans Verkuil return "Median Luma Filter Minimum"; 6562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 6662595820SHans Verkuil return "Median Chroma Filter Maximum"; 6762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 6862595820SHans Verkuil return "Median Chroma Filter Minimum"; 6962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 7062595820SHans Verkuil return "Insert Navigation Packets"; 7162595820SHans Verkuil } 7262595820SHans Verkuil return NULL; 7362595820SHans Verkuil } 7462595820SHans Verkuil 7562595820SHans Verkuil static const char **cx2341x_get_menu(u32 id) 7662595820SHans Verkuil { 7762595820SHans Verkuil static const char *cx2341x_video_spatial_filter_mode_menu[] = { 7862595820SHans Verkuil "Manual", 7962595820SHans Verkuil "Auto", 8062595820SHans Verkuil NULL 8162595820SHans Verkuil }; 8262595820SHans Verkuil 8362595820SHans Verkuil static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { 8462595820SHans Verkuil "Off", 8562595820SHans Verkuil "1D Horizontal", 8662595820SHans Verkuil "1D Vertical", 8762595820SHans Verkuil "2D H/V Separable", 8862595820SHans Verkuil "2D Symmetric non-separable", 8962595820SHans Verkuil NULL 9062595820SHans Verkuil }; 9162595820SHans Verkuil 9262595820SHans Verkuil static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { 9362595820SHans Verkuil "Off", 9462595820SHans Verkuil "1D Horizontal", 9562595820SHans Verkuil NULL 9662595820SHans Verkuil }; 9762595820SHans Verkuil 9862595820SHans Verkuil static const char *cx2341x_video_temporal_filter_mode_menu[] = { 9962595820SHans Verkuil "Manual", 10062595820SHans Verkuil "Auto", 10162595820SHans Verkuil NULL 10262595820SHans Verkuil }; 10362595820SHans Verkuil 10462595820SHans Verkuil static const char *cx2341x_video_median_filter_type_menu[] = { 10562595820SHans Verkuil "Off", 10662595820SHans Verkuil "Horizontal", 10762595820SHans Verkuil "Vertical", 10862595820SHans Verkuil "Horizontal/Vertical", 10962595820SHans Verkuil "Diagonal", 11062595820SHans Verkuil NULL 11162595820SHans Verkuil }; 11262595820SHans Verkuil 11362595820SHans Verkuil switch (id) { 11462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 11562595820SHans Verkuil return cx2341x_video_spatial_filter_mode_menu; 11662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 11762595820SHans Verkuil return cx2341x_video_luma_spatial_filter_type_menu; 11862595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 11962595820SHans Verkuil return cx2341x_video_chroma_spatial_filter_type_menu; 12062595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 12162595820SHans Verkuil return cx2341x_video_temporal_filter_mode_menu; 12262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 12362595820SHans Verkuil return cx2341x_video_median_filter_type_menu; 12462595820SHans Verkuil } 12562595820SHans Verkuil return NULL; 12662595820SHans Verkuil } 12762595820SHans Verkuil 12862595820SHans Verkuil static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, 12962595820SHans Verkuil s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags) 13062595820SHans Verkuil { 13162595820SHans Verkuil *name = cx2341x_get_name(id); 13262595820SHans Verkuil *flags = 0; 13362595820SHans Verkuil 13462595820SHans Verkuil switch (id) { 13562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 13662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 13762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 13862595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 13962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 14062595820SHans Verkuil *type = V4L2_CTRL_TYPE_MENU; 14162595820SHans Verkuil *min = 0; 14262595820SHans Verkuil *step = 0; 14362595820SHans Verkuil break; 14462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 14562595820SHans Verkuil *type = V4L2_CTRL_TYPE_BOOLEAN; 14662595820SHans Verkuil *min = 0; 14762595820SHans Verkuil *max = *step = 1; 14862595820SHans Verkuil break; 14962595820SHans Verkuil default: 15062595820SHans Verkuil *type = V4L2_CTRL_TYPE_INTEGER; 15162595820SHans Verkuil break; 15262595820SHans Verkuil } 15362595820SHans Verkuil switch (id) { 15462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 15562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 15662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 15762595820SHans Verkuil *flags |= V4L2_CTRL_FLAG_UPDATE; 15862595820SHans Verkuil break; 15962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 16062595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 16162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 16262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 16362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 16462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 16562595820SHans Verkuil *flags |= V4L2_CTRL_FLAG_SLIDER; 16662595820SHans Verkuil break; 16762595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ENCODING: 16862595820SHans Verkuil *flags |= V4L2_CTRL_FLAG_READ_ONLY; 16962595820SHans Verkuil break; 17062595820SHans Verkuil } 17162595820SHans Verkuil } 17262595820SHans Verkuil 17362595820SHans Verkuil 17462595820SHans Verkuil /********************** OLD CODE *********************/ 17562595820SHans Verkuil 17662595820SHans Verkuil /* Must be sorted from low to high control ID! */ 17762595820SHans Verkuil const u32 cx2341x_mpeg_ctrls[] = { 17862595820SHans Verkuil V4L2_CID_MPEG_CLASS, 17962595820SHans Verkuil V4L2_CID_MPEG_STREAM_TYPE, 18062595820SHans Verkuil V4L2_CID_MPEG_STREAM_VBI_FMT, 18162595820SHans Verkuil V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, 18262595820SHans Verkuil V4L2_CID_MPEG_AUDIO_ENCODING, 18362595820SHans Verkuil V4L2_CID_MPEG_AUDIO_L2_BITRATE, 18462595820SHans Verkuil V4L2_CID_MPEG_AUDIO_MODE, 18562595820SHans Verkuil V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, 18662595820SHans Verkuil V4L2_CID_MPEG_AUDIO_EMPHASIS, 18762595820SHans Verkuil V4L2_CID_MPEG_AUDIO_CRC, 18862595820SHans Verkuil V4L2_CID_MPEG_AUDIO_MUTE, 18962595820SHans Verkuil V4L2_CID_MPEG_AUDIO_AC3_BITRATE, 19062595820SHans Verkuil V4L2_CID_MPEG_VIDEO_ENCODING, 19162595820SHans Verkuil V4L2_CID_MPEG_VIDEO_ASPECT, 19262595820SHans Verkuil V4L2_CID_MPEG_VIDEO_B_FRAMES, 19362595820SHans Verkuil V4L2_CID_MPEG_VIDEO_GOP_SIZE, 19462595820SHans Verkuil V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 19562595820SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE_MODE, 19662595820SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE, 19762595820SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 19862595820SHans Verkuil V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 19962595820SHans Verkuil V4L2_CID_MPEG_VIDEO_MUTE, 20062595820SHans Verkuil V4L2_CID_MPEG_VIDEO_MUTE_YUV, 20162595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, 20262595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, 20362595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, 20462595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, 20562595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, 20662595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, 20762595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, 20862595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, 20962595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, 21062595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, 21162595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, 21262595820SHans Verkuil V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS, 21362595820SHans Verkuil 0 21462595820SHans Verkuil }; 21562595820SHans Verkuil EXPORT_SYMBOL(cx2341x_mpeg_ctrls); 21662595820SHans Verkuil 21762595820SHans Verkuil static const struct cx2341x_mpeg_params default_params = { 21862595820SHans Verkuil /* misc */ 21962595820SHans Verkuil .capabilities = 0, 22062595820SHans Verkuil .port = CX2341X_PORT_MEMORY, 22162595820SHans Verkuil .width = 720, 22262595820SHans Verkuil .height = 480, 22362595820SHans Verkuil .is_50hz = 0, 22462595820SHans Verkuil 22562595820SHans Verkuil /* stream */ 22662595820SHans Verkuil .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS, 22762595820SHans Verkuil .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE, 22862595820SHans Verkuil .stream_insert_nav_packets = 0, 22962595820SHans Verkuil 23062595820SHans Verkuil /* audio */ 23162595820SHans Verkuil .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 23262595820SHans Verkuil .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 23362595820SHans Verkuil .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K, 23462595820SHans Verkuil .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K, 23562595820SHans Verkuil .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO, 23662595820SHans Verkuil .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, 23762595820SHans Verkuil .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE, 23862595820SHans Verkuil .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE, 23962595820SHans Verkuil .audio_mute = 0, 24062595820SHans Verkuil 24162595820SHans Verkuil /* video */ 24262595820SHans Verkuil .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 24362595820SHans Verkuil .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, 24462595820SHans Verkuil .video_b_frames = 2, 24562595820SHans Verkuil .video_gop_size = 12, 24662595820SHans Verkuil .video_gop_closure = 1, 24762595820SHans Verkuil .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, 24862595820SHans Verkuil .video_bitrate = 6000000, 24962595820SHans Verkuil .video_bitrate_peak = 8000000, 25062595820SHans Verkuil .video_temporal_decimation = 0, 25162595820SHans Verkuil .video_mute = 0, 25262595820SHans Verkuil .video_mute_yuv = 0x008080, /* YCbCr value for black */ 25362595820SHans Verkuil 25462595820SHans Verkuil /* encoding filters */ 25562595820SHans Verkuil .video_spatial_filter_mode = 25662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 25762595820SHans Verkuil .video_spatial_filter = 0, 25862595820SHans Verkuil .video_luma_spatial_filter_type = 25962595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR, 26062595820SHans Verkuil .video_chroma_spatial_filter_type = 26162595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 26262595820SHans Verkuil .video_temporal_filter_mode = 26362595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 26462595820SHans Verkuil .video_temporal_filter = 8, 26562595820SHans Verkuil .video_median_filter_type = 26662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 26762595820SHans Verkuil .video_luma_median_filter_top = 255, 26862595820SHans Verkuil .video_luma_median_filter_bottom = 0, 26962595820SHans Verkuil .video_chroma_median_filter_top = 255, 27062595820SHans Verkuil .video_chroma_median_filter_bottom = 0, 27162595820SHans Verkuil }; 27262595820SHans Verkuil /* Map the control ID to the correct field in the cx2341x_mpeg_params 27362595820SHans Verkuil struct. Return -EINVAL if the ID is unknown, else return 0. */ 27462595820SHans Verkuil static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params, 27562595820SHans Verkuil struct v4l2_ext_control *ctrl) 27662595820SHans Verkuil { 27762595820SHans Verkuil switch (ctrl->id) { 27862595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 27962595820SHans Verkuil ctrl->value = params->audio_sampling_freq; 28062595820SHans Verkuil break; 28162595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_ENCODING: 28262595820SHans Verkuil ctrl->value = params->audio_encoding; 28362595820SHans Verkuil break; 28462595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 28562595820SHans Verkuil ctrl->value = params->audio_l2_bitrate; 28662595820SHans Verkuil break; 28762595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 28862595820SHans Verkuil ctrl->value = params->audio_ac3_bitrate; 28962595820SHans Verkuil break; 29062595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MODE: 29162595820SHans Verkuil ctrl->value = params->audio_mode; 29262595820SHans Verkuil break; 29362595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 29462595820SHans Verkuil ctrl->value = params->audio_mode_extension; 29562595820SHans Verkuil break; 29662595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_EMPHASIS: 29762595820SHans Verkuil ctrl->value = params->audio_emphasis; 29862595820SHans Verkuil break; 29962595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_CRC: 30062595820SHans Verkuil ctrl->value = params->audio_crc; 30162595820SHans Verkuil break; 30262595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MUTE: 30362595820SHans Verkuil ctrl->value = params->audio_mute; 30462595820SHans Verkuil break; 30562595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ENCODING: 30662595820SHans Verkuil ctrl->value = params->video_encoding; 30762595820SHans Verkuil break; 30862595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ASPECT: 30962595820SHans Verkuil ctrl->value = params->video_aspect; 31062595820SHans Verkuil break; 31162595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_B_FRAMES: 31262595820SHans Verkuil ctrl->value = params->video_b_frames; 31362595820SHans Verkuil break; 31462595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 31562595820SHans Verkuil ctrl->value = params->video_gop_size; 31662595820SHans Verkuil break; 31762595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 31862595820SHans Verkuil ctrl->value = params->video_gop_closure; 31962595820SHans Verkuil break; 32062595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 32162595820SHans Verkuil ctrl->value = params->video_bitrate_mode; 32262595820SHans Verkuil break; 32362595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE: 32462595820SHans Verkuil ctrl->value = params->video_bitrate; 32562595820SHans Verkuil break; 32662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 32762595820SHans Verkuil ctrl->value = params->video_bitrate_peak; 32862595820SHans Verkuil break; 32962595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 33062595820SHans Verkuil ctrl->value = params->video_temporal_decimation; 33162595820SHans Verkuil break; 33262595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE: 33362595820SHans Verkuil ctrl->value = params->video_mute; 33462595820SHans Verkuil break; 33562595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE_YUV: 33662595820SHans Verkuil ctrl->value = params->video_mute_yuv; 33762595820SHans Verkuil break; 33862595820SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 33962595820SHans Verkuil ctrl->value = params->stream_type; 34062595820SHans Verkuil break; 34162595820SHans Verkuil case V4L2_CID_MPEG_STREAM_VBI_FMT: 34262595820SHans Verkuil ctrl->value = params->stream_vbi_fmt; 34362595820SHans Verkuil break; 34462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 34562595820SHans Verkuil ctrl->value = params->video_spatial_filter_mode; 34662595820SHans Verkuil break; 34762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 34862595820SHans Verkuil ctrl->value = params->video_spatial_filter; 34962595820SHans Verkuil break; 35062595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 35162595820SHans Verkuil ctrl->value = params->video_luma_spatial_filter_type; 35262595820SHans Verkuil break; 35362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 35462595820SHans Verkuil ctrl->value = params->video_chroma_spatial_filter_type; 35562595820SHans Verkuil break; 35662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 35762595820SHans Verkuil ctrl->value = params->video_temporal_filter_mode; 35862595820SHans Verkuil break; 35962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 36062595820SHans Verkuil ctrl->value = params->video_temporal_filter; 36162595820SHans Verkuil break; 36262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 36362595820SHans Verkuil ctrl->value = params->video_median_filter_type; 36462595820SHans Verkuil break; 36562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 36662595820SHans Verkuil ctrl->value = params->video_luma_median_filter_top; 36762595820SHans Verkuil break; 36862595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 36962595820SHans Verkuil ctrl->value = params->video_luma_median_filter_bottom; 37062595820SHans Verkuil break; 37162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 37262595820SHans Verkuil ctrl->value = params->video_chroma_median_filter_top; 37362595820SHans Verkuil break; 37462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 37562595820SHans Verkuil ctrl->value = params->video_chroma_median_filter_bottom; 37662595820SHans Verkuil break; 37762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 37862595820SHans Verkuil ctrl->value = params->stream_insert_nav_packets; 37962595820SHans Verkuil break; 38062595820SHans Verkuil default: 38162595820SHans Verkuil return -EINVAL; 38262595820SHans Verkuil } 38362595820SHans Verkuil return 0; 38462595820SHans Verkuil } 38562595820SHans Verkuil 38662595820SHans Verkuil /* Map the control ID to the correct field in the cx2341x_mpeg_params 38762595820SHans Verkuil struct. Return -EINVAL if the ID is unknown, else return 0. */ 38862595820SHans Verkuil static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, 38962595820SHans Verkuil struct v4l2_ext_control *ctrl) 39062595820SHans Verkuil { 39162595820SHans Verkuil switch (ctrl->id) { 39262595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 39362595820SHans Verkuil if (busy) 39462595820SHans Verkuil return -EBUSY; 39562595820SHans Verkuil params->audio_sampling_freq = ctrl->value; 39662595820SHans Verkuil break; 39762595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_ENCODING: 39862595820SHans Verkuil if (busy) 39962595820SHans Verkuil return -EBUSY; 40062595820SHans Verkuil if (params->capabilities & CX2341X_CAP_HAS_AC3) 40162595820SHans Verkuil if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && 40262595820SHans Verkuil ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3) 40362595820SHans Verkuil return -ERANGE; 40462595820SHans Verkuil params->audio_encoding = ctrl->value; 40562595820SHans Verkuil break; 40662595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 40762595820SHans Verkuil if (busy) 40862595820SHans Verkuil return -EBUSY; 40962595820SHans Verkuil params->audio_l2_bitrate = ctrl->value; 41062595820SHans Verkuil break; 41162595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 41262595820SHans Verkuil if (busy) 41362595820SHans Verkuil return -EBUSY; 41462595820SHans Verkuil if (!(params->capabilities & CX2341X_CAP_HAS_AC3)) 41562595820SHans Verkuil return -EINVAL; 41662595820SHans Verkuil params->audio_ac3_bitrate = ctrl->value; 41762595820SHans Verkuil break; 41862595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MODE: 41962595820SHans Verkuil params->audio_mode = ctrl->value; 42062595820SHans Verkuil break; 42162595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 42262595820SHans Verkuil params->audio_mode_extension = ctrl->value; 42362595820SHans Verkuil break; 42462595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_EMPHASIS: 42562595820SHans Verkuil params->audio_emphasis = ctrl->value; 42662595820SHans Verkuil break; 42762595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_CRC: 42862595820SHans Verkuil params->audio_crc = ctrl->value; 42962595820SHans Verkuil break; 43062595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MUTE: 43162595820SHans Verkuil params->audio_mute = ctrl->value; 43262595820SHans Verkuil break; 43362595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ASPECT: 43462595820SHans Verkuil params->video_aspect = ctrl->value; 43562595820SHans Verkuil break; 43662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_B_FRAMES: { 43762595820SHans Verkuil int b = ctrl->value + 1; 43862595820SHans Verkuil int gop = params->video_gop_size; 43962595820SHans Verkuil params->video_b_frames = ctrl->value; 44062595820SHans Verkuil params->video_gop_size = b * ((gop + b - 1) / b); 44162595820SHans Verkuil /* Max GOP size = 34 */ 44262595820SHans Verkuil while (params->video_gop_size > 34) 44362595820SHans Verkuil params->video_gop_size -= b; 44462595820SHans Verkuil break; 44562595820SHans Verkuil } 44662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_SIZE: { 44762595820SHans Verkuil int b = params->video_b_frames + 1; 44862595820SHans Verkuil int gop = ctrl->value; 44962595820SHans Verkuil params->video_gop_size = b * ((gop + b - 1) / b); 45062595820SHans Verkuil /* Max GOP size = 34 */ 45162595820SHans Verkuil while (params->video_gop_size > 34) 45262595820SHans Verkuil params->video_gop_size -= b; 45362595820SHans Verkuil ctrl->value = params->video_gop_size; 45462595820SHans Verkuil break; 45562595820SHans Verkuil } 45662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 45762595820SHans Verkuil params->video_gop_closure = ctrl->value; 45862595820SHans Verkuil break; 45962595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 46062595820SHans Verkuil if (busy) 46162595820SHans Verkuil return -EBUSY; 46262595820SHans Verkuil /* MPEG-1 only allows CBR */ 46362595820SHans Verkuil if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && 46462595820SHans Verkuil ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) 46562595820SHans Verkuil return -EINVAL; 46662595820SHans Verkuil params->video_bitrate_mode = ctrl->value; 46762595820SHans Verkuil break; 46862595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE: 46962595820SHans Verkuil if (busy) 47062595820SHans Verkuil return -EBUSY; 47162595820SHans Verkuil params->video_bitrate = ctrl->value; 47262595820SHans Verkuil break; 47362595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 47462595820SHans Verkuil if (busy) 47562595820SHans Verkuil return -EBUSY; 47662595820SHans Verkuil params->video_bitrate_peak = ctrl->value; 47762595820SHans Verkuil break; 47862595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 47962595820SHans Verkuil params->video_temporal_decimation = ctrl->value; 48062595820SHans Verkuil break; 48162595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE: 48262595820SHans Verkuil params->video_mute = (ctrl->value != 0); 48362595820SHans Verkuil break; 48462595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE_YUV: 48562595820SHans Verkuil params->video_mute_yuv = ctrl->value; 48662595820SHans Verkuil break; 48762595820SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 48862595820SHans Verkuil if (busy) 48962595820SHans Verkuil return -EBUSY; 49062595820SHans Verkuil params->stream_type = ctrl->value; 49162595820SHans Verkuil params->video_encoding = 49262595820SHans Verkuil (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || 49362595820SHans Verkuil params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? 49462595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : 49562595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2; 49662595820SHans Verkuil if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 49762595820SHans Verkuil /* MPEG-1 implies CBR */ 49862595820SHans Verkuil params->video_bitrate_mode = 49962595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; 50062595820SHans Verkuil break; 50162595820SHans Verkuil case V4L2_CID_MPEG_STREAM_VBI_FMT: 50262595820SHans Verkuil params->stream_vbi_fmt = ctrl->value; 50362595820SHans Verkuil break; 50462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 50562595820SHans Verkuil params->video_spatial_filter_mode = ctrl->value; 50662595820SHans Verkuil break; 50762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 50862595820SHans Verkuil params->video_spatial_filter = ctrl->value; 50962595820SHans Verkuil break; 51062595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 51162595820SHans Verkuil params->video_luma_spatial_filter_type = ctrl->value; 51262595820SHans Verkuil break; 51362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 51462595820SHans Verkuil params->video_chroma_spatial_filter_type = ctrl->value; 51562595820SHans Verkuil break; 51662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 51762595820SHans Verkuil params->video_temporal_filter_mode = ctrl->value; 51862595820SHans Verkuil break; 51962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 52062595820SHans Verkuil params->video_temporal_filter = ctrl->value; 52162595820SHans Verkuil break; 52262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 52362595820SHans Verkuil params->video_median_filter_type = ctrl->value; 52462595820SHans Verkuil break; 52562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 52662595820SHans Verkuil params->video_luma_median_filter_top = ctrl->value; 52762595820SHans Verkuil break; 52862595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 52962595820SHans Verkuil params->video_luma_median_filter_bottom = ctrl->value; 53062595820SHans Verkuil break; 53162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 53262595820SHans Verkuil params->video_chroma_median_filter_top = ctrl->value; 53362595820SHans Verkuil break; 53462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 53562595820SHans Verkuil params->video_chroma_median_filter_bottom = ctrl->value; 53662595820SHans Verkuil break; 53762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 53862595820SHans Verkuil params->stream_insert_nav_packets = ctrl->value; 53962595820SHans Verkuil break; 54062595820SHans Verkuil default: 54162595820SHans Verkuil return -EINVAL; 54262595820SHans Verkuil } 54362595820SHans Verkuil return 0; 54462595820SHans Verkuil } 54562595820SHans Verkuil 54662595820SHans Verkuil static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, 54762595820SHans Verkuil s32 min, s32 max, s32 step, s32 def) 54862595820SHans Verkuil { 54962595820SHans Verkuil const char *name; 55062595820SHans Verkuil 55162595820SHans Verkuil switch (qctrl->id) { 55262595820SHans Verkuil /* MPEG controls */ 55362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 55462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 55562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 55662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 55762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 55862595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 55962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 56062595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 56162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 56262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 56362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 56462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 56562595820SHans Verkuil cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type, 56662595820SHans Verkuil &min, &max, &step, &def, &qctrl->flags); 56762595820SHans Verkuil qctrl->minimum = min; 56862595820SHans Verkuil qctrl->maximum = max; 56962595820SHans Verkuil qctrl->step = step; 57062595820SHans Verkuil qctrl->default_value = def; 57162595820SHans Verkuil qctrl->reserved[0] = qctrl->reserved[1] = 0; 572c0decac1SMauro Carvalho Chehab strscpy(qctrl->name, name, sizeof(qctrl->name)); 57362595820SHans Verkuil return 0; 57462595820SHans Verkuil 57562595820SHans Verkuil default: 57662595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, min, max, step, def); 57762595820SHans Verkuil } 57862595820SHans Verkuil } 57962595820SHans Verkuil 58062595820SHans Verkuil int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, 58162595820SHans Verkuil struct v4l2_queryctrl *qctrl) 58262595820SHans Verkuil { 58362595820SHans Verkuil int err; 58462595820SHans Verkuil 58562595820SHans Verkuil switch (qctrl->id) { 58662595820SHans Verkuil case V4L2_CID_MPEG_CLASS: 58762595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); 58862595820SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 58962595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 59062595820SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_PS, 59162595820SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, 59262595820SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_PS); 59362595820SHans Verkuil 59462595820SHans Verkuil case V4L2_CID_MPEG_STREAM_VBI_FMT: 59562595820SHans Verkuil if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) 59662595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 59762595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_NONE, 59862595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, 59962595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_NONE); 60062595820SHans Verkuil return cx2341x_ctrl_query_fill(qctrl, 60162595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_NONE, 60262595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, 60362595820SHans Verkuil default_params.stream_vbi_fmt); 60462595820SHans Verkuil 60562595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 60662595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 60762595820SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, 60862595820SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, 60962595820SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); 61062595820SHans Verkuil 61162595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_ENCODING: 61262595820SHans Verkuil if (params->capabilities & CX2341X_CAP_HAS_AC3) { 61362595820SHans Verkuil /* 61462595820SHans Verkuil * The state of L2 & AC3 bitrate controls can change 61562595820SHans Verkuil * when this control changes, but v4l2_ctrl_query_fill() 61662595820SHans Verkuil * already sets V4L2_CTRL_FLAG_UPDATE for 61762595820SHans Verkuil * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here. 61862595820SHans Verkuil */ 61962595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 62062595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 62162595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_AC3, 1, 62262595820SHans Verkuil default_params.audio_encoding); 62362595820SHans Verkuil } 62462595820SHans Verkuil 62562595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 62662595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 62762595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, 62862595820SHans Verkuil default_params.audio_encoding); 62962595820SHans Verkuil 63062595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 63162595820SHans Verkuil err = v4l2_ctrl_query_fill(qctrl, 63262595820SHans Verkuil V4L2_MPEG_AUDIO_L2_BITRATE_192K, 63362595820SHans Verkuil V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, 63462595820SHans Verkuil default_params.audio_l2_bitrate); 63562595820SHans Verkuil if (err) 63662595820SHans Verkuil return err; 63762595820SHans Verkuil if (params->capabilities & CX2341X_CAP_HAS_AC3 && 63862595820SHans Verkuil params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2) 63962595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 64062595820SHans Verkuil return 0; 64162595820SHans Verkuil 64262595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MODE: 64362595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 64462595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_STEREO, 64562595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_MONO, 1, 64662595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_STEREO); 64762595820SHans Verkuil 64862595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 64962595820SHans Verkuil err = v4l2_ctrl_query_fill(qctrl, 65062595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, 65162595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, 65262595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); 65362595820SHans Verkuil if (err == 0 && 65462595820SHans Verkuil params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) 65562595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 65662595820SHans Verkuil return err; 65762595820SHans Verkuil 65862595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_EMPHASIS: 65962595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 66062595820SHans Verkuil V4L2_MPEG_AUDIO_EMPHASIS_NONE, 66162595820SHans Verkuil V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, 66262595820SHans Verkuil V4L2_MPEG_AUDIO_EMPHASIS_NONE); 66362595820SHans Verkuil 66462595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_CRC: 66562595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 66662595820SHans Verkuil V4L2_MPEG_AUDIO_CRC_NONE, 66762595820SHans Verkuil V4L2_MPEG_AUDIO_CRC_CRC16, 1, 66862595820SHans Verkuil V4L2_MPEG_AUDIO_CRC_NONE); 66962595820SHans Verkuil 67062595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MUTE: 67162595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); 67262595820SHans Verkuil 67362595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 67462595820SHans Verkuil err = v4l2_ctrl_query_fill(qctrl, 67562595820SHans Verkuil V4L2_MPEG_AUDIO_AC3_BITRATE_48K, 67662595820SHans Verkuil V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1, 67762595820SHans Verkuil default_params.audio_ac3_bitrate); 67862595820SHans Verkuil if (err) 67962595820SHans Verkuil return err; 68062595820SHans Verkuil if (params->capabilities & CX2341X_CAP_HAS_AC3) { 68162595820SHans Verkuil if (params->audio_encoding != 68262595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_AC3) 68362595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 68462595820SHans Verkuil } else 68562595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; 68662595820SHans Verkuil return 0; 68762595820SHans Verkuil 68862595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ENCODING: 68962595820SHans Verkuil /* this setting is read-only for the cx2341x since the 69062595820SHans Verkuil V4L2_CID_MPEG_STREAM_TYPE really determines the 69162595820SHans Verkuil MPEG-1/2 setting */ 69262595820SHans Verkuil err = v4l2_ctrl_query_fill(qctrl, 69362595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_1, 69462595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, 69562595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2); 69662595820SHans Verkuil if (err == 0) 69762595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 69862595820SHans Verkuil return err; 69962595820SHans Verkuil 70062595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ASPECT: 70162595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 70262595820SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_1x1, 70362595820SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_221x100, 1, 70462595820SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_4x3); 70562595820SHans Verkuil 70662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_B_FRAMES: 70762595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); 70862595820SHans Verkuil 70962595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 71062595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 71162595820SHans Verkuil params->is_50hz ? 12 : 15); 71262595820SHans Verkuil 71362595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 71462595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); 71562595820SHans Verkuil 71662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 71762595820SHans Verkuil err = v4l2_ctrl_query_fill(qctrl, 71862595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, 71962595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, 72062595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 72162595820SHans Verkuil if (err == 0 && 72262595820SHans Verkuil params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 72362595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 72462595820SHans Verkuil return err; 72562595820SHans Verkuil 72662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE: 72762595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); 72862595820SHans Verkuil 72962595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 73062595820SHans Verkuil err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); 73162595820SHans Verkuil if (err == 0 && 73262595820SHans Verkuil params->video_bitrate_mode == 73362595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) 73462595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 73562595820SHans Verkuil return err; 73662595820SHans Verkuil 73762595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 73862595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); 73962595820SHans Verkuil 74062595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE: 74162595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); 74262595820SHans Verkuil 74362595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */ 74462595820SHans Verkuil return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080); 74562595820SHans Verkuil 74662595820SHans Verkuil /* CX23415/6 specific */ 74762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 74862595820SHans Verkuil return cx2341x_ctrl_query_fill(qctrl, 74962595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 75062595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1, 75162595820SHans Verkuil default_params.video_spatial_filter_mode); 75262595820SHans Verkuil 75362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 75462595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 75562595820SHans Verkuil default_params.video_spatial_filter); 75662595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 75762595820SHans Verkuil if (params->video_spatial_filter_mode == 75862595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 75962595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 76062595820SHans Verkuil return 0; 76162595820SHans Verkuil 76262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 76362595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 76462595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, 76562595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 76662595820SHans Verkuil 1, 76762595820SHans Verkuil default_params.video_luma_spatial_filter_type); 76862595820SHans Verkuil if (params->video_spatial_filter_mode == 76962595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 77062595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 77162595820SHans Verkuil return 0; 77262595820SHans Verkuil 77362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 77462595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 77562595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, 77662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 77762595820SHans Verkuil 1, 77862595820SHans Verkuil default_params.video_chroma_spatial_filter_type); 77962595820SHans Verkuil if (params->video_spatial_filter_mode == 78062595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 78162595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 78262595820SHans Verkuil return 0; 78362595820SHans Verkuil 78462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 78562595820SHans Verkuil return cx2341x_ctrl_query_fill(qctrl, 78662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 78762595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1, 78862595820SHans Verkuil default_params.video_temporal_filter_mode); 78962595820SHans Verkuil 79062595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 79162595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 79262595820SHans Verkuil default_params.video_temporal_filter); 79362595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 79462595820SHans Verkuil if (params->video_temporal_filter_mode == 79562595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO) 79662595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 79762595820SHans Verkuil return 0; 79862595820SHans Verkuil 79962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 80062595820SHans Verkuil return cx2341x_ctrl_query_fill(qctrl, 80162595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 80262595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1, 80362595820SHans Verkuil default_params.video_median_filter_type); 80462595820SHans Verkuil 80562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 80662595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 80762595820SHans Verkuil default_params.video_luma_median_filter_top); 80862595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 80962595820SHans Verkuil if (params->video_median_filter_type == 81062595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 81162595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 81262595820SHans Verkuil return 0; 81362595820SHans Verkuil 81462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 81562595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 81662595820SHans Verkuil default_params.video_luma_median_filter_bottom); 81762595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 81862595820SHans Verkuil if (params->video_median_filter_type == 81962595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 82062595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 82162595820SHans Verkuil return 0; 82262595820SHans Verkuil 82362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 82462595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 82562595820SHans Verkuil default_params.video_chroma_median_filter_top); 82662595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 82762595820SHans Verkuil if (params->video_median_filter_type == 82862595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 82962595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 83062595820SHans Verkuil return 0; 83162595820SHans Verkuil 83262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 83362595820SHans Verkuil cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 83462595820SHans Verkuil default_params.video_chroma_median_filter_bottom); 83562595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 83662595820SHans Verkuil if (params->video_median_filter_type == 83762595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 83862595820SHans Verkuil qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 83962595820SHans Verkuil return 0; 84062595820SHans Verkuil 84162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 84262595820SHans Verkuil return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 84362595820SHans Verkuil default_params.stream_insert_nav_packets); 84462595820SHans Verkuil 84562595820SHans Verkuil default: 84662595820SHans Verkuil return -EINVAL; 84762595820SHans Verkuil 84862595820SHans Verkuil } 84962595820SHans Verkuil } 85062595820SHans Verkuil EXPORT_SYMBOL(cx2341x_ctrl_query); 85162595820SHans Verkuil 85262595820SHans Verkuil const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) 85362595820SHans Verkuil { 85462595820SHans Verkuil static const char * const mpeg_stream_type_without_ts[] = { 85562595820SHans Verkuil "MPEG-2 Program Stream", 85662595820SHans Verkuil "", 85762595820SHans Verkuil "MPEG-1 System Stream", 85862595820SHans Verkuil "MPEG-2 DVD-compatible Stream", 85962595820SHans Verkuil "MPEG-1 VCD-compatible Stream", 86062595820SHans Verkuil "MPEG-2 SVCD-compatible Stream", 86162595820SHans Verkuil NULL 86262595820SHans Verkuil }; 86362595820SHans Verkuil 86462595820SHans Verkuil static const char *mpeg_stream_type_with_ts[] = { 86562595820SHans Verkuil "MPEG-2 Program Stream", 86662595820SHans Verkuil "MPEG-2 Transport Stream", 86762595820SHans Verkuil "MPEG-1 System Stream", 86862595820SHans Verkuil "MPEG-2 DVD-compatible Stream", 86962595820SHans Verkuil "MPEG-1 VCD-compatible Stream", 87062595820SHans Verkuil "MPEG-2 SVCD-compatible Stream", 87162595820SHans Verkuil NULL 87262595820SHans Verkuil }; 87362595820SHans Verkuil 87462595820SHans Verkuil static const char *mpeg_audio_encoding_l2_ac3[] = { 87562595820SHans Verkuil "", 87662595820SHans Verkuil "MPEG-1/2 Layer II", 87762595820SHans Verkuil "", 87862595820SHans Verkuil "", 87962595820SHans Verkuil "AC-3", 88062595820SHans Verkuil NULL 88162595820SHans Verkuil }; 88262595820SHans Verkuil 88362595820SHans Verkuil switch (id) { 88462595820SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 88562595820SHans Verkuil return (p->capabilities & CX2341X_CAP_HAS_TS) ? 88662595820SHans Verkuil mpeg_stream_type_with_ts : mpeg_stream_type_without_ts; 88762595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_ENCODING: 88862595820SHans Verkuil return (p->capabilities & CX2341X_CAP_HAS_AC3) ? 88962595820SHans Verkuil mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id); 89062595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 89162595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 89262595820SHans Verkuil return NULL; 89362595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 89462595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 89562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 89662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 89762595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 89862595820SHans Verkuil return cx2341x_get_menu(id); 89962595820SHans Verkuil default: 90062595820SHans Verkuil return v4l2_ctrl_get_menu(id); 90162595820SHans Verkuil } 90262595820SHans Verkuil } 90362595820SHans Verkuil EXPORT_SYMBOL(cx2341x_ctrl_get_menu); 90462595820SHans Verkuil 90562595820SHans Verkuil static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) 90662595820SHans Verkuil { 90762595820SHans Verkuil params->audio_properties = 90862595820SHans Verkuil (params->audio_sampling_freq << 0) | 90962595820SHans Verkuil (params->audio_mode << 8) | 91062595820SHans Verkuil (params->audio_mode_extension << 10) | 91162595820SHans Verkuil (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) 91262595820SHans Verkuil ? 3 : params->audio_emphasis) << 12) | 91362595820SHans Verkuil (params->audio_crc << 14); 91462595820SHans Verkuil 91562595820SHans Verkuil if ((params->capabilities & CX2341X_CAP_HAS_AC3) && 91662595820SHans Verkuil params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { 91762595820SHans Verkuil params->audio_properties |= 91862595820SHans Verkuil /* Not sure if this MPEG Layer II setting is required */ 91962595820SHans Verkuil ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | 92062595820SHans Verkuil (params->audio_ac3_bitrate << 4) | 92162595820SHans Verkuil (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28); 92262595820SHans Verkuil } else { 92362595820SHans Verkuil /* Assuming MPEG Layer II */ 92462595820SHans Verkuil params->audio_properties |= 92562595820SHans Verkuil ((3 - params->audio_encoding) << 2) | 92662595820SHans Verkuil ((1 + params->audio_l2_bitrate) << 4); 92762595820SHans Verkuil } 92862595820SHans Verkuil } 92962595820SHans Verkuil 9304daee779SHans Verkuil /* Check for correctness of the ctrl's value based on the data from 9314daee779SHans Verkuil struct v4l2_queryctrl and the available menu items. Note that 9324daee779SHans Verkuil menu_items may be NULL, in that case it is ignored. */ 9334daee779SHans Verkuil static int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, 9344daee779SHans Verkuil const char * const *menu_items) 9354daee779SHans Verkuil { 9364daee779SHans Verkuil if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) 9374daee779SHans Verkuil return -EINVAL; 9384daee779SHans Verkuil if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) 9394daee779SHans Verkuil return -EBUSY; 9404daee779SHans Verkuil if (qctrl->type == V4L2_CTRL_TYPE_STRING) 9414daee779SHans Verkuil return 0; 9424daee779SHans Verkuil if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || 9434daee779SHans Verkuil qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || 9444daee779SHans Verkuil qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) 9454daee779SHans Verkuil return 0; 9464daee779SHans Verkuil if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum) 9474daee779SHans Verkuil return -ERANGE; 9484daee779SHans Verkuil if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) { 9494daee779SHans Verkuil if (menu_items[ctrl->value] == NULL || 9504daee779SHans Verkuil menu_items[ctrl->value][0] == '\0') 9514daee779SHans Verkuil return -EINVAL; 9524daee779SHans Verkuil } 9534daee779SHans Verkuil if (qctrl->type == V4L2_CTRL_TYPE_BITMASK && 9544daee779SHans Verkuil (ctrl->value & ~qctrl->maximum)) 9554daee779SHans Verkuil return -ERANGE; 9564daee779SHans Verkuil return 0; 9574daee779SHans Verkuil } 9584daee779SHans Verkuil 95962595820SHans Verkuil int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, 96062595820SHans Verkuil struct v4l2_ext_controls *ctrls, unsigned int cmd) 96162595820SHans Verkuil { 96262595820SHans Verkuil int err = 0; 96362595820SHans Verkuil int i; 96462595820SHans Verkuil 96562595820SHans Verkuil if (cmd == VIDIOC_G_EXT_CTRLS) { 96662595820SHans Verkuil for (i = 0; i < ctrls->count; i++) { 96762595820SHans Verkuil struct v4l2_ext_control *ctrl = ctrls->controls + i; 96862595820SHans Verkuil 96962595820SHans Verkuil err = cx2341x_get_ctrl(params, ctrl); 97062595820SHans Verkuil if (err) { 97162595820SHans Verkuil ctrls->error_idx = i; 97262595820SHans Verkuil break; 97362595820SHans Verkuil } 97462595820SHans Verkuil } 97562595820SHans Verkuil return err; 97662595820SHans Verkuil } 97762595820SHans Verkuil for (i = 0; i < ctrls->count; i++) { 97862595820SHans Verkuil struct v4l2_ext_control *ctrl = ctrls->controls + i; 97962595820SHans Verkuil struct v4l2_queryctrl qctrl; 98062595820SHans Verkuil const char * const *menu_items = NULL; 98162595820SHans Verkuil 98262595820SHans Verkuil qctrl.id = ctrl->id; 98362595820SHans Verkuil err = cx2341x_ctrl_query(params, &qctrl); 98462595820SHans Verkuil if (err) 98562595820SHans Verkuil break; 98662595820SHans Verkuil if (qctrl.type == V4L2_CTRL_TYPE_MENU) 98762595820SHans Verkuil menu_items = cx2341x_ctrl_get_menu(params, qctrl.id); 98862595820SHans Verkuil err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); 98962595820SHans Verkuil if (err) 99062595820SHans Verkuil break; 99162595820SHans Verkuil err = cx2341x_set_ctrl(params, busy, ctrl); 99262595820SHans Verkuil if (err) 99362595820SHans Verkuil break; 99462595820SHans Verkuil } 99562595820SHans Verkuil if (err == 0 && 99662595820SHans Verkuil params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && 99762595820SHans Verkuil params->video_bitrate_peak < params->video_bitrate) { 99862595820SHans Verkuil err = -ERANGE; 99962595820SHans Verkuil ctrls->error_idx = ctrls->count; 100062595820SHans Verkuil } 100162595820SHans Verkuil if (err) 100262595820SHans Verkuil ctrls->error_idx = i; 100362595820SHans Verkuil else 100462595820SHans Verkuil cx2341x_calc_audio_properties(params); 100562595820SHans Verkuil return err; 100662595820SHans Verkuil } 100762595820SHans Verkuil EXPORT_SYMBOL(cx2341x_ext_ctrls); 100862595820SHans Verkuil 100962595820SHans Verkuil void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) 101062595820SHans Verkuil { 101162595820SHans Verkuil *p = default_params; 101262595820SHans Verkuil cx2341x_calc_audio_properties(p); 101362595820SHans Verkuil } 101462595820SHans Verkuil EXPORT_SYMBOL(cx2341x_fill_defaults); 101562595820SHans Verkuil 101662595820SHans Verkuil static int cx2341x_api(void *priv, cx2341x_mbox_func func, 101762595820SHans Verkuil u32 cmd, int args, ...) 101862595820SHans Verkuil { 101962595820SHans Verkuil u32 data[CX2341X_MBOX_MAX_DATA]; 102062595820SHans Verkuil va_list vargs; 102162595820SHans Verkuil int i; 102262595820SHans Verkuil 102362595820SHans Verkuil va_start(vargs, args); 102462595820SHans Verkuil 102562595820SHans Verkuil for (i = 0; i < args; i++) 102662595820SHans Verkuil data[i] = va_arg(vargs, int); 102762595820SHans Verkuil va_end(vargs); 102862595820SHans Verkuil return func(priv, cmd, args, 0, data); 102962595820SHans Verkuil } 103062595820SHans Verkuil 10313d19cde7SMauro Carvalho Chehab #define CMP_FIELD(__old, __new, __field) (__old->__field != __new->__field) 103262595820SHans Verkuil 103362595820SHans Verkuil int cx2341x_update(void *priv, cx2341x_mbox_func func, 103462595820SHans Verkuil const struct cx2341x_mpeg_params *old, 103562595820SHans Verkuil const struct cx2341x_mpeg_params *new) 103662595820SHans Verkuil { 103762595820SHans Verkuil static int mpeg_stream_type[] = { 103862595820SHans Verkuil 0, /* MPEG-2 PS */ 103962595820SHans Verkuil 1, /* MPEG-2 TS */ 104062595820SHans Verkuil 2, /* MPEG-1 SS */ 104162595820SHans Verkuil 14, /* DVD */ 104262595820SHans Verkuil 11, /* VCD */ 104362595820SHans Verkuil 12, /* SVCD */ 104462595820SHans Verkuil }; 10453d19cde7SMauro Carvalho Chehab int err; 104662595820SHans Verkuil 104762595820SHans Verkuil cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0); 104862595820SHans Verkuil 10493d19cde7SMauro Carvalho Chehab if (!old || 10503d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, is_50hz)) { 105162595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, 105262595820SHans Verkuil new->is_50hz); 10533d19cde7SMauro Carvalho Chehab if (err) 10543d19cde7SMauro Carvalho Chehab return err; 105562595820SHans Verkuil } 105662595820SHans Verkuil 10573d19cde7SMauro Carvalho Chehab if (!old || 10583d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, width) || 10593d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, height) || 10603d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_encoding)) { 106162595820SHans Verkuil u16 w = new->width; 106262595820SHans Verkuil u16 h = new->height; 106362595820SHans Verkuil 106462595820SHans Verkuil if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { 106562595820SHans Verkuil w /= 2; 106662595820SHans Verkuil h /= 2; 106762595820SHans Verkuil } 106862595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, 106962595820SHans Verkuil h, w); 10703d19cde7SMauro Carvalho Chehab if (err) 10713d19cde7SMauro Carvalho Chehab return err; 107262595820SHans Verkuil } 10733d19cde7SMauro Carvalho Chehab if (!old || 10743d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, stream_type)) { 107562595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, 107662595820SHans Verkuil mpeg_stream_type[new->stream_type]); 10773d19cde7SMauro Carvalho Chehab if (err) 10783d19cde7SMauro Carvalho Chehab return err; 107962595820SHans Verkuil } 10803d19cde7SMauro Carvalho Chehab if (!old || 10813d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_aspect)) { 108262595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 108362595820SHans Verkuil 1 + new->video_aspect); 10843d19cde7SMauro Carvalho Chehab if (err) 10853d19cde7SMauro Carvalho Chehab return err; 108662595820SHans Verkuil } 10873d19cde7SMauro Carvalho Chehab if (!old || 10883d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_b_frames) || 10893d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_gop_size)) { 109062595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2, 109162595820SHans Verkuil new->video_gop_size, new->video_b_frames + 1); 10923d19cde7SMauro Carvalho Chehab if (err) 10933d19cde7SMauro Carvalho Chehab return err; 109462595820SHans Verkuil } 10953d19cde7SMauro Carvalho Chehab if (!old || 10963d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_gop_closure)) { 109762595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, 109862595820SHans Verkuil new->video_gop_closure); 10993d19cde7SMauro Carvalho Chehab if (err) 11003d19cde7SMauro Carvalho Chehab return err; 110162595820SHans Verkuil } 11023d19cde7SMauro Carvalho Chehab if (!old || 11033d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, audio_properties)) { 110462595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 110562595820SHans Verkuil 1, new->audio_properties); 11063d19cde7SMauro Carvalho Chehab if (err) 11073d19cde7SMauro Carvalho Chehab return err; 110862595820SHans Verkuil } 11093d19cde7SMauro Carvalho Chehab if (!old || 11103d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, audio_mute)) { 111162595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, 111262595820SHans Verkuil new->audio_mute); 11133d19cde7SMauro Carvalho Chehab if (err) 11143d19cde7SMauro Carvalho Chehab return err; 111562595820SHans Verkuil } 11163d19cde7SMauro Carvalho Chehab if (!old || 11173d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_bitrate_mode) || 11183d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_bitrate) || 11193d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_bitrate_peak)) { 112062595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5, 112162595820SHans Verkuil new->video_bitrate_mode, new->video_bitrate, 112262595820SHans Verkuil new->video_bitrate_peak / 400, 0, 0); 11233d19cde7SMauro Carvalho Chehab if (err) 11243d19cde7SMauro Carvalho Chehab return err; 112562595820SHans Verkuil } 11263d19cde7SMauro Carvalho Chehab if (!old || 11273d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_spatial_filter_mode) || 11283d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_temporal_filter_mode) || 11293d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_median_filter_type)) { 113062595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 11313d19cde7SMauro Carvalho Chehab 2, 11323d19cde7SMauro Carvalho Chehab new->video_spatial_filter_mode | 113362595820SHans Verkuil (new->video_temporal_filter_mode << 1), 113462595820SHans Verkuil new->video_median_filter_type); 11353d19cde7SMauro Carvalho Chehab if (err) 11363d19cde7SMauro Carvalho Chehab return err; 113762595820SHans Verkuil } 11383d19cde7SMauro Carvalho Chehab if (!old || 11393d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_luma_median_filter_bottom) || 11403d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_luma_median_filter_top) || 11413d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_chroma_median_filter_bottom) || 11423d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_chroma_median_filter_top)) { 114362595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4, 114462595820SHans Verkuil new->video_luma_median_filter_bottom, 114562595820SHans Verkuil new->video_luma_median_filter_top, 114662595820SHans Verkuil new->video_chroma_median_filter_bottom, 114762595820SHans Verkuil new->video_chroma_median_filter_top); 11483d19cde7SMauro Carvalho Chehab if (err) 11493d19cde7SMauro Carvalho Chehab return err; 115062595820SHans Verkuil } 11513d19cde7SMauro Carvalho Chehab if (!old || 11523d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_luma_spatial_filter_type) || 11533d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_chroma_spatial_filter_type)) { 115462595820SHans Verkuil err = cx2341x_api(priv, func, 115562595820SHans Verkuil CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 115662595820SHans Verkuil 2, new->video_luma_spatial_filter_type, 115762595820SHans Verkuil new->video_chroma_spatial_filter_type); 11583d19cde7SMauro Carvalho Chehab if (err) 11593d19cde7SMauro Carvalho Chehab return err; 116062595820SHans Verkuil } 11613d19cde7SMauro Carvalho Chehab if (!old || 11623d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_spatial_filter) || 11633d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_temporal_filter)) { 116462595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 11653d19cde7SMauro Carvalho Chehab 2, new->video_spatial_filter, 11663d19cde7SMauro Carvalho Chehab new->video_temporal_filter); 11673d19cde7SMauro Carvalho Chehab if (err) 11683d19cde7SMauro Carvalho Chehab return err; 116962595820SHans Verkuil } 11703d19cde7SMauro Carvalho Chehab if (!old || 11713d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_temporal_decimation)) { 117262595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 117362595820SHans Verkuil 1, new->video_temporal_decimation); 11743d19cde7SMauro Carvalho Chehab if (err) 11753d19cde7SMauro Carvalho Chehab return err; 117662595820SHans Verkuil } 11773d19cde7SMauro Carvalho Chehab if (!old || 11783d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, video_mute) || 11793d19cde7SMauro Carvalho Chehab (new->video_mute && CMP_FIELD(old, new, video_mute_yuv))) { 118062595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, 118162595820SHans Verkuil new->video_mute | (new->video_mute_yuv << 8)); 11823d19cde7SMauro Carvalho Chehab if (err) 11833d19cde7SMauro Carvalho Chehab return err; 118462595820SHans Verkuil } 11853d19cde7SMauro Carvalho Chehab if (!old || 11863d19cde7SMauro Carvalho Chehab CMP_FIELD(old, new, stream_insert_nav_packets)) { 118762595820SHans Verkuil err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, 118862595820SHans Verkuil 7, new->stream_insert_nav_packets); 11893d19cde7SMauro Carvalho Chehab if (err) 11903d19cde7SMauro Carvalho Chehab return err; 119162595820SHans Verkuil } 119262595820SHans Verkuil return 0; 119362595820SHans Verkuil } 119462595820SHans Verkuil EXPORT_SYMBOL(cx2341x_update); 119562595820SHans Verkuil 119662595820SHans Verkuil static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id) 119762595820SHans Verkuil { 119862595820SHans Verkuil const char * const *menu = cx2341x_ctrl_get_menu(p, id); 119962595820SHans Verkuil struct v4l2_ext_control ctrl; 120062595820SHans Verkuil 120162595820SHans Verkuil if (menu == NULL) 120262595820SHans Verkuil goto invalid; 120362595820SHans Verkuil ctrl.id = id; 120462595820SHans Verkuil if (cx2341x_get_ctrl(p, &ctrl)) 120562595820SHans Verkuil goto invalid; 120662595820SHans Verkuil while (ctrl.value-- && *menu) menu++; 120762595820SHans Verkuil if (*menu == NULL) 120862595820SHans Verkuil goto invalid; 120962595820SHans Verkuil return *menu; 121062595820SHans Verkuil 121162595820SHans Verkuil invalid: 121262595820SHans Verkuil return "<invalid>"; 121362595820SHans Verkuil } 121462595820SHans Verkuil 121562595820SHans Verkuil void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) 121662595820SHans Verkuil { 121762595820SHans Verkuil int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 121862595820SHans Verkuil 121962595820SHans Verkuil /* Stream */ 122062595820SHans Verkuil printk(KERN_INFO "%s: Stream: %s", 122162595820SHans Verkuil prefix, 122262595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE)); 122362595820SHans Verkuil if (p->stream_insert_nav_packets) 12246dd23d4cSMauro Carvalho Chehab printk(KERN_CONT " (with navigation packets)"); 12256dd23d4cSMauro Carvalho Chehab printk(KERN_CONT "\n"); 122662595820SHans Verkuil printk(KERN_INFO "%s: VBI Format: %s\n", 122762595820SHans Verkuil prefix, 122862595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT)); 122962595820SHans Verkuil 123062595820SHans Verkuil /* Video */ 123162595820SHans Verkuil printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n", 123262595820SHans Verkuil prefix, 123362595820SHans Verkuil p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1), 123462595820SHans Verkuil p->is_50hz ? 25 : 30, 123562595820SHans Verkuil (p->video_mute) ? " (muted)" : ""); 123662595820SHans Verkuil printk(KERN_INFO "%s: Video: %s, %s, %s, %d", 123762595820SHans Verkuil prefix, 123862595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING), 123962595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT), 124062595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE), 124162595820SHans Verkuil p->video_bitrate); 124262595820SHans Verkuil if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) 12436dd23d4cSMauro Carvalho Chehab printk(KERN_CONT ", Peak %d", p->video_bitrate_peak); 12446dd23d4cSMauro Carvalho Chehab printk(KERN_CONT "\n"); 124562595820SHans Verkuil printk(KERN_INFO 124662595820SHans Verkuil "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n", 124762595820SHans Verkuil prefix, 124862595820SHans Verkuil p->video_gop_size, p->video_b_frames, 124962595820SHans Verkuil p->video_gop_closure ? "" : "No "); 125062595820SHans Verkuil if (p->video_temporal_decimation) 125162595820SHans Verkuil printk(KERN_INFO "%s: Video: Temporal Decimation %d\n", 125262595820SHans Verkuil prefix, p->video_temporal_decimation); 125362595820SHans Verkuil 125462595820SHans Verkuil /* Audio */ 125562595820SHans Verkuil printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s", 125662595820SHans Verkuil prefix, 125762595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), 125862595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), 125962595820SHans Verkuil cx2341x_menu_item(p, 126062595820SHans Verkuil p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3 126162595820SHans Verkuil ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE 126262595820SHans Verkuil : V4L2_CID_MPEG_AUDIO_L2_BITRATE), 126362595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE), 126462595820SHans Verkuil p->audio_mute ? " (muted)" : ""); 126562595820SHans Verkuil if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) 12666dd23d4cSMauro Carvalho Chehab printk(KERN_CONT ", %s", cx2341x_menu_item(p, 126762595820SHans Verkuil V4L2_CID_MPEG_AUDIO_MODE_EXTENSION)); 12686dd23d4cSMauro Carvalho Chehab printk(KERN_CONT ", %s, %s\n", 126962595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS), 127062595820SHans Verkuil cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC)); 127162595820SHans Verkuil 127262595820SHans Verkuil /* Encoding filters */ 127362595820SHans Verkuil printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", 127462595820SHans Verkuil prefix, 127562595820SHans Verkuil cx2341x_menu_item(p, 127662595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE), 127762595820SHans Verkuil cx2341x_menu_item(p, 127862595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE), 127962595820SHans Verkuil cx2341x_menu_item(p, 128062595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), 128162595820SHans Verkuil p->video_spatial_filter); 128262595820SHans Verkuil 128362595820SHans Verkuil printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", 128462595820SHans Verkuil prefix, 128562595820SHans Verkuil cx2341x_menu_item(p, 128662595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), 128762595820SHans Verkuil p->video_temporal_filter); 128862595820SHans Verkuil printk(KERN_INFO 128962595820SHans Verkuil "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", 129062595820SHans Verkuil prefix, 129162595820SHans Verkuil cx2341x_menu_item(p, 129262595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE), 129362595820SHans Verkuil p->video_luma_median_filter_bottom, 129462595820SHans Verkuil p->video_luma_median_filter_top, 129562595820SHans Verkuil p->video_chroma_median_filter_bottom, 129662595820SHans Verkuil p->video_chroma_median_filter_top); 129762595820SHans Verkuil } 129862595820SHans Verkuil EXPORT_SYMBOL(cx2341x_log_status); 129962595820SHans Verkuil 130062595820SHans Verkuil 130162595820SHans Verkuil 130262595820SHans Verkuil /********************** NEW CODE *********************/ 130362595820SHans Verkuil 130462595820SHans Verkuil static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl) 130562595820SHans Verkuil { 130662595820SHans Verkuil return container_of(ctrl->handler, struct cx2341x_handler, hdl); 130762595820SHans Verkuil } 130862595820SHans Verkuil 130962595820SHans Verkuil static int cx2341x_hdl_api(struct cx2341x_handler *hdl, 131062595820SHans Verkuil u32 cmd, int args, ...) 131162595820SHans Verkuil { 131262595820SHans Verkuil u32 data[CX2341X_MBOX_MAX_DATA]; 131362595820SHans Verkuil va_list vargs; 131462595820SHans Verkuil int i; 131562595820SHans Verkuil 131662595820SHans Verkuil va_start(vargs, args); 131762595820SHans Verkuil 131862595820SHans Verkuil for (i = 0; i < args; i++) 131962595820SHans Verkuil data[i] = va_arg(vargs, int); 132062595820SHans Verkuil va_end(vargs); 132162595820SHans Verkuil return hdl->func(hdl->priv, cmd, args, 0, data); 132262595820SHans Verkuil } 132362595820SHans Verkuil 132462595820SHans Verkuil /* ctrl->handler->lock is held, so it is safe to access cur.val */ 132562595820SHans Verkuil static inline int cx2341x_neq(struct v4l2_ctrl *ctrl) 132662595820SHans Verkuil { 132762595820SHans Verkuil return ctrl && ctrl->val != ctrl->cur.val; 132862595820SHans Verkuil } 132962595820SHans Verkuil 133062595820SHans Verkuil static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl) 133162595820SHans Verkuil { 133262595820SHans Verkuil struct cx2341x_handler *hdl = to_cxhdl(ctrl); 133362595820SHans Verkuil s32 val = ctrl->val; 133462595820SHans Verkuil 133562595820SHans Verkuil switch (ctrl->id) { 133662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_B_FRAMES: { 133762595820SHans Verkuil /* video gop cluster */ 133862595820SHans Verkuil int b = val + 1; 133962595820SHans Verkuil int gop = hdl->video_gop_size->val; 134062595820SHans Verkuil 134162595820SHans Verkuil gop = b * ((gop + b - 1) / b); 134262595820SHans Verkuil 134362595820SHans Verkuil /* Max GOP size = 34 */ 134462595820SHans Verkuil while (gop > 34) 134562595820SHans Verkuil gop -= b; 134662595820SHans Verkuil hdl->video_gop_size->val = gop; 134762595820SHans Verkuil break; 134862595820SHans Verkuil } 134962595820SHans Verkuil 135062595820SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 135162595820SHans Verkuil /* stream type cluster */ 135262595820SHans Verkuil hdl->video_encoding->val = 135362595820SHans Verkuil (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || 135462595820SHans Verkuil hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? 135562595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : 135662595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2; 135762595820SHans Verkuil if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 135862595820SHans Verkuil /* MPEG-1 implies CBR */ 135962595820SHans Verkuil hdl->video_bitrate_mode->val = 136062595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; 136162595820SHans Verkuil /* peak bitrate shall be >= normal bitrate */ 136262595820SHans Verkuil if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && 136362595820SHans Verkuil hdl->video_bitrate_peak->val < hdl->video_bitrate->val) 136462595820SHans Verkuil hdl->video_bitrate_peak->val = hdl->video_bitrate->val; 136562595820SHans Verkuil break; 136662595820SHans Verkuil } 136762595820SHans Verkuil return 0; 136862595820SHans Verkuil } 136962595820SHans Verkuil 137062595820SHans Verkuil static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl) 137162595820SHans Verkuil { 137262595820SHans Verkuil static const int mpeg_stream_type[] = { 137362595820SHans Verkuil 0, /* MPEG-2 PS */ 137462595820SHans Verkuil 1, /* MPEG-2 TS */ 137562595820SHans Verkuil 2, /* MPEG-1 SS */ 137662595820SHans Verkuil 14, /* DVD */ 137762595820SHans Verkuil 11, /* VCD */ 137862595820SHans Verkuil 12, /* SVCD */ 137962595820SHans Verkuil }; 138062595820SHans Verkuil struct cx2341x_handler *hdl = to_cxhdl(ctrl); 138162595820SHans Verkuil s32 val = ctrl->val; 138262595820SHans Verkuil u32 props; 138362595820SHans Verkuil int err; 138462595820SHans Verkuil 138562595820SHans Verkuil switch (ctrl->id) { 138662595820SHans Verkuil case V4L2_CID_MPEG_STREAM_VBI_FMT: 138762595820SHans Verkuil if (hdl->ops && hdl->ops->s_stream_vbi_fmt) 138862595820SHans Verkuil return hdl->ops->s_stream_vbi_fmt(hdl, val); 138962595820SHans Verkuil return 0; 139062595820SHans Verkuil 139162595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_ASPECT: 139262595820SHans Verkuil return cx2341x_hdl_api(hdl, 139362595820SHans Verkuil CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1); 139462595820SHans Verkuil 139562595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 139662595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val); 139762595820SHans Verkuil 139862595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_MUTE: 139962595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val); 140062595820SHans Verkuil 140162595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: 140262595820SHans Verkuil return cx2341x_hdl_api(hdl, 140362595820SHans Verkuil CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val); 140462595820SHans Verkuil 140562595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 140662595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val); 140762595820SHans Verkuil 140862595820SHans Verkuil case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 140962595820SHans Verkuil /* audio properties cluster */ 141062595820SHans Verkuil props = (hdl->audio_sampling_freq->val << 0) | 141162595820SHans Verkuil (hdl->audio_mode->val << 8) | 141262595820SHans Verkuil (hdl->audio_mode_extension->val << 10) | 141362595820SHans Verkuil (hdl->audio_crc->val << 14); 141462595820SHans Verkuil if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) 141562595820SHans Verkuil props |= 3 << 12; 141662595820SHans Verkuil else 141762595820SHans Verkuil props |= hdl->audio_emphasis->val << 12; 141862595820SHans Verkuil 141962595820SHans Verkuil if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) { 142062595820SHans Verkuil props |= 142162595820SHans Verkuil #if 1 142262595820SHans Verkuil /* Not sure if this MPEG Layer II setting is required */ 142362595820SHans Verkuil ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | 142462595820SHans Verkuil #endif 142562595820SHans Verkuil (hdl->audio_ac3_bitrate->val << 4) | 142662595820SHans Verkuil (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28); 142762595820SHans Verkuil } else { 142862595820SHans Verkuil /* Assuming MPEG Layer II */ 142962595820SHans Verkuil props |= 143062595820SHans Verkuil ((3 - hdl->audio_encoding->val) << 2) | 143162595820SHans Verkuil ((1 + hdl->audio_l2_bitrate->val) << 4); 143262595820SHans Verkuil } 143362595820SHans Verkuil err = cx2341x_hdl_api(hdl, 143462595820SHans Verkuil CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props); 143562595820SHans Verkuil if (err) 143662595820SHans Verkuil return err; 143762595820SHans Verkuil 143862595820SHans Verkuil hdl->audio_properties = props; 143962595820SHans Verkuil if (hdl->audio_ac3_bitrate) { 144062595820SHans Verkuil int is_ac3 = hdl->audio_encoding->val == 144162595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_AC3; 144262595820SHans Verkuil 144362595820SHans Verkuil v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3); 144462595820SHans Verkuil v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3); 144562595820SHans Verkuil } 144662595820SHans Verkuil v4l2_ctrl_activate(hdl->audio_mode_extension, 144762595820SHans Verkuil hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO); 144862595820SHans Verkuil if (cx2341x_neq(hdl->audio_sampling_freq) && 144962595820SHans Verkuil hdl->ops && hdl->ops->s_audio_sampling_freq) 145062595820SHans Verkuil return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val); 145162595820SHans Verkuil if (cx2341x_neq(hdl->audio_mode) && 145262595820SHans Verkuil hdl->ops && hdl->ops->s_audio_mode) 145362595820SHans Verkuil return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val); 145462595820SHans Verkuil return 0; 145562595820SHans Verkuil 145662595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_B_FRAMES: 145762595820SHans Verkuil /* video gop cluster */ 145862595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2, 145962595820SHans Verkuil hdl->video_gop_size->val, 146062595820SHans Verkuil hdl->video_b_frames->val + 1); 146162595820SHans Verkuil 146262595820SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 146362595820SHans Verkuil /* stream type cluster */ 146462595820SHans Verkuil err = cx2341x_hdl_api(hdl, 146562595820SHans Verkuil CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]); 146662595820SHans Verkuil if (err) 146762595820SHans Verkuil return err; 146862595820SHans Verkuil 146962595820SHans Verkuil err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5, 147062595820SHans Verkuil hdl->video_bitrate_mode->val, 147162595820SHans Verkuil hdl->video_bitrate->val, 147262595820SHans Verkuil hdl->video_bitrate_peak->val / 400, 0, 0); 147362595820SHans Verkuil if (err) 147462595820SHans Verkuil return err; 147562595820SHans Verkuil 147662595820SHans Verkuil v4l2_ctrl_activate(hdl->video_bitrate_mode, 147762595820SHans Verkuil hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1); 147862595820SHans Verkuil v4l2_ctrl_activate(hdl->video_bitrate_peak, 147962595820SHans Verkuil hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); 148062595820SHans Verkuil if (cx2341x_neq(hdl->video_encoding) && 148162595820SHans Verkuil hdl->ops && hdl->ops->s_video_encoding) 148262595820SHans Verkuil return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val); 148362595820SHans Verkuil return 0; 148462595820SHans Verkuil 148562595820SHans Verkuil case V4L2_CID_MPEG_VIDEO_MUTE: 148662595820SHans Verkuil /* video mute cluster */ 148762595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1, 148862595820SHans Verkuil hdl->video_mute->val | 148962595820SHans Verkuil (hdl->video_mute_yuv->val << 8)); 149062595820SHans Verkuil 149162595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: { 149262595820SHans Verkuil int active_filter; 149362595820SHans Verkuil 149462595820SHans Verkuil /* video filter mode */ 149562595820SHans Verkuil err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, 149662595820SHans Verkuil hdl->video_spatial_filter_mode->val | 149762595820SHans Verkuil (hdl->video_temporal_filter_mode->val << 1), 149862595820SHans Verkuil hdl->video_median_filter_type->val); 149962595820SHans Verkuil if (err) 150062595820SHans Verkuil return err; 150162595820SHans Verkuil 150262595820SHans Verkuil active_filter = hdl->video_spatial_filter_mode->val != 150362595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO; 150462595820SHans Verkuil v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter); 150562595820SHans Verkuil v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter); 150662595820SHans Verkuil v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter); 150762595820SHans Verkuil active_filter = hdl->video_temporal_filter_mode->val != 150862595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO; 150962595820SHans Verkuil v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter); 151062595820SHans Verkuil active_filter = hdl->video_median_filter_type->val != 151162595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF; 151262595820SHans Verkuil v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter); 151362595820SHans Verkuil v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter); 151462595820SHans Verkuil v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter); 151562595820SHans Verkuil v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter); 151662595820SHans Verkuil return 0; 151762595820SHans Verkuil } 151862595820SHans Verkuil 151962595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 152062595820SHans Verkuil /* video filter type cluster */ 152162595820SHans Verkuil return cx2341x_hdl_api(hdl, 152262595820SHans Verkuil CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, 152362595820SHans Verkuil hdl->video_luma_spatial_filter_type->val, 152462595820SHans Verkuil hdl->video_chroma_spatial_filter_type->val); 152562595820SHans Verkuil 152662595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 152762595820SHans Verkuil /* video filter cluster */ 152862595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, 152962595820SHans Verkuil hdl->video_spatial_filter->val, 153062595820SHans Verkuil hdl->video_temporal_filter->val); 153162595820SHans Verkuil 153262595820SHans Verkuil case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 153362595820SHans Verkuil /* video median cluster */ 153462595820SHans Verkuil return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4, 153562595820SHans Verkuil hdl->video_luma_median_filter_bottom->val, 153662595820SHans Verkuil hdl->video_luma_median_filter_top->val, 153762595820SHans Verkuil hdl->video_chroma_median_filter_bottom->val, 153862595820SHans Verkuil hdl->video_chroma_median_filter_top->val); 153962595820SHans Verkuil } 154062595820SHans Verkuil return -EINVAL; 154162595820SHans Verkuil } 154262595820SHans Verkuil 154362595820SHans Verkuil static const struct v4l2_ctrl_ops cx2341x_ops = { 154462595820SHans Verkuil .try_ctrl = cx2341x_try_ctrl, 154562595820SHans Verkuil .s_ctrl = cx2341x_s_ctrl, 154662595820SHans Verkuil }; 154762595820SHans Verkuil 154862595820SHans Verkuil static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, 154962595820SHans Verkuil u32 id, s32 min, s32 max, s32 step, s32 def) 155062595820SHans Verkuil { 155162595820SHans Verkuil struct v4l2_ctrl_config cfg; 155262595820SHans Verkuil 155350394e73SHans Verkuil memset(&cfg, 0, sizeof(cfg)); 155462595820SHans Verkuil cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags); 155562595820SHans Verkuil cfg.ops = &cx2341x_ops; 155662595820SHans Verkuil cfg.id = id; 155762595820SHans Verkuil cfg.min = min; 155862595820SHans Verkuil cfg.max = max; 155962595820SHans Verkuil cfg.def = def; 156062595820SHans Verkuil if (cfg.type == V4L2_CTRL_TYPE_MENU) { 156162595820SHans Verkuil cfg.step = 0; 156262595820SHans Verkuil cfg.menu_skip_mask = step; 156362595820SHans Verkuil cfg.qmenu = cx2341x_get_menu(id); 156462595820SHans Verkuil } else { 156562595820SHans Verkuil cfg.step = step; 156662595820SHans Verkuil cfg.menu_skip_mask = 0; 156762595820SHans Verkuil } 156862595820SHans Verkuil return v4l2_ctrl_new_custom(hdl, &cfg, NULL); 156962595820SHans Verkuil } 157062595820SHans Verkuil 157162595820SHans Verkuil static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl, 157262595820SHans Verkuil u32 id, s32 min, s32 max, s32 step, s32 def) 157362595820SHans Verkuil { 157462595820SHans Verkuil return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def); 157562595820SHans Verkuil } 157662595820SHans Verkuil 157762595820SHans Verkuil static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl, 157862595820SHans Verkuil u32 id, s32 max, s32 mask, s32 def) 157962595820SHans Verkuil { 158062595820SHans Verkuil return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def); 158162595820SHans Verkuil } 158262595820SHans Verkuil 158362595820SHans Verkuil int cx2341x_handler_init(struct cx2341x_handler *cxhdl, 158462595820SHans Verkuil unsigned nr_of_controls_hint) 158562595820SHans Verkuil { 158662595820SHans Verkuil struct v4l2_ctrl_handler *hdl = &cxhdl->hdl; 158762595820SHans Verkuil u32 caps = cxhdl->capabilities; 158862595820SHans Verkuil int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI; 158962595820SHans Verkuil int has_ac3 = caps & CX2341X_CAP_HAS_AC3; 159062595820SHans Verkuil int has_ts = caps & CX2341X_CAP_HAS_TS; 159162595820SHans Verkuil 159262595820SHans Verkuil cxhdl->width = 720; 159362595820SHans Verkuil cxhdl->height = 480; 159462595820SHans Verkuil 159562595820SHans Verkuil v4l2_ctrl_handler_init(hdl, nr_of_controls_hint); 159662595820SHans Verkuil 159762595820SHans Verkuil /* Add controls in ascending control ID order for fastest 159862595820SHans Verkuil insertion time. */ 159962595820SHans Verkuil cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl, 160062595820SHans Verkuil V4L2_CID_MPEG_STREAM_TYPE, 160162595820SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2, 160262595820SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_PS); 160362595820SHans Verkuil cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl, 160462595820SHans Verkuil V4L2_CID_MPEG_STREAM_VBI_FMT, 160562595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2, 160662595820SHans Verkuil V4L2_MPEG_STREAM_VBI_FMT_NONE); 160762595820SHans Verkuil cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl, 160862595820SHans Verkuil V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, 160962595820SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0, 161062595820SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); 161162595820SHans Verkuil cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl, 161262595820SHans Verkuil V4L2_CID_MPEG_AUDIO_ENCODING, 161362595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2, 161462595820SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_LAYER_2); 161562595820SHans Verkuil cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl, 161662595820SHans Verkuil V4L2_CID_MPEG_AUDIO_L2_BITRATE, 161762595820SHans Verkuil V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff, 161862595820SHans Verkuil V4L2_MPEG_AUDIO_L2_BITRATE_224K); 161962595820SHans Verkuil cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl, 162062595820SHans Verkuil V4L2_CID_MPEG_AUDIO_MODE, 162162595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_MONO, 0, 162262595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_STEREO); 162362595820SHans Verkuil cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl, 162462595820SHans Verkuil V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, 162562595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0, 162662595820SHans Verkuil V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); 162762595820SHans Verkuil cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl, 162862595820SHans Verkuil V4L2_CID_MPEG_AUDIO_EMPHASIS, 162962595820SHans Verkuil V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0, 163062595820SHans Verkuil V4L2_MPEG_AUDIO_EMPHASIS_NONE); 163162595820SHans Verkuil cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl, 163262595820SHans Verkuil V4L2_CID_MPEG_AUDIO_CRC, 163362595820SHans Verkuil V4L2_MPEG_AUDIO_CRC_CRC16, 0, 163462595820SHans Verkuil V4L2_MPEG_AUDIO_CRC_NONE); 163562595820SHans Verkuil 163662595820SHans Verkuil cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0); 163762595820SHans Verkuil if (has_ac3) 163862595820SHans Verkuil cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl, 163962595820SHans Verkuil V4L2_CID_MPEG_AUDIO_AC3_BITRATE, 164062595820SHans Verkuil V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03, 164162595820SHans Verkuil V4L2_MPEG_AUDIO_AC3_BITRATE_224K); 164262595820SHans Verkuil cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl, 164362595820SHans Verkuil V4L2_CID_MPEG_VIDEO_ENCODING, 164462595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0, 164562595820SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2); 164662595820SHans Verkuil cx2341x_ctrl_new_menu(hdl, 164762595820SHans Verkuil V4L2_CID_MPEG_VIDEO_ASPECT, 164862595820SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_221x100, 0, 164962595820SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_4x3); 165062595820SHans Verkuil cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl, 165162595820SHans Verkuil V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2); 165262595820SHans Verkuil cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl, 165362595820SHans Verkuil V4L2_CID_MPEG_VIDEO_GOP_SIZE, 165462595820SHans Verkuil 1, 34, 1, cxhdl->is_50hz ? 12 : 15); 165562595820SHans Verkuil cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1); 165662595820SHans Verkuil cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl, 165762595820SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE_MODE, 165862595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, 165962595820SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 166062595820SHans Verkuil cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl, 166162595820SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE, 166262595820SHans Verkuil 0, 27000000, 1, 6000000); 166362595820SHans Verkuil cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl, 166462595820SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 166562595820SHans Verkuil 0, 27000000, 1, 8000000); 166662595820SHans Verkuil cx2341x_ctrl_new_std(hdl, 166762595820SHans Verkuil V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0); 166862595820SHans Verkuil cxhdl->video_mute = cx2341x_ctrl_new_std(hdl, 166962595820SHans Verkuil V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0); 167062595820SHans Verkuil cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl, 167162595820SHans Verkuil V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080); 167262595820SHans Verkuil 167362595820SHans Verkuil /* CX23415/6 specific */ 167462595820SHans Verkuil cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl, 167562595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, 167662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 167762595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0, 167862595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); 167962595820SHans Verkuil cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl, 168062595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, 168162595820SHans Verkuil 0, 15, 1, 0); 168262595820SHans Verkuil cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl, 168362595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, 168462595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, 168562595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 168662595820SHans Verkuil 0, 168762595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR); 168862595820SHans Verkuil cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl, 168962595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, 169062595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, 169162595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 169262595820SHans Verkuil 0, 169362595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR); 169462595820SHans Verkuil cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl, 169562595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, 169662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 169762595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 169862595820SHans Verkuil 0, 169962595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); 170062595820SHans Verkuil cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl, 170162595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, 170262595820SHans Verkuil 0, 31, 1, 8); 170362595820SHans Verkuil cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl, 170462595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, 170562595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 170662595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 170762595820SHans Verkuil 0, 170862595820SHans Verkuil V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); 170962595820SHans Verkuil cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl, 171062595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, 171162595820SHans Verkuil 0, 255, 1, 0); 171262595820SHans Verkuil cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl, 171362595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, 171462595820SHans Verkuil 0, 255, 1, 255); 171562595820SHans Verkuil cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl, 171662595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, 171762595820SHans Verkuil 0, 255, 1, 0); 171862595820SHans Verkuil cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl, 171962595820SHans Verkuil V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, 172062595820SHans Verkuil 0, 255, 1, 255); 172162595820SHans Verkuil cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS, 172262595820SHans Verkuil 0, 1, 1, 0); 172362595820SHans Verkuil 172462595820SHans Verkuil if (hdl->error) { 172562595820SHans Verkuil int err = hdl->error; 172662595820SHans Verkuil 172762595820SHans Verkuil v4l2_ctrl_handler_free(hdl); 172862595820SHans Verkuil return err; 172962595820SHans Verkuil } 173062595820SHans Verkuil 173162595820SHans Verkuil v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq); 173262595820SHans Verkuil v4l2_ctrl_cluster(2, &cxhdl->video_b_frames); 173362595820SHans Verkuil v4l2_ctrl_cluster(5, &cxhdl->stream_type); 173462595820SHans Verkuil v4l2_ctrl_cluster(2, &cxhdl->video_mute); 173562595820SHans Verkuil v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode); 173662595820SHans Verkuil v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type); 173762595820SHans Verkuil v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter); 173862595820SHans Verkuil v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top); 173962595820SHans Verkuil 174062595820SHans Verkuil return 0; 174162595820SHans Verkuil } 174262595820SHans Verkuil EXPORT_SYMBOL(cx2341x_handler_init); 174362595820SHans Verkuil 174462595820SHans Verkuil void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz) 174562595820SHans Verkuil { 174662595820SHans Verkuil cxhdl->is_50hz = is_50hz; 174762595820SHans Verkuil cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15; 174862595820SHans Verkuil } 174962595820SHans Verkuil EXPORT_SYMBOL(cx2341x_handler_set_50hz); 175062595820SHans Verkuil 175162595820SHans Verkuil int cx2341x_handler_setup(struct cx2341x_handler *cxhdl) 175262595820SHans Verkuil { 175362595820SHans Verkuil int h = cxhdl->height; 175462595820SHans Verkuil int w = cxhdl->width; 175562595820SHans Verkuil int err; 175662595820SHans Verkuil 175762595820SHans Verkuil err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0); 175862595820SHans Verkuil if (err) 175962595820SHans Verkuil return err; 176062595820SHans Verkuil err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz); 176162595820SHans Verkuil if (err) 176262595820SHans Verkuil return err; 176362595820SHans Verkuil 176462595820SHans Verkuil if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { 176562595820SHans Verkuil w /= 2; 176662595820SHans Verkuil h /= 2; 176762595820SHans Verkuil } 176862595820SHans Verkuil err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); 176962595820SHans Verkuil if (err) 177062595820SHans Verkuil return err; 177162595820SHans Verkuil return v4l2_ctrl_handler_setup(&cxhdl->hdl); 177262595820SHans Verkuil } 177362595820SHans Verkuil EXPORT_SYMBOL(cx2341x_handler_setup); 177462595820SHans Verkuil 177562595820SHans Verkuil void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy) 177662595820SHans Verkuil { 177762595820SHans Verkuil v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy); 177862595820SHans Verkuil v4l2_ctrl_grab(cxhdl->audio_encoding, busy); 177962595820SHans Verkuil v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy); 178062595820SHans Verkuil v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy); 178162595820SHans Verkuil v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy); 178262595820SHans Verkuil v4l2_ctrl_grab(cxhdl->stream_type, busy); 178362595820SHans Verkuil v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy); 178462595820SHans Verkuil v4l2_ctrl_grab(cxhdl->video_bitrate, busy); 178562595820SHans Verkuil v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy); 178662595820SHans Verkuil } 178762595820SHans Verkuil EXPORT_SYMBOL(cx2341x_handler_set_busy); 1788