cx23885-417.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * Support for a cx23417 mpeg encoder via cx23885 host port.
  5. *
  6. * (c) 2004 Jelle Foks <[email protected]>
  7. * (c) 2004 Gerd Knorr <[email protected]>
  8. * (c) 2008 Steven Toth <[email protected]>
  9. * - CX23885/7/8 support
  10. *
  11. * Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
  12. */
  13. #include "cx23885.h"
  14. #include "cx23885-ioctl.h"
  15. #include <linux/module.h>
  16. #include <linux/moduleparam.h>
  17. #include <linux/init.h>
  18. #include <linux/fs.h>
  19. #include <linux/delay.h>
  20. #include <linux/device.h>
  21. #include <linux/firmware.h>
  22. #include <linux/slab.h>
  23. #include <media/v4l2-common.h>
  24. #include <media/v4l2-ioctl.h>
  25. #include <media/drv-intf/cx2341x.h>
  26. #define CX23885_FIRM_IMAGE_SIZE 376836
  27. #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
  28. static unsigned int mpegbufs = 32;
  29. module_param(mpegbufs, int, 0644);
  30. MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
  31. static unsigned int mpeglines = 32;
  32. module_param(mpeglines, int, 0644);
  33. MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
  34. static unsigned int mpeglinesize = 512;
  35. module_param(mpeglinesize, int, 0644);
  36. MODULE_PARM_DESC(mpeglinesize,
  37. "number of bytes in each line of an MPEG buffer, range 512-1024");
  38. static unsigned int v4l_debug;
  39. module_param(v4l_debug, int, 0644);
  40. MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
  41. #define dprintk(level, fmt, arg...)\
  42. do { if (v4l_debug >= level) \
  43. printk(KERN_DEBUG pr_fmt("%s: 417:" fmt), \
  44. __func__, ##arg); \
  45. } while (0)
  46. static struct cx23885_tvnorm cx23885_tvnorms[] = {
  47. {
  48. .name = "NTSC-M",
  49. .id = V4L2_STD_NTSC_M,
  50. }, {
  51. .name = "NTSC-JP",
  52. .id = V4L2_STD_NTSC_M_JP,
  53. }, {
  54. .name = "PAL-BG",
  55. .id = V4L2_STD_PAL_BG,
  56. }, {
  57. .name = "PAL-DK",
  58. .id = V4L2_STD_PAL_DK,
  59. }, {
  60. .name = "PAL-I",
  61. .id = V4L2_STD_PAL_I,
  62. }, {
  63. .name = "PAL-M",
  64. .id = V4L2_STD_PAL_M,
  65. }, {
  66. .name = "PAL-N",
  67. .id = V4L2_STD_PAL_N,
  68. }, {
  69. .name = "PAL-Nc",
  70. .id = V4L2_STD_PAL_Nc,
  71. }, {
  72. .name = "PAL-60",
  73. .id = V4L2_STD_PAL_60,
  74. }, {
  75. .name = "SECAM-L",
  76. .id = V4L2_STD_SECAM_L,
  77. }, {
  78. .name = "SECAM-DK",
  79. .id = V4L2_STD_SECAM_DK,
  80. }
  81. };
  82. /* ------------------------------------------------------------------ */
  83. enum cx23885_capture_type {
  84. CX23885_MPEG_CAPTURE,
  85. CX23885_RAW_CAPTURE,
  86. CX23885_RAW_PASSTHRU_CAPTURE
  87. };
  88. enum cx23885_capture_bits {
  89. CX23885_RAW_BITS_NONE = 0x00,
  90. CX23885_RAW_BITS_YUV_CAPTURE = 0x01,
  91. CX23885_RAW_BITS_PCM_CAPTURE = 0x02,
  92. CX23885_RAW_BITS_VBI_CAPTURE = 0x04,
  93. CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
  94. CX23885_RAW_BITS_TO_HOST_CAPTURE = 0x10
  95. };
  96. enum cx23885_capture_end {
  97. CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
  98. CX23885_END_NOW, /* stop immediately, no irq */
  99. };
  100. enum cx23885_framerate {
  101. CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
  102. CX23885_FRAMERATE_PAL_25 /* PAL: 25fps */
  103. };
  104. enum cx23885_stream_port {
  105. CX23885_OUTPUT_PORT_MEMORY,
  106. CX23885_OUTPUT_PORT_STREAMING,
  107. CX23885_OUTPUT_PORT_SERIAL
  108. };
  109. enum cx23885_data_xfer_status {
  110. CX23885_MORE_BUFFERS_FOLLOW,
  111. CX23885_LAST_BUFFER,
  112. };
  113. enum cx23885_picture_mask {
  114. CX23885_PICTURE_MASK_NONE,
  115. CX23885_PICTURE_MASK_I_FRAMES,
  116. CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
  117. CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
  118. };
  119. enum cx23885_vbi_mode_bits {
  120. CX23885_VBI_BITS_SLICED,
  121. CX23885_VBI_BITS_RAW,
  122. };
  123. enum cx23885_vbi_insertion_bits {
  124. CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
  125. CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
  126. CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
  127. CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
  128. CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
  129. };
  130. enum cx23885_dma_unit {
  131. CX23885_DMA_BYTES,
  132. CX23885_DMA_FRAMES,
  133. };
  134. enum cx23885_dma_transfer_status_bits {
  135. CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
  136. CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
  137. CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
  138. };
  139. enum cx23885_pause {
  140. CX23885_PAUSE_ENCODING,
  141. CX23885_RESUME_ENCODING,
  142. };
  143. enum cx23885_copyright {
  144. CX23885_COPYRIGHT_OFF,
  145. CX23885_COPYRIGHT_ON,
  146. };
  147. enum cx23885_notification_type {
  148. CX23885_NOTIFICATION_REFRESH,
  149. };
  150. enum cx23885_notification_status {
  151. CX23885_NOTIFICATION_OFF,
  152. CX23885_NOTIFICATION_ON,
  153. };
  154. enum cx23885_notification_mailbox {
  155. CX23885_NOTIFICATION_NO_MAILBOX = -1,
  156. };
  157. enum cx23885_field1_lines {
  158. CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
  159. CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
  160. CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
  161. };
  162. enum cx23885_field2_lines {
  163. CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
  164. CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
  165. CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
  166. };
  167. enum cx23885_custom_data_type {
  168. CX23885_CUSTOM_EXTENSION_USR_DATA,
  169. CX23885_CUSTOM_PRIVATE_PACKET,
  170. };
  171. enum cx23885_mute {
  172. CX23885_UNMUTE,
  173. CX23885_MUTE,
  174. };
  175. enum cx23885_mute_video_mask {
  176. CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
  177. CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
  178. CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
  179. };
  180. enum cx23885_mute_video_shift {
  181. CX23885_MUTE_VIDEO_V_SHIFT = 8,
  182. CX23885_MUTE_VIDEO_U_SHIFT = 16,
  183. CX23885_MUTE_VIDEO_Y_SHIFT = 24,
  184. };
  185. /* defines below are from ivtv-driver.h */
  186. #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
  187. /* Firmware API commands */
  188. #define IVTV_API_STD_TIMEOUT 500
  189. /* Registers */
  190. /* IVTV_REG_OFFSET */
  191. #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
  192. #define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
  193. #define IVTV_REG_SPU (0x9050)
  194. #define IVTV_REG_HW_BLOCKS (0x9054)
  195. #define IVTV_REG_VPU (0x9058)
  196. #define IVTV_REG_APU (0xA064)
  197. /**** Bit definitions for MC417_RWD and MC417_OEN registers ***
  198. bits 31-16
  199. +-----------+
  200. | Reserved |
  201. +-----------+
  202. bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8
  203. +-------+-------+-------+-------+-------+-------+-------+-------+
  204. | MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
  205. +-------+-------+-------+-------+-------+-------+-------+-------+
  206. bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
  207. +-------+-------+-------+-------+-------+-------+-------+-------+
  208. |MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
  209. +-------+-------+-------+-------+-------+-------+-------+-------+
  210. ***/
  211. #define MC417_MIWR 0x8000
  212. #define MC417_MIRD 0x4000
  213. #define MC417_MICS 0x2000
  214. #define MC417_MIRDY 0x1000
  215. #define MC417_MIADDR 0x0F00
  216. #define MC417_MIDATA 0x00FF
  217. /* MIADDR* nibble definitions */
  218. #define MCI_MEMORY_DATA_BYTE0 0x000
  219. #define MCI_MEMORY_DATA_BYTE1 0x100
  220. #define MCI_MEMORY_DATA_BYTE2 0x200
  221. #define MCI_MEMORY_DATA_BYTE3 0x300
  222. #define MCI_MEMORY_ADDRESS_BYTE2 0x400
  223. #define MCI_MEMORY_ADDRESS_BYTE1 0x500
  224. #define MCI_MEMORY_ADDRESS_BYTE0 0x600
  225. #define MCI_REGISTER_DATA_BYTE0 0x800
  226. #define MCI_REGISTER_DATA_BYTE1 0x900
  227. #define MCI_REGISTER_DATA_BYTE2 0xA00
  228. #define MCI_REGISTER_DATA_BYTE3 0xB00
  229. #define MCI_REGISTER_ADDRESS_BYTE0 0xC00
  230. #define MCI_REGISTER_ADDRESS_BYTE1 0xD00
  231. #define MCI_REGISTER_MODE 0xE00
  232. /* Read and write modes */
  233. #define MCI_MODE_REGISTER_READ 0
  234. #define MCI_MODE_REGISTER_WRITE 1
  235. #define MCI_MODE_MEMORY_READ 0
  236. #define MCI_MODE_MEMORY_WRITE 0x40
  237. /*** Bit definitions for MC417_CTL register ****
  238. bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0
  239. +--------+-------------+--------+--------------+------------+
  240. |Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
  241. +--------+-------------+--------+--------------+------------+
  242. ***/
  243. #define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)
  244. #define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)
  245. #define MC417_UART_GPIO_EN 0x00000001
  246. /* Values for speed control */
  247. #define MC417_SPD_CTL_SLOW 0x1
  248. #define MC417_SPD_CTL_MEDIUM 0x0
  249. #define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */
  250. /* Values for GPIO select */
  251. #define MC417_GPIO_SEL_GPIO3 0x3
  252. #define MC417_GPIO_SEL_GPIO2 0x2
  253. #define MC417_GPIO_SEL_GPIO1 0x1
  254. #define MC417_GPIO_SEL_GPIO0 0x0
  255. void cx23885_mc417_init(struct cx23885_dev *dev)
  256. {
  257. u32 regval;
  258. dprintk(2, "%s()\n", __func__);
  259. /* Configure MC417_CTL register to defaults. */
  260. regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST) |
  261. MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3) |
  262. MC417_UART_GPIO_EN;
  263. cx_write(MC417_CTL, regval);
  264. /* Configure MC417_OEN to defaults. */
  265. regval = MC417_MIRDY;
  266. cx_write(MC417_OEN, regval);
  267. /* Configure MC417_RWD to defaults. */
  268. regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
  269. cx_write(MC417_RWD, regval);
  270. }
  271. static int mc417_wait_ready(struct cx23885_dev *dev)
  272. {
  273. u32 mi_ready;
  274. unsigned long timeout = jiffies + msecs_to_jiffies(1);
  275. for (;;) {
  276. mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
  277. if (mi_ready != 0)
  278. return 0;
  279. if (time_after(jiffies, timeout))
  280. return -1;
  281. udelay(1);
  282. }
  283. }
  284. int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
  285. {
  286. u32 regval;
  287. /* Enable MC417 GPIO outputs except for MC417_MIRDY,
  288. * which is an input.
  289. */
  290. cx_write(MC417_OEN, MC417_MIRDY);
  291. /* Write data byte 0 */
  292. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
  293. (value & 0x000000FF);
  294. cx_write(MC417_RWD, regval);
  295. /* Transition CS/WR to effect write transaction across bus. */
  296. regval |= MC417_MICS | MC417_MIWR;
  297. cx_write(MC417_RWD, regval);
  298. /* Write data byte 1 */
  299. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
  300. ((value >> 8) & 0x000000FF);
  301. cx_write(MC417_RWD, regval);
  302. regval |= MC417_MICS | MC417_MIWR;
  303. cx_write(MC417_RWD, regval);
  304. /* Write data byte 2 */
  305. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
  306. ((value >> 16) & 0x000000FF);
  307. cx_write(MC417_RWD, regval);
  308. regval |= MC417_MICS | MC417_MIWR;
  309. cx_write(MC417_RWD, regval);
  310. /* Write data byte 3 */
  311. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
  312. ((value >> 24) & 0x000000FF);
  313. cx_write(MC417_RWD, regval);
  314. regval |= MC417_MICS | MC417_MIWR;
  315. cx_write(MC417_RWD, regval);
  316. /* Write address byte 0 */
  317. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
  318. (address & 0xFF);
  319. cx_write(MC417_RWD, regval);
  320. regval |= MC417_MICS | MC417_MIWR;
  321. cx_write(MC417_RWD, regval);
  322. /* Write address byte 1 */
  323. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
  324. ((address >> 8) & 0xFF);
  325. cx_write(MC417_RWD, regval);
  326. regval |= MC417_MICS | MC417_MIWR;
  327. cx_write(MC417_RWD, regval);
  328. /* Indicate that this is a write. */
  329. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
  330. MCI_MODE_REGISTER_WRITE;
  331. cx_write(MC417_RWD, regval);
  332. regval |= MC417_MICS | MC417_MIWR;
  333. cx_write(MC417_RWD, regval);
  334. /* Wait for the trans to complete (MC417_MIRDY asserted). */
  335. return mc417_wait_ready(dev);
  336. }
  337. int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
  338. {
  339. int retval;
  340. u32 regval;
  341. u32 tempval;
  342. u32 dataval;
  343. /* Enable MC417 GPIO outputs except for MC417_MIRDY,
  344. * which is an input.
  345. */
  346. cx_write(MC417_OEN, MC417_MIRDY);
  347. /* Write address byte 0 */
  348. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
  349. ((address & 0x00FF));
  350. cx_write(MC417_RWD, regval);
  351. regval |= MC417_MICS | MC417_MIWR;
  352. cx_write(MC417_RWD, regval);
  353. /* Write address byte 1 */
  354. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
  355. ((address >> 8) & 0xFF);
  356. cx_write(MC417_RWD, regval);
  357. regval |= MC417_MICS | MC417_MIWR;
  358. cx_write(MC417_RWD, regval);
  359. /* Indicate that this is a register read. */
  360. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
  361. MCI_MODE_REGISTER_READ;
  362. cx_write(MC417_RWD, regval);
  363. regval |= MC417_MICS | MC417_MIWR;
  364. cx_write(MC417_RWD, regval);
  365. /* Wait for the trans to complete (MC417_MIRDY asserted). */
  366. retval = mc417_wait_ready(dev);
  367. /* switch the DAT0-7 GPIO[10:3] to input mode */
  368. cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
  369. /* Read data byte 0 */
  370. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
  371. cx_write(MC417_RWD, regval);
  372. /* Transition RD to effect read transaction across bus.
  373. * Transition 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
  374. * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
  375. * input only...)
  376. */
  377. regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
  378. cx_write(MC417_RWD, regval);
  379. /* Collect byte */
  380. tempval = cx_read(MC417_RWD);
  381. dataval = tempval & 0x000000FF;
  382. /* Bring CS and RD high. */
  383. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  384. cx_write(MC417_RWD, regval);
  385. /* Read data byte 1 */
  386. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
  387. cx_write(MC417_RWD, regval);
  388. regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
  389. cx_write(MC417_RWD, regval);
  390. tempval = cx_read(MC417_RWD);
  391. dataval |= ((tempval & 0x000000FF) << 8);
  392. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  393. cx_write(MC417_RWD, regval);
  394. /* Read data byte 2 */
  395. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
  396. cx_write(MC417_RWD, regval);
  397. regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
  398. cx_write(MC417_RWD, regval);
  399. tempval = cx_read(MC417_RWD);
  400. dataval |= ((tempval & 0x000000FF) << 16);
  401. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  402. cx_write(MC417_RWD, regval);
  403. /* Read data byte 3 */
  404. regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
  405. cx_write(MC417_RWD, regval);
  406. regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
  407. cx_write(MC417_RWD, regval);
  408. tempval = cx_read(MC417_RWD);
  409. dataval |= ((tempval & 0x000000FF) << 24);
  410. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  411. cx_write(MC417_RWD, regval);
  412. *value = dataval;
  413. return retval;
  414. }
  415. int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
  416. {
  417. u32 regval;
  418. /* Enable MC417 GPIO outputs except for MC417_MIRDY,
  419. * which is an input.
  420. */
  421. cx_write(MC417_OEN, MC417_MIRDY);
  422. /* Write data byte 0 */
  423. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
  424. (value & 0x000000FF);
  425. cx_write(MC417_RWD, regval);
  426. /* Transition CS/WR to effect write transaction across bus. */
  427. regval |= MC417_MICS | MC417_MIWR;
  428. cx_write(MC417_RWD, regval);
  429. /* Write data byte 1 */
  430. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
  431. ((value >> 8) & 0x000000FF);
  432. cx_write(MC417_RWD, regval);
  433. regval |= MC417_MICS | MC417_MIWR;
  434. cx_write(MC417_RWD, regval);
  435. /* Write data byte 2 */
  436. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
  437. ((value >> 16) & 0x000000FF);
  438. cx_write(MC417_RWD, regval);
  439. regval |= MC417_MICS | MC417_MIWR;
  440. cx_write(MC417_RWD, regval);
  441. /* Write data byte 3 */
  442. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
  443. ((value >> 24) & 0x000000FF);
  444. cx_write(MC417_RWD, regval);
  445. regval |= MC417_MICS | MC417_MIWR;
  446. cx_write(MC417_RWD, regval);
  447. /* Write address byte 2 */
  448. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
  449. MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
  450. cx_write(MC417_RWD, regval);
  451. regval |= MC417_MICS | MC417_MIWR;
  452. cx_write(MC417_RWD, regval);
  453. /* Write address byte 1 */
  454. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
  455. ((address >> 8) & 0xFF);
  456. cx_write(MC417_RWD, regval);
  457. regval |= MC417_MICS | MC417_MIWR;
  458. cx_write(MC417_RWD, regval);
  459. /* Write address byte 0 */
  460. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
  461. (address & 0xFF);
  462. cx_write(MC417_RWD, regval);
  463. regval |= MC417_MICS | MC417_MIWR;
  464. cx_write(MC417_RWD, regval);
  465. /* Wait for the trans to complete (MC417_MIRDY asserted). */
  466. return mc417_wait_ready(dev);
  467. }
  468. int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
  469. {
  470. int retval;
  471. u32 regval;
  472. u32 tempval;
  473. u32 dataval;
  474. /* Enable MC417 GPIO outputs except for MC417_MIRDY,
  475. * which is an input.
  476. */
  477. cx_write(MC417_OEN, MC417_MIRDY);
  478. /* Write address byte 2 */
  479. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
  480. MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
  481. cx_write(MC417_RWD, regval);
  482. regval |= MC417_MICS | MC417_MIWR;
  483. cx_write(MC417_RWD, regval);
  484. /* Write address byte 1 */
  485. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
  486. ((address >> 8) & 0xFF);
  487. cx_write(MC417_RWD, regval);
  488. regval |= MC417_MICS | MC417_MIWR;
  489. cx_write(MC417_RWD, regval);
  490. /* Write address byte 0 */
  491. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
  492. (address & 0xFF);
  493. cx_write(MC417_RWD, regval);
  494. regval |= MC417_MICS | MC417_MIWR;
  495. cx_write(MC417_RWD, regval);
  496. /* Wait for the trans to complete (MC417_MIRDY asserted). */
  497. retval = mc417_wait_ready(dev);
  498. /* switch the DAT0-7 GPIO[10:3] to input mode */
  499. cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
  500. /* Read data byte 3 */
  501. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
  502. cx_write(MC417_RWD, regval);
  503. /* Transition RD to effect read transaction across bus. */
  504. regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
  505. cx_write(MC417_RWD, regval);
  506. /* Collect byte */
  507. tempval = cx_read(MC417_RWD);
  508. dataval = ((tempval & 0x000000FF) << 24);
  509. /* Bring CS and RD high. */
  510. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  511. cx_write(MC417_RWD, regval);
  512. /* Read data byte 2 */
  513. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
  514. cx_write(MC417_RWD, regval);
  515. regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
  516. cx_write(MC417_RWD, regval);
  517. tempval = cx_read(MC417_RWD);
  518. dataval |= ((tempval & 0x000000FF) << 16);
  519. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  520. cx_write(MC417_RWD, regval);
  521. /* Read data byte 1 */
  522. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
  523. cx_write(MC417_RWD, regval);
  524. regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
  525. cx_write(MC417_RWD, regval);
  526. tempval = cx_read(MC417_RWD);
  527. dataval |= ((tempval & 0x000000FF) << 8);
  528. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  529. cx_write(MC417_RWD, regval);
  530. /* Read data byte 0 */
  531. regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
  532. cx_write(MC417_RWD, regval);
  533. regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
  534. cx_write(MC417_RWD, regval);
  535. tempval = cx_read(MC417_RWD);
  536. dataval |= (tempval & 0x000000FF);
  537. regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
  538. cx_write(MC417_RWD, regval);
  539. *value = dataval;
  540. return retval;
  541. }
  542. void mc417_gpio_set(struct cx23885_dev *dev, u32 mask)
  543. {
  544. u32 val;
  545. /* Set the gpio value */
  546. mc417_register_read(dev, 0x900C, &val);
  547. val |= (mask & 0x000ffff);
  548. mc417_register_write(dev, 0x900C, val);
  549. }
  550. void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask)
  551. {
  552. u32 val;
  553. /* Clear the gpio value */
  554. mc417_register_read(dev, 0x900C, &val);
  555. val &= ~(mask & 0x0000ffff);
  556. mc417_register_write(dev, 0x900C, val);
  557. }
  558. void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
  559. {
  560. u32 val;
  561. /* Enable GPIO direction bits */
  562. mc417_register_read(dev, 0x9020, &val);
  563. if (asoutput)
  564. val |= (mask & 0x0000ffff);
  565. else
  566. val &= ~(mask & 0x0000ffff);
  567. mc417_register_write(dev, 0x9020, val);
  568. }
  569. /* ------------------------------------------------------------------ */
  570. /* MPEG encoder API */
  571. static char *cmd_to_str(int cmd)
  572. {
  573. switch (cmd) {
  574. case CX2341X_ENC_PING_FW:
  575. return "PING_FW";
  576. case CX2341X_ENC_START_CAPTURE:
  577. return "START_CAPTURE";
  578. case CX2341X_ENC_STOP_CAPTURE:
  579. return "STOP_CAPTURE";
  580. case CX2341X_ENC_SET_AUDIO_ID:
  581. return "SET_AUDIO_ID";
  582. case CX2341X_ENC_SET_VIDEO_ID:
  583. return "SET_VIDEO_ID";
  584. case CX2341X_ENC_SET_PCR_ID:
  585. return "SET_PCR_ID";
  586. case CX2341X_ENC_SET_FRAME_RATE:
  587. return "SET_FRAME_RATE";
  588. case CX2341X_ENC_SET_FRAME_SIZE:
  589. return "SET_FRAME_SIZE";
  590. case CX2341X_ENC_SET_BIT_RATE:
  591. return "SET_BIT_RATE";
  592. case CX2341X_ENC_SET_GOP_PROPERTIES:
  593. return "SET_GOP_PROPERTIES";
  594. case CX2341X_ENC_SET_ASPECT_RATIO:
  595. return "SET_ASPECT_RATIO";
  596. case CX2341X_ENC_SET_DNR_FILTER_MODE:
  597. return "SET_DNR_FILTER_MODE";
  598. case CX2341X_ENC_SET_DNR_FILTER_PROPS:
  599. return "SET_DNR_FILTER_PROPS";
  600. case CX2341X_ENC_SET_CORING_LEVELS:
  601. return "SET_CORING_LEVELS";
  602. case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
  603. return "SET_SPATIAL_FILTER_TYPE";
  604. case CX2341X_ENC_SET_VBI_LINE:
  605. return "SET_VBI_LINE";
  606. case CX2341X_ENC_SET_STREAM_TYPE:
  607. return "SET_STREAM_TYPE";
  608. case CX2341X_ENC_SET_OUTPUT_PORT:
  609. return "SET_OUTPUT_PORT";
  610. case CX2341X_ENC_SET_AUDIO_PROPERTIES:
  611. return "SET_AUDIO_PROPERTIES";
  612. case CX2341X_ENC_HALT_FW:
  613. return "HALT_FW";
  614. case CX2341X_ENC_GET_VERSION:
  615. return "GET_VERSION";
  616. case CX2341X_ENC_SET_GOP_CLOSURE:
  617. return "SET_GOP_CLOSURE";
  618. case CX2341X_ENC_GET_SEQ_END:
  619. return "GET_SEQ_END";
  620. case CX2341X_ENC_SET_PGM_INDEX_INFO:
  621. return "SET_PGM_INDEX_INFO";
  622. case CX2341X_ENC_SET_VBI_CONFIG:
  623. return "SET_VBI_CONFIG";
  624. case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
  625. return "SET_DMA_BLOCK_SIZE";
  626. case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
  627. return "GET_PREV_DMA_INFO_MB_10";
  628. case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
  629. return "GET_PREV_DMA_INFO_MB_9";
  630. case CX2341X_ENC_SCHED_DMA_TO_HOST:
  631. return "SCHED_DMA_TO_HOST";
  632. case CX2341X_ENC_INITIALIZE_INPUT:
  633. return "INITIALIZE_INPUT";
  634. case CX2341X_ENC_SET_FRAME_DROP_RATE:
  635. return "SET_FRAME_DROP_RATE";
  636. case CX2341X_ENC_PAUSE_ENCODER:
  637. return "PAUSE_ENCODER";
  638. case CX2341X_ENC_REFRESH_INPUT:
  639. return "REFRESH_INPUT";
  640. case CX2341X_ENC_SET_COPYRIGHT:
  641. return "SET_COPYRIGHT";
  642. case CX2341X_ENC_SET_EVENT_NOTIFICATION:
  643. return "SET_EVENT_NOTIFICATION";
  644. case CX2341X_ENC_SET_NUM_VSYNC_LINES:
  645. return "SET_NUM_VSYNC_LINES";
  646. case CX2341X_ENC_SET_PLACEHOLDER:
  647. return "SET_PLACEHOLDER";
  648. case CX2341X_ENC_MUTE_VIDEO:
  649. return "MUTE_VIDEO";
  650. case CX2341X_ENC_MUTE_AUDIO:
  651. return "MUTE_AUDIO";
  652. case CX2341X_ENC_MISC:
  653. return "MISC";
  654. default:
  655. return "UNKNOWN";
  656. }
  657. }
  658. static int cx23885_mbox_func(void *priv,
  659. u32 command,
  660. int in,
  661. int out,
  662. u32 data[CX2341X_MBOX_MAX_DATA])
  663. {
  664. struct cx23885_dev *dev = priv;
  665. unsigned long timeout;
  666. u32 value, flag, retval = 0;
  667. int i;
  668. dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
  669. cmd_to_str(command));
  670. /* this may not be 100% safe if we can't read any memory location
  671. without side effects */
  672. mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
  673. if (value != 0x12345678) {
  674. pr_err("Firmware and/or mailbox pointer not initialized or corrupted, signature = 0x%x, cmd = %s\n",
  675. value, cmd_to_str(command));
  676. return -1;
  677. }
  678. /* This read looks at 32 bits, but flag is only 8 bits.
  679. * Seems we also bail if CMD or TIMEOUT bytes are set???
  680. */
  681. mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
  682. if (flag) {
  683. pr_err("ERROR: Mailbox appears to be in use (%x), cmd = %s\n",
  684. flag, cmd_to_str(command));
  685. return -1;
  686. }
  687. flag |= 1; /* tell 'em we're working on it */
  688. mc417_memory_write(dev, dev->cx23417_mailbox, flag);
  689. /* write command + args + fill remaining with zeros */
  690. /* command code */
  691. mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
  692. mc417_memory_write(dev, dev->cx23417_mailbox + 3,
  693. IVTV_API_STD_TIMEOUT); /* timeout */
  694. for (i = 0; i < in; i++) {
  695. mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
  696. dprintk(3, "API Input %d = %d\n", i, data[i]);
  697. }
  698. for (; i < CX2341X_MBOX_MAX_DATA; i++)
  699. mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
  700. flag |= 3; /* tell 'em we're done writing */
  701. mc417_memory_write(dev, dev->cx23417_mailbox, flag);
  702. /* wait for firmware to handle the API command */
  703. timeout = jiffies + msecs_to_jiffies(10);
  704. for (;;) {
  705. mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
  706. if (0 != (flag & 4))
  707. break;
  708. if (time_after(jiffies, timeout)) {
  709. pr_err("ERROR: API Mailbox timeout\n");
  710. return -1;
  711. }
  712. udelay(10);
  713. }
  714. /* read output values */
  715. for (i = 0; i < out; i++) {
  716. mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
  717. dprintk(3, "API Output %d = %d\n", i, data[i]);
  718. }
  719. mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
  720. dprintk(3, "API result = %d\n", retval);
  721. flag = 0;
  722. mc417_memory_write(dev, dev->cx23417_mailbox, flag);
  723. return retval;
  724. }
  725. /* We don't need to call the API often, so using just one
  726. * mailbox will probably suffice
  727. */
  728. static int cx23885_api_cmd(struct cx23885_dev *dev,
  729. u32 command,
  730. u32 inputcnt,
  731. u32 outputcnt,
  732. ...)
  733. {
  734. u32 data[CX2341X_MBOX_MAX_DATA];
  735. va_list vargs;
  736. int i, err;
  737. dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
  738. va_start(vargs, outputcnt);
  739. for (i = 0; i < inputcnt; i++)
  740. data[i] = va_arg(vargs, int);
  741. err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
  742. for (i = 0; i < outputcnt; i++) {
  743. int *vptr = va_arg(vargs, int *);
  744. *vptr = data[i];
  745. }
  746. va_end(vargs);
  747. return err;
  748. }
  749. static int cx23885_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
  750. {
  751. return cx23885_mbox_func(priv, cmd, in, out, data);
  752. }
  753. static int cx23885_find_mailbox(struct cx23885_dev *dev)
  754. {
  755. u32 signature[4] = {
  756. 0x12345678, 0x34567812, 0x56781234, 0x78123456
  757. };
  758. int signaturecnt = 0;
  759. u32 value;
  760. int i;
  761. dprintk(2, "%s()\n", __func__);
  762. for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
  763. mc417_memory_read(dev, i, &value);
  764. if (value == signature[signaturecnt])
  765. signaturecnt++;
  766. else
  767. signaturecnt = 0;
  768. if (4 == signaturecnt) {
  769. dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
  770. return i+1;
  771. }
  772. }
  773. pr_err("Mailbox signature values not found!\n");
  774. return -1;
  775. }
  776. static int cx23885_load_firmware(struct cx23885_dev *dev)
  777. {
  778. static const unsigned char magic[8] = {
  779. 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
  780. };
  781. const struct firmware *firmware;
  782. int i, retval = 0;
  783. u32 value = 0;
  784. u32 gpio_output = 0;
  785. u32 gpio_value;
  786. u32 checksum = 0;
  787. u32 *dataptr;
  788. dprintk(2, "%s()\n", __func__);
  789. /* Save GPIO settings before reset of APU */
  790. retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
  791. retval |= mc417_memory_read(dev, 0x900C, &gpio_value);
  792. retval = mc417_register_write(dev,
  793. IVTV_REG_VPU, 0xFFFFFFED);
  794. retval |= mc417_register_write(dev,
  795. IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
  796. retval |= mc417_register_write(dev,
  797. IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
  798. retval |= mc417_register_write(dev,
  799. IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
  800. retval |= mc417_register_write(dev,
  801. IVTV_REG_APU, 0);
  802. if (retval != 0) {
  803. pr_err("%s: Error with mc417_register_write\n",
  804. __func__);
  805. return -1;
  806. }
  807. retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
  808. &dev->pci->dev);
  809. if (retval != 0) {
  810. pr_err("ERROR: Hotplug firmware request failed (%s).\n",
  811. CX23885_FIRM_IMAGE_NAME);
  812. pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
  813. return -1;
  814. }
  815. if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
  816. pr_err("ERROR: Firmware size mismatch (have %zu, expected %d)\n",
  817. firmware->size, CX23885_FIRM_IMAGE_SIZE);
  818. release_firmware(firmware);
  819. return -1;
  820. }
  821. if (0 != memcmp(firmware->data, magic, 8)) {
  822. pr_err("ERROR: Firmware magic mismatch, wrong file?\n");
  823. release_firmware(firmware);
  824. return -1;
  825. }
  826. /* transfer to the chip */
  827. dprintk(2, "Loading firmware ...\n");
  828. dataptr = (u32 *)firmware->data;
  829. for (i = 0; i < (firmware->size >> 2); i++) {
  830. value = *dataptr;
  831. checksum += ~value;
  832. if (mc417_memory_write(dev, i, value) != 0) {
  833. pr_err("ERROR: Loading firmware failed!\n");
  834. release_firmware(firmware);
  835. return -1;
  836. }
  837. dataptr++;
  838. }
  839. /* read back to verify with the checksum */
  840. dprintk(1, "Verifying firmware ...\n");
  841. for (i--; i >= 0; i--) {
  842. if (mc417_memory_read(dev, i, &value) != 0) {
  843. pr_err("ERROR: Reading firmware failed!\n");
  844. release_firmware(firmware);
  845. return -1;
  846. }
  847. checksum -= ~value;
  848. }
  849. if (checksum) {
  850. pr_err("ERROR: Firmware load failed (checksum mismatch).\n");
  851. release_firmware(firmware);
  852. return -1;
  853. }
  854. release_firmware(firmware);
  855. dprintk(1, "Firmware upload successful.\n");
  856. retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
  857. IVTV_CMD_HW_BLOCKS_RST);
  858. /* F/W power up disturbs the GPIOs, restore state */
  859. retval |= mc417_register_write(dev, 0x9020, gpio_output);
  860. retval |= mc417_register_write(dev, 0x900C, gpio_value);
  861. retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
  862. retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
  863. /* Hardcoded GPIO's here */
  864. retval |= mc417_register_write(dev, 0x9020, 0x4000);
  865. retval |= mc417_register_write(dev, 0x900C, 0x4000);
  866. mc417_register_read(dev, 0x9020, &gpio_output);
  867. mc417_register_read(dev, 0x900C, &gpio_value);
  868. if (retval < 0)
  869. pr_err("%s: Error with mc417_register_write\n",
  870. __func__);
  871. return 0;
  872. }
  873. void cx23885_417_check_encoder(struct cx23885_dev *dev)
  874. {
  875. u32 status, seq;
  876. status = seq = 0;
  877. cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
  878. dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
  879. }
  880. static void cx23885_codec_settings(struct cx23885_dev *dev)
  881. {
  882. dprintk(1, "%s()\n", __func__);
  883. /* Dynamically change the height based on video standard */
  884. if (dev->encodernorm.id & V4L2_STD_525_60)
  885. dev->ts1.height = 480;
  886. else
  887. dev->ts1.height = 576;
  888. /* assign frame size */
  889. cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
  890. dev->ts1.height, dev->ts1.width);
  891. dev->cxhdl.width = dev->ts1.width;
  892. dev->cxhdl.height = dev->ts1.height;
  893. dev->cxhdl.is_50hz =
  894. (dev->encodernorm.id & V4L2_STD_625_50) != 0;
  895. cx2341x_handler_setup(&dev->cxhdl);
  896. cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
  897. cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
  898. }
  899. static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
  900. {
  901. int version;
  902. int retval;
  903. u32 i, data[7];
  904. dprintk(1, "%s()\n", __func__);
  905. retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
  906. if (retval < 0) {
  907. dprintk(2, "%s() PING OK\n", __func__);
  908. retval = cx23885_load_firmware(dev);
  909. if (retval < 0) {
  910. pr_err("%s() f/w load failed\n", __func__);
  911. return retval;
  912. }
  913. retval = cx23885_find_mailbox(dev);
  914. if (retval < 0) {
  915. pr_err("%s() mailbox < 0, error\n",
  916. __func__);
  917. return -1;
  918. }
  919. dev->cx23417_mailbox = retval;
  920. retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
  921. if (retval < 0) {
  922. pr_err("ERROR: cx23417 firmware ping failed!\n");
  923. return -1;
  924. }
  925. retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
  926. &version);
  927. if (retval < 0) {
  928. pr_err("ERROR: cx23417 firmware get encoder :version failed!\n");
  929. return -1;
  930. }
  931. dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
  932. msleep(200);
  933. }
  934. cx23885_codec_settings(dev);
  935. msleep(60);
  936. cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
  937. CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
  938. cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
  939. CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  940. 0, 0);
  941. /* Setup to capture VBI */
  942. data[0] = 0x0001BD00;
  943. data[1] = 1; /* frames per interrupt */
  944. data[2] = 4; /* total bufs */
  945. data[3] = 0x91559155; /* start codes */
  946. data[4] = 0x206080C0; /* stop codes */
  947. data[5] = 6; /* lines */
  948. data[6] = 64; /* BPL */
  949. cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
  950. data[2], data[3], data[4], data[5], data[6]);
  951. for (i = 2; i <= 24; i++) {
  952. int valid;
  953. valid = ((i >= 19) && (i <= 21));
  954. cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
  955. valid, 0 , 0, 0);
  956. cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
  957. i | 0x80000000, valid, 0, 0, 0);
  958. }
  959. cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
  960. msleep(60);
  961. /* initialize the video input */
  962. cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
  963. msleep(60);
  964. /* Enable VIP style pixel invalidation so we work with scaled mode */
  965. mc417_memory_write(dev, 2120, 0x00000080);
  966. /* start capturing to the host interface */
  967. if (startencoder) {
  968. cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
  969. CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
  970. msleep(10);
  971. }
  972. return 0;
  973. }
  974. /* ------------------------------------------------------------------ */
  975. static int queue_setup(struct vb2_queue *q,
  976. unsigned int *num_buffers, unsigned int *num_planes,
  977. unsigned int sizes[], struct device *alloc_devs[])
  978. {
  979. struct cx23885_dev *dev = q->drv_priv;
  980. dev->ts1.ts_packet_size = mpeglinesize;
  981. dev->ts1.ts_packet_count = mpeglines;
  982. *num_planes = 1;
  983. sizes[0] = mpeglinesize * mpeglines;
  984. *num_buffers = mpegbufs;
  985. return 0;
  986. }
  987. static int buffer_prepare(struct vb2_buffer *vb)
  988. {
  989. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  990. struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
  991. struct cx23885_buffer *buf =
  992. container_of(vbuf, struct cx23885_buffer, vb);
  993. return cx23885_buf_prepare(buf, &dev->ts1);
  994. }
  995. static void buffer_finish(struct vb2_buffer *vb)
  996. {
  997. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  998. struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
  999. struct cx23885_buffer *buf = container_of(vbuf,
  1000. struct cx23885_buffer, vb);
  1001. cx23885_free_buffer(dev, buf);
  1002. }
  1003. static void buffer_queue(struct vb2_buffer *vb)
  1004. {
  1005. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  1006. struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
  1007. struct cx23885_buffer *buf = container_of(vbuf,
  1008. struct cx23885_buffer, vb);
  1009. cx23885_buf_queue(&dev->ts1, buf);
  1010. }
  1011. static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count)
  1012. {
  1013. struct cx23885_dev *dev = q->drv_priv;
  1014. struct cx23885_dmaqueue *dmaq = &dev->ts1.mpegq;
  1015. unsigned long flags;
  1016. int ret;
  1017. ret = cx23885_initialize_codec(dev, 1);
  1018. if (ret == 0) {
  1019. struct cx23885_buffer *buf = list_entry(dmaq->active.next,
  1020. struct cx23885_buffer, queue);
  1021. cx23885_start_dma(&dev->ts1, dmaq, buf);
  1022. return 0;
  1023. }
  1024. spin_lock_irqsave(&dev->slock, flags);
  1025. while (!list_empty(&dmaq->active)) {
  1026. struct cx23885_buffer *buf = list_entry(dmaq->active.next,
  1027. struct cx23885_buffer, queue);
  1028. list_del(&buf->queue);
  1029. vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
  1030. }
  1031. spin_unlock_irqrestore(&dev->slock, flags);
  1032. return ret;
  1033. }
  1034. static void cx23885_stop_streaming(struct vb2_queue *q)
  1035. {
  1036. struct cx23885_dev *dev = q->drv_priv;
  1037. /* stop mpeg capture */
  1038. cx23885_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
  1039. CX23885_END_NOW, CX23885_MPEG_CAPTURE,
  1040. CX23885_RAW_BITS_NONE);
  1041. msleep(500);
  1042. cx23885_417_check_encoder(dev);
  1043. cx23885_cancel_buffers(&dev->ts1);
  1044. }
  1045. static const struct vb2_ops cx23885_qops = {
  1046. .queue_setup = queue_setup,
  1047. .buf_prepare = buffer_prepare,
  1048. .buf_finish = buffer_finish,
  1049. .buf_queue = buffer_queue,
  1050. .wait_prepare = vb2_ops_wait_prepare,
  1051. .wait_finish = vb2_ops_wait_finish,
  1052. .start_streaming = cx23885_start_streaming,
  1053. .stop_streaming = cx23885_stop_streaming,
  1054. };
  1055. /* ------------------------------------------------------------------ */
  1056. static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
  1057. {
  1058. struct cx23885_dev *dev = video_drvdata(file);
  1059. *id = dev->tvnorm;
  1060. return 0;
  1061. }
  1062. static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
  1063. {
  1064. struct cx23885_dev *dev = video_drvdata(file);
  1065. unsigned int i;
  1066. int ret;
  1067. for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
  1068. if (id & cx23885_tvnorms[i].id)
  1069. break;
  1070. if (i == ARRAY_SIZE(cx23885_tvnorms))
  1071. return -EINVAL;
  1072. ret = cx23885_set_tvnorm(dev, id);
  1073. if (!ret)
  1074. dev->encodernorm = cx23885_tvnorms[i];
  1075. return ret;
  1076. }
  1077. static int vidioc_enum_input(struct file *file, void *priv,
  1078. struct v4l2_input *i)
  1079. {
  1080. struct cx23885_dev *dev = video_drvdata(file);
  1081. dprintk(1, "%s()\n", __func__);
  1082. return cx23885_enum_input(dev, i);
  1083. }
  1084. static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
  1085. {
  1086. return cx23885_get_input(file, priv, i);
  1087. }
  1088. static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
  1089. {
  1090. return cx23885_set_input(file, priv, i);
  1091. }
  1092. static int vidioc_g_tuner(struct file *file, void *priv,
  1093. struct v4l2_tuner *t)
  1094. {
  1095. struct cx23885_dev *dev = video_drvdata(file);
  1096. if (dev->tuner_type == TUNER_ABSENT)
  1097. return -EINVAL;
  1098. if (0 != t->index)
  1099. return -EINVAL;
  1100. strscpy(t->name, "Television", sizeof(t->name));
  1101. call_all(dev, tuner, g_tuner, t);
  1102. dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
  1103. return 0;
  1104. }
  1105. static int vidioc_s_tuner(struct file *file, void *priv,
  1106. const struct v4l2_tuner *t)
  1107. {
  1108. struct cx23885_dev *dev = video_drvdata(file);
  1109. if (dev->tuner_type == TUNER_ABSENT)
  1110. return -EINVAL;
  1111. /* Update the A/V core */
  1112. call_all(dev, tuner, s_tuner, t);
  1113. return 0;
  1114. }
  1115. static int vidioc_g_frequency(struct file *file, void *priv,
  1116. struct v4l2_frequency *f)
  1117. {
  1118. struct cx23885_dev *dev = video_drvdata(file);
  1119. if (dev->tuner_type == TUNER_ABSENT)
  1120. return -EINVAL;
  1121. f->type = V4L2_TUNER_ANALOG_TV;
  1122. f->frequency = dev->freq;
  1123. call_all(dev, tuner, g_frequency, f);
  1124. return 0;
  1125. }
  1126. static int vidioc_s_frequency(struct file *file, void *priv,
  1127. const struct v4l2_frequency *f)
  1128. {
  1129. return cx23885_set_frequency(file, priv, f);
  1130. }
  1131. static int vidioc_querycap(struct file *file, void *priv,
  1132. struct v4l2_capability *cap)
  1133. {
  1134. struct cx23885_dev *dev = video_drvdata(file);
  1135. struct cx23885_tsport *tsport = &dev->ts1;
  1136. strscpy(cap->driver, dev->name, sizeof(cap->driver));
  1137. strscpy(cap->card, cx23885_boards[tsport->dev->board].name,
  1138. sizeof(cap->card));
  1139. sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
  1140. cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
  1141. V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE |
  1142. V4L2_CAP_AUDIO | V4L2_CAP_DEVICE_CAPS;
  1143. if (dev->tuner_type != TUNER_ABSENT)
  1144. cap->capabilities |= V4L2_CAP_TUNER;
  1145. return 0;
  1146. }
  1147. static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
  1148. struct v4l2_fmtdesc *f)
  1149. {
  1150. if (f->index != 0)
  1151. return -EINVAL;
  1152. f->pixelformat = V4L2_PIX_FMT_MPEG;
  1153. return 0;
  1154. }
  1155. static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
  1156. struct v4l2_format *f)
  1157. {
  1158. struct cx23885_dev *dev = video_drvdata(file);
  1159. f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
  1160. f->fmt.pix.bytesperline = 0;
  1161. f->fmt.pix.sizeimage =
  1162. dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
  1163. f->fmt.pix.colorspace = 0;
  1164. f->fmt.pix.width = dev->ts1.width;
  1165. f->fmt.pix.height = dev->ts1.height;
  1166. f->fmt.pix.field = V4L2_FIELD_INTERLACED;
  1167. dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
  1168. dev->ts1.width, dev->ts1.height);
  1169. return 0;
  1170. }
  1171. static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
  1172. struct v4l2_format *f)
  1173. {
  1174. struct cx23885_dev *dev = video_drvdata(file);
  1175. f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
  1176. f->fmt.pix.bytesperline = 0;
  1177. f->fmt.pix.sizeimage =
  1178. dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
  1179. f->fmt.pix.colorspace = 0;
  1180. f->fmt.pix.field = V4L2_FIELD_INTERLACED;
  1181. dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
  1182. dev->ts1.width, dev->ts1.height);
  1183. return 0;
  1184. }
  1185. static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
  1186. struct v4l2_format *f)
  1187. {
  1188. struct cx23885_dev *dev = video_drvdata(file);
  1189. f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
  1190. f->fmt.pix.bytesperline = 0;
  1191. f->fmt.pix.sizeimage =
  1192. dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
  1193. f->fmt.pix.colorspace = 0;
  1194. f->fmt.pix.field = V4L2_FIELD_INTERLACED;
  1195. dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
  1196. f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
  1197. return 0;
  1198. }
  1199. static int vidioc_log_status(struct file *file, void *priv)
  1200. {
  1201. struct cx23885_dev *dev = video_drvdata(file);
  1202. char name[32 + 2];
  1203. snprintf(name, sizeof(name), "%s/2", dev->name);
  1204. call_all(dev, core, log_status);
  1205. v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
  1206. return 0;
  1207. }
  1208. static const struct v4l2_file_operations mpeg_fops = {
  1209. .owner = THIS_MODULE,
  1210. .open = v4l2_fh_open,
  1211. .release = vb2_fop_release,
  1212. .read = vb2_fop_read,
  1213. .poll = vb2_fop_poll,
  1214. .unlocked_ioctl = video_ioctl2,
  1215. .mmap = vb2_fop_mmap,
  1216. };
  1217. static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
  1218. .vidioc_g_std = vidioc_g_std,
  1219. .vidioc_s_std = vidioc_s_std,
  1220. .vidioc_enum_input = vidioc_enum_input,
  1221. .vidioc_g_input = vidioc_g_input,
  1222. .vidioc_s_input = vidioc_s_input,
  1223. .vidioc_g_tuner = vidioc_g_tuner,
  1224. .vidioc_s_tuner = vidioc_s_tuner,
  1225. .vidioc_g_frequency = vidioc_g_frequency,
  1226. .vidioc_s_frequency = vidioc_s_frequency,
  1227. .vidioc_querycap = vidioc_querycap,
  1228. .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
  1229. .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
  1230. .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
  1231. .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
  1232. .vidioc_reqbufs = vb2_ioctl_reqbufs,
  1233. .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
  1234. .vidioc_querybuf = vb2_ioctl_querybuf,
  1235. .vidioc_qbuf = vb2_ioctl_qbuf,
  1236. .vidioc_dqbuf = vb2_ioctl_dqbuf,
  1237. .vidioc_streamon = vb2_ioctl_streamon,
  1238. .vidioc_streamoff = vb2_ioctl_streamoff,
  1239. .vidioc_log_status = vidioc_log_status,
  1240. #ifdef CONFIG_VIDEO_ADV_DEBUG
  1241. .vidioc_g_chip_info = cx23885_g_chip_info,
  1242. .vidioc_g_register = cx23885_g_register,
  1243. .vidioc_s_register = cx23885_s_register,
  1244. #endif
  1245. };
  1246. static struct video_device cx23885_mpeg_template = {
  1247. .name = "cx23885",
  1248. .fops = &mpeg_fops,
  1249. .ioctl_ops = &mpeg_ioctl_ops,
  1250. .tvnorms = CX23885_NORMS,
  1251. };
  1252. void cx23885_417_unregister(struct cx23885_dev *dev)
  1253. {
  1254. dprintk(1, "%s()\n", __func__);
  1255. if (dev->v4l_device) {
  1256. if (video_is_registered(dev->v4l_device))
  1257. video_unregister_device(dev->v4l_device);
  1258. else
  1259. video_device_release(dev->v4l_device);
  1260. v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
  1261. dev->v4l_device = NULL;
  1262. }
  1263. }
  1264. static struct video_device *cx23885_video_dev_alloc(
  1265. struct cx23885_tsport *tsport,
  1266. struct pci_dev *pci,
  1267. struct video_device *template,
  1268. char *type)
  1269. {
  1270. struct video_device *vfd;
  1271. struct cx23885_dev *dev = tsport->dev;
  1272. dprintk(1, "%s()\n", __func__);
  1273. vfd = video_device_alloc();
  1274. if (NULL == vfd)
  1275. return NULL;
  1276. *vfd = *template;
  1277. snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
  1278. cx23885_boards[tsport->dev->board].name, type);
  1279. vfd->v4l2_dev = &dev->v4l2_dev;
  1280. vfd->release = video_device_release;
  1281. return vfd;
  1282. }
  1283. int cx23885_417_register(struct cx23885_dev *dev)
  1284. {
  1285. /* FIXME: Port1 hardcoded here */
  1286. int err = -ENODEV;
  1287. struct cx23885_tsport *tsport = &dev->ts1;
  1288. struct vb2_queue *q;
  1289. dprintk(1, "%s()\n", __func__);
  1290. if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
  1291. return err;
  1292. /* Set default TV standard */
  1293. dev->encodernorm = cx23885_tvnorms[0];
  1294. if (dev->encodernorm.id & V4L2_STD_525_60)
  1295. tsport->height = 480;
  1296. else
  1297. tsport->height = 576;
  1298. tsport->width = 720;
  1299. dev->cxhdl.port = CX2341X_PORT_SERIAL;
  1300. err = cx2341x_handler_init(&dev->cxhdl, 50);
  1301. if (err)
  1302. return err;
  1303. dev->cxhdl.priv = dev;
  1304. dev->cxhdl.func = cx23885_api_func;
  1305. cx2341x_handler_set_50hz(&dev->cxhdl, tsport->height == 576);
  1306. v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL, false);
  1307. /* Allocate and initialize V4L video device */
  1308. dev->v4l_device = cx23885_video_dev_alloc(tsport,
  1309. dev->pci, &cx23885_mpeg_template, "mpeg");
  1310. q = &dev->vb2_mpegq;
  1311. q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1312. q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
  1313. q->gfp_flags = GFP_DMA32;
  1314. q->min_buffers_needed = 2;
  1315. q->drv_priv = dev;
  1316. q->buf_struct_size = sizeof(struct cx23885_buffer);
  1317. q->ops = &cx23885_qops;
  1318. q->mem_ops = &vb2_dma_sg_memops;
  1319. q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
  1320. q->lock = &dev->lock;
  1321. q->dev = &dev->pci->dev;
  1322. err = vb2_queue_init(q);
  1323. if (err < 0)
  1324. return err;
  1325. video_set_drvdata(dev->v4l_device, dev);
  1326. dev->v4l_device->lock = &dev->lock;
  1327. dev->v4l_device->queue = q;
  1328. dev->v4l_device->device_caps = V4L2_CAP_VIDEO_CAPTURE |
  1329. V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
  1330. if (dev->tuner_type != TUNER_ABSENT)
  1331. dev->v4l_device->device_caps |= V4L2_CAP_TUNER;
  1332. err = video_register_device(dev->v4l_device,
  1333. VFL_TYPE_VIDEO, -1);
  1334. if (err < 0) {
  1335. pr_info("%s: can't register mpeg device\n", dev->name);
  1336. return err;
  1337. }
  1338. pr_info("%s: registered device %s [mpeg]\n",
  1339. dev->name, video_device_node_name(dev->v4l_device));
  1340. /* ST: Configure the encoder parameters, but don't begin
  1341. * encoding, this resolves an issue where the first time the
  1342. * encoder is started video can be choppy.
  1343. */
  1344. cx23885_initialize_codec(dev, 0);
  1345. return 0;
  1346. }
  1347. MODULE_FIRMWARE(CX23885_FIRM_IMAGE_NAME);