diff options
-rw-r--r-- | sound/pci/oxygen/oxygen.h | 3 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_io.c | 16 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 29 |
3 files changed, 48 insertions, 0 deletions
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index c500d48ea349..bd615dbffadb 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #define OXYGEN_IO_SIZE 0x100 | 19 | #define OXYGEN_IO_SIZE 0x100 |
20 | 20 | ||
21 | #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ | ||
22 | |||
21 | /* model-specific configuration of outputs/inputs */ | 23 | /* model-specific configuration of outputs/inputs */ |
22 | #define PLAYBACK_0_TO_I2S 0x0001 | 24 | #define PLAYBACK_0_TO_I2S 0x0001 |
23 | /* PLAYBACK_0_TO_AC97_0 not implemented */ | 25 | /* PLAYBACK_0_TO_AC97_0 not implemented */ |
@@ -190,6 +192,7 @@ void oxygen_reset_uart(struct oxygen *chip); | |||
190 | void oxygen_write_uart(struct oxygen *chip, u8 data); | 192 | void oxygen_write_uart(struct oxygen *chip, u8 data); |
191 | 193 | ||
192 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); | 194 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); |
195 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); | ||
193 | 196 | ||
194 | static inline void oxygen_set_bits8(struct oxygen *chip, | 197 | static inline void oxygen_set_bits8(struct oxygen *chip, |
195 | unsigned int reg, u8 value) | 198 | unsigned int reg, u8 value) |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 05f48ef1a442..c1eb923f2ac9 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
@@ -269,3 +269,19 @@ u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) | |||
269 | } | 269 | } |
270 | return oxygen_read16(chip, OXYGEN_EEPROM_DATA); | 270 | return oxygen_read16(chip, OXYGEN_EEPROM_DATA); |
271 | } | 271 | } |
272 | |||
273 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) | ||
274 | { | ||
275 | unsigned int timeout; | ||
276 | |||
277 | oxygen_write16(chip, OXYGEN_EEPROM_DATA, value); | ||
278 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, | ||
279 | index | OXYGEN_EEPROM_DIR_WRITE); | ||
280 | for (timeout = 0; timeout < 10; ++timeout) { | ||
281 | msleep(1); | ||
282 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) | ||
283 | & OXYGEN_EEPROM_BUSY)) | ||
284 | return; | ||
285 | } | ||
286 | snd_printk(KERN_ERR "EEPROM write timeout\n"); | ||
287 | } | ||
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[]) | |||
272 | return NULL; | 272 | return NULL; |
273 | } | 273 | } |
274 | 274 | ||
275 | static void oxygen_restore_eeprom(struct oxygen *chip, | ||
276 | const struct pci_device_id *id) | ||
277 | { | ||
278 | if (oxygen_read_eeprom(chip, 0) != OXYGEN_EEPROM_ID) { | ||
279 | /* | ||
280 | * This function gets called only when a known card model has | ||
281 | * been detected, i.e., we know there is a valid subsystem | ||
282 | * product ID at index 2 in the EEPROM. Therefore, we have | ||
283 | * been able to deduce the correct subsystem vendor ID, and | ||
284 | * this is enough information to restore the original EEPROM | ||
285 | * contents. | ||
286 | */ | ||
287 | oxygen_write_eeprom(chip, 1, id->subvendor); | ||
288 | oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID); | ||
289 | |||
290 | oxygen_set_bits8(chip, OXYGEN_MISC, | ||
291 | OXYGEN_MISC_WRITE_PCI_SUBID); | ||
292 | pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, | ||
293 | id->subvendor); | ||
294 | pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID, | ||
295 | id->subdevice); | ||
296 | oxygen_clear_bits8(chip, OXYGEN_MISC, | ||
297 | OXYGEN_MISC_WRITE_PCI_SUBID); | ||
298 | |||
299 | snd_printk(KERN_INFO "EEPROM ID restored\n"); | ||
300 | } | ||
301 | } | ||
302 | |||
275 | static void oxygen_init(struct oxygen *chip) | 303 | static void oxygen_init(struct oxygen *chip) |
276 | { | 304 | { |
277 | unsigned int i; | 305 | unsigned int i; |
@@ -532,6 +560,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
532 | err = -ENODEV; | 560 | err = -ENODEV; |
533 | goto err_pci_regions; | 561 | goto err_pci_regions; |
534 | } | 562 | } |
563 | oxygen_restore_eeprom(chip, pci_id); | ||
535 | err = get_model(chip, pci_id); | 564 | err = get_model(chip, pci_id); |
536 | if (err < 0) | 565 | if (err < 0) |
537 | goto err_pci_regions; | 566 | goto err_pci_regions; |