diff options
Diffstat (limited to 'sound/pci/oxygen/oxygen_lib.c')
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 7e93cf884437..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 | ||
311 | static void pci_bridge_magic(void) | 311 | static 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 | ||
@@ -613,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
613 | snd_card_set_dev(card, &pci->dev); | 634 | snd_card_set_dev(card, &pci->dev); |
614 | card->private_free = oxygen_card_free; | 635 | card->private_free = oxygen_card_free; |
615 | 636 | ||
616 | pci_bridge_magic(); | 637 | configure_pcie_bridge(pci); |
617 | oxygen_init(chip); | 638 | oxygen_init(chip); |
618 | chip->model.init(chip); | 639 | chip->model.init(chip); |
619 | 640 | ||