cx2341x.c 56 KB

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