0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/of_device.h>
0011 #include <linux/of_platform.h>
0012
0013 #include <sound/pcm.h>
0014 #include <sound/pcm_params.h>
0015 #include <sound/soc.h>
0016
0017 #include <asm/mpc52xx_psc.h>
0018
0019 #include "mpc5200_dma.h"
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #define PSC_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
0030
0031
0032
0033
0034 #define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
0035 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
0036
0037 static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
0038 struct snd_pcm_hw_params *params,
0039 struct snd_soc_dai *dai)
0040 {
0041 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0042 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0043 u32 mode;
0044
0045 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
0046 " periods=%i buffer_size=%i buffer_bytes=%i\n",
0047 __func__, substream, params_period_size(params),
0048 params_period_bytes(params), params_periods(params),
0049 params_buffer_size(params), params_buffer_bytes(params));
0050
0051 switch (params_format(params)) {
0052 case SNDRV_PCM_FORMAT_S8:
0053 mode = MPC52xx_PSC_SICR_SIM_CODEC_8;
0054 break;
0055 case SNDRV_PCM_FORMAT_S16_BE:
0056 mode = MPC52xx_PSC_SICR_SIM_CODEC_16;
0057 break;
0058 case SNDRV_PCM_FORMAT_S24_BE:
0059 mode = MPC52xx_PSC_SICR_SIM_CODEC_24;
0060 break;
0061 case SNDRV_PCM_FORMAT_S32_BE:
0062 mode = MPC52xx_PSC_SICR_SIM_CODEC_32;
0063 break;
0064 default:
0065 dev_dbg(psc_dma->dev, "invalid format\n");
0066 return -EINVAL;
0067 }
0068 out_be32(&psc_dma->psc_regs->sicr, psc_dma->sicr | mode);
0069
0070 return 0;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
0088 int clk_id, unsigned int freq, int dir)
0089 {
0090 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
0091 dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
0092 cpu_dai, dir);
0093 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
0094 }
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
0108 {
0109 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
0110 dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
0111 cpu_dai, format);
0112 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 static const struct snd_soc_dai_ops psc_i2s_dai_ops = {
0126 .hw_params = psc_i2s_hw_params,
0127 .set_sysclk = psc_i2s_set_sysclk,
0128 .set_fmt = psc_i2s_set_fmt,
0129 };
0130
0131 static struct snd_soc_dai_driver psc_i2s_dai[] = {{
0132 .name = "mpc5200-psc-i2s.0",
0133 .playback = {
0134 .stream_name = "I2S Playback",
0135 .channels_min = 2,
0136 .channels_max = 2,
0137 .rates = PSC_I2S_RATES,
0138 .formats = PSC_I2S_FORMATS,
0139 },
0140 .capture = {
0141 .stream_name = "I2S Capture",
0142 .channels_min = 2,
0143 .channels_max = 2,
0144 .rates = PSC_I2S_RATES,
0145 .formats = PSC_I2S_FORMATS,
0146 },
0147 .ops = &psc_i2s_dai_ops,
0148 } };
0149
0150 static const struct snd_soc_component_driver psc_i2s_component = {
0151 .name = "mpc5200-i2s",
0152 .legacy_dai_naming = 1,
0153 };
0154
0155
0156
0157
0158
0159
0160 static int psc_i2s_of_probe(struct platform_device *op)
0161 {
0162 int rc;
0163 struct psc_dma *psc_dma;
0164 struct mpc52xx_psc __iomem *regs;
0165
0166 rc = mpc5200_audio_dma_create(op);
0167 if (rc != 0)
0168 return rc;
0169
0170 rc = snd_soc_register_component(&op->dev, &psc_i2s_component,
0171 psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
0172 if (rc != 0) {
0173 pr_err("Failed to register DAI\n");
0174 return rc;
0175 }
0176
0177 psc_dma = dev_get_drvdata(&op->dev);
0178 regs = psc_dma->psc_regs;
0179
0180
0181 psc_dma->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S |
0182 MPC52xx_PSC_SICR_CLKPOL;
0183 out_be32(&psc_dma->psc_regs->sicr,
0184 psc_dma->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8);
0185
0186
0187
0188 if (!of_get_property(op->dev.of_node, "codec-handle", NULL))
0189 return 0;
0190
0191
0192
0193
0194
0195
0196 while ((in_8(®s->ipcr_acr.ipcr) & 0x80) != 0)
0197 ;
0198
0199 while ((in_8(®s->ipcr_acr.ipcr) & 0x80) == 0)
0200 ;
0201
0202
0203
0204
0205
0206 out_8(&psc_dma->psc_regs->command,
0207 MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
0208
0209 return 0;
0210
0211 }
0212
0213 static int psc_i2s_of_remove(struct platform_device *op)
0214 {
0215 mpc5200_audio_dma_destroy(op);
0216 snd_soc_unregister_component(&op->dev);
0217 return 0;
0218 }
0219
0220
0221 static const struct of_device_id psc_i2s_match[] = {
0222 { .compatible = "fsl,mpc5200-psc-i2s", },
0223 { .compatible = "fsl,mpc5200b-psc-i2s", },
0224 {}
0225 };
0226 MODULE_DEVICE_TABLE(of, psc_i2s_match);
0227
0228 static struct platform_driver psc_i2s_driver = {
0229 .probe = psc_i2s_of_probe,
0230 .remove = psc_i2s_of_remove,
0231 .driver = {
0232 .name = "mpc5200-psc-i2s",
0233 .of_match_table = psc_i2s_match,
0234 },
0235 };
0236
0237 module_platform_driver(psc_i2s_driver);
0238
0239 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
0240 MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
0241 MODULE_LICENSE("GPL");
0242