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