1 // SPDX-License-Identifier: GPL-2.0
3 // linux/sound/mpc5200-ac97.c -- AC97 support for the Freescale MPC52xx chip.
5 // Copyright (C) 2009 Jon Smirl, Digispeaker
6 // Author: Jon Smirl <jonsmirl@gmail.com>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
10 #include <linux/of_platform.h>
11 #include <linux/delay.h>
12 #include <linux/time.h>
14 #include <sound/pcm.h>
15 #include <sound/pcm_params.h>
16 #include <sound/soc.h>
19 #include <asm/delay.h>
20 #include <asm/mpc52xx.h>
21 #include <asm/mpc52xx_psc.h>
23 #include "mpc5200_dma.h"
25 #define DRV_NAME "mpc5200-psc-ac97"
27 /* ALSA only supports a single AC97 device so static is recommend here */
28 static struct psc_dma
*psc_dma
;
30 static unsigned short psc_ac97_read(struct snd_ac97
*ac97
, unsigned short reg
)
35 mutex_lock(&psc_dma
->mutex
);
37 /* Wait for command send status zero = ready */
38 status
= spin_event_timeout(!(in_be16(&psc_dma
->psc_regs
->sr_csr
.status
) &
39 MPC52xx_PSC_SR_CMDSEND
), 100, 0);
41 pr_err("timeout on ac97 bus (rdy)\n");
42 mutex_unlock(&psc_dma
->mutex
);
46 /* Force clear the data valid bit */
47 in_be32(&psc_dma
->psc_regs
->ac97_data
);
50 out_be32(&psc_dma
->psc_regs
->ac97_cmd
, (1<<31) | ((reg
& 0x7f) << 24));
52 /* Wait for the answer */
53 status
= spin_event_timeout((in_be16(&psc_dma
->psc_regs
->sr_csr
.status
) &
54 MPC52xx_PSC_SR_DATA_VAL
), 100, 0);
56 pr_err("timeout on ac97 read (val) %x\n",
57 in_be16(&psc_dma
->psc_regs
->sr_csr
.status
));
58 mutex_unlock(&psc_dma
->mutex
);
62 val
= in_be32(&psc_dma
->psc_regs
->ac97_data
);
63 if (((val
>> 24) & 0x7f) != reg
) {
64 pr_err("reg echo error on ac97 read\n");
65 mutex_unlock(&psc_dma
->mutex
);
68 val
= (val
>> 8) & 0xffff;
70 mutex_unlock(&psc_dma
->mutex
);
71 return (unsigned short) val
;
74 static void psc_ac97_write(struct snd_ac97
*ac97
,
75 unsigned short reg
, unsigned short val
)
79 mutex_lock(&psc_dma
->mutex
);
81 /* Wait for command status zero = ready */
82 status
= spin_event_timeout(!(in_be16(&psc_dma
->psc_regs
->sr_csr
.status
) &
83 MPC52xx_PSC_SR_CMDSEND
), 100, 0);
85 pr_err("timeout on ac97 bus (write)\n");
89 out_be32(&psc_dma
->psc_regs
->ac97_cmd
,
90 ((reg
& 0x7f) << 24) | (val
<< 8));
93 mutex_unlock(&psc_dma
->mutex
);
96 static void psc_ac97_warm_reset(struct snd_ac97
*ac97
)
98 struct mpc52xx_psc __iomem
*regs
= psc_dma
->psc_regs
;
100 mutex_lock(&psc_dma
->mutex
);
102 out_be32(®s
->sicr
, psc_dma
->sicr
| MPC52xx_PSC_SICR_AWR
);
104 out_be32(®s
->sicr
, psc_dma
->sicr
);
106 mutex_unlock(&psc_dma
->mutex
);
109 static void psc_ac97_cold_reset(struct snd_ac97
*ac97
)
111 struct mpc52xx_psc __iomem
*regs
= psc_dma
->psc_regs
;
113 mutex_lock(&psc_dma
->mutex
);
114 dev_dbg(psc_dma
->dev
, "cold reset\n");
116 mpc5200_psc_ac97_gpio_reset(psc_dma
->id
);
118 /* Notify the PSC that a reset has occurred */
119 out_be32(®s
->sicr
, psc_dma
->sicr
| MPC52xx_PSC_SICR_ACRB
);
121 /* Re-enable RX and TX */
122 out_8(®s
->command
, MPC52xx_PSC_TX_ENABLE
| MPC52xx_PSC_RX_ENABLE
);
124 mutex_unlock(&psc_dma
->mutex
);
126 usleep_range(1000, 2000);
127 psc_ac97_warm_reset(ac97
);
130 static struct snd_ac97_bus_ops psc_ac97_ops
= {
131 .read
= psc_ac97_read
,
132 .write
= psc_ac97_write
,
133 .reset
= psc_ac97_cold_reset
,
134 .warm_reset
= psc_ac97_warm_reset
,
137 static int psc_ac97_hw_analog_params(struct snd_pcm_substream
*substream
,
138 struct snd_pcm_hw_params
*params
,
139 struct snd_soc_dai
*cpu_dai
)
141 struct psc_dma
*psc_dma
= snd_soc_dai_get_drvdata(cpu_dai
);
142 struct psc_dma_stream
*s
= to_psc_dma_stream(substream
, psc_dma
);
144 dev_dbg(psc_dma
->dev
, "%s(substream=%p) p_size=%i p_bytes=%i"
145 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
146 " rate=%i format=%i\n",
147 __func__
, substream
, params_period_size(params
),
148 params_period_bytes(params
), params_periods(params
),
149 params_buffer_size(params
), params_buffer_bytes(params
),
150 params_channels(params
), params_rate(params
),
151 params_format(params
));
153 /* Determine the set of enable bits to turn on */
154 s
->ac97_slot_bits
= (params_channels(params
) == 1) ? 0x100 : 0x300;
155 if (substream
->pstr
->stream
!= SNDRV_PCM_STREAM_CAPTURE
)
156 s
->ac97_slot_bits
<<= 16;
160 static int psc_ac97_hw_digital_params(struct snd_pcm_substream
*substream
,
161 struct snd_pcm_hw_params
*params
,
162 struct snd_soc_dai
*cpu_dai
)
164 struct psc_dma
*psc_dma
= snd_soc_dai_get_drvdata(cpu_dai
);
166 dev_dbg(psc_dma
->dev
, "%s(substream=%p)\n", __func__
, substream
);
168 if (params_channels(params
) == 1)
169 out_be32(&psc_dma
->psc_regs
->ac97_slots
, 0x01000000);
171 out_be32(&psc_dma
->psc_regs
->ac97_slots
, 0x03000000);
176 static int psc_ac97_trigger(struct snd_pcm_substream
*substream
, int cmd
,
177 struct snd_soc_dai
*dai
)
179 struct psc_dma
*psc_dma
= snd_soc_dai_get_drvdata(dai
);
180 struct psc_dma_stream
*s
= to_psc_dma_stream(substream
, psc_dma
);
183 case SNDRV_PCM_TRIGGER_START
:
184 dev_dbg(psc_dma
->dev
, "AC97 START: stream=%i\n",
185 substream
->pstr
->stream
);
187 /* Set the slot enable bits */
188 psc_dma
->slots
|= s
->ac97_slot_bits
;
189 out_be32(&psc_dma
->psc_regs
->ac97_slots
, psc_dma
->slots
);
192 case SNDRV_PCM_TRIGGER_STOP
:
193 dev_dbg(psc_dma
->dev
, "AC97 STOP: stream=%i\n",
194 substream
->pstr
->stream
);
196 /* Clear the slot enable bits */
197 psc_dma
->slots
&= ~(s
->ac97_slot_bits
);
198 out_be32(&psc_dma
->psc_regs
->ac97_slots
, psc_dma
->slots
);
204 static int psc_ac97_probe(struct snd_soc_dai
*cpu_dai
)
206 struct psc_dma
*psc_dma
= snd_soc_dai_get_drvdata(cpu_dai
);
207 struct mpc52xx_psc __iomem
*regs
= psc_dma
->psc_regs
;
210 out_8(®s
->command
, MPC52xx_PSC_TX_ENABLE
| MPC52xx_PSC_RX_ENABLE
);
214 /* ---------------------------------------------------------------------
217 * - Digital Audio Interface (DAI) template
218 * - create/destroy dai hooks
222 * psc_ac97_dai_template: template CPU Digital Audio Interface
224 static const struct snd_soc_dai_ops psc_ac97_analog_ops
= {
225 .hw_params
= psc_ac97_hw_analog_params
,
226 .trigger
= psc_ac97_trigger
,
229 static const struct snd_soc_dai_ops psc_ac97_digital_ops
= {
230 .hw_params
= psc_ac97_hw_digital_params
,
233 static struct snd_soc_dai_driver psc_ac97_dai
[] = {
235 .name
= "mpc5200-psc-ac97.0",
236 .probe
= psc_ac97_probe
,
238 .stream_name
= "AC97 Playback",
241 .rates
= SNDRV_PCM_RATE_8000_48000
,
242 .formats
= SNDRV_PCM_FMTBIT_S32_BE
,
245 .stream_name
= "AC97 Capture",
248 .rates
= SNDRV_PCM_RATE_8000_48000
,
249 .formats
= SNDRV_PCM_FMTBIT_S32_BE
,
251 .ops
= &psc_ac97_analog_ops
,
254 .name
= "mpc5200-psc-ac97.1",
256 .stream_name
= "AC97 SPDIF",
259 .rates
= SNDRV_PCM_RATE_32000
| \
260 SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
,
261 .formats
= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE
,
263 .ops
= &psc_ac97_digital_ops
,
266 static const struct snd_soc_component_driver psc_ac97_component
= {
271 /* ---------------------------------------------------------------------
272 * OF platform bus binding code:
273 * - Probe/remove operations
274 * - OF device match table
276 static int psc_ac97_of_probe(struct platform_device
*op
)
279 struct mpc52xx_psc __iomem
*regs
;
281 rc
= mpc5200_audio_dma_create(op
);
285 rc
= snd_soc_set_ac97_ops(&psc_ac97_ops
);
287 dev_err(&op
->dev
, "Failed to set AC'97 ops: %d\n", rc
);
291 rc
= snd_soc_register_component(&op
->dev
, &psc_ac97_component
,
292 psc_ac97_dai
, ARRAY_SIZE(psc_ac97_dai
));
294 dev_err(&op
->dev
, "Failed to register DAI\n");
298 psc_dma
= dev_get_drvdata(&op
->dev
);
299 regs
= psc_dma
->psc_regs
;
302 out_be16(&psc_dma
->psc_regs
->isr_imr
.imr
, psc_dma
->imr
);
304 /* Configure the serial interface mode to AC97 */
305 psc_dma
->sicr
= MPC52xx_PSC_SICR_SIM_AC97
| MPC52xx_PSC_SICR_ENAC97
;
306 out_be32(®s
->sicr
, psc_dma
->sicr
);
308 /* No slots active */
309 out_be32(®s
->ac97_slots
, 0x00000000);
314 static int psc_ac97_of_remove(struct platform_device
*op
)
316 mpc5200_audio_dma_destroy(op
);
317 snd_soc_unregister_component(&op
->dev
);
318 snd_soc_set_ac97_ops(NULL
);
322 /* Match table for of_platform binding */
323 static const struct of_device_id psc_ac97_match
[] = {
324 { .compatible
= "fsl,mpc5200-psc-ac97", },
325 { .compatible
= "fsl,mpc5200b-psc-ac97", },
328 MODULE_DEVICE_TABLE(of
, psc_ac97_match
);
330 static struct platform_driver psc_ac97_driver
= {
331 .probe
= psc_ac97_of_probe
,
332 .remove
= psc_ac97_of_remove
,
334 .name
= "mpc5200-psc-ac97",
335 .of_match_table
= psc_ac97_match
,
339 module_platform_driver(psc_ac97_driver
);
341 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
342 MODULE_DESCRIPTION("mpc5200 AC97 module");
343 MODULE_LICENSE("GPL");