^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) card-ad1816a.c - driver for ADI SoundPort AD1816A based soundcards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Copyright (C) 2000 by Massimo Piccioni <dafastidio@libero.it>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sound/ad1816a.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/mpu401.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/opl3.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define PFX "ad1816a: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) MODULE_DESCRIPTION("AD1816A, AD1815");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D},"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) "{Analog Devices,AD1815},"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) "{Analog Devices,AD1816A},"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) "{TerraTec,Base 64},"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) "{TerraTec,AudioSystem EWS64S},"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) "{Aztech/Newcom SC-16 3D},"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) "{Shark Predator ISA}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int clockfreq[SNDRV_CARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MODULE_PARM_DESC(id, "ID string for ad1816a based soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param_array(enable, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) module_param_array(clockfreq, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct pnp_card_device_id snd_ad1816a_pnpids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Analog Devices AD1815 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Analog Devices AD1816? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { .id = "AZT1022", .devs = { { .id = "AZT1018" }, { .id = "AZT2002" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Highscreen Sound-Boostar 16 3D - added by Stefan Behnel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { .id = "LWC1061", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Highscreen Sound-Boostar 16 3D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Shark Predator ISA - added by Ken Arromdee */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { .id = "TER1112", .devs = { { .id = "TER1100" }, { .id = "TER1101" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Analog Devices AD1816A - Terratec Base 64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { .id = "" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define DRIVER_NAME "snd-card-ad1816a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) const struct pnp_card_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct pnp_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pdev = pnp_request_card_device(card, id->devs[0].id, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (pdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) err = pnp_activate_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) printk(KERN_ERR PFX "AUDIO PnP configure failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) port[dev] = pnp_port_start(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) fm_port[dev] = pnp_port_start(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dma1[dev] = pnp_dma(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dma2[dev] = pnp_dma(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) irq[dev] = pnp_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pdev = pnp_request_card_device(card, id->devs[1].id, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) mpu_port[dev] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) err = pnp_activate_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) printk(KERN_ERR PFX "MPU401 PnP configure failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mpu_port[dev] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mpu_port[dev] = pnp_port_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) mpu_irq[dev] = pnp_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) const struct pnp_card_device_id *pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct snd_ad1816a *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct snd_opl3 *opl3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) error = snd_card_new(&pcard->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) index[dev], id[dev], THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) sizeof(struct snd_ad1816a), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if ((error = snd_card_ad1816a_pnp(dev, pcard, pid))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if ((error = snd_ad1816a_create(card, port[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) irq[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dma1[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dma2[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) chip)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) chip->clock_freq = clockfreq[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) strcpy(card->driver, "AD1816A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) strcpy(card->shortname, "ADI SoundPort AD1816A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if ((error = snd_ad1816a_pcm(chip, 0)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if ((error = snd_ad1816a_mixer(chip)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) error = snd_ad1816a_timer(chip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (error < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (mpu_port[dev] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mpu_port[dev], 0, mpu_irq[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) NULL) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (fm_port[dev] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (snd_opl3_create(card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) fm_port[dev], fm_port[dev] + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) OPL3_HW_AUTO, 0, &opl3) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (error < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if ((error = snd_card_register(card)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pnp_set_card_drvdata(pcard, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static unsigned int ad1816a_devices;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) const struct pnp_card_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for ( ; dev < SNDRV_CARDS; dev++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!enable[dev])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) res = snd_card_ad1816a_probe(dev, card, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ad1816a_devices++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) snd_card_free(pnp_get_card_drvdata(pcard));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pnp_set_card_drvdata(pcard, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int snd_ad1816a_pnp_suspend(struct pnp_card_link *pcard,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct snd_card *card = pnp_get_card_drvdata(pcard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) snd_ad1816a_suspend(card->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int snd_ad1816a_pnp_resume(struct pnp_card_link *pcard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct snd_card *card = pnp_get_card_drvdata(pcard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) snd_ad1816a_resume(card->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static struct pnp_card_driver ad1816a_pnpc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .flags = PNP_DRIVER_RES_DISABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .name = "ad1816a",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .id_table = snd_ad1816a_pnpids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .probe = snd_ad1816a_pnp_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .remove = snd_ad1816a_pnp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .suspend = snd_ad1816a_pnp_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .resume = snd_ad1816a_pnp_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int __init alsa_card_ad1816a_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) err = pnp_register_card_driver(&ad1816a_pnpc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (!ad1816a_devices) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pnp_unregister_card_driver(&ad1816a_pnpc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) printk(KERN_ERR "no AD1816A based soundcards found.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #endif /* MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static void __exit alsa_card_ad1816a_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pnp_unregister_card_driver(&ad1816a_pnpc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) module_init(alsa_card_ad1816a_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) module_exit(alsa_card_ad1816a_exit)