From 1cd1ffcc4848b6b0028f3cb1821cb481816f309e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 19 Feb 2009 08:44:12 +0100 Subject: [PATCH] --- yaml --- r: 133179 b: refs/heads/master c: 1275d6f608abda23d101ada17dc39940192d4bc4 h: refs/heads/master i: 133177: b00f316d8bf176ab36bd31f0f02ace2985acedac 133175: ac784c37b75906cb7c0968989f96805e1a05a0dd v: v3 --- [refs] | 2 +- trunk/sound/pci/oxygen/oxygen.h | 3 +++ trunk/sound/pci/oxygen/oxygen_io.c | 16 ++++++++++++++++ trunk/sound/pci/oxygen/oxygen_lib.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index d0b687702fbb..c2de3d646253 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 30459d7b1843cbdea56ca120c8cac10dc5613e90 +refs/heads/master: 1275d6f608abda23d101ada17dc39940192d4bc4 diff --git a/trunk/sound/pci/oxygen/oxygen.h b/trunk/sound/pci/oxygen/oxygen.h index c500d48ea349..bd615dbffadb 100644 --- a/trunk/sound/pci/oxygen/oxygen.h +++ b/trunk/sound/pci/oxygen/oxygen.h @@ -18,6 +18,8 @@ #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 */ @@ -190,6 +192,7 @@ void oxygen_reset_uart(struct oxygen *chip); 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) diff --git a/trunk/sound/pci/oxygen/oxygen_io.c b/trunk/sound/pci/oxygen/oxygen_io.c index 05f48ef1a442..c1eb923f2ac9 100644 --- a/trunk/sound/pci/oxygen/oxygen_io.c +++ b/trunk/sound/pci/oxygen/oxygen_io.c @@ -269,3 +269,19 @@ u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) } 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"); +} diff --git a/trunk/sound/pci/oxygen/oxygen_lib.c b/trunk/sound/pci/oxygen/oxygen_lib.c index d83c3a957323..6e1cdd2fd768 100644 --- a/trunk/sound/pci/oxygen/oxygen_lib.c +++ b/trunk/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;