1 /* 2 * tegra20_i2s.c - Tegra20 I2S driver 3 * 4 * Author: Stephen Warren <swarren@nvidia.com> 5 * Copyright (C) 2010,2012 - NVIDIA, Inc. 6 * 7 * Based on code copyright/by: 8 * 9 * Copyright (c) 2009-2010, NVIDIA Corporation. 10 * Scott Peterson <speterson@nvidia.com> 11 * 12 * Copyright (C) 2010 Google, Inc. 13 * Iliyan Malchev <malchev@google.com> 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License 17 * version 2 as published by the Free Software Foundation. 18 * 19 * This program is distributed in the hope that it will be useful, but 20 * WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 * General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 27 * 02110-1301 USA 28 * 29 */ 30 31 #include <linux/clk.h> 32 #include <linux/device.h> 33 #include <linux/io.h> 34 #include <linux/module.h> 35 #include <linux/of.h> 36 #include <linux/platform_device.h> 37 #include <linux/pm_runtime.h> 38 #include <linux/regmap.h> 39 #include <linux/slab.h> 40 #include <sound/core.h> 41 #include <sound/pcm.h> 42 #include <sound/pcm_params.h> 43 #include <sound/soc.h> 44 45 #include "tegra20_i2s.h" 46 47 #define DRV_NAME "tegra20-i2s" 48 49 static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val) 50 { 51 regmap_write(i2s->regmap, reg, val); 52 } 53 54 static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg) 55 { 56 u32 val; 57 regmap_read(i2s->regmap, reg, &val); 58 return val; 59 } 60 61 static int tegra20_i2s_runtime_suspend(struct device *dev) 62 { 63 struct tegra20_i2s *i2s = dev_get_drvdata(dev); 64 65 clk_disable(i2s->clk_i2s); 66 67 return 0; 68 } 69 70 static int tegra20_i2s_runtime_resume(struct device *dev) 71 { 72 struct tegra20_i2s *i2s = dev_get_drvdata(dev); 73 int ret; 74 75 ret = clk_enable(i2s->clk_i2s); 76 if (ret) { 77 dev_err(dev, "clk_enable failed: %d\n", ret); 78 return ret; 79 } 80 81 return 0; 82 } 83 84 static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, 85 unsigned int fmt) 86 { 87 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 88 89 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 90 case SND_SOC_DAIFMT_NB_NF: 91 break; 92 default: 93 return -EINVAL; 94 } 95 96 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE; 97 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 98 case SND_SOC_DAIFMT_CBS_CFS: 99 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE; 100 break; 101 case SND_SOC_DAIFMT_CBM_CFM: 102 break; 103 default: 104 return -EINVAL; 105 } 106 107 i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | 108 TEGRA20_I2S_CTRL_LRCK_MASK); 109 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 110 case SND_SOC_DAIFMT_DSP_A: 111 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 112 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 113 break; 114 case SND_SOC_DAIFMT_DSP_B: 115 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 116 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW; 117 break; 118 case SND_SOC_DAIFMT_I2S: 119 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; 120 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 121 break; 122 case SND_SOC_DAIFMT_RIGHT_J: 123 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; 124 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 125 break; 126 case SND_SOC_DAIFMT_LEFT_J: 127 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; 128 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 129 break; 130 default: 131 return -EINVAL; 132 } 133 134 return 0; 135 } 136 137 static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, 138 struct snd_pcm_hw_params *params, 139 struct snd_soc_dai *dai) 140 { 141 struct device *dev = substream->pcm->card->dev; 142 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 143 u32 reg; 144 int ret, sample_size, srate, i2sclock, bitcnt; 145 146 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK; 147 switch (params_format(params)) { 148 case SNDRV_PCM_FORMAT_S16_LE: 149 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16; 150 sample_size = 16; 151 break; 152 case SNDRV_PCM_FORMAT_S24_LE: 153 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24; 154 sample_size = 24; 155 break; 156 case SNDRV_PCM_FORMAT_S32_LE: 157 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32; 158 sample_size = 32; 159 break; 160 default: 161 return -EINVAL; 162 } 163 164 srate = params_rate(params); 165 166 /* Final "* 2" required by Tegra hardware */ 167 i2sclock = srate * params_channels(params) * sample_size * 2; 168 169 ret = clk_set_rate(i2s->clk_i2s, i2sclock); 170 if (ret) { 171 dev_err(dev, "Can't set I2S clock rate: %d\n", ret); 172 return ret; 173 } 174 175 bitcnt = (i2sclock / (2 * srate)) - 1; 176 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) 177 return -EINVAL; 178 reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; 179 180 if (i2sclock % (2 * srate)) 181 reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; 182 183 tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg); 184 185 tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR, 186 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | 187 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); 188 189 return 0; 190 } 191 192 static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) 193 { 194 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE; 195 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 196 } 197 198 static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) 199 { 200 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE; 201 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 202 } 203 204 static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) 205 { 206 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE; 207 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 208 } 209 210 static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) 211 { 212 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE; 213 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 214 } 215 216 static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 217 struct snd_soc_dai *dai) 218 { 219 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 220 221 switch (cmd) { 222 case SNDRV_PCM_TRIGGER_START: 223 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 224 case SNDRV_PCM_TRIGGER_RESUME: 225 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 226 tegra20_i2s_start_playback(i2s); 227 else 228 tegra20_i2s_start_capture(i2s); 229 break; 230 case SNDRV_PCM_TRIGGER_STOP: 231 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 232 case SNDRV_PCM_TRIGGER_SUSPEND: 233 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 234 tegra20_i2s_stop_playback(i2s); 235 else 236 tegra20_i2s_stop_capture(i2s); 237 break; 238 default: 239 return -EINVAL; 240 } 241 242 return 0; 243 } 244 245 static int tegra20_i2s_probe(struct snd_soc_dai *dai) 246 { 247 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 248 249 dai->capture_dma_data = &i2s->capture_dma_data; 250 dai->playback_dma_data = &i2s->playback_dma_data; 251 252 return 0; 253 } 254 255 static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { 256 .set_fmt = tegra20_i2s_set_fmt, 257 .hw_params = tegra20_i2s_hw_params, 258 .trigger = tegra20_i2s_trigger, 259 }; 260 261 static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { 262 .probe = tegra20_i2s_probe, 263 .playback = { 264 .channels_min = 2, 265 .channels_max = 2, 266 .rates = SNDRV_PCM_RATE_8000_96000, 267 .formats = SNDRV_PCM_FMTBIT_S16_LE, 268 }, 269 .capture = { 270 .channels_min = 2, 271 .channels_max = 2, 272 .rates = SNDRV_PCM_RATE_8000_96000, 273 .formats = SNDRV_PCM_FMTBIT_S16_LE, 274 }, 275 .ops = &tegra20_i2s_dai_ops, 276 .symmetric_rates = 1, 277 }; 278 279 static bool tegra20_i2s_wr_rd_reg(struct device *dev, unsigned int reg) 280 { 281 switch (reg) { 282 case TEGRA20_I2S_CTRL: 283 case TEGRA20_I2S_STATUS: 284 case TEGRA20_I2S_TIMING: 285 case TEGRA20_I2S_FIFO_SCR: 286 case TEGRA20_I2S_PCM_CTRL: 287 case TEGRA20_I2S_NW_CTRL: 288 case TEGRA20_I2S_TDM_CTRL: 289 case TEGRA20_I2S_TDM_TX_RX_CTRL: 290 case TEGRA20_I2S_FIFO1: 291 case TEGRA20_I2S_FIFO2: 292 return true; 293 default: 294 return false; 295 }; 296 } 297 298 static bool tegra20_i2s_volatile_reg(struct device *dev, unsigned int reg) 299 { 300 switch (reg) { 301 case TEGRA20_I2S_STATUS: 302 case TEGRA20_I2S_FIFO_SCR: 303 case TEGRA20_I2S_FIFO1: 304 case TEGRA20_I2S_FIFO2: 305 return true; 306 default: 307 return false; 308 }; 309 } 310 311 static bool tegra20_i2s_precious_reg(struct device *dev, unsigned int reg) 312 { 313 switch (reg) { 314 case TEGRA20_I2S_FIFO1: 315 case TEGRA20_I2S_FIFO2: 316 return true; 317 default: 318 return false; 319 }; 320 } 321 322 static const struct regmap_config tegra20_i2s_regmap_config = { 323 .reg_bits = 32, 324 .reg_stride = 4, 325 .val_bits = 32, 326 .max_register = TEGRA20_I2S_FIFO2, 327 .writeable_reg = tegra20_i2s_wr_rd_reg, 328 .readable_reg = tegra20_i2s_wr_rd_reg, 329 .volatile_reg = tegra20_i2s_volatile_reg, 330 .precious_reg = tegra20_i2s_precious_reg, 331 .cache_type = REGCACHE_RBTREE, 332 }; 333 334 static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev) 335 { 336 struct tegra20_i2s *i2s; 337 struct resource *mem, *memregion, *dmareq; 338 u32 of_dma[2]; 339 u32 dma_ch; 340 void __iomem *regs; 341 int ret; 342 343 i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_i2s), GFP_KERNEL); 344 if (!i2s) { 345 dev_err(&pdev->dev, "Can't allocate tegra20_i2s\n"); 346 ret = -ENOMEM; 347 goto err; 348 } 349 dev_set_drvdata(&pdev->dev, i2s); 350 351 i2s->dai = tegra20_i2s_dai_template; 352 i2s->dai.name = dev_name(&pdev->dev); 353 354 i2s->clk_i2s = clk_get(&pdev->dev, NULL); 355 if (IS_ERR(i2s->clk_i2s)) { 356 dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); 357 ret = PTR_ERR(i2s->clk_i2s); 358 goto err; 359 } 360 361 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 362 if (!mem) { 363 dev_err(&pdev->dev, "No memory resource\n"); 364 ret = -ENODEV; 365 goto err_clk_put; 366 } 367 368 dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); 369 if (!dmareq) { 370 if (of_property_read_u32_array(pdev->dev.of_node, 371 "nvidia,dma-request-selector", 372 of_dma, 2) < 0) { 373 dev_err(&pdev->dev, "No DMA resource\n"); 374 ret = -ENODEV; 375 goto err_clk_put; 376 } 377 dma_ch = of_dma[1]; 378 } else { 379 dma_ch = dmareq->start; 380 } 381 382 memregion = devm_request_mem_region(&pdev->dev, mem->start, 383 resource_size(mem), DRV_NAME); 384 if (!memregion) { 385 dev_err(&pdev->dev, "Memory region already claimed\n"); 386 ret = -EBUSY; 387 goto err_clk_put; 388 } 389 390 regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); 391 if (!regs) { 392 dev_err(&pdev->dev, "ioremap failed\n"); 393 ret = -ENOMEM; 394 goto err_clk_put; 395 } 396 397 i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 398 &tegra20_i2s_regmap_config); 399 if (IS_ERR(i2s->regmap)) { 400 dev_err(&pdev->dev, "regmap init failed\n"); 401 ret = PTR_ERR(i2s->regmap); 402 goto err_clk_put; 403 } 404 405 i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; 406 i2s->capture_dma_data.wrap = 4; 407 i2s->capture_dma_data.width = 32; 408 i2s->capture_dma_data.req_sel = dma_ch; 409 410 i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1; 411 i2s->playback_dma_data.wrap = 4; 412 i2s->playback_dma_data.width = 32; 413 i2s->playback_dma_data.req_sel = dma_ch; 414 415 i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; 416 417 pm_runtime_enable(&pdev->dev); 418 if (!pm_runtime_enabled(&pdev->dev)) { 419 ret = tegra20_i2s_runtime_resume(&pdev->dev); 420 if (ret) 421 goto err_pm_disable; 422 } 423 424 ret = snd_soc_register_dai(&pdev->dev, &i2s->dai); 425 if (ret) { 426 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 427 ret = -ENOMEM; 428 goto err_suspend; 429 } 430 431 ret = tegra_pcm_platform_register(&pdev->dev); 432 if (ret) { 433 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 434 goto err_unregister_dai; 435 } 436 437 return 0; 438 439 err_unregister_dai: 440 snd_soc_unregister_dai(&pdev->dev); 441 err_suspend: 442 if (!pm_runtime_status_suspended(&pdev->dev)) 443 tegra20_i2s_runtime_suspend(&pdev->dev); 444 err_pm_disable: 445 pm_runtime_disable(&pdev->dev); 446 err_clk_put: 447 clk_put(i2s->clk_i2s); 448 err: 449 return ret; 450 } 451 452 static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev) 453 { 454 struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev); 455 456 pm_runtime_disable(&pdev->dev); 457 if (!pm_runtime_status_suspended(&pdev->dev)) 458 tegra20_i2s_runtime_suspend(&pdev->dev); 459 460 tegra_pcm_platform_unregister(&pdev->dev); 461 snd_soc_unregister_dai(&pdev->dev); 462 463 clk_put(i2s->clk_i2s); 464 465 return 0; 466 } 467 468 static const struct of_device_id tegra20_i2s_of_match[] __devinitconst = { 469 { .compatible = "nvidia,tegra20-i2s", }, 470 {}, 471 }; 472 473 static const struct dev_pm_ops tegra20_i2s_pm_ops __devinitconst = { 474 SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend, 475 tegra20_i2s_runtime_resume, NULL) 476 }; 477 478 static struct platform_driver tegra20_i2s_driver = { 479 .driver = { 480 .name = DRV_NAME, 481 .owner = THIS_MODULE, 482 .of_match_table = tegra20_i2s_of_match, 483 .pm = &tegra20_i2s_pm_ops, 484 }, 485 .probe = tegra20_i2s_platform_probe, 486 .remove = __devexit_p(tegra20_i2s_platform_remove), 487 }; 488 module_platform_driver(tegra20_i2s_driver); 489 490 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 491 MODULE_DESCRIPTION("Tegra20 I2S ASoC driver"); 492 MODULE_LICENSE("GPL"); 493 MODULE_ALIAS("platform:" DRV_NAME); 494 MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match); 495