msnd_pinnacle.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*********************************************************************
  3. *
  4. * Linux multisound pinnacle/fiji driver for ALSA.
  5. *
  6. * 2002/06/30 Karsten Wiese:
  7. * for now this is only used to build a pinnacle / fiji driver.
  8. * the OSS parent of this code is designed to also support
  9. * the multisound classic via the file msnd_classic.c.
  10. * to make it easier for some brave heart to implemt classic
  11. * support in alsa, i left all the MSND_CLASSIC tokens in this file.
  12. * but for now this untested & undone.
  13. *
  14. * ripped from linux kernel 2.4.18 by Karsten Wiese.
  15. *
  16. * the following is a copy of the 2.4.18 OSS FREE file-heading comment:
  17. *
  18. * Turtle Beach MultiSound Sound Card Driver for Linux
  19. * msnd_pinnacle.c / msnd_classic.c
  20. *
  21. * -- If MSND_CLASSIC is defined:
  22. *
  23. * -> driver for Turtle Beach Classic/Monterey/Tahiti
  24. *
  25. * -- Else
  26. *
  27. * -> driver for Turtle Beach Pinnacle/Fiji
  28. *
  29. * 12-3-2000 Modified IO port validation Steve Sycamore
  30. *
  31. * Copyright (C) 1998 Andrew Veliath
  32. *
  33. ********************************************************************/
  34. #include <linux/kernel.h>
  35. #include <linux/module.h>
  36. #include <linux/interrupt.h>
  37. #include <linux/types.h>
  38. #include <linux/delay.h>
  39. #include <linux/ioport.h>
  40. #include <linux/firmware.h>
  41. #include <linux/isa.h>
  42. #include <linux/isapnp.h>
  43. #include <linux/irq.h>
  44. #include <linux/io.h>
  45. #include <sound/core.h>
  46. #include <sound/initval.h>
  47. #include <sound/asound.h>
  48. #include <sound/pcm.h>
  49. #include <sound/mpu401.h>
  50. #ifdef MSND_CLASSIC
  51. # ifndef __alpha__
  52. # define SLOWIO
  53. # endif
  54. #endif
  55. #include "msnd.h"
  56. #ifdef MSND_CLASSIC
  57. # include "msnd_classic.h"
  58. # define LOGNAME "msnd_classic"
  59. # define DEV_NAME "msnd-classic"
  60. #else
  61. # include "msnd_pinnacle.h"
  62. # define LOGNAME "snd_msnd_pinnacle"
  63. # define DEV_NAME "msnd-pinnacle"
  64. #endif
  65. static void set_default_audio_parameters(struct snd_msnd *chip)
  66. {
  67. chip->play_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
  68. chip->play_sample_rate = DEFSAMPLERATE;
  69. chip->play_channels = DEFCHANNELS;
  70. chip->capture_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
  71. chip->capture_sample_rate = DEFSAMPLERATE;
  72. chip->capture_channels = DEFCHANNELS;
  73. }
  74. static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage)
  75. {
  76. switch (HIBYTE(wMessage)) {
  77. case HIMT_PLAY_DONE: {
  78. if (chip->banksPlayed < 3)
  79. dev_dbg(chip->card->dev, "%08X: HIMT_PLAY_DONE: %i\n",
  80. (unsigned)jiffies, LOBYTE(wMessage));
  81. if (chip->last_playbank == LOBYTE(wMessage)) {
  82. dev_dbg(chip->card->dev,
  83. "chip.last_playbank == LOBYTE(wMessage)\n");
  84. break;
  85. }
  86. chip->banksPlayed++;
  87. if (test_bit(F_WRITING, &chip->flags))
  88. snd_msnd_DAPQ(chip, 0);
  89. chip->last_playbank = LOBYTE(wMessage);
  90. chip->playDMAPos += chip->play_period_bytes;
  91. if (chip->playDMAPos > chip->playLimit)
  92. chip->playDMAPos = 0;
  93. snd_pcm_period_elapsed(chip->playback_substream);
  94. break;
  95. }
  96. case HIMT_RECORD_DONE:
  97. if (chip->last_recbank == LOBYTE(wMessage))
  98. break;
  99. chip->last_recbank = LOBYTE(wMessage);
  100. chip->captureDMAPos += chip->capturePeriodBytes;
  101. if (chip->captureDMAPos > (chip->captureLimit))
  102. chip->captureDMAPos = 0;
  103. if (test_bit(F_READING, &chip->flags))
  104. snd_msnd_DARQ(chip, chip->last_recbank);
  105. snd_pcm_period_elapsed(chip->capture_substream);
  106. break;
  107. case HIMT_DSP:
  108. switch (LOBYTE(wMessage)) {
  109. #ifndef MSND_CLASSIC
  110. case HIDSP_PLAY_UNDER:
  111. #endif
  112. case HIDSP_INT_PLAY_UNDER:
  113. dev_dbg(chip->card->dev,
  114. LOGNAME ": Play underflow %i\n",
  115. chip->banksPlayed);
  116. if (chip->banksPlayed > 2)
  117. clear_bit(F_WRITING, &chip->flags);
  118. break;
  119. case HIDSP_INT_RECORD_OVER:
  120. dev_dbg(chip->card->dev, LOGNAME ": Record overflow\n");
  121. clear_bit(F_READING, &chip->flags);
  122. break;
  123. default:
  124. dev_dbg(chip->card->dev, LOGNAME
  125. ": DSP message %d 0x%02x\n",
  126. LOBYTE(wMessage), LOBYTE(wMessage));
  127. break;
  128. }
  129. break;
  130. case HIMT_MIDI_IN_UCHAR:
  131. if (chip->msndmidi_mpu)
  132. snd_msndmidi_input_read(chip->msndmidi_mpu);
  133. break;
  134. default:
  135. dev_dbg(chip->card->dev, LOGNAME ": HIMT message %d 0x%02x\n",
  136. HIBYTE(wMessage), HIBYTE(wMessage));
  137. break;
  138. }
  139. }
  140. static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id)
  141. {
  142. struct snd_msnd *chip = dev_id;
  143. void __iomem *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
  144. u16 head, tail, size;
  145. /* Send ack to DSP */
  146. /* inb(chip->io + HP_RXL); */
  147. /* Evaluate queued DSP messages */
  148. head = readw(chip->DSPQ + JQS_wHead);
  149. tail = readw(chip->DSPQ + JQS_wTail);
  150. size = readw(chip->DSPQ + JQS_wSize);
  151. if (head > size || tail > size)
  152. goto out;
  153. while (head != tail) {
  154. snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head));
  155. if (++head > size)
  156. head = 0;
  157. writew(head, chip->DSPQ + JQS_wHead);
  158. }
  159. out:
  160. /* Send ack to DSP */
  161. inb(chip->io + HP_RXL);
  162. return IRQ_HANDLED;
  163. }
  164. static int snd_msnd_reset_dsp(struct snd_msnd *chip, unsigned char *info)
  165. {
  166. long io = chip->io;
  167. int timeout = 100;
  168. outb(HPDSPRESET_ON, io + HP_DSPR);
  169. msleep(1);
  170. #ifndef MSND_CLASSIC
  171. if (info)
  172. *info = inb(io + HP_INFO);
  173. #endif
  174. outb(HPDSPRESET_OFF, io + HP_DSPR);
  175. msleep(1);
  176. while (timeout-- > 0) {
  177. if (inb(io + HP_CVR) == HP_CVR_DEF)
  178. return 0;
  179. msleep(1);
  180. }
  181. dev_err(chip->card->dev, LOGNAME ": Cannot reset DSP\n");
  182. return -EIO;
  183. }
  184. static int snd_msnd_probe(struct snd_card *card)
  185. {
  186. struct snd_msnd *chip = card->private_data;
  187. unsigned char info;
  188. #ifndef MSND_CLASSIC
  189. char *xv, *rev = NULL;
  190. char *pin = "TB Pinnacle", *fiji = "TB Fiji";
  191. char *pinfiji = "TB Pinnacle/Fiji";
  192. #endif
  193. if (!request_region(chip->io, DSP_NUMIO, "probing")) {
  194. dev_err(card->dev, LOGNAME ": I/O port conflict\n");
  195. return -ENODEV;
  196. }
  197. if (snd_msnd_reset_dsp(chip, &info) < 0) {
  198. release_region(chip->io, DSP_NUMIO);
  199. return -ENODEV;
  200. }
  201. #ifdef MSND_CLASSIC
  202. strcpy(card->shortname, "Classic/Tahiti/Monterey");
  203. strcpy(card->longname, "Turtle Beach Multisound");
  204. dev_info(card->dev, LOGNAME ": %s, "
  205. "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
  206. card->shortname,
  207. chip->io, chip->io + DSP_NUMIO - 1,
  208. chip->irq,
  209. chip->base, chip->base + 0x7fff);
  210. #else
  211. switch (info >> 4) {
  212. case 0xf:
  213. xv = "<= 1.15";
  214. break;
  215. case 0x1:
  216. xv = "1.18/1.2";
  217. break;
  218. case 0x2:
  219. xv = "1.3";
  220. break;
  221. case 0x3:
  222. xv = "1.4";
  223. break;
  224. default:
  225. xv = "unknown";
  226. break;
  227. }
  228. switch (info & 0x7) {
  229. case 0x0:
  230. rev = "I";
  231. strcpy(card->shortname, pin);
  232. break;
  233. case 0x1:
  234. rev = "F";
  235. strcpy(card->shortname, pin);
  236. break;
  237. case 0x2:
  238. rev = "G";
  239. strcpy(card->shortname, pin);
  240. break;
  241. case 0x3:
  242. rev = "H";
  243. strcpy(card->shortname, pin);
  244. break;
  245. case 0x4:
  246. rev = "E";
  247. strcpy(card->shortname, fiji);
  248. break;
  249. case 0x5:
  250. rev = "C";
  251. strcpy(card->shortname, fiji);
  252. break;
  253. case 0x6:
  254. rev = "D";
  255. strcpy(card->shortname, fiji);
  256. break;
  257. case 0x7:
  258. rev = "A-B (Fiji) or A-E (Pinnacle)";
  259. strcpy(card->shortname, pinfiji);
  260. break;
  261. }
  262. strcpy(card->longname, "Turtle Beach Multisound Pinnacle");
  263. dev_info(card->dev, LOGNAME ": %s revision %s, Xilinx version %s, "
  264. "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
  265. card->shortname,
  266. rev, xv,
  267. chip->io, chip->io + DSP_NUMIO - 1,
  268. chip->irq,
  269. chip->base, chip->base + 0x7fff);
  270. #endif
  271. release_region(chip->io, DSP_NUMIO);
  272. return 0;
  273. }
  274. static int snd_msnd_init_sma(struct snd_msnd *chip)
  275. {
  276. static int initted;
  277. u16 mastVolLeft, mastVolRight;
  278. unsigned long flags;
  279. #ifdef MSND_CLASSIC
  280. outb(chip->memid, chip->io + HP_MEMM);
  281. #endif
  282. outb(HPBLKSEL_0, chip->io + HP_BLKS);
  283. /* Motorola 56k shared memory base */
  284. chip->SMA = chip->mappedbase + SMA_STRUCT_START;
  285. if (initted) {
  286. mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft);
  287. mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight);
  288. } else
  289. mastVolLeft = mastVolRight = 0;
  290. memset_io(chip->mappedbase, 0, 0x8000);
  291. /* Critical section: bank 1 access */
  292. spin_lock_irqsave(&chip->lock, flags);
  293. outb(HPBLKSEL_1, chip->io + HP_BLKS);
  294. memset_io(chip->mappedbase, 0, 0x8000);
  295. outb(HPBLKSEL_0, chip->io + HP_BLKS);
  296. spin_unlock_irqrestore(&chip->lock, flags);
  297. /* Digital audio play queue */
  298. chip->DAPQ = chip->mappedbase + DAPQ_OFFSET;
  299. snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE);
  300. /* Digital audio record queue */
  301. chip->DARQ = chip->mappedbase + DARQ_OFFSET;
  302. snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE);
  303. /* MIDI out queue */
  304. chip->MODQ = chip->mappedbase + MODQ_OFFSET;
  305. snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE);
  306. /* MIDI in queue */
  307. chip->MIDQ = chip->mappedbase + MIDQ_OFFSET;
  308. snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE);
  309. /* DSP -> host message queue */
  310. chip->DSPQ = chip->mappedbase + DSPQ_OFFSET;
  311. snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE);
  312. /* Setup some DSP values */
  313. #ifndef MSND_CLASSIC
  314. writew(1, chip->SMA + SMA_wCurrPlayFormat);
  315. writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize);
  316. writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels);
  317. writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate);
  318. #endif
  319. writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD);
  320. writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft);
  321. writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight);
  322. #ifndef MSND_CLASSIC
  323. writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch);
  324. writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate);
  325. #endif
  326. writew(0x303, chip->SMA + SMA_wCurrInputTagBits);
  327. initted = 1;
  328. return 0;
  329. }
  330. static int upload_dsp_code(struct snd_card *card)
  331. {
  332. struct snd_msnd *chip = card->private_data;
  333. const struct firmware *init_fw = NULL, *perm_fw = NULL;
  334. int err;
  335. outb(HPBLKSEL_0, chip->io + HP_BLKS);
  336. err = request_firmware(&init_fw, INITCODEFILE, card->dev);
  337. if (err < 0) {
  338. dev_err(card->dev, LOGNAME ": Error loading " INITCODEFILE);
  339. goto cleanup1;
  340. }
  341. err = request_firmware(&perm_fw, PERMCODEFILE, card->dev);
  342. if (err < 0) {
  343. dev_err(card->dev, LOGNAME ": Error loading " PERMCODEFILE);
  344. goto cleanup;
  345. }
  346. memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size);
  347. if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) {
  348. dev_warn(card->dev, LOGNAME ": Error uploading to DSP\n");
  349. err = -ENODEV;
  350. goto cleanup;
  351. }
  352. dev_info(card->dev, LOGNAME ": DSP firmware uploaded\n");
  353. err = 0;
  354. cleanup:
  355. release_firmware(perm_fw);
  356. cleanup1:
  357. release_firmware(init_fw);
  358. return err;
  359. }
  360. #ifdef MSND_CLASSIC
  361. static void reset_proteus(struct snd_msnd *chip)
  362. {
  363. outb(HPPRORESET_ON, chip->io + HP_PROR);
  364. msleep(TIME_PRO_RESET);
  365. outb(HPPRORESET_OFF, chip->io + HP_PROR);
  366. msleep(TIME_PRO_RESET_DONE);
  367. }
  368. #endif
  369. static int snd_msnd_initialize(struct snd_card *card)
  370. {
  371. struct snd_msnd *chip = card->private_data;
  372. int err, timeout;
  373. #ifdef MSND_CLASSIC
  374. outb(HPWAITSTATE_0, chip->io + HP_WAIT);
  375. outb(HPBITMODE_16, chip->io + HP_BITM);
  376. reset_proteus(chip);
  377. #endif
  378. err = snd_msnd_init_sma(chip);
  379. if (err < 0) {
  380. dev_warn(card->dev, LOGNAME ": Cannot initialize SMA\n");
  381. return err;
  382. }
  383. err = snd_msnd_reset_dsp(chip, NULL);
  384. if (err < 0)
  385. return err;
  386. err = upload_dsp_code(card);
  387. if (err < 0) {
  388. dev_warn(card->dev, LOGNAME ": Cannot upload DSP code\n");
  389. return err;
  390. }
  391. timeout = 200;
  392. while (readw(chip->mappedbase)) {
  393. msleep(1);
  394. if (!timeout--) {
  395. dev_err(card->dev, LOGNAME ": DSP reset timeout\n");
  396. return -EIO;
  397. }
  398. }
  399. snd_msndmix_setup(chip);
  400. return 0;
  401. }
  402. static int snd_msnd_dsp_full_reset(struct snd_card *card)
  403. {
  404. struct snd_msnd *chip = card->private_data;
  405. int rv;
  406. if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10)
  407. return 0;
  408. set_bit(F_RESETTING, &chip->flags);
  409. snd_msnd_dsp_halt(chip, NULL); /* Unconditionally halt */
  410. rv = snd_msnd_initialize(card);
  411. if (rv)
  412. dev_warn(card->dev, LOGNAME ": DSP reset failed\n");
  413. snd_msndmix_force_recsrc(chip, 0);
  414. clear_bit(F_RESETTING, &chip->flags);
  415. return rv;
  416. }
  417. static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
  418. {
  419. if (snd_msnd_send_dsp_cmd(chip, cmd) == 0)
  420. return 0;
  421. snd_msnd_dsp_full_reset(chip->card);
  422. return snd_msnd_send_dsp_cmd(chip, cmd);
  423. }
  424. static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
  425. {
  426. dev_dbg(chip->card->dev, "snd_msnd_calibrate_adc(%i)\n", srate);
  427. writew(srate, chip->SMA + SMA_wCalFreqAtoD);
  428. if (chip->calibrate_signal == 0)
  429. writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
  430. | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
  431. else
  432. writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
  433. & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
  434. if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
  435. snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) {
  436. schedule_timeout_interruptible(msecs_to_jiffies(333));
  437. return 0;
  438. }
  439. dev_warn(chip->card->dev, LOGNAME ": ADC calibration failed\n");
  440. return -EIO;
  441. }
  442. /*
  443. * ALSA callback function, called when attempting to open the MIDI device.
  444. */
  445. static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu)
  446. {
  447. snd_msnd_enable_irq(mpu->private_data);
  448. snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START);
  449. return 0;
  450. }
  451. static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
  452. {
  453. snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP);
  454. snd_msnd_disable_irq(mpu->private_data);
  455. }
  456. static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  457. static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
  458. static int snd_msnd_attach(struct snd_card *card)
  459. {
  460. struct snd_msnd *chip = card->private_data;
  461. int err;
  462. err = devm_request_irq(card->dev, chip->irq, snd_msnd_interrupt, 0,
  463. card->shortname, chip);
  464. if (err < 0) {
  465. dev_err(card->dev, LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
  466. return err;
  467. }
  468. card->sync_irq = chip->irq;
  469. if (!devm_request_region(card->dev, chip->io, DSP_NUMIO,
  470. card->shortname))
  471. return -EBUSY;
  472. if (!devm_request_mem_region(card->dev, chip->base, BUFFSIZE,
  473. card->shortname)) {
  474. dev_err(card->dev, LOGNAME
  475. ": unable to grab memory region 0x%lx-0x%lx\n",
  476. chip->base, chip->base + BUFFSIZE - 1);
  477. return -EBUSY;
  478. }
  479. chip->mappedbase = devm_ioremap(card->dev, chip->base, 0x8000);
  480. if (!chip->mappedbase) {
  481. dev_err(card->dev, LOGNAME
  482. ": unable to map memory region 0x%lx-0x%lx\n",
  483. chip->base, chip->base + BUFFSIZE - 1);
  484. return -EIO;
  485. }
  486. err = snd_msnd_dsp_full_reset(card);
  487. if (err < 0)
  488. return err;
  489. err = snd_msnd_pcm(card, 0);
  490. if (err < 0) {
  491. dev_err(card->dev, LOGNAME ": error creating new PCM device\n");
  492. return err;
  493. }
  494. err = snd_msndmix_new(card);
  495. if (err < 0) {
  496. dev_err(card->dev, LOGNAME ": error creating new Mixer device\n");
  497. return err;
  498. }
  499. if (mpu_io[0] != SNDRV_AUTO_PORT) {
  500. struct snd_mpu401 *mpu;
  501. err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
  502. mpu_io[0],
  503. MPU401_MODE_INPUT |
  504. MPU401_MODE_OUTPUT,
  505. mpu_irq[0],
  506. &chip->rmidi);
  507. if (err < 0) {
  508. dev_err(card->dev, LOGNAME
  509. ": error creating new Midi device\n");
  510. return err;
  511. }
  512. mpu = chip->rmidi->private_data;
  513. mpu->open_input = snd_msnd_mpu401_open;
  514. mpu->close_input = snd_msnd_mpu401_close;
  515. mpu->private_data = chip;
  516. }
  517. disable_irq(chip->irq);
  518. snd_msnd_calibrate_adc(chip, chip->play_sample_rate);
  519. snd_msndmix_force_recsrc(chip, 0);
  520. err = snd_card_register(card);
  521. if (err < 0)
  522. return err;
  523. return 0;
  524. }
  525. #ifndef MSND_CLASSIC
  526. /* Pinnacle/Fiji Logical Device Configuration */
  527. static int snd_msnd_write_cfg(struct snd_msnd *chip, int cfg, int reg, int value)
  528. {
  529. outb(reg, cfg);
  530. outb(value, cfg + 1);
  531. if (value != inb(cfg + 1)) {
  532. dev_err(chip->card->dev, LOGNAME ": %s: I/O error\n", __func__);
  533. return -EIO;
  534. }
  535. return 0;
  536. }
  537. static int snd_msnd_write_cfg_io0(struct snd_msnd *chip, int cfg, int num, u16 io)
  538. {
  539. if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num))
  540. return -EIO;
  541. if (snd_msnd_write_cfg(chip, cfg, IREG_IO0_BASEHI, HIBYTE(io)))
  542. return -EIO;
  543. if (snd_msnd_write_cfg(chip, cfg, IREG_IO0_BASELO, LOBYTE(io)))
  544. return -EIO;
  545. return 0;
  546. }
  547. static int snd_msnd_write_cfg_io1(struct snd_msnd *chip, int cfg, int num, u16 io)
  548. {
  549. if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num))
  550. return -EIO;
  551. if (snd_msnd_write_cfg(chip, cfg, IREG_IO1_BASEHI, HIBYTE(io)))
  552. return -EIO;
  553. if (snd_msnd_write_cfg(chip, cfg, IREG_IO1_BASELO, LOBYTE(io)))
  554. return -EIO;
  555. return 0;
  556. }
  557. static int snd_msnd_write_cfg_irq(struct snd_msnd *chip, int cfg, int num, u16 irq)
  558. {
  559. if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num))
  560. return -EIO;
  561. if (snd_msnd_write_cfg(chip, cfg, IREG_IRQ_NUMBER, LOBYTE(irq)))
  562. return -EIO;
  563. if (snd_msnd_write_cfg(chip, cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE))
  564. return -EIO;
  565. return 0;
  566. }
  567. static int snd_msnd_write_cfg_mem(struct snd_msnd *chip, int cfg, int num, int mem)
  568. {
  569. u16 wmem;
  570. mem >>= 8;
  571. wmem = (u16)(mem & 0xfff);
  572. if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num))
  573. return -EIO;
  574. if (snd_msnd_write_cfg(chip, cfg, IREG_MEMBASEHI, HIBYTE(wmem)))
  575. return -EIO;
  576. if (snd_msnd_write_cfg(chip, cfg, IREG_MEMBASELO, LOBYTE(wmem)))
  577. return -EIO;
  578. if (wmem && snd_msnd_write_cfg(chip, cfg, IREG_MEMCONTROL,
  579. MEMTYPE_HIADDR | MEMTYPE_16BIT))
  580. return -EIO;
  581. return 0;
  582. }
  583. static int snd_msnd_activate_logical(struct snd_msnd *chip, int cfg, int num)
  584. {
  585. if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num))
  586. return -EIO;
  587. if (snd_msnd_write_cfg(chip, cfg, IREG_ACTIVATE, LD_ACTIVATE))
  588. return -EIO;
  589. return 0;
  590. }
  591. static int snd_msnd_write_cfg_logical(struct snd_msnd *chip,
  592. int cfg, int num, u16 io0,
  593. u16 io1, u16 irq, int mem)
  594. {
  595. if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num))
  596. return -EIO;
  597. if (snd_msnd_write_cfg_io0(chip, cfg, num, io0))
  598. return -EIO;
  599. if (snd_msnd_write_cfg_io1(chip, cfg, num, io1))
  600. return -EIO;
  601. if (snd_msnd_write_cfg_irq(chip, cfg, num, irq))
  602. return -EIO;
  603. if (snd_msnd_write_cfg_mem(chip, cfg, num, mem))
  604. return -EIO;
  605. if (snd_msnd_activate_logical(chip, cfg, num))
  606. return -EIO;
  607. return 0;
  608. }
  609. static int snd_msnd_pinnacle_cfg_reset(struct snd_msnd *chip, int cfg)
  610. {
  611. int i;
  612. /* Reset devices if told to */
  613. dev_info(chip->card->dev, LOGNAME ": Resetting all devices\n");
  614. for (i = 0; i < 4; ++i)
  615. if (snd_msnd_write_cfg_logical(chip, cfg, i, 0, 0, 0, 0))
  616. return -EIO;
  617. return 0;
  618. }
  619. #endif
  620. static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
  621. static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
  622. module_param_array(index, int, NULL, 0444);
  623. MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard.");
  624. module_param_array(id, charp, NULL, 0444);
  625. MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard.");
  626. static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  627. static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
  628. static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  629. #ifndef MSND_CLASSIC
  630. static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  631. /* Extra Peripheral Configuration (Default: Disable) */
  632. static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  633. static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  634. static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
  635. static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  636. /* If we have the digital daugherboard... */
  637. static int digital[SNDRV_CARDS];
  638. /* Extra Peripheral Configuration */
  639. static int reset[SNDRV_CARDS];
  640. #endif
  641. static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
  642. static int calibrate_signal;
  643. #ifdef CONFIG_PNP
  644. static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
  645. module_param_array(isapnp, bool, NULL, 0444);
  646. MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
  647. #define has_isapnp(x) isapnp[x]
  648. #else
  649. #define has_isapnp(x) 0
  650. #endif
  651. MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
  652. MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver");
  653. MODULE_LICENSE("GPL");
  654. MODULE_FIRMWARE(INITCODEFILE);
  655. MODULE_FIRMWARE(PERMCODEFILE);
  656. module_param_hw_array(io, long, ioport, NULL, 0444);
  657. MODULE_PARM_DESC(io, "IO port #");
  658. module_param_hw_array(irq, int, irq, NULL, 0444);
  659. module_param_hw_array(mem, long, iomem, NULL, 0444);
  660. module_param_array(write_ndelay, int, NULL, 0444);
  661. module_param(calibrate_signal, int, 0444);
  662. #ifndef MSND_CLASSIC
  663. module_param_array(digital, int, NULL, 0444);
  664. module_param_hw_array(cfg, long, ioport, NULL, 0444);
  665. module_param_array(reset, int, NULL, 0444);
  666. module_param_hw_array(mpu_io, long, ioport, NULL, 0444);
  667. module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
  668. module_param_hw_array(ide_io0, long, ioport, NULL, 0444);
  669. module_param_hw_array(ide_io1, long, ioport, NULL, 0444);
  670. module_param_hw_array(ide_irq, int, irq, NULL, 0444);
  671. module_param_hw_array(joystick_io, long, ioport, NULL, 0444);
  672. #endif
  673. static int snd_msnd_isa_match(struct device *pdev, unsigned int i)
  674. {
  675. if (io[i] == SNDRV_AUTO_PORT)
  676. return 0;
  677. if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) {
  678. dev_warn(pdev, LOGNAME ": io, irq and mem must be set\n");
  679. return 0;
  680. }
  681. #ifdef MSND_CLASSIC
  682. if (!(io[i] == 0x290 ||
  683. io[i] == 0x260 ||
  684. io[i] == 0x250 ||
  685. io[i] == 0x240 ||
  686. io[i] == 0x230 ||
  687. io[i] == 0x220 ||
  688. io[i] == 0x210 ||
  689. io[i] == 0x3e0)) {
  690. dev_err(pdev, LOGNAME ": \"io\" - DSP I/O base must be set "
  691. " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, "
  692. "or 0x3E0\n");
  693. return 0;
  694. }
  695. #else
  696. if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) {
  697. dev_err(pdev, LOGNAME
  698. ": \"io\" - DSP I/O base must within the range 0x100 "
  699. "to 0x3E0 and must be evenly divisible by 0x10\n");
  700. return 0;
  701. }
  702. #endif /* MSND_CLASSIC */
  703. if (!(irq[i] == 5 ||
  704. irq[i] == 7 ||
  705. irq[i] == 9 ||
  706. irq[i] == 10 ||
  707. irq[i] == 11 ||
  708. irq[i] == 12)) {
  709. dev_err(pdev, LOGNAME
  710. ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n");
  711. return 0;
  712. }
  713. if (!(mem[i] == 0xb0000 ||
  714. mem[i] == 0xc8000 ||
  715. mem[i] == 0xd0000 ||
  716. mem[i] == 0xd8000 ||
  717. mem[i] == 0xe0000 ||
  718. mem[i] == 0xe8000)) {
  719. dev_err(pdev, LOGNAME ": \"mem\" - must be set to "
  720. "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or "
  721. "0xe8000\n");
  722. return 0;
  723. }
  724. #ifndef MSND_CLASSIC
  725. if (cfg[i] == SNDRV_AUTO_PORT) {
  726. dev_info(pdev, LOGNAME ": Assuming PnP mode\n");
  727. } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) {
  728. dev_info(pdev, LOGNAME
  729. ": Config port must be 0x250, 0x260 or 0x270 "
  730. "(or unspecified for PnP mode)\n");
  731. return 0;
  732. }
  733. #endif /* MSND_CLASSIC */
  734. return 1;
  735. }
  736. static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
  737. {
  738. int err;
  739. struct snd_card *card;
  740. struct snd_msnd *chip;
  741. if (has_isapnp(idx)
  742. #ifndef MSND_CLASSIC
  743. || cfg[idx] == SNDRV_AUTO_PORT
  744. #endif
  745. ) {
  746. dev_info(pdev, LOGNAME ": Assuming PnP mode\n");
  747. return -ENODEV;
  748. }
  749. err = snd_devm_card_new(pdev, index[idx], id[idx], THIS_MODULE,
  750. sizeof(struct snd_msnd), &card);
  751. if (err < 0)
  752. return err;
  753. chip = card->private_data;
  754. chip->card = card;
  755. #ifdef MSND_CLASSIC
  756. switch (irq[idx]) {
  757. case 5:
  758. chip->irqid = HPIRQ_5; break;
  759. case 7:
  760. chip->irqid = HPIRQ_7; break;
  761. case 9:
  762. chip->irqid = HPIRQ_9; break;
  763. case 10:
  764. chip->irqid = HPIRQ_10; break;
  765. case 11:
  766. chip->irqid = HPIRQ_11; break;
  767. case 12:
  768. chip->irqid = HPIRQ_12; break;
  769. }
  770. switch (mem[idx]) {
  771. case 0xb0000:
  772. chip->memid = HPMEM_B000; break;
  773. case 0xc8000:
  774. chip->memid = HPMEM_C800; break;
  775. case 0xd0000:
  776. chip->memid = HPMEM_D000; break;
  777. case 0xd8000:
  778. chip->memid = HPMEM_D800; break;
  779. case 0xe0000:
  780. chip->memid = HPMEM_E000; break;
  781. case 0xe8000:
  782. chip->memid = HPMEM_E800; break;
  783. }
  784. #else
  785. dev_info(pdev, LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
  786. cfg[idx]);
  787. if (!devm_request_region(card->dev, cfg[idx], 2,
  788. "Pinnacle/Fiji Config")) {
  789. dev_err(pdev, LOGNAME ": Config port 0x%lx conflict\n",
  790. cfg[idx]);
  791. return -EIO;
  792. }
  793. if (reset[idx])
  794. if (snd_msnd_pinnacle_cfg_reset(chip, cfg[idx]))
  795. return -EIO;
  796. /* DSP */
  797. err = snd_msnd_write_cfg_logical(chip, cfg[idx], 0,
  798. io[idx], 0,
  799. irq[idx], mem[idx]);
  800. if (err)
  801. return err;
  802. /* The following are Pinnacle specific */
  803. /* MPU */
  804. if (mpu_io[idx] != SNDRV_AUTO_PORT
  805. && mpu_irq[idx] != SNDRV_AUTO_IRQ) {
  806. dev_info(pdev, LOGNAME
  807. ": Configuring MPU to I/O 0x%lx IRQ %d\n",
  808. mpu_io[idx], mpu_irq[idx]);
  809. err = snd_msnd_write_cfg_logical(chip, cfg[idx], 1,
  810. mpu_io[idx], 0,
  811. mpu_irq[idx], 0);
  812. if (err)
  813. return err;
  814. }
  815. /* IDE */
  816. if (ide_io0[idx] != SNDRV_AUTO_PORT
  817. && ide_io1[idx] != SNDRV_AUTO_PORT
  818. && ide_irq[idx] != SNDRV_AUTO_IRQ) {
  819. dev_info(pdev, LOGNAME
  820. ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n",
  821. ide_io0[idx], ide_io1[idx], ide_irq[idx]);
  822. err = snd_msnd_write_cfg_logical(chip, cfg[idx], 2,
  823. ide_io0[idx], ide_io1[idx],
  824. ide_irq[idx], 0);
  825. if (err)
  826. return err;
  827. }
  828. /* Joystick */
  829. if (joystick_io[idx] != SNDRV_AUTO_PORT) {
  830. dev_info(pdev, LOGNAME
  831. ": Configuring joystick to I/O 0x%lx\n",
  832. joystick_io[idx]);
  833. err = snd_msnd_write_cfg_logical(chip, cfg[idx], 3,
  834. joystick_io[idx], 0,
  835. 0, 0);
  836. if (err)
  837. return err;
  838. }
  839. #endif /* MSND_CLASSIC */
  840. set_default_audio_parameters(chip);
  841. #ifdef MSND_CLASSIC
  842. chip->type = msndClassic;
  843. #else
  844. chip->type = msndPinnacle;
  845. #endif
  846. chip->io = io[idx];
  847. chip->irq = irq[idx];
  848. chip->base = mem[idx];
  849. chip->calibrate_signal = calibrate_signal ? 1 : 0;
  850. chip->recsrc = 0;
  851. chip->dspq_data_buff = DSPQ_DATA_BUFF;
  852. chip->dspq_buff_size = DSPQ_BUFF_SIZE;
  853. if (write_ndelay[idx])
  854. clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
  855. else
  856. set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
  857. #ifndef MSND_CLASSIC
  858. if (digital[idx])
  859. set_bit(F_HAVEDIGITAL, &chip->flags);
  860. #endif
  861. spin_lock_init(&chip->lock);
  862. err = snd_msnd_probe(card);
  863. if (err < 0) {
  864. dev_err(pdev, LOGNAME ": Probe failed\n");
  865. return err;
  866. }
  867. err = snd_msnd_attach(card);
  868. if (err < 0) {
  869. dev_err(pdev, LOGNAME ": Attach failed\n");
  870. return err;
  871. }
  872. dev_set_drvdata(pdev, card);
  873. return 0;
  874. }
  875. static struct isa_driver snd_msnd_driver = {
  876. .match = snd_msnd_isa_match,
  877. .probe = snd_msnd_isa_probe,
  878. /* FIXME: suspend, resume */
  879. .driver = {
  880. .name = DEV_NAME
  881. },
  882. };
  883. #ifdef CONFIG_PNP
  884. static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
  885. const struct pnp_card_device_id *pid)
  886. {
  887. static int idx;
  888. struct pnp_dev *pnp_dev;
  889. struct pnp_dev *mpu_dev;
  890. struct snd_card *card;
  891. struct snd_msnd *chip;
  892. int ret;
  893. for ( ; idx < SNDRV_CARDS; idx++) {
  894. if (has_isapnp(idx))
  895. break;
  896. }
  897. if (idx >= SNDRV_CARDS)
  898. return -ENODEV;
  899. /*
  900. * Check that we still have room for another sound card ...
  901. */
  902. pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
  903. if (!pnp_dev)
  904. return -ENODEV;
  905. mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL);
  906. if (!mpu_dev)
  907. return -ENODEV;
  908. if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) {
  909. dev_info(&pcard->card->dev, "msnd_pinnacle: device is inactive\n");
  910. return -EBUSY;
  911. }
  912. if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) {
  913. dev_info(&pcard->card->dev, "msnd_pinnacle: MPU device is inactive\n");
  914. return -EBUSY;
  915. }
  916. /*
  917. * Create a new ALSA sound card entry, in anticipation
  918. * of detecting our hardware ...
  919. */
  920. ret = snd_devm_card_new(&pcard->card->dev,
  921. index[idx], id[idx], THIS_MODULE,
  922. sizeof(struct snd_msnd), &card);
  923. if (ret < 0)
  924. return ret;
  925. chip = card->private_data;
  926. chip->card = card;
  927. /*
  928. * Read the correct parameters off the ISA PnP bus ...
  929. */
  930. io[idx] = pnp_port_start(pnp_dev, 0);
  931. irq[idx] = pnp_irq(pnp_dev, 0);
  932. mem[idx] = pnp_mem_start(pnp_dev, 0);
  933. mpu_io[idx] = pnp_port_start(mpu_dev, 0);
  934. mpu_irq[idx] = pnp_irq(mpu_dev, 0);
  935. set_default_audio_parameters(chip);
  936. #ifdef MSND_CLASSIC
  937. chip->type = msndClassic;
  938. #else
  939. chip->type = msndPinnacle;
  940. #endif
  941. chip->io = io[idx];
  942. chip->irq = irq[idx];
  943. chip->base = mem[idx];
  944. chip->calibrate_signal = calibrate_signal ? 1 : 0;
  945. chip->recsrc = 0;
  946. chip->dspq_data_buff = DSPQ_DATA_BUFF;
  947. chip->dspq_buff_size = DSPQ_BUFF_SIZE;
  948. if (write_ndelay[idx])
  949. clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
  950. else
  951. set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
  952. #ifndef MSND_CLASSIC
  953. if (digital[idx])
  954. set_bit(F_HAVEDIGITAL, &chip->flags);
  955. #endif
  956. spin_lock_init(&chip->lock);
  957. ret = snd_msnd_probe(card);
  958. if (ret < 0) {
  959. dev_err(&pcard->card->dev, LOGNAME ": Probe failed\n");
  960. return ret;
  961. }
  962. ret = snd_msnd_attach(card);
  963. if (ret < 0) {
  964. dev_err(&pcard->card->dev, LOGNAME ": Attach failed\n");
  965. return ret;
  966. }
  967. pnp_set_card_drvdata(pcard, card);
  968. ++idx;
  969. return 0;
  970. }
  971. static int isa_registered;
  972. static int pnp_registered;
  973. static const struct pnp_card_device_id msnd_pnpids[] = {
  974. /* Pinnacle PnP */
  975. { .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } },
  976. { .id = "" } /* end */
  977. };
  978. MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids);
  979. static struct pnp_card_driver msnd_pnpc_driver = {
  980. .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
  981. .name = "msnd_pinnacle",
  982. .id_table = msnd_pnpids,
  983. .probe = snd_msnd_pnp_detect,
  984. };
  985. #endif /* CONFIG_PNP */
  986. static int __init snd_msnd_init(void)
  987. {
  988. int err;
  989. err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS);
  990. #ifdef CONFIG_PNP
  991. if (!err)
  992. isa_registered = 1;
  993. err = pnp_register_card_driver(&msnd_pnpc_driver);
  994. if (!err)
  995. pnp_registered = 1;
  996. if (isa_registered)
  997. err = 0;
  998. #endif
  999. return err;
  1000. }
  1001. static void __exit snd_msnd_exit(void)
  1002. {
  1003. #ifdef CONFIG_PNP
  1004. if (pnp_registered)
  1005. pnp_unregister_card_driver(&msnd_pnpc_driver);
  1006. if (isa_registered)
  1007. #endif
  1008. isa_unregister_driver(&snd_msnd_driver);
  1009. }
  1010. module_init(snd_msnd_init);
  1011. module_exit(snd_msnd_exit);