aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2014-10-01 09:02:12 -0400
committerMark Brown <broonie@kernel.org>2014-10-01 12:02:09 -0400
commitf114ce605daa1fb9d4efa253ea6d5bd4802902af (patch)
tree9f688ab28ccc755e99ceda4a4ad432a0c2b1144d
parent1cc0c054f380c1c477642b5d9d9d9f697f641dbc (diff)
ASoC: davinvi-mcasp: Proper suspend/resume support while audio is active
If the board is sent to suspend (deep sleep) the McASP context will be lost. In case when suspend happens during active audio we need to save and restore more registers, which was configured during hw_param times as well. We need to add more config registers, AFIFO control registers and we also need to save and restore the serializer configuration as well. Since the number of serializers depends on the SoC we need to allocate the memory for it based on the num_serializer for the given McASP instance. With this patch the ongoing stream will resume after resuming from deep sleep. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/davinci/davinci-mcasp.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 63e24449eb89..5dcacc495438 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -49,11 +49,19 @@ static u32 context_regs[] = {
49 DAVINCI_MCASP_RXFMT_REG, 49 DAVINCI_MCASP_RXFMT_REG,
50 DAVINCI_MCASP_ACLKXCTL_REG, 50 DAVINCI_MCASP_ACLKXCTL_REG,
51 DAVINCI_MCASP_ACLKRCTL_REG, 51 DAVINCI_MCASP_ACLKRCTL_REG,
52 DAVINCI_MCASP_AHCLKXCTL_REG,
53 DAVINCI_MCASP_AHCLKRCTL_REG,
52 DAVINCI_MCASP_PDIR_REG, 54 DAVINCI_MCASP_PDIR_REG,
55 DAVINCI_MCASP_RXMASK_REG,
56 DAVINCI_MCASP_TXMASK_REG,
57 DAVINCI_MCASP_RXTDM_REG,
58 DAVINCI_MCASP_TXTDM_REG,
53}; 59};
54 60
55struct davinci_mcasp_context { 61struct davinci_mcasp_context {
56 u32 config_regs[ARRAY_SIZE(context_regs)]; 62 u32 config_regs[ARRAY_SIZE(context_regs)];
63 u32 afifo_regs[2]; /* for read/write fifo control registers */
64 u32 *xrsr_regs; /* for serializer configuration */
57}; 65};
58 66
59struct davinci_mcasp { 67struct davinci_mcasp {
@@ -861,11 +869,25 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
861{ 869{
862 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); 870 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
863 struct davinci_mcasp_context *context = &mcasp->context; 871 struct davinci_mcasp_context *context = &mcasp->context;
872 u32 reg;
864 int i; 873 int i;
865 874
866 for (i = 0; i < ARRAY_SIZE(context_regs); i++) 875 for (i = 0; i < ARRAY_SIZE(context_regs); i++)
867 context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); 876 context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
868 877
878 if (mcasp->txnumevt) {
879 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
880 context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
881 }
882 if (mcasp->rxnumevt) {
883 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
884 context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
885 }
886
887 for (i = 0; i < mcasp->num_serializer; i++)
888 context->xrsr_regs[i] = mcasp_get_reg(mcasp,
889 DAVINCI_MCASP_XRSRCTL_REG(i));
890
869 return 0; 891 return 0;
870} 892}
871 893
@@ -873,11 +895,25 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
873{ 895{
874 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); 896 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
875 struct davinci_mcasp_context *context = &mcasp->context; 897 struct davinci_mcasp_context *context = &mcasp->context;
898 u32 reg;
876 int i; 899 int i;
877 900
878 for (i = 0; i < ARRAY_SIZE(context_regs); i++) 901 for (i = 0; i < ARRAY_SIZE(context_regs); i++)
879 mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); 902 mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
880 903
904 if (mcasp->txnumevt) {
905 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
906 mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
907 }
908 if (mcasp->rxnumevt) {
909 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
910 mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
911 }
912
913 for (i = 0; i < mcasp->num_serializer; i++)
914 mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
915 context->xrsr_regs[i]);
916
881 return 0; 917 return 0;
882} 918}
883#else 919#else
@@ -1195,6 +1231,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
1195 mcasp->op_mode = pdata->op_mode; 1231 mcasp->op_mode = pdata->op_mode;
1196 mcasp->tdm_slots = pdata->tdm_slots; 1232 mcasp->tdm_slots = pdata->tdm_slots;
1197 mcasp->num_serializer = pdata->num_serializer; 1233 mcasp->num_serializer = pdata->num_serializer;
1234#ifdef CONFIG_PM_SLEEP
1235 mcasp->context.xrsr_regs = devm_kzalloc(&pdev->dev,
1236 sizeof(u32) * mcasp->num_serializer,
1237 GFP_KERNEL);
1238#endif
1198 mcasp->serial_dir = pdata->serial_dir; 1239 mcasp->serial_dir = pdata->serial_dir;
1199 mcasp->version = pdata->version; 1240 mcasp->version = pdata->version;
1200 mcasp->txnumevt = pdata->txnumevt; 1241 mcasp->txnumevt = pdata->txnumevt;