trix.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * sound/trix.c
  3.  *
  4.  * Low level driver for the MediaTrix AudioTrix Pro
  5.  * (MT-0002-PC Control Chip)
  6.  *
  7.  *
  8.  * Copyright (C) by Hannu Savolainen 1993-1997
  9.  *
  10.  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  11.  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  12.  * for more info.
  13.  *
  14.  * Changes
  15.  * Alan Cox Modularisation, cleanup.
  16.  * Christoph Hellwig Adapted to module_init/module_exit
  17.  * Arnaldo C. de Melo Got rid of attach_uart401
  18.  */
  19.  
  20. #include <linux/init.h>
  21. #include <linux/module.h>
  22. #include "sound_config.h"
  23. #include "sb.h"
  24. #include "sound_firmware.h"
  25. #include "ad1848.h"
  26. #include "mpu401.h"
  27. #include "trix_boot.h"
  28. static int kilroy_was_here = 0; /* Don't detect twice */
  29. static int sb_initialized = 0;
  30. static int mpu_initialized = 0;
  31. static int *trix_osp = NULL;
  32. static int mpu = 0;
  33. static int joystick=0;
  34. static unsigned char trix_read(int addr)
  35. {
  36. outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */
  37. return inb(0x391); /* MT-0002-PC ASIC data */
  38. }
  39. static void trix_write(int addr, int data)
  40. {
  41. outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */
  42. outb(((unsigned char) data), 0x391); /* MT-0002-PC ASIC data */
  43. }
  44. static void download_boot(int base)
  45. {
  46. int i = 0, n = trix_boot_len;
  47. if (trix_boot_len == 0)
  48. return;
  49. trix_write(0xf8, 0x00); /* ??????? */
  50. outb((0x01), base + 6); /* Clear the internal data pointer */
  51. outb((0x00), base + 6); /* Restart */
  52. /*
  53.    *  Write the boot code to the RAM upload/download register.
  54.    *  Each write increments the internal data pointer.
  55.  */
  56. outb((0x01), base + 6); /* Clear the internal data pointer */
  57. outb((0x1A), 0x390); /* Select RAM download/upload port */
  58. for (i = 0; i < n; i++)
  59. outb((trix_boot[i]), 0x391);
  60. for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */
  61. outb((0x00), 0x391);
  62. outb((0x00), base + 6); /* Reset */
  63. outb((0x50), 0x390); /* ?????? */
  64. }
  65. static int trix_set_wss_port(struct address_info *hw_config)
  66. {
  67. unsigned char   addr_bits;
  68. if (check_region(0x390, 2))
  69. {
  70. printk(KERN_ERR "AudioTrix: Config port I/O conflictn");
  71. return 0;
  72. }
  73. if (kilroy_was_here) /* Already initialized */
  74. return 0;
  75. if (trix_read(0x15) != 0x71) /* No ASIC signature */
  76. {
  77. MDB(printk(KERN_ERR "No AudioTrix ASIC signature foundn"));
  78. return 0;
  79. }
  80. kilroy_was_here = 1;
  81. /*
  82.  * Reset some registers.
  83.  */
  84. trix_write(0x13, 0);
  85. trix_write(0x14, 0);
  86. /*
  87.  * Configure the ASIC to place the codec to the proper I/O location
  88.  */
  89. switch (hw_config->io_base)
  90. {
  91. case 0x530:
  92. addr_bits = 0;
  93. break;
  94. case 0x604:
  95. addr_bits = 1;
  96. break;
  97. case 0xE80:
  98. addr_bits = 2;
  99. break;
  100. case 0xF40:
  101. addr_bits = 3;
  102. break;
  103. default:
  104. return 0;
  105. }
  106. trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits);
  107. return 1;
  108. }
  109. /*
  110.  *    Probe and attach routines for the Windows Sound System mode of
  111.  *      AudioTrix Pro
  112.  */
  113. static int __init probe_trix_wss(struct address_info *hw_config)
  114. {
  115. int ret;
  116. /*
  117.  * Check if the IO port returns valid signature. The original MS Sound
  118.  * system returns 0x04 while some cards (AudioTrix Pro for example)
  119.  * return 0x00.
  120.  */
  121. if (check_region(hw_config->io_base, 8))
  122. {
  123. printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)n", hw_config->io_base);
  124. return 0;
  125. }
  126. trix_osp = hw_config->osp;
  127. if (!trix_set_wss_port(hw_config))
  128. return 0;
  129. if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00)
  130. {
  131. MDB(printk(KERN_ERR "No MSS signature detected on port 0x%xn", hw_config->io_base));
  132. return 0;
  133. }
  134. if (hw_config->irq > 11)
  135. {
  136. printk(KERN_ERR "AudioTrix: Bad WSS IRQ %dn", hw_config->irq);
  137. return 0;
  138. }
  139. if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
  140. {
  141. printk(KERN_ERR "AudioTrix: Bad WSS DMA %dn", hw_config->dma);
  142. return 0;
  143. }
  144. if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
  145. if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
  146. {
  147.   printk(KERN_ERR "AudioTrix: Bad capture DMA %dn", hw_config->dma2);
  148.   return 0;
  149. }
  150. /*
  151.  * Check that DMA0 is not in use with a 8 bit board.
  152.  */
  153. if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
  154. {
  155. printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slotn");
  156. return 0;
  157. }
  158. if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
  159. {
  160. printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slotn", hw_config->irq);
  161. return 0;
  162. }
  163. ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
  164. if (ret)
  165. {
  166. if(joystick==1)
  167. trix_write(0x15, 0x80);
  168. request_region(0x390, 2, "AudioTrix");
  169. }
  170. return ret;
  171. }
  172. static void __init attach_trix_wss(struct address_info *hw_config)
  173. {
  174. static unsigned char interrupt_bits[12] = {
  175. 0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20
  176. };
  177. char bits;
  178. static unsigned char dma_bits[4] = {
  179. 1, 2, 0, 3
  180. };
  181. int config_port = hw_config->io_base + 0;
  182. int dma1 = hw_config->dma, dma2 = hw_config->dma2;
  183. int old_num_mixers = num_mixers;
  184. trix_osp = hw_config->osp;
  185. if (!kilroy_was_here)
  186. {
  187. DDB(printk("AudioTrix: Attach called but not probed yet???n"));
  188. return;
  189. }
  190. /*
  191.  * Set the IRQ and DMA addresses.
  192.  */
  193. bits = interrupt_bits[hw_config->irq];
  194. if (bits == 0)
  195. {
  196. printk("AudioTrix: Bad IRQ (%d)n", hw_config->irq);
  197. return;
  198. }
  199. outb((bits | 0x40), config_port);
  200. if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
  201. {
  202.   bits |= dma_bits[dma1];
  203.   dma2 = dma1;
  204. }
  205. else
  206. {
  207. unsigned char tmp;
  208. tmp = trix_read(0x13) & ~30;
  209. trix_write(0x13, tmp | 0x80 | (dma1 << 4));
  210. tmp = trix_read(0x14) & ~30;
  211. trix_write(0x14, tmp | 0x80 | (dma2 << 4));
  212. }
  213. outb((bits), config_port); /* Write IRQ+DMA setup */
  214. hw_config->slots[0] = ad1848_init("AudioTrix Pro", hw_config->io_base + 4,
  215.   hw_config->irq,
  216.   dma1,
  217.   dma2,
  218.   0,
  219.   hw_config->osp,
  220.   THIS_MODULE);
  221. request_region(hw_config->io_base, 4, "MSS config");
  222. if (num_mixers > old_num_mixers) /* Mixer got installed */
  223. {
  224. AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); /* Line in */
  225. AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
  226. AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* OPL4 */
  227. AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM); /* SB */
  228. }
  229. }
  230. static int __init probe_trix_sb(struct address_info *hw_config)
  231. {
  232. int tmp;
  233. unsigned char conf;
  234. static signed char irq_translate[] = {
  235. -1, -1, -1, 0, 1, 2, -1, 3
  236. };
  237. if (trix_boot_len == 0)
  238. return 0; /* No boot code -> no fun */
  239. if (!kilroy_was_here)
  240. return 0; /* AudioTrix Pro has not been detected earlier */
  241. if (sb_initialized)
  242. return 0;
  243. if (check_region(hw_config->io_base, 16))
  244. {
  245. printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)n", hw_config->io_base);
  246. return 0;
  247. }
  248. if ((hw_config->io_base & 0xffffff8f) != 0x200)
  249. return 0;
  250. tmp = hw_config->irq;
  251. if (tmp > 7)
  252. return 0;
  253. if (irq_translate[tmp] == -1)
  254. return 0;
  255. tmp = hw_config->dma;
  256. if (tmp != 1 && tmp != 3)
  257. return 0;
  258. conf = 0x84; /* DMA and IRQ enable */
  259. conf |= hw_config->io_base & 0x70; /* I/O address bits */
  260. conf |= irq_translate[hw_config->irq];
  261. if (hw_config->dma == 3)
  262. conf |= 0x08;
  263. trix_write(0x1b, conf);
  264. download_boot(hw_config->io_base);
  265. sb_initialized = 1;
  266. hw_config->name = "AudioTrix SB";
  267. return sb_dsp_detect(hw_config, 0, 0, NULL);
  268. }
  269. static void __init attach_trix_sb(struct address_info *hw_config)
  270. {
  271. extern int sb_be_quiet;
  272. int old_quiet;
  273. hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
  274. /* Prevent false alarms */
  275. old_quiet = sb_be_quiet;
  276. sb_be_quiet = 1;
  277. sb_dsp_init(hw_config, THIS_MODULE);
  278. sb_be_quiet = old_quiet;
  279. }
  280. static int __init probe_trix_mpu(struct address_info *hw_config)
  281. {
  282. unsigned char conf;
  283. static int irq_bits[] = {
  284. -1, -1, -1, 1, 2, 3, -1, 4, -1, 5
  285. };
  286. if (!kilroy_was_here)
  287. {
  288. DDB(printk("Trix: WSS and SB modes must be initialized before MPUn"));
  289. return 0; /* AudioTrix Pro has not been detected earlier */
  290. }
  291. if (!sb_initialized)
  292. {
  293. DDB(printk("Trix: SB mode must be initialized before MPUn"));
  294. return 0;
  295. }
  296. if (mpu_initialized)
  297. {
  298. DDB(printk("Trix: MPU mode already initializedn"));
  299. return 0;
  300. }
  301. if (hw_config->irq > 9)
  302. {
  303. printk(KERN_ERR "AudioTrix: Bad MPU IRQ %dn", hw_config->irq);
  304. return 0;
  305. }
  306. if (irq_bits[hw_config->irq] == -1)
  307. {
  308. printk(KERN_ERR "AudioTrix: Bad MPU IRQ %dn", hw_config->irq);
  309. return 0;
  310. }
  311. switch (hw_config->io_base)
  312. {
  313. case 0x330:
  314. conf = 0x00;
  315. break;
  316. case 0x370:
  317. conf = 0x04;
  318. break;
  319. case 0x3b0:
  320. conf = 0x08;
  321. break;
  322. case 0x3f0:
  323. conf = 0x0c;
  324. break;
  325. default:
  326. return 0; /* Invalid port */
  327. }
  328. conf |= irq_bits[hw_config->irq] << 4;
  329. trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
  330. mpu_initialized = 1;
  331. hw_config->name = "AudioTrix Pro";
  332. return probe_uart401(hw_config, THIS_MODULE);
  333. }
  334. static void __exit unload_trix_wss(struct address_info *hw_config)
  335. {
  336. int dma2 = hw_config->dma2;
  337. if (dma2 == -1)
  338. dma2 = hw_config->dma;
  339. release_region(0x390, 2);
  340. release_region(hw_config->io_base, 4);
  341. ad1848_unload(hw_config->io_base + 4,
  342.       hw_config->irq,
  343.       hw_config->dma,
  344.       dma2,
  345.       0);
  346. sound_unload_audiodev(hw_config->slots[0]);
  347. }
  348. static inline void __exit unload_trix_mpu(struct address_info *hw_config)
  349. {
  350. unload_uart401(hw_config);
  351. }
  352. static inline void __exit unload_trix_sb(struct address_info *hw_config)
  353. {
  354. sb_dsp_unload(hw_config, mpu);
  355. }
  356. static struct address_info cfg;
  357. static struct address_info cfg2;
  358. static struct address_info cfg_mpu;
  359. static int sb = 0;
  360. static int fw_load;
  361. static int __initdata io = -1;
  362. static int __initdata irq = -1;
  363. static int __initdata dma = -1;
  364. static int __initdata dma2 = -1; /* Set this for modules that need it */
  365. static int __initdata sb_io = -1;
  366. static int __initdata sb_dma = -1;
  367. static int __initdata sb_irq = -1;
  368. static int __initdata mpu_io = -1;
  369. static int __initdata mpu_irq = -1;
  370. MODULE_PARM(io,"i");
  371. MODULE_PARM(irq,"i");
  372. MODULE_PARM(dma,"i");
  373. MODULE_PARM(dma2,"i");
  374. MODULE_PARM(sb_io,"i");
  375. MODULE_PARM(sb_dma,"i");
  376. MODULE_PARM(sb_irq,"i");
  377. MODULE_PARM(mpu_io,"i");
  378. MODULE_PARM(mpu_irq,"i");
  379. MODULE_PARM(joystick, "i");
  380. static int __init init_trix(void)
  381. {
  382. printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996n");
  383. cfg.io_base = io;
  384. cfg.irq = irq;
  385. cfg.dma = dma;
  386. cfg.dma2 = dma2;
  387. cfg2.io_base = sb_io;
  388. cfg2.irq = sb_irq;
  389. cfg2.dma = sb_dma;
  390. cfg_mpu.io_base = mpu_io;
  391. cfg_mpu.irq = mpu_irq;
  392. if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
  393. printk(KERN_INFO "I/O, IRQ, DMA and type are mandatoryn");
  394. return -EINVAL;
  395. }
  396. if (cfg2.io_base != -1 && (cfg2.irq == -1 || cfg2.dma == -1)) {
  397. printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.n");
  398. return -EINVAL;
  399. }
  400. if (cfg_mpu.io_base != -1 && cfg_mpu.irq == -1) {
  401. printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.n");
  402. return -EINVAL;
  403. }
  404. if (!trix_boot)
  405. {
  406. fw_load = 1;
  407. trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
  408.     (char **) &trix_boot);
  409. }
  410. if (!probe_trix_wss(&cfg))
  411. return -ENODEV;
  412. attach_trix_wss(&cfg);
  413. /*
  414.  *    We must attach in the right order to get the firmware
  415.  *      loaded up in time.
  416.  */
  417. if (cfg2.io_base != -1) {
  418. sb = probe_trix_sb(&cfg2);
  419. if (sb)
  420. attach_trix_sb(&cfg2);
  421. }
  422. if (cfg_mpu.io_base != -1)
  423. mpu = probe_trix_mpu(&cfg_mpu);
  424. return 0;
  425. }
  426. static void __exit cleanup_trix(void)
  427. {
  428. if (fw_load && trix_boot)
  429. vfree(trix_boot);
  430. if (sb)
  431. unload_trix_sb(&cfg2);
  432. if (mpu)
  433. unload_trix_mpu(&cfg_mpu);
  434. unload_trix_wss(&cfg);
  435. }
  436. module_init(init_trix);
  437. module_exit(cleanup_trix);
  438. #ifndef MODULE
  439. static int __init setup_trix (char *str)
  440. {
  441. /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, mpu_io, mpu_irq */
  442. int ints[9];
  443. str = get_options(str, ARRAY_SIZE(ints), ints);
  444. io = ints[1];
  445. irq = ints[2];
  446. dma = ints[3];
  447. dma2 = ints[4];
  448. sb_io = ints[5];
  449. sb_irq = ints[6];
  450. sb_dma = ints[6];
  451. mpu_io = ints[7];
  452. mpu_irq = ints[8];
  453. return 1;
  454. }
  455. __setup("trix=", setup_trix);
  456. #endif
  457. MODULE_LICENSE("GPL");