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 39 #include "tegra_asoc_utils.h" 40 #include "tegra20_ac97.h" 41 42 #define DRV_NAME "tegra20-ac97" 43 44 static struct tegra20_ac97 *workdata; 45 46 static void tegra20_ac97_codec_reset(struct snd_ac97 *ac97) 47 { 48 u32 readback; 49 unsigned long timeout; 50 51 /* reset line is not driven by DAC pad group, have to toggle GPIO */ 52 gpio_set_value(workdata->reset_gpio, 0); 53 udelay(2); 54 55 gpio_set_value(workdata->reset_gpio, 1); 56 udelay(2); 57 58 timeout = jiffies + msecs_to_jiffies(100); 59 60 do { 61 regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback); 62 if (readback & TEGRA20_AC97_STATUS1_CODEC1_RDY) 63 break; 64 usleep_range(1000, 2000); 65 } while (!time_after(jiffies, timeout)); 66 } 67 68 static void tegra20_ac97_codec_warm_reset(struct snd_ac97 *ac97) 69 { 70 u32 readback; 71 unsigned long timeout; 72 73 /* 74 * although sync line is driven by the DAC pad group warm reset using 75 * the controller cmd is not working, have to toggle sync line 76 * manually. 77 */ 78 gpio_request(workdata->sync_gpio, "codec-sync"); 79 80 gpio_direction_output(workdata->sync_gpio, 1); 81 82 udelay(2); 83 gpio_set_value(workdata->sync_gpio, 0); 84 udelay(2); 85 gpio_free(workdata->sync_gpio); 86 87 timeout = jiffies + msecs_to_jiffies(100); 88 89 do { 90 regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback); 91 if (readback & TEGRA20_AC97_STATUS1_CODEC1_RDY) 92 break; 93 usleep_range(1000, 2000); 94 } while (!time_after(jiffies, timeout)); 95 } 96 97 static unsigned short tegra20_ac97_codec_read(struct snd_ac97 *ac97_snd, 98 unsigned short reg) 99 { 100 u32 readback; 101 unsigned long timeout; 102 103 regmap_write(workdata->regmap, TEGRA20_AC97_CMD, 104 (((reg | 0x80) << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT) & 105 TEGRA20_AC97_CMD_CMD_ADDR_MASK) | 106 TEGRA20_AC97_CMD_BUSY); 107 108 timeout = jiffies + msecs_to_jiffies(100); 109 110 do { 111 regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback); 112 if (readback & TEGRA20_AC97_STATUS1_STA_VALID1) 113 break; 114 usleep_range(1000, 2000); 115 } while (!time_after(jiffies, timeout)); 116 117 return ((readback & TEGRA20_AC97_STATUS1_STA_DATA1_MASK) >> 118 TEGRA20_AC97_STATUS1_STA_DATA1_SHIFT); 119 } 120 121 static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, 122 unsigned short reg, unsigned short val) 123 { 124 u32 readback; 125 unsigned long timeout; 126 127 regmap_write(workdata->regmap, TEGRA20_AC97_CMD, 128 ((reg << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT) & 129 TEGRA20_AC97_CMD_CMD_ADDR_MASK) | 130 ((val << TEGRA20_AC97_CMD_CMD_DATA_SHIFT) & 131 TEGRA20_AC97_CMD_CMD_DATA_MASK) | 132 TEGRA20_AC97_CMD_BUSY); 133 134 timeout = jiffies + msecs_to_jiffies(100); 135 136 do { 137 regmap_read(workdata->regmap, TEGRA20_AC97_CMD, &readback); 138 if (!(readback & TEGRA20_AC97_CMD_BUSY)) 139 break; 140 usleep_range(1000, 2000); 141 } while (!time_after(jiffies, timeout)); 142 } 143 144 struct snd_ac97_bus_ops soc_ac97_ops = { 145 .read = tegra20_ac97_codec_read, 146 .write = tegra20_ac97_codec_write, 147 .reset = tegra20_ac97_codec_reset, 148 .warm_reset = tegra20_ac97_codec_warm_reset, 149 }; 150 EXPORT_SYMBOL_GPL(soc_ac97_ops); 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 bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg) 252 { 253 switch (reg) { 254 case TEGRA20_AC97_CTRL: 255 case TEGRA20_AC97_CMD: 256 case TEGRA20_AC97_STATUS1: 257 case TEGRA20_AC97_FIFO1_SCR: 258 case TEGRA20_AC97_FIFO_TX1: 259 case TEGRA20_AC97_FIFO_RX1: 260 return true; 261 default: 262 break; 263 } 264 265 return false; 266 } 267 268 static bool tegra20_ac97_volatile_reg(struct device *dev, unsigned int reg) 269 { 270 switch (reg) { 271 case TEGRA20_AC97_STATUS1: 272 case TEGRA20_AC97_FIFO1_SCR: 273 case TEGRA20_AC97_FIFO_TX1: 274 case TEGRA20_AC97_FIFO_RX1: 275 return true; 276 default: 277 break; 278 } 279 280 return false; 281 } 282 283 static bool tegra20_ac97_precious_reg(struct device *dev, unsigned int reg) 284 { 285 switch (reg) { 286 case TEGRA20_AC97_FIFO_TX1: 287 case TEGRA20_AC97_FIFO_RX1: 288 return true; 289 default: 290 break; 291 } 292 293 return false; 294 } 295 296 static const struct regmap_config tegra20_ac97_regmap_config = { 297 .reg_bits = 32, 298 .reg_stride = 4, 299 .val_bits = 32, 300 .max_register = TEGRA20_AC97_FIFO_RX1, 301 .writeable_reg = tegra20_ac97_wr_rd_reg, 302 .readable_reg = tegra20_ac97_wr_rd_reg, 303 .volatile_reg = tegra20_ac97_volatile_reg, 304 .precious_reg = tegra20_ac97_precious_reg, 305 .cache_type = REGCACHE_RBTREE, 306 }; 307 308 static int tegra20_ac97_platform_probe(struct platform_device *pdev) 309 { 310 struct tegra20_ac97 *ac97; 311 struct resource *mem, *memregion; 312 u32 of_dma[2]; 313 void __iomem *regs; 314 int ret = 0; 315 316 ac97 = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_ac97), 317 GFP_KERNEL); 318 if (!ac97) { 319 dev_err(&pdev->dev, "Can't allocate tegra20_ac97\n"); 320 ret = -ENOMEM; 321 goto err; 322 } 323 dev_set_drvdata(&pdev->dev, ac97); 324 325 ac97->clk_ac97 = clk_get(&pdev->dev, NULL); 326 if (IS_ERR(ac97->clk_ac97)) { 327 dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); 328 ret = PTR_ERR(ac97->clk_ac97); 329 goto err; 330 } 331 332 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 333 if (!mem) { 334 dev_err(&pdev->dev, "No memory resource\n"); 335 ret = -ENODEV; 336 goto err_clk_put; 337 } 338 339 memregion = devm_request_mem_region(&pdev->dev, mem->start, 340 resource_size(mem), DRV_NAME); 341 if (!memregion) { 342 dev_err(&pdev->dev, "Memory region already claimed\n"); 343 ret = -EBUSY; 344 goto err_clk_put; 345 } 346 347 regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); 348 if (!regs) { 349 dev_err(&pdev->dev, "ioremap failed\n"); 350 ret = -ENOMEM; 351 goto err_clk_put; 352 } 353 354 ac97->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 355 &tegra20_ac97_regmap_config); 356 if (IS_ERR(ac97->regmap)) { 357 dev_err(&pdev->dev, "regmap init failed\n"); 358 ret = PTR_ERR(ac97->regmap); 359 goto err_clk_put; 360 } 361 362 if (of_property_read_u32_array(pdev->dev.of_node, 363 "nvidia,dma-request-selector", 364 of_dma, 2) < 0) { 365 dev_err(&pdev->dev, "No DMA resource\n"); 366 ret = -ENODEV; 367 goto err_clk_put; 368 } 369 370 ac97->reset_gpio = of_get_named_gpio(pdev->dev.of_node, 371 "nvidia,codec-reset-gpio", 0); 372 if (gpio_is_valid(ac97->reset_gpio)) { 373 ret = devm_gpio_request_one(&pdev->dev, ac97->reset_gpio, 374 GPIOF_OUT_INIT_HIGH, "codec-reset"); 375 if (ret) { 376 dev_err(&pdev->dev, "could not get codec-reset GPIO\n"); 377 goto err_clk_put; 378 } 379 } else { 380 dev_err(&pdev->dev, "no codec-reset GPIO supplied\n"); 381 goto err_clk_put; 382 } 383 384 ac97->sync_gpio = of_get_named_gpio(pdev->dev.of_node, 385 "nvidia,codec-sync-gpio", 0); 386 if (!gpio_is_valid(ac97->sync_gpio)) { 387 dev_err(&pdev->dev, "no codec-sync GPIO supplied\n"); 388 goto err_clk_put; 389 } 390 391 ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; 392 ac97->capture_dma_data.wrap = 4; 393 ac97->capture_dma_data.width = 32; 394 ac97->capture_dma_data.req_sel = of_dma[1]; 395 396 ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; 397 ac97->playback_dma_data.wrap = 4; 398 ac97->playback_dma_data.width = 32; 399 ac97->playback_dma_data.req_sel = of_dma[1]; 400 401 ret = snd_soc_register_dais(&pdev->dev, &tegra20_ac97_dai, 1); 402 if (ret) { 403 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 404 ret = -ENOMEM; 405 goto err_clk_put; 406 } 407 408 ret = tegra_pcm_platform_register(&pdev->dev); 409 if (ret) { 410 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 411 goto err_unregister_dai; 412 } 413 414 ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); 415 if (ret) 416 goto err_unregister_pcm; 417 418 ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); 419 if (ret) 420 goto err_asoc_utils_fini; 421 422 ret = clk_prepare_enable(ac97->clk_ac97); 423 if (ret) { 424 dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); 425 goto err_asoc_utils_fini; 426 } 427 428 /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ 429 workdata = ac97; 430 431 return 0; 432 433 err_asoc_utils_fini: 434 tegra_asoc_utils_fini(&ac97->util_data); 435 err_unregister_pcm: 436 tegra_pcm_platform_unregister(&pdev->dev); 437 err_unregister_dai: 438 snd_soc_unregister_dai(&pdev->dev); 439 err_clk_put: 440 clk_put(ac97->clk_ac97); 441 err: 442 return ret; 443 } 444 445 static int tegra20_ac97_platform_remove(struct platform_device *pdev) 446 { 447 struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev); 448 449 tegra_pcm_platform_unregister(&pdev->dev); 450 snd_soc_unregister_dai(&pdev->dev); 451 452 tegra_asoc_utils_fini(&ac97->util_data); 453 454 clk_disable_unprepare(ac97->clk_ac97); 455 clk_put(ac97->clk_ac97); 456 457 return 0; 458 } 459 460 static const struct of_device_id tegra20_ac97_of_match[] = { 461 { .compatible = "nvidia,tegra20-ac97", }, 462 {}, 463 }; 464 465 static struct platform_driver tegra20_ac97_driver = { 466 .driver = { 467 .name = DRV_NAME, 468 .owner = THIS_MODULE, 469 .of_match_table = tegra20_ac97_of_match, 470 }, 471 .probe = tegra20_ac97_platform_probe, 472 .remove = tegra20_ac97_platform_remove, 473 }; 474 module_platform_driver(tegra20_ac97_driver); 475 476 MODULE_AUTHOR("Lucas Stach"); 477 MODULE_DESCRIPTION("Tegra20 AC97 ASoC driver"); 478 MODULE_LICENSE("GPL v2"); 479 MODULE_ALIAS("platform:" DRV_NAME); 480 MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match); 481