13 #include <linux/module.h>
14 #include <linux/gameport.h>
20 #define SNDRV_LEGACY_FIND_FREE_IOPORT
21 #define SNDRV_LEGACY_FIND_FREE_IRQ
22 #define SNDRV_LEGACY_FIND_FREE_DMA
29 #if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
30 #define SUPPORT_JOYSTICK 1
34 static int cmi8328_ports[] = { 0x530, 0xe80, 0xf40, 0x604 };
35 #define CMI8328_MAX ARRAY_SIZE(cmi8328_ports)
45 #ifdef SUPPORT_JOYSTICK
67 #ifdef SUPPORT_JOYSTICK
78 #ifdef SUPPORT_JOYSTICK
79 struct gameport *gameport;
85 #define CFG1_SB_DISABLE (1 << 0)
86 #define CFG1_GAMEPORT (1 << 1)
95 #define CFG2_MPU_ENABLE (1 << 2)
113 static u8 snd_cmi8328_cfg_read(
u16 port,
u8 reg)
115 outb(0x43, port + 3);
116 outb(0x21, port + 3);
123 outb(0x43, port + 3);
124 outb(0x21, port + 3);
129 static void snd_cmi8328_cfg_save(
u16 port,
u8 cfg[])
131 cfg[0] = snd_cmi8328_cfg_read(port,
CFG1);
132 cfg[1] = snd_cmi8328_cfg_read(port,
CFG2);
133 cfg[2] = snd_cmi8328_cfg_read(port,
CFG3);
136 static void snd_cmi8328_cfg_restore(
u16 port,
u8 cfg[])
138 snd_cmi8328_cfg_write(port,
CFG1, cfg[0]);
139 snd_cmi8328_cfg_write(port,
CFG2, cfg[1]);
140 snd_cmi8328_cfg_write(port,
CFG3, cfg[2]);
173 strcpy(
id2.name,
"Synth Playback Switch");
182 strcpy(
id2.name,
"Synth Playback Volume");
197 for (i = 0; array[
i] != -1; i++)
198 if (array[i] == item)
208 for (i = 0; array[
i] != -1; i++)
209 if (array[i] == item)
220 #ifdef SUPPORT_JOYSTICK
224 static long mpu_ports[] = { 0x330, 0x300, 0x310, 0x320, 0x332, 0x334,
226 static u8 mpu_port_bits[] = { 3, 0, 1, 2, 4, 5, 6 };
227 static int mpu_irqs[] = { 9, 7, 5, 3, -1 };
228 static u8 mpu_irq_bits[] = { 3, 2, 1, 0 };
229 static int irqs[] = { 9, 10, 11, 7, -1 };
230 static u8 irq_bits[] = { 2, 3, 4, 1 };
231 static int dma1s[] = { 3, 1, 0, -1 };
232 static u8 dma_bits[] = { 3, 2, 1 };
233 static int dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, {0, -1} };
234 u16 port = cmi8328_ports[
ndev];
238 if (snd_cmi8328_cfg_read(port,
CFG1) == 0xff)
245 snd_cmi8328_cfg_write(port,
CFG2, 0);
246 snd_cmi8328_cfg_write(port,
CFG3, 0);
249 irq[
ndev] = snd_legacy_find_free_irq(irqs);
256 dma1[
ndev] = snd_legacy_find_free_dma(dma1s);
257 if (dma1[ndev] < 0) {
263 dma2[
ndev] = snd_legacy_find_free_dma(dma2s[dma1[ndev] % 4]);
264 if (dma2[ndev] < 0) {
275 val = irq_bits[
pos] << 3;
282 val |= dma_bits[
pos];
284 if (dma2[ndev] >= 0 && dma1[ndev] != dma2[ndev]) {
285 pos =
array_find(dma2s[dma1[ndev]], dma2[ndev]);
316 err = snd_cmi8328_mixer(cmi->
wss);
324 mpuport[
ndev] = snd_legacy_find_free_ioport(mpu_ports, 2);
325 if (mpuport[ndev] < 0)
329 mpuirq[
ndev] = snd_legacy_find_free_irq(mpu_irqs);
330 if (mpuirq[ndev] < 0)
334 if (mpuport[ndev] > 0 && mpuirq[ndev] > 0) {
341 val |= mpu_port_bits[
pos] << 5;
347 val |= mpu_irq_bits[
pos] << 3;
348 snd_cmi8328_cfg_write(port,
CFG2, val);
351 0, mpuirq[ndev],
NULL) < 0)
367 (dma2[ndev] >= 0) ? dma2[ndev] : dma1[ndev]);
373 #ifdef SUPPORT_JOYSTICK
381 struct gameport *
gp = cmi->gameport = gameport_allocate_port();
385 gameport_set_name(gp,
"CMI8328 Gameport");
387 gameport_set_dev_parent(gp, pdev);
389 gameport_set_port_data(gp, res);
391 snd_cmi8328_cfg_write(port,
CFG1,
393 gameport_register_port(gp);
409 #ifdef SUPPORT_JOYSTICK
411 struct resource *res = gameport_get_port_data(cmi->gameport);
418 snd_cmi8328_cfg_write(cmi->
port,
CFG2, 0);
419 snd_cmi8328_cfg_write(cmi->
port,
CFG3, 0);
426 static int snd_cmi8328_suspend(
struct device *pdev,
unsigned int n,
435 snd_cmi8328_cfg_save(cmi->
port, cmi->
cfg);
437 snd_pcm_suspend_all(cmi->
wss->pcm);
438 cmi->
wss->suspend(cmi->
wss);
443 static int snd_cmi8328_resume(
struct device *pdev,
unsigned int n)
451 snd_cmi8328_cfg_restore(cmi->
port, cmi->
cfg);
453 cmi->
wss->resume(cmi->
wss);
460 static struct isa_driver snd_cmi8328_driver = {
461 .probe = snd_cmi8328_probe,
464 .suspend = snd_cmi8328_suspend,
465 .resume = snd_cmi8328_resume,
472 static int __init alsa_card_cmi8328_init(
void)
477 static void __exit alsa_card_cmi8328_exit(
void)