cx88-core.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. /*
  2. * $Id: cx88-core.c,v 1.33 2005/07/07 14:17:47 mchehab Exp $
  3. *
  4. * device driver for Conexant 2388x based TV cards
  5. * driver core
  6. *
  7. * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23. #include <linux/init.h>
  24. #include <linux/list.h>
  25. #include <linux/module.h>
  26. #include <linux/moduleparam.h>
  27. #include <linux/kernel.h>
  28. #include <linux/slab.h>
  29. #include <linux/kmod.h>
  30. #include <linux/sound.h>
  31. #include <linux/interrupt.h>
  32. #include <linux/pci.h>
  33. #include <linux/delay.h>
  34. #include <linux/videodev.h>
  35. #include "cx88.h"
  36. MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
  37. MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  38. MODULE_LICENSE("GPL");
  39. /* ------------------------------------------------------------------ */
  40. static unsigned int core_debug = 0;
  41. module_param(core_debug,int,0644);
  42. MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
  43. static unsigned int latency = UNSET;
  44. module_param(latency,int,0444);
  45. MODULE_PARM_DESC(latency,"pci latency timer");
  46. static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
  47. static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
  48. static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
  49. module_param_array(tuner, int, NULL, 0444);
  50. module_param_array(radio, int, NULL, 0444);
  51. module_param_array(card, int, NULL, 0444);
  52. MODULE_PARM_DESC(tuner,"tuner type");
  53. MODULE_PARM_DESC(radio,"radio tuner type");
  54. MODULE_PARM_DESC(card,"card type");
  55. static unsigned int nicam = 0;
  56. module_param(nicam,int,0644);
  57. MODULE_PARM_DESC(nicam,"tv audio is nicam");
  58. static unsigned int nocomb = 0;
  59. module_param(nocomb,int,0644);
  60. MODULE_PARM_DESC(nocomb,"disable comb filter");
  61. #define dprintk(level,fmt, arg...) if (core_debug >= level) \
  62. printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
  63. static unsigned int cx88_devcount;
  64. static LIST_HEAD(cx88_devlist);
  65. static DECLARE_MUTEX(devlist);
  66. /* ------------------------------------------------------------------ */
  67. /* debug help functions */
  68. static const char *v4l1_ioctls[] = {
  69. "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
  70. "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
  71. "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
  72. "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
  73. "SMICROCODE", "GVBIFMT", "SVBIFMT" };
  74. #define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
  75. static const char *v4l2_ioctls[] = {
  76. "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
  77. "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
  78. "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
  79. "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
  80. "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
  81. "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
  82. "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
  83. "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
  84. "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
  85. "S_MODULATOR"
  86. };
  87. #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
  88. void cx88_print_ioctl(char *name, unsigned int cmd)
  89. {
  90. char *dir;
  91. switch (_IOC_DIR(cmd)) {
  92. case _IOC_NONE: dir = "--"; break;
  93. case _IOC_READ: dir = "r-"; break;
  94. case _IOC_WRITE: dir = "-w"; break;
  95. case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
  96. default: dir = "??"; break;
  97. }
  98. switch (_IOC_TYPE(cmd)) {
  99. case 'v':
  100. printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
  101. name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
  102. v4l1_ioctls[_IOC_NR(cmd)] : "???");
  103. break;
  104. case 'V':
  105. printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
  106. name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
  107. v4l2_ioctls[_IOC_NR(cmd)] : "???");
  108. break;
  109. default:
  110. printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
  111. name, cmd, dir, _IOC_NR(cmd));
  112. }
  113. }
  114. /* ------------------------------------------------------------------ */
  115. #define NO_SYNC_LINE (-1U)
  116. static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
  117. unsigned int offset, u32 sync_line,
  118. unsigned int bpl, unsigned int padding,
  119. unsigned int lines)
  120. {
  121. struct scatterlist *sg;
  122. unsigned int line,todo;
  123. /* sync instruction */
  124. if (sync_line != NO_SYNC_LINE)
  125. *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
  126. /* scan lines */
  127. sg = sglist;
  128. for (line = 0; line < lines; line++) {
  129. while (offset && offset >= sg_dma_len(sg)) {
  130. offset -= sg_dma_len(sg);
  131. sg++;
  132. }
  133. if (bpl <= sg_dma_len(sg)-offset) {
  134. /* fits into current chunk */
  135. *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
  136. *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
  137. offset+=bpl;
  138. } else {
  139. /* scanline needs to be splitted */
  140. todo = bpl;
  141. *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
  142. (sg_dma_len(sg)-offset));
  143. *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
  144. todo -= (sg_dma_len(sg)-offset);
  145. offset = 0;
  146. sg++;
  147. while (todo > sg_dma_len(sg)) {
  148. *(rp++)=cpu_to_le32(RISC_WRITE|
  149. sg_dma_len(sg));
  150. *(rp++)=cpu_to_le32(sg_dma_address(sg));
  151. todo -= sg_dma_len(sg);
  152. sg++;
  153. }
  154. *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
  155. *(rp++)=cpu_to_le32(sg_dma_address(sg));
  156. offset += todo;
  157. }
  158. offset += padding;
  159. }
  160. return rp;
  161. }
  162. int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
  163. struct scatterlist *sglist,
  164. unsigned int top_offset, unsigned int bottom_offset,
  165. unsigned int bpl, unsigned int padding, unsigned int lines)
  166. {
  167. u32 instructions,fields;
  168. u32 *rp;
  169. int rc;
  170. fields = 0;
  171. if (UNSET != top_offset)
  172. fields++;
  173. if (UNSET != bottom_offset)
  174. fields++;
  175. /* estimate risc mem: worst case is one write per page border +
  176. one write per scan line + syncs + jump (all 2 dwords) */
  177. instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
  178. instructions += 3 + 4;
  179. if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
  180. return rc;
  181. /* write risc instructions */
  182. rp = risc->cpu;
  183. if (UNSET != top_offset)
  184. rp = cx88_risc_field(rp, sglist, top_offset, 0,
  185. bpl, padding, lines);
  186. if (UNSET != bottom_offset)
  187. rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
  188. bpl, padding, lines);
  189. /* save pointer to jmp instruction address */
  190. risc->jmp = rp;
  191. BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
  192. return 0;
  193. }
  194. int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
  195. struct scatterlist *sglist, unsigned int bpl,
  196. unsigned int lines)
  197. {
  198. u32 instructions;
  199. u32 *rp;
  200. int rc;
  201. /* estimate risc mem: worst case is one write per page border +
  202. one write per scan line + syncs + jump (all 2 dwords) */
  203. instructions = (bpl * lines) / PAGE_SIZE + lines;
  204. instructions += 3 + 4;
  205. if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
  206. return rc;
  207. /* write risc instructions */
  208. rp = risc->cpu;
  209. rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
  210. /* save pointer to jmp instruction address */
  211. risc->jmp = rp;
  212. BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
  213. return 0;
  214. }
  215. int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
  216. u32 reg, u32 mask, u32 value)
  217. {
  218. u32 *rp;
  219. int rc;
  220. if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
  221. return rc;
  222. /* write risc instructions */
  223. rp = risc->cpu;
  224. *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
  225. *(rp++) = cpu_to_le32(reg);
  226. *(rp++) = cpu_to_le32(value);
  227. *(rp++) = cpu_to_le32(mask);
  228. *(rp++) = cpu_to_le32(RISC_JUMP);
  229. *(rp++) = cpu_to_le32(risc->dma);
  230. return 0;
  231. }
  232. void
  233. cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
  234. {
  235. if (in_interrupt())
  236. BUG();
  237. videobuf_waiton(&buf->vb,0,0);
  238. videobuf_dma_pci_unmap(pci, &buf->vb.dma);
  239. videobuf_dma_free(&buf->vb.dma);
  240. btcx_riscmem_free(pci, &buf->risc);
  241. buf->vb.state = STATE_NEEDS_INIT;
  242. }
  243. /* ------------------------------------------------------------------ */
  244. /* our SRAM memory layout */
  245. /* we are going to put all thr risc programs into host memory, so we
  246. * can use the whole SDRAM for the DMA fifos. To simplify things, we
  247. * use a static memory layout. That surely will waste memory in case
  248. * we don't use all DMA channels at the same time (which will be the
  249. * case most of the time). But that still gives us enougth FIFO space
  250. * to be able to deal with insane long pci latencies ...
  251. *
  252. * FIFO space allocations:
  253. * channel 21 (y video) - 10.0k
  254. * channel 22 (u video) - 2.0k
  255. * channel 23 (v video) - 2.0k
  256. * channel 24 (vbi) - 4.0k
  257. * channels 25+26 (audio) - 0.5k
  258. * channel 28 (mpeg) - 4.0k
  259. * TOTAL = 25.5k
  260. *
  261. * Every channel has 160 bytes control data (64 bytes instruction
  262. * queue and 6 CDT entries), which is close to 2k total.
  263. *
  264. * Address layout:
  265. * 0x0000 - 0x03ff CMDs / reserved
  266. * 0x0400 - 0x0bff instruction queues + CDs
  267. * 0x0c00 - FIFOs
  268. */
  269. struct sram_channel cx88_sram_channels[] = {
  270. [SRAM_CH21] = {
  271. .name = "video y / packed",
  272. .cmds_start = 0x180040,
  273. .ctrl_start = 0x180400,
  274. .cdt = 0x180400 + 64,
  275. .fifo_start = 0x180c00,
  276. .fifo_size = 0x002800,
  277. .ptr1_reg = MO_DMA21_PTR1,
  278. .ptr2_reg = MO_DMA21_PTR2,
  279. .cnt1_reg = MO_DMA21_CNT1,
  280. .cnt2_reg = MO_DMA21_CNT2,
  281. },
  282. [SRAM_CH22] = {
  283. .name = "video u",
  284. .cmds_start = 0x180080,
  285. .ctrl_start = 0x1804a0,
  286. .cdt = 0x1804a0 + 64,
  287. .fifo_start = 0x183400,
  288. .fifo_size = 0x000800,
  289. .ptr1_reg = MO_DMA22_PTR1,
  290. .ptr2_reg = MO_DMA22_PTR2,
  291. .cnt1_reg = MO_DMA22_CNT1,
  292. .cnt2_reg = MO_DMA22_CNT2,
  293. },
  294. [SRAM_CH23] = {
  295. .name = "video v",
  296. .cmds_start = 0x1800c0,
  297. .ctrl_start = 0x180540,
  298. .cdt = 0x180540 + 64,
  299. .fifo_start = 0x183c00,
  300. .fifo_size = 0x000800,
  301. .ptr1_reg = MO_DMA23_PTR1,
  302. .ptr2_reg = MO_DMA23_PTR2,
  303. .cnt1_reg = MO_DMA23_CNT1,
  304. .cnt2_reg = MO_DMA23_CNT2,
  305. },
  306. [SRAM_CH24] = {
  307. .name = "vbi",
  308. .cmds_start = 0x180100,
  309. .ctrl_start = 0x1805e0,
  310. .cdt = 0x1805e0 + 64,
  311. .fifo_start = 0x184400,
  312. .fifo_size = 0x001000,
  313. .ptr1_reg = MO_DMA24_PTR1,
  314. .ptr2_reg = MO_DMA24_PTR2,
  315. .cnt1_reg = MO_DMA24_CNT1,
  316. .cnt2_reg = MO_DMA24_CNT2,
  317. },
  318. [SRAM_CH25] = {
  319. .name = "audio from",
  320. .cmds_start = 0x180140,
  321. .ctrl_start = 0x180680,
  322. .cdt = 0x180680 + 64,
  323. .fifo_start = 0x185400,
  324. .fifo_size = 0x000200,
  325. .ptr1_reg = MO_DMA25_PTR1,
  326. .ptr2_reg = MO_DMA25_PTR2,
  327. .cnt1_reg = MO_DMA25_CNT1,
  328. .cnt2_reg = MO_DMA25_CNT2,
  329. },
  330. [SRAM_CH26] = {
  331. .name = "audio to",
  332. .cmds_start = 0x180180,
  333. .ctrl_start = 0x180720,
  334. .cdt = 0x180680 + 64, /* same as audio IN */
  335. .fifo_start = 0x185400, /* same as audio IN */
  336. .fifo_size = 0x000200, /* same as audio IN */
  337. .ptr1_reg = MO_DMA26_PTR1,
  338. .ptr2_reg = MO_DMA26_PTR2,
  339. .cnt1_reg = MO_DMA26_CNT1,
  340. .cnt2_reg = MO_DMA26_CNT2,
  341. },
  342. [SRAM_CH28] = {
  343. .name = "mpeg",
  344. .cmds_start = 0x180200,
  345. .ctrl_start = 0x1807C0,
  346. .cdt = 0x1807C0 + 64,
  347. .fifo_start = 0x185600,
  348. .fifo_size = 0x001000,
  349. .ptr1_reg = MO_DMA28_PTR1,
  350. .ptr2_reg = MO_DMA28_PTR2,
  351. .cnt1_reg = MO_DMA28_CNT1,
  352. .cnt2_reg = MO_DMA28_CNT2,
  353. },
  354. };
  355. int cx88_sram_channel_setup(struct cx88_core *core,
  356. struct sram_channel *ch,
  357. unsigned int bpl, u32 risc)
  358. {
  359. unsigned int i,lines;
  360. u32 cdt;
  361. bpl = (bpl + 7) & ~7; /* alignment */
  362. cdt = ch->cdt;
  363. lines = ch->fifo_size / bpl;
  364. if (lines > 6)
  365. lines = 6;
  366. BUG_ON(lines < 2);
  367. /* write CDT */
  368. for (i = 0; i < lines; i++)
  369. cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
  370. /* write CMDS */
  371. cx_write(ch->cmds_start + 0, risc);
  372. cx_write(ch->cmds_start + 4, cdt);
  373. cx_write(ch->cmds_start + 8, (lines*16) >> 3);
  374. cx_write(ch->cmds_start + 12, ch->ctrl_start);
  375. cx_write(ch->cmds_start + 16, 64 >> 2);
  376. for (i = 20; i < 64; i += 4)
  377. cx_write(ch->cmds_start + i, 0);
  378. /* fill registers */
  379. cx_write(ch->ptr1_reg, ch->fifo_start);
  380. cx_write(ch->ptr2_reg, cdt);
  381. cx_write(ch->cnt1_reg, (bpl >> 3) -1);
  382. cx_write(ch->cnt2_reg, (lines*16) >> 3);
  383. dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
  384. return 0;
  385. }
  386. /* ------------------------------------------------------------------ */
  387. /* debug helper code */
  388. int cx88_risc_decode(u32 risc)
  389. {
  390. static char *instr[16] = {
  391. [ RISC_SYNC >> 28 ] = "sync",
  392. [ RISC_WRITE >> 28 ] = "write",
  393. [ RISC_WRITEC >> 28 ] = "writec",
  394. [ RISC_READ >> 28 ] = "read",
  395. [ RISC_READC >> 28 ] = "readc",
  396. [ RISC_JUMP >> 28 ] = "jump",
  397. [ RISC_SKIP >> 28 ] = "skip",
  398. [ RISC_WRITERM >> 28 ] = "writerm",
  399. [ RISC_WRITECM >> 28 ] = "writecm",
  400. [ RISC_WRITECR >> 28 ] = "writecr",
  401. };
  402. static int incr[16] = {
  403. [ RISC_WRITE >> 28 ] = 2,
  404. [ RISC_JUMP >> 28 ] = 2,
  405. [ RISC_WRITERM >> 28 ] = 3,
  406. [ RISC_WRITECM >> 28 ] = 3,
  407. [ RISC_WRITECR >> 28 ] = 4,
  408. };
  409. static char *bits[] = {
  410. "12", "13", "14", "resync",
  411. "cnt0", "cnt1", "18", "19",
  412. "20", "21", "22", "23",
  413. "irq1", "irq2", "eol", "sol",
  414. };
  415. int i;
  416. printk("0x%08x [ %s", risc,
  417. instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
  418. for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
  419. if (risc & (1 << (i + 12)))
  420. printk(" %s",bits[i]);
  421. printk(" count=%d ]\n", risc & 0xfff);
  422. return incr[risc >> 28] ? incr[risc >> 28] : 1;
  423. }
  424. void cx88_sram_channel_dump(struct cx88_core *core,
  425. struct sram_channel *ch)
  426. {
  427. static char *name[] = {
  428. "initial risc",
  429. "cdt base",
  430. "cdt size",
  431. "iq base",
  432. "iq size",
  433. "risc pc",
  434. "iq wr ptr",
  435. "iq rd ptr",
  436. "cdt current",
  437. "pci target",
  438. "line / byte",
  439. };
  440. u32 risc;
  441. unsigned int i,j,n;
  442. printk("%s: %s - dma channel status dump\n",
  443. core->name,ch->name);
  444. for (i = 0; i < ARRAY_SIZE(name); i++)
  445. printk("%s: cmds: %-12s: 0x%08x\n",
  446. core->name,name[i],
  447. cx_read(ch->cmds_start + 4*i));
  448. for (i = 0; i < 4; i++) {
  449. risc = cx_read(ch->cmds_start + 4 * (i+11));
  450. printk("%s: risc%d: ", core->name, i);
  451. cx88_risc_decode(risc);
  452. }
  453. for (i = 0; i < 16; i += n) {
  454. risc = cx_read(ch->ctrl_start + 4 * i);
  455. printk("%s: iq %x: ", core->name, i);
  456. n = cx88_risc_decode(risc);
  457. for (j = 1; j < n; j++) {
  458. risc = cx_read(ch->ctrl_start + 4 * (i+j));
  459. printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
  460. core->name, i+j, risc, j);
  461. }
  462. }
  463. printk("%s: fifo: 0x%08x -> 0x%x\n",
  464. core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
  465. printk("%s: ctrl: 0x%08x -> 0x%x\n",
  466. core->name, ch->ctrl_start, ch->ctrl_start+6*16);
  467. printk("%s: ptr1_reg: 0x%08x\n",
  468. core->name,cx_read(ch->ptr1_reg));
  469. printk("%s: ptr2_reg: 0x%08x\n",
  470. core->name,cx_read(ch->ptr2_reg));
  471. printk("%s: cnt1_reg: 0x%08x\n",
  472. core->name,cx_read(ch->cnt1_reg));
  473. printk("%s: cnt2_reg: 0x%08x\n",
  474. core->name,cx_read(ch->cnt2_reg));
  475. }
  476. static char *cx88_pci_irqs[32] = {
  477. "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
  478. "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
  479. "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
  480. "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
  481. };
  482. void cx88_print_irqbits(char *name, char *tag, char **strings,
  483. u32 bits, u32 mask)
  484. {
  485. unsigned int i;
  486. printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
  487. for (i = 0; i < 32; i++) {
  488. if (!(bits & (1 << i)))
  489. continue;
  490. if (strings[i])
  491. printk(" %s", strings[i]);
  492. else
  493. printk(" %d", i);
  494. if (!(mask & (1 << i)))
  495. continue;
  496. printk("*");
  497. }
  498. printk("\n");
  499. }
  500. /* ------------------------------------------------------------------ */
  501. int cx88_core_irq(struct cx88_core *core, u32 status)
  502. {
  503. int handled = 0;
  504. if (status & (1<<18)) {
  505. cx88_ir_irq(core);
  506. handled++;
  507. }
  508. if (!handled)
  509. cx88_print_irqbits(core->name, "irq pci",
  510. cx88_pci_irqs, status,
  511. core->pci_irqmask);
  512. return handled;
  513. }
  514. void cx88_wakeup(struct cx88_core *core,
  515. struct cx88_dmaqueue *q, u32 count)
  516. {
  517. struct cx88_buffer *buf;
  518. int bc;
  519. for (bc = 0;; bc++) {
  520. if (list_empty(&q->active))
  521. break;
  522. buf = list_entry(q->active.next,
  523. struct cx88_buffer, vb.queue);
  524. /* count comes from the hw and is is 16bit wide --
  525. * this trick handles wrap-arounds correctly for
  526. * up to 32767 buffers in flight... */
  527. if ((s16) (count - buf->count) < 0)
  528. break;
  529. do_gettimeofday(&buf->vb.ts);
  530. dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
  531. count, buf->count);
  532. buf->vb.state = STATE_DONE;
  533. list_del(&buf->vb.queue);
  534. wake_up(&buf->vb.done);
  535. }
  536. if (list_empty(&q->active)) {
  537. del_timer(&q->timeout);
  538. } else {
  539. mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
  540. }
  541. if (bc != 1)
  542. printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
  543. }
  544. void cx88_shutdown(struct cx88_core *core)
  545. {
  546. /* disable RISC controller + IRQs */
  547. cx_write(MO_DEV_CNTRL2, 0);
  548. /* stop dma transfers */
  549. cx_write(MO_VID_DMACNTRL, 0x0);
  550. cx_write(MO_AUD_DMACNTRL, 0x0);
  551. cx_write(MO_TS_DMACNTRL, 0x0);
  552. cx_write(MO_VIP_DMACNTRL, 0x0);
  553. cx_write(MO_GPHST_DMACNTRL, 0x0);
  554. /* stop interrupts */
  555. cx_write(MO_PCI_INTMSK, 0x0);
  556. cx_write(MO_VID_INTMSK, 0x0);
  557. cx_write(MO_AUD_INTMSK, 0x0);
  558. cx_write(MO_TS_INTMSK, 0x0);
  559. cx_write(MO_VIP_INTMSK, 0x0);
  560. cx_write(MO_GPHST_INTMSK, 0x0);
  561. /* stop capturing */
  562. cx_write(VID_CAPTURE_CONTROL, 0);
  563. }
  564. int cx88_reset(struct cx88_core *core)
  565. {
  566. dprintk(1,"%s\n",__FUNCTION__);
  567. cx88_shutdown(core);
  568. /* clear irq status */
  569. cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
  570. cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
  571. cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
  572. /* wait a bit */
  573. msleep(100);
  574. /* init sram */
  575. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
  576. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
  577. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
  578. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
  579. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
  580. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
  581. cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
  582. /* misc init ... */
  583. cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
  584. (1 << 12) | // agc gain
  585. (1 << 11) | // adaptibe agc
  586. (0 << 10) | // chroma agc
  587. (0 << 9) | // ckillen
  588. (7)));
  589. /* setup image format */
  590. cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
  591. /* setup FIFO Threshholds */
  592. cx_write(MO_PDMA_STHRSH, 0x0807);
  593. cx_write(MO_PDMA_DTHRSH, 0x0807);
  594. /* fixes flashing of image */
  595. cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
  596. cx_write(MO_AGC_BACK_VBI, 0x00E00555);
  597. cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
  598. cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
  599. cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
  600. /* Reset on-board parts */
  601. cx_write(MO_SRST_IO, 0);
  602. msleep(10);
  603. cx_write(MO_SRST_IO, 1);
  604. return 0;
  605. }
  606. /* ------------------------------------------------------------------ */
  607. static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
  608. {
  609. return (norm->id & V4L2_STD_625_50) ? 922 : 754;
  610. }
  611. static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
  612. {
  613. return (norm->id & V4L2_STD_625_50) ? 186 : 135;
  614. }
  615. static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
  616. {
  617. return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
  618. }
  619. static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
  620. {
  621. static const unsigned int ntsc = 28636360;
  622. static const unsigned int pal = 35468950;
  623. static const unsigned int palm = 28604892;
  624. if (norm->id & V4L2_STD_PAL_M)
  625. return palm;
  626. return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
  627. }
  628. static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
  629. {
  630. return (norm->id & V4L2_STD_625_50)
  631. ? HLNotchFilter135PAL
  632. : HLNotchFilter135NTSC;
  633. }
  634. static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
  635. {
  636. /* Should always be Line Draw Time / (4*FSC) */
  637. if (norm->id & V4L2_STD_PAL_M)
  638. return 909;
  639. return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
  640. }
  641. static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
  642. {
  643. return (norm->id & V4L2_STD_625_50) ? 511 : 288;
  644. }
  645. int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
  646. enum v4l2_field field)
  647. {
  648. unsigned int swidth = norm_swidth(core->tvnorm);
  649. unsigned int sheight = norm_maxh(core->tvnorm);
  650. u32 value;
  651. dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
  652. V4L2_FIELD_HAS_TOP(field) ? "T" : "",
  653. V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
  654. core->tvnorm->name);
  655. if (!V4L2_FIELD_HAS_BOTH(field))
  656. height *= 2;
  657. // recalc H delay and scale registers
  658. value = (width * norm_hdelay(core->tvnorm)) / swidth;
  659. value &= 0x3fe;
  660. cx_write(MO_HDELAY_EVEN, value);
  661. cx_write(MO_HDELAY_ODD, value);
  662. dprintk(1,"set_scale: hdelay 0x%04x\n", value);
  663. value = (swidth * 4096 / width) - 4096;
  664. cx_write(MO_HSCALE_EVEN, value);
  665. cx_write(MO_HSCALE_ODD, value);
  666. dprintk(1,"set_scale: hscale 0x%04x\n", value);
  667. cx_write(MO_HACTIVE_EVEN, width);
  668. cx_write(MO_HACTIVE_ODD, width);
  669. dprintk(1,"set_scale: hactive 0x%04x\n", width);
  670. // recalc V scale Register (delay is constant)
  671. cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
  672. cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
  673. dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
  674. value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
  675. cx_write(MO_VSCALE_EVEN, value);
  676. cx_write(MO_VSCALE_ODD, value);
  677. dprintk(1,"set_scale: vscale 0x%04x\n", value);
  678. cx_write(MO_VACTIVE_EVEN, sheight);
  679. cx_write(MO_VACTIVE_ODD, sheight);
  680. dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
  681. // setup filters
  682. value = 0;
  683. value |= (1 << 19); // CFILT (default)
  684. if (core->tvnorm->id & V4L2_STD_SECAM) {
  685. value |= (1 << 15);
  686. value |= (1 << 16);
  687. }
  688. if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
  689. value |= (1 << 13) | (1 << 5);
  690. if (V4L2_FIELD_INTERLACED == field)
  691. value |= (1 << 3); // VINT (interlaced vertical scaling)
  692. if (width < 385)
  693. value |= (1 << 0); // 3-tap interpolation
  694. if (width < 193)
  695. value |= (1 << 1); // 5-tap interpolation
  696. if (nocomb)
  697. value |= (3 << 5); // disable comb filter
  698. cx_write(MO_FILTER_EVEN, value);
  699. cx_write(MO_FILTER_ODD, value);
  700. dprintk(1,"set_scale: filter 0x%04x\n", value);
  701. return 0;
  702. }
  703. static const u32 xtal = 28636363;
  704. static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
  705. {
  706. static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
  707. u64 pll;
  708. u32 reg;
  709. int i;
  710. if (prescale < 2)
  711. prescale = 2;
  712. if (prescale > 5)
  713. prescale = 5;
  714. pll = ofreq * 8 * prescale * (u64)(1 << 20);
  715. do_div(pll,xtal);
  716. reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
  717. if (((reg >> 20) & 0x3f) < 14) {
  718. printk("%s/0: pll out of range\n",core->name);
  719. return -1;
  720. }
  721. dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
  722. reg, cx_read(MO_PLL_REG), ofreq);
  723. cx_write(MO_PLL_REG, reg);
  724. for (i = 0; i < 100; i++) {
  725. reg = cx_read(MO_DEVICE_STATUS);
  726. if (reg & (1<<2)) {
  727. dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
  728. prescale,ofreq);
  729. return 0;
  730. }
  731. dprintk(1,"pll not locked yet, waiting ...\n");
  732. msleep(10);
  733. }
  734. dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
  735. return -1;
  736. }
  737. static int set_tvaudio(struct cx88_core *core)
  738. {
  739. struct cx88_tvnorm *norm = core->tvnorm;
  740. if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
  741. return 0;
  742. if (V4L2_STD_PAL_BG & norm->id) {
  743. core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG;
  744. } else if (V4L2_STD_PAL_DK & norm->id) {
  745. core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK;
  746. } else if (V4L2_STD_PAL_I & norm->id) {
  747. core->tvaudio = WW_NICAM_I;
  748. } else if (V4L2_STD_SECAM_L & norm->id) {
  749. core->tvaudio = WW_SYSTEM_L_AM;
  750. } else if (V4L2_STD_SECAM_DK & norm->id) {
  751. core->tvaudio = WW_A2_DK;
  752. } else if ((V4L2_STD_NTSC_M & norm->id) ||
  753. (V4L2_STD_PAL_M & norm->id)) {
  754. core->tvaudio = WW_BTSC;
  755. } else if (V4L2_STD_NTSC_M_JP & norm->id) {
  756. core->tvaudio = WW_EIAJ;
  757. } else {
  758. printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
  759. core->name, norm->name);
  760. core->tvaudio = 0;
  761. return 0;
  762. }
  763. cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
  764. cx88_set_tvaudio(core);
  765. // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
  766. cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
  767. cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
  768. cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
  769. return 0;
  770. }
  771. int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
  772. {
  773. u32 fsc8;
  774. u32 adc_clock;
  775. u32 vdec_clock;
  776. u32 step_db,step_dr;
  777. u64 tmp64;
  778. u32 bdelay,agcdelay,htotal;
  779. core->tvnorm = norm;
  780. fsc8 = norm_fsc8(norm);
  781. adc_clock = xtal;
  782. vdec_clock = fsc8;
  783. step_db = fsc8;
  784. step_dr = fsc8;
  785. if (norm->id & V4L2_STD_SECAM) {
  786. step_db = 4250000 * 8;
  787. step_dr = 4406250 * 8;
  788. }
  789. dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
  790. norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
  791. set_pll(core,2,vdec_clock);
  792. dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
  793. norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
  794. cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
  795. // FIXME: as-is from DScaler
  796. dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
  797. norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
  798. cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
  799. // MO_SCONV_REG = adc clock / video dec clock * 2^17
  800. tmp64 = adc_clock * (u64)(1 << 17);
  801. do_div(tmp64, vdec_clock);
  802. dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
  803. (u32)tmp64, cx_read(MO_SCONV_REG));
  804. cx_write(MO_SCONV_REG, (u32)tmp64);
  805. // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
  806. tmp64 = step_db * (u64)(1 << 22);
  807. do_div(tmp64, vdec_clock);
  808. dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
  809. (u32)tmp64, cx_read(MO_SUB_STEP));
  810. cx_write(MO_SUB_STEP, (u32)tmp64);
  811. // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
  812. tmp64 = step_dr * (u64)(1 << 22);
  813. do_div(tmp64, vdec_clock);
  814. dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
  815. (u32)tmp64, cx_read(MO_SUB_STEP_DR));
  816. cx_write(MO_SUB_STEP_DR, (u32)tmp64);
  817. // bdelay + agcdelay
  818. bdelay = vdec_clock * 65 / 20000000 + 21;
  819. agcdelay = vdec_clock * 68 / 20000000 + 15;
  820. dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
  821. (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
  822. cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
  823. // htotal
  824. tmp64 = norm_htotal(norm) * (u64)vdec_clock;
  825. do_div(tmp64, fsc8);
  826. htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
  827. dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
  828. htotal, cx_read(MO_HTOTAL), (u32)tmp64);
  829. cx_write(MO_HTOTAL, htotal);
  830. // vbi stuff
  831. cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
  832. norm_vbipack(norm)));
  833. // this is needed as well to set all tvnorm parameter
  834. cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
  835. // audio
  836. set_tvaudio(core);
  837. // tell i2c chips
  838. cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
  839. // done
  840. return 0;
  841. }
  842. /* ------------------------------------------------------------------ */
  843. static int cx88_pci_quirks(char *name, struct pci_dev *pci)
  844. {
  845. unsigned int lat = UNSET;
  846. u8 ctrl = 0;
  847. u8 value;
  848. /* check pci quirks */
  849. if (pci_pci_problems & PCIPCI_TRITON) {
  850. printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
  851. name);
  852. ctrl |= CX88X_EN_TBFX;
  853. }
  854. if (pci_pci_problems & PCIPCI_NATOMA) {
  855. printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
  856. name);
  857. ctrl |= CX88X_EN_TBFX;
  858. }
  859. if (pci_pci_problems & PCIPCI_VIAETBF) {
  860. printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
  861. name);
  862. ctrl |= CX88X_EN_TBFX;
  863. }
  864. if (pci_pci_problems & PCIPCI_VSFX) {
  865. printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
  866. name);
  867. ctrl |= CX88X_EN_VSFX;
  868. }
  869. #ifdef PCIPCI_ALIMAGIK
  870. if (pci_pci_problems & PCIPCI_ALIMAGIK) {
  871. printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
  872. name);
  873. lat = 0x0A;
  874. }
  875. #endif
  876. /* check insmod options */
  877. if (UNSET != latency)
  878. lat = latency;
  879. /* apply stuff */
  880. if (ctrl) {
  881. pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
  882. value |= ctrl;
  883. pci_write_config_byte(pci, CX88X_DEVCTRL, value);
  884. }
  885. if (UNSET != lat) {
  886. printk(KERN_INFO "%s: setting pci latency timer to %d\n",
  887. name, latency);
  888. pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
  889. }
  890. return 0;
  891. }
  892. /* ------------------------------------------------------------------ */
  893. struct video_device *cx88_vdev_init(struct cx88_core *core,
  894. struct pci_dev *pci,
  895. struct video_device *template,
  896. char *type)
  897. {
  898. struct video_device *vfd;
  899. vfd = video_device_alloc();
  900. if (NULL == vfd)
  901. return NULL;
  902. *vfd = *template;
  903. vfd->minor = -1;
  904. vfd->dev = &pci->dev;
  905. vfd->release = video_device_release;
  906. snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
  907. core->name, type, cx88_boards[core->board].name);
  908. return vfd;
  909. }
  910. static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
  911. {
  912. if (request_mem_region(pci_resource_start(pci,0),
  913. pci_resource_len(pci,0),
  914. core->name))
  915. return 0;
  916. printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
  917. core->name,pci_resource_start(pci,0));
  918. return -EBUSY;
  919. }
  920. struct cx88_core* cx88_core_get(struct pci_dev *pci)
  921. {
  922. struct cx88_core *core;
  923. struct list_head *item;
  924. int i;
  925. down(&devlist);
  926. list_for_each(item,&cx88_devlist) {
  927. core = list_entry(item, struct cx88_core, devlist);
  928. if (pci->bus->number != core->pci_bus)
  929. continue;
  930. if (PCI_SLOT(pci->devfn) != core->pci_slot)
  931. continue;
  932. if (0 != get_ressources(core,pci))
  933. goto fail_unlock;
  934. atomic_inc(&core->refcount);
  935. up(&devlist);
  936. return core;
  937. }
  938. core = kmalloc(sizeof(*core),GFP_KERNEL);
  939. if (NULL == core)
  940. goto fail_unlock;
  941. memset(core,0,sizeof(*core));
  942. atomic_inc(&core->refcount);
  943. core->pci_bus = pci->bus->number;
  944. core->pci_slot = PCI_SLOT(pci->devfn);
  945. core->pci_irqmask = 0x00fc00;
  946. core->nr = cx88_devcount++;
  947. sprintf(core->name,"cx88[%d]",core->nr);
  948. if (0 != get_ressources(core,pci)) {
  949. cx88_devcount--;
  950. goto fail_free;
  951. }
  952. list_add_tail(&core->devlist,&cx88_devlist);
  953. /* PCI stuff */
  954. cx88_pci_quirks(core->name, pci);
  955. core->lmmio = ioremap(pci_resource_start(pci,0),
  956. pci_resource_len(pci,0));
  957. core->bmmio = (u8 __iomem *)core->lmmio;
  958. /* board config */
  959. core->board = UNSET;
  960. if (card[core->nr] < cx88_bcount)
  961. core->board = card[core->nr];
  962. for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
  963. if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
  964. pci->subsystem_device == cx88_subids[i].subdevice)
  965. core->board = cx88_subids[i].card;
  966. if (UNSET == core->board) {
  967. core->board = CX88_BOARD_UNKNOWN;
  968. cx88_card_list(core,pci);
  969. }
  970. printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
  971. core->name,pci->subsystem_vendor,
  972. pci->subsystem_device,cx88_boards[core->board].name,
  973. core->board, card[core->nr] == core->board ?
  974. "insmod option" : "autodetected");
  975. core->tuner_type = tuner[core->nr];
  976. core->radio_type = radio[core->nr];
  977. if (UNSET == core->tuner_type)
  978. core->tuner_type = cx88_boards[core->board].tuner_type;
  979. if (UNSET == core->radio_type)
  980. core->radio_type = cx88_boards[core->board].radio_type;
  981. if (!core->tuner_addr)
  982. core->tuner_addr = cx88_boards[core->board].tuner_addr;
  983. if (!core->radio_addr)
  984. core->radio_addr = cx88_boards[core->board].radio_addr;
  985. printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
  986. core->tuner_type, core->tuner_addr<<1,
  987. core->radio_type, core->radio_addr<<1);
  988. core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
  989. /* init hardware */
  990. cx88_reset(core);
  991. cx88_i2c_init(core,pci);
  992. cx88_card_setup(core);
  993. cx88_ir_init(core,pci);
  994. up(&devlist);
  995. return core;
  996. fail_free:
  997. kfree(core);
  998. fail_unlock:
  999. up(&devlist);
  1000. return NULL;
  1001. }
  1002. void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
  1003. {
  1004. release_mem_region(pci_resource_start(pci,0),
  1005. pci_resource_len(pci,0));
  1006. if (!atomic_dec_and_test(&core->refcount))
  1007. return;
  1008. down(&devlist);
  1009. cx88_ir_fini(core);
  1010. if (0 == core->i2c_rc)
  1011. i2c_bit_del_bus(&core->i2c_adap);
  1012. list_del(&core->devlist);
  1013. iounmap(core->lmmio);
  1014. cx88_devcount--;
  1015. up(&devlist);
  1016. kfree(core);
  1017. }
  1018. /* ------------------------------------------------------------------ */
  1019. EXPORT_SYMBOL(cx88_print_ioctl);
  1020. EXPORT_SYMBOL(cx88_print_irqbits);
  1021. EXPORT_SYMBOL(cx88_core_irq);
  1022. EXPORT_SYMBOL(cx88_wakeup);
  1023. EXPORT_SYMBOL(cx88_reset);
  1024. EXPORT_SYMBOL(cx88_shutdown);
  1025. EXPORT_SYMBOL(cx88_risc_buffer);
  1026. EXPORT_SYMBOL(cx88_risc_databuffer);
  1027. EXPORT_SYMBOL(cx88_risc_stopper);
  1028. EXPORT_SYMBOL(cx88_free_buffer);
  1029. EXPORT_SYMBOL(cx88_sram_channels);
  1030. EXPORT_SYMBOL(cx88_sram_channel_setup);
  1031. EXPORT_SYMBOL(cx88_sram_channel_dump);
  1032. EXPORT_SYMBOL(cx88_set_tvnorm);
  1033. EXPORT_SYMBOL(cx88_set_scale);
  1034. EXPORT_SYMBOL(cx88_vdev_init);
  1035. EXPORT_SYMBOL(cx88_core_get);
  1036. EXPORT_SYMBOL(cx88_core_put);
  1037. /*
  1038. * Local variables:
  1039. * c-basic-offset: 8
  1040. * End:
  1041. */