cx88-core.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. /*
  2. * device driver for Conexant 2388x based TV cards
  3. * driver core
  4. *
  5. * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  6. *
  7. * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@kernel.org>
  8. * - Multituner support
  9. * - video_ioctl2 conversion
  10. * - PAL/M fixes
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. */
  22. #include "cx88.h"
  23. #include <linux/init.h>
  24. #include <linux/list.h>
  25. #include <linux/module.h>
  26. #include <linux/kernel.h>
  27. #include <linux/slab.h>
  28. #include <linux/kmod.h>
  29. #include <linux/sound.h>
  30. #include <linux/interrupt.h>
  31. #include <linux/pci.h>
  32. #include <linux/delay.h>
  33. #include <linux/videodev2.h>
  34. #include <linux/mutex.h>
  35. #include <media/v4l2-common.h>
  36. #include <media/v4l2-ioctl.h>
  37. MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
  38. MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  39. MODULE_LICENSE("GPL");
  40. /* ------------------------------------------------------------------ */
  41. unsigned int cx88_core_debug;
  42. module_param_named(core_debug, cx88_core_debug, int, 0644);
  43. MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
  44. static unsigned int nicam;
  45. module_param(nicam, int, 0644);
  46. MODULE_PARM_DESC(nicam, "tv audio is nicam");
  47. static unsigned int nocomb;
  48. module_param(nocomb, int, 0644);
  49. MODULE_PARM_DESC(nocomb, "disable comb filter");
  50. #define dprintk0(fmt, arg...) \
  51. printk(KERN_DEBUG pr_fmt("%s: core:" fmt), \
  52. __func__, ##arg) \
  53. #define dprintk(level, fmt, arg...) do { \
  54. if (cx88_core_debug >= level) \
  55. printk(KERN_DEBUG pr_fmt("%s: core:" fmt), \
  56. __func__, ##arg); \
  57. } while (0)
  58. static unsigned int cx88_devcount;
  59. static LIST_HEAD(cx88_devlist);
  60. static DEFINE_MUTEX(devlist);
  61. #define NO_SYNC_LINE (-1U)
  62. /*
  63. * @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
  64. * generated _after_ lpi lines are transferred.
  65. */
  66. static __le32 *cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
  67. unsigned int offset, u32 sync_line,
  68. unsigned int bpl, unsigned int padding,
  69. unsigned int lines, unsigned int lpi, bool jump)
  70. {
  71. struct scatterlist *sg;
  72. unsigned int line, todo, sol;
  73. if (jump) {
  74. (*rp++) = cpu_to_le32(RISC_JUMP);
  75. (*rp++) = 0;
  76. }
  77. /* sync instruction */
  78. if (sync_line != NO_SYNC_LINE)
  79. *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
  80. /* scan lines */
  81. sg = sglist;
  82. for (line = 0; line < lines; line++) {
  83. while (offset && offset >= sg_dma_len(sg)) {
  84. offset -= sg_dma_len(sg);
  85. sg = sg_next(sg);
  86. }
  87. if (lpi && line > 0 && !(line % lpi))
  88. sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
  89. else
  90. sol = RISC_SOL;
  91. if (bpl <= sg_dma_len(sg) - offset) {
  92. /* fits into current chunk */
  93. *(rp++) = cpu_to_le32(RISC_WRITE | sol |
  94. RISC_EOL | bpl);
  95. *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
  96. offset += bpl;
  97. } else {
  98. /* scanline needs to be split */
  99. todo = bpl;
  100. *(rp++) = cpu_to_le32(RISC_WRITE | sol |
  101. (sg_dma_len(sg) - offset));
  102. *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
  103. todo -= (sg_dma_len(sg) - offset);
  104. offset = 0;
  105. sg = sg_next(sg);
  106. while (todo > sg_dma_len(sg)) {
  107. *(rp++) = cpu_to_le32(RISC_WRITE |
  108. sg_dma_len(sg));
  109. *(rp++) = cpu_to_le32(sg_dma_address(sg));
  110. todo -= sg_dma_len(sg);
  111. sg = sg_next(sg);
  112. }
  113. *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
  114. *(rp++) = cpu_to_le32(sg_dma_address(sg));
  115. offset += todo;
  116. }
  117. offset += padding;
  118. }
  119. return rp;
  120. }
  121. int cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
  122. struct scatterlist *sglist,
  123. unsigned int top_offset, unsigned int bottom_offset,
  124. unsigned int bpl, unsigned int padding, unsigned int lines)
  125. {
  126. u32 instructions, fields;
  127. __le32 *rp;
  128. fields = 0;
  129. if (top_offset != UNSET)
  130. fields++;
  131. if (bottom_offset != UNSET)
  132. fields++;
  133. /*
  134. * estimate risc mem: worst case is one write per page border +
  135. * one write per scan line + syncs + jump (all 2 dwords). Padding
  136. * can cause next bpl to start close to a page border. First DMA
  137. * region may be smaller than PAGE_SIZE
  138. */
  139. instructions = fields * (1 + ((bpl + padding) * lines) /
  140. PAGE_SIZE + lines);
  141. instructions += 4;
  142. risc->size = instructions * 8;
  143. risc->dma = 0;
  144. risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
  145. if (!risc->cpu)
  146. return -ENOMEM;
  147. /* write risc instructions */
  148. rp = risc->cpu;
  149. if (top_offset != UNSET)
  150. rp = cx88_risc_field(rp, sglist, top_offset, 0,
  151. bpl, padding, lines, 0, true);
  152. if (bottom_offset != UNSET)
  153. rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
  154. bpl, padding, lines, 0,
  155. top_offset == UNSET);
  156. /* save pointer to jmp instruction address */
  157. risc->jmp = rp;
  158. WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
  159. return 0;
  160. }
  161. EXPORT_SYMBOL(cx88_risc_buffer);
  162. int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
  163. struct scatterlist *sglist, unsigned int bpl,
  164. unsigned int lines, unsigned int lpi)
  165. {
  166. u32 instructions;
  167. __le32 *rp;
  168. /*
  169. * estimate risc mem: worst case is one write per page border +
  170. * one write per scan line + syncs + jump (all 2 dwords). Here
  171. * there is no padding and no sync. First DMA region may be smaller
  172. * than PAGE_SIZE
  173. */
  174. instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
  175. instructions += 3;
  176. risc->size = instructions * 8;
  177. risc->dma = 0;
  178. risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
  179. if (!risc->cpu)
  180. return -ENOMEM;
  181. /* write risc instructions */
  182. rp = risc->cpu;
  183. rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
  184. lines, lpi, !lpi);
  185. /* save pointer to jmp instruction address */
  186. risc->jmp = rp;
  187. WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
  188. return 0;
  189. }
  190. EXPORT_SYMBOL(cx88_risc_databuffer);
  191. /*
  192. * our SRAM memory layout
  193. */
  194. /*
  195. * we are going to put all thr risc programs into host memory, so we
  196. * can use the whole SDRAM for the DMA fifos. To simplify things, we
  197. * use a static memory layout. That surely will waste memory in case
  198. * we don't use all DMA channels at the same time (which will be the
  199. * case most of the time). But that still gives us enough FIFO space
  200. * to be able to deal with insane long pci latencies ...
  201. *
  202. * FIFO space allocations:
  203. * channel 21 (y video) - 10.0k
  204. * channel 22 (u video) - 2.0k
  205. * channel 23 (v video) - 2.0k
  206. * channel 24 (vbi) - 4.0k
  207. * channels 25+26 (audio) - 4.0k
  208. * channel 28 (mpeg) - 4.0k
  209. * channel 27 (audio rds)- 3.0k
  210. * TOTAL = 29.0k
  211. *
  212. * Every channel has 160 bytes control data (64 bytes instruction
  213. * queue and 6 CDT entries), which is close to 2k total.
  214. *
  215. * Address layout:
  216. * 0x0000 - 0x03ff CMDs / reserved
  217. * 0x0400 - 0x0bff instruction queues + CDs
  218. * 0x0c00 - FIFOs
  219. */
  220. const struct sram_channel cx88_sram_channels[] = {
  221. [SRAM_CH21] = {
  222. .name = "video y / packed",
  223. .cmds_start = 0x180040,
  224. .ctrl_start = 0x180400,
  225. .cdt = 0x180400 + 64,
  226. .fifo_start = 0x180c00,
  227. .fifo_size = 0x002800,
  228. .ptr1_reg = MO_DMA21_PTR1,
  229. .ptr2_reg = MO_DMA21_PTR2,
  230. .cnt1_reg = MO_DMA21_CNT1,
  231. .cnt2_reg = MO_DMA21_CNT2,
  232. },
  233. [SRAM_CH22] = {
  234. .name = "video u",
  235. .cmds_start = 0x180080,
  236. .ctrl_start = 0x1804a0,
  237. .cdt = 0x1804a0 + 64,
  238. .fifo_start = 0x183400,
  239. .fifo_size = 0x000800,
  240. .ptr1_reg = MO_DMA22_PTR1,
  241. .ptr2_reg = MO_DMA22_PTR2,
  242. .cnt1_reg = MO_DMA22_CNT1,
  243. .cnt2_reg = MO_DMA22_CNT2,
  244. },
  245. [SRAM_CH23] = {
  246. .name = "video v",
  247. .cmds_start = 0x1800c0,
  248. .ctrl_start = 0x180540,
  249. .cdt = 0x180540 + 64,
  250. .fifo_start = 0x183c00,
  251. .fifo_size = 0x000800,
  252. .ptr1_reg = MO_DMA23_PTR1,
  253. .ptr2_reg = MO_DMA23_PTR2,
  254. .cnt1_reg = MO_DMA23_CNT1,
  255. .cnt2_reg = MO_DMA23_CNT2,
  256. },
  257. [SRAM_CH24] = {
  258. .name = "vbi",
  259. .cmds_start = 0x180100,
  260. .ctrl_start = 0x1805e0,
  261. .cdt = 0x1805e0 + 64,
  262. .fifo_start = 0x184400,
  263. .fifo_size = 0x001000,
  264. .ptr1_reg = MO_DMA24_PTR1,
  265. .ptr2_reg = MO_DMA24_PTR2,
  266. .cnt1_reg = MO_DMA24_CNT1,
  267. .cnt2_reg = MO_DMA24_CNT2,
  268. },
  269. [SRAM_CH25] = {
  270. .name = "audio from",
  271. .cmds_start = 0x180140,
  272. .ctrl_start = 0x180680,
  273. .cdt = 0x180680 + 64,
  274. .fifo_start = 0x185400,
  275. .fifo_size = 0x001000,
  276. .ptr1_reg = MO_DMA25_PTR1,
  277. .ptr2_reg = MO_DMA25_PTR2,
  278. .cnt1_reg = MO_DMA25_CNT1,
  279. .cnt2_reg = MO_DMA25_CNT2,
  280. },
  281. [SRAM_CH26] = {
  282. .name = "audio to",
  283. .cmds_start = 0x180180,
  284. .ctrl_start = 0x180720,
  285. .cdt = 0x180680 + 64, /* same as audio IN */
  286. .fifo_start = 0x185400, /* same as audio IN */
  287. .fifo_size = 0x001000, /* same as audio IN */
  288. .ptr1_reg = MO_DMA26_PTR1,
  289. .ptr2_reg = MO_DMA26_PTR2,
  290. .cnt1_reg = MO_DMA26_CNT1,
  291. .cnt2_reg = MO_DMA26_CNT2,
  292. },
  293. [SRAM_CH28] = {
  294. .name = "mpeg",
  295. .cmds_start = 0x180200,
  296. .ctrl_start = 0x1807C0,
  297. .cdt = 0x1807C0 + 64,
  298. .fifo_start = 0x186400,
  299. .fifo_size = 0x001000,
  300. .ptr1_reg = MO_DMA28_PTR1,
  301. .ptr2_reg = MO_DMA28_PTR2,
  302. .cnt1_reg = MO_DMA28_CNT1,
  303. .cnt2_reg = MO_DMA28_CNT2,
  304. },
  305. [SRAM_CH27] = {
  306. .name = "audio rds",
  307. .cmds_start = 0x1801C0,
  308. .ctrl_start = 0x180860,
  309. .cdt = 0x180860 + 64,
  310. .fifo_start = 0x187400,
  311. .fifo_size = 0x000C00,
  312. .ptr1_reg = MO_DMA27_PTR1,
  313. .ptr2_reg = MO_DMA27_PTR2,
  314. .cnt1_reg = MO_DMA27_CNT1,
  315. .cnt2_reg = MO_DMA27_CNT2,
  316. },
  317. };
  318. EXPORT_SYMBOL(cx88_sram_channels);
  319. int cx88_sram_channel_setup(struct cx88_core *core,
  320. const struct sram_channel *ch,
  321. unsigned int bpl, u32 risc)
  322. {
  323. unsigned int i, lines;
  324. u32 cdt;
  325. bpl = (bpl + 7) & ~7; /* alignment */
  326. cdt = ch->cdt;
  327. lines = ch->fifo_size / bpl;
  328. if (lines > 6)
  329. lines = 6;
  330. WARN_ON(lines < 2);
  331. /* write CDT */
  332. for (i = 0; i < lines; i++)
  333. cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
  334. /* write CMDS */
  335. cx_write(ch->cmds_start + 0, risc);
  336. cx_write(ch->cmds_start + 4, cdt);
  337. cx_write(ch->cmds_start + 8, (lines * 16) >> 3);
  338. cx_write(ch->cmds_start + 12, ch->ctrl_start);
  339. cx_write(ch->cmds_start + 16, 64 >> 2);
  340. for (i = 20; i < 64; i += 4)
  341. cx_write(ch->cmds_start + i, 0);
  342. /* fill registers */
  343. cx_write(ch->ptr1_reg, ch->fifo_start);
  344. cx_write(ch->ptr2_reg, cdt);
  345. cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
  346. cx_write(ch->cnt2_reg, (lines * 16) >> 3);
  347. dprintk(2, "sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
  348. return 0;
  349. }
  350. EXPORT_SYMBOL(cx88_sram_channel_setup);
  351. /* ------------------------------------------------------------------ */
  352. /* debug helper code */
  353. static int cx88_risc_decode(u32 risc)
  354. {
  355. static const char * const instr[16] = {
  356. [RISC_SYNC >> 28] = "sync",
  357. [RISC_WRITE >> 28] = "write",
  358. [RISC_WRITEC >> 28] = "writec",
  359. [RISC_READ >> 28] = "read",
  360. [RISC_READC >> 28] = "readc",
  361. [RISC_JUMP >> 28] = "jump",
  362. [RISC_SKIP >> 28] = "skip",
  363. [RISC_WRITERM >> 28] = "writerm",
  364. [RISC_WRITECM >> 28] = "writecm",
  365. [RISC_WRITECR >> 28] = "writecr",
  366. };
  367. static int const incr[16] = {
  368. [RISC_WRITE >> 28] = 2,
  369. [RISC_JUMP >> 28] = 2,
  370. [RISC_WRITERM >> 28] = 3,
  371. [RISC_WRITECM >> 28] = 3,
  372. [RISC_WRITECR >> 28] = 4,
  373. };
  374. static const char * const bits[] = {
  375. "12", "13", "14", "resync",
  376. "cnt0", "cnt1", "18", "19",
  377. "20", "21", "22", "23",
  378. "irq1", "irq2", "eol", "sol",
  379. };
  380. int i;
  381. dprintk0("0x%08x [ %s", risc,
  382. instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
  383. for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)
  384. if (risc & (1 << (i + 12)))
  385. pr_cont(" %s", bits[i]);
  386. pr_cont(" count=%d ]\n", risc & 0xfff);
  387. return incr[risc >> 28] ? incr[risc >> 28] : 1;
  388. }
  389. void cx88_sram_channel_dump(struct cx88_core *core,
  390. const struct sram_channel *ch)
  391. {
  392. static const char * const name[] = {
  393. "initial risc",
  394. "cdt base",
  395. "cdt size",
  396. "iq base",
  397. "iq size",
  398. "risc pc",
  399. "iq wr ptr",
  400. "iq rd ptr",
  401. "cdt current",
  402. "pci target",
  403. "line / byte",
  404. };
  405. u32 risc;
  406. unsigned int i, j, n;
  407. dprintk0("%s - dma channel status dump\n", ch->name);
  408. for (i = 0; i < ARRAY_SIZE(name); i++)
  409. dprintk0(" cmds: %-12s: 0x%08x\n",
  410. name[i], cx_read(ch->cmds_start + 4 * i));
  411. for (n = 1, i = 0; i < 4; i++) {
  412. risc = cx_read(ch->cmds_start + 4 * (i + 11));
  413. pr_cont(" risc%d: ", i);
  414. if (--n)
  415. pr_cont("0x%08x [ arg #%d ]\n", risc, n);
  416. else
  417. n = cx88_risc_decode(risc);
  418. }
  419. for (i = 0; i < 16; i += n) {
  420. risc = cx_read(ch->ctrl_start + 4 * i);
  421. dprintk0(" iq %x: ", i);
  422. n = cx88_risc_decode(risc);
  423. for (j = 1; j < n; j++) {
  424. risc = cx_read(ch->ctrl_start + 4 * (i + j));
  425. pr_cont(" iq %x: 0x%08x [ arg #%d ]\n",
  426. i + j, risc, j);
  427. }
  428. }
  429. dprintk0("fifo: 0x%08x -> 0x%x\n",
  430. ch->fifo_start, ch->fifo_start + ch->fifo_size);
  431. dprintk0("ctrl: 0x%08x -> 0x%x\n",
  432. ch->ctrl_start, ch->ctrl_start + 6 * 16);
  433. dprintk0(" ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg));
  434. dprintk0(" ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg));
  435. dprintk0(" cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg));
  436. dprintk0(" cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg));
  437. }
  438. EXPORT_SYMBOL(cx88_sram_channel_dump);
  439. static const char *cx88_pci_irqs[32] = {
  440. "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
  441. "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
  442. "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
  443. "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
  444. };
  445. void cx88_print_irqbits(const char *tag, const char *strings[],
  446. int len, u32 bits, u32 mask)
  447. {
  448. unsigned int i;
  449. dprintk0("%s [0x%x]", tag, bits);
  450. for (i = 0; i < len; i++) {
  451. if (!(bits & (1 << i)))
  452. continue;
  453. if (strings[i])
  454. pr_cont(" %s", strings[i]);
  455. else
  456. pr_cont(" %d", i);
  457. if (!(mask & (1 << i)))
  458. continue;
  459. pr_cont("*");
  460. }
  461. pr_cont("\n");
  462. }
  463. EXPORT_SYMBOL(cx88_print_irqbits);
  464. /* ------------------------------------------------------------------ */
  465. int cx88_core_irq(struct cx88_core *core, u32 status)
  466. {
  467. int handled = 0;
  468. if (status & PCI_INT_IR_SMPINT) {
  469. cx88_ir_irq(core);
  470. handled++;
  471. }
  472. if (!handled)
  473. cx88_print_irqbits("irq pci",
  474. cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
  475. status, core->pci_irqmask);
  476. return handled;
  477. }
  478. EXPORT_SYMBOL(cx88_core_irq);
  479. void cx88_wakeup(struct cx88_core *core,
  480. struct cx88_dmaqueue *q, u32 count)
  481. {
  482. struct cx88_buffer *buf;
  483. buf = list_entry(q->active.next,
  484. struct cx88_buffer, list);
  485. buf->vb.vb2_buf.timestamp = ktime_get_ns();
  486. buf->vb.field = core->field;
  487. buf->vb.sequence = q->count++;
  488. list_del(&buf->list);
  489. vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
  490. }
  491. EXPORT_SYMBOL(cx88_wakeup);
  492. void cx88_shutdown(struct cx88_core *core)
  493. {
  494. /* disable RISC controller + IRQs */
  495. cx_write(MO_DEV_CNTRL2, 0);
  496. /* stop dma transfers */
  497. cx_write(MO_VID_DMACNTRL, 0x0);
  498. cx_write(MO_AUD_DMACNTRL, 0x0);
  499. cx_write(MO_TS_DMACNTRL, 0x0);
  500. cx_write(MO_VIP_DMACNTRL, 0x0);
  501. cx_write(MO_GPHST_DMACNTRL, 0x0);
  502. /* stop interrupts */
  503. cx_write(MO_PCI_INTMSK, 0x0);
  504. cx_write(MO_VID_INTMSK, 0x0);
  505. cx_write(MO_AUD_INTMSK, 0x0);
  506. cx_write(MO_TS_INTMSK, 0x0);
  507. cx_write(MO_VIP_INTMSK, 0x0);
  508. cx_write(MO_GPHST_INTMSK, 0x0);
  509. /* stop capturing */
  510. cx_write(VID_CAPTURE_CONTROL, 0);
  511. }
  512. EXPORT_SYMBOL(cx88_shutdown);
  513. int cx88_reset(struct cx88_core *core)
  514. {
  515. dprintk(1, "");
  516. cx88_shutdown(core);
  517. /* clear irq status */
  518. cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
  519. cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
  520. cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
  521. /* wait a bit */
  522. msleep(100);
  523. /* init sram */
  524. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
  525. 720 * 4, 0);
  526. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
  527. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
  528. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
  529. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
  530. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
  531. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
  532. 188 * 4, 0);
  533. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
  534. /* misc init ... */
  535. cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
  536. (1 << 12) | // agc gain
  537. (1 << 11) | // adaptibe agc
  538. (0 << 10) | // chroma agc
  539. (0 << 9) | // ckillen
  540. (7)));
  541. /* setup image format */
  542. cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
  543. /* setup FIFO Thresholds */
  544. cx_write(MO_PDMA_STHRSH, 0x0807);
  545. cx_write(MO_PDMA_DTHRSH, 0x0807);
  546. /* fixes flashing of image */
  547. cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
  548. cx_write(MO_AGC_BACK_VBI, 0x00E00555);
  549. cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
  550. cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
  551. cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
  552. /* Reset on-board parts */
  553. cx_write(MO_SRST_IO, 0);
  554. usleep_range(10000, 20000);
  555. cx_write(MO_SRST_IO, 1);
  556. return 0;
  557. }
  558. EXPORT_SYMBOL(cx88_reset);
  559. /* ------------------------------------------------------------------ */
  560. static inline unsigned int norm_swidth(v4l2_std_id norm)
  561. {
  562. return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
  563. }
  564. static inline unsigned int norm_hdelay(v4l2_std_id norm)
  565. {
  566. return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
  567. }
  568. static inline unsigned int norm_vdelay(v4l2_std_id norm)
  569. {
  570. return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
  571. }
  572. static inline unsigned int norm_fsc8(v4l2_std_id norm)
  573. {
  574. if (norm & V4L2_STD_PAL_M)
  575. return 28604892; // 3.575611 MHz
  576. if (norm & (V4L2_STD_PAL_Nc))
  577. return 28656448; // 3.582056 MHz
  578. if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
  579. return 28636360; // 3.57954545 MHz +/- 10 Hz
  580. /*
  581. * SECAM have also different sub carrier for chroma,
  582. * but step_db and step_dr, at cx88_set_tvnorm already handles that.
  583. *
  584. * The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
  585. */
  586. return 35468950; // 4.43361875 MHz +/- 5 Hz
  587. }
  588. static inline unsigned int norm_htotal(v4l2_std_id norm)
  589. {
  590. unsigned int fsc4 = norm_fsc8(norm) / 2;
  591. /* returns 4*FSC / vtotal / frames per seconds */
  592. return (norm & V4L2_STD_625_50) ?
  593. ((fsc4 + 312) / 625 + 12) / 25 :
  594. ((fsc4 + 262) / 525 * 1001 + 15000) / 30000;
  595. }
  596. static inline unsigned int norm_vbipack(v4l2_std_id norm)
  597. {
  598. return (norm & V4L2_STD_625_50) ? 511 : 400;
  599. }
  600. int cx88_set_scale(struct cx88_core *core, unsigned int width,
  601. unsigned int height, enum v4l2_field field)
  602. {
  603. unsigned int swidth = norm_swidth(core->tvnorm);
  604. unsigned int sheight = norm_maxh(core->tvnorm);
  605. u32 value;
  606. dprintk(1, "set_scale: %dx%d [%s%s,%s]\n", width, height,
  607. V4L2_FIELD_HAS_TOP(field) ? "T" : "",
  608. V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
  609. v4l2_norm_to_name(core->tvnorm));
  610. if (!V4L2_FIELD_HAS_BOTH(field))
  611. height *= 2;
  612. // recalc H delay and scale registers
  613. value = (width * norm_hdelay(core->tvnorm)) / swidth;
  614. value &= 0x3fe;
  615. cx_write(MO_HDELAY_EVEN, value);
  616. cx_write(MO_HDELAY_ODD, value);
  617. dprintk(1, "set_scale: hdelay 0x%04x (width %d)\n", value, swidth);
  618. value = (swidth * 4096 / width) - 4096;
  619. cx_write(MO_HSCALE_EVEN, value);
  620. cx_write(MO_HSCALE_ODD, value);
  621. dprintk(1, "set_scale: hscale 0x%04x\n", value);
  622. cx_write(MO_HACTIVE_EVEN, width);
  623. cx_write(MO_HACTIVE_ODD, width);
  624. dprintk(1, "set_scale: hactive 0x%04x\n", width);
  625. // recalc V scale Register (delay is constant)
  626. cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
  627. cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
  628. dprintk(1, "set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
  629. value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
  630. cx_write(MO_VSCALE_EVEN, value);
  631. cx_write(MO_VSCALE_ODD, value);
  632. dprintk(1, "set_scale: vscale 0x%04x\n", value);
  633. cx_write(MO_VACTIVE_EVEN, sheight);
  634. cx_write(MO_VACTIVE_ODD, sheight);
  635. dprintk(1, "set_scale: vactive 0x%04x\n", sheight);
  636. // setup filters
  637. value = 0;
  638. value |= (1 << 19); // CFILT (default)
  639. if (core->tvnorm & V4L2_STD_SECAM) {
  640. value |= (1 << 15);
  641. value |= (1 << 16);
  642. }
  643. if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
  644. value |= (1 << 13) | (1 << 5);
  645. if (field == V4L2_FIELD_INTERLACED)
  646. value |= (1 << 3); // VINT (interlaced vertical scaling)
  647. if (width < 385)
  648. value |= (1 << 0); // 3-tap interpolation
  649. if (width < 193)
  650. value |= (1 << 1); // 5-tap interpolation
  651. if (nocomb)
  652. value |= (3 << 5); // disable comb filter
  653. cx_andor(MO_FILTER_EVEN, 0x7ffc7f, value); /* preserve PEAKEN, PSEL */
  654. cx_andor(MO_FILTER_ODD, 0x7ffc7f, value);
  655. dprintk(1, "set_scale: filter 0x%04x\n", value);
  656. return 0;
  657. }
  658. EXPORT_SYMBOL(cx88_set_scale);
  659. static const u32 xtal = 28636363;
  660. static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
  661. {
  662. static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
  663. u64 pll;
  664. u32 reg;
  665. int i;
  666. if (prescale < 2)
  667. prescale = 2;
  668. if (prescale > 5)
  669. prescale = 5;
  670. pll = ofreq * 8 * prescale * (u64)(1 << 20);
  671. do_div(pll, xtal);
  672. reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
  673. if (((reg >> 20) & 0x3f) < 14) {
  674. pr_err("pll out of range\n");
  675. return -1;
  676. }
  677. dprintk(1, "set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
  678. reg, cx_read(MO_PLL_REG), ofreq);
  679. cx_write(MO_PLL_REG, reg);
  680. for (i = 0; i < 100; i++) {
  681. reg = cx_read(MO_DEVICE_STATUS);
  682. if (reg & (1 << 2)) {
  683. dprintk(1, "pll locked [pre=%d,ofreq=%d]\n",
  684. prescale, ofreq);
  685. return 0;
  686. }
  687. dprintk(1, "pll not locked yet, waiting ...\n");
  688. usleep_range(10000, 20000);
  689. }
  690. dprintk(1, "pll NOT locked [pre=%d,ofreq=%d]\n", prescale, ofreq);
  691. return -1;
  692. }
  693. int cx88_start_audio_dma(struct cx88_core *core)
  694. {
  695. /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
  696. int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
  697. int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size / AUD_RDS_LINES;
  698. /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
  699. if (cx_read(MO_AUD_DMACNTRL) & 0x10)
  700. return 0;
  701. /* setup fifo + format */
  702. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
  703. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
  704. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
  705. rds_bpl, 0);
  706. cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
  707. cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
  708. /* enable Up, Down and Audio RDS fifo */
  709. cx_write(MO_AUD_DMACNTRL, 0x0007);
  710. return 0;
  711. }
  712. int cx88_stop_audio_dma(struct cx88_core *core)
  713. {
  714. /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
  715. if (cx_read(MO_AUD_DMACNTRL) & 0x10)
  716. return 0;
  717. /* stop dma */
  718. cx_write(MO_AUD_DMACNTRL, 0x0000);
  719. return 0;
  720. }
  721. static int set_tvaudio(struct cx88_core *core)
  722. {
  723. v4l2_std_id norm = core->tvnorm;
  724. if (INPUT(core->input).type != CX88_VMUX_TELEVISION &&
  725. INPUT(core->input).type != CX88_VMUX_CABLE)
  726. return 0;
  727. if (V4L2_STD_PAL_BG & norm) {
  728. core->tvaudio = WW_BG;
  729. } else if (V4L2_STD_PAL_DK & norm) {
  730. core->tvaudio = WW_DK;
  731. } else if (V4L2_STD_PAL_I & norm) {
  732. core->tvaudio = WW_I;
  733. } else if (V4L2_STD_SECAM_L & norm) {
  734. core->tvaudio = WW_L;
  735. } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) &
  736. norm) {
  737. core->tvaudio = WW_BG;
  738. } else if (V4L2_STD_SECAM_DK & norm) {
  739. core->tvaudio = WW_DK;
  740. } else if ((V4L2_STD_NTSC_M & norm) ||
  741. (V4L2_STD_PAL_M & norm)) {
  742. core->tvaudio = WW_BTSC;
  743. } else if (V4L2_STD_NTSC_M_JP & norm) {
  744. core->tvaudio = WW_EIAJ;
  745. } else {
  746. pr_info("tvaudio support needs work for this tv norm [%s], sorry\n",
  747. v4l2_norm_to_name(core->tvnorm));
  748. core->tvaudio = WW_NONE;
  749. return 0;
  750. }
  751. cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
  752. cx88_set_tvaudio(core);
  753. /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
  754. /*
  755. * This should be needed only on cx88-alsa. It seems that some cx88 chips have
  756. * bugs and does require DMA enabled for it to work.
  757. */
  758. cx88_start_audio_dma(core);
  759. return 0;
  760. }
  761. int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
  762. {
  763. u32 fsc8;
  764. u32 adc_clock;
  765. u32 vdec_clock;
  766. u32 step_db, step_dr;
  767. u64 tmp64;
  768. u32 bdelay, agcdelay, htotal;
  769. u32 cxiformat, cxoformat;
  770. if (norm == core->tvnorm)
  771. return 0;
  772. if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
  773. vb2_is_busy(&core->v4ldev->vb2_vbiq)))
  774. return -EBUSY;
  775. if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
  776. return -EBUSY;
  777. core->tvnorm = norm;
  778. fsc8 = norm_fsc8(norm);
  779. adc_clock = xtal;
  780. vdec_clock = fsc8;
  781. step_db = fsc8;
  782. step_dr = fsc8;
  783. if (norm & V4L2_STD_NTSC_M_JP) {
  784. cxiformat = VideoFormatNTSCJapan;
  785. cxoformat = 0x181f0008;
  786. } else if (norm & V4L2_STD_NTSC_443) {
  787. cxiformat = VideoFormatNTSC443;
  788. cxoformat = 0x181f0008;
  789. } else if (norm & V4L2_STD_PAL_M) {
  790. cxiformat = VideoFormatPALM;
  791. cxoformat = 0x1c1f0008;
  792. } else if (norm & V4L2_STD_PAL_N) {
  793. cxiformat = VideoFormatPALN;
  794. cxoformat = 0x1c1f0008;
  795. } else if (norm & V4L2_STD_PAL_Nc) {
  796. cxiformat = VideoFormatPALNC;
  797. cxoformat = 0x1c1f0008;
  798. } else if (norm & V4L2_STD_PAL_60) {
  799. cxiformat = VideoFormatPAL60;
  800. cxoformat = 0x181f0008;
  801. } else if (norm & V4L2_STD_NTSC) {
  802. cxiformat = VideoFormatNTSC;
  803. cxoformat = 0x181f0008;
  804. } else if (norm & V4L2_STD_SECAM) {
  805. step_db = 4250000 * 8;
  806. step_dr = 4406250 * 8;
  807. cxiformat = VideoFormatSECAM;
  808. cxoformat = 0x181f0008;
  809. } else { /* PAL */
  810. cxiformat = VideoFormatPAL;
  811. cxoformat = 0x181f0008;
  812. }
  813. dprintk(1, "set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
  814. v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
  815. step_db, step_dr);
  816. set_pll(core, 2, vdec_clock);
  817. dprintk(1, "set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
  818. cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
  819. /*
  820. * Chroma AGC must be disabled if SECAM is used, we enable it
  821. * by default on PAL and NTSC
  822. */
  823. cx_andor(MO_INPUT_FORMAT, 0x40f,
  824. norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
  825. // FIXME: as-is from DScaler
  826. dprintk(1, "set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
  827. cxoformat, cx_read(MO_OUTPUT_FORMAT));
  828. cx_write(MO_OUTPUT_FORMAT, cxoformat);
  829. // MO_SCONV_REG = adc clock / video dec clock * 2^17
  830. tmp64 = adc_clock * (u64)(1 << 17);
  831. do_div(tmp64, vdec_clock);
  832. dprintk(1, "set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
  833. (u32)tmp64, cx_read(MO_SCONV_REG));
  834. cx_write(MO_SCONV_REG, (u32)tmp64);
  835. // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
  836. tmp64 = step_db * (u64)(1 << 22);
  837. do_div(tmp64, vdec_clock);
  838. dprintk(1, "set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
  839. (u32)tmp64, cx_read(MO_SUB_STEP));
  840. cx_write(MO_SUB_STEP, (u32)tmp64);
  841. // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
  842. tmp64 = step_dr * (u64)(1 << 22);
  843. do_div(tmp64, vdec_clock);
  844. dprintk(1, "set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
  845. (u32)tmp64, cx_read(MO_SUB_STEP_DR));
  846. cx_write(MO_SUB_STEP_DR, (u32)tmp64);
  847. // bdelay + agcdelay
  848. bdelay = vdec_clock * 65 / 20000000 + 21;
  849. agcdelay = vdec_clock * 68 / 20000000 + 15;
  850. dprintk(1,
  851. "set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
  852. (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST),
  853. bdelay, agcdelay);
  854. cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
  855. // htotal
  856. tmp64 = norm_htotal(norm) * (u64)vdec_clock;
  857. do_div(tmp64, fsc8);
  858. htotal = (u32)tmp64;
  859. dprintk(1,
  860. "set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
  861. htotal, cx_read(MO_HTOTAL), (u32)tmp64);
  862. cx_andor(MO_HTOTAL, 0x07ff, htotal);
  863. // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
  864. // the effective vbi offset ~244 samples, the same as the Bt8x8
  865. cx_write(MO_VBI_PACKET, (10 << 11) | norm_vbipack(norm));
  866. // this is needed as well to set all tvnorm parameter
  867. cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
  868. // audio
  869. set_tvaudio(core);
  870. // tell i2c chips
  871. call_all(core, video, s_std, norm);
  872. /*
  873. * The chroma_agc control should be inaccessible
  874. * if the video format is SECAM
  875. */
  876. v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
  877. // done
  878. return 0;
  879. }
  880. EXPORT_SYMBOL(cx88_set_tvnorm);
  881. /* ------------------------------------------------------------------ */
  882. void cx88_vdev_init(struct cx88_core *core,
  883. struct pci_dev *pci,
  884. struct video_device *vfd,
  885. const struct video_device *template_,
  886. const char *type)
  887. {
  888. *vfd = *template_;
  889. /*
  890. * The dev pointer of v4l2_device is NULL, instead we set the
  891. * video_device dev_parent pointer to the correct PCI bus device.
  892. * This driver is a rare example where there is one v4l2_device,
  893. * but the video nodes have different parent (PCI) devices.
  894. */
  895. vfd->v4l2_dev = &core->v4l2_dev;
  896. vfd->dev_parent = &pci->dev;
  897. vfd->release = video_device_release_empty;
  898. vfd->lock = &core->lock;
  899. snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
  900. core->name, type, core->board.name);
  901. }
  902. EXPORT_SYMBOL(cx88_vdev_init);
  903. struct cx88_core *cx88_core_get(struct pci_dev *pci)
  904. {
  905. struct cx88_core *core;
  906. mutex_lock(&devlist);
  907. list_for_each_entry(core, &cx88_devlist, devlist) {
  908. if (pci->bus->number != core->pci_bus)
  909. continue;
  910. if (PCI_SLOT(pci->devfn) != core->pci_slot)
  911. continue;
  912. if (cx88_get_resources(core, pci) != 0) {
  913. mutex_unlock(&devlist);
  914. return NULL;
  915. }
  916. refcount_inc(&core->refcount);
  917. mutex_unlock(&devlist);
  918. return core;
  919. }
  920. core = cx88_core_create(pci, cx88_devcount);
  921. if (core) {
  922. cx88_devcount++;
  923. list_add_tail(&core->devlist, &cx88_devlist);
  924. }
  925. mutex_unlock(&devlist);
  926. return core;
  927. }
  928. EXPORT_SYMBOL(cx88_core_get);
  929. void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
  930. {
  931. release_mem_region(pci_resource_start(pci, 0),
  932. pci_resource_len(pci, 0));
  933. if (!refcount_dec_and_test(&core->refcount))
  934. return;
  935. mutex_lock(&devlist);
  936. cx88_ir_fini(core);
  937. if (core->i2c_rc == 0) {
  938. if (core->i2c_rtc)
  939. i2c_unregister_device(core->i2c_rtc);
  940. i2c_del_adapter(&core->i2c_adap);
  941. }
  942. list_del(&core->devlist);
  943. iounmap(core->lmmio);
  944. cx88_devcount--;
  945. mutex_unlock(&devlist);
  946. v4l2_ctrl_handler_free(&core->video_hdl);
  947. v4l2_ctrl_handler_free(&core->audio_hdl);
  948. v4l2_device_unregister(&core->v4l2_dev);
  949. kfree(core);
  950. }
  951. EXPORT_SYMBOL(cx88_core_put);