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 struct snd_ac97_bus_ops soc_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 EXPORT_SYMBOL_GPL(soc_ac97_ops); 152 153 static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) 154 { 155 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 156 TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 157 TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN); 158 159 regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL, 160 TEGRA20_AC97_CTRL_PCM_DAC_EN | 161 TEGRA20_AC97_CTRL_STM_EN, 162 TEGRA20_AC97_CTRL_PCM_DAC_EN | 163 TEGRA20_AC97_CTRL_STM_EN); 164 } 165 166 static inline void tegra20_ac97_stop_playback(struct tegra20_ac97 *ac97) 167 { 168 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 169 TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 0); 170 171 regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL, 172 TEGRA20_AC97_CTRL_PCM_DAC_EN, 0); 173 } 174 175 static inline void tegra20_ac97_start_capture(struct tegra20_ac97 *ac97) 176 { 177 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 178 TEGRA20_AC97_FIFO_SCR_REC_FULL_EN, 179 TEGRA20_AC97_FIFO_SCR_REC_FULL_EN); 180 } 181 182 static inline void tegra20_ac97_stop_capture(struct tegra20_ac97 *ac97) 183 { 184 regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR, 185 TEGRA20_AC97_FIFO_SCR_REC_FULL_EN, 0); 186 } 187 188 static int tegra20_ac97_trigger(struct snd_pcm_substream *substream, int cmd, 189 struct snd_soc_dai *dai) 190 { 191 struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai); 192 193 switch (cmd) { 194 case SNDRV_PCM_TRIGGER_START: 195 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 196 case SNDRV_PCM_TRIGGER_RESUME: 197 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 198 tegra20_ac97_start_playback(ac97); 199 else 200 tegra20_ac97_start_capture(ac97); 201 break; 202 case SNDRV_PCM_TRIGGER_STOP: 203 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 204 case SNDRV_PCM_TRIGGER_SUSPEND: 205 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 206 tegra20_ac97_stop_playback(ac97); 207 else 208 tegra20_ac97_stop_capture(ac97); 209 break; 210 default: 211 return -EINVAL; 212 } 213 214 return 0; 215 } 216 217 static const struct snd_soc_dai_ops tegra20_ac97_dai_ops = { 218 .trigger = tegra20_ac97_trigger, 219 }; 220 221 static int tegra20_ac97_probe(struct snd_soc_dai *dai) 222 { 223 struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai); 224 225 dai->capture_dma_data = &ac97->capture_dma_data; 226 dai->playback_dma_data = &ac97->playback_dma_data; 227 228 return 0; 229 } 230 231 static struct snd_soc_dai_driver tegra20_ac97_dai = { 232 .name = "tegra-ac97-pcm", 233 .ac97_control = 1, 234 .probe = tegra20_ac97_probe, 235 .playback = { 236 .stream_name = "PCM Playback", 237 .channels_min = 2, 238 .channels_max = 2, 239 .rates = SNDRV_PCM_RATE_8000_48000, 240 .formats = SNDRV_PCM_FMTBIT_S16_LE, 241 }, 242 .capture = { 243 .stream_name = "PCM Capture", 244 .channels_min = 2, 245 .channels_max = 2, 246 .rates = SNDRV_PCM_RATE_8000_48000, 247 .formats = SNDRV_PCM_FMTBIT_S16_LE, 248 }, 249 .ops = &tegra20_ac97_dai_ops, 250 }; 251 252 static const struct snd_soc_component_driver tegra20_ac97_component = { 253 .name = DRV_NAME, 254 }; 255 256 static bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg) 257 { 258 switch (reg) { 259 case TEGRA20_AC97_CTRL: 260 case TEGRA20_AC97_CMD: 261 case TEGRA20_AC97_STATUS1: 262 case TEGRA20_AC97_FIFO1_SCR: 263 case TEGRA20_AC97_FIFO_TX1: 264 case TEGRA20_AC97_FIFO_RX1: 265 return true; 266 default: 267 break; 268 } 269 270 return false; 271 } 272 273 static bool tegra20_ac97_volatile_reg(struct device *dev, unsigned int reg) 274 { 275 switch (reg) { 276 case TEGRA20_AC97_STATUS1: 277 case TEGRA20_AC97_FIFO1_SCR: 278 case TEGRA20_AC97_FIFO_TX1: 279 case TEGRA20_AC97_FIFO_RX1: 280 return true; 281 default: 282 break; 283 } 284 285 return false; 286 } 287 288 static bool tegra20_ac97_precious_reg(struct device *dev, unsigned int reg) 289 { 290 switch (reg) { 291 case TEGRA20_AC97_FIFO_TX1: 292 case TEGRA20_AC97_FIFO_RX1: 293 return true; 294 default: 295 break; 296 } 297 298 return false; 299 } 300 301 static const struct regmap_config tegra20_ac97_regmap_config = { 302 .reg_bits = 32, 303 .reg_stride = 4, 304 .val_bits = 32, 305 .max_register = TEGRA20_AC97_FIFO_RX1, 306 .writeable_reg = tegra20_ac97_wr_rd_reg, 307 .readable_reg = tegra20_ac97_wr_rd_reg, 308 .volatile_reg = tegra20_ac97_volatile_reg, 309 .precious_reg = tegra20_ac97_precious_reg, 310 .cache_type = REGCACHE_RBTREE, 311 }; 312 313 static int tegra20_ac97_platform_probe(struct platform_device *pdev) 314 { 315 struct tegra20_ac97 *ac97; 316 struct resource *mem, *memregion; 317 u32 of_dma[2]; 318 void __iomem *regs; 319 int ret = 0; 320 321 ac97 = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_ac97), 322 GFP_KERNEL); 323 if (!ac97) { 324 dev_err(&pdev->dev, "Can't allocate tegra20_ac97\n"); 325 ret = -ENOMEM; 326 goto err; 327 } 328 dev_set_drvdata(&pdev->dev, ac97); 329 330 ac97->clk_ac97 = clk_get(&pdev->dev, NULL); 331 if (IS_ERR(ac97->clk_ac97)) { 332 dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); 333 ret = PTR_ERR(ac97->clk_ac97); 334 goto err; 335 } 336 337 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 338 if (!mem) { 339 dev_err(&pdev->dev, "No memory resource\n"); 340 ret = -ENODEV; 341 goto err_clk_put; 342 } 343 344 memregion = devm_request_mem_region(&pdev->dev, mem->start, 345 resource_size(mem), DRV_NAME); 346 if (!memregion) { 347 dev_err(&pdev->dev, "Memory region already claimed\n"); 348 ret = -EBUSY; 349 goto err_clk_put; 350 } 351 352 regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); 353 if (!regs) { 354 dev_err(&pdev->dev, "ioremap failed\n"); 355 ret = -ENOMEM; 356 goto err_clk_put; 357 } 358 359 ac97->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 360 &tegra20_ac97_regmap_config); 361 if (IS_ERR(ac97->regmap)) { 362 dev_err(&pdev->dev, "regmap init failed\n"); 363 ret = PTR_ERR(ac97->regmap); 364 goto err_clk_put; 365 } 366 367 if (of_property_read_u32_array(pdev->dev.of_node, 368 "nvidia,dma-request-selector", 369 of_dma, 2) < 0) { 370 dev_err(&pdev->dev, "No DMA resource\n"); 371 ret = -ENODEV; 372 goto err_clk_put; 373 } 374 375 ac97->reset_gpio = of_get_named_gpio(pdev->dev.of_node, 376 "nvidia,codec-reset-gpio", 0); 377 if (gpio_is_valid(ac97->reset_gpio)) { 378 ret = devm_gpio_request_one(&pdev->dev, ac97->reset_gpio, 379 GPIOF_OUT_INIT_HIGH, "codec-reset"); 380 if (ret) { 381 dev_err(&pdev->dev, "could not get codec-reset GPIO\n"); 382 goto err_clk_put; 383 } 384 } else { 385 dev_err(&pdev->dev, "no codec-reset GPIO supplied\n"); 386 goto err_clk_put; 387 } 388 389 ac97->sync_gpio = of_get_named_gpio(pdev->dev.of_node, 390 "nvidia,codec-sync-gpio", 0); 391 if (!gpio_is_valid(ac97->sync_gpio)) { 392 dev_err(&pdev->dev, "no codec-sync GPIO supplied\n"); 393 goto err_clk_put; 394 } 395 396 ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; 397 ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 398 ac97->capture_dma_data.maxburst = 4; 399 ac97->capture_dma_data.slave_id = of_dma[1]; 400 401 ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; 402 ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 403 ac97->capture_dma_data.maxburst = 4; 404 ac97->capture_dma_data.slave_id = of_dma[0]; 405 406 ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, 407 &tegra20_ac97_dai, 1); 408 if (ret) { 409 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 410 ret = -ENOMEM; 411 goto err_clk_put; 412 } 413 414 ret = tegra_pcm_platform_register(&pdev->dev); 415 if (ret) { 416 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 417 goto err_unregister_component; 418 } 419 420 ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); 421 if (ret) 422 goto err_unregister_pcm; 423 424 ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); 425 if (ret) 426 goto err_asoc_utils_fini; 427 428 ret = clk_prepare_enable(ac97->clk_ac97); 429 if (ret) { 430 dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); 431 goto err_asoc_utils_fini; 432 } 433 434 /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ 435 workdata = ac97; 436 437 return 0; 438 439 err_asoc_utils_fini: 440 tegra_asoc_utils_fini(&ac97->util_data); 441 err_unregister_pcm: 442 tegra_pcm_platform_unregister(&pdev->dev); 443 err_unregister_component: 444 snd_soc_unregister_component(&pdev->dev); 445 err_clk_put: 446 clk_put(ac97->clk_ac97); 447 err: 448 return ret; 449 } 450 451 static int tegra20_ac97_platform_remove(struct platform_device *pdev) 452 { 453 struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev); 454 455 tegra_pcm_platform_unregister(&pdev->dev); 456 snd_soc_unregister_component(&pdev->dev); 457 458 tegra_asoc_utils_fini(&ac97->util_data); 459 460 clk_disable_unprepare(ac97->clk_ac97); 461 clk_put(ac97->clk_ac97); 462 463 return 0; 464 } 465 466 static const struct of_device_id tegra20_ac97_of_match[] = { 467 { .compatible = "nvidia,tegra20-ac97", }, 468 {}, 469 }; 470 471 static struct platform_driver tegra20_ac97_driver = { 472 .driver = { 473 .name = DRV_NAME, 474 .owner = THIS_MODULE, 475 .of_match_table = tegra20_ac97_of_match, 476 }, 477 .probe = tegra20_ac97_platform_probe, 478 .remove = tegra20_ac97_platform_remove, 479 }; 480 module_platform_driver(tegra20_ac97_driver); 481 482 MODULE_AUTHOR("Lucas Stach"); 483 MODULE_DESCRIPTION("Tegra20 AC97 ASoC driver"); 484 MODULE_LICENSE("GPL v2"); 485 MODULE_ALIAS("platform:" DRV_NAME); 486 MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match); 487