1 2 /* 3 * jazz16.c - driver for Media Vision Jazz16 based soundcards. 4 * Copyright (C) 2009 Krzysztof Helt <krzysztof.h1@wp.pl> 5 * Based on patches posted by Rask Ingemann Lambertsen and Rene Herman. 6 * Based on OSS Sound Blaster driver. 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive for 10 * more details. 11 * 12 */ 13 14 #include <linux/init.h> 15 #include <linux/module.h> 16 #include <linux/io.h> 17 #include <linux/delay.h> 18 #include <asm/dma.h> 19 #include <linux/isa.h> 20 #include <sound/core.h> 21 #include <sound/mpu401.h> 22 #include <sound/opl3.h> 23 #include <sound/sb.h> 24 #define SNDRV_LEGACY_FIND_FREE_IRQ 25 #define SNDRV_LEGACY_FIND_FREE_DMA 26 #include <sound/initval.h> 27 28 #define PFX "jazz16: " 29 30 MODULE_DESCRIPTION("Media Vision Jazz16"); 31 MODULE_SUPPORTED_DEVICE("{{Media Vision ??? }," 32 "{RTL,RTL3000}}"); 33 34 MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); 35 MODULE_LICENSE("GPL"); 36 37 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 38 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 39 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 40 static unsigned long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; 41 static unsigned long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; 42 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; 43 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; 44 static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; 45 static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; 46 47 module_param_array(index, int, NULL, 0444); 48 MODULE_PARM_DESC(index, "Index value for Media Vision Jazz16 based soundcard."); 49 module_param_array(id, charp, NULL, 0444); 50 MODULE_PARM_DESC(id, "ID string for Media Vision Jazz16 based soundcard."); 51 module_param_array(enable, bool, NULL, 0444); 52 MODULE_PARM_DESC(enable, "Enable Media Vision Jazz16 based soundcard."); 53 module_param_hw_array(port, long, ioport, NULL, 0444); 54 MODULE_PARM_DESC(port, "Port # for jazz16 driver."); 55 module_param_hw_array(mpu_port, long, ioport, NULL, 0444); 56 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for jazz16 driver."); 57 module_param_hw_array(irq, int, irq, NULL, 0444); 58 MODULE_PARM_DESC(irq, "IRQ # for jazz16 driver."); 59 module_param_hw_array(mpu_irq, int, irq, NULL, 0444); 60 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for jazz16 driver."); 61 module_param_hw_array(dma8, int, dma, NULL, 0444); 62 MODULE_PARM_DESC(dma8, "DMA8 # for jazz16 driver."); 63 module_param_hw_array(dma16, int, dma, NULL, 0444); 64 MODULE_PARM_DESC(dma16, "DMA16 # for jazz16 driver."); 65 66 #define SB_JAZZ16_WAKEUP 0xaf 67 #define SB_JAZZ16_SET_PORTS 0x50 68 #define SB_DSP_GET_JAZZ_BRD_REV 0xfa 69 #define SB_JAZZ16_SET_DMAINTR 0xfb 70 #define SB_DSP_GET_JAZZ_MODEL 0xfe 71 72 struct snd_card_jazz16 { 73 struct snd_sb *chip; 74 }; 75 76 static irqreturn_t jazz16_interrupt(int irq, void *chip) 77 { 78 return snd_sb8dsp_interrupt(chip); 79 } 80 81 static int jazz16_configure_ports(unsigned long port, 82 unsigned long mpu_port, int idx) 83 { 84 unsigned char val; 85 86 if (!request_region(0x201, 1, "jazz16 config")) { 87 snd_printk(KERN_ERR "config port region is already in use.\n"); 88 return -EBUSY; 89 } 90 outb(SB_JAZZ16_WAKEUP - idx, 0x201); 91 udelay(100); 92 outb(SB_JAZZ16_SET_PORTS + idx, 0x201); 93 udelay(100); 94 val = port & 0x70; 95 val |= (mpu_port & 0x30) >> 4; 96 outb(val, 0x201); 97 98 release_region(0x201, 1); 99 return 0; 100 } 101 102 static int jazz16_detect_board(unsigned long port, 103 unsigned long mpu_port) 104 { 105 int err; 106 int val; 107 struct snd_sb chip; 108 109 if (!request_region(port, 0x10, "jazz16")) { 110 snd_printk(KERN_ERR "I/O port region is already in use.\n"); 111 return -EBUSY; 112 } 113 /* just to call snd_sbdsp_command/reset/get_byte() */ 114 chip.port = port; 115 116 err = snd_sbdsp_reset(&chip); 117 if (err < 0) 118 for (val = 0; val < 4; val++) { 119 err = jazz16_configure_ports(port, mpu_port, val); 120 if (err < 0) 121 break; 122 123 err = snd_sbdsp_reset(&chip); 124 if (!err) 125 break; 126 } 127 if (err < 0) { 128 err = -ENODEV; 129 goto err_unmap; 130 } 131 if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_BRD_REV)) { 132 err = -EBUSY; 133 goto err_unmap; 134 } 135 val = snd_sbdsp_get_byte(&chip); 136 if (val >= 0x30) 137 snd_sbdsp_get_byte(&chip); 138 139 if ((val & 0xf0) != 0x10) { 140 err = -ENODEV; 141 goto err_unmap; 142 } 143 if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_MODEL)) { 144 err = -EBUSY; 145 goto err_unmap; 146 } 147 snd_sbdsp_get_byte(&chip); 148 err = snd_sbdsp_get_byte(&chip); 149 snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n", 150 val, err); 151 152 err = 0; 153 154 err_unmap: 155 release_region(port, 0x10); 156 return err; 157 } 158 159 static int jazz16_configure_board(struct snd_sb *chip, int mpu_irq) 160 { 161 static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4, 162 0, 2, 5, 0, 0, 0, 0, 6 }; 163 static unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 }; 164 165 if (jazz_dma_bits[chip->dma8] == 0 || 166 jazz_dma_bits[chip->dma16] == 0 || 167 jazz_irq_bits[chip->irq] == 0) 168 return -EINVAL; 169 170 if (!snd_sbdsp_command(chip, SB_JAZZ16_SET_DMAINTR)) 171 return -EBUSY; 172 173 if (!snd_sbdsp_command(chip, 174 jazz_dma_bits[chip->dma8] | 175 (jazz_dma_bits[chip->dma16] << 4))) 176 return -EBUSY; 177 178 if (!snd_sbdsp_command(chip, 179 jazz_irq_bits[chip->irq] | 180 (jazz_irq_bits[mpu_irq] << 4))) 181 return -EBUSY; 182 183 return 0; 184 } 185 186 static int snd_jazz16_match(struct device *devptr, unsigned int dev) 187 { 188 if (!enable[dev]) 189 return 0; 190 if (port[dev] == SNDRV_AUTO_PORT) { 191 snd_printk(KERN_ERR "please specify port\n"); 192 return 0; 193 } else if (port[dev] == 0x200 || (port[dev] & ~0x270)) { 194 snd_printk(KERN_ERR "incorrect port specified\n"); 195 return 0; 196 } 197 if (dma8[dev] != SNDRV_AUTO_DMA && 198 dma8[dev] != 1 && dma8[dev] != 3) { 199 snd_printk(KERN_ERR "dma8 must be 1 or 3\n"); 200 return 0; 201 } 202 if (dma16[dev] != SNDRV_AUTO_DMA && 203 dma16[dev] != 5 && dma16[dev] != 7) { 204 snd_printk(KERN_ERR "dma16 must be 5 or 7\n"); 205 return 0; 206 } 207 if (mpu_port[dev] != SNDRV_AUTO_PORT && 208 (mpu_port[dev] & ~0x030) != 0x300) { 209 snd_printk(KERN_ERR "incorrect mpu_port specified\n"); 210 return 0; 211 } 212 if (mpu_irq[dev] != SNDRV_AUTO_DMA && 213 mpu_irq[dev] != 2 && mpu_irq[dev] != 3 && 214 mpu_irq[dev] != 5 && mpu_irq[dev] != 7) { 215 snd_printk(KERN_ERR "mpu_irq must be 2, 3, 5 or 7\n"); 216 return 0; 217 } 218 return 1; 219 } 220 221 static int snd_jazz16_probe(struct device *devptr, unsigned int dev) 222 { 223 struct snd_card *card; 224 struct snd_card_jazz16 *jazz16; 225 struct snd_sb *chip; 226 struct snd_opl3 *opl3; 227 static int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1}; 228 static int possible_dmas8[] = {1, 3, -1}; 229 static int possible_dmas16[] = {5, 7, -1}; 230 int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq; 231 232 err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE, 233 sizeof(struct snd_card_jazz16), &card); 234 if (err < 0) 235 return err; 236 237 jazz16 = card->private_data; 238 239 xirq = irq[dev]; 240 if (xirq == SNDRV_AUTO_IRQ) { 241 xirq = snd_legacy_find_free_irq(possible_irqs); 242 if (xirq < 0) { 243 snd_printk(KERN_ERR "unable to find a free IRQ\n"); 244 err = -EBUSY; 245 goto err_free; 246 } 247 } 248 xdma8 = dma8[dev]; 249 if (xdma8 == SNDRV_AUTO_DMA) { 250 xdma8 = snd_legacy_find_free_dma(possible_dmas8); 251 if (xdma8 < 0) { 252 snd_printk(KERN_ERR "unable to find a free DMA8\n"); 253 err = -EBUSY; 254 goto err_free; 255 } 256 } 257 xdma16 = dma16[dev]; 258 if (xdma16 == SNDRV_AUTO_DMA) { 259 xdma16 = snd_legacy_find_free_dma(possible_dmas16); 260 if (xdma16 < 0) { 261 snd_printk(KERN_ERR "unable to find a free DMA16\n"); 262 err = -EBUSY; 263 goto err_free; 264 } 265 } 266 267 xmpu_port = mpu_port[dev]; 268 if (xmpu_port == SNDRV_AUTO_PORT) 269 xmpu_port = 0; 270 err = jazz16_detect_board(port[dev], xmpu_port); 271 if (err < 0) { 272 printk(KERN_ERR "Media Vision Jazz16 board not detected\n"); 273 goto err_free; 274 } 275 err = snd_sbdsp_create(card, port[dev], irq[dev], 276 jazz16_interrupt, 277 dma8[dev], dma16[dev], 278 SB_HW_JAZZ16, 279 &chip); 280 if (err < 0) 281 goto err_free; 282 283 xmpu_irq = mpu_irq[dev]; 284 if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT) 285 xmpu_irq = 0; 286 err = jazz16_configure_board(chip, xmpu_irq); 287 if (err < 0) { 288 printk(KERN_ERR "Media Vision Jazz16 configuration failed\n"); 289 goto err_free; 290 } 291 292 jazz16->chip = chip; 293 294 strcpy(card->driver, "jazz16"); 295 strcpy(card->shortname, "Media Vision Jazz16"); 296 sprintf(card->longname, 297 "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d", 298 port[dev], xirq, xdma8, xdma16); 299 300 err = snd_sb8dsp_pcm(chip, 0); 301 if (err < 0) 302 goto err_free; 303 err = snd_sbmixer_new(chip); 304 if (err < 0) 305 goto err_free; 306 307 err = snd_opl3_create(card, chip->port, chip->port + 2, 308 OPL3_HW_AUTO, 1, &opl3); 309 if (err < 0) 310 snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", 311 chip->port, chip->port + 2); 312 else { 313 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); 314 if (err < 0) 315 goto err_free; 316 } 317 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { 318 if (mpu_irq[dev] == SNDRV_AUTO_IRQ) 319 mpu_irq[dev] = -1; 320 321 if (snd_mpu401_uart_new(card, 0, 322 MPU401_HW_MPU401, 323 mpu_port[dev], 0, 324 mpu_irq[dev], 325 NULL) < 0) 326 snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n", 327 mpu_port[dev]); 328 } 329 330 err = snd_card_register(card); 331 if (err < 0) 332 goto err_free; 333 334 dev_set_drvdata(devptr, card); 335 return 0; 336 337 err_free: 338 snd_card_free(card); 339 return err; 340 } 341 342 static int snd_jazz16_remove(struct device *devptr, unsigned int dev) 343 { 344 struct snd_card *card = dev_get_drvdata(devptr); 345 346 snd_card_free(card); 347 return 0; 348 } 349 350 #ifdef CONFIG_PM 351 static int snd_jazz16_suspend(struct device *pdev, unsigned int n, 352 pm_message_t state) 353 { 354 struct snd_card *card = dev_get_drvdata(pdev); 355 struct snd_card_jazz16 *acard = card->private_data; 356 struct snd_sb *chip = acard->chip; 357 358 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 359 snd_pcm_suspend_all(chip->pcm); 360 snd_sbmixer_suspend(chip); 361 return 0; 362 } 363 364 static int snd_jazz16_resume(struct device *pdev, unsigned int n) 365 { 366 struct snd_card *card = dev_get_drvdata(pdev); 367 struct snd_card_jazz16 *acard = card->private_data; 368 struct snd_sb *chip = acard->chip; 369 370 snd_sbdsp_reset(chip); 371 snd_sbmixer_resume(chip); 372 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 373 return 0; 374 } 375 #endif 376 377 static struct isa_driver snd_jazz16_driver = { 378 .match = snd_jazz16_match, 379 .probe = snd_jazz16_probe, 380 .remove = snd_jazz16_remove, 381 #ifdef CONFIG_PM 382 .suspend = snd_jazz16_suspend, 383 .resume = snd_jazz16_resume, 384 #endif 385 .driver = { 386 .name = "jazz16" 387 }, 388 }; 389 390 module_isa_driver(snd_jazz16_driver, SNDRV_CARDS); 391