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