cx2341x.c 56 KB

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