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 #include <sound/dmaengine_pcm.h> 45 46 #include "tegra20_i2s.h" 47 48 #define DRV_NAME "tegra20-i2s" 49 50 static int tegra20_i2s_runtime_suspend(struct device *dev) 51 { 52 struct tegra20_i2s *i2s = dev_get_drvdata(dev); 53 54 clk_disable_unprepare(i2s->clk_i2s); 55 56 return 0; 57 } 58 59 static int tegra20_i2s_runtime_resume(struct device *dev) 60 { 61 struct tegra20_i2s *i2s = dev_get_drvdata(dev); 62 int ret; 63 64 ret = clk_prepare_enable(i2s->clk_i2s); 65 if (ret) { 66 dev_err(dev, "clk_enable failed: %d\n", ret); 67 return ret; 68 } 69 70 return 0; 71 } 72 73 static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, 74 unsigned int fmt) 75 { 76 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 77 unsigned int mask = 0, val = 0; 78 79 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 80 case SND_SOC_DAIFMT_NB_NF: 81 break; 82 default: 83 return -EINVAL; 84 } 85 86 mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE; 87 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 88 case SND_SOC_DAIFMT_CBS_CFS: 89 val |= TEGRA20_I2S_CTRL_MASTER_ENABLE; 90 break; 91 case SND_SOC_DAIFMT_CBM_CFM: 92 break; 93 default: 94 return -EINVAL; 95 } 96 97 mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | 98 TEGRA20_I2S_CTRL_LRCK_MASK; 99 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 100 case SND_SOC_DAIFMT_DSP_A: 101 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 102 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 103 break; 104 case SND_SOC_DAIFMT_DSP_B: 105 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 106 val |= TEGRA20_I2S_CTRL_LRCK_R_LOW; 107 break; 108 case SND_SOC_DAIFMT_I2S: 109 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; 110 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 111 break; 112 case SND_SOC_DAIFMT_RIGHT_J: 113 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; 114 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 115 break; 116 case SND_SOC_DAIFMT_LEFT_J: 117 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; 118 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 119 break; 120 default: 121 return -EINVAL; 122 } 123 124 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); 125 126 return 0; 127 } 128 129 static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, 130 struct snd_pcm_hw_params *params, 131 struct snd_soc_dai *dai) 132 { 133 struct device *dev = dai->dev; 134 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 135 unsigned int mask, val; 136 int ret, sample_size, srate, i2sclock, bitcnt; 137 138 mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK; 139 switch (params_format(params)) { 140 case SNDRV_PCM_FORMAT_S16_LE: 141 val = TEGRA20_I2S_CTRL_BIT_SIZE_16; 142 sample_size = 16; 143 break; 144 case SNDRV_PCM_FORMAT_S24_LE: 145 val = TEGRA20_I2S_CTRL_BIT_SIZE_24; 146 sample_size = 24; 147 break; 148 case SNDRV_PCM_FORMAT_S32_LE: 149 val = TEGRA20_I2S_CTRL_BIT_SIZE_32; 150 sample_size = 32; 151 break; 152 default: 153 return -EINVAL; 154 } 155 156 mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK; 157 val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; 158 159 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); 160 161 srate = params_rate(params); 162 163 /* Final "* 2" required by Tegra hardware */ 164 i2sclock = srate * params_channels(params) * sample_size * 2; 165 166 ret = clk_set_rate(i2s->clk_i2s, i2sclock); 167 if (ret) { 168 dev_err(dev, "Can't set I2S clock rate: %d\n", ret); 169 return ret; 170 } 171 172 bitcnt = (i2sclock / (2 * srate)) - 1; 173 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) 174 return -EINVAL; 175 val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; 176 177 if (i2sclock % (2 * srate)) 178 val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; 179 180 regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val); 181 182 regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR, 183 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | 184 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); 185 186 return 0; 187 } 188 189 static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) 190 { 191 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, 192 TEGRA20_I2S_CTRL_FIFO1_ENABLE, 193 TEGRA20_I2S_CTRL_FIFO1_ENABLE); 194 } 195 196 static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) 197 { 198 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, 199 TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0); 200 } 201 202 static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) 203 { 204 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, 205 TEGRA20_I2S_CTRL_FIFO2_ENABLE, 206 TEGRA20_I2S_CTRL_FIFO2_ENABLE); 207 } 208 209 static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) 210 { 211 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, 212 TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0); 213 } 214 215 static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 216 struct snd_soc_dai *dai) 217 { 218 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 219 220 switch (cmd) { 221 case SNDRV_PCM_TRIGGER_START: 222 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 223 case SNDRV_PCM_TRIGGER_RESUME: 224 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 225 tegra20_i2s_start_playback(i2s); 226 else 227 tegra20_i2s_start_capture(i2s); 228 break; 229 case SNDRV_PCM_TRIGGER_STOP: 230 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 231 case SNDRV_PCM_TRIGGER_SUSPEND: 232 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 233 tegra20_i2s_stop_playback(i2s); 234 else 235 tegra20_i2s_stop_capture(i2s); 236 break; 237 default: 238 return -EINVAL; 239 } 240 241 return 0; 242 } 243 244 static int tegra20_i2s_probe(struct snd_soc_dai *dai) 245 { 246 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 247 248 dai->capture_dma_data = &i2s->capture_dma_data; 249 dai->playback_dma_data = &i2s->playback_dma_data; 250 251 return 0; 252 } 253 254 static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { 255 .set_fmt = tegra20_i2s_set_fmt, 256 .hw_params = tegra20_i2s_hw_params, 257 .trigger = tegra20_i2s_trigger, 258 }; 259 260 static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { 261 .probe = tegra20_i2s_probe, 262 .playback = { 263 .stream_name = "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 .stream_name = "Capture", 271 .channels_min = 2, 272 .channels_max = 2, 273 .rates = SNDRV_PCM_RATE_8000_96000, 274 .formats = SNDRV_PCM_FMTBIT_S16_LE, 275 }, 276 .ops = &tegra20_i2s_dai_ops, 277 .symmetric_rates = 1, 278 }; 279 280 static const struct snd_soc_component_driver tegra20_i2s_component = { 281 .name = DRV_NAME, 282 }; 283 284 static bool tegra20_i2s_wr_rd_reg(struct device *dev, unsigned int reg) 285 { 286 switch (reg) { 287 case TEGRA20_I2S_CTRL: 288 case TEGRA20_I2S_STATUS: 289 case TEGRA20_I2S_TIMING: 290 case TEGRA20_I2S_FIFO_SCR: 291 case TEGRA20_I2S_PCM_CTRL: 292 case TEGRA20_I2S_NW_CTRL: 293 case TEGRA20_I2S_TDM_CTRL: 294 case TEGRA20_I2S_TDM_TX_RX_CTRL: 295 case TEGRA20_I2S_FIFO1: 296 case TEGRA20_I2S_FIFO2: 297 return true; 298 default: 299 return false; 300 } 301 } 302 303 static bool tegra20_i2s_volatile_reg(struct device *dev, unsigned int reg) 304 { 305 switch (reg) { 306 case TEGRA20_I2S_STATUS: 307 case TEGRA20_I2S_FIFO_SCR: 308 case TEGRA20_I2S_FIFO1: 309 case TEGRA20_I2S_FIFO2: 310 return true; 311 default: 312 return false; 313 } 314 } 315 316 static bool tegra20_i2s_precious_reg(struct device *dev, unsigned int reg) 317 { 318 switch (reg) { 319 case TEGRA20_I2S_FIFO1: 320 case TEGRA20_I2S_FIFO2: 321 return true; 322 default: 323 return false; 324 } 325 } 326 327 static const struct regmap_config tegra20_i2s_regmap_config = { 328 .reg_bits = 32, 329 .reg_stride = 4, 330 .val_bits = 32, 331 .max_register = TEGRA20_I2S_FIFO2, 332 .writeable_reg = tegra20_i2s_wr_rd_reg, 333 .readable_reg = tegra20_i2s_wr_rd_reg, 334 .volatile_reg = tegra20_i2s_volatile_reg, 335 .precious_reg = tegra20_i2s_precious_reg, 336 .cache_type = REGCACHE_RBTREE, 337 }; 338 339 static int tegra20_i2s_platform_probe(struct platform_device *pdev) 340 { 341 struct tegra20_i2s *i2s; 342 struct resource *mem, *memregion, *dmareq; 343 u32 of_dma[2]; 344 u32 dma_ch; 345 void __iomem *regs; 346 int ret; 347 348 i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_i2s), GFP_KERNEL); 349 if (!i2s) { 350 dev_err(&pdev->dev, "Can't allocate tegra20_i2s\n"); 351 ret = -ENOMEM; 352 goto err; 353 } 354 dev_set_drvdata(&pdev->dev, i2s); 355 356 i2s->dai = tegra20_i2s_dai_template; 357 i2s->dai.name = dev_name(&pdev->dev); 358 359 i2s->clk_i2s = clk_get(&pdev->dev, NULL); 360 if (IS_ERR(i2s->clk_i2s)) { 361 dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); 362 ret = PTR_ERR(i2s->clk_i2s); 363 goto err; 364 } 365 366 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 367 if (!mem) { 368 dev_err(&pdev->dev, "No memory resource\n"); 369 ret = -ENODEV; 370 goto err_clk_put; 371 } 372 373 dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); 374 if (!dmareq) { 375 if (of_property_read_u32_array(pdev->dev.of_node, 376 "nvidia,dma-request-selector", 377 of_dma, 2) < 0) { 378 dev_err(&pdev->dev, "No DMA resource\n"); 379 ret = -ENODEV; 380 goto err_clk_put; 381 } 382 dma_ch = of_dma[1]; 383 } else { 384 dma_ch = dmareq->start; 385 } 386 387 memregion = devm_request_mem_region(&pdev->dev, mem->start, 388 resource_size(mem), DRV_NAME); 389 if (!memregion) { 390 dev_err(&pdev->dev, "Memory region already claimed\n"); 391 ret = -EBUSY; 392 goto err_clk_put; 393 } 394 395 regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); 396 if (!regs) { 397 dev_err(&pdev->dev, "ioremap failed\n"); 398 ret = -ENOMEM; 399 goto err_clk_put; 400 } 401 402 i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 403 &tegra20_i2s_regmap_config); 404 if (IS_ERR(i2s->regmap)) { 405 dev_err(&pdev->dev, "regmap init failed\n"); 406 ret = PTR_ERR(i2s->regmap); 407 goto err_clk_put; 408 } 409 410 i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; 411 i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 412 i2s->capture_dma_data.maxburst = 4; 413 i2s->capture_dma_data.slave_id = dma_ch; 414 415 i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1; 416 i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 417 i2s->playback_dma_data.maxburst = 4; 418 i2s->playback_dma_data.slave_id = dma_ch; 419 420 pm_runtime_enable(&pdev->dev); 421 if (!pm_runtime_enabled(&pdev->dev)) { 422 ret = tegra20_i2s_runtime_resume(&pdev->dev); 423 if (ret) 424 goto err_pm_disable; 425 } 426 427 ret = snd_soc_register_component(&pdev->dev, &tegra20_i2s_component, 428 &i2s->dai, 1); 429 if (ret) { 430 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 431 ret = -ENOMEM; 432 goto err_suspend; 433 } 434 435 ret = tegra_pcm_platform_register(&pdev->dev); 436 if (ret) { 437 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 438 goto err_unregister_component; 439 } 440 441 return 0; 442 443 err_unregister_component: 444 snd_soc_unregister_component(&pdev->dev); 445 err_suspend: 446 if (!pm_runtime_status_suspended(&pdev->dev)) 447 tegra20_i2s_runtime_suspend(&pdev->dev); 448 err_pm_disable: 449 pm_runtime_disable(&pdev->dev); 450 err_clk_put: 451 clk_put(i2s->clk_i2s); 452 err: 453 return ret; 454 } 455 456 static int tegra20_i2s_platform_remove(struct platform_device *pdev) 457 { 458 struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev); 459 460 pm_runtime_disable(&pdev->dev); 461 if (!pm_runtime_status_suspended(&pdev->dev)) 462 tegra20_i2s_runtime_suspend(&pdev->dev); 463 464 tegra_pcm_platform_unregister(&pdev->dev); 465 snd_soc_unregister_component(&pdev->dev); 466 467 clk_put(i2s->clk_i2s); 468 469 return 0; 470 } 471 472 static const struct of_device_id tegra20_i2s_of_match[] = { 473 { .compatible = "nvidia,tegra20-i2s", }, 474 {}, 475 }; 476 477 static const struct dev_pm_ops tegra20_i2s_pm_ops = { 478 SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend, 479 tegra20_i2s_runtime_resume, NULL) 480 }; 481 482 static struct platform_driver tegra20_i2s_driver = { 483 .driver = { 484 .name = DRV_NAME, 485 .owner = THIS_MODULE, 486 .of_match_table = tegra20_i2s_of_match, 487 .pm = &tegra20_i2s_pm_ops, 488 }, 489 .probe = tegra20_i2s_platform_probe, 490 .remove = tegra20_i2s_platform_remove, 491 }; 492 module_platform_driver(tegra20_i2s_driver); 493 494 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 495 MODULE_DESCRIPTION("Tegra20 I2S ASoC driver"); 496 MODULE_LICENSE("GPL"); 497 MODULE_ALIAS("platform:" DRV_NAME); 498 MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match); 499