diff options
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
-rw-r--r-- | sound/soc/pxa/pxa-ssp.c | 93 |
1 files changed, 62 insertions, 31 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index e69397f40f72..9e95e5117c88 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -42,11 +42,14 @@ | |||
42 | * SSP audio private data | 42 | * SSP audio private data |
43 | */ | 43 | */ |
44 | struct ssp_priv { | 44 | struct ssp_priv { |
45 | struct ssp_dev dev; | 45 | struct ssp_device *ssp; |
46 | unsigned int sysclk; | 46 | unsigned int sysclk; |
47 | int dai_fmt; | 47 | int dai_fmt; |
48 | #ifdef CONFIG_PM | 48 | #ifdef CONFIG_PM |
49 | struct ssp_state state; | 49 | uint32_t cr0; |
50 | uint32_t cr1; | ||
51 | uint32_t to; | ||
52 | uint32_t psp; | ||
50 | #endif | 53 | #endif |
51 | }; | 54 | }; |
52 | 55 | ||
@@ -61,6 +64,22 @@ static void dump_registers(struct ssp_device *ssp) | |||
61 | ssp_read_reg(ssp, SSACD)); | 64 | ssp_read_reg(ssp, SSACD)); |
62 | } | 65 | } |
63 | 66 | ||
67 | static void ssp_enable(struct ssp_device *ssp) | ||
68 | { | ||
69 | uint32_t sscr0; | ||
70 | |||
71 | sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE; | ||
72 | __raw_writel(sscr0, ssp->mmio_base + SSCR0); | ||
73 | } | ||
74 | |||
75 | static void ssp_disable(struct ssp_device *ssp) | ||
76 | { | ||
77 | uint32_t sscr0; | ||
78 | |||
79 | sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE; | ||
80 | __raw_writel(sscr0, ssp->mmio_base + SSCR0); | ||
81 | } | ||
82 | |||
64 | struct pxa2xx_pcm_dma_data { | 83 | struct pxa2xx_pcm_dma_data { |
65 | struct pxa2xx_pcm_dma_params params; | 84 | struct pxa2xx_pcm_dma_params params; |
66 | char name[20]; | 85 | char name[20]; |
@@ -94,13 +113,12 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
94 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 113 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
95 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 114 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
96 | struct ssp_priv *priv = cpu_dai->private_data; | 115 | struct ssp_priv *priv = cpu_dai->private_data; |
116 | struct ssp_device *ssp = priv->ssp; | ||
97 | int ret = 0; | 117 | int ret = 0; |
98 | 118 | ||
99 | if (!cpu_dai->active) { | 119 | if (!cpu_dai->active) { |
100 | priv->dev.port = cpu_dai->id + 1; | 120 | clk_enable(ssp->clk); |
101 | priv->dev.irq = NO_IRQ; | 121 | ssp_disable(ssp); |
102 | clk_enable(priv->dev.ssp->clk); | ||
103 | ssp_disable(&priv->dev); | ||
104 | } | 122 | } |
105 | 123 | ||
106 | if (cpu_dai->dma_data) { | 124 | if (cpu_dai->dma_data) { |
@@ -116,10 +134,11 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | |||
116 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 134 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
117 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 135 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
118 | struct ssp_priv *priv = cpu_dai->private_data; | 136 | struct ssp_priv *priv = cpu_dai->private_data; |
137 | struct ssp_device *ssp = priv->ssp; | ||
119 | 138 | ||
120 | if (!cpu_dai->active) { | 139 | if (!cpu_dai->active) { |
121 | ssp_disable(&priv->dev); | 140 | ssp_disable(ssp); |
122 | clk_disable(priv->dev.ssp->clk); | 141 | clk_disable(ssp->clk); |
123 | } | 142 | } |
124 | 143 | ||
125 | if (cpu_dai->dma_data) { | 144 | if (cpu_dai->dma_data) { |
@@ -133,27 +152,39 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | |||
133 | static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) | 152 | static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) |
134 | { | 153 | { |
135 | struct ssp_priv *priv = cpu_dai->private_data; | 154 | struct ssp_priv *priv = cpu_dai->private_data; |
155 | struct ssp_device *ssp = priv->ssp; | ||
136 | 156 | ||
137 | if (!cpu_dai->active) | 157 | if (!cpu_dai->active) |
138 | clk_enable(priv->dev.ssp->clk); | 158 | clk_enable(ssp->clk); |
139 | 159 | ||
140 | ssp_save_state(&priv->dev, &priv->state); | 160 | priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0); |
141 | clk_disable(priv->dev.ssp->clk); | 161 | priv->cr1 = __raw_readl(ssp->mmio_base + SSCR1); |
162 | priv->to = __raw_readl(ssp->mmio_base + SSTO); | ||
163 | priv->psp = __raw_readl(ssp->mmio_base + SSPSP); | ||
142 | 164 | ||
165 | ssp_disable(ssp); | ||
166 | clk_disable(ssp->clk); | ||
143 | return 0; | 167 | return 0; |
144 | } | 168 | } |
145 | 169 | ||
146 | static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) | 170 | static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) |
147 | { | 171 | { |
148 | struct ssp_priv *priv = cpu_dai->private_data; | 172 | struct ssp_priv *priv = cpu_dai->private_data; |
173 | struct ssp_device *ssp = priv->ssp; | ||
174 | uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; | ||
175 | |||
176 | clk_enable(ssp->clk); | ||
149 | 177 | ||
150 | clk_enable(priv->dev.ssp->clk); | 178 | __raw_writel(sssr, ssp->mmio_base + SSSR); |
151 | ssp_restore_state(&priv->dev, &priv->state); | 179 | __raw_writel(priv->cr0 & ~SSCR0_SSE, ssp->mmio_base + SSCR0); |
180 | __raw_writel(priv->cr1, ssp->mmio_base + SSCR1); | ||
181 | __raw_writel(priv->to, ssp->mmio_base + SSTO); | ||
182 | __raw_writel(priv->psp, ssp->mmio_base + SSPSP); | ||
152 | 183 | ||
153 | if (cpu_dai->active) | 184 | if (cpu_dai->active) |
154 | ssp_enable(&priv->dev); | 185 | ssp_enable(ssp); |
155 | else | 186 | else |
156 | clk_disable(priv->dev.ssp->clk); | 187 | clk_disable(ssp->clk); |
157 | 188 | ||
158 | return 0; | 189 | return 0; |
159 | } | 190 | } |
@@ -203,7 +234,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
203 | int clk_id, unsigned int freq, int dir) | 234 | int clk_id, unsigned int freq, int dir) |
204 | { | 235 | { |
205 | struct ssp_priv *priv = cpu_dai->private_data; | 236 | struct ssp_priv *priv = cpu_dai->private_data; |
206 | struct ssp_device *ssp = priv->dev.ssp; | 237 | struct ssp_device *ssp = priv->ssp; |
207 | int val; | 238 | int val; |
208 | 239 | ||
209 | u32 sscr0 = ssp_read_reg(ssp, SSCR0) & | 240 | u32 sscr0 = ssp_read_reg(ssp, SSCR0) & |
@@ -244,11 +275,11 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
244 | /* The SSP clock must be disabled when changing SSP clock mode | 275 | /* The SSP clock must be disabled when changing SSP clock mode |
245 | * on PXA2xx. On PXA3xx it must be enabled when doing so. */ | 276 | * on PXA2xx. On PXA3xx it must be enabled when doing so. */ |
246 | if (!cpu_is_pxa3xx()) | 277 | if (!cpu_is_pxa3xx()) |
247 | clk_disable(priv->dev.ssp->clk); | 278 | clk_disable(ssp->clk); |
248 | val = ssp_read_reg(ssp, SSCR0) | sscr0; | 279 | val = ssp_read_reg(ssp, SSCR0) | sscr0; |
249 | ssp_write_reg(ssp, SSCR0, val); | 280 | ssp_write_reg(ssp, SSCR0, val); |
250 | if (!cpu_is_pxa3xx()) | 281 | if (!cpu_is_pxa3xx()) |
251 | clk_enable(priv->dev.ssp->clk); | 282 | clk_enable(ssp->clk); |
252 | 283 | ||
253 | return 0; | 284 | return 0; |
254 | } | 285 | } |
@@ -260,7 +291,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | |||
260 | int div_id, int div) | 291 | int div_id, int div) |
261 | { | 292 | { |
262 | struct ssp_priv *priv = cpu_dai->private_data; | 293 | struct ssp_priv *priv = cpu_dai->private_data; |
263 | struct ssp_device *ssp = priv->dev.ssp; | 294 | struct ssp_device *ssp = priv->ssp; |
264 | int val; | 295 | int val; |
265 | 296 | ||
266 | switch (div_id) { | 297 | switch (div_id) { |
@@ -311,7 +342,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, | |||
311 | int source, unsigned int freq_in, unsigned int freq_out) | 342 | int source, unsigned int freq_in, unsigned int freq_out) |
312 | { | 343 | { |
313 | struct ssp_priv *priv = cpu_dai->private_data; | 344 | struct ssp_priv *priv = cpu_dai->private_data; |
314 | struct ssp_device *ssp = priv->dev.ssp; | 345 | struct ssp_device *ssp = priv->ssp; |
315 | u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70; | 346 | u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70; |
316 | 347 | ||
317 | #if defined(CONFIG_PXA3xx) | 348 | #if defined(CONFIG_PXA3xx) |
@@ -380,7 +411,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | |||
380 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 411 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
381 | { | 412 | { |
382 | struct ssp_priv *priv = cpu_dai->private_data; | 413 | struct ssp_priv *priv = cpu_dai->private_data; |
383 | struct ssp_device *ssp = priv->dev.ssp; | 414 | struct ssp_device *ssp = priv->ssp; |
384 | u32 sscr0; | 415 | u32 sscr0; |
385 | 416 | ||
386 | sscr0 = ssp_read_reg(ssp, SSCR0); | 417 | sscr0 = ssp_read_reg(ssp, SSCR0); |
@@ -415,7 +446,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, | |||
415 | int tristate) | 446 | int tristate) |
416 | { | 447 | { |
417 | struct ssp_priv *priv = cpu_dai->private_data; | 448 | struct ssp_priv *priv = cpu_dai->private_data; |
418 | struct ssp_device *ssp = priv->dev.ssp; | 449 | struct ssp_device *ssp = priv->ssp; |
419 | u32 sscr1; | 450 | u32 sscr1; |
420 | 451 | ||
421 | sscr1 = ssp_read_reg(ssp, SSCR1); | 452 | sscr1 = ssp_read_reg(ssp, SSCR1); |
@@ -437,7 +468,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
437 | unsigned int fmt) | 468 | unsigned int fmt) |
438 | { | 469 | { |
439 | struct ssp_priv *priv = cpu_dai->private_data; | 470 | struct ssp_priv *priv = cpu_dai->private_data; |
440 | struct ssp_device *ssp = priv->dev.ssp; | 471 | struct ssp_device *ssp = priv->ssp; |
441 | u32 sscr0; | 472 | u32 sscr0; |
442 | u32 sscr1; | 473 | u32 sscr1; |
443 | u32 sspsp; | 474 | u32 sspsp; |
@@ -532,7 +563,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
532 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 563 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
533 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 564 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
534 | struct ssp_priv *priv = cpu_dai->private_data; | 565 | struct ssp_priv *priv = cpu_dai->private_data; |
535 | struct ssp_device *ssp = priv->dev.ssp; | 566 | struct ssp_device *ssp = priv->ssp; |
536 | int chn = params_channels(params); | 567 | int chn = params_channels(params); |
537 | u32 sscr0; | 568 | u32 sscr0; |
538 | u32 sspsp; | 569 | u32 sspsp; |
@@ -642,12 +673,12 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | |||
642 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 673 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
643 | int ret = 0; | 674 | int ret = 0; |
644 | struct ssp_priv *priv = cpu_dai->private_data; | 675 | struct ssp_priv *priv = cpu_dai->private_data; |
645 | struct ssp_device *ssp = priv->dev.ssp; | 676 | struct ssp_device *ssp = priv->ssp; |
646 | int val; | 677 | int val; |
647 | 678 | ||
648 | switch (cmd) { | 679 | switch (cmd) { |
649 | case SNDRV_PCM_TRIGGER_RESUME: | 680 | case SNDRV_PCM_TRIGGER_RESUME: |
650 | ssp_enable(&priv->dev); | 681 | ssp_enable(ssp); |
651 | break; | 682 | break; |
652 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 683 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
653 | val = ssp_read_reg(ssp, SSCR1); | 684 | val = ssp_read_reg(ssp, SSCR1); |
@@ -666,7 +697,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | |||
666 | else | 697 | else |
667 | val |= SSCR1_RSRE; | 698 | val |= SSCR1_RSRE; |
668 | ssp_write_reg(ssp, SSCR1, val); | 699 | ssp_write_reg(ssp, SSCR1, val); |
669 | ssp_enable(&priv->dev); | 700 | ssp_enable(ssp); |
670 | break; | 701 | break; |
671 | case SNDRV_PCM_TRIGGER_STOP: | 702 | case SNDRV_PCM_TRIGGER_STOP: |
672 | val = ssp_read_reg(ssp, SSCR1); | 703 | val = ssp_read_reg(ssp, SSCR1); |
@@ -677,7 +708,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | |||
677 | ssp_write_reg(ssp, SSCR1, val); | 708 | ssp_write_reg(ssp, SSCR1, val); |
678 | break; | 709 | break; |
679 | case SNDRV_PCM_TRIGGER_SUSPEND: | 710 | case SNDRV_PCM_TRIGGER_SUSPEND: |
680 | ssp_disable(&priv->dev); | 711 | ssp_disable(ssp); |
681 | break; | 712 | break; |
682 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 713 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
683 | val = ssp_read_reg(ssp, SSCR1); | 714 | val = ssp_read_reg(ssp, SSCR1); |
@@ -707,8 +738,8 @@ static int pxa_ssp_probe(struct platform_device *pdev, | |||
707 | if (!priv) | 738 | if (!priv) |
708 | return -ENOMEM; | 739 | return -ENOMEM; |
709 | 740 | ||
710 | priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio"); | 741 | priv->ssp = ssp_request(dai->id + 1, "SoC audio"); |
711 | if (priv->dev.ssp == NULL) { | 742 | if (priv->ssp == NULL) { |
712 | ret = -ENODEV; | 743 | ret = -ENODEV; |
713 | goto err_priv; | 744 | goto err_priv; |
714 | } | 745 | } |
@@ -727,7 +758,7 @@ static void pxa_ssp_remove(struct platform_device *pdev, | |||
727 | struct snd_soc_dai *dai) | 758 | struct snd_soc_dai *dai) |
728 | { | 759 | { |
729 | struct ssp_priv *priv = dai->private_data; | 760 | struct ssp_priv *priv = dai->private_data; |
730 | ssp_free(priv->dev.ssp); | 761 | ssp_free(priv->ssp); |
731 | } | 762 | } |
732 | 763 | ||
733 | #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 764 | #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |