aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/oxygen/oxygen_lib.c
diff options
context:
space:
mode:
authorGravatar Clemens Ladisch <clemens@ladisch.de> 2009-02-19 08:44:12 +0100
committerGravatar Takashi Iwai <tiwai@suse.de> 2009-02-19 10:22:26 +0100
commit1275d6f608abda23d101ada17dc39940192d4bc4 (patch)
tree17a9954dc31d2fa79494fe9b9b867a48a1dafc3e /sound/pci/oxygen/oxygen_lib.c
parentsound: oxygen: handle cards with broken EEPROM (diff)
downloadlinux-1275d6f608abda23d101ada17dc39940192d4bc4.tar.gz
linux-1275d6f608abda23d101ada17dc39940192d4bc4.tar.bz2
linux-1275d6f608abda23d101ada17dc39940192d4bc4.zip
sound: oxygen: automatically restore overwritten EEPROM
If the EEPROM was partially overwritten (which seems to happen before the OS is booted), restore its entire contents by deducing it from the remaining information. This does not have any effect on the Linux driver, which works even with incomplete information in the EEPROM, but it makes other drivers work again. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen/oxygen_lib.c')
-rw-r--r--sound/pci/oxygen/oxygen_lib.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index d83c3a957323..6e1cdd2fd768 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -272,6 +272,34 @@ oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
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;
@@ -532,6 +560,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
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;