#define OXYGEN_IO_SIZE 0x100
+#define OXYGEN_EEPROM_ID 0x434d /* "CM" */
+
/* model-specific configuration of outputs/inputs */
#define PLAYBACK_0_TO_I2S 0x0001
/* PLAYBACK_0_TO_AC97_0 not implemented */
void oxygen_write_uart(struct oxygen *chip, u8 data);
u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index);
+void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value);
static inline void oxygen_set_bits8(struct oxygen *chip,
unsigned int reg, u8 value)
}
return oxygen_read16(chip, OXYGEN_EEPROM_DATA);
}
+
+void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value)
+{
+ unsigned int timeout;
+
+ oxygen_write16(chip, OXYGEN_EEPROM_DATA, value);
+ oxygen_write8(chip, OXYGEN_EEPROM_CONTROL,
+ index | OXYGEN_EEPROM_DIR_WRITE);
+ for (timeout = 0; timeout < 10; ++timeout) {
+ msleep(1);
+ if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS)
+ & OXYGEN_EEPROM_BUSY))
+ return;
+ }
+ snd_printk(KERN_ERR "EEPROM write timeout\n");
+}
return NULL;
}
+static void oxygen_restore_eeprom(struct oxygen *chip,
+ const struct pci_device_id *id)
+{
+ if (oxygen_read_eeprom(chip, 0) != OXYGEN_EEPROM_ID) {
+ /*
+ * This function gets called only when a known card model has
+ * been detected, i.e., we know there is a valid subsystem
+ * product ID at index 2 in the EEPROM. Therefore, we have
+ * been able to deduce the correct subsystem vendor ID, and
+ * this is enough information to restore the original EEPROM
+ * contents.
+ */
+ oxygen_write_eeprom(chip, 1, id->subvendor);
+ oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID);
+
+ oxygen_set_bits8(chip, OXYGEN_MISC,
+ OXYGEN_MISC_WRITE_PCI_SUBID);
+ pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID,
+ id->subvendor);
+ pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID,
+ id->subdevice);
+ oxygen_clear_bits8(chip, OXYGEN_MISC,
+ OXYGEN_MISC_WRITE_PCI_SUBID);
+
+ snd_printk(KERN_INFO "EEPROM ID restored\n");
+ }
+}
+
static void oxygen_init(struct oxygen *chip)
{
unsigned int i;
err = -ENODEV;
goto err_pci_regions;
}
+ oxygen_restore_eeprom(chip, pci_id);
err = get_model(chip, pci_id);
if (err < 0)
goto err_pci_regions;