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