1 /* 2 * tegra20_ac97.c - Tegra20 AC97 platform driver 3 * 4 * Copyright (c) 2012 Lucas Stach <dev@lynxeye.de> 5 * 6 * Partly based on code copyright/by: 7 * 8 * Copyright (c) 2011,2012 Toradex Inc. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * version 2 as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 */ 20 21 #include <linux/clk.h> 22 #include <linux/delay.h> 23 #include <linux/device.h> 24 #include <linux/gpio.h> 25 #include <linux/io.h> 26 #include <linux/jiffies.h> 27 #include <linux/module.h> 28 #include <linux/of.h> 29 #include <linux/of_gpio.h> 30 #include <linux/platform_device.h> 31 #include <linux/pm_runtime.h> 32 #include <linux/regmap.h> 33 #include <linux/slab.h> 34 #include <sound/core.h> 35 #include <sound/pcm.h> 36 #include <sound/pcm_params.h> 37 #include <sound/soc.h> 38 #include <sound/dmaengine_pcm.h> 39 40 #include "tegra_asoc_utils.h" 41 #include "tegra20_ac97.h" 42 43 #define DRV_NAME "tegra20-ac97" 44 45 static struct tegra20_ac97 *workdata; 46 47 static void tegra20_ac97_codec_reset(struct snd_ac97 *ac97) 48 { 49 u32 readback; 50 unsigned long timeout; 51 52 /* reset line is not driven by DAC pad group, have to toggle GPIO */ 53 gpio_set_value(workdata->reset_gpio, 0); 54 udelay(2); 55 56 gpio_set_value(workdata->reset_gpio, 1); 57 udelay(2); 58 59 timeout = jiffies + msecs_to_jiffies(100); 60 61 do { 62 regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback); 63 if (readback & TEGRA20_AC97_STATUS1_CODEC1_RDY) 64 break; 65 usleep_range(1000, 2000); 66 } while (!time_after(jiffies, timeout)); 67 } 68 69 static void tegra20_ac97_codec_warm_reset(struct snd_ac97 *ac97) 70 { 71 u32 readback; 72 unsigned long timeout; 73 74 /* 75 * although sync line is driven by the DAC pad group warm reset using 76 * the controller cmd is not working, have to toggle sync line 77 * manually. 78 */ 79 gpio_request(workdata->sync_gpio, "codec-sync"); 80 81 gpio_direction_output(workdata->sync_gpio, 1); 82 83 udelay(2); 84 gpio_set_value(workdata->sync_gpio, 0); 85 udelay(2); 86 gpio_free(workdata->sync_gpio); 87 88 timeout = jiffies + msecs_to_jiffies(100); 89 90 do { 91 regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback); 92 if (readback & TEGRA20_AC97_STATUS1_CODEC1_RDY) 93 break; 94 usleep_range(1000, 2000); 95 } while (!time_after(jiffies, timeout)); 96 } 97 98 static unsigned short tegra20_ac97_codec_read(struct snd_ac97 *ac97_snd, 99 unsigned short reg) 100 { 101 u32 readback; 102 unsigned long timeout; 103 104 regmap_write(workdata->regmap, TEGRA20_AC97_CMD, 105 (((reg | 0x80) << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT) & 106 TEGRA20_AC97_CMD_CMD_ADDR_MASK) | 107 TEGRA20_AC97_CMD_BUSY); 108 109 timeout = jiffies + msecs_to_jiffies(100); 110 111 do { 112 regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback); 113 if (readback & TEGRA20_AC97_STATUS1_STA_VALID1) 114 break; 115 usleep_range(1000, 2000); 116 } while (!time_after(jiffies, timeout)); 117 118 return ((readback & TEGRA20_AC97_STATUS1_STA_DATA1_MASK) >> 119 TEGRA20_AC97_STATUS1_STA_DATA1_SHIFT); 120 } 121 122 static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, 123 unsigned short reg, unsigned short val) 124 { 125 u32 readback; 126 unsigned long timeout; 127 128 regmap_write(workdata->regmap, TEGRA20_AC97_CMD, 129 ((reg << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT) & 130 TEGRA20_AC97_CMD_CMD_ADDR_MASK) | 131 ((val << TEGRA20_AC97_CMD_CMD_DATA_SHIFT) & 132 TEGRA20_AC97_CMD_CMD_DATA_MASK) | 133 TEGRA20_AC97_CMD_BUSY); 134 135 timeout = jiffies + msecs_to_jiffies(100); 136 137 do { 138 regmap_read(workdata->regmap, TEGRA20_AC97_CMD, &readback); 139 if (!(readback & TEGRA20_AC97_CMD_BUSY)) 140 break; 141 usleep_range(1000, 2000); 142 } while (!time_after(jiffies, timeout)); 143 } 144 145 static struct snd_ac97_bus_ops tegra20_ac97_ops = { 146 .read = tegra20_ac97_codec_read, 147 .write = tegra20_ac97_codec_write, 148 .reset = tegra20_ac97_codec_reset, 149 .warm_reset = tegra20_ac97_codec_warm_reset, 150 }; 151 152 static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) 153 { 154 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 155 TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 156 TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN); 157 158 regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL, 159 TEGRA20_AC97_CTRL_PCM_DAC_EN | 160 TEGRA20_AC97_CTRL_STM_EN, 161 TEGRA20_AC97_CTRL_PCM_DAC_EN | 162 TEGRA20_AC97_CTRL_STM_EN); 163 } 164 165 static inline void tegra20_ac97_stop_playback(struct tegra20_ac97 *ac97) 166 { 167 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 168 TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 0); 169 170 regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL, 171 TEGRA20_AC97_CTRL_PCM_DAC_EN, 0); 172 } 173 174 static inline void tegra20_ac97_start_capture(struct tegra20_ac97 *ac97) 175 { 176 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 177 TEGRA20_AC97_FIFO_SCR_REC_FULL_EN, 178 TEGRA20_AC97_FIFO_SCR_REC_FULL_EN); 179 } 180 181 static inline void tegra20_ac97_stop_capture(struct tegra20_ac97 *ac97) 182 { 183 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 184 TEGRA20_AC97_FIFO_SCR_REC_FULL_EN, 0); 185 } 186 187 static int tegra20_ac97_trigger(struct snd_pcm_substream *substream, int cmd, 188 struct snd_soc_dai *dai) 189 { 190 struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai); 191 192 switch (cmd) { 193 case SNDRV_PCM_TRIGGER_START: 194 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 195 case SNDRV_PCM_TRIGGER_RESUME: 196 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 197 tegra20_ac97_start_playback(ac97); 198 else 199 tegra20_ac97_start_capture(ac97); 200 break; 201 case SNDRV_PCM_TRIGGER_STOP: 202 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 203 case SNDRV_PCM_TRIGGER_SUSPEND: 204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 205 tegra20_ac97_stop_playback(ac97); 206 else 207 tegra20_ac97_stop_capture(ac97); 208 break; 209 default: 210 return -EINVAL; 211 } 212 213 return 0; 214 } 215 216 static const struct snd_soc_dai_ops tegra20_ac97_dai_ops = { 217 .trigger = tegra20_ac97_trigger, 218 }; 219 220 static int tegra20_ac97_probe(struct snd_soc_dai *dai) 221 { 222 struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai); 223 224 dai->capture_dma_data = &ac97->capture_dma_data; 225 dai->playback_dma_data = &ac97->playback_dma_data; 226 227 return 0; 228 } 229 230 static struct snd_soc_dai_driver tegra20_ac97_dai = { 231 .name = "tegra-ac97-pcm", 232 .ac97_control = 1, 233 .probe = tegra20_ac97_probe, 234 .playback = { 235 .stream_name = "PCM Playback", 236 .channels_min = 2, 237 .channels_max = 2, 238 .rates = SNDRV_PCM_RATE_8000_48000, 239 .formats = SNDRV_PCM_FMTBIT_S16_LE, 240 }, 241 .capture = { 242 .stream_name = "PCM Capture", 243 .channels_min = 2, 244 .channels_max = 2, 245 .rates = SNDRV_PCM_RATE_8000_48000, 246 .formats = SNDRV_PCM_FMTBIT_S16_LE, 247 }, 248 .ops = &tegra20_ac97_dai_ops, 249 }; 250 251 static const struct snd_soc_component_driver tegra20_ac97_component = { 252 .name = DRV_NAME, 253 }; 254 255 static bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg) 256 { 257 switch (reg) { 258 case TEGRA20_AC97_CTRL: 259 case TEGRA20_AC97_CMD: 260 case TEGRA20_AC97_STATUS1: 261 case TEGRA20_AC97_FIFO1_SCR: 262 case TEGRA20_AC97_FIFO_TX1: 263 case TEGRA20_AC97_FIFO_RX1: 264 return true; 265 default: 266 break; 267 } 268 269 return false; 270 } 271 272 static bool tegra20_ac97_volatile_reg(struct device *dev, unsigned int reg) 273 { 274 switch (reg) { 275 case TEGRA20_AC97_STATUS1: 276 case TEGRA20_AC97_FIFO1_SCR: 277 case TEGRA20_AC97_FIFO_TX1: 278 case TEGRA20_AC97_FIFO_RX1: 279 return true; 280 default: 281 break; 282 } 283 284 return false; 285 } 286 287 static bool tegra20_ac97_precious_reg(struct device *dev, unsigned int reg) 288 { 289 switch (reg) { 290 case TEGRA20_AC97_FIFO_TX1: 291 case TEGRA20_AC97_FIFO_RX1: 292 return true; 293 default: 294 break; 295 } 296 297 return false; 298 } 299 300 static const struct regmap_config tegra20_ac97_regmap_config = { 301 .reg_bits = 32, 302 .reg_stride = 4, 303 .val_bits = 32, 304 .max_register = TEGRA20_AC97_FIFO_RX1, 305 .writeable_reg = tegra20_ac97_wr_rd_reg, 306 .readable_reg = tegra20_ac97_wr_rd_reg, 307 .volatile_reg = tegra20_ac97_volatile_reg, 308 .precious_reg = tegra20_ac97_precious_reg, 309 .cache_type = REGCACHE_RBTREE, 310 }; 311 312 static int tegra20_ac97_platform_probe(struct platform_device *pdev) 313 { 314 struct tegra20_ac97 *ac97; 315 struct resource *mem; 316 u32 of_dma[2]; 317 void __iomem *regs; 318 int ret = 0; 319 320 ac97 = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_ac97), 321 GFP_KERNEL); 322 if (!ac97) { 323 dev_err(&pdev->dev, "Can't allocate tegra20_ac97\n"); 324 ret = -ENOMEM; 325 goto err; 326 } 327 dev_set_drvdata(&pdev->dev, ac97); 328 329 ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); 330 if (IS_ERR(ac97->clk_ac97)) { 331 dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); 332 ret = PTR_ERR(ac97->clk_ac97); 333 goto err; 334 } 335 336 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 337 regs = devm_ioremap_resource(&pdev->dev, mem); 338 if (IS_ERR(regs)) { 339 ret = PTR_ERR(regs); 340 goto err_clk_put; 341 } 342 343 ac97->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 344 &tegra20_ac97_regmap_config); 345 if (IS_ERR(ac97->regmap)) { 346 dev_err(&pdev->dev, "regmap init failed\n"); 347 ret = PTR_ERR(ac97->regmap); 348 goto err_clk_put; 349 } 350 351 if (of_property_read_u32_array(pdev->dev.of_node, 352 "nvidia,dma-request-selector", 353 of_dma, 2) < 0) { 354 dev_err(&pdev->dev, "No DMA resource\n"); 355 ret = -ENODEV; 356 goto err_clk_put; 357 } 358 359 ac97->reset_gpio = of_get_named_gpio(pdev->dev.of_node, 360 "nvidia,codec-reset-gpio", 0); 361 if (gpio_is_valid(ac97->reset_gpio)) { 362 ret = devm_gpio_request_one(&pdev->dev, ac97->reset_gpio, 363 GPIOF_OUT_INIT_HIGH, "codec-reset"); 364 if (ret) { 365 dev_err(&pdev->dev, "could not get codec-reset GPIO\n"); 366 goto err_clk_put; 367 } 368 } else { 369 dev_err(&pdev->dev, "no codec-reset GPIO supplied\n"); 370 goto err_clk_put; 371 } 372 373 ac97->sync_gpio = of_get_named_gpio(pdev->dev.of_node, 374 "nvidia,codec-sync-gpio", 0); 375 if (!gpio_is_valid(ac97->sync_gpio)) { 376 dev_err(&pdev->dev, "no codec-sync GPIO supplied\n"); 377 goto err_clk_put; 378 } 379 380 ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; 381 ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 382 ac97->capture_dma_data.maxburst = 4; 383 ac97->capture_dma_data.slave_id = of_dma[1]; 384 385 ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; 386 ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 387 ac97->playback_dma_data.maxburst = 4; 388 ac97->playback_dma_data.slave_id = of_dma[1]; 389 390 ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); 391 if (ret) 392 goto err_clk_put; 393 394 ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); 395 if (ret) 396 goto err_asoc_utils_fini; 397 398 ret = clk_prepare_enable(ac97->clk_ac97); 399 if (ret) { 400 dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); 401 goto err_asoc_utils_fini; 402 } 403 404 ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); 405 if (ret) { 406 dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); 407 goto err_asoc_utils_fini; 408 } 409 410 ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, 411 &tegra20_ac97_dai, 1); 412 if (ret) { 413 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 414 ret = -ENOMEM; 415 goto err_asoc_utils_fini; 416 } 417 418 ret = tegra_pcm_platform_register(&pdev->dev); 419 if (ret) { 420 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 421 goto err_unregister_component; 422 } 423 424 /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ 425 workdata = ac97; 426 427 return 0; 428 429 err_unregister_component: 430 snd_soc_unregister_component(&pdev->dev); 431 err_asoc_utils_fini: 432 tegra_asoc_utils_fini(&ac97->util_data); 433 err_clk_put: 434 err: 435 snd_soc_set_ac97_ops(NULL); 436 return ret; 437 } 438 439 static int tegra20_ac97_platform_remove(struct platform_device *pdev) 440 { 441 struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev); 442 443 tegra_pcm_platform_unregister(&pdev->dev); 444 snd_soc_unregister_component(&pdev->dev); 445 446 tegra_asoc_utils_fini(&ac97->util_data); 447 448 clk_disable_unprepare(ac97->clk_ac97); 449 450 snd_soc_set_ac97_ops(NULL); 451 452 return 0; 453 } 454 455 static const struct of_device_id tegra20_ac97_of_match[] = { 456 { .compatible = "nvidia,tegra20-ac97", }, 457 {}, 458 }; 459 460 static struct platform_driver tegra20_ac97_driver = { 461 .driver = { 462 .name = DRV_NAME, 463 .owner = THIS_MODULE, 464 .of_match_table = tegra20_ac97_of_match, 465 }, 466 .probe = tegra20_ac97_platform_probe, 467 .remove = tegra20_ac97_platform_remove, 468 }; 469 module_platform_driver(tegra20_ac97_driver); 470 471 MODULE_AUTHOR("Lucas Stach"); 472 MODULE_DESCRIPTION("Tegra20 AC97 ASoC driver"); 473 MODULE_LICENSE("GPL v2"); 474 MODULE_ALIAS("platform:" DRV_NAME); 475 MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match); 476