diff options
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
| -rw-r--r-- | sound/soc/pxa/pxa-ssp.c | 218 |
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 | |||
| 58 | static 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 | |||
| 66 | static 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 | |||
| 74 | static 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 | |||
| 82 | static 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 | |||
| 90 | static 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 | |||
| 98 | static 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 | |||
| 106 | static 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 | |||
| 114 | static 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 | |||
| 122 | static 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 | |||
| 130 | static 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 | |||
| 138 | static 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 | |||
| 146 | static 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 | |||
| 154 | static 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 | |||
| 162 | static 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 | |||
| 170 | static 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 | |||
| 178 | static 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 | |||
| 186 | static void dump_registers(struct ssp_device *ssp) | 53 | static 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 | ||
| 197 | static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = { | 64 | struct 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 | ||
| 69 | static struct pxa2xx_pcm_dma_params * | ||
| 70 | ssp_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 | |||
| 216 | static int pxa_ssp_startup(struct snd_pcm_substream *substream, | 91 | static 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) |
