diff options
| author | Takashi Iwai <tiwai@suse.de> | 2009-09-10 09:32:55 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2009-09-10 09:32:55 -0400 |
| commit | 8a3351bbb93b15ec5d35fd4b3e6e971d6285e674 (patch) | |
| tree | ec40d226dc962401fa022ad3d862f2ccd01f6817 | |
| parent | dcb37d509a93710f96ebfd8b653e3653144799f9 (diff) | |
| parent | cd775387244e379ef9b284f9b6aff6ee069f4d12 (diff) | |
Merge branch 'topic/ice1724-pm' into for-linus
* topic/ice1724-pm:
ALSA: ice1724 - Fix section mismatch
ALSA: ice1724 - Patch for suspend/resume for Audiotrak Prodigy HD2
| -rw-r--r-- | sound/pci/ice1712/ice1712.h | 9 | ||||
| -rw-r--r-- | sound/pci/ice1712/ice1724.c | 112 | ||||
| -rw-r--r-- | sound/pci/ice1712/prodigy_hifi.c | 46 |
3 files changed, 147 insertions, 20 deletions
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index adc909ec125c..9da2dae64c5b 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
| @@ -379,6 +379,15 @@ struct snd_ice1712 { | |||
| 379 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); | 379 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); |
| 380 | void (*set_spdif_clock)(struct snd_ice1712 *ice); | 380 | void (*set_spdif_clock)(struct snd_ice1712 *ice); |
| 381 | 381 | ||
| 382 | #ifdef CONFIG_PM | ||
| 383 | int (*pm_suspend)(struct snd_ice1712 *); | ||
| 384 | int (*pm_resume)(struct snd_ice1712 *); | ||
| 385 | int pm_suspend_enabled:1; | ||
| 386 | int pm_saved_is_spdif_master:1; | ||
| 387 | unsigned int pm_saved_spdif_ctrl; | ||
| 388 | unsigned char pm_saved_spdif_cfg; | ||
| 389 | unsigned int pm_saved_route; | ||
| 390 | #endif | ||
| 382 | }; | 391 | }; |
| 383 | 392 | ||
| 384 | 393 | ||
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index cc84a831eb21..af6e00148621 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
| @@ -560,6 +560,7 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 560 | 560 | ||
| 561 | case SNDRV_PCM_TRIGGER_START: | 561 | case SNDRV_PCM_TRIGGER_START: |
| 562 | case SNDRV_PCM_TRIGGER_STOP: | 562 | case SNDRV_PCM_TRIGGER_STOP: |
| 563 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
| 563 | spin_lock(&ice->reg_lock); | 564 | spin_lock(&ice->reg_lock); |
| 564 | old = inb(ICEMT1724(ice, DMA_CONTROL)); | 565 | old = inb(ICEMT1724(ice, DMA_CONTROL)); |
| 565 | if (cmd == SNDRV_PCM_TRIGGER_START) | 566 | if (cmd == SNDRV_PCM_TRIGGER_START) |
| @@ -570,6 +571,10 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 570 | spin_unlock(&ice->reg_lock); | 571 | spin_unlock(&ice->reg_lock); |
| 571 | break; | 572 | break; |
| 572 | 573 | ||
| 574 | case SNDRV_PCM_TRIGGER_RESUME: | ||
| 575 | /* apps will have to restart stream */ | ||
| 576 | break; | ||
| 577 | |||
| 573 | default: | 578 | default: |
| 574 | return -EINVAL; | 579 | return -EINVAL; |
| 575 | } | 580 | } |
| @@ -2262,7 +2267,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, | |||
| 2262 | 2267 | ||
| 2263 | 2268 | ||
| 2264 | 2269 | ||
| 2265 | static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice) | 2270 | static void snd_vt1724_chip_reset(struct snd_ice1712 *ice) |
| 2266 | { | 2271 | { |
| 2267 | outb(VT1724_RESET , ICEREG1724(ice, CONTROL)); | 2272 | outb(VT1724_RESET , ICEREG1724(ice, CONTROL)); |
| 2268 | inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */ | 2273 | inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */ |
| @@ -2272,7 +2277,7 @@ static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice) | |||
| 2272 | msleep(10); | 2277 | msleep(10); |
| 2273 | } | 2278 | } |
| 2274 | 2279 | ||
| 2275 | static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice) | 2280 | static int snd_vt1724_chip_init(struct snd_ice1712 *ice) |
| 2276 | { | 2281 | { |
| 2277 | outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG)); | 2282 | outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG)); |
| 2278 | outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG)); | 2283 | outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG)); |
| @@ -2287,6 +2292,14 @@ static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice) | |||
| 2287 | 2292 | ||
| 2288 | outb(0, ICEREG1724(ice, POWERDOWN)); | 2293 | outb(0, ICEREG1724(ice, POWERDOWN)); |
| 2289 | 2294 | ||
| 2295 | /* MPU_RX and TX irq masks are cleared later dynamically */ | ||
| 2296 | outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK)); | ||
| 2297 | |||
| 2298 | /* don't handle FIFO overrun/underruns (just yet), | ||
| 2299 | * since they cause machine lockups | ||
| 2300 | */ | ||
| 2301 | outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK)); | ||
| 2302 | |||
| 2290 | return 0; | 2303 | return 0; |
| 2291 | } | 2304 | } |
| 2292 | 2305 | ||
| @@ -2431,6 +2444,8 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
| 2431 | snd_vt1724_proc_init(ice); | 2444 | snd_vt1724_proc_init(ice); |
| 2432 | synchronize_irq(pci->irq); | 2445 | synchronize_irq(pci->irq); |
| 2433 | 2446 | ||
| 2447 | card->private_data = ice; | ||
| 2448 | |||
| 2434 | err = pci_request_regions(pci, "ICE1724"); | 2449 | err = pci_request_regions(pci, "ICE1724"); |
| 2435 | if (err < 0) { | 2450 | if (err < 0) { |
| 2436 | kfree(ice); | 2451 | kfree(ice); |
| @@ -2459,14 +2474,6 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
| 2459 | return -EIO; | 2474 | return -EIO; |
| 2460 | } | 2475 | } |
| 2461 | 2476 | ||
| 2462 | /* MPU_RX and TX irq masks are cleared later dynamically */ | ||
| 2463 | outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK)); | ||
| 2464 | |||
| 2465 | /* don't handle FIFO overrun/underruns (just yet), | ||
| 2466 | * since they cause machine lockups | ||
| 2467 | */ | ||
| 2468 | outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK)); | ||
| 2469 | |||
| 2470 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); | 2477 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); |
| 2471 | if (err < 0) { | 2478 | if (err < 0) { |
| 2472 | snd_vt1724_free(ice); | 2479 | snd_vt1724_free(ice); |
| @@ -2650,11 +2657,96 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci) | |||
| 2650 | pci_set_drvdata(pci, NULL); | 2657 | pci_set_drvdata(pci, NULL); |
| 2651 | } | 2658 | } |
| 2652 | 2659 | ||
| 2660 | #ifdef CONFIG_PM | ||
| 2661 | static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state) | ||
| 2662 | { | ||
| 2663 | struct snd_card *card = pci_get_drvdata(pci); | ||
| 2664 | struct snd_ice1712 *ice = card->private_data; | ||
| 2665 | |||
| 2666 | if (!ice->pm_suspend_enabled) | ||
| 2667 | return 0; | ||
| 2668 | |||
| 2669 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
| 2670 | |||
| 2671 | snd_pcm_suspend_all(ice->pcm); | ||
| 2672 | snd_pcm_suspend_all(ice->pcm_pro); | ||
| 2673 | snd_pcm_suspend_all(ice->pcm_ds); | ||
| 2674 | snd_ac97_suspend(ice->ac97); | ||
| 2675 | |||
| 2676 | spin_lock_irq(&ice->reg_lock); | ||
| 2677 | ice->pm_saved_is_spdif_master = ice->is_spdif_master(ice); | ||
| 2678 | ice->pm_saved_spdif_ctrl = inw(ICEMT1724(ice, SPDIF_CTRL)); | ||
| 2679 | ice->pm_saved_spdif_cfg = inb(ICEREG1724(ice, SPDIF_CFG)); | ||
| 2680 | ice->pm_saved_route = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); | ||
| 2681 | spin_unlock_irq(&ice->reg_lock); | ||
| 2682 | |||
| 2683 | if (ice->pm_suspend) | ||
| 2684 | ice->pm_suspend(ice); | ||
| 2685 | |||
| 2686 | pci_disable_device(pci); | ||
| 2687 | pci_save_state(pci); | ||
| 2688 | pci_set_power_state(pci, pci_choose_state(pci, state)); | ||
| 2689 | return 0; | ||
| 2690 | } | ||
| 2691 | |||
| 2692 | static int snd_vt1724_resume(struct pci_dev *pci) | ||
| 2693 | { | ||
| 2694 | struct snd_card *card = pci_get_drvdata(pci); | ||
| 2695 | struct snd_ice1712 *ice = card->private_data; | ||
| 2696 | |||
| 2697 | if (!ice->pm_suspend_enabled) | ||
| 2698 | return 0; | ||
| 2699 | |||
| 2700 | pci_set_power_state(pci, PCI_D0); | ||
| 2701 | pci_restore_state(pci); | ||
| 2702 | |||
| 2703 | if (pci_enable_device(pci) < 0) { | ||
| 2704 | snd_card_disconnect(card); | ||
| 2705 | return -EIO; | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | pci_set_master(pci); | ||
| 2709 | |||
| 2710 | snd_vt1724_chip_reset(ice); | ||
| 2711 | |||
| 2712 | if (snd_vt1724_chip_init(ice) < 0) { | ||
| 2713 | snd_card_disconnect(card); | ||
| 2714 | return -EIO; | ||
| 2715 | } | ||
| 2716 | |||
| 2717 | if (ice->pm_resume) | ||
| 2718 | ice->pm_resume(ice); | ||
| 2719 | |||
| 2720 | if (ice->pm_saved_is_spdif_master) { | ||
| 2721 | /* switching to external clock via SPDIF */ | ||
| 2722 | ice->set_spdif_clock(ice); | ||
| 2723 | } else { | ||
| 2724 | /* internal on-card clock */ | ||
| 2725 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); | ||
| 2726 | } | ||
| 2727 | |||
| 2728 | update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); | ||
| 2729 | |||
| 2730 | outb(ice->pm_saved_spdif_cfg, ICEREG1724(ice, SPDIF_CFG)); | ||
| 2731 | outl(ice->pm_saved_route, ICEMT1724(ice, ROUTE_PLAYBACK)); | ||
| 2732 | |||
| 2733 | if (ice->ac97) | ||
| 2734 | snd_ac97_resume(ice->ac97); | ||
| 2735 | |||
| 2736 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
| 2737 | return 0; | ||
| 2738 | } | ||
| 2739 | #endif | ||
| 2740 | |||
| 2653 | static struct pci_driver driver = { | 2741 | static struct pci_driver driver = { |
| 2654 | .name = "ICE1724", | 2742 | .name = "ICE1724", |
| 2655 | .id_table = snd_vt1724_ids, | 2743 | .id_table = snd_vt1724_ids, |
| 2656 | .probe = snd_vt1724_probe, | 2744 | .probe = snd_vt1724_probe, |
| 2657 | .remove = __devexit_p(snd_vt1724_remove), | 2745 | .remove = __devexit_p(snd_vt1724_remove), |
| 2746 | #ifdef CONFIG_PM | ||
| 2747 | .suspend = snd_vt1724_suspend, | ||
| 2748 | .resume = snd_vt1724_resume, | ||
| 2749 | #endif | ||
| 2658 | }; | 2750 | }; |
| 2659 | 2751 | ||
| 2660 | static int __init alsa_card_ice1724_init(void) | 2752 | static int __init alsa_card_ice1724_init(void) |
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 043a93879bd5..c75515f5be6f 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c | |||
| @@ -1077,7 +1077,7 @@ static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice) | |||
| 1077 | /* | 1077 | /* |
| 1078 | * initialize the chip | 1078 | * initialize the chip |
| 1079 | */ | 1079 | */ |
| 1080 | static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) | 1080 | static void ak4396_init(struct snd_ice1712 *ice) |
| 1081 | { | 1081 | { |
| 1082 | static unsigned short ak4396_inits[] = { | 1082 | static unsigned short ak4396_inits[] = { |
| 1083 | AK4396_CTRL1, 0x87, /* I2S Normal Mode, 24 bit */ | 1083 | AK4396_CTRL1, 0x87, /* I2S Normal Mode, 24 bit */ |
| @@ -1087,9 +1087,37 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) | |||
| 1087 | AK4396_RCH_ATT, 0x00, | 1087 | AK4396_RCH_ATT, 0x00, |
| 1088 | }; | 1088 | }; |
| 1089 | 1089 | ||
| 1090 | struct prodigy_hifi_spec *spec; | ||
| 1091 | unsigned int i; | 1090 | unsigned int i; |
| 1092 | 1091 | ||
| 1092 | /* initialize ak4396 codec */ | ||
| 1093 | /* reset codec */ | ||
| 1094 | ak4396_write(ice, AK4396_CTRL1, 0x86); | ||
| 1095 | msleep(100); | ||
| 1096 | ak4396_write(ice, AK4396_CTRL1, 0x87); | ||
| 1097 | |||
| 1098 | for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2) | ||
| 1099 | ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | #ifdef CONFIG_PM | ||
| 1103 | static int __devinit prodigy_hd2_resume(struct snd_ice1712 *ice) | ||
| 1104 | { | ||
| 1105 | /* initialize ak4396 codec and restore previous mixer volumes */ | ||
| 1106 | struct prodigy_hifi_spec *spec = ice->spec; | ||
| 1107 | int i; | ||
| 1108 | mutex_lock(&ice->gpio_mutex); | ||
| 1109 | ak4396_init(ice); | ||
| 1110 | for (i = 0; i < 2; i++) | ||
| 1111 | ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff); | ||
| 1112 | mutex_unlock(&ice->gpio_mutex); | ||
| 1113 | return 0; | ||
| 1114 | } | ||
| 1115 | #endif | ||
| 1116 | |||
| 1117 | static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) | ||
| 1118 | { | ||
| 1119 | struct prodigy_hifi_spec *spec; | ||
| 1120 | |||
| 1093 | ice->vt1720 = 0; | 1121 | ice->vt1720 = 0; |
| 1094 | ice->vt1724 = 1; | 1122 | ice->vt1724 = 1; |
| 1095 | 1123 | ||
| @@ -1112,14 +1140,12 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) | |||
| 1112 | return -ENOMEM; | 1140 | return -ENOMEM; |
| 1113 | ice->spec = spec; | 1141 | ice->spec = spec; |
| 1114 | 1142 | ||
| 1115 | /* initialize ak4396 codec */ | 1143 | #ifdef CONFIG_PM |
| 1116 | /* reset codec */ | 1144 | ice->pm_resume = &prodigy_hd2_resume; |
| 1117 | ak4396_write(ice, AK4396_CTRL1, 0x86); | 1145 | ice->pm_suspend_enabled = 1; |
| 1118 | msleep(100); | 1146 | #endif |
| 1119 | ak4396_write(ice, AK4396_CTRL1, 0x87); | 1147 | |
| 1120 | 1148 | ak4396_init(ice); | |
| 1121 | for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2) | ||
| 1122 | ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]); | ||
| 1123 | 1149 | ||
| 1124 | return 0; | 1150 | return 0; |
| 1125 | } | 1151 | } |
