diff options
Diffstat (limited to 'sound/pci/oxygen/oxygen_lib.c')
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 126 |
1 files changed, 82 insertions, 44 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 7e93cf884437..70b739816fcc 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -202,7 +202,13 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
202 | struct oxygen *chip = entry->private_data; | 202 | struct oxygen *chip = entry->private_data; |
203 | int i, j; | 203 | int i, j; |
204 | 204 | ||
205 | snd_iprintf(buffer, "CMI8788\n\n"); | 205 | switch (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_PACKAGE_ID_MASK) { |
206 | case OXYGEN_PACKAGE_ID_8786: i = '6'; break; | ||
207 | case OXYGEN_PACKAGE_ID_8787: i = '7'; break; | ||
208 | case OXYGEN_PACKAGE_ID_8788: i = '8'; break; | ||
209 | default: i = '?'; break; | ||
210 | } | ||
211 | snd_iprintf(buffer, "CMI878%c:\n", i); | ||
206 | for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) { | 212 | for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) { |
207 | snd_iprintf(buffer, "%02x:", i); | 213 | snd_iprintf(buffer, "%02x:", i); |
208 | for (j = 0; j < 0x10; ++j) | 214 | for (j = 0; j < 0x10; ++j) |
@@ -212,7 +218,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
212 | if (mutex_lock_interruptible(&chip->mutex) < 0) | 218 | if (mutex_lock_interruptible(&chip->mutex) < 0) |
213 | return; | 219 | return; |
214 | if (chip->has_ac97_0) { | 220 | if (chip->has_ac97_0) { |
215 | snd_iprintf(buffer, "\nAC97\n"); | 221 | snd_iprintf(buffer, "\nAC97:\n"); |
216 | for (i = 0; i < 0x80; i += 0x10) { | 222 | for (i = 0; i < 0x80; i += 0x10) { |
217 | snd_iprintf(buffer, "%02x:", i); | 223 | snd_iprintf(buffer, "%02x:", i); |
218 | for (j = 0; j < 0x10; j += 2) | 224 | for (j = 0; j < 0x10; j += 2) |
@@ -222,7 +228,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
222 | } | 228 | } |
223 | } | 229 | } |
224 | if (chip->has_ac97_1) { | 230 | if (chip->has_ac97_1) { |
225 | snd_iprintf(buffer, "\nAC97 2\n"); | 231 | snd_iprintf(buffer, "\nAC97 2:\n"); |
226 | for (i = 0; i < 0x80; i += 0x10) { | 232 | for (i = 0; i < 0x80; i += 0x10) { |
227 | snd_iprintf(buffer, "%02x:", i); | 233 | snd_iprintf(buffer, "%02x:", i); |
228 | for (j = 0; j < 0x10; j += 2) | 234 | for (j = 0; j < 0x10; j += 2) |
@@ -232,13 +238,15 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
232 | } | 238 | } |
233 | } | 239 | } |
234 | mutex_unlock(&chip->mutex); | 240 | mutex_unlock(&chip->mutex); |
241 | if (chip->model.dump_registers) | ||
242 | chip->model.dump_registers(chip, buffer); | ||
235 | } | 243 | } |
236 | 244 | ||
237 | static void oxygen_proc_init(struct oxygen *chip) | 245 | static void oxygen_proc_init(struct oxygen *chip) |
238 | { | 246 | { |
239 | struct snd_info_entry *entry; | 247 | struct snd_info_entry *entry; |
240 | 248 | ||
241 | if (!snd_card_proc_new(chip->card, "cmi8788", &entry)) | 249 | if (!snd_card_proc_new(chip->card, "oxygen", &entry)) |
242 | snd_info_set_text_ops(entry, chip, oxygen_proc_read); | 250 | snd_info_set_text_ops(entry, chip, oxygen_proc_read); |
243 | } | 251 | } |
244 | #else | 252 | #else |
@@ -262,7 +270,7 @@ oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) | |||
262 | */ | 270 | */ |
263 | subdevice = oxygen_read_eeprom(chip, 2); | 271 | subdevice = oxygen_read_eeprom(chip, 2); |
264 | /* use default ID if EEPROM is missing */ | 272 | /* use default ID if EEPROM is missing */ |
265 | if (subdevice == 0xffff) | 273 | if (subdevice == 0xffff && oxygen_read_eeprom(chip, 1) == 0xffff) |
266 | subdevice = 0x8788; | 274 | subdevice = 0x8788; |
267 | /* | 275 | /* |
268 | * We use only the subsystem device ID for searching because it is | 276 | * We use only the subsystem device ID for searching because it is |
@@ -308,25 +316,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip, | |||
308 | } | 316 | } |
309 | } | 317 | } |
310 | 318 | ||
311 | static void pci_bridge_magic(void) | 319 | static void configure_pcie_bridge(struct pci_dev *pci) |
312 | { | 320 | { |
313 | struct pci_dev *pci = NULL; | 321 | enum { PEX811X, PI7C9X110 }; |
322 | static const struct pci_device_id bridge_ids[] = { | ||
323 | { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, | ||
324 | { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, | ||
325 | { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, | ||
326 | { } | ||
327 | }; | ||
328 | struct pci_dev *bridge; | ||
329 | const struct pci_device_id *id; | ||
314 | u32 tmp; | 330 | u32 tmp; |
315 | 331 | ||
316 | for (;;) { | 332 | if (!pci->bus || !pci->bus->self) |
317 | /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */ | 333 | return; |
318 | pci = pci_get_device(0x12d8, 0xe110, pci); | 334 | bridge = pci->bus->self; |
319 | if (!pci) | 335 | |
320 | break; | 336 | id = pci_match_id(bridge_ids, bridge); |
321 | /* | 337 | if (!id) |
322 | * ... configure its secondary internal arbiter to park to | 338 | return; |
323 | * the secondary port, instead of to the last master. | 339 | |
324 | */ | 340 | switch (id->driver_data) { |
325 | if (!pci_read_config_dword(pci, 0x40, &tmp)) { | 341 | case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */ |
326 | tmp |= 1; | 342 | pci_read_config_dword(bridge, 0x48, &tmp); |
327 | pci_write_config_dword(pci, 0x40, tmp); | 343 | tmp |= 1; /* enable blind prefetching */ |
328 | } | 344 | tmp |= 1 << 11; /* enable beacon generation */ |
329 | /* Why? Try asking C-Media. */ | 345 | pci_write_config_dword(bridge, 0x48, tmp); |
346 | |||
347 | pci_write_config_dword(bridge, 0x84, 0x0c); | ||
348 | pci_read_config_dword(bridge, 0x88, &tmp); | ||
349 | tmp &= ~(7 << 27); | ||
350 | tmp |= 2 << 27; /* set prefetch size to 128 bytes */ | ||
351 | pci_write_config_dword(bridge, 0x88, tmp); | ||
352 | break; | ||
353 | |||
354 | case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */ | ||
355 | pci_read_config_dword(bridge, 0x40, &tmp); | ||
356 | tmp |= 1; /* park the PCI arbiter to the sound chip */ | ||
357 | pci_write_config_dword(bridge, 0x40, tmp); | ||
358 | break; | ||
330 | } | 359 | } |
331 | } | 360 | } |
332 | 361 | ||
@@ -343,12 +372,7 @@ static void oxygen_init(struct oxygen *chip) | |||
343 | (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); | 372 | (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); |
344 | chip->spdif_pcm_bits = chip->spdif_bits; | 373 | chip->spdif_pcm_bits = chip->spdif_bits; |
345 | 374 | ||
346 | if (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2) | 375 | if (!(oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2)) |
347 | chip->revision = 2; | ||
348 | else | ||
349 | chip->revision = 1; | ||
350 | |||
351 | if (chip->revision == 1) | ||
352 | oxygen_set_bits8(chip, OXYGEN_MISC, | 376 | oxygen_set_bits8(chip, OXYGEN_MISC, |
353 | OXYGEN_MISC_PCI_MEM_W_1_CLOCK); | 377 | OXYGEN_MISC_PCI_MEM_W_1_CLOCK); |
354 | 378 | ||
@@ -385,28 +409,40 @@ static void oxygen_init(struct oxygen *chip) | |||
385 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); | 409 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); |
386 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); | 410 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); |
387 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, | 411 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, |
388 | OXYGEN_RATE_48000 | chip->model.dac_i2s_format | | 412 | OXYGEN_RATE_48000 | |
389 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 413 | chip->model.dac_i2s_format | |
390 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 414 | OXYGEN_I2S_MCLK(chip->model.dac_mclks) | |
415 | OXYGEN_I2S_BITS_16 | | ||
416 | OXYGEN_I2S_MASTER | | ||
417 | OXYGEN_I2S_BCLK_64); | ||
391 | if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) | 418 | if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) |
392 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 419 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
393 | OXYGEN_RATE_48000 | chip->model.adc_i2s_format | | 420 | OXYGEN_RATE_48000 | |
394 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 421 | chip->model.adc_i2s_format | |
395 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 422 | OXYGEN_I2S_MCLK(chip->model.adc_mclks) | |
423 | OXYGEN_I2S_BITS_16 | | ||
424 | OXYGEN_I2S_MASTER | | ||
425 | OXYGEN_I2S_BCLK_64); | ||
396 | else | 426 | else |
397 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 427 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
398 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 428 | OXYGEN_I2S_MASTER | |
429 | OXYGEN_I2S_MUTE_MCLK); | ||
399 | if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | | 430 | if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | |
400 | CAPTURE_2_FROM_I2S_2)) | 431 | CAPTURE_2_FROM_I2S_2)) |
401 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | 432 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, |
402 | OXYGEN_RATE_48000 | chip->model.adc_i2s_format | | 433 | OXYGEN_RATE_48000 | |
403 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 434 | chip->model.adc_i2s_format | |
404 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 435 | OXYGEN_I2S_MCLK(chip->model.adc_mclks) | |
436 | OXYGEN_I2S_BITS_16 | | ||
437 | OXYGEN_I2S_MASTER | | ||
438 | OXYGEN_I2S_BCLK_64); | ||
405 | else | 439 | else |
406 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | 440 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, |
407 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 441 | OXYGEN_I2S_MASTER | |
442 | OXYGEN_I2S_MUTE_MCLK); | ||
408 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, | 443 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, |
409 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 444 | OXYGEN_I2S_MASTER | |
445 | OXYGEN_I2S_MUTE_MCLK); | ||
410 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, | 446 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
411 | OXYGEN_SPDIF_OUT_ENABLE | | 447 | OXYGEN_SPDIF_OUT_ENABLE | |
412 | OXYGEN_SPDIF_LOOPBACK); | 448 | OXYGEN_SPDIF_LOOPBACK); |
@@ -536,7 +572,8 @@ static void oxygen_card_free(struct snd_card *card) | |||
536 | oxygen_shutdown(chip); | 572 | oxygen_shutdown(chip); |
537 | if (chip->irq >= 0) | 573 | if (chip->irq >= 0) |
538 | free_irq(chip->irq, chip); | 574 | free_irq(chip->irq, chip); |
539 | flush_scheduled_work(); | 575 | flush_work_sync(&chip->spdif_input_bits_work); |
576 | flush_work_sync(&chip->gpio_work); | ||
540 | chip->model.cleanup(chip); | 577 | chip->model.cleanup(chip); |
541 | kfree(chip->model_data); | 578 | kfree(chip->model_data); |
542 | mutex_destroy(&chip->mutex); | 579 | mutex_destroy(&chip->mutex); |
@@ -613,7 +650,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
613 | snd_card_set_dev(card, &pci->dev); | 650 | snd_card_set_dev(card, &pci->dev); |
614 | card->private_free = oxygen_card_free; | 651 | card->private_free = oxygen_card_free; |
615 | 652 | ||
616 | pci_bridge_magic(); | 653 | configure_pcie_bridge(pci); |
617 | oxygen_init(chip); | 654 | oxygen_init(chip); |
618 | chip->model.init(chip); | 655 | chip->model.init(chip); |
619 | 656 | ||
@@ -627,8 +664,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
627 | 664 | ||
628 | strcpy(card->driver, chip->model.chip); | 665 | strcpy(card->driver, chip->model.chip); |
629 | strcpy(card->shortname, chip->model.shortname); | 666 | strcpy(card->shortname, chip->model.shortname); |
630 | sprintf(card->longname, "%s (rev %u) at %#lx, irq %i", | 667 | sprintf(card->longname, "%s at %#lx, irq %i", |
631 | chip->model.longname, chip->revision, chip->addr, chip->irq); | 668 | chip->model.longname, chip->addr, chip->irq); |
632 | strcpy(card->mixername, chip->model.chip); | 669 | strcpy(card->mixername, chip->model.chip); |
633 | snd_component_add(card, chip->model.chip); | 670 | snd_component_add(card, chip->model.chip); |
634 | 671 | ||
@@ -712,7 +749,8 @@ int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) | |||
712 | spin_unlock_irq(&chip->reg_lock); | 749 | spin_unlock_irq(&chip->reg_lock); |
713 | 750 | ||
714 | synchronize_irq(chip->irq); | 751 | synchronize_irq(chip->irq); |
715 | flush_scheduled_work(); | 752 | flush_work_sync(&chip->spdif_input_bits_work); |
753 | flush_work_sync(&chip->gpio_work); | ||
716 | chip->interrupt_mask = saved_interrupt_mask; | 754 | chip->interrupt_mask = saved_interrupt_mask; |
717 | 755 | ||
718 | pci_disable_device(pci); | 756 | pci_disable_device(pci); |