343 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// linux/sound/mpc5200-ac97.c -- AC97 support for the Freescale MPC52xx chip.4//5// Copyright (C) 2009 Jon Smirl, Digispeaker6// Author: Jon Smirl <jonsmirl@gmail.com>7 8#include <linux/mod_devicetable.h>9#include <linux/module.h>10#include <linux/delay.h>11#include <linux/time.h>12 13#include <sound/pcm.h>14#include <sound/pcm_params.h>15#include <sound/soc.h>16 17#include <asm/time.h>18#include <asm/delay.h>19#include <asm/mpc52xx.h>20#include <asm/mpc52xx_psc.h>21 22#include "mpc5200_dma.h"23 24#define DRV_NAME "mpc5200-psc-ac97"25 26/* ALSA only supports a single AC97 device so static is recommend here */27static struct psc_dma *psc_dma;28 29static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)30{31 int status;32 unsigned int val;33 34 mutex_lock(&psc_dma->mutex);35 36 /* Wait for command send status zero = ready */37 status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &38 MPC52xx_PSC_SR_CMDSEND), 100, 0);39 if (status == 0) {40 pr_err("timeout on ac97 bus (rdy)\n");41 mutex_unlock(&psc_dma->mutex);42 return -ENODEV;43 }44 45 /* Force clear the data valid bit */46 in_be32(&psc_dma->psc_regs->ac97_data);47 48 /* Send the read */49 out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));50 51 /* Wait for the answer */52 status = spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &53 MPC52xx_PSC_SR_DATA_VAL), 100, 0);54 if (status == 0) {55 pr_err("timeout on ac97 read (val) %x\n",56 in_be16(&psc_dma->psc_regs->sr_csr.status));57 mutex_unlock(&psc_dma->mutex);58 return -ENODEV;59 }60 /* Get the data */61 val = in_be32(&psc_dma->psc_regs->ac97_data);62 if (((val >> 24) & 0x7f) != reg) {63 pr_err("reg echo error on ac97 read\n");64 mutex_unlock(&psc_dma->mutex);65 return -ENODEV;66 }67 val = (val >> 8) & 0xffff;68 69 mutex_unlock(&psc_dma->mutex);70 return (unsigned short) val;71}72 73static void psc_ac97_write(struct snd_ac97 *ac97,74 unsigned short reg, unsigned short val)75{76 int status;77 78 mutex_lock(&psc_dma->mutex);79 80 /* Wait for command status zero = ready */81 status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &82 MPC52xx_PSC_SR_CMDSEND), 100, 0);83 if (status == 0) {84 pr_err("timeout on ac97 bus (write)\n");85 goto out;86 }87 /* Write data */88 out_be32(&psc_dma->psc_regs->ac97_cmd,89 ((reg & 0x7f) << 24) | (val << 8));90 91 out:92 mutex_unlock(&psc_dma->mutex);93}94 95static void psc_ac97_warm_reset(struct snd_ac97 *ac97)96{97 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;98 99 mutex_lock(&psc_dma->mutex);100 101 out_be32(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);102 udelay(3);103 out_be32(®s->sicr, psc_dma->sicr);104 105 mutex_unlock(&psc_dma->mutex);106}107 108static void psc_ac97_cold_reset(struct snd_ac97 *ac97)109{110 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;111 112 mutex_lock(&psc_dma->mutex);113 dev_dbg(psc_dma->dev, "cold reset\n");114 115 mpc5200_psc_ac97_gpio_reset(psc_dma->id);116 117 /* Notify the PSC that a reset has occurred */118 out_be32(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_ACRB);119 120 /* Re-enable RX and TX */121 out_8(®s->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);122 123 mutex_unlock(&psc_dma->mutex);124 125 usleep_range(1000, 2000);126 psc_ac97_warm_reset(ac97);127}128 129static struct snd_ac97_bus_ops psc_ac97_ops = {130 .read = psc_ac97_read,131 .write = psc_ac97_write,132 .reset = psc_ac97_cold_reset,133 .warm_reset = psc_ac97_warm_reset,134};135 136static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,137 struct snd_pcm_hw_params *params,138 struct snd_soc_dai *cpu_dai)139{140 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);141 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);142 143 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"144 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"145 " rate=%i format=%i\n",146 __func__, substream, params_period_size(params),147 params_period_bytes(params), params_periods(params),148 params_buffer_size(params), params_buffer_bytes(params),149 params_channels(params), params_rate(params),150 params_format(params));151 152 /* Determine the set of enable bits to turn on */153 s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300;154 if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE)155 s->ac97_slot_bits <<= 16;156 return 0;157}158 159static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,160 struct snd_pcm_hw_params *params,161 struct snd_soc_dai *cpu_dai)162{163 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);164 165 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);166 167 if (params_channels(params) == 1)168 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);169 else170 out_be32(&psc_dma->psc_regs->ac97_slots, 0x03000000);171 172 return 0;173}174 175static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,176 struct snd_soc_dai *dai)177{178 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai);179 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);180 181 switch (cmd) {182 case SNDRV_PCM_TRIGGER_START:183 dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n",184 substream->pstr->stream);185 186 /* Set the slot enable bits */187 psc_dma->slots |= s->ac97_slot_bits;188 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);189 break;190 191 case SNDRV_PCM_TRIGGER_STOP:192 dev_dbg(psc_dma->dev, "AC97 STOP: stream=%i\n",193 substream->pstr->stream);194 195 /* Clear the slot enable bits */196 psc_dma->slots &= ~(s->ac97_slot_bits);197 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);198 break;199 }200 return 0;201}202 203static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)204{205 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);206 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;207 208 /* Go */209 out_8(®s->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);210 return 0;211}212 213/* ---------------------------------------------------------------------214 * ALSA SoC Bindings215 *216 * - Digital Audio Interface (DAI) template217 * - create/destroy dai hooks218 */219 220/**221 * psc_ac97_dai_template: template CPU Digital Audio Interface222 */223static const struct snd_soc_dai_ops psc_ac97_analog_ops = {224 .probe = psc_ac97_probe,225 .hw_params = psc_ac97_hw_analog_params,226 .trigger = psc_ac97_trigger,227};228 229static const struct snd_soc_dai_ops psc_ac97_digital_ops = {230 .hw_params = psc_ac97_hw_digital_params,231};232 233static struct snd_soc_dai_driver psc_ac97_dai[] = {234{235 .name = "mpc5200-psc-ac97.0",236 .playback = {237 .stream_name = "AC97 Playback",238 .channels_min = 1,239 .channels_max = 6,240 .rates = SNDRV_PCM_RATE_8000_48000,241 .formats = SNDRV_PCM_FMTBIT_S32_BE,242 },243 .capture = {244 .stream_name = "AC97 Capture",245 .channels_min = 1,246 .channels_max = 2,247 .rates = SNDRV_PCM_RATE_8000_48000,248 .formats = SNDRV_PCM_FMTBIT_S32_BE,249 },250 .ops = &psc_ac97_analog_ops,251},252{253 .name = "mpc5200-psc-ac97.1",254 .playback = {255 .stream_name = "AC97 SPDIF",256 .channels_min = 1,257 .channels_max = 2,258 .rates = SNDRV_PCM_RATE_32000 | \259 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,260 .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,261 },262 .ops = &psc_ac97_digital_ops,263} };264 265static const struct snd_soc_component_driver psc_ac97_component = {266 .name = DRV_NAME,267};268 269 270/* ---------------------------------------------------------------------271 * OF platform bus binding code:272 * - Probe/remove operations273 * - OF device match table274 */275static int psc_ac97_of_probe(struct platform_device *op)276{277 int rc;278 struct mpc52xx_psc __iomem *regs;279 280 rc = mpc5200_audio_dma_create(op);281 if (rc != 0)282 return rc;283 284 rc = snd_soc_set_ac97_ops(&psc_ac97_ops);285 if (rc != 0) {286 dev_err(&op->dev, "Failed to set AC'97 ops: %d\n", rc);287 return rc;288 }289 290 rc = snd_soc_register_component(&op->dev, &psc_ac97_component,291 psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));292 if (rc != 0) {293 dev_err(&op->dev, "Failed to register DAI\n");294 return rc;295 }296 297 psc_dma = dev_get_drvdata(&op->dev);298 regs = psc_dma->psc_regs;299 300 psc_dma->imr = 0;301 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);302 303 /* Configure the serial interface mode to AC97 */304 psc_dma->sicr = MPC52xx_PSC_SICR_SIM_AC97 | MPC52xx_PSC_SICR_ENAC97;305 out_be32(®s->sicr, psc_dma->sicr);306 307 /* No slots active */308 out_be32(®s->ac97_slots, 0x00000000);309 310 return 0;311}312 313static void psc_ac97_of_remove(struct platform_device *op)314{315 mpc5200_audio_dma_destroy(op);316 snd_soc_unregister_component(&op->dev);317 snd_soc_set_ac97_ops(NULL);318}319 320/* Match table for of_platform binding */321static const struct of_device_id psc_ac97_match[] = {322 { .compatible = "fsl,mpc5200-psc-ac97", },323 { .compatible = "fsl,mpc5200b-psc-ac97", },324 {}325};326MODULE_DEVICE_TABLE(of, psc_ac97_match);327 328static struct platform_driver psc_ac97_driver = {329 .probe = psc_ac97_of_probe,330 .remove = psc_ac97_of_remove,331 .driver = {332 .name = "mpc5200-psc-ac97",333 .of_match_table = psc_ac97_match,334 },335};336 337module_platform_driver(psc_ac97_driver);338 339MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");340MODULE_DESCRIPTION("mpc5200 AC97 module");341MODULE_LICENSE("GPL");342 343