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