aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa-ssp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
-rw-r--r--sound/soc/pxa/pxa-ssp.c218
1 files changed, 55 insertions, 163 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 286be31545df..19c45409d94c 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -50,139 +50,6 @@ struct ssp_priv {
50#endif 50#endif
51}; 51};
52 52
53#define PXA2xx_SSP1_BASE 0x41000000
54#define PXA27x_SSP2_BASE 0x41700000
55#define PXA27x_SSP3_BASE 0x41900000
56#define PXA3xx_SSP4_BASE 0x41a00000
57
58static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
59 .name = "SSP1 PCM Mono out",
60 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
61 .drcmr = &DRCMR(14),
62 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
63 DCMD_BURST16 | DCMD_WIDTH2,
64};
65
66static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
67 .name = "SSP1 PCM Mono in",
68 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
69 .drcmr = &DRCMR(13),
70 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
71 DCMD_BURST16 | DCMD_WIDTH2,
72};
73
74static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
75 .name = "SSP1 PCM Stereo out",
76 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
77 .drcmr = &DRCMR(14),
78 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
79 DCMD_BURST16 | DCMD_WIDTH4,
80};
81
82static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
83 .name = "SSP1 PCM Stereo in",
84 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
85 .drcmr = &DRCMR(13),
86 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
87 DCMD_BURST16 | DCMD_WIDTH4,
88};
89
90static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
91 .name = "SSP2 PCM Mono out",
92 .dev_addr = PXA27x_SSP2_BASE + SSDR,
93 .drcmr = &DRCMR(16),
94 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
95 DCMD_BURST16 | DCMD_WIDTH2,
96};
97
98static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
99 .name = "SSP2 PCM Mono in",
100 .dev_addr = PXA27x_SSP2_BASE + SSDR,
101 .drcmr = &DRCMR(15),
102 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
103 DCMD_BURST16 | DCMD_WIDTH2,
104};
105
106static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
107 .name = "SSP2 PCM Stereo out",
108 .dev_addr = PXA27x_SSP2_BASE + SSDR,
109 .drcmr = &DRCMR(16),
110 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
111 DCMD_BURST16 | DCMD_WIDTH4,
112};
113
114static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
115 .name = "SSP2 PCM Stereo in",
116 .dev_addr = PXA27x_SSP2_BASE + SSDR,
117 .drcmr = &DRCMR(15),
118 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
119 DCMD_BURST16 | DCMD_WIDTH4,
120};
121
122static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
123 .name = "SSP3 PCM Mono out",
124 .dev_addr = PXA27x_SSP3_BASE + SSDR,
125 .drcmr = &DRCMR(67),
126 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
127 DCMD_BURST16 | DCMD_WIDTH2,
128};
129
130static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
131 .name = "SSP3 PCM Mono in",
132 .dev_addr = PXA27x_SSP3_BASE + SSDR,
133 .drcmr = &DRCMR(66),
134 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
135 DCMD_BURST16 | DCMD_WIDTH2,
136};
137
138static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
139 .name = "SSP3 PCM Stereo out",
140 .dev_addr = PXA27x_SSP3_BASE + SSDR,
141 .drcmr = &DRCMR(67),
142 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
143 DCMD_BURST16 | DCMD_WIDTH4,
144};
145
146static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
147 .name = "SSP3 PCM Stereo in",
148 .dev_addr = PXA27x_SSP3_BASE + SSDR,
149 .drcmr = &DRCMR(66),
150 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
151 DCMD_BURST16 | DCMD_WIDTH4,
152};
153
154static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
155 .name = "SSP4 PCM Mono out",
156 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
157 .drcmr = &DRCMR(67),
158 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
159 DCMD_BURST16 | DCMD_WIDTH2,
160};
161
162static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
163 .name = "SSP4 PCM Mono in",
164 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
165 .drcmr = &DRCMR(66),
166 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
167 DCMD_BURST16 | DCMD_WIDTH2,
168};
169
170static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
171 .name = "SSP4 PCM Stereo out",
172 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
173 .drcmr = &DRCMR(67),
174 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
175 DCMD_BURST16 | DCMD_WIDTH4,
176};
177
178static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
179 .name = "SSP4 PCM Stereo in",
180 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
181 .drcmr = &DRCMR(66),
182 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
183 DCMD_BURST16 | DCMD_WIDTH4,
184};
185
186static void dump_registers(struct ssp_device *ssp) 53static void dump_registers(struct ssp_device *ssp)
187{ 54{
188 dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n", 55 dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
@@ -194,25 +61,33 @@ static void dump_registers(struct ssp_device *ssp)
194 ssp_read_reg(ssp, SSACD)); 61 ssp_read_reg(ssp, SSACD));
195} 62}
196 63
197static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = { 64struct pxa2xx_pcm_dma_data {
198 { 65 struct pxa2xx_pcm_dma_params params;
199 &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in, 66 char name[20];
200 &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
201 },
202 {
203 &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
204 &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
205 },
206 {
207 &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
208 &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
209 },
210 {
211 &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
212 &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
213 },
214}; 67};
215 68
69static struct pxa2xx_pcm_dma_params *
70ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
71{
72 struct pxa2xx_pcm_dma_data *dma;
73
74 dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL);
75 if (dma == NULL)
76 return NULL;
77
78 snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id,
79 width4 ? "32-bit" : "16-bit", out ? "out" : "in");
80
81 dma->params.name = dma->name;
82 dma->params.drcmr = &DRCMR(out ? ssp->drcmr_tx : ssp->drcmr_rx);
83 dma->params.dcmd = (out ? (DCMD_INCSRCADDR | DCMD_FLOWTRG) :
84 (DCMD_INCTRGADDR | DCMD_FLOWSRC)) |
85 (width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16;
86 dma->params.dev_addr = ssp->phys_base + SSDR;
87
88 return &dma->params;
89}
90
216static int pxa_ssp_startup(struct snd_pcm_substream *substream, 91static int pxa_ssp_startup(struct snd_pcm_substream *substream,
217 struct snd_soc_dai *dai) 92 struct snd_soc_dai *dai)
218{ 93{
@@ -227,6 +102,11 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
227 clk_enable(priv->dev.ssp->clk); 102 clk_enable(priv->dev.ssp->clk);
228 ssp_disable(&priv->dev); 103 ssp_disable(&priv->dev);
229 } 104 }
105
106 if (cpu_dai->dma_data) {
107 kfree(cpu_dai->dma_data);
108 cpu_dai->dma_data = NULL;
109 }
230 return ret; 110 return ret;
231} 111}
232 112
@@ -241,6 +121,11 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
241 ssp_disable(&priv->dev); 121 ssp_disable(&priv->dev);
242 clk_disable(priv->dev.ssp->clk); 122 clk_disable(priv->dev.ssp->clk);
243 } 123 }
124
125 if (cpu_dai->dma_data) {
126 kfree(cpu_dai->dma_data);
127 cpu_dai->dma_data = NULL;
128 }
244} 129}
245 130
246#ifdef CONFIG_PM 131#ifdef CONFIG_PM
@@ -323,7 +208,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
323 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); 208 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
324 209
325 dev_dbg(&ssp->pdev->dev, 210 dev_dbg(&ssp->pdev->dev,
326 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", 211 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %u\n",
327 cpu_dai->id, clk_id, freq); 212 cpu_dai->id, clk_id, freq);
328 213
329 switch (clk_id) { 214 switch (clk_id) {
@@ -472,7 +357,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
472 ssacd |= (0x6 << 4); 357 ssacd |= (0x6 << 4);
473 358
474 dev_dbg(&ssp->pdev->dev, 359 dev_dbg(&ssp->pdev->dev,
475 "Using SSACDD %x to supply %dHz\n", 360 "Using SSACDD %x to supply %uHz\n",
476 val, freq_out); 361 val, freq_out);
477 break; 362 break;
478 } 363 }
@@ -589,7 +474,10 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
589 case SND_SOC_DAIFMT_NB_IF: 474 case SND_SOC_DAIFMT_NB_IF:
590 break; 475 break;
591 case SND_SOC_DAIFMT_IB_IF: 476 case SND_SOC_DAIFMT_IB_IF:
592 sspsp |= SSPSP_SCMODE(3); 477 sspsp |= SSPSP_SCMODE(2);
478 break;
479 case SND_SOC_DAIFMT_IB_NF:
480 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
593 break; 481 break;
594 default: 482 default:
595 return -EINVAL; 483 return -EINVAL;
@@ -606,7 +494,13 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
606 case SND_SOC_DAIFMT_NB_NF: 494 case SND_SOC_DAIFMT_NB_NF:
607 sspsp |= SSPSP_SFRMP; 495 sspsp |= SSPSP_SFRMP;
608 break; 496 break;
497 case SND_SOC_DAIFMT_NB_IF:
498 break;
609 case SND_SOC_DAIFMT_IB_IF: 499 case SND_SOC_DAIFMT_IB_IF:
500 sspsp |= SSPSP_SCMODE(2);
501 break;
502 case SND_SOC_DAIFMT_IB_NF:
503 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
610 break; 504 break;
611 default: 505 default:
612 return -EINVAL; 506 return -EINVAL;
@@ -644,25 +538,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
644 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 538 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
645 struct ssp_priv *priv = cpu_dai->private_data; 539 struct ssp_priv *priv = cpu_dai->private_data;
646 struct ssp_device *ssp = priv->dev.ssp; 540 struct ssp_device *ssp = priv->dev.ssp;
647 int dma = 0, chn = params_channels(params); 541 int chn = params_channels(params);
648 u32 sscr0; 542 u32 sscr0;
649 u32 sspsp; 543 u32 sspsp;
650 int width = snd_pcm_format_physical_width(params_format(params)); 544 int width = snd_pcm_format_physical_width(params_format(params));
651 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; 545 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
652 546
653 /* select correct DMA params */ 547 /* generate correct DMA params */
654 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 548 if (cpu_dai->dma_data)
655 dma = 1; /* capture DMA offset is 1,3 */ 549 kfree(cpu_dai->dma_data);
550
656 /* Network mode with one active slot (ttsa == 1) can be used 551 /* Network mode with one active slot (ttsa == 1) can be used
657 * to force 16-bit frame width on the wire (for S16_LE), even 552 * to force 16-bit frame width on the wire (for S16_LE), even
658 * with two channels. Use 16-bit DMA transfers for this case. 553 * with two channels. Use 16-bit DMA transfers for this case.
659 */ 554 */
660 if (((chn == 2) && (ttsa != 1)) || (width == 32)) 555 cpu_dai->dma_data = ssp_get_dma_params(ssp,
661 dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */ 556 ((chn == 2) && (ttsa != 1)) || (width == 32),
662 557 substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
663 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
664
665 dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
666 558
667 /* we can only change the settings if the port is not in use */ 559 /* we can only change the settings if the port is not in use */
668 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 560 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)