diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-11-17 10:14:10 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:27:58 -0500 |
commit | 09668b441dacdf4640509b640ad73e24efd5204f (patch) | |
tree | 177d0548acbcca4432f82ce6f3aa397cba5ba528 /sound/pci/emu10k1/emufx.c | |
parent | fe8be10786c040bce53c18048d75b1b23aec64ae (diff) |
[ALSA] emu10k1 - Add PM support
Modules: EMU10K1/EMU10K2 driver
Add PM support to emu10k1 driver.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/emu10k1/emufx.c')
-rw-r--r-- | sound/pci/emu10k1/emufx.c | 121 |
1 files changed, 114 insertions, 7 deletions
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index f4452c5cb4cd..a44e4fdfc025 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -1071,9 +1071,6 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1071 | u32 *gpr_map; | 1071 | u32 *gpr_map; |
1072 | mm_segment_t seg; | 1072 | mm_segment_t seg; |
1073 | 1073 | ||
1074 | spin_lock_init(&emu->fx8010.irq_lock); | ||
1075 | INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); | ||
1076 | |||
1077 | if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL || | 1074 | if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL || |
1078 | (icode->gpr_map = (u_int32_t __user *) | 1075 | (icode->gpr_map = (u_int32_t __user *) |
1079 | kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), | 1076 | kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), |
@@ -1541,9 +1538,6 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
1541 | u32 *gpr_map; | 1538 | u32 *gpr_map; |
1542 | mm_segment_t seg; | 1539 | mm_segment_t seg; |
1543 | 1540 | ||
1544 | spin_lock_init(&emu->fx8010.irq_lock); | ||
1545 | INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); | ||
1546 | |||
1547 | if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL) | 1541 | if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL) |
1548 | return -ENOMEM; | 1542 | return -ENOMEM; |
1549 | if ((icode->gpr_map = (u_int32_t __user *) | 1543 | if ((icode->gpr_map = (u_int32_t __user *) |
@@ -2102,6 +2096,8 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
2102 | 2096 | ||
2103 | int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | 2097 | int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu) |
2104 | { | 2098 | { |
2099 | spin_lock_init(&emu->fx8010.irq_lock); | ||
2100 | INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); | ||
2105 | if (emu->audigy) | 2101 | if (emu->audigy) |
2106 | return _snd_emu10k1_audigy_init_efx(emu); | 2102 | return _snd_emu10k1_audigy_init_efx(emu); |
2107 | else | 2103 | else |
@@ -2171,7 +2167,7 @@ int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size) | |||
2171 | snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); | 2167 | snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); |
2172 | spin_lock_irq(&emu->emu_lock); | 2168 | spin_lock_irq(&emu->emu_lock); |
2173 | outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); | 2169 | outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); |
2174 | spin_unlock_irq(&emu->emu_lock); | 2170 | spin_unlock_irq(&emu->emu_lock); |
2175 | } | 2171 | } |
2176 | 2172 | ||
2177 | return 0; | 2173 | return 0; |
@@ -2387,3 +2383,114 @@ int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct | |||
2387 | *rhwdep = hw; | 2383 | *rhwdep = hw; |
2388 | return 0; | 2384 | return 0; |
2389 | } | 2385 | } |
2386 | |||
2387 | #ifdef CONFIG_PM | ||
2388 | int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) | ||
2389 | { | ||
2390 | int len; | ||
2391 | |||
2392 | len = emu->audigy ? 0x200 : 0x100; | ||
2393 | emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL); | ||
2394 | if (! emu->saved_gpr) | ||
2395 | return -ENOMEM; | ||
2396 | len = emu->audigy ? 0x100 : 0xa0; | ||
2397 | emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL); | ||
2398 | emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL); | ||
2399 | if (! emu->tram_val_saved || ! emu->tram_addr_saved) | ||
2400 | return -ENOMEM; | ||
2401 | len = emu->audigy ? 2 * 1024 : 2 * 512; | ||
2402 | emu->saved_icode = vmalloc(len * 4); | ||
2403 | if (! emu->saved_icode) | ||
2404 | return -ENOMEM; | ||
2405 | return 0; | ||
2406 | } | ||
2407 | |||
2408 | void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu) | ||
2409 | { | ||
2410 | kfree(emu->saved_gpr); | ||
2411 | kfree(emu->tram_val_saved); | ||
2412 | kfree(emu->tram_addr_saved); | ||
2413 | vfree(emu->saved_icode); | ||
2414 | } | ||
2415 | |||
2416 | /* | ||
2417 | * save/restore GPR, TRAM and codes | ||
2418 | */ | ||
2419 | void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu) | ||
2420 | { | ||
2421 | int i, len; | ||
2422 | |||
2423 | len = emu->audigy ? 0x200 : 0x100; | ||
2424 | for (i = 0; i < len; i++) | ||
2425 | emu->saved_gpr[i] = snd_emu10k1_ptr_read(emu, emu->gpr_base + i, 0); | ||
2426 | |||
2427 | len = emu->audigy ? 0x100 : 0xa0; | ||
2428 | for (i = 0; i < len; i++) { | ||
2429 | emu->tram_val_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + i, 0); | ||
2430 | emu->tram_addr_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + i, 0); | ||
2431 | if (emu->audigy) { | ||
2432 | emu->tram_addr_saved[i] >>= 12; | ||
2433 | emu->tram_addr_saved[i] |= | ||
2434 | snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + i, 0) << 20; | ||
2435 | } | ||
2436 | } | ||
2437 | |||
2438 | len = emu->audigy ? 2 * 1024 : 2 * 512; | ||
2439 | for (i = 0; i < len; i++) | ||
2440 | emu->saved_icode[i] = snd_emu10k1_efx_read(emu, i); | ||
2441 | } | ||
2442 | |||
2443 | void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu) | ||
2444 | { | ||
2445 | int i, len; | ||
2446 | |||
2447 | /* set up TRAM */ | ||
2448 | if (emu->fx8010.etram_pages.bytes > 0) { | ||
2449 | unsigned size, size_reg = 0; | ||
2450 | size = emu->fx8010.etram_pages.bytes / 2; | ||
2451 | size = (size - 1) >> 13; | ||
2452 | while (size) { | ||
2453 | size >>= 1; | ||
2454 | size_reg++; | ||
2455 | } | ||
2456 | outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); | ||
2457 | snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr); | ||
2458 | snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); | ||
2459 | outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); | ||
2460 | } | ||
2461 | |||
2462 | if (emu->audigy) | ||
2463 | snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP); | ||
2464 | else | ||
2465 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); | ||
2466 | |||
2467 | len = emu->audigy ? 0x200 : 0x100; | ||
2468 | for (i = 0; i < len; i++) | ||
2469 | snd_emu10k1_ptr_write(emu, emu->gpr_base + i, 0, emu->saved_gpr[i]); | ||
2470 | |||
2471 | len = emu->audigy ? 0x100 : 0xa0; | ||
2472 | for (i = 0; i < len; i++) { | ||
2473 | snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + i, 0, | ||
2474 | emu->tram_val_saved[i]); | ||
2475 | if (! emu->audigy) | ||
2476 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, | ||
2477 | emu->tram_addr_saved[i]); | ||
2478 | else { | ||
2479 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, | ||
2480 | emu->tram_addr_saved[i] << 12); | ||
2481 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, | ||
2482 | emu->tram_addr_saved[i] >> 20); | ||
2483 | } | ||
2484 | } | ||
2485 | |||
2486 | len = emu->audigy ? 2 * 1024 : 2 * 512; | ||
2487 | for (i = 0; i < len; i++) | ||
2488 | snd_emu10k1_efx_write(emu, i, emu->saved_icode[i]); | ||
2489 | |||
2490 | /* start FX processor when the DSP code is updated */ | ||
2491 | if (emu->audigy) | ||
2492 | snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); | ||
2493 | else | ||
2494 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); | ||
2495 | } | ||
2496 | #endif | ||