^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) * Driver for audio on multifunction CS5535/6 companion device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) Jaya Kumar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based on Jaroslav Kysela and Takashi Iwai's examples.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This work was sponsored by CIS(M) Sdn Bhd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/rawmidi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "cs5535audio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DRIVER_NAME "cs5535audio"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static char *ac97_quirk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) module_param(ac97_quirk, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static const struct ac97_quirk ac97_quirks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #if 0 /* Not yet confirmed if all 5536 boards are HP only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .subvendor = PCI_VENDOR_ID_AMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .subdevice = PCI_DEVICE_ID_AMD_CS5536_AUDIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .name = "AMD RDK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .type = AC97_TUNE_HP_ONLY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) module_param_array(enable, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static const struct pci_device_id snd_cs5535audio_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) MODULE_DEVICE_TABLE(pci, snd_cs5535audio_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void wait_till_cmd_acked(struct cs5535audio *cs5535au, unsigned long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) tmp = cs_readl(cs5535au, ACC_CODEC_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!(tmp & CMD_NEW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) } while (--timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dev_err(cs5535au->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "Failure writing to cs5535 codec\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int regdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) regdata = ((unsigned int) reg) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) regdata |= ACC_CODEC_CNTL_RD_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) regdata |= CMD_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) cs_writel(cs5535au, ACC_CODEC_CNTL, regdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) wait_till_cmd_acked(cs5535au, 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) timeout = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) val = cs_readl(cs5535au, ACC_CODEC_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if ((val & STS_NEW) && reg == (val >> 24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) } while (--timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev_err(cs5535au->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "Failure reading codec reg 0x%x, Last value=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return (unsigned short) val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static void snd_cs5535audio_codec_write(struct cs5535audio *cs5535au,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned short reg, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned int regdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) regdata = ((unsigned int) reg) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) regdata |= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) regdata &= CMD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) regdata |= CMD_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) regdata &= ACC_CODEC_CNTL_WR_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) cs_writel(cs5535au, ACC_CODEC_CNTL, regdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) wait_till_cmd_acked(cs5535au, 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void snd_cs5535audio_ac97_codec_write(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned short reg, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct cs5535audio *cs5535au = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) snd_cs5535audio_codec_write(cs5535au, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static unsigned short snd_cs5535audio_ac97_codec_read(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct cs5535audio *cs5535au = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return snd_cs5535audio_codec_read(cs5535au, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct snd_card *card = cs5535au->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct snd_ac97_bus *pbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct snd_ac97_template ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct snd_ac97_bus_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .write = snd_cs5535audio_ac97_codec_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .read = snd_cs5535audio_ac97_codec_read,
^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 ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) memset(&ac97, 0, sizeof(ac97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ac97.scaps = AC97_SCAP_AUDIO | AC97_SCAP_SKIP_MODEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) | AC97_SCAP_POWER_SAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ac97.private_data = cs5535au;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ac97.pci = cs5535au->pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* set any OLPC-specific scaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) olpc_prequirks(card, &ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if ((err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dev_err(card->dev, "mixer failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) err = olpc_quirks(card, cs5535au->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dev_err(card->dev, "olpc quirks failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void process_bm0_irq(struct cs5535audio *cs5535au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u8 bm_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) spin_lock(&cs5535au->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) bm_stat = cs_readb(cs5535au, ACC_BM0_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) spin_unlock(&cs5535au->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (bm_stat & EOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) snd_pcm_period_elapsed(cs5535au->playback_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) dev_err(cs5535au->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) "unexpected bm0 irq src, bm_stat=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bm_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void process_bm1_irq(struct cs5535audio *cs5535au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u8 bm_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) spin_lock(&cs5535au->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) bm_stat = cs_readb(cs5535au, ACC_BM1_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) spin_unlock(&cs5535au->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (bm_stat & EOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) snd_pcm_period_elapsed(cs5535au->capture_substream);
^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) static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u16 acc_irq_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned char count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct cs5535audio *cs5535au = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (cs5535au == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) acc_irq_stat = cs_readw(cs5535au, ACC_IRQ_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!acc_irq_stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (count = 0; count < 4; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (acc_irq_stat & (1 << count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) switch (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case IRQ_STS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) cs_readl(cs5535au, ACC_GPIO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case WU_IRQ_STS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) cs_readl(cs5535au, ACC_GPIO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case BM0_IRQ_STS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) process_bm0_irq(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case BM1_IRQ_STS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) process_bm1_irq(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) dev_err(cs5535au->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "Unexpected irq src: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) acc_irq_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pci_set_power_state(cs5535au->pci, PCI_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (cs5535au->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) free_irq(cs5535au->irq, cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) pci_release_regions(cs5535au->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pci_disable_device(cs5535au->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) kfree(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int snd_cs5535audio_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct cs5535audio *cs5535au = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return snd_cs5535audio_free(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int snd_cs5535audio_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct cs5535audio **rcs5535au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct cs5535audio *cs5535au;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .dev_free = snd_cs5535audio_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) *rcs5535au = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev_warn(card->dev, "unable to get 32bit dma\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) goto pcifail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (cs5535au == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) goto pcifail;
^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) spin_lock_init(&cs5535au->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) cs5535au->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) cs5535au->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) cs5535au->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if ((err = pci_request_regions(pci, "CS5535 Audio")) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) kfree(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) goto pcifail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) cs5535au->port = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (request_irq(pci->irq, snd_cs5535audio_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) goto sndfail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) cs5535au->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) card->sync_irq = cs5535au->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) cs5535au, &ops)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) goto sndfail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *rcs5535au = cs5535au;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) sndfail: /* leave the device alive, just kill the snd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) snd_cs5535audio_free(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) pcifail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static int snd_cs5535audio_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct cs5535audio *cs5535au;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (dev >= SNDRV_CARDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!enable[dev]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 0, &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto probefail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) card->private_data = cs5535au;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if ((err = snd_cs5535audio_mixer(cs5535au)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto probefail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if ((err = snd_cs5535audio_pcm(cs5535au)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto probefail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) strcpy(card->driver, DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) strcpy(card->shortname, "CS5535 Audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) sprintf(card->longname, "%s %s at 0x%lx, irq %i",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) card->shortname, card->driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) cs5535au->port, cs5535au->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if ((err = snd_card_register(card)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) goto probefail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) pci_set_drvdata(pci, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) probefail_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static void snd_cs5535audio_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) olpc_quirks_cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) snd_card_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static struct pci_driver cs5535audio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .id_table = snd_cs5535audio_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .probe = snd_cs5535audio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .remove = snd_cs5535audio_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .pm = &snd_cs5535audio_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) module_pci_driver(cs5535audio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) MODULE_AUTHOR("Jaya Kumar");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) MODULE_DESCRIPTION("CS5535 Audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) MODULE_SUPPORTED_DEVICE("CS5535 Audio");