diff options
Diffstat (limited to 'sound/pci/oxygen/oxygen_lib.c')
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 22f37851045..84f481d41ef 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -35,6 +35,30 @@ MODULE_DESCRIPTION("C-Media CMI8788 helper library"); | |||
35 | MODULE_LICENSE("GPL v2"); | 35 | MODULE_LICENSE("GPL v2"); |
36 | 36 | ||
37 | 37 | ||
38 | static inline int oxygen_uart_input_ready(struct oxygen *chip) | ||
39 | { | ||
40 | return !(oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_RX_EMPTY); | ||
41 | } | ||
42 | |||
43 | static void oxygen_read_uart(struct oxygen *chip) | ||
44 | { | ||
45 | if (unlikely(!oxygen_uart_input_ready(chip))) { | ||
46 | /* no data, but read it anyway to clear the interrupt */ | ||
47 | oxygen_read8(chip, OXYGEN_MPU401); | ||
48 | return; | ||
49 | } | ||
50 | do { | ||
51 | u8 data = oxygen_read8(chip, OXYGEN_MPU401); | ||
52 | if (data == MPU401_ACK) | ||
53 | continue; | ||
54 | if (chip->uart_input_count >= ARRAY_SIZE(chip->uart_input)) | ||
55 | chip->uart_input_count = 0; | ||
56 | chip->uart_input[chip->uart_input_count++] = data; | ||
57 | } while (oxygen_uart_input_ready(chip)); | ||
58 | if (chip->model.uart_input) | ||
59 | chip->model.uart_input(chip); | ||
60 | } | ||
61 | |||
38 | static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) | 62 | static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) |
39 | { | 63 | { |
40 | struct oxygen *chip = dev_id; | 64 | struct oxygen *chip = dev_id; |
@@ -87,8 +111,12 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) | |||
87 | if (status & OXYGEN_INT_GPIO) | 111 | if (status & OXYGEN_INT_GPIO) |
88 | schedule_work(&chip->gpio_work); | 112 | schedule_work(&chip->gpio_work); |
89 | 113 | ||
90 | if ((status & OXYGEN_INT_MIDI) && chip->midi) | 114 | if (status & OXYGEN_INT_MIDI) { |
91 | snd_mpu401_uart_interrupt(0, chip->midi->private_data); | 115 | if (chip->midi) |
116 | snd_mpu401_uart_interrupt(0, chip->midi->private_data); | ||
117 | else | ||
118 | oxygen_read_uart(chip); | ||
119 | } | ||
92 | 120 | ||
93 | if (status & OXYGEN_INT_AC97) | 121 | if (status & OXYGEN_INT_AC97) |
94 | wake_up(&chip->ac97_waitqueue); | 122 | wake_up(&chip->ac97_waitqueue); |
@@ -161,8 +189,8 @@ static void oxygen_gpio_changed(struct work_struct *work) | |||
161 | { | 189 | { |
162 | struct oxygen *chip = container_of(work, struct oxygen, gpio_work); | 190 | struct oxygen *chip = container_of(work, struct oxygen, gpio_work); |
163 | 191 | ||
164 | if (chip->model->gpio_changed) | 192 | if (chip->model.gpio_changed) |
165 | chip->model->gpio_changed(chip); | 193 | chip->model.gpio_changed(chip); |
166 | } | 194 | } |
167 | 195 | ||
168 | #ifdef CONFIG_PROC_FS | 196 | #ifdef CONFIG_PROC_FS |
@@ -221,7 +249,7 @@ static void oxygen_init(struct oxygen *chip) | |||
221 | 249 | ||
222 | chip->dac_routing = 1; | 250 | chip->dac_routing = 1; |
223 | for (i = 0; i < 8; ++i) | 251 | for (i = 0; i < 8; ++i) |
224 | chip->dac_volume[i] = chip->model->dac_volume_min; | 252 | chip->dac_volume[i] = chip->model.dac_volume_min; |
225 | chip->dac_mute = 1; | 253 | chip->dac_mute = 1; |
226 | chip->spdif_playback_enable = 1; | 254 | chip->spdif_playback_enable = 1; |
227 | chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL | | 255 | chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL | |
@@ -243,7 +271,7 @@ static void oxygen_init(struct oxygen *chip) | |||
243 | 271 | ||
244 | oxygen_write8_masked(chip, OXYGEN_FUNCTION, | 272 | oxygen_write8_masked(chip, OXYGEN_FUNCTION, |
245 | OXYGEN_FUNCTION_RESET_CODEC | | 273 | OXYGEN_FUNCTION_RESET_CODEC | |
246 | chip->model->function_flags, | 274 | chip->model.function_flags, |
247 | OXYGEN_FUNCTION_RESET_CODEC | | 275 | OXYGEN_FUNCTION_RESET_CODEC | |
248 | OXYGEN_FUNCTION_2WIRE_SPI_MASK | | 276 | OXYGEN_FUNCTION_2WIRE_SPI_MASK | |
249 | OXYGEN_FUNCTION_ENABLE_SPI_4_5); | 277 | OXYGEN_FUNCTION_ENABLE_SPI_4_5); |
@@ -255,7 +283,7 @@ static void oxygen_init(struct oxygen *chip) | |||
255 | OXYGEN_DMA_MULTICH_BURST_8); | 283 | OXYGEN_DMA_MULTICH_BURST_8); |
256 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); | 284 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); |
257 | oxygen_write8_masked(chip, OXYGEN_MISC, | 285 | oxygen_write8_masked(chip, OXYGEN_MISC, |
258 | chip->model->misc_flags, | 286 | chip->model.misc_flags, |
259 | OXYGEN_MISC_WRITE_PCI_SUBID | | 287 | OXYGEN_MISC_WRITE_PCI_SUBID | |
260 | OXYGEN_MISC_REC_C_FROM_SPDIF | | 288 | OXYGEN_MISC_REC_C_FROM_SPDIF | |
261 | OXYGEN_MISC_REC_B_FROM_AC97 | | 289 | OXYGEN_MISC_REC_B_FROM_AC97 | |
@@ -270,21 +298,21 @@ static void oxygen_init(struct oxygen *chip) | |||
270 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); | 298 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); |
271 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); | 299 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); |
272 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, | 300 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, |
273 | OXYGEN_RATE_48000 | chip->model->dac_i2s_format | | 301 | OXYGEN_RATE_48000 | chip->model.dac_i2s_format | |
274 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 302 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | |
275 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 303 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); |
276 | if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1) | 304 | if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) |
277 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 305 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
278 | OXYGEN_RATE_48000 | chip->model->adc_i2s_format | | 306 | OXYGEN_RATE_48000 | chip->model.adc_i2s_format | |
279 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 307 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | |
280 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 308 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); |
281 | else | 309 | else |
282 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 310 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
283 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 311 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); |
284 | if (chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_2 | | 312 | if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | |
285 | CAPTURE_2_FROM_I2S_2)) | 313 | CAPTURE_2_FROM_I2S_2)) |
286 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | 314 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, |
287 | OXYGEN_RATE_48000 | chip->model->adc_i2s_format | | 315 | OXYGEN_RATE_48000 | chip->model.adc_i2s_format | |
288 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 316 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | |
289 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 317 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); |
290 | else | 318 | else |
@@ -295,7 +323,7 @@ static void oxygen_init(struct oxygen *chip) | |||
295 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, | 323 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
296 | OXYGEN_SPDIF_OUT_ENABLE | | 324 | OXYGEN_SPDIF_OUT_ENABLE | |
297 | OXYGEN_SPDIF_LOOPBACK); | 325 | OXYGEN_SPDIF_LOOPBACK); |
298 | if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) | 326 | if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) |
299 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, | 327 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, |
300 | OXYGEN_SPDIF_SENSE_MASK | | 328 | OXYGEN_SPDIF_SENSE_MASK | |
301 | OXYGEN_SPDIF_LOCK_MASK | | 329 | OXYGEN_SPDIF_LOCK_MASK | |
@@ -417,14 +445,15 @@ static void oxygen_card_free(struct snd_card *card) | |||
417 | if (chip->irq >= 0) | 445 | if (chip->irq >= 0) |
418 | free_irq(chip->irq, chip); | 446 | free_irq(chip->irq, chip); |
419 | flush_scheduled_work(); | 447 | flush_scheduled_work(); |
420 | chip->model->cleanup(chip); | 448 | chip->model.cleanup(chip); |
421 | mutex_destroy(&chip->mutex); | 449 | mutex_destroy(&chip->mutex); |
422 | pci_release_regions(chip->pci); | 450 | pci_release_regions(chip->pci); |
423 | pci_disable_device(chip->pci); | 451 | pci_disable_device(chip->pci); |
424 | } | 452 | } |
425 | 453 | ||
426 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 454 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
427 | const struct oxygen_model *model) | 455 | const struct oxygen_model *model, |
456 | unsigned long driver_data) | ||
428 | { | 457 | { |
429 | struct snd_card *card; | 458 | struct snd_card *card; |
430 | struct oxygen *chip; | 459 | struct oxygen *chip; |
@@ -439,7 +468,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
439 | chip->card = card; | 468 | chip->card = card; |
440 | chip->pci = pci; | 469 | chip->pci = pci; |
441 | chip->irq = -1; | 470 | chip->irq = -1; |
442 | chip->model = model; | 471 | chip->model = *model; |
443 | chip->model_data = chip + 1; | 472 | chip->model_data = chip + 1; |
444 | spin_lock_init(&chip->reg_lock); | 473 | spin_lock_init(&chip->reg_lock); |
445 | mutex_init(&chip->mutex); | 474 | mutex_init(&chip->mutex); |
@@ -470,23 +499,28 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
470 | snd_card_set_dev(card, &pci->dev); | 499 | snd_card_set_dev(card, &pci->dev); |
471 | card->private_free = oxygen_card_free; | 500 | card->private_free = oxygen_card_free; |
472 | 501 | ||
502 | if (chip->model.probe) { | ||
503 | err = chip->model.probe(chip, driver_data); | ||
504 | if (err < 0) | ||
505 | goto err_card; | ||
506 | } | ||
473 | oxygen_init(chip); | 507 | oxygen_init(chip); |
474 | model->init(chip); | 508 | chip->model.init(chip); |
475 | 509 | ||
476 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, | 510 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, |
477 | model->chip, chip); | 511 | chip->model.chip, chip); |
478 | if (err < 0) { | 512 | if (err < 0) { |
479 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); | 513 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); |
480 | goto err_card; | 514 | goto err_card; |
481 | } | 515 | } |
482 | chip->irq = pci->irq; | 516 | chip->irq = pci->irq; |
483 | 517 | ||
484 | strcpy(card->driver, model->chip); | 518 | strcpy(card->driver, chip->model.chip); |
485 | strcpy(card->shortname, model->shortname); | 519 | strcpy(card->shortname, chip->model.shortname); |
486 | sprintf(card->longname, "%s (rev %u) at %#lx, irq %i", | 520 | sprintf(card->longname, "%s (rev %u) at %#lx, irq %i", |
487 | model->longname, chip->revision, chip->addr, chip->irq); | 521 | chip->model.longname, chip->revision, chip->addr, chip->irq); |
488 | strcpy(card->mixername, model->chip); | 522 | strcpy(card->mixername, chip->model.chip); |
489 | snd_component_add(card, model->chip); | 523 | snd_component_add(card, chip->model.chip); |
490 | 524 | ||
491 | err = oxygen_pcm_init(chip); | 525 | err = oxygen_pcm_init(chip); |
492 | if (err < 0) | 526 | if (err < 0) |
@@ -496,10 +530,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
496 | if (err < 0) | 530 | if (err < 0) |
497 | goto err_card; | 531 | goto err_card; |
498 | 532 | ||
499 | if (model->misc_flags & OXYGEN_MISC_MIDI) { | 533 | if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) { |
534 | unsigned int info_flags = MPU401_INFO_INTEGRATED; | ||
535 | if (chip->model.device_config & MIDI_OUTPUT) | ||
536 | info_flags |= MPU401_INFO_OUTPUT; | ||
537 | if (chip->model.device_config & MIDI_INPUT) | ||
538 | info_flags |= MPU401_INFO_INPUT; | ||
500 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, | 539 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, |
501 | chip->addr + OXYGEN_MPU401, | 540 | chip->addr + OXYGEN_MPU401, |
502 | MPU401_INFO_INTEGRATED, 0, 0, | 541 | info_flags, 0, 0, |
503 | &chip->midi); | 542 | &chip->midi); |
504 | if (err < 0) | 543 | if (err < 0) |
505 | goto err_card; | 544 | goto err_card; |
@@ -508,7 +547,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
508 | oxygen_proc_init(chip); | 547 | oxygen_proc_init(chip); |
509 | 548 | ||
510 | spin_lock_irq(&chip->reg_lock); | 549 | spin_lock_irq(&chip->reg_lock); |
511 | if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) | 550 | if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) |
512 | chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; | 551 | chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; |
513 | if (chip->has_ac97_0 | chip->has_ac97_1) | 552 | if (chip->has_ac97_0 | chip->has_ac97_1) |
514 | chip->interrupt_mask |= OXYGEN_INT_AC97; | 553 | chip->interrupt_mask |= OXYGEN_INT_AC97; |
@@ -552,8 +591,8 @@ int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) | |||
552 | if (chip->streams[i]) | 591 | if (chip->streams[i]) |
553 | snd_pcm_suspend(chip->streams[i]); | 592 | snd_pcm_suspend(chip->streams[i]); |
554 | 593 | ||
555 | if (chip->model->suspend) | 594 | if (chip->model.suspend) |
556 | chip->model->suspend(chip); | 595 | chip->model.suspend(chip); |
557 | 596 | ||
558 | spin_lock_irq(&chip->reg_lock); | 597 | spin_lock_irq(&chip->reg_lock); |
559 | saved_interrupt_mask = chip->interrupt_mask; | 598 | saved_interrupt_mask = chip->interrupt_mask; |
@@ -624,8 +663,8 @@ int oxygen_pci_resume(struct pci_dev *pci) | |||
624 | if (chip->has_ac97_1) | 663 | if (chip->has_ac97_1) |
625 | oxygen_restore_ac97(chip, 1); | 664 | oxygen_restore_ac97(chip, 1); |
626 | 665 | ||
627 | if (chip->model->resume) | 666 | if (chip->model.resume) |
628 | chip->model->resume(chip); | 667 | chip->model.resume(chip); |
629 | 668 | ||
630 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); | 669 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); |
631 | 670 | ||