aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/oxygen_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/oxygen/oxygen_lib.c')
-rw-r--r--sound/pci/oxygen/oxygen_lib.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index fad03d64e3ad..e5ebe56fb0c5 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -308,25 +308,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip,
308 } 308 }
309} 309}
310 310
311static void pci_bridge_magic(void) 311static void configure_pcie_bridge(struct pci_dev *pci)
312{ 312{
313 struct pci_dev *pci = NULL; 313 enum { PEX811X, PI7C9X110 };
314 static const struct pci_device_id bridge_ids[] = {
315 { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X },
316 { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X },
317 { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 },
318 { }
319 };
320 struct pci_dev *bridge;
321 const struct pci_device_id *id;
314 u32 tmp; 322 u32 tmp;
315 323
316 for (;;) { 324 if (!pci->bus || !pci->bus->self)
317 /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */ 325 return;
318 pci = pci_get_device(0x12d8, 0xe110, pci); 326 bridge = pci->bus->self;
319 if (!pci) 327
320 break; 328 id = pci_match_id(bridge_ids, bridge);
321 /* 329 if (!id)
322 * ... configure its secondary internal arbiter to park to 330 return;
323 * the secondary port, instead of to the last master. 331
324 */ 332 switch (id->driver_data) {
325 if (!pci_read_config_dword(pci, 0x40, &tmp)) { 333 case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */
326 tmp |= 1; 334 pci_read_config_dword(bridge, 0x48, &tmp);
327 pci_write_config_dword(pci, 0x40, tmp); 335 tmp |= 1; /* enable blind prefetching */
328 } 336 tmp |= 1 << 11; /* enable beacon generation */
329 /* Why? Try asking C-Media. */ 337 pci_write_config_dword(bridge, 0x48, tmp);
338
339 pci_write_config_dword(bridge, 0x84, 0x0c);
340 pci_read_config_dword(bridge, 0x88, &tmp);
341 tmp &= ~(7 << 27);
342 tmp |= 2 << 27; /* set prefetch size to 128 bytes */
343 pci_write_config_dword(bridge, 0x88, tmp);
344 break;
345
346 case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */
347 pci_read_config_dword(bridge, 0x40, &tmp);
348 tmp |= 1; /* park the PCI arbiter to the sound chip */
349 pci_write_config_dword(bridge, 0x40, tmp);
350 break;
330 } 351 }
331} 352}
332 353
@@ -519,16 +540,21 @@ static void oxygen_init(struct oxygen *chip)
519 } 540 }
520} 541}
521 542
522static void oxygen_card_free(struct snd_card *card) 543static void oxygen_shutdown(struct oxygen *chip)
523{ 544{
524 struct oxygen *chip = card->private_data;
525
526 spin_lock_irq(&chip->reg_lock); 545 spin_lock_irq(&chip->reg_lock);
527 chip->interrupt_mask = 0; 546 chip->interrupt_mask = 0;
528 chip->pcm_running = 0; 547 chip->pcm_running = 0;
529 oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); 548 oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
530 oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); 549 oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
531 spin_unlock_irq(&chip->reg_lock); 550 spin_unlock_irq(&chip->reg_lock);
551}
552
553static void oxygen_card_free(struct snd_card *card)
554{
555 struct oxygen *chip = card->private_data;
556
557 oxygen_shutdown(chip);
532 if (chip->irq >= 0) 558 if (chip->irq >= 0)
533 free_irq(chip->irq, chip); 559 free_irq(chip->irq, chip);
534 flush_scheduled_work(); 560 flush_scheduled_work();
@@ -608,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
608 snd_card_set_dev(card, &pci->dev); 634 snd_card_set_dev(card, &pci->dev);
609 card->private_free = oxygen_card_free; 635 card->private_free = oxygen_card_free;
610 636
611 pci_bridge_magic(); 637 configure_pcie_bridge(pci);
612 oxygen_init(chip); 638 oxygen_init(chip);
613 chip->model.init(chip); 639 chip->model.init(chip);
614 640
@@ -778,3 +804,13 @@ int oxygen_pci_resume(struct pci_dev *pci)
778} 804}
779EXPORT_SYMBOL(oxygen_pci_resume); 805EXPORT_SYMBOL(oxygen_pci_resume);
780#endif /* CONFIG_PM */ 806#endif /* CONFIG_PM */
807
808void oxygen_pci_shutdown(struct pci_dev *pci)
809{
810 struct snd_card *card = pci_get_drvdata(pci);
811 struct oxygen *chip = card->private_data;
812
813 oxygen_shutdown(chip);
814 chip->model.cleanup(chip);
815}
816EXPORT_SYMBOL(oxygen_pci_shutdown);