aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/oxygen_lib.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-02-19 02:42:44 -0500
committerTakashi Iwai <tiwai@suse.de>2009-02-19 04:22:25 -0500
commit30459d7b1843cbdea56ca120c8cac10dc5613e90 (patch)
tree47341d43931193917c28dab16eaf7e1a12b2b6d6 /sound/pci/oxygen/oxygen_lib.c
parenta69bb3c3fe0881d986ec78e253cb8a6bb9c28230 (diff)
sound: oxygen: handle cards with broken EEPROM
Under as yet unknown circumstances, the first word of the sound card's EEPROM gets overwritten. When this has happened, we cannot rely on the subsystem IDs that the kernel reads from the PCI configuration registers. Instead, we read the IDs directly from the EEPROM and do the ID matching manually. Because the model-specific driver cannot determine the model before calling oxygen_pci_probe(), that function now gets a get_model() callback as parameter. The customizing of the model structure, which was formerly done by the probe() callback, also has moved into get_model(). 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.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 516d94ad2bbb..d83c3a957323 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -244,6 +244,34 @@ static void oxygen_proc_init(struct oxygen *chip)
244#define oxygen_proc_init(chip) 244#define oxygen_proc_init(chip)
245#endif 245#endif
246 246
247static const struct pci_device_id *
248oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
249{
250 u16 subdevice;
251
252 /*
253 * Make sure the EEPROM pins are available, i.e., not used for SPI.
254 * (This function is called before we initialize or use SPI.)
255 */
256 oxygen_clear_bits8(chip, OXYGEN_FUNCTION,
257 OXYGEN_FUNCTION_ENABLE_SPI_4_5);
258 /*
259 * Read the subsystem device ID directly from the EEPROM, because the
260 * chip didn't if the first EEPROM word was overwritten.
261 */
262 subdevice = oxygen_read_eeprom(chip, 2);
263 /*
264 * We use only the subsystem device ID for searching because it is
265 * unique even without the subsystem vendor ID, which may have been
266 * overwritten in the EEPROM.
267 */
268 for (; ids->vendor; ++ids)
269 if (ids->subdevice == subdevice &&
270 ids->driver_data != BROKEN_EEPROM_DRIVER_DATA)
271 return ids;
272 return NULL;
273}
274
247static void oxygen_init(struct oxygen *chip) 275static void oxygen_init(struct oxygen *chip)
248{ 276{
249 unsigned int i; 277 unsigned int i;
@@ -455,11 +483,15 @@ static void oxygen_card_free(struct snd_card *card)
455 483
456int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, 484int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
457 struct module *owner, 485 struct module *owner,
458 const struct oxygen_model *model, 486 const struct pci_device_id *ids,
459 unsigned long driver_data) 487 int (*get_model)(struct oxygen *chip,
488 const struct pci_device_id *id
489 )
490 )
460{ 491{
461 struct snd_card *card; 492 struct snd_card *card;
462 struct oxygen *chip; 493 struct oxygen *chip;
494 const struct pci_device_id *pci_id;
463 int err; 495 int err;
464 496
465 err = snd_card_create(index, id, owner, sizeof(*chip), &card); 497 err = snd_card_create(index, id, owner, sizeof(*chip), &card);
@@ -470,7 +502,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
470 chip->card = card; 502 chip->card = card;
471 chip->pci = pci; 503 chip->pci = pci;
472 chip->irq = -1; 504 chip->irq = -1;
473 chip->model = *model;
474 spin_lock_init(&chip->reg_lock); 505 spin_lock_init(&chip->reg_lock);
475 mutex_init(&chip->mutex); 506 mutex_init(&chip->mutex);
476 INIT_WORK(&chip->spdif_input_bits_work, 507 INIT_WORK(&chip->spdif_input_bits_work,
@@ -496,6 +527,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
496 } 527 }
497 chip->addr = pci_resource_start(pci, 0); 528 chip->addr = pci_resource_start(pci, 0);
498 529
530 pci_id = oxygen_search_pci_id(chip, ids);
531 if (!pci_id) {
532 err = -ENODEV;
533 goto err_pci_regions;
534 }
535 err = get_model(chip, pci_id);
536 if (err < 0)
537 goto err_pci_regions;
538
499 if (chip->model.model_data_size) { 539 if (chip->model.model_data_size) {
500 chip->model_data = kmalloc(chip->model.model_data_size, 540 chip->model_data = kmalloc(chip->model.model_data_size,
501 GFP_KERNEL); 541 GFP_KERNEL);
@@ -509,11 +549,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
509 snd_card_set_dev(card, &pci->dev); 549 snd_card_set_dev(card, &pci->dev);
510 card->private_free = oxygen_card_free; 550 card->private_free = oxygen_card_free;
511 551
512 if (chip->model.probe) {
513 err = chip->model.probe(chip, driver_data);
514 if (err < 0)
515 goto err_card;
516 }
517 oxygen_init(chip); 552 oxygen_init(chip);
518 chip->model.init(chip); 553 chip->model.init(chip);
519 554