1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753 |
- /*
- * cx2341x - generic code for cx23415/6/8 based devices
- *
- * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/videodev2.h>
- #include <media/tuner.h>
- #include <media/drv-intf/cx2341x.h>
- #include <media/v4l2-common.h>
- MODULE_DESCRIPTION("cx23415/6/8 driver");
- MODULE_AUTHOR("Hans Verkuil");
- MODULE_LICENSE("GPL");
- static int debug;
- module_param(debug, int, 0644);
- MODULE_PARM_DESC(debug, "Debug level (0-1)");
- /********************** COMMON CODE *********************/
- /* definitions for audio properties bits 29-28 */
- #define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0
- #define CX2341X_AUDIO_ENCODING_METHOD_AC3 1
- #define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2
- static const char *cx2341x_get_name(u32 id)
- {
- switch (id) {
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- return "Spatial Filter Mode";
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- return "Spatial Filter";
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- return "Spatial Luma Filter Type";
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- return "Spatial Chroma Filter Type";
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- return "Temporal Filter Mode";
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- return "Temporal Filter";
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- return "Median Filter Type";
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- return "Median Luma Filter Maximum";
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- return "Median Luma Filter Minimum";
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- return "Median Chroma Filter Maximum";
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- return "Median Chroma Filter Minimum";
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- return "Insert Navigation Packets";
- }
- return NULL;
- }
- static const char **cx2341x_get_menu(u32 id)
- {
- static const char *cx2341x_video_spatial_filter_mode_menu[] = {
- "Manual",
- "Auto",
- NULL
- };
- static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
- "Off",
- "1D Horizontal",
- "1D Vertical",
- "2D H/V Separable",
- "2D Symmetric non-separable",
- NULL
- };
- static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
- "Off",
- "1D Horizontal",
- NULL
- };
- static const char *cx2341x_video_temporal_filter_mode_menu[] = {
- "Manual",
- "Auto",
- NULL
- };
- static const char *cx2341x_video_median_filter_type_menu[] = {
- "Off",
- "Horizontal",
- "Vertical",
- "Horizontal/Vertical",
- "Diagonal",
- NULL
- };
- switch (id) {
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- return cx2341x_video_spatial_filter_mode_menu;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- return cx2341x_video_luma_spatial_filter_type_menu;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- return cx2341x_video_chroma_spatial_filter_type_menu;
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- return cx2341x_video_temporal_filter_mode_menu;
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- return cx2341x_video_median_filter_type_menu;
- }
- return NULL;
- }
- static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
- s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
- {
- *name = cx2341x_get_name(id);
- *flags = 0;
- switch (id) {
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- *type = V4L2_CTRL_TYPE_MENU;
- *min = 0;
- *step = 0;
- break;
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- *type = V4L2_CTRL_TYPE_BOOLEAN;
- *min = 0;
- *max = *step = 1;
- break;
- default:
- *type = V4L2_CTRL_TYPE_INTEGER;
- break;
- }
- switch (id) {
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- *flags |= V4L2_CTRL_FLAG_UPDATE;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- *flags |= V4L2_CTRL_FLAG_SLIDER;
- break;
- case V4L2_CID_MPEG_VIDEO_ENCODING:
- *flags |= V4L2_CTRL_FLAG_READ_ONLY;
- break;
- }
- }
- /********************** OLD CODE *********************/
- /* Must be sorted from low to high control ID! */
- const u32 cx2341x_mpeg_ctrls[] = {
- V4L2_CID_MPEG_CLASS,
- V4L2_CID_MPEG_STREAM_TYPE,
- V4L2_CID_MPEG_STREAM_VBI_FMT,
- V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
- V4L2_CID_MPEG_AUDIO_ENCODING,
- V4L2_CID_MPEG_AUDIO_L2_BITRATE,
- V4L2_CID_MPEG_AUDIO_MODE,
- V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
- V4L2_CID_MPEG_AUDIO_EMPHASIS,
- V4L2_CID_MPEG_AUDIO_CRC,
- V4L2_CID_MPEG_AUDIO_MUTE,
- V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
- V4L2_CID_MPEG_VIDEO_ENCODING,
- V4L2_CID_MPEG_VIDEO_ASPECT,
- V4L2_CID_MPEG_VIDEO_B_FRAMES,
- V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- V4L2_CID_MPEG_VIDEO_BITRATE,
- V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
- V4L2_CID_MPEG_VIDEO_MUTE,
- V4L2_CID_MPEG_VIDEO_MUTE_YUV,
- V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
- V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
- V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
- V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
- V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
- V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
- 0
- };
- EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
- static const struct cx2341x_mpeg_params default_params = {
- /* misc */
- .capabilities = 0,
- .port = CX2341X_PORT_MEMORY,
- .width = 720,
- .height = 480,
- .is_50hz = 0,
- /* stream */
- .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
- .stream_insert_nav_packets = 0,
- /* audio */
- .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
- .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
- .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
- .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
- .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
- .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
- .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
- .audio_mute = 0,
- /* video */
- .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
- .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
- .video_b_frames = 2,
- .video_gop_size = 12,
- .video_gop_closure = 1,
- .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
- .video_bitrate = 6000000,
- .video_bitrate_peak = 8000000,
- .video_temporal_decimation = 0,
- .video_mute = 0,
- .video_mute_yuv = 0x008080, /* YCbCr value for black */
- /* encoding filters */
- .video_spatial_filter_mode =
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
- .video_spatial_filter = 0,
- .video_luma_spatial_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
- .video_chroma_spatial_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
- .video_temporal_filter_mode =
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
- .video_temporal_filter = 8,
- .video_median_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
- .video_luma_median_filter_top = 255,
- .video_luma_median_filter_bottom = 0,
- .video_chroma_median_filter_top = 255,
- .video_chroma_median_filter_bottom = 0,
- };
- /* Map the control ID to the correct field in the cx2341x_mpeg_params
- struct. Return -EINVAL if the ID is unknown, else return 0. */
- static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
- struct v4l2_ext_control *ctrl)
- {
- switch (ctrl->id) {
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- ctrl->value = params->audio_sampling_freq;
- break;
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- ctrl->value = params->audio_encoding;
- break;
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- ctrl->value = params->audio_l2_bitrate;
- break;
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- ctrl->value = params->audio_ac3_bitrate;
- break;
- case V4L2_CID_MPEG_AUDIO_MODE:
- ctrl->value = params->audio_mode;
- break;
- case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
- ctrl->value = params->audio_mode_extension;
- break;
- case V4L2_CID_MPEG_AUDIO_EMPHASIS:
- ctrl->value = params->audio_emphasis;
- break;
- case V4L2_CID_MPEG_AUDIO_CRC:
- ctrl->value = params->audio_crc;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- ctrl->value = params->audio_mute;
- break;
- case V4L2_CID_MPEG_VIDEO_ENCODING:
- ctrl->value = params->video_encoding;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- ctrl->value = params->video_aspect;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- ctrl->value = params->video_b_frames;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- ctrl->value = params->video_gop_size;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
- ctrl->value = params->video_gop_closure;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- ctrl->value = params->video_bitrate_mode;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- ctrl->value = params->video_bitrate;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- ctrl->value = params->video_bitrate_peak;
- break;
- case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
- ctrl->value = params->video_temporal_decimation;
- break;
- case V4L2_CID_MPEG_VIDEO_MUTE:
- ctrl->value = params->video_mute;
- break;
- case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
- ctrl->value = params->video_mute_yuv;
- break;
- case V4L2_CID_MPEG_STREAM_TYPE:
- ctrl->value = params->stream_type;
- break;
- case V4L2_CID_MPEG_STREAM_VBI_FMT:
- ctrl->value = params->stream_vbi_fmt;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- ctrl->value = params->video_spatial_filter_mode;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- ctrl->value = params->video_spatial_filter;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- ctrl->value = params->video_luma_spatial_filter_type;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- ctrl->value = params->video_chroma_spatial_filter_type;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- ctrl->value = params->video_temporal_filter_mode;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- ctrl->value = params->video_temporal_filter;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- ctrl->value = params->video_median_filter_type;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- ctrl->value = params->video_luma_median_filter_top;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- ctrl->value = params->video_luma_median_filter_bottom;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- ctrl->value = params->video_chroma_median_filter_top;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- ctrl->value = params->video_chroma_median_filter_bottom;
- break;
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- ctrl->value = params->stream_insert_nav_packets;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- /* Map the control ID to the correct field in the cx2341x_mpeg_params
- struct. Return -EINVAL if the ID is unknown, else return 0. */
- static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
- struct v4l2_ext_control *ctrl)
- {
- switch (ctrl->id) {
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- if (busy)
- return -EBUSY;
- params->audio_sampling_freq = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- if (busy)
- return -EBUSY;
- if (params->capabilities & CX2341X_CAP_HAS_AC3)
- if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
- ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
- return -ERANGE;
- params->audio_encoding = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- if (busy)
- return -EBUSY;
- params->audio_l2_bitrate = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- if (busy)
- return -EBUSY;
- if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
- return -EINVAL;
- params->audio_ac3_bitrate = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_MODE:
- params->audio_mode = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
- params->audio_mode_extension = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_EMPHASIS:
- params->audio_emphasis = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_CRC:
- params->audio_crc = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- params->audio_mute = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- params->video_aspect = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
- int b = ctrl->value + 1;
- int gop = params->video_gop_size;
- params->video_b_frames = ctrl->value;
- params->video_gop_size = b * ((gop + b - 1) / b);
- /* Max GOP size = 34 */
- while (params->video_gop_size > 34)
- params->video_gop_size -= b;
- break;
- }
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
- int b = params->video_b_frames + 1;
- int gop = ctrl->value;
- params->video_gop_size = b * ((gop + b - 1) / b);
- /* Max GOP size = 34 */
- while (params->video_gop_size > 34)
- params->video_gop_size -= b;
- ctrl->value = params->video_gop_size;
- break;
- }
- case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
- params->video_gop_closure = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- if (busy)
- return -EBUSY;
- /* MPEG-1 only allows CBR */
- if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
- ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
- return -EINVAL;
- params->video_bitrate_mode = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- if (busy)
- return -EBUSY;
- params->video_bitrate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- if (busy)
- return -EBUSY;
- params->video_bitrate_peak = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
- params->video_temporal_decimation = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MUTE:
- params->video_mute = (ctrl->value != 0);
- break;
- case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
- params->video_mute_yuv = ctrl->value;
- break;
- case V4L2_CID_MPEG_STREAM_TYPE:
- if (busy)
- return -EBUSY;
- params->stream_type = ctrl->value;
- params->video_encoding =
- (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
- params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
- V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
- if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
- /* MPEG-1 implies CBR */
- params->video_bitrate_mode =
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
- break;
- case V4L2_CID_MPEG_STREAM_VBI_FMT:
- params->stream_vbi_fmt = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- params->video_spatial_filter_mode = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- params->video_spatial_filter = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- params->video_luma_spatial_filter_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- params->video_chroma_spatial_filter_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- params->video_temporal_filter_mode = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- params->video_temporal_filter = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- params->video_median_filter_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- params->video_luma_median_filter_top = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- params->video_luma_median_filter_bottom = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- params->video_chroma_median_filter_top = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- params->video_chroma_median_filter_bottom = ctrl->value;
- break;
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- params->stream_insert_nav_packets = ctrl->value;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
- s32 min, s32 max, s32 step, s32 def)
- {
- const char *name;
- switch (qctrl->id) {
- /* MPEG controls */
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type,
- &min, &max, &step, &def, &qctrl->flags);
- qctrl->minimum = min;
- qctrl->maximum = max;
- qctrl->step = step;
- qctrl->default_value = def;
- qctrl->reserved[0] = qctrl->reserved[1] = 0;
- strlcpy(qctrl->name, name, sizeof(qctrl->name));
- return 0;
- default:
- return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
- }
- }
- int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
- struct v4l2_queryctrl *qctrl)
- {
- int err;
- switch (qctrl->id) {
- case V4L2_CID_MPEG_CLASS:
- return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
- case V4L2_CID_MPEG_STREAM_TYPE:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
- case V4L2_CID_MPEG_STREAM_VBI_FMT:
- if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_STREAM_VBI_FMT_NONE,
- V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
- V4L2_MPEG_STREAM_VBI_FMT_NONE);
- return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_STREAM_VBI_FMT_NONE,
- V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
- default_params.stream_vbi_fmt);
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- if (params->capabilities & CX2341X_CAP_HAS_AC3) {
- /*
- * The state of L2 & AC3 bitrate controls can change
- * when this control changes, but v4l2_ctrl_query_fill()
- * already sets V4L2_CTRL_FLAG_UPDATE for
- * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
- */
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
- default_params.audio_encoding);
- }
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
- default_params.audio_encoding);
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- err = v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_L2_BITRATE_192K,
- V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
- default_params.audio_l2_bitrate);
- if (err)
- return err;
- if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
- params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_AUDIO_MODE:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_MODE_STEREO,
- V4L2_MPEG_AUDIO_MODE_MONO, 1,
- V4L2_MPEG_AUDIO_MODE_STEREO);
- case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
- err = v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
- V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
- V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
- if (err == 0 &&
- params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return err;
- case V4L2_CID_MPEG_AUDIO_EMPHASIS:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_EMPHASIS_NONE,
- V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
- V4L2_MPEG_AUDIO_EMPHASIS_NONE);
- case V4L2_CID_MPEG_AUDIO_CRC:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_CRC_NONE,
- V4L2_MPEG_AUDIO_CRC_CRC16, 1,
- V4L2_MPEG_AUDIO_CRC_NONE);
- case V4L2_CID_MPEG_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- err = v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
- V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
- default_params.audio_ac3_bitrate);
- if (err)
- return err;
- if (params->capabilities & CX2341X_CAP_HAS_AC3) {
- if (params->audio_encoding !=
- V4L2_MPEG_AUDIO_ENCODING_AC3)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- } else
- qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
- return 0;
- case V4L2_CID_MPEG_VIDEO_ENCODING:
- /* this setting is read-only for the cx2341x since the
- V4L2_CID_MPEG_STREAM_TYPE really determines the
- MPEG-1/2 setting */
- err = v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
- if (err == 0)
- qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- return err;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_VIDEO_ASPECT_1x1,
- V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
- V4L2_MPEG_VIDEO_ASPECT_4x3);
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
- params->is_50hz ? 12 : 15);
- case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
- return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- err = v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- if (err == 0 &&
- params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return err;
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
- if (err == 0 &&
- params->video_bitrate_mode ==
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return err;
- case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
- return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
- case V4L2_CID_MPEG_VIDEO_MUTE:
- return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
- case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */
- return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
- /* CX23415/6 specific */
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
- default_params.video_spatial_filter_mode);
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
- default_params.video_spatial_filter);
- qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_spatial_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
- 1,
- default_params.video_luma_spatial_filter_type);
- if (params->video_spatial_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
- 1,
- default_params.video_chroma_spatial_filter_type);
- if (params->video_spatial_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
- default_params.video_temporal_filter_mode);
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
- default_params.video_temporal_filter);
- qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_temporal_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
- default_params.video_median_filter_type);
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
- default_params.video_luma_median_filter_top);
- qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
- default_params.video_luma_median_filter_bottom);
- qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
- default_params.video_chroma_median_filter_top);
- qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
- default_params.video_chroma_median_filter_bottom);
- qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return 0;
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
- default_params.stream_insert_nav_packets);
- default:
- return -EINVAL;
- }
- }
- EXPORT_SYMBOL(cx2341x_ctrl_query);
- const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
- {
- static const char * const mpeg_stream_type_without_ts[] = {
- "MPEG-2 Program Stream",
- "",
- "MPEG-1 System Stream",
- "MPEG-2 DVD-compatible Stream",
- "MPEG-1 VCD-compatible Stream",
- "MPEG-2 SVCD-compatible Stream",
- NULL
- };
- static const char *mpeg_stream_type_with_ts[] = {
- "MPEG-2 Program Stream",
- "MPEG-2 Transport Stream",
- "MPEG-1 System Stream",
- "MPEG-2 DVD-compatible Stream",
- "MPEG-1 VCD-compatible Stream",
- "MPEG-2 SVCD-compatible Stream",
- NULL
- };
- static const char *mpeg_audio_encoding_l2_ac3[] = {
- "",
- "MPEG-1/2 Layer II",
- "",
- "",
- "AC-3",
- NULL
- };
- switch (id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- return (p->capabilities & CX2341X_CAP_HAS_TS) ?
- mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
- mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
- case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
- case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
- return NULL;
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
- case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
- return cx2341x_get_menu(id);
- default:
- return v4l2_ctrl_get_menu(id);
- }
- }
- EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
- static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
- {
- params->audio_properties =
- (params->audio_sampling_freq << 0) |
- (params->audio_mode << 8) |
- (params->audio_mode_extension << 10) |
- (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
- ? 3 : params->audio_emphasis) << 12) |
- (params->audio_crc << 14);
- if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
- params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
- params->audio_properties |=
- /* Not sure if this MPEG Layer II setting is required */
- ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
- (params->audio_ac3_bitrate << 4) |
- (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
- } else {
- /* Assuming MPEG Layer II */
- params->audio_properties |=
- ((3 - params->audio_encoding) << 2) |
- ((1 + params->audio_l2_bitrate) << 4);
- }
- }
- /* Check for correctness of the ctrl's value based on the data from
- struct v4l2_queryctrl and the available menu items. Note that
- menu_items may be NULL, in that case it is ignored. */
- static int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
- const char * const *menu_items)
- {
- if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
- return -EINVAL;
- if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
- return -EBUSY;
- if (qctrl->type == V4L2_CTRL_TYPE_STRING)
- return 0;
- if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
- qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
- qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
- return 0;
- if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
- return -ERANGE;
- if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
- if (menu_items[ctrl->value] == NULL ||
- menu_items[ctrl->value][0] == '\0')
- return -EINVAL;
- }
- if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
- (ctrl->value & ~qctrl->maximum))
- return -ERANGE;
- return 0;
- }
- int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
- struct v4l2_ext_controls *ctrls, unsigned int cmd)
- {
- int err = 0;
- int i;
- if (cmd == VIDIOC_G_EXT_CTRLS) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
- err = cx2341x_get_ctrl(params, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
- }
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
- struct v4l2_queryctrl qctrl;
- const char * const *menu_items = NULL;
- qctrl.id = ctrl->id;
- err = cx2341x_ctrl_query(params, &qctrl);
- if (err)
- break;
- if (qctrl.type == V4L2_CTRL_TYPE_MENU)
- menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
- err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
- if (err)
- break;
- err = cx2341x_set_ctrl(params, busy, ctrl);
- if (err)
- break;
- }
- if (err == 0 &&
- params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
- params->video_bitrate_peak < params->video_bitrate) {
- err = -ERANGE;
- ctrls->error_idx = ctrls->count;
- }
- if (err)
- ctrls->error_idx = i;
- else
- cx2341x_calc_audio_properties(params);
- return err;
- }
- EXPORT_SYMBOL(cx2341x_ext_ctrls);
- void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
- {
- *p = default_params;
- cx2341x_calc_audio_properties(p);
- }
- EXPORT_SYMBOL(cx2341x_fill_defaults);
- static int cx2341x_api(void *priv, cx2341x_mbox_func func,
- u32 cmd, int args, ...)
- {
- u32 data[CX2341X_MBOX_MAX_DATA];
- va_list vargs;
- int i;
- va_start(vargs, args);
- for (i = 0; i < args; i++)
- data[i] = va_arg(vargs, int);
- va_end(vargs);
- return func(priv, cmd, args, 0, data);
- }
- #define NEQ(field) (old->field != new->field)
- int cx2341x_update(void *priv, cx2341x_mbox_func func,
- const struct cx2341x_mpeg_params *old,
- const struct cx2341x_mpeg_params *new)
- {
- static int mpeg_stream_type[] = {
- 0, /* MPEG-2 PS */
- 1, /* MPEG-2 TS */
- 2, /* MPEG-1 SS */
- 14, /* DVD */
- 11, /* VCD */
- 12, /* SVCD */
- };
- int err = 0;
- int force = (old == NULL);
- u16 temporal = new->video_temporal_filter;
- cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
- if (force || NEQ(is_50hz)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
- new->is_50hz);
- if (err) return err;
- }
- if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
- u16 w = new->width;
- u16 h = new->height;
- if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
- w /= 2;
- h /= 2;
- }
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
- h, w);
- if (err) return err;
- }
- if (force || NEQ(stream_type)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
- mpeg_stream_type[new->stream_type]);
- if (err) return err;
- }
- if (force || NEQ(video_aspect)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
- 1 + new->video_aspect);
- if (err) return err;
- }
- if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
- new->video_gop_size, new->video_b_frames + 1);
- if (err) return err;
- }
- if (force || NEQ(video_gop_closure)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
- new->video_gop_closure);
- if (err) return err;
- }
- if (force || NEQ(audio_properties)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
- 1, new->audio_properties);
- if (err) return err;
- }
- if (force || NEQ(audio_mute)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
- new->audio_mute);
- if (err) return err;
- }
- if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
- NEQ(video_bitrate_peak)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
- new->video_bitrate_mode, new->video_bitrate,
- new->video_bitrate_peak / 400, 0, 0);
- if (err) return err;
- }
- if (force || NEQ(video_spatial_filter_mode) ||
- NEQ(video_temporal_filter_mode) ||
- NEQ(video_median_filter_type)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
- 2, new->video_spatial_filter_mode |
- (new->video_temporal_filter_mode << 1),
- new->video_median_filter_type);
- if (err) return err;
- }
- if (force || NEQ(video_luma_median_filter_bottom) ||
- NEQ(video_luma_median_filter_top) ||
- NEQ(video_chroma_median_filter_bottom) ||
- NEQ(video_chroma_median_filter_top)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
- new->video_luma_median_filter_bottom,
- new->video_luma_median_filter_top,
- new->video_chroma_median_filter_bottom,
- new->video_chroma_median_filter_top);
- if (err) return err;
- }
- if (force || NEQ(video_luma_spatial_filter_type) ||
- NEQ(video_chroma_spatial_filter_type)) {
- err = cx2341x_api(priv, func,
- CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
- 2, new->video_luma_spatial_filter_type,
- new->video_chroma_spatial_filter_type);
- if (err) return err;
- }
- if (force || NEQ(video_spatial_filter) ||
- old->video_temporal_filter != temporal) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
- 2, new->video_spatial_filter, temporal);
- if (err) return err;
- }
- if (force || NEQ(video_temporal_decimation)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
- 1, new->video_temporal_decimation);
- if (err) return err;
- }
- if (force || NEQ(video_mute) ||
- (new->video_mute && NEQ(video_mute_yuv))) {
- err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
- new->video_mute | (new->video_mute_yuv << 8));
- if (err) return err;
- }
- if (force || NEQ(stream_insert_nav_packets)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
- 7, new->stream_insert_nav_packets);
- if (err) return err;
- }
- return 0;
- }
- EXPORT_SYMBOL(cx2341x_update);
- static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
- {
- const char * const *menu = cx2341x_ctrl_get_menu(p, id);
- struct v4l2_ext_control ctrl;
- if (menu == NULL)
- goto invalid;
- ctrl.id = id;
- if (cx2341x_get_ctrl(p, &ctrl))
- goto invalid;
- while (ctrl.value-- && *menu) menu++;
- if (*menu == NULL)
- goto invalid;
- return *menu;
- invalid:
- return "<invalid>";
- }
- void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
- {
- int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- /* Stream */
- printk(KERN_INFO "%s: Stream: %s",
- prefix,
- cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
- if (p->stream_insert_nav_packets)
- printk(KERN_CONT " (with navigation packets)");
- printk(KERN_CONT "\n");
- printk(KERN_INFO "%s: VBI Format: %s\n",
- prefix,
- cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
- /* Video */
- printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
- prefix,
- p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
- p->is_50hz ? 25 : 30,
- (p->video_mute) ? " (muted)" : "");
- printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
- prefix,
- cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
- cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
- cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
- p->video_bitrate);
- if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
- printk(KERN_CONT ", Peak %d", p->video_bitrate_peak);
- printk(KERN_CONT "\n");
- printk(KERN_INFO
- "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
- prefix,
- p->video_gop_size, p->video_b_frames,
- p->video_gop_closure ? "" : "No ");
- if (p->video_temporal_decimation)
- printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
- prefix, p->video_temporal_decimation);
- /* Audio */
- printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
- prefix,
- cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
- cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
- cx2341x_menu_item(p,
- p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
- ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
- : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
- cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
- p->audio_mute ? " (muted)" : "");
- if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
- printk(KERN_CONT ", %s", cx2341x_menu_item(p,
- V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
- printk(KERN_CONT ", %s, %s\n",
- cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
- cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
- /* Encoding filters */
- printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
- prefix,
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
- p->video_spatial_filter);
- printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
- prefix,
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
- p->video_temporal_filter);
- printk(KERN_INFO
- "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
- prefix,
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
- p->video_luma_median_filter_bottom,
- p->video_luma_median_filter_top,
- p->video_chroma_median_filter_bottom,
- p->video_chroma_median_filter_top);
- }
- EXPORT_SYMBOL(cx2341x_log_status);
- /********************** NEW CODE *********************/
- static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl)
- {
- return container_of(ctrl->handler, struct cx2341x_handler, hdl);
- }
- static int cx2341x_hdl_api(struct cx2341x_handler *hdl,
- u32 cmd, int args, ...)
- {
- u32 data[CX2341X_MBOX_MAX_DATA];
- va_list vargs;
- int i;
- va_start(vargs, args);
- for (i = 0; i < args; i++)
- data[i] = va_arg(vargs, int);
- va_end(vargs);
- return hdl->func(hdl->priv, cmd, args, 0, data);
- }
- /* ctrl->handler->lock is held, so it is safe to access cur.val */
- static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)
- {
- return ctrl && ctrl->val != ctrl->cur.val;
- }
- static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)
- {
- struct cx2341x_handler *hdl = to_cxhdl(ctrl);
- s32 val = ctrl->val;
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
- /* video gop cluster */
- int b = val + 1;
- int gop = hdl->video_gop_size->val;
- gop = b * ((gop + b - 1) / b);
- /* Max GOP size = 34 */
- while (gop > 34)
- gop -= b;
- hdl->video_gop_size->val = gop;
- break;
- }
- case V4L2_CID_MPEG_STREAM_TYPE:
- /* stream type cluster */
- hdl->video_encoding->val =
- (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
- hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
- V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
- if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
- /* MPEG-1 implies CBR */
- hdl->video_bitrate_mode->val =
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
- /* peak bitrate shall be >= normal bitrate */
- if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
- hdl->video_bitrate_peak->val < hdl->video_bitrate->val)
- hdl->video_bitrate_peak->val = hdl->video_bitrate->val;
- break;
- }
- return 0;
- }
- static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl)
- {
- static const int mpeg_stream_type[] = {
- 0, /* MPEG-2 PS */
- 1, /* MPEG-2 TS */
- 2, /* MPEG-1 SS */
- 14, /* DVD */
- 11, /* VCD */
- 12, /* SVCD */
- };
- struct cx2341x_handler *hdl = to_cxhdl(ctrl);
- s32 val = ctrl->val;
- u32 props;
- int err;
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_VBI_FMT:
- if (hdl->ops && hdl->ops->s_stream_vbi_fmt)
- return hdl->ops->s_stream_vbi_fmt(hdl, val);
- return 0;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return cx2341x_hdl_api(hdl,
- CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1);
- case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
- return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val);
- case V4L2_CID_MPEG_AUDIO_MUTE:
- return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val);
- case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
- return cx2341x_hdl_api(hdl,
- CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val);
- case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val);
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- /* audio properties cluster */
- props = (hdl->audio_sampling_freq->val << 0) |
- (hdl->audio_mode->val << 8) |
- (hdl->audio_mode_extension->val << 10) |
- (hdl->audio_crc->val << 14);
- if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
- props |= 3 << 12;
- else
- props |= hdl->audio_emphasis->val << 12;
- if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) {
- props |=
- #if 1
- /* Not sure if this MPEG Layer II setting is required */
- ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
- #endif
- (hdl->audio_ac3_bitrate->val << 4) |
- (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
- } else {
- /* Assuming MPEG Layer II */
- props |=
- ((3 - hdl->audio_encoding->val) << 2) |
- ((1 + hdl->audio_l2_bitrate->val) << 4);
- }
- err = cx2341x_hdl_api(hdl,
- CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props);
- if (err)
- return err;
- hdl->audio_properties = props;
- if (hdl->audio_ac3_bitrate) {
- int is_ac3 = hdl->audio_encoding->val ==
- V4L2_MPEG_AUDIO_ENCODING_AC3;
- v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3);
- v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3);
- }
- v4l2_ctrl_activate(hdl->audio_mode_extension,
- hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO);
- if (cx2341x_neq(hdl->audio_sampling_freq) &&
- hdl->ops && hdl->ops->s_audio_sampling_freq)
- return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val);
- if (cx2341x_neq(hdl->audio_mode) &&
- hdl->ops && hdl->ops->s_audio_mode)
- return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val);
- return 0;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- /* video gop cluster */
- return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
- hdl->video_gop_size->val,
- hdl->video_b_frames->val + 1);
- case V4L2_CID_MPEG_STREAM_TYPE:
- /* stream type cluster */
- err = cx2341x_hdl_api(hdl,
- CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]);
- if (err)
- return err;
- err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5,
- hdl->video_bitrate_mode->val,
- hdl->video_bitrate->val,
- hdl->video_bitrate_peak->val / 400, 0, 0);
- if (err)
- return err;
- v4l2_ctrl_activate(hdl->video_bitrate_mode,
- hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1);
- v4l2_ctrl_activate(hdl->video_bitrate_peak,
- hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
- if (cx2341x_neq(hdl->video_encoding) &&
- hdl->ops && hdl->ops->s_video_encoding)
- return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val);
- return 0;
- case V4L2_CID_MPEG_VIDEO_MUTE:
- /* video mute cluster */
- return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1,
- hdl->video_mute->val |
- (hdl->video_mute_yuv->val << 8));
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: {
- int active_filter;
- /* video filter mode */
- err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
- hdl->video_spatial_filter_mode->val |
- (hdl->video_temporal_filter_mode->val << 1),
- hdl->video_median_filter_type->val);
- if (err)
- return err;
- active_filter = hdl->video_spatial_filter_mode->val !=
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO;
- v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter);
- v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter);
- v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter);
- active_filter = hdl->video_temporal_filter_mode->val !=
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO;
- v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter);
- active_filter = hdl->video_median_filter_type->val !=
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF;
- v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter);
- v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter);
- v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter);
- v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter);
- return 0;
- }
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
- /* video filter type cluster */
- return cx2341x_hdl_api(hdl,
- CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
- hdl->video_luma_spatial_filter_type->val,
- hdl->video_chroma_spatial_filter_type->val);
- case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- /* video filter cluster */
- return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
- hdl->video_spatial_filter->val,
- hdl->video_temporal_filter->val);
- case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- /* video median cluster */
- return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4,
- hdl->video_luma_median_filter_bottom->val,
- hdl->video_luma_median_filter_top->val,
- hdl->video_chroma_median_filter_bottom->val,
- hdl->video_chroma_median_filter_top->val);
- }
- return -EINVAL;
- }
- static const struct v4l2_ctrl_ops cx2341x_ops = {
- .try_ctrl = cx2341x_try_ctrl,
- .s_ctrl = cx2341x_s_ctrl,
- };
- static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
- u32 id, s32 min, s32 max, s32 step, s32 def)
- {
- struct v4l2_ctrl_config cfg;
- memset(&cfg, 0, sizeof(cfg));
- cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags);
- cfg.ops = &cx2341x_ops;
- cfg.id = id;
- cfg.min = min;
- cfg.max = max;
- cfg.def = def;
- if (cfg.type == V4L2_CTRL_TYPE_MENU) {
- cfg.step = 0;
- cfg.menu_skip_mask = step;
- cfg.qmenu = cx2341x_get_menu(id);
- } else {
- cfg.step = step;
- cfg.menu_skip_mask = 0;
- }
- return v4l2_ctrl_new_custom(hdl, &cfg, NULL);
- }
- static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
- u32 id, s32 min, s32 max, s32 step, s32 def)
- {
- return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def);
- }
- static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl,
- u32 id, s32 max, s32 mask, s32 def)
- {
- return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def);
- }
- int cx2341x_handler_init(struct cx2341x_handler *cxhdl,
- unsigned nr_of_controls_hint)
- {
- struct v4l2_ctrl_handler *hdl = &cxhdl->hdl;
- u32 caps = cxhdl->capabilities;
- int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI;
- int has_ac3 = caps & CX2341X_CAP_HAS_AC3;
- int has_ts = caps & CX2341X_CAP_HAS_TS;
- cxhdl->width = 720;
- cxhdl->height = 480;
- v4l2_ctrl_handler_init(hdl, nr_of_controls_hint);
- /* Add controls in ascending control ID order for fastest
- insertion time. */
- cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_STREAM_TYPE,
- V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
- cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_STREAM_VBI_FMT,
- V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2,
- V4L2_MPEG_STREAM_VBI_FMT_NONE);
- cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
- cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_ENCODING,
- V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
- cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_L2_BITRATE,
- V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff,
- V4L2_MPEG_AUDIO_L2_BITRATE_224K);
- cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_MODE,
- V4L2_MPEG_AUDIO_MODE_MONO, 0,
- V4L2_MPEG_AUDIO_MODE_STEREO);
- cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
- V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0,
- V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
- cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_EMPHASIS,
- V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0,
- V4L2_MPEG_AUDIO_EMPHASIS_NONE);
- cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_CRC,
- V4L2_MPEG_AUDIO_CRC_CRC16, 0,
- V4L2_MPEG_AUDIO_CRC_NONE);
- cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0);
- if (has_ac3)
- cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
- V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03,
- V4L2_MPEG_AUDIO_AC3_BITRATE_224K);
- cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_VIDEO_ENCODING,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
- cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_VIDEO_ASPECT,
- V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
- V4L2_MPEG_VIDEO_ASPECT_4x3);
- cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2);
- cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- 1, 34, 1, cxhdl->is_50hz ? 12 : 15);
- cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
- cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl,
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_BITRATE,
- 0, 27000000, 1, 6000000);
- cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- 0, 27000000, 1, 8000000);
- cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0);
- cxhdl->video_mute = cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0);
- cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl,
- V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080);
- /* CX23415/6 specific */
- cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
- cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
- 0, 15, 1, 0);
- cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
- 0,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR);
- cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
- 0,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR);
- cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO,
- 0,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
- cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
- 0, 31, 1, 8);
- cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG,
- 0,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
- cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
- 0, 255, 1, 0);
- cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
- 0, 255, 1, 255);
- cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
- 0, 255, 1, 0);
- cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
- 0, 255, 1, 255);
- cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
- 0, 1, 1, 0);
- if (hdl->error) {
- int err = hdl->error;
- v4l2_ctrl_handler_free(hdl);
- return err;
- }
- v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq);
- v4l2_ctrl_cluster(2, &cxhdl->video_b_frames);
- v4l2_ctrl_cluster(5, &cxhdl->stream_type);
- v4l2_ctrl_cluster(2, &cxhdl->video_mute);
- v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode);
- v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type);
- v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter);
- v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top);
- return 0;
- }
- EXPORT_SYMBOL(cx2341x_handler_init);
- void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz)
- {
- cxhdl->is_50hz = is_50hz;
- cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15;
- }
- EXPORT_SYMBOL(cx2341x_handler_set_50hz);
- int cx2341x_handler_setup(struct cx2341x_handler *cxhdl)
- {
- int h = cxhdl->height;
- int w = cxhdl->width;
- int err;
- err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0);
- if (err)
- return err;
- err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz);
- if (err)
- return err;
- if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
- w /= 2;
- h /= 2;
- }
- err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
- if (err)
- return err;
- return v4l2_ctrl_handler_setup(&cxhdl->hdl);
- }
- EXPORT_SYMBOL(cx2341x_handler_setup);
- void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy)
- {
- v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy);
- v4l2_ctrl_grab(cxhdl->audio_encoding, busy);
- v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy);
- v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy);
- v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy);
- v4l2_ctrl_grab(cxhdl->stream_type, busy);
- v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy);
- v4l2_ctrl_grab(cxhdl->video_bitrate, busy);
- v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy);
- }
- EXPORT_SYMBOL(cx2341x_handler_set_busy);
|