aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/oxygen/oxygen.h3
-rw-r--r--sound/pci/oxygen/oxygen_io.c16
-rw-r--r--sound/pci/oxygen/oxygen_lib.c29
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);
190void oxygen_write_uart(struct oxygen *chip, u8 data); 192void oxygen_write_uart(struct oxygen *chip, u8 data);
191 193
192u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); 194u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index);
195void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value);
193 196
194static inline void oxygen_set_bits8(struct oxygen *chip, 197static 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
273void 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
275static 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
275static void oxygen_init(struct oxygen *chip) 303static 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;