davinci_voicecodec.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * DaVinci Voice Codec Core Interface for TI platforms
  4. *
  5. * Copyright (C) 2010 Texas Instruments, Inc
  6. *
  7. * Author: Miguel Aguilar <[email protected]>
  8. */
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/device.h>
  12. #include <linux/slab.h>
  13. #include <linux/delay.h>
  14. #include <linux/io.h>
  15. #include <linux/clk.h>
  16. #include <linux/regmap.h>
  17. #include <sound/pcm.h>
  18. #include <linux/mfd/davinci_voicecodec.h>
  19. static const struct regmap_config davinci_vc_regmap = {
  20. .reg_bits = 32,
  21. .val_bits = 32,
  22. };
  23. static int __init davinci_vc_probe(struct platform_device *pdev)
  24. {
  25. struct davinci_vc *davinci_vc;
  26. struct resource *res;
  27. struct mfd_cell *cell = NULL;
  28. dma_addr_t fifo_base;
  29. int ret;
  30. davinci_vc = devm_kzalloc(&pdev->dev,
  31. sizeof(struct davinci_vc), GFP_KERNEL);
  32. if (!davinci_vc)
  33. return -ENOMEM;
  34. davinci_vc->clk = devm_clk_get(&pdev->dev, NULL);
  35. if (IS_ERR(davinci_vc->clk)) {
  36. dev_dbg(&pdev->dev,
  37. "could not get the clock for voice codec\n");
  38. return -ENODEV;
  39. }
  40. clk_enable(davinci_vc->clk);
  41. davinci_vc->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
  42. if (IS_ERR(davinci_vc->base)) {
  43. ret = PTR_ERR(davinci_vc->base);
  44. goto fail;
  45. }
  46. fifo_base = (dma_addr_t)res->start;
  47. davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev,
  48. davinci_vc->base,
  49. &davinci_vc_regmap);
  50. if (IS_ERR(davinci_vc->regmap)) {
  51. ret = PTR_ERR(davinci_vc->regmap);
  52. goto fail;
  53. }
  54. res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
  55. if (!res) {
  56. dev_err(&pdev->dev, "no DMA resource\n");
  57. ret = -ENXIO;
  58. goto fail;
  59. }
  60. davinci_vc->davinci_vcif.dma_tx_channel = res->start;
  61. davinci_vc->davinci_vcif.dma_tx_addr = fifo_base + DAVINCI_VC_WFIFO;
  62. res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
  63. if (!res) {
  64. dev_err(&pdev->dev, "no DMA resource\n");
  65. ret = -ENXIO;
  66. goto fail;
  67. }
  68. davinci_vc->davinci_vcif.dma_rx_channel = res->start;
  69. davinci_vc->davinci_vcif.dma_rx_addr = fifo_base + DAVINCI_VC_RFIFO;
  70. davinci_vc->dev = &pdev->dev;
  71. davinci_vc->pdev = pdev;
  72. /* Voice codec interface client */
  73. cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
  74. cell->name = "davinci-vcif";
  75. cell->platform_data = davinci_vc;
  76. cell->pdata_size = sizeof(*davinci_vc);
  77. /* Voice codec CQ93VC client */
  78. cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
  79. cell->name = "cq93vc-codec";
  80. cell->platform_data = davinci_vc;
  81. cell->pdata_size = sizeof(*davinci_vc);
  82. ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
  83. DAVINCI_VC_CELLS, NULL, 0, NULL);
  84. if (ret != 0) {
  85. dev_err(&pdev->dev, "fail to register client devices\n");
  86. goto fail;
  87. }
  88. return 0;
  89. fail:
  90. clk_disable(davinci_vc->clk);
  91. return ret;
  92. }
  93. static int davinci_vc_remove(struct platform_device *pdev)
  94. {
  95. struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
  96. mfd_remove_devices(&pdev->dev);
  97. clk_disable(davinci_vc->clk);
  98. return 0;
  99. }
  100. static struct platform_driver davinci_vc_driver = {
  101. .driver = {
  102. .name = "davinci_voicecodec",
  103. },
  104. .remove = davinci_vc_remove,
  105. };
  106. module_platform_driver_probe(davinci_vc_driver, davinci_vc_probe);
  107. MODULE_AUTHOR("Miguel Aguilar");
  108. MODULE_DESCRIPTION("Texas Instruments DaVinci Voice Codec Core Interface");
  109. MODULE_LICENSE("GPL");