tegra20_das.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * tegra20_das.c - Tegra20 DAS driver
  3. *
  4. * Author: Stephen Warren <swarren@nvidia.com>
  5. * Copyright (C) 2010 - NVIDIA, Inc.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * version 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  19. * 02110-1301 USA
  20. *
  21. */
  22. #include <linux/device.h>
  23. #include <linux/io.h>
  24. #include <linux/module.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/regmap.h>
  27. #include <linux/slab.h>
  28. #include <sound/soc.h>
  29. #include "tegra20_das.h"
  30. #define DRV_NAME "tegra20-das"
  31. static struct tegra20_das *das;
  32. static inline void tegra20_das_write(u32 reg, u32 val)
  33. {
  34. regmap_write(das->regmap, reg, val);
  35. }
  36. static inline u32 tegra20_das_read(u32 reg)
  37. {
  38. u32 val;
  39. regmap_read(das->regmap, reg, &val);
  40. return val;
  41. }
  42. int tegra20_das_connect_dap_to_dac(int dap, int dac)
  43. {
  44. u32 addr;
  45. u32 reg;
  46. if (!das)
  47. return -ENODEV;
  48. addr = TEGRA20_DAS_DAP_CTRL_SEL +
  49. (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
  50. reg = dac << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
  51. tegra20_das_write(addr, reg);
  52. return 0;
  53. }
  54. EXPORT_SYMBOL_GPL(tegra20_das_connect_dap_to_dac);
  55. int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master,
  56. int sdata1rx, int sdata2rx)
  57. {
  58. u32 addr;
  59. u32 reg;
  60. if (!das)
  61. return -ENODEV;
  62. addr = TEGRA20_DAS_DAP_CTRL_SEL +
  63. (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
  64. reg = otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
  65. !!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
  66. !!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
  67. !!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
  68. tegra20_das_write(addr, reg);
  69. return 0;
  70. }
  71. EXPORT_SYMBOL_GPL(tegra20_das_connect_dap_to_dap);
  72. int tegra20_das_connect_dac_to_dap(int dac, int dap)
  73. {
  74. u32 addr;
  75. u32 reg;
  76. if (!das)
  77. return -ENODEV;
  78. addr = TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL +
  79. (dac * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
  80. reg = dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
  81. dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
  82. dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
  83. tegra20_das_write(addr, reg);
  84. return 0;
  85. }
  86. EXPORT_SYMBOL_GPL(tegra20_das_connect_dac_to_dap);
  87. #define LAST_REG(name) \
  88. (TEGRA20_DAS_##name + \
  89. (TEGRA20_DAS_##name##_STRIDE * (TEGRA20_DAS_##name##_COUNT - 1)))
  90. static bool tegra20_das_wr_rd_reg(struct device *dev, unsigned int reg)
  91. {
  92. if ((reg >= TEGRA20_DAS_DAP_CTRL_SEL) &&
  93. (reg <= LAST_REG(DAP_CTRL_SEL)))
  94. return true;
  95. if ((reg >= TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL) &&
  96. (reg <= LAST_REG(DAC_INPUT_DATA_CLK_SEL)))
  97. return true;
  98. return false;
  99. }
  100. static const struct regmap_config tegra20_das_regmap_config = {
  101. .reg_bits = 32,
  102. .reg_stride = 4,
  103. .val_bits = 32,
  104. .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL),
  105. .writeable_reg = tegra20_das_wr_rd_reg,
  106. .readable_reg = tegra20_das_wr_rd_reg,
  107. .cache_type = REGCACHE_FLAT,
  108. };
  109. static int tegra20_das_probe(struct platform_device *pdev)
  110. {
  111. struct resource *res;
  112. void __iomem *regs;
  113. int ret = 0;
  114. if (das)
  115. return -ENODEV;
  116. das = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_das), GFP_KERNEL);
  117. if (!das) {
  118. dev_err(&pdev->dev, "Can't allocate tegra20_das\n");
  119. ret = -ENOMEM;
  120. goto err;
  121. }
  122. das->dev = &pdev->dev;
  123. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  124. regs = devm_ioremap_resource(&pdev->dev, res);
  125. if (IS_ERR(regs)) {
  126. ret = PTR_ERR(regs);
  127. goto err;
  128. }
  129. das->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
  130. &tegra20_das_regmap_config);
  131. if (IS_ERR(das->regmap)) {
  132. dev_err(&pdev->dev, "regmap init failed\n");
  133. ret = PTR_ERR(das->regmap);
  134. goto err;
  135. }
  136. ret = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
  137. TEGRA20_DAS_DAP_SEL_DAC1);
  138. if (ret) {
  139. dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
  140. goto err;
  141. }
  142. ret = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAC_ID_1,
  143. TEGRA20_DAS_DAC_SEL_DAP1);
  144. if (ret) {
  145. dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
  146. goto err;
  147. }
  148. ret = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_3,
  149. TEGRA20_DAS_DAP_SEL_DAC3);
  150. if (ret) {
  151. dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
  152. goto err;
  153. }
  154. ret = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAC_ID_3,
  155. TEGRA20_DAS_DAC_SEL_DAP3);
  156. if (ret) {
  157. dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
  158. goto err;
  159. }
  160. platform_set_drvdata(pdev, das);
  161. return 0;
  162. err:
  163. das = NULL;
  164. return ret;
  165. }
  166. static int tegra20_das_remove(struct platform_device *pdev)
  167. {
  168. if (!das)
  169. return -ENODEV;
  170. das = NULL;
  171. return 0;
  172. }
  173. static const struct of_device_id tegra20_das_of_match[] = {
  174. { .compatible = "nvidia,tegra20-das", },
  175. {},
  176. };
  177. static struct platform_driver tegra20_das_driver = {
  178. .probe = tegra20_das_probe,
  179. .remove = tegra20_das_remove,
  180. .driver = {
  181. .name = DRV_NAME,
  182. .of_match_table = tegra20_das_of_match,
  183. },
  184. };
  185. module_platform_driver(tegra20_das_driver);
  186. MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
  187. MODULE_DESCRIPTION("Tegra20 DAS driver");
  188. MODULE_LICENSE("GPL");
  189. MODULE_ALIAS("platform:" DRV_NAME);
  190. MODULE_DEVICE_TABLE(of, tegra20_das_of_match);