Lines Matching +full:rom +full:- +full:val
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for C-Media CMI8328-based soundcards, such as AudioExcel AV500
7 * - CMI8328 - main chip (SB Pro emulation, gameport, OPL3, MPU401, CD-ROM)
8 * - CS4231A - WSS codec
9 * - Dream SAM9233+GMS950400+RAM+ROM: Wavetable MIDI, connected to MPU401
26 MODULE_AUTHOR("Ondrej Zary <linux@rainbow-software.org>");
27 MODULE_DESCRIPTION("C-Media CMI8328");
38 static int index[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = -1};
39 static char *id[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = NULL};
40 static long port[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_PORT};
41 static int irq[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_IRQ};
42 static int dma1[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_DMA};
43 static int dma2[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_DMA};
44 static long mpuport[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_PORT};
45 static int mpuirq[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_IRQ};
47 static bool gameport[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = true};
65 MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8328 driver.");
67 MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8328 MPU-401 port.");
91 * bits 2-4: SB IRQ: 001=3, 010=5, 011=7, 100=9, 101=10, 110=11
92 * bits 5-6: SB DMA: 00=disabled (when SB disabled), 01=DMA0, 10=DMA1, 11=DMA3
98 * bits 0-1: CD-ROM mode: 00=disabled, 01=Panasonic, 10=Sony/Mitsumi/Wearnes,
101 * bits 3-4: MPU401 IRQ: 00=3, 01=5, 10=7, 11=9,
102 * bits 5-7: MPU401 port: 000=0x300, 001=0x310, 010=0x320, 011=0x330, 100=0x332,
107 * bits 0-2: CD-ROM IRQ: 000=disabled, 001=3, 010=5, 011=7, 100=9, 101=10,
109 * bits 3-4: CD-ROM DMA: 00=disabled, 01=DMA0, 10=DMA1, 11=DMA3
110 * bits 5-7: CD-ROM port: 000=0x300, 001=0x310, 010=0x320, 011=0x330, 100=0x340,
122 static void snd_cmi8328_cfg_write(u16 port, u8 reg, u8 val) in snd_cmi8328_cfg_write() argument
127 outb(val, port + 3); /* yes, value goes to the same port as index */ in snd_cmi8328_cfg_write()
152 card = chip->card; in snd_cmi8328_mixer()
162 dev_err(card->dev, "error renaming control\n"); in snd_cmi8328_mixer()
170 dev_err(card->dev, "error renaming control\n"); in snd_cmi8328_mixer()
179 dev_err(card->dev, "error renaming control\n"); in snd_cmi8328_mixer()
188 dev_err(card->dev, "error renaming control\n"); in snd_cmi8328_mixer()
195 /* find index of an item in "-1"-ended array */
200 for (i = 0; array[i] != -1; i++) in array_find()
204 return -1; in array_find()
211 for (i = 0; array[i] != -1; i++) in array_find_l()
215 return -1; in array_find_l()
228 0x336, -1 }; in snd_cmi8328_probe()
230 static const int mpu_irqs[] = { 9, 7, 5, 3, -1 }; in snd_cmi8328_probe()
232 static const int irqs[] = { 9, 10, 11, 7, -1 }; in snd_cmi8328_probe()
234 static const int dma1s[] = { 3, 1, 0, -1 }; in snd_cmi8328_probe()
236 static const int dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, {0, -1} }; in snd_cmi8328_probe()
238 u8 val; in snd_cmi8328_probe() local
240 /* 0xff is invalid configuration (but settable - hope it isn't set) */ in snd_cmi8328_probe()
242 return -ENODEV; in snd_cmi8328_probe()
246 return -ENODEV; in snd_cmi8328_probe()
255 return -EBUSY; in snd_cmi8328_probe()
262 return -EBUSY; in snd_cmi8328_probe()
268 dev_warn(pdev, "unable to find a free DMA2, full-duplex will not work\n"); in snd_cmi8328_probe()
269 dma2[ndev] = -1; in snd_cmi8328_probe()
276 return -EINVAL; in snd_cmi8328_probe()
278 val = irq_bits[pos] << 3; in snd_cmi8328_probe()
283 return -EINVAL; in snd_cmi8328_probe()
285 val |= dma_bits[pos]; in snd_cmi8328_probe()
291 return -EINVAL; in snd_cmi8328_probe()
293 val |= 0x04; /* enable separate capture DMA */ in snd_cmi8328_probe()
295 outb(val, port); in snd_cmi8328_probe()
301 cmi = card->private_data; in snd_cmi8328_probe()
302 cmi->card = card; in snd_cmi8328_probe()
303 cmi->port = port; in snd_cmi8328_probe()
304 cmi->wss_cfg = val; in snd_cmi8328_probe()
306 err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev], in snd_cmi8328_probe()
307 dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss); in snd_cmi8328_probe()
311 err = snd_wss_pcm(cmi->wss, 0); in snd_cmi8328_probe()
315 err = snd_wss_mixer(cmi->wss); in snd_cmi8328_probe()
318 err = snd_cmi8328_mixer(cmi->wss); in snd_cmi8328_probe()
322 if (snd_wss_timer(cmi->wss, 0) < 0) in snd_cmi8328_probe()
337 val = CFG2_MPU_ENABLE; in snd_cmi8328_probe()
343 val |= mpu_port_bits[pos] << 5; in snd_cmi8328_probe()
349 val |= mpu_irq_bits[pos] << 3; in snd_cmi8328_probe()
350 snd_cmi8328_cfg_write(port, CFG2, val); in snd_cmi8328_probe()
365 strcpy(card->driver, "CMI8328"); in snd_cmi8328_probe()
366 strcpy(card->shortname, "C-Media CMI8328"); in snd_cmi8328_probe()
367 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d,%d", in snd_cmi8328_probe()
368 card->shortname, cmi->wss->port, irq[ndev], dma1[ndev], in snd_cmi8328_probe()
383 struct gameport *gp = cmi->gameport = gameport_allocate_port(); in snd_cmi8328_probe()
384 if (cmi->gameport) { in snd_cmi8328_probe()
388 gp->io = 0x200; in snd_cmi8328_probe()
402 struct snd_cmi8328 *cmi = card->private_data; in snd_cmi8328_remove()
405 if (cmi->gameport) in snd_cmi8328_remove()
406 gameport_unregister_port(cmi->gameport); in snd_cmi8328_remove()
409 snd_cmi8328_cfg_write(cmi->port, CFG1, CFG1_SB_DISABLE); in snd_cmi8328_remove()
410 snd_cmi8328_cfg_write(cmi->port, CFG2, 0); in snd_cmi8328_remove()
411 snd_cmi8328_cfg_write(cmi->port, CFG3, 0); in snd_cmi8328_remove()
423 cmi = card->private_data; in snd_cmi8328_suspend()
424 snd_cmi8328_cfg_save(cmi->port, cmi->cfg); in snd_cmi8328_suspend()
426 cmi->wss->suspend(cmi->wss); in snd_cmi8328_suspend()
438 cmi = card->private_data; in snd_cmi8328_resume()
439 snd_cmi8328_cfg_restore(cmi->port, cmi->cfg); in snd_cmi8328_resume()
440 outb(cmi->wss_cfg, cmi->port); in snd_cmi8328_resume()
441 cmi->wss->resume(cmi->wss); in snd_cmi8328_resume()