Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");