xref: /linux/sound/pci/oxygen/oxygen_lib.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
19c9cf6beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d0ce9946SClemens Ladisch /*
3d0ce9946SClemens Ladisch  * C-Media CMI8788 driver - main driver module
4d0ce9946SClemens Ladisch  *
5d0ce9946SClemens Ladisch  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
6d0ce9946SClemens Ladisch  */
7d0ce9946SClemens Ladisch 
8d0ce9946SClemens Ladisch #include <linux/delay.h>
9d0ce9946SClemens Ladisch #include <linux/interrupt.h>
10d0ce9946SClemens Ladisch #include <linux/mutex.h>
11d0ce9946SClemens Ladisch #include <linux/pci.h>
125a0e3ad6STejun Heo #include <linux/slab.h>
13da155d5bSPaul Gortmaker #include <linux/module.h>
14d0ce9946SClemens Ladisch #include <sound/ac97_codec.h>
15d0ce9946SClemens Ladisch #include <sound/asoundef.h>
16d0ce9946SClemens Ladisch #include <sound/core.h>
17d0ce9946SClemens Ladisch #include <sound/info.h>
18d0ce9946SClemens Ladisch #include <sound/mpu401.h>
19d0ce9946SClemens Ladisch #include <sound/pcm.h>
20d0ce9946SClemens Ladisch #include "oxygen.h"
21878ac3eeSClemens Ladisch #include "cm9780.h"
22d0ce9946SClemens Ladisch 
23d0ce9946SClemens Ladisch MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
24d0ce9946SClemens Ladisch MODULE_DESCRIPTION("C-Media CMI8788 helper library");
25d023dc0aSClemens Ladisch MODULE_LICENSE("GPL v2");
26d0ce9946SClemens Ladisch 
27a69bb3c3SClemens Ladisch #define DRIVER "oxygen"
28d0ce9946SClemens Ladisch 
oxygen_uart_input_ready(struct oxygen * chip)29397b1dccSClemens Ladisch static inline int oxygen_uart_input_ready(struct oxygen *chip)
30397b1dccSClemens Ladisch {
31397b1dccSClemens Ladisch 	return !(oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_RX_EMPTY);
32397b1dccSClemens Ladisch }
33397b1dccSClemens Ladisch 
oxygen_read_uart(struct oxygen * chip)34397b1dccSClemens Ladisch static void oxygen_read_uart(struct oxygen *chip)
35397b1dccSClemens Ladisch {
36397b1dccSClemens Ladisch 	if (unlikely(!oxygen_uart_input_ready(chip))) {
37397b1dccSClemens Ladisch 		/* no data, but read it anyway to clear the interrupt */
38397b1dccSClemens Ladisch 		oxygen_read8(chip, OXYGEN_MPU401);
39397b1dccSClemens Ladisch 		return;
40397b1dccSClemens Ladisch 	}
41397b1dccSClemens Ladisch 	do {
42397b1dccSClemens Ladisch 		u8 data = oxygen_read8(chip, OXYGEN_MPU401);
43397b1dccSClemens Ladisch 		if (data == MPU401_ACK)
44397b1dccSClemens Ladisch 			continue;
45397b1dccSClemens Ladisch 		if (chip->uart_input_count >= ARRAY_SIZE(chip->uart_input))
46397b1dccSClemens Ladisch 			chip->uart_input_count = 0;
47397b1dccSClemens Ladisch 		chip->uart_input[chip->uart_input_count++] = data;
48397b1dccSClemens Ladisch 	} while (oxygen_uart_input_ready(chip));
49397b1dccSClemens Ladisch 	if (chip->model.uart_input)
50397b1dccSClemens Ladisch 		chip->model.uart_input(chip);
51397b1dccSClemens Ladisch }
52397b1dccSClemens Ladisch 
oxygen_interrupt(int dummy,void * dev_id)53d0ce9946SClemens Ladisch static irqreturn_t oxygen_interrupt(int dummy, void *dev_id)
54d0ce9946SClemens Ladisch {
55d0ce9946SClemens Ladisch 	struct oxygen *chip = dev_id;
56d0ce9946SClemens Ladisch 	unsigned int status, clear, elapsed_streams, i;
57d0ce9946SClemens Ladisch 
58d0ce9946SClemens Ladisch 	status = oxygen_read16(chip, OXYGEN_INTERRUPT_STATUS);
59d0ce9946SClemens Ladisch 	if (!status)
60d0ce9946SClemens Ladisch 		return IRQ_NONE;
61d0ce9946SClemens Ladisch 
62d0ce9946SClemens Ladisch 	spin_lock(&chip->reg_lock);
63d0ce9946SClemens Ladisch 
64d0ce9946SClemens Ladisch 	clear = status & (OXYGEN_CHANNEL_A |
65d0ce9946SClemens Ladisch 			  OXYGEN_CHANNEL_B |
66d0ce9946SClemens Ladisch 			  OXYGEN_CHANNEL_C |
67d0ce9946SClemens Ladisch 			  OXYGEN_CHANNEL_SPDIF |
68d0ce9946SClemens Ladisch 			  OXYGEN_CHANNEL_MULTICH |
69d0ce9946SClemens Ladisch 			  OXYGEN_CHANNEL_AC97 |
70c2353a08SClemens Ladisch 			  OXYGEN_INT_SPDIF_IN_DETECT |
711e821dd2SClemens Ladisch 			  OXYGEN_INT_GPIO |
721e821dd2SClemens Ladisch 			  OXYGEN_INT_AC97);
73d0ce9946SClemens Ladisch 	if (clear) {
74c2353a08SClemens Ladisch 		if (clear & OXYGEN_INT_SPDIF_IN_DETECT)
75c2353a08SClemens Ladisch 			chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT;
76d0ce9946SClemens Ladisch 		oxygen_write16(chip, OXYGEN_INTERRUPT_MASK,
77d0ce9946SClemens Ladisch 			       chip->interrupt_mask & ~clear);
78d0ce9946SClemens Ladisch 		oxygen_write16(chip, OXYGEN_INTERRUPT_MASK,
79d0ce9946SClemens Ladisch 			       chip->interrupt_mask);
80d0ce9946SClemens Ladisch 	}
81d0ce9946SClemens Ladisch 
82d0ce9946SClemens Ladisch 	elapsed_streams = status & chip->pcm_running;
83d0ce9946SClemens Ladisch 
84d0ce9946SClemens Ladisch 	spin_unlock(&chip->reg_lock);
85d0ce9946SClemens Ladisch 
86d0ce9946SClemens Ladisch 	for (i = 0; i < PCM_COUNT; ++i)
87d0ce9946SClemens Ladisch 		if ((elapsed_streams & (1 << i)) && chip->streams[i])
88d0ce9946SClemens Ladisch 			snd_pcm_period_elapsed(chip->streams[i]);
89d0ce9946SClemens Ladisch 
90c2353a08SClemens Ladisch 	if (status & OXYGEN_INT_SPDIF_IN_DETECT) {
91d0ce9946SClemens Ladisch 		spin_lock(&chip->reg_lock);
92d0ce9946SClemens Ladisch 		i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
937f0b8946SClemens Ladisch 		if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT |
947f0b8946SClemens Ladisch 			 OXYGEN_SPDIF_RATE_INT)) {
957f0b8946SClemens Ladisch 			/* write the interrupt bit(s) to clear */
96d0ce9946SClemens Ladisch 			oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i);
97d0ce9946SClemens Ladisch 			schedule_work(&chip->spdif_input_bits_work);
98d0ce9946SClemens Ladisch 		}
99d0ce9946SClemens Ladisch 		spin_unlock(&chip->reg_lock);
100d0ce9946SClemens Ladisch 	}
101d0ce9946SClemens Ladisch 
102d0ce9946SClemens Ladisch 	if (status & OXYGEN_INT_GPIO)
1037c014159SClemens Ladisch 		schedule_work(&chip->gpio_work);
104d0ce9946SClemens Ladisch 
105397b1dccSClemens Ladisch 	if (status & OXYGEN_INT_MIDI) {
106397b1dccSClemens Ladisch 		if (chip->midi)
107d0ce9946SClemens Ladisch 			snd_mpu401_uart_interrupt(0, chip->midi->private_data);
108397b1dccSClemens Ladisch 		else
109397b1dccSClemens Ladisch 			oxygen_read_uart(chip);
110397b1dccSClemens Ladisch 	}
111d0ce9946SClemens Ladisch 
1121e821dd2SClemens Ladisch 	if (status & OXYGEN_INT_AC97)
1131e821dd2SClemens Ladisch 		wake_up(&chip->ac97_waitqueue);
1141e821dd2SClemens Ladisch 
115d0ce9946SClemens Ladisch 	return IRQ_HANDLED;
116d0ce9946SClemens Ladisch }
117d0ce9946SClemens Ladisch 
oxygen_spdif_input_bits_changed(struct work_struct * work)118d0ce9946SClemens Ladisch static void oxygen_spdif_input_bits_changed(struct work_struct *work)
119d0ce9946SClemens Ladisch {
120d0ce9946SClemens Ladisch 	struct oxygen *chip = container_of(work, struct oxygen,
121d0ce9946SClemens Ladisch 					   spdif_input_bits_work);
1227f0b8946SClemens Ladisch 	u32 reg;
123d0ce9946SClemens Ladisch 
1247f0b8946SClemens Ladisch 	/*
1257f0b8946SClemens Ladisch 	 * This function gets called when there is new activity on the SPDIF
1267f0b8946SClemens Ladisch 	 * input, or when we lose lock on the input signal, or when the rate
1277f0b8946SClemens Ladisch 	 * changes.
1287f0b8946SClemens Ladisch 	 */
1297f0b8946SClemens Ladisch 	msleep(1);
130d0ce9946SClemens Ladisch 	spin_lock_irq(&chip->reg_lock);
1317f0b8946SClemens Ladisch 	reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
1327f0b8946SClemens Ladisch 	if ((reg & (OXYGEN_SPDIF_SENSE_STATUS |
1337f0b8946SClemens Ladisch 		    OXYGEN_SPDIF_LOCK_STATUS))
1347f0b8946SClemens Ladisch 	    == OXYGEN_SPDIF_SENSE_STATUS) {
1357f0b8946SClemens Ladisch 		/*
1367f0b8946SClemens Ladisch 		 * If we detect activity on the SPDIF input but cannot lock to
1377f0b8946SClemens Ladisch 		 * a signal, the clock bit is likely to be wrong.
1387f0b8946SClemens Ladisch 		 */
1397f0b8946SClemens Ladisch 		reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK;
1407f0b8946SClemens Ladisch 		oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg);
141d0ce9946SClemens Ladisch 		spin_unlock_irq(&chip->reg_lock);
142d0ce9946SClemens Ladisch 		msleep(1);
143d0ce9946SClemens Ladisch 		spin_lock_irq(&chip->reg_lock);
1447f0b8946SClemens Ladisch 		reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
1457f0b8946SClemens Ladisch 		if ((reg & (OXYGEN_SPDIF_SENSE_STATUS |
1467f0b8946SClemens Ladisch 			    OXYGEN_SPDIF_LOCK_STATUS))
1477f0b8946SClemens Ladisch 		    == OXYGEN_SPDIF_SENSE_STATUS) {
1487f0b8946SClemens Ladisch 			/* nothing detected with either clock; give up */
1497f0b8946SClemens Ladisch 			if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK)
1507f0b8946SClemens Ladisch 			    == OXYGEN_SPDIF_IN_CLOCK_192) {
1517f0b8946SClemens Ladisch 				/*
1527f0b8946SClemens Ladisch 				 * Reset clock to <= 96 kHz because this is
1537f0b8946SClemens Ladisch 				 * more likely to be received next time.
1547f0b8946SClemens Ladisch 				 */
1557f0b8946SClemens Ladisch 				reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK;
1567f0b8946SClemens Ladisch 				reg |= OXYGEN_SPDIF_IN_CLOCK_96;
1577f0b8946SClemens Ladisch 				oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg);
158d0ce9946SClemens Ladisch 			}
159d0ce9946SClemens Ladisch 		}
1607f0b8946SClemens Ladisch 	}
1617f0b8946SClemens Ladisch 	spin_unlock_irq(&chip->reg_lock);
162d0ce9946SClemens Ladisch 
16301a3affbSClemens Ladisch 	if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) {
164d0ce9946SClemens Ladisch 		spin_lock_irq(&chip->reg_lock);
165c2353a08SClemens Ladisch 		chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT;
166d0ce9946SClemens Ladisch 		oxygen_write16(chip, OXYGEN_INTERRUPT_MASK,
167d0ce9946SClemens Ladisch 			       chip->interrupt_mask);
168d0ce9946SClemens Ladisch 		spin_unlock_irq(&chip->reg_lock);
169d0ce9946SClemens Ladisch 
1707f0b8946SClemens Ladisch 		/*
1717f0b8946SClemens Ladisch 		 * We don't actually know that any channel status bits have
1727f0b8946SClemens Ladisch 		 * changed, but let's send a notification just to be sure.
1737f0b8946SClemens Ladisch 		 */
174d0ce9946SClemens Ladisch 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
17501a3affbSClemens Ladisch 			       &chip->controls[CONTROL_SPDIF_INPUT_BITS]->id);
176d0ce9946SClemens Ladisch 	}
177d0ce9946SClemens Ladisch }
178d0ce9946SClemens Ladisch 
oxygen_gpio_changed(struct work_struct * work)1797c014159SClemens Ladisch static void oxygen_gpio_changed(struct work_struct *work)
1807c014159SClemens Ladisch {
1817c014159SClemens Ladisch 	struct oxygen *chip = container_of(work, struct oxygen, gpio_work);
1827c014159SClemens Ladisch 
1839bd6a73aSClemens Ladisch 	if (chip->model.gpio_changed)
1849bd6a73aSClemens Ladisch 		chip->model.gpio_changed(chip);
1857c014159SClemens Ladisch }
1867c014159SClemens Ladisch 
oxygen_proc_read(struct snd_info_entry * entry,struct snd_info_buffer * buffer)187d0ce9946SClemens Ladisch static void oxygen_proc_read(struct snd_info_entry *entry,
188d0ce9946SClemens Ladisch 			     struct snd_info_buffer *buffer)
189d0ce9946SClemens Ladisch {
190d0ce9946SClemens Ladisch 	struct oxygen *chip = entry->private_data;
191d0ce9946SClemens Ladisch 	int i, j;
192d0ce9946SClemens Ladisch 
193e2943efaSClemens Ladisch 	switch (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_PACKAGE_ID_MASK) {
194e2943efaSClemens Ladisch 	case OXYGEN_PACKAGE_ID_8786: i = '6'; break;
195e2943efaSClemens Ladisch 	case OXYGEN_PACKAGE_ID_8787: i = '7'; break;
196e2943efaSClemens Ladisch 	case OXYGEN_PACKAGE_ID_8788: i = '8'; break;
197e2943efaSClemens Ladisch 	default:                     i = '?'; break;
198e2943efaSClemens Ladisch 	}
199e2943efaSClemens Ladisch 	snd_iprintf(buffer, "CMI878%c:\n", i);
200c1365007SClemens Ladisch 	for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) {
201d0ce9946SClemens Ladisch 		snd_iprintf(buffer, "%02x:", i);
202d0ce9946SClemens Ladisch 		for (j = 0; j < 0x10; ++j)
203d0ce9946SClemens Ladisch 			snd_iprintf(buffer, " %02x", oxygen_read8(chip, i + j));
204d0ce9946SClemens Ladisch 		snd_iprintf(buffer, "\n");
205d0ce9946SClemens Ladisch 	}
206d0ce9946SClemens Ladisch 	if (mutex_lock_interruptible(&chip->mutex) < 0)
207d0ce9946SClemens Ladisch 		return;
20831c77643SClemens Ladisch 	if (chip->has_ac97_0) {
2099719fcaaSClemens Ladisch 		snd_iprintf(buffer, "\nAC97:\n");
210d0ce9946SClemens Ladisch 		for (i = 0; i < 0x80; i += 0x10) {
211d0ce9946SClemens Ladisch 			snd_iprintf(buffer, "%02x:", i);
212d0ce9946SClemens Ladisch 			for (j = 0; j < 0x10; j += 2)
213d0ce9946SClemens Ladisch 				snd_iprintf(buffer, " %04x",
214d0ce9946SClemens Ladisch 					    oxygen_read_ac97(chip, 0, i + j));
215d0ce9946SClemens Ladisch 			snd_iprintf(buffer, "\n");
216d0ce9946SClemens Ladisch 		}
21731c77643SClemens Ladisch 	}
21831c77643SClemens Ladisch 	if (chip->has_ac97_1) {
2199719fcaaSClemens Ladisch 		snd_iprintf(buffer, "\nAC97 2:\n");
22031c77643SClemens Ladisch 		for (i = 0; i < 0x80; i += 0x10) {
22131c77643SClemens Ladisch 			snd_iprintf(buffer, "%02x:", i);
22231c77643SClemens Ladisch 			for (j = 0; j < 0x10; j += 2)
22331c77643SClemens Ladisch 				snd_iprintf(buffer, " %04x",
22431c77643SClemens Ladisch 					    oxygen_read_ac97(chip, 1, i + j));
22531c77643SClemens Ladisch 			snd_iprintf(buffer, "\n");
22631c77643SClemens Ladisch 		}
22731c77643SClemens Ladisch 	}
228d0ce9946SClemens Ladisch 	mutex_unlock(&chip->mutex);
2299719fcaaSClemens Ladisch 	if (chip->model.dump_registers)
2309719fcaaSClemens Ladisch 		chip->model.dump_registers(chip, buffer);
231d0ce9946SClemens Ladisch }
232d0ce9946SClemens Ladisch 
oxygen_proc_init(struct oxygen * chip)233f007dc04STakashi Iwai static void oxygen_proc_init(struct oxygen *chip)
234d0ce9946SClemens Ladisch {
23547f2769bSTakashi Iwai 	snd_card_ro_proc_new(chip->card, "oxygen", chip, oxygen_proc_read);
236d0ce9946SClemens Ladisch }
237d0ce9946SClemens Ladisch 
23830459d7bSClemens Ladisch static const struct pci_device_id *
oxygen_search_pci_id(struct oxygen * chip,const struct pci_device_id ids[])23930459d7bSClemens Ladisch oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
24030459d7bSClemens Ladisch {
24130459d7bSClemens Ladisch 	u16 subdevice;
24230459d7bSClemens Ladisch 
24330459d7bSClemens Ladisch 	/*
24430459d7bSClemens Ladisch 	 * Make sure the EEPROM pins are available, i.e., not used for SPI.
24530459d7bSClemens Ladisch 	 * (This function is called before we initialize or use SPI.)
24630459d7bSClemens Ladisch 	 */
24730459d7bSClemens Ladisch 	oxygen_clear_bits8(chip, OXYGEN_FUNCTION,
24830459d7bSClemens Ladisch 			   OXYGEN_FUNCTION_ENABLE_SPI_4_5);
24930459d7bSClemens Ladisch 	/*
25030459d7bSClemens Ladisch 	 * Read the subsystem device ID directly from the EEPROM, because the
25130459d7bSClemens Ladisch 	 * chip didn't if the first EEPROM word was overwritten.
25230459d7bSClemens Ladisch 	 */
25330459d7bSClemens Ladisch 	subdevice = oxygen_read_eeprom(chip, 2);
25492653453SClemens Ladisch 	/* use default ID if EEPROM is missing */
25531f86bacSClemens Ladisch 	if (subdevice == 0xffff && oxygen_read_eeprom(chip, 1) == 0xffff)
25692653453SClemens Ladisch 		subdevice = 0x8788;
25730459d7bSClemens Ladisch 	/*
25830459d7bSClemens Ladisch 	 * We use only the subsystem device ID for searching because it is
25930459d7bSClemens Ladisch 	 * unique even without the subsystem vendor ID, which may have been
26030459d7bSClemens Ladisch 	 * overwritten in the EEPROM.
26130459d7bSClemens Ladisch 	 */
26230459d7bSClemens Ladisch 	for (; ids->vendor; ++ids)
26330459d7bSClemens Ladisch 		if (ids->subdevice == subdevice &&
26430459d7bSClemens Ladisch 		    ids->driver_data != BROKEN_EEPROM_DRIVER_DATA)
26530459d7bSClemens Ladisch 			return ids;
26630459d7bSClemens Ladisch 	return NULL;
26730459d7bSClemens Ladisch }
26830459d7bSClemens Ladisch 
oxygen_restore_eeprom(struct oxygen * chip,const struct pci_device_id * id)2691275d6f6SClemens Ladisch static void oxygen_restore_eeprom(struct oxygen *chip,
2701275d6f6SClemens Ladisch 				  const struct pci_device_id *id)
2711275d6f6SClemens Ladisch {
27287b61902SClemens Ladisch 	u16 eeprom_id;
27387b61902SClemens Ladisch 
27487b61902SClemens Ladisch 	eeprom_id = oxygen_read_eeprom(chip, 0);
27587b61902SClemens Ladisch 	if (eeprom_id != OXYGEN_EEPROM_ID &&
27687b61902SClemens Ladisch 	    (eeprom_id != 0xffff || id->subdevice != 0x8788)) {
2771275d6f6SClemens Ladisch 		/*
2781275d6f6SClemens Ladisch 		 * This function gets called only when a known card model has
2791275d6f6SClemens Ladisch 		 * been detected, i.e., we know there is a valid subsystem
2801275d6f6SClemens Ladisch 		 * product ID at index 2 in the EEPROM.  Therefore, we have
2811275d6f6SClemens Ladisch 		 * been able to deduce the correct subsystem vendor ID, and
2821275d6f6SClemens Ladisch 		 * this is enough information to restore the original EEPROM
2831275d6f6SClemens Ladisch 		 * contents.
2841275d6f6SClemens Ladisch 		 */
2851275d6f6SClemens Ladisch 		oxygen_write_eeprom(chip, 1, id->subvendor);
2861275d6f6SClemens Ladisch 		oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID);
2871275d6f6SClemens Ladisch 
2881275d6f6SClemens Ladisch 		oxygen_set_bits8(chip, OXYGEN_MISC,
2891275d6f6SClemens Ladisch 				 OXYGEN_MISC_WRITE_PCI_SUBID);
2901275d6f6SClemens Ladisch 		pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID,
2911275d6f6SClemens Ladisch 				      id->subvendor);
2921275d6f6SClemens Ladisch 		pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID,
2931275d6f6SClemens Ladisch 				      id->subdevice);
2941275d6f6SClemens Ladisch 		oxygen_clear_bits8(chip, OXYGEN_MISC,
2951275d6f6SClemens Ladisch 				   OXYGEN_MISC_WRITE_PCI_SUBID);
2961275d6f6SClemens Ladisch 
29703d3ac21STakashi Iwai 		dev_info(chip->card->dev, "EEPROM ID restored\n");
2981275d6f6SClemens Ladisch 	}
2991275d6f6SClemens Ladisch }
3001275d6f6SClemens Ladisch 
configure_pcie_bridge(struct pci_dev * pci)3017cb4ced5SClemens Ladisch static void configure_pcie_bridge(struct pci_dev *pci)
302362bc24dSClemens Ladisch {
303a5a33533SClemens Ladisch 	enum { PEX811X, PI7C9X110, XIO2001 };
3047cb4ced5SClemens Ladisch 	static const struct pci_device_id bridge_ids[] = {
305ebebeeceSClemens Ladisch 		{ PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X },
306ebebeeceSClemens Ladisch 		{ PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X },
3077cb4ced5SClemens Ladisch 		{ PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 },
308a5a33533SClemens Ladisch 		{ PCI_VDEVICE(TI, 0x8240), .driver_data = XIO2001 },
3097cb4ced5SClemens Ladisch 		{ }
3107cb4ced5SClemens Ladisch 	};
3117cb4ced5SClemens Ladisch 	struct pci_dev *bridge;
3127cb4ced5SClemens Ladisch 	const struct pci_device_id *id;
313362bc24dSClemens Ladisch 	u32 tmp;
314362bc24dSClemens Ladisch 
3157cb4ced5SClemens Ladisch 	if (!pci->bus || !pci->bus->self)
3167cb4ced5SClemens Ladisch 		return;
3177cb4ced5SClemens Ladisch 	bridge = pci->bus->self;
3187cb4ced5SClemens Ladisch 
3197cb4ced5SClemens Ladisch 	id = pci_match_id(bridge_ids, bridge);
3207cb4ced5SClemens Ladisch 	if (!id)
3217cb4ced5SClemens Ladisch 		return;
3227cb4ced5SClemens Ladisch 
3237cb4ced5SClemens Ladisch 	switch (id->driver_data) {
324ebebeeceSClemens Ladisch 	case PEX811X:	/* PLX PEX8111/PEX8112 PCIe/PCI bridge */
325ebebeeceSClemens Ladisch 		pci_read_config_dword(bridge, 0x48, &tmp);
326ebebeeceSClemens Ladisch 		tmp |= 1;	/* enable blind prefetching */
327ebebeeceSClemens Ladisch 		tmp |= 1 << 11;	/* enable beacon generation */
328ebebeeceSClemens Ladisch 		pci_write_config_dword(bridge, 0x48, tmp);
329ebebeeceSClemens Ladisch 
330ebebeeceSClemens Ladisch 		pci_write_config_dword(bridge, 0x84, 0x0c);
331ebebeeceSClemens Ladisch 		pci_read_config_dword(bridge, 0x88, &tmp);
332ebebeeceSClemens Ladisch 		tmp &= ~(7 << 27);
333ebebeeceSClemens Ladisch 		tmp |= 2 << 27;	/* set prefetch size to 128 bytes */
334ebebeeceSClemens Ladisch 		pci_write_config_dword(bridge, 0x88, tmp);
335ebebeeceSClemens Ladisch 		break;
336ebebeeceSClemens Ladisch 
3377cb4ced5SClemens Ladisch 	case PI7C9X110:	/* Pericom PI7C9X110 PCIe/PCI bridge */
3387cb4ced5SClemens Ladisch 		pci_read_config_dword(bridge, 0x40, &tmp);
3397cb4ced5SClemens Ladisch 		tmp |= 1;	/* park the PCI arbiter to the sound chip */
3407cb4ced5SClemens Ladisch 		pci_write_config_dword(bridge, 0x40, tmp);
341362bc24dSClemens Ladisch 		break;
342a5a33533SClemens Ladisch 
343a5a33533SClemens Ladisch 	case XIO2001: /* Texas Instruments XIO2001 PCIe/PCI bridge */
344a5a33533SClemens Ladisch 		pci_read_config_dword(bridge, 0xe8, &tmp);
345a5a33533SClemens Ladisch 		tmp &= ~0xf;	/* request length limit: 64 bytes */
346a5a33533SClemens Ladisch 		tmp &= ~(0xf << 8);
347a5a33533SClemens Ladisch 		tmp |= 1 << 8;	/* request count limit: one buffer */
348a5a33533SClemens Ladisch 		pci_write_config_dword(bridge, 0xe8, tmp);
349a5a33533SClemens Ladisch 		break;
350362bc24dSClemens Ladisch 	}
351362bc24dSClemens Ladisch }
352362bc24dSClemens Ladisch 
oxygen_init(struct oxygen * chip)353f007dc04STakashi Iwai static void oxygen_init(struct oxygen *chip)
354d0ce9946SClemens Ladisch {
355d0ce9946SClemens Ladisch 	unsigned int i;
356d0ce9946SClemens Ladisch 
357d0ce9946SClemens Ladisch 	chip->dac_routing = 1;
358d0ce9946SClemens Ladisch 	for (i = 0; i < 8; ++i)
3599bd6a73aSClemens Ladisch 		chip->dac_volume[i] = chip->model.dac_volume_min;
360e983532eSClemens Ladisch 	chip->dac_mute = 1;
3614bccb403STom Yan 	chip->spdif_playback_enable = 0;
362d0ce9946SClemens Ladisch 	chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
363d0ce9946SClemens Ladisch 		(IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
364d0ce9946SClemens Ladisch 	chip->spdif_pcm_bits = chip->spdif_bits;
365d0ce9946SClemens Ladisch 
366a1f80fcfSClemens Ladisch 	if (!(oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2))
367c2353a08SClemens Ladisch 		oxygen_set_bits8(chip, OXYGEN_MISC,
368c2353a08SClemens Ladisch 				 OXYGEN_MISC_PCI_MEM_W_1_CLOCK);
369d0ce9946SClemens Ladisch 
37031c77643SClemens Ladisch 	i = oxygen_read16(chip, OXYGEN_AC97_CONTROL);
37131c77643SClemens Ladisch 	chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0;
37231c77643SClemens Ladisch 	chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0;
37331c77643SClemens Ladisch 
374b78e3dbbSClemens Ladisch 	oxygen_write8_masked(chip, OXYGEN_FUNCTION,
37587eedd2fSClemens Ladisch 			     OXYGEN_FUNCTION_RESET_CODEC |
3769bd6a73aSClemens Ladisch 			     chip->model.function_flags,
37787eedd2fSClemens Ladisch 			     OXYGEN_FUNCTION_RESET_CODEC |
37887eedd2fSClemens Ladisch 			     OXYGEN_FUNCTION_2WIRE_SPI_MASK |
37987eedd2fSClemens Ladisch 			     OXYGEN_FUNCTION_ENABLE_SPI_4_5);
380b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_DMA_STATUS, 0);
381b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0);
382b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_PLAY_CHANNELS,
383b78e3dbbSClemens Ladisch 		      OXYGEN_PLAY_CHANNELS_2 |
384b78e3dbbSClemens Ladisch 		      OXYGEN_DMA_A_BURST_8 |
385b78e3dbbSClemens Ladisch 		      OXYGEN_DMA_MULTICH_BURST_8);
386b78e3dbbSClemens Ladisch 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
387db12b8e3SClemens Ladisch 	oxygen_write8_masked(chip, OXYGEN_MISC,
3889bd6a73aSClemens Ladisch 			     chip->model.misc_flags,
389b78e3dbbSClemens Ladisch 			     OXYGEN_MISC_WRITE_PCI_SUBID |
390b78e3dbbSClemens Ladisch 			     OXYGEN_MISC_REC_C_FROM_SPDIF |
391b78e3dbbSClemens Ladisch 			     OXYGEN_MISC_REC_B_FROM_AC97 |
392db12b8e3SClemens Ladisch 			     OXYGEN_MISC_REC_A_FROM_MULTICH |
393db12b8e3SClemens Ladisch 			     OXYGEN_MISC_MIDI);
394b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_REC_FORMAT,
395b78e3dbbSClemens Ladisch 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) |
396b78e3dbbSClemens Ladisch 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) |
397b78e3dbbSClemens Ladisch 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_C_SHIFT));
398b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_PLAY_FORMAT,
399b78e3dbbSClemens Ladisch 		      (OXYGEN_FORMAT_16 << OXYGEN_SPDIF_FORMAT_SHIFT) |
400b78e3dbbSClemens Ladisch 		      (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
401b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
402c9946b2cSClemens Ladisch 	oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
4035b8bf2a5SClemens Ladisch 		       OXYGEN_RATE_48000 |
4045b8bf2a5SClemens Ladisch 		       chip->model.dac_i2s_format |
4055b8bf2a5SClemens Ladisch 		       OXYGEN_I2S_MCLK(chip->model.dac_mclks) |
4065b8bf2a5SClemens Ladisch 		       OXYGEN_I2S_BITS_16 |
4075b8bf2a5SClemens Ladisch 		       OXYGEN_I2S_MASTER |
4085b8bf2a5SClemens Ladisch 		       OXYGEN_I2S_BCLK_64);
409d76596b1SClemens Ladisch 	if (chip->model.device_config & CAPTURE_0_FROM_I2S_1)
410c9946b2cSClemens Ladisch 		oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
4115b8bf2a5SClemens Ladisch 			       OXYGEN_RATE_48000 |
4125b8bf2a5SClemens Ladisch 			       chip->model.adc_i2s_format |
4135b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MCLK(chip->model.adc_mclks) |
4145b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_BITS_16 |
4155b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MASTER |
4165b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_BCLK_64);
41743dd89c7SClemens Ladisch 	else
41843dd89c7SClemens Ladisch 		oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
4195b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MASTER |
4205b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MUTE_MCLK);
421d76596b1SClemens Ladisch 	if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 |
42243dd89c7SClemens Ladisch 					 CAPTURE_2_FROM_I2S_2))
423c9946b2cSClemens Ladisch 		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
4245b8bf2a5SClemens Ladisch 			       OXYGEN_RATE_48000 |
4255b8bf2a5SClemens Ladisch 			       chip->model.adc_i2s_format |
4265b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MCLK(chip->model.adc_mclks) |
4275b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_BITS_16 |
4285b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MASTER |
4295b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_BCLK_64);
43043dd89c7SClemens Ladisch 	else
43143dd89c7SClemens Ladisch 		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
4325b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MASTER |
4335b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MUTE_MCLK);
4340902fbb9SClemens Ladisch 	if (chip->model.device_config & CAPTURE_3_FROM_I2S_3)
4350902fbb9SClemens Ladisch 		oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
4360902fbb9SClemens Ladisch 			       OXYGEN_RATE_48000 |
4370902fbb9SClemens Ladisch 			       chip->model.adc_i2s_format |
4380902fbb9SClemens Ladisch 			       OXYGEN_I2S_MCLK(chip->model.adc_mclks) |
4390902fbb9SClemens Ladisch 			       OXYGEN_I2S_BITS_16 |
4400902fbb9SClemens Ladisch 			       OXYGEN_I2S_MASTER |
4410902fbb9SClemens Ladisch 			       OXYGEN_I2S_BCLK_64);
4420902fbb9SClemens Ladisch 	else
443c9946b2cSClemens Ladisch 		oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
4445b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MASTER |
4455b8bf2a5SClemens Ladisch 			       OXYGEN_I2S_MUTE_MCLK);
4461d98c7d4SClemens Ladisch 	oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
4471d98c7d4SClemens Ladisch 			    OXYGEN_SPDIF_OUT_ENABLE |
4481d98c7d4SClemens Ladisch 			    OXYGEN_SPDIF_LOOPBACK);
449d76596b1SClemens Ladisch 	if (chip->model.device_config & CAPTURE_1_FROM_SPDIF)
4507f0b8946SClemens Ladisch 		oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
4517f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_SENSE_MASK |
4527f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_LOCK_MASK |
4537f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_RATE_MASK |
4547f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_LOCK_PAR |
4557f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_IN_CLOCK_96,
4567f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_SENSE_MASK |
4577f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_LOCK_MASK |
4587f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_RATE_MASK |
4597f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_SENSE_PAR |
4607f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_LOCK_PAR |
4617f0b8946SClemens Ladisch 				      OXYGEN_SPDIF_IN_CLOCK_MASK);
4621d98c7d4SClemens Ladisch 	else
4631d98c7d4SClemens Ladisch 		oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
4641d98c7d4SClemens Ladisch 				    OXYGEN_SPDIF_SENSE_MASK |
4651d98c7d4SClemens Ladisch 				    OXYGEN_SPDIF_LOCK_MASK |
4661d98c7d4SClemens Ladisch 				    OXYGEN_SPDIF_RATE_MASK);
467d0ce9946SClemens Ladisch 	oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
4684a4bc53bSClemens Ladisch 	oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
4694a4bc53bSClemens Ladisch 		       OXYGEN_2WIRE_LENGTH_8 |
4704a4bc53bSClemens Ladisch 		       OXYGEN_2WIRE_INTERRUPT_MASK |
4714a4bc53bSClemens Ladisch 		       OXYGEN_2WIRE_SPEED_STANDARD);
472b78e3dbbSClemens Ladisch 	oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
473b78e3dbbSClemens Ladisch 	oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
474b78e3dbbSClemens Ladisch 	oxygen_write16(chip, OXYGEN_GPIO_INTERRUPT_MASK, 0);
475c9946b2cSClemens Ladisch 	oxygen_write16(chip, OXYGEN_PLAY_ROUTING,
476b78e3dbbSClemens Ladisch 		       OXYGEN_PLAY_MULTICH_I2S_DAC |
477b78e3dbbSClemens Ladisch 		       OXYGEN_PLAY_SPDIF_SPDIF |
478c9946b2cSClemens Ladisch 		       (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |
479c9946b2cSClemens Ladisch 		       (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
480c9946b2cSClemens Ladisch 		       (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
481c9946b2cSClemens Ladisch 		       (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT));
482c9946b2cSClemens Ladisch 	oxygen_write8(chip, OXYGEN_REC_ROUTING,
483c9946b2cSClemens Ladisch 		      OXYGEN_REC_A_ROUTE_I2S_ADC_1 |
484b78e3dbbSClemens Ladisch 		      OXYGEN_REC_B_ROUTE_I2S_ADC_2 |
485c9946b2cSClemens Ladisch 		      OXYGEN_REC_C_ROUTE_SPDIF);
486c9946b2cSClemens Ladisch 	oxygen_write8(chip, OXYGEN_ADC_MONITOR, 0);
487c9946b2cSClemens Ladisch 	oxygen_write8(chip, OXYGEN_A_MONITOR_ROUTING,
488c9946b2cSClemens Ladisch 		      (0 << OXYGEN_A_MONITOR_ROUTE_0_SHIFT) |
489c9946b2cSClemens Ladisch 		      (1 << OXYGEN_A_MONITOR_ROUTE_1_SHIFT) |
490c9946b2cSClemens Ladisch 		      (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) |
491c9946b2cSClemens Ladisch 		      (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT));
492d0ce9946SClemens Ladisch 
4931d98c7d4SClemens Ladisch 	if (chip->has_ac97_0 | chip->has_ac97_1)
4941e821dd2SClemens Ladisch 		oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
4951e821dd2SClemens Ladisch 			      OXYGEN_AC97_INT_READ_DONE |
4961e821dd2SClemens Ladisch 			      OXYGEN_AC97_INT_WRITE_DONE);
4971d98c7d4SClemens Ladisch 	else
4981d98c7d4SClemens Ladisch 		oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0);
499b78e3dbbSClemens Ladisch 	oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0);
500b78e3dbbSClemens Ladisch 	oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0);
501b78e3dbbSClemens Ladisch 	if (!(chip->has_ac97_0 | chip->has_ac97_1))
502b78e3dbbSClemens Ladisch 		oxygen_set_bits16(chip, OXYGEN_AC97_CONTROL,
503b78e3dbbSClemens Ladisch 				  OXYGEN_AC97_CLOCK_DISABLE);
504b78e3dbbSClemens Ladisch 	if (!chip->has_ac97_0) {
505b78e3dbbSClemens Ladisch 		oxygen_set_bits16(chip, OXYGEN_AC97_CONTROL,
506b78e3dbbSClemens Ladisch 				  OXYGEN_AC97_NO_CODEC_0);
507b78e3dbbSClemens Ladisch 	} else {
508d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_RESET, 0);
509d0ce9946SClemens Ladisch 		msleep(1);
510878ac3eeSClemens Ladisch 		oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_SETUP,
511878ac3eeSClemens Ladisch 				     CM9780_GPIO0IO | CM9780_GPIO1IO);
512878ac3eeSClemens Ladisch 		oxygen_ac97_set_bits(chip, 0, CM9780_MIXER,
513878ac3eeSClemens Ladisch 				     CM9780_BSTSEL | CM9780_STRO_MIC |
514878ac3eeSClemens Ladisch 				     CM9780_MIX2FR | CM9780_PCBSW);
515878ac3eeSClemens Ladisch 		oxygen_ac97_set_bits(chip, 0, CM9780_JACK,
516878ac3eeSClemens Ladisch 				     CM9780_RSOE | CM9780_CBOE |
517878ac3eeSClemens Ladisch 				     CM9780_SSOE | CM9780_FROE |
518878ac3eeSClemens Ladisch 				     CM9780_MIC2MIC | CM9780_LI2LI);
519d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_MASTER, 0x0000);
520d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_PC_BEEP, 0x8000);
521d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_MIC, 0x8808);
522d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_LINE, 0x0808);
523d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_CD, 0x8808);
524d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_VIDEO, 0x8808);
525d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_AUX, 0x8808);
526d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000);
527d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080);
528d0ce9946SClemens Ladisch 		oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080);
529e97f7999SClemens Ladisch 		oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS,
530e97f7999SClemens Ladisch 				       CM9780_GPO0);
531d0ce9946SClemens Ladisch 		/* power down unused ADCs and DACs */
532d0ce9946SClemens Ladisch 		oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN,
533d0ce9946SClemens Ladisch 				     AC97_PD_PR0 | AC97_PD_PR1);
534d0ce9946SClemens Ladisch 		oxygen_ac97_set_bits(chip, 0, AC97_EXTENDED_STATUS,
535d0ce9946SClemens Ladisch 				     AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK);
536d0ce9946SClemens Ladisch 	}
537b78e3dbbSClemens Ladisch 	if (chip->has_ac97_1) {
538b78e3dbbSClemens Ladisch 		oxygen_set_bits32(chip, OXYGEN_AC97_OUT_CONFIG,
539b78e3dbbSClemens Ladisch 				  OXYGEN_AC97_CODEC1_SLOT3 |
540b78e3dbbSClemens Ladisch 				  OXYGEN_AC97_CODEC1_SLOT4);
541b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_RESET, 0);
542b78e3dbbSClemens Ladisch 		msleep(1);
543b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_MASTER, 0x0000);
544b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_HEADPHONE, 0x8000);
545b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_PC_BEEP, 0x8000);
546b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_MIC, 0x8808);
547b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_LINE, 0x8808);
548b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_CD, 0x8808);
549b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_VIDEO, 0x8808);
550b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_AUX, 0x8808);
551b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_PCM, 0x0808);
552b78e3dbbSClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_REC_SEL, 0x0000);
553a3601560SClemens Ladisch 		oxygen_write_ac97(chip, 1, AC97_REC_GAIN, 0x0000);
554b78e3dbbSClemens Ladisch 		oxygen_ac97_set_bits(chip, 1, 0x6a, 0x0040);
555b78e3dbbSClemens Ladisch 	}
55631c77643SClemens Ladisch }
557d0ce9946SClemens Ladisch 
oxygen_shutdown(struct oxygen * chip)5584c25b932SClemens Ladisch static void oxygen_shutdown(struct oxygen *chip)
559d0ce9946SClemens Ladisch {
560d0ce9946SClemens Ladisch 	spin_lock_irq(&chip->reg_lock);
561d0ce9946SClemens Ladisch 	chip->interrupt_mask = 0;
562d0ce9946SClemens Ladisch 	chip->pcm_running = 0;
563d0ce9946SClemens Ladisch 	oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
564d0ce9946SClemens Ladisch 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
565d0ce9946SClemens Ladisch 	spin_unlock_irq(&chip->reg_lock);
5664c25b932SClemens Ladisch }
5674c25b932SClemens Ladisch 
oxygen_card_free(struct snd_card * card)5684c25b932SClemens Ladisch static void oxygen_card_free(struct snd_card *card)
5694c25b932SClemens Ladisch {
5704c25b932SClemens Ladisch 	struct oxygen *chip = card->private_data;
5714c25b932SClemens Ladisch 
5724c25b932SClemens Ladisch 	oxygen_shutdown(chip);
57343829731STejun Heo 	flush_work(&chip->spdif_input_bits_work);
57443829731STejun Heo 	flush_work(&chip->gpio_work);
5759bd6a73aSClemens Ladisch 	chip->model.cleanup(chip);
576d0ce9946SClemens Ladisch 	mutex_destroy(&chip->mutex);
577d0ce9946SClemens Ladisch }
578d0ce9946SClemens Ladisch 
__oxygen_pci_probe(struct pci_dev * pci,int index,char * id,struct module * owner,const struct pci_device_id * ids,int (* get_model)(struct oxygen * chip,const struct pci_device_id * id))579*6ebc16e2STakashi Iwai static int __oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
580bb718588SClemens Ladisch 		     struct module *owner,
58130459d7bSClemens Ladisch 		     const struct pci_device_id *ids,
58230459d7bSClemens Ladisch 		     int (*get_model)(struct oxygen *chip,
58330459d7bSClemens Ladisch 				      const struct pci_device_id *id
58430459d7bSClemens Ladisch 				     )
58530459d7bSClemens Ladisch 		    )
586d0ce9946SClemens Ladisch {
587d0ce9946SClemens Ladisch 	struct snd_card *card;
588d0ce9946SClemens Ladisch 	struct oxygen *chip;
58930459d7bSClemens Ladisch 	const struct pci_device_id *pci_id;
590d0ce9946SClemens Ladisch 	int err;
591d0ce9946SClemens Ladisch 
592596ae97aSTakashi Iwai 	err = snd_devm_card_new(&pci->dev, index, id, owner,
59360c5772bSTakashi Iwai 				sizeof(*chip), &card);
594e58de7baSTakashi Iwai 	if (err < 0)
595e58de7baSTakashi Iwai 		return err;
596d0ce9946SClemens Ladisch 
597d0ce9946SClemens Ladisch 	chip = card->private_data;
598d0ce9946SClemens Ladisch 	chip->card = card;
599d0ce9946SClemens Ladisch 	chip->pci = pci;
600d0ce9946SClemens Ladisch 	chip->irq = -1;
601d0ce9946SClemens Ladisch 	spin_lock_init(&chip->reg_lock);
602d0ce9946SClemens Ladisch 	mutex_init(&chip->mutex);
603d0ce9946SClemens Ladisch 	INIT_WORK(&chip->spdif_input_bits_work,
604d0ce9946SClemens Ladisch 		  oxygen_spdif_input_bits_changed);
6057c014159SClemens Ladisch 	INIT_WORK(&chip->gpio_work, oxygen_gpio_changed);
6061e821dd2SClemens Ladisch 	init_waitqueue_head(&chip->ac97_waitqueue);
607d0ce9946SClemens Ladisch 
608596ae97aSTakashi Iwai 	err = pcim_enable_device(pci);
609d0ce9946SClemens Ladisch 	if (err < 0)
610596ae97aSTakashi Iwai 		return err;
611d0ce9946SClemens Ladisch 
612a69bb3c3SClemens Ladisch 	err = pci_request_regions(pci, DRIVER);
613d0ce9946SClemens Ladisch 	if (err < 0) {
61403d3ac21STakashi Iwai 		dev_err(card->dev, "cannot reserve PCI resources\n");
615596ae97aSTakashi Iwai 		return err;
616d0ce9946SClemens Ladisch 	}
617d0ce9946SClemens Ladisch 
618d0ce9946SClemens Ladisch 	if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) ||
619c1365007SClemens Ladisch 	    pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) {
62003d3ac21STakashi Iwai 		dev_err(card->dev, "invalid PCI I/O range\n");
621596ae97aSTakashi Iwai 		return -ENXIO;
622d0ce9946SClemens Ladisch 	}
623d0ce9946SClemens Ladisch 	chip->addr = pci_resource_start(pci, 0);
624d0ce9946SClemens Ladisch 
62530459d7bSClemens Ladisch 	pci_id = oxygen_search_pci_id(chip, ids);
626596ae97aSTakashi Iwai 	if (!pci_id)
627596ae97aSTakashi Iwai 		return -ENODEV;
628596ae97aSTakashi Iwai 
6291275d6f6SClemens Ladisch 	oxygen_restore_eeprom(chip, pci_id);
63030459d7bSClemens Ladisch 	err = get_model(chip, pci_id);
63130459d7bSClemens Ladisch 	if (err < 0)
632596ae97aSTakashi Iwai 		return err;
63330459d7bSClemens Ladisch 
6346ed91157SClemens Ladisch 	if (chip->model.model_data_size) {
635596ae97aSTakashi Iwai 		chip->model_data = devm_kzalloc(&pci->dev,
636596ae97aSTakashi Iwai 						chip->model.model_data_size,
6376ed91157SClemens Ladisch 						GFP_KERNEL);
638596ae97aSTakashi Iwai 		if (!chip->model_data)
639596ae97aSTakashi Iwai 			return -ENOMEM;
6406ed91157SClemens Ladisch 	}
6416ed91157SClemens Ladisch 
642d0ce9946SClemens Ladisch 	pci_set_master(pci);
643d0ce9946SClemens Ladisch 	card->private_free = oxygen_card_free;
644d0ce9946SClemens Ladisch 
6457cb4ced5SClemens Ladisch 	configure_pcie_bridge(pci);
646d0ce9946SClemens Ladisch 	oxygen_init(chip);
6479bd6a73aSClemens Ladisch 	chip->model.init(chip);
648d0ce9946SClemens Ladisch 
649596ae97aSTakashi Iwai 	err = devm_request_irq(&pci->dev, pci->irq, oxygen_interrupt,
650596ae97aSTakashi Iwai 			       IRQF_SHARED, KBUILD_MODNAME, chip);
651d0ce9946SClemens Ladisch 	if (err < 0) {
65203d3ac21STakashi Iwai 		dev_err(card->dev, "cannot grab interrupt %d\n", pci->irq);
653596ae97aSTakashi Iwai 		return err;
654d0ce9946SClemens Ladisch 	}
655d0ce9946SClemens Ladisch 	chip->irq = pci->irq;
656bf17d20aSTakashi Iwai 	card->sync_irq = chip->irq;
657d0ce9946SClemens Ladisch 
6589bd6a73aSClemens Ladisch 	strcpy(card->driver, chip->model.chip);
6599bd6a73aSClemens Ladisch 	strcpy(card->shortname, chip->model.shortname);
660a1f80fcfSClemens Ladisch 	sprintf(card->longname, "%s at %#lx, irq %i",
661a1f80fcfSClemens Ladisch 		chip->model.longname, chip->addr, chip->irq);
6629bd6a73aSClemens Ladisch 	strcpy(card->mixername, chip->model.chip);
6639bd6a73aSClemens Ladisch 	snd_component_add(card, chip->model.chip);
664d0ce9946SClemens Ladisch 
665d0ce9946SClemens Ladisch 	err = oxygen_pcm_init(chip);
666d0ce9946SClemens Ladisch 	if (err < 0)
667596ae97aSTakashi Iwai 		return err;
668d0ce9946SClemens Ladisch 
669d0ce9946SClemens Ladisch 	err = oxygen_mixer_init(chip);
670d0ce9946SClemens Ladisch 	if (err < 0)
671596ae97aSTakashi Iwai 		return err;
672d0ce9946SClemens Ladisch 
673dbbbd674SClemens Ladisch 	if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
674dba8b469SClemens Ladisch 		unsigned int info_flags =
675dba8b469SClemens Ladisch 				MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK;
676dbbbd674SClemens Ladisch 		if (chip->model.device_config & MIDI_OUTPUT)
677dbbbd674SClemens Ladisch 			info_flags |= MPU401_INFO_OUTPUT;
678dbbbd674SClemens Ladisch 		if (chip->model.device_config & MIDI_INPUT)
679dbbbd674SClemens Ladisch 			info_flags |= MPU401_INFO_INPUT;
680d0ce9946SClemens Ladisch 		err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
681d0ce9946SClemens Ladisch 					  chip->addr + OXYGEN_MPU401,
682dba8b469SClemens Ladisch 					  info_flags, -1, &chip->midi);
683d0ce9946SClemens Ladisch 		if (err < 0)
684596ae97aSTakashi Iwai 			return err;
685d0ce9946SClemens Ladisch 	}
686d0ce9946SClemens Ladisch 
687d0ce9946SClemens Ladisch 	oxygen_proc_init(chip);
688d0ce9946SClemens Ladisch 
689d0ce9946SClemens Ladisch 	spin_lock_irq(&chip->reg_lock);
690d76596b1SClemens Ladisch 	if (chip->model.device_config & CAPTURE_1_FROM_SPDIF)
6911d98c7d4SClemens Ladisch 		chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT;
6921d98c7d4SClemens Ladisch 	if (chip->has_ac97_0 | chip->has_ac97_1)
6931d98c7d4SClemens Ladisch 		chip->interrupt_mask |= OXYGEN_INT_AC97;
694d0ce9946SClemens Ladisch 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
695d0ce9946SClemens Ladisch 	spin_unlock_irq(&chip->reg_lock);
696d0ce9946SClemens Ladisch 
697d0ce9946SClemens Ladisch 	err = snd_card_register(card);
698d0ce9946SClemens Ladisch 	if (err < 0)
699596ae97aSTakashi Iwai 		return err;
700d0ce9946SClemens Ladisch 
701d0ce9946SClemens Ladisch 	pci_set_drvdata(pci, card);
702d0ce9946SClemens Ladisch 	return 0;
703d0ce9946SClemens Ladisch }
704*6ebc16e2STakashi Iwai 
oxygen_pci_probe(struct pci_dev * pci,int index,char * id,struct module * owner,const struct pci_device_id * ids,int (* get_model)(struct oxygen * chip,const struct pci_device_id * id))705*6ebc16e2STakashi Iwai int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
706*6ebc16e2STakashi Iwai 		     struct module *owner,
707*6ebc16e2STakashi Iwai 		     const struct pci_device_id *ids,
708*6ebc16e2STakashi Iwai 		     int (*get_model)(struct oxygen *chip,
709*6ebc16e2STakashi Iwai 				      const struct pci_device_id *id))
710*6ebc16e2STakashi Iwai {
711*6ebc16e2STakashi Iwai 	return snd_card_free_on_error(&pci->dev,
712*6ebc16e2STakashi Iwai 				      __oxygen_pci_probe(pci, index, id, owner, ids, get_model));
713*6ebc16e2STakashi Iwai }
714d0ce9946SClemens Ladisch EXPORT_SYMBOL(oxygen_pci_probe);
715d0ce9946SClemens Ladisch 
716c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
oxygen_pci_suspend(struct device * dev)71768cb2b55STakashi Iwai static int oxygen_pci_suspend(struct device *dev)
7184a4bc53bSClemens Ladisch {
71968cb2b55STakashi Iwai 	struct snd_card *card = dev_get_drvdata(dev);
7204a4bc53bSClemens Ladisch 	struct oxygen *chip = card->private_data;
72117bc4815STakashi Iwai 	unsigned int saved_interrupt_mask;
7224a4bc53bSClemens Ladisch 
7234a4bc53bSClemens Ladisch 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
7244a4bc53bSClemens Ladisch 
7259bd6a73aSClemens Ladisch 	if (chip->model.suspend)
7269bd6a73aSClemens Ladisch 		chip->model.suspend(chip);
7274a4bc53bSClemens Ladisch 
7284a4bc53bSClemens Ladisch 	spin_lock_irq(&chip->reg_lock);
7294a4bc53bSClemens Ladisch 	saved_interrupt_mask = chip->interrupt_mask;
7304a4bc53bSClemens Ladisch 	chip->interrupt_mask = 0;
7314a4bc53bSClemens Ladisch 	oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
7324a4bc53bSClemens Ladisch 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
7334a4bc53bSClemens Ladisch 	spin_unlock_irq(&chip->reg_lock);
7344a4bc53bSClemens Ladisch 
73543829731STejun Heo 	flush_work(&chip->spdif_input_bits_work);
73643829731STejun Heo 	flush_work(&chip->gpio_work);
7374a4bc53bSClemens Ladisch 	chip->interrupt_mask = saved_interrupt_mask;
7384a4bc53bSClemens Ladisch 	return 0;
7394a4bc53bSClemens Ladisch }
7404a4bc53bSClemens Ladisch 
7414a4bc53bSClemens Ladisch static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = {
7424a4bc53bSClemens Ladisch 	0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff,
7434a4bc53bSClemens Ladisch 	0x00300000, 0x00000fe4, 0x0ff7001f, 0x00000000
7444a4bc53bSClemens Ladisch };
7454a4bc53bSClemens Ladisch static const u32 ac97_registers_to_restore[2][0x40 / 32] = {
7464a4bc53bSClemens Ladisch 	{ 0x18284fa2, 0x03060000 },
7474a4bc53bSClemens Ladisch 	{ 0x00007fa6, 0x00200000 }
7484a4bc53bSClemens Ladisch };
7494a4bc53bSClemens Ladisch 
is_bit_set(const u32 * bitmap,unsigned int bit)7504a4bc53bSClemens Ladisch static inline int is_bit_set(const u32 *bitmap, unsigned int bit)
7514a4bc53bSClemens Ladisch {
7524a4bc53bSClemens Ladisch 	return bitmap[bit / 32] & (1 << (bit & 31));
7534a4bc53bSClemens Ladisch }
7544a4bc53bSClemens Ladisch 
oxygen_restore_ac97(struct oxygen * chip,unsigned int codec)7554a4bc53bSClemens Ladisch static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec)
7564a4bc53bSClemens Ladisch {
7574a4bc53bSClemens Ladisch 	unsigned int i;
7584a4bc53bSClemens Ladisch 
7594a4bc53bSClemens Ladisch 	oxygen_write_ac97(chip, codec, AC97_RESET, 0);
7604a4bc53bSClemens Ladisch 	msleep(1);
7614a4bc53bSClemens Ladisch 	for (i = 1; i < 0x40; ++i)
7624a4bc53bSClemens Ladisch 		if (is_bit_set(ac97_registers_to_restore[codec], i))
7634a4bc53bSClemens Ladisch 			oxygen_write_ac97(chip, codec, i * 2,
7644a4bc53bSClemens Ladisch 					  chip->saved_ac97_registers[codec][i]);
7654a4bc53bSClemens Ladisch }
7664a4bc53bSClemens Ladisch 
oxygen_pci_resume(struct device * dev)76768cb2b55STakashi Iwai static int oxygen_pci_resume(struct device *dev)
7684a4bc53bSClemens Ladisch {
76968cb2b55STakashi Iwai 	struct snd_card *card = dev_get_drvdata(dev);
7704a4bc53bSClemens Ladisch 	struct oxygen *chip = card->private_data;
7714a4bc53bSClemens Ladisch 	unsigned int i;
7724a4bc53bSClemens Ladisch 
7734a4bc53bSClemens Ladisch 	oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
7744a4bc53bSClemens Ladisch 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
7754a4bc53bSClemens Ladisch 	for (i = 0; i < OXYGEN_IO_SIZE; ++i)
7764a4bc53bSClemens Ladisch 		if (is_bit_set(registers_to_restore, i))
7774a4bc53bSClemens Ladisch 			oxygen_write8(chip, i, chip->saved_registers._8[i]);
7784a4bc53bSClemens Ladisch 	if (chip->has_ac97_0)
7794a4bc53bSClemens Ladisch 		oxygen_restore_ac97(chip, 0);
7804a4bc53bSClemens Ladisch 	if (chip->has_ac97_1)
7814a4bc53bSClemens Ladisch 		oxygen_restore_ac97(chip, 1);
7824a4bc53bSClemens Ladisch 
7839bd6a73aSClemens Ladisch 	if (chip->model.resume)
7849bd6a73aSClemens Ladisch 		chip->model.resume(chip);
7854a4bc53bSClemens Ladisch 
7864a4bc53bSClemens Ladisch 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
7874a4bc53bSClemens Ladisch 
7884a4bc53bSClemens Ladisch 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
7894a4bc53bSClemens Ladisch 	return 0;
7904a4bc53bSClemens Ladisch }
79168cb2b55STakashi Iwai 
79268cb2b55STakashi Iwai SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume);
79368cb2b55STakashi Iwai EXPORT_SYMBOL(oxygen_pci_pm);
794c7561cd8STakashi Iwai #endif /* CONFIG_PM_SLEEP */
7954c25b932SClemens Ladisch 
oxygen_pci_shutdown(struct pci_dev * pci)7964c25b932SClemens Ladisch void oxygen_pci_shutdown(struct pci_dev *pci)
7974c25b932SClemens Ladisch {
7984c25b932SClemens Ladisch 	struct snd_card *card = pci_get_drvdata(pci);
7994c25b932SClemens Ladisch 	struct oxygen *chip = card->private_data;
8004c25b932SClemens Ladisch 
8014c25b932SClemens Ladisch 	oxygen_shutdown(chip);
8024c25b932SClemens Ladisch 	chip->model.cleanup(chip);
8034c25b932SClemens Ladisch }
8044c25b932SClemens Ladisch EXPORT_SYMBOL(oxygen_pci_shutdown);
805