cx2341x.c 56 KB

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