1 /* 2 * linux/sound/soc/pxa/mmp-sspa.c 3 * Base on pxa2xx-ssp.c 4 * 5 * Copyright (C) 2011 Marvell International Ltd. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 */ 22 #include <linux/init.h> 23 #include <linux/module.h> 24 #include <linux/platform_device.h> 25 #include <linux/delay.h> 26 #include <linux/clk.h> 27 #include <linux/slab.h> 28 #include <linux/pxa2xx_ssp.h> 29 #include <linux/io.h> 30 #include <sound/core.h> 31 #include <sound/pcm.h> 32 #include <sound/initval.h> 33 #include <sound/pcm_params.h> 34 #include <sound/soc.h> 35 #include <sound/pxa2xx-lib.h> 36 #include "mmp-sspa.h" 37 38 /* 39 * SSPA audio private data 40 */ 41 struct sspa_priv { 42 struct ssp_device *sspa; 43 struct pxa2xx_pcm_dma_params *dma_params; 44 struct clk *audio_clk; 45 struct clk *sysclk; 46 int dai_fmt; 47 int running_cnt; 48 }; 49 50 static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val) 51 { 52 __raw_writel(val, sspa->mmio_base + reg); 53 } 54 55 static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg) 56 { 57 return __raw_readl(sspa->mmio_base + reg); 58 } 59 60 static void mmp_sspa_tx_enable(struct ssp_device *sspa) 61 { 62 unsigned int sspa_sp; 63 64 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); 65 sspa_sp |= SSPA_SP_S_EN; 66 sspa_sp |= SSPA_SP_WEN; 67 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); 68 } 69 70 static void mmp_sspa_tx_disable(struct ssp_device *sspa) 71 { 72 unsigned int sspa_sp; 73 74 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); 75 sspa_sp &= ~SSPA_SP_S_EN; 76 sspa_sp |= SSPA_SP_WEN; 77 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); 78 } 79 80 static void mmp_sspa_rx_enable(struct ssp_device *sspa) 81 { 82 unsigned int sspa_sp; 83 84 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); 85 sspa_sp |= SSPA_SP_S_EN; 86 sspa_sp |= SSPA_SP_WEN; 87 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); 88 } 89 90 static void mmp_sspa_rx_disable(struct ssp_device *sspa) 91 { 92 unsigned int sspa_sp; 93 94 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); 95 sspa_sp &= ~SSPA_SP_S_EN; 96 sspa_sp |= SSPA_SP_WEN; 97 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); 98 } 99 100 static int mmp_sspa_startup(struct snd_pcm_substream *substream, 101 struct snd_soc_dai *dai) 102 { 103 struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); 104 105 clk_enable(priv->sysclk); 106 clk_enable(priv->sspa->clk); 107 108 return 0; 109 } 110 111 static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, 112 struct snd_soc_dai *dai) 113 { 114 struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); 115 116 clk_disable(priv->sspa->clk); 117 clk_disable(priv->sysclk); 118 119 return; 120 } 121 122 /* 123 * Set the SSP ports SYSCLK. 124 */ 125 static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 126 int clk_id, unsigned int freq, int dir) 127 { 128 struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); 129 int ret = 0; 130 131 switch (clk_id) { 132 case MMP_SSPA_CLK_AUDIO: 133 ret = clk_set_rate(priv->audio_clk, freq); 134 if (ret) 135 return ret; 136 break; 137 case MMP_SSPA_CLK_PLL: 138 case MMP_SSPA_CLK_VCXO: 139 /* not support yet */ 140 return -EINVAL; 141 default: 142 return -EINVAL; 143 } 144 145 return 0; 146 } 147 148 static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, 149 int source, unsigned int freq_in, 150 unsigned int freq_out) 151 { 152 struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); 153 int ret = 0; 154 155 switch (pll_id) { 156 case MMP_SYSCLK: 157 ret = clk_set_rate(priv->sysclk, freq_out); 158 if (ret) 159 return ret; 160 break; 161 case MMP_SSPA_CLK: 162 ret = clk_set_rate(priv->sspa->clk, freq_out); 163 if (ret) 164 return ret; 165 break; 166 default: 167 return -ENODEV; 168 } 169 170 return 0; 171 } 172 173 /* 174 * Set up the sspa dai format. The sspa port must be inactive 175 * before calling this function as the physical 176 * interface format is changed. 177 */ 178 static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, 179 unsigned int fmt) 180 { 181 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai); 182 struct ssp_device *sspa = sspa_priv->sspa; 183 u32 sspa_sp, sspa_ctrl; 184 185 /* check if we need to change anything at all */ 186 if (sspa_priv->dai_fmt == fmt) 187 return 0; 188 189 /* we can only change the settings if the port is not in use */ 190 if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || 191 (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { 192 dev_err(&sspa->pdev->dev, 193 "can't change hardware dai format: stream is in use\n"); 194 return -EINVAL; 195 } 196 197 /* reset port settings */ 198 sspa_sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; 199 sspa_ctrl = 0; 200 201 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 202 case SND_SOC_DAIFMT_CBS_CFS: 203 sspa_sp |= SSPA_SP_MSL; 204 break; 205 case SND_SOC_DAIFMT_CBM_CFM: 206 break; 207 default: 208 return -EINVAL; 209 } 210 211 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 212 case SND_SOC_DAIFMT_NB_NF: 213 sspa_sp |= SSPA_SP_FSP; 214 break; 215 default: 216 return -EINVAL; 217 } 218 219 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 220 case SND_SOC_DAIFMT_I2S: 221 sspa_sp |= SSPA_TXSP_FPER(63); 222 sspa_sp |= SSPA_SP_FWID(31); 223 sspa_ctrl |= SSPA_CTL_XDATDLY(1); 224 break; 225 default: 226 return -EINVAL; 227 } 228 229 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); 230 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); 231 232 sspa_sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); 233 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); 234 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); 235 236 /* 237 * FIXME: hw issue, for the tx serial port, 238 * can not config the master/slave mode; 239 * so must clean this bit. 240 * The master/slave mode has been set in the 241 * rx port. 242 */ 243 sspa_sp &= ~SSPA_SP_MSL; 244 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); 245 246 mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); 247 mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); 248 249 /* Since we are configuring the timings for the format by hand 250 * we have to defer some things until hw_params() where we 251 * know parameters like the sample size. 252 */ 253 sspa_priv->dai_fmt = fmt; 254 return 0; 255 } 256 257 /* 258 * Set the SSPA audio DMA parameters and sample size. 259 * Can be called multiple times by oss emulation. 260 */ 261 static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, 262 struct snd_pcm_hw_params *params, 263 struct snd_soc_dai *dai) 264 { 265 struct snd_soc_pcm_runtime *rtd = substream->private_data; 266 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 267 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); 268 struct ssp_device *sspa = sspa_priv->sspa; 269 struct pxa2xx_pcm_dma_params *dma_params; 270 u32 sspa_ctrl; 271 272 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 273 sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL); 274 else 275 sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL); 276 277 sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK; 278 sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1); 279 sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; 280 sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS); 281 sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; 282 283 switch (params_format(params)) { 284 case SNDRV_PCM_FORMAT_S8: 285 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS); 286 break; 287 case SNDRV_PCM_FORMAT_S16_LE: 288 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS); 289 break; 290 case SNDRV_PCM_FORMAT_S20_3LE: 291 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS); 292 break; 293 case SNDRV_PCM_FORMAT_S24_3LE: 294 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS); 295 break; 296 case SNDRV_PCM_FORMAT_S32_LE: 297 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS); 298 break; 299 default: 300 return -EINVAL; 301 } 302 303 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 304 mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); 305 mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1); 306 } else { 307 mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); 308 mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0); 309 } 310 311 dma_params = &sspa_priv->dma_params[substream->stream]; 312 dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 313 (sspa->phys_base + SSPA_TXD) : 314 (sspa->phys_base + SSPA_RXD); 315 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); 316 return 0; 317 } 318 319 static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd, 320 struct snd_soc_dai *dai) 321 { 322 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); 323 struct ssp_device *sspa = sspa_priv->sspa; 324 int ret = 0; 325 326 switch (cmd) { 327 case SNDRV_PCM_TRIGGER_START: 328 case SNDRV_PCM_TRIGGER_RESUME: 329 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 330 /* 331 * whatever playback or capture, must enable rx. 332 * this is a hw issue, so need check if rx has been 333 * enabled or not; if has been enabled by another 334 * stream, do not enable again. 335 */ 336 if (!sspa_priv->running_cnt) 337 mmp_sspa_rx_enable(sspa); 338 339 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 340 mmp_sspa_tx_enable(sspa); 341 342 sspa_priv->running_cnt++; 343 break; 344 345 case SNDRV_PCM_TRIGGER_STOP: 346 case SNDRV_PCM_TRIGGER_SUSPEND: 347 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 348 sspa_priv->running_cnt--; 349 350 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 351 mmp_sspa_tx_disable(sspa); 352 353 /* have no capture stream, disable rx port */ 354 if (!sspa_priv->running_cnt) 355 mmp_sspa_rx_disable(sspa); 356 break; 357 358 default: 359 ret = -EINVAL; 360 } 361 362 return ret; 363 } 364 365 static int mmp_sspa_probe(struct snd_soc_dai *dai) 366 { 367 struct sspa_priv *priv = dev_get_drvdata(dai->dev); 368 369 snd_soc_dai_set_drvdata(dai, priv); 370 return 0; 371 372 } 373 374 #define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000 375 #define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 376 SNDRV_PCM_FMTBIT_S16_LE | \ 377 SNDRV_PCM_FMTBIT_S24_LE | \ 378 SNDRV_PCM_FMTBIT_S24_LE | \ 379 SNDRV_PCM_FMTBIT_S32_LE) 380 381 static struct snd_soc_dai_ops mmp_sspa_dai_ops = { 382 .startup = mmp_sspa_startup, 383 .shutdown = mmp_sspa_shutdown, 384 .trigger = mmp_sspa_trigger, 385 .hw_params = mmp_sspa_hw_params, 386 .set_sysclk = mmp_sspa_set_dai_sysclk, 387 .set_pll = mmp_sspa_set_dai_pll, 388 .set_fmt = mmp_sspa_set_dai_fmt, 389 }; 390 391 struct snd_soc_dai_driver mmp_sspa_dai = { 392 .probe = mmp_sspa_probe, 393 .playback = { 394 .channels_min = 1, 395 .channels_max = 128, 396 .rates = MMP_SSPA_RATES, 397 .formats = MMP_SSPA_FORMATS, 398 }, 399 .capture = { 400 .channels_min = 1, 401 .channels_max = 2, 402 .rates = MMP_SSPA_RATES, 403 .formats = MMP_SSPA_FORMATS, 404 }, 405 .ops = &mmp_sspa_dai_ops, 406 }; 407 408 static int asoc_mmp_sspa_probe(struct platform_device *pdev) 409 { 410 struct sspa_priv *priv; 411 struct resource *res; 412 413 priv = devm_kzalloc(&pdev->dev, 414 sizeof(struct sspa_priv), GFP_KERNEL); 415 if (!priv) 416 return -ENOMEM; 417 418 priv->sspa = devm_kzalloc(&pdev->dev, 419 sizeof(struct ssp_device), GFP_KERNEL); 420 if (priv->sspa == NULL) 421 return -ENOMEM; 422 423 priv->dma_params = devm_kzalloc(&pdev->dev, 424 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL); 425 if (priv->dma_params == NULL) 426 return -ENOMEM; 427 428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 429 if (res == NULL) 430 return -ENOMEM; 431 432 priv->sspa->mmio_base = devm_request_and_ioremap(&pdev->dev, res); 433 if (priv->sspa->mmio_base == NULL) 434 return -ENODEV; 435 436 priv->sspa->clk = devm_clk_get(&pdev->dev, NULL); 437 if (IS_ERR(priv->sspa->clk)) 438 return PTR_ERR(priv->sspa->clk); 439 440 priv->audio_clk = clk_get(NULL, "mmp-audio"); 441 if (IS_ERR(priv->audio_clk)) 442 return PTR_ERR(priv->audio_clk); 443 444 priv->sysclk = clk_get(NULL, "mmp-sysclk"); 445 if (IS_ERR(priv->sysclk)) { 446 clk_put(priv->audio_clk); 447 return PTR_ERR(priv->sysclk); 448 } 449 clk_enable(priv->audio_clk); 450 priv->dai_fmt = (unsigned int) -1; 451 platform_set_drvdata(pdev, priv); 452 453 return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai); 454 } 455 456 static int asoc_mmp_sspa_remove(struct platform_device *pdev) 457 { 458 struct sspa_priv *priv = platform_get_drvdata(pdev); 459 460 clk_disable(priv->audio_clk); 461 clk_put(priv->audio_clk); 462 clk_put(priv->sysclk); 463 snd_soc_unregister_dai(&pdev->dev); 464 return 0; 465 } 466 467 static struct platform_driver asoc_mmp_sspa_driver = { 468 .driver = { 469 .name = "mmp-sspa-dai", 470 .owner = THIS_MODULE, 471 }, 472 .probe = asoc_mmp_sspa_probe, 473 .remove = asoc_mmp_sspa_remove, 474 }; 475 476 module_platform_driver(asoc_mmp_sspa_driver); 477 478 MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 479 MODULE_DESCRIPTION("MMP SSPA SoC Interface"); 480 MODULE_LICENSE("GPL"); 481