Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: AMD: Manage ACP 2.x SRAM banks power

ACP SRAM banks gets turned on when ACP is powered on.
Not all banks are used for playback/capture. So, power on
required banks during audio device open and power off during
audio device close.

Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Maruthi Srinivas Bayyavarapu and committed by
Mark Brown
c36d9b3f 1927da93

+87 -7
+87 -7
sound/soc/amd/acp-pcm-dma.c
··· 376 376 return 0; 377 377 } 378 378 379 + static void acp_set_sram_bank_state(void __iomem *acp_mmio, u16 bank, 380 + bool power_on) 381 + { 382 + u32 val, req_reg, sts_reg, sts_reg_mask; 383 + u32 loops = 1000; 384 + 385 + if (bank < 32) { 386 + req_reg = mmACP_MEM_SHUT_DOWN_REQ_LO; 387 + sts_reg = mmACP_MEM_SHUT_DOWN_STS_LO; 388 + sts_reg_mask = 0xFFFFFFFF; 389 + 390 + } else { 391 + bank -= 32; 392 + req_reg = mmACP_MEM_SHUT_DOWN_REQ_HI; 393 + sts_reg = mmACP_MEM_SHUT_DOWN_STS_HI; 394 + sts_reg_mask = 0x0000FFFF; 395 + } 396 + 397 + val = acp_reg_read(acp_mmio, req_reg); 398 + if (val & (1 << bank)) { 399 + /* bank is in off state */ 400 + if (power_on == true) 401 + /* request to on */ 402 + val &= ~(1 << bank); 403 + else 404 + /* request to off */ 405 + return; 406 + } else { 407 + /* bank is in on state */ 408 + if (power_on == false) 409 + /* request to off */ 410 + val |= 1 << bank; 411 + else 412 + /* request to on */ 413 + return; 414 + } 415 + acp_reg_write(val, acp_mmio, req_reg); 416 + 417 + while (acp_reg_read(acp_mmio, sts_reg) != sts_reg_mask) { 418 + if (!loops--) { 419 + pr_err("ACP SRAM bank %d state change failed\n", bank); 420 + break; 421 + } 422 + cpu_relax(); 423 + } 424 + } 425 + 379 426 /* Initialize and bring ACP hardware to default state. */ 380 427 static int acp_init(void __iomem *acp_mmio) 381 428 { 429 + u16 bank; 382 430 u32 val, count, sram_pte_offset; 383 431 384 432 /* Assert Soft reset of ACP */ ··· 494 446 acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR); 495 447 acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK, 496 448 acp_mmio, mmACP_EXTERNAL_INTR_CNTL); 449 + 450 + /* When ACP_TILE_P1 is turned on, all SRAM banks get turned on. 451 + * Now, turn off all of them. This can't be done in 'poweron' of 452 + * ACP pm domain, as this requires ACP to be initialized. 453 + */ 454 + for (bank = 1; bank < 48; bank++) 455 + acp_set_sram_bank_state(acp_mmio, bank, false); 497 456 498 457 return 0; 499 458 } ··· 614 559 615 560 static int acp_dma_open(struct snd_pcm_substream *substream) 616 561 { 562 + u16 bank; 617 563 int ret = 0; 618 564 struct snd_pcm_runtime *runtime = substream->runtime; 619 565 struct snd_soc_pcm_runtime *prtd = substream->private_data; ··· 648 592 if (!intr_data->play_stream && !intr_data->capture_stream) 649 593 acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); 650 594 651 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 595 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 652 596 intr_data->play_stream = substream; 653 - else 597 + for (bank = 1; bank <= 4; bank++) 598 + acp_set_sram_bank_state(intr_data->acp_mmio, bank, 599 + true); 600 + } else { 654 601 intr_data->capture_stream = substream; 602 + for (bank = 5; bank <= 8; bank++) 603 + acp_set_sram_bank_state(intr_data->acp_mmio, bank, 604 + true); 605 + } 655 606 656 607 return 0; 657 608 } ··· 690 627 pg = virt_to_page(substream->dma_buffer.area); 691 628 692 629 if (pg != NULL) { 630 + acp_set_sram_bank_state(rtd->acp_mmio, 0, true); 693 631 /* Save for runtime private data */ 694 632 rtd->pg = pg; 695 633 rtd->order = get_order(size); ··· 866 802 867 803 static int acp_dma_close(struct snd_pcm_substream *substream) 868 804 { 805 + u16 bank; 869 806 struct snd_pcm_runtime *runtime = substream->runtime; 870 807 struct audio_substream_data *rtd = runtime->private_data; 871 808 struct snd_soc_pcm_runtime *prtd = substream->private_data; ··· 874 809 875 810 kfree(rtd); 876 811 877 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 812 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 878 813 adata->play_stream = NULL; 879 - else 814 + for (bank = 1; bank <= 4; bank++) 815 + acp_set_sram_bank_state(adata->acp_mmio, bank, 816 + false); 817 + } else { 880 818 adata->capture_stream = NULL; 819 + for (bank = 5; bank <= 8; bank++) 820 + acp_set_sram_bank_state(adata->acp_mmio, bank, 821 + false); 822 + } 881 823 882 824 /* Disable ACP irq, when the current stream is being closed and 883 825 * another stream is also not active. ··· 978 906 979 907 static int acp_pcm_resume(struct device *dev) 980 908 { 909 + u16 bank; 981 910 struct audio_drv_data *adata = dev_get_drvdata(dev); 982 911 983 912 acp_init(adata->acp_mmio); 984 913 985 - if (adata->play_stream && adata->play_stream->runtime) 914 + if (adata->play_stream && adata->play_stream->runtime) { 915 + for (bank = 1; bank <= 4; bank++) 916 + acp_set_sram_bank_state(adata->acp_mmio, bank, 917 + true); 986 918 config_acp_dma(adata->acp_mmio, 987 919 adata->play_stream->runtime->private_data); 988 - if (adata->capture_stream && adata->capture_stream->runtime) 920 + } 921 + if (adata->capture_stream && adata->capture_stream->runtime) { 922 + for (bank = 5; bank <= 8; bank++) 923 + acp_set_sram_bank_state(adata->acp_mmio, bank, 924 + true); 989 925 config_acp_dma(adata->acp_mmio, 990 926 adata->capture_stream->runtime->private_data); 991 - 927 + } 992 928 acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB); 993 929 return 0; 994 930 }