diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-04-13 14:14:07 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-13 14:16:53 -0400 |
commit | 5939ae74753ceda976732899bef71f99ffea6ea5 (patch) | |
tree | 8226f5a9a601ae1fd86a37be1f6f720974e92e53 /sound/soc/tegra | |
parent | c1607416aa59b8bc78445f8ac3de559ed68864a2 (diff) |
ASoC: convert Tegra20 SPDIF driver to regmap
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.c | 173 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.h | 3 |
2 files changed, 92 insertions, 84 deletions
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 9efd71e13a0a..f9b57418bd08 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c | |||
@@ -21,13 +21,12 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/debugfs.h> | ||
25 | #include <linux/device.h> | 24 | #include <linux/device.h> |
26 | #include <linux/io.h> | 25 | #include <linux/io.h> |
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
28 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
29 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
30 | #include <linux/seq_file.h> | 29 | #include <linux/regmap.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
32 | #include <sound/core.h> | 31 | #include <sound/core.h> |
33 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -41,12 +40,14 @@ | |||
41 | static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg, | 40 | static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg, |
42 | u32 val) | 41 | u32 val) |
43 | { | 42 | { |
44 | __raw_writel(val, spdif->regs + reg); | 43 | regmap_write(spdif->regmap, reg, val); |
45 | } | 44 | } |
46 | 45 | ||
47 | static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg) | 46 | static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg) |
48 | { | 47 | { |
49 | return __raw_readl(spdif->regs + reg); | 48 | u32 val; |
49 | regmap_read(spdif->regmap, reg, &val); | ||
50 | return val; | ||
50 | } | 51 | } |
51 | 52 | ||
52 | static int tegra20_spdif_runtime_suspend(struct device *dev) | 53 | static int tegra20_spdif_runtime_suspend(struct device *dev) |
@@ -72,78 +73,6 @@ static int tegra20_spdif_runtime_resume(struct device *dev) | |||
72 | return 0; | 73 | return 0; |
73 | } | 74 | } |
74 | 75 | ||
75 | #ifdef CONFIG_DEBUG_FS | ||
76 | static int tegra20_spdif_show(struct seq_file *s, void *unused) | ||
77 | { | ||
78 | #define REG(r) { r, #r } | ||
79 | static const struct { | ||
80 | int offset; | ||
81 | const char *name; | ||
82 | } regs[] = { | ||
83 | REG(TEGRA20_SPDIF_CTRL), | ||
84 | REG(TEGRA20_SPDIF_STATUS), | ||
85 | REG(TEGRA20_SPDIF_STROBE_CTRL), | ||
86 | REG(TEGRA20_SPDIF_DATA_FIFO_CSR), | ||
87 | REG(TEGRA20_SPDIF_CH_STA_RX_A), | ||
88 | REG(TEGRA20_SPDIF_CH_STA_RX_B), | ||
89 | REG(TEGRA20_SPDIF_CH_STA_RX_C), | ||
90 | REG(TEGRA20_SPDIF_CH_STA_RX_D), | ||
91 | REG(TEGRA20_SPDIF_CH_STA_RX_E), | ||
92 | REG(TEGRA20_SPDIF_CH_STA_RX_F), | ||
93 | REG(TEGRA20_SPDIF_CH_STA_TX_A), | ||
94 | REG(TEGRA20_SPDIF_CH_STA_TX_B), | ||
95 | REG(TEGRA20_SPDIF_CH_STA_TX_C), | ||
96 | REG(TEGRA20_SPDIF_CH_STA_TX_D), | ||
97 | REG(TEGRA20_SPDIF_CH_STA_TX_E), | ||
98 | REG(TEGRA20_SPDIF_CH_STA_TX_F), | ||
99 | }; | ||
100 | #undef REG | ||
101 | |||
102 | struct tegra20_spdif *spdif = s->private; | ||
103 | int i; | ||
104 | |||
105 | for (i = 0; i < ARRAY_SIZE(regs); i++) { | ||
106 | u32 val = tegra20_spdif_read(spdif, regs[i].offset); | ||
107 | seq_printf(s, "%s = %08x\n", regs[i].name, val); | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int tegra20_spdif_debug_open(struct inode *inode, struct file *file) | ||
114 | { | ||
115 | return single_open(file, tegra20_spdif_show, inode->i_private); | ||
116 | } | ||
117 | |||
118 | static const struct file_operations tegra20_spdif_debug_fops = { | ||
119 | .open = tegra20_spdif_debug_open, | ||
120 | .read = seq_read, | ||
121 | .llseek = seq_lseek, | ||
122 | .release = single_release, | ||
123 | }; | ||
124 | |||
125 | static void tegra20_spdif_debug_add(struct tegra20_spdif *spdif) | ||
126 | { | ||
127 | spdif->debug = debugfs_create_file(DRV_NAME, S_IRUGO, | ||
128 | snd_soc_debugfs_root, spdif, | ||
129 | &tegra20_spdif_debug_fops); | ||
130 | } | ||
131 | |||
132 | static void tegra20_spdif_debug_remove(struct tegra20_spdif *spdif) | ||
133 | { | ||
134 | if (spdif->debug) | ||
135 | debugfs_remove(spdif->debug); | ||
136 | } | ||
137 | #else | ||
138 | static inline void tegra20_spdif_debug_add(struct tegra20_spdif *spdif) | ||
139 | { | ||
140 | } | ||
141 | |||
142 | static inline void tegra20_spdif_debug_remove(struct tegra20_spdif *spdif) | ||
143 | { | ||
144 | } | ||
145 | #endif | ||
146 | |||
147 | static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, | 76 | static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, |
148 | struct snd_pcm_hw_params *params, | 77 | struct snd_pcm_hw_params *params, |
149 | struct snd_soc_dai *dai) | 78 | struct snd_soc_dai *dai) |
@@ -261,10 +190,86 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = { | |||
261 | .ops = &tegra20_spdif_dai_ops, | 190 | .ops = &tegra20_spdif_dai_ops, |
262 | }; | 191 | }; |
263 | 192 | ||
193 | static bool tegra20_spdif_wr_rd_reg(struct device *dev, unsigned int reg) | ||
194 | { | ||
195 | switch (reg) { | ||
196 | case TEGRA20_SPDIF_CTRL: | ||
197 | case TEGRA20_SPDIF_STATUS: | ||
198 | case TEGRA20_SPDIF_STROBE_CTRL: | ||
199 | case TEGRA20_SPDIF_DATA_FIFO_CSR: | ||
200 | case TEGRA20_SPDIF_DATA_OUT: | ||
201 | case TEGRA20_SPDIF_DATA_IN: | ||
202 | case TEGRA20_SPDIF_CH_STA_RX_A: | ||
203 | case TEGRA20_SPDIF_CH_STA_RX_B: | ||
204 | case TEGRA20_SPDIF_CH_STA_RX_C: | ||
205 | case TEGRA20_SPDIF_CH_STA_RX_D: | ||
206 | case TEGRA20_SPDIF_CH_STA_RX_E: | ||
207 | case TEGRA20_SPDIF_CH_STA_RX_F: | ||
208 | case TEGRA20_SPDIF_CH_STA_TX_A: | ||
209 | case TEGRA20_SPDIF_CH_STA_TX_B: | ||
210 | case TEGRA20_SPDIF_CH_STA_TX_C: | ||
211 | case TEGRA20_SPDIF_CH_STA_TX_D: | ||
212 | case TEGRA20_SPDIF_CH_STA_TX_E: | ||
213 | case TEGRA20_SPDIF_CH_STA_TX_F: | ||
214 | case TEGRA20_SPDIF_USR_STA_RX_A: | ||
215 | case TEGRA20_SPDIF_USR_DAT_TX_A: | ||
216 | return true; | ||
217 | default: | ||
218 | return false; | ||
219 | }; | ||
220 | } | ||
221 | |||
222 | static bool tegra20_spdif_volatile_reg(struct device *dev, unsigned int reg) | ||
223 | { | ||
224 | switch (reg) { | ||
225 | case TEGRA20_SPDIF_STATUS: | ||
226 | case TEGRA20_SPDIF_DATA_FIFO_CSR: | ||
227 | case TEGRA20_SPDIF_DATA_OUT: | ||
228 | case TEGRA20_SPDIF_DATA_IN: | ||
229 | case TEGRA20_SPDIF_CH_STA_RX_A: | ||
230 | case TEGRA20_SPDIF_CH_STA_RX_B: | ||
231 | case TEGRA20_SPDIF_CH_STA_RX_C: | ||
232 | case TEGRA20_SPDIF_CH_STA_RX_D: | ||
233 | case TEGRA20_SPDIF_CH_STA_RX_E: | ||
234 | case TEGRA20_SPDIF_CH_STA_RX_F: | ||
235 | case TEGRA20_SPDIF_USR_STA_RX_A: | ||
236 | case TEGRA20_SPDIF_USR_DAT_TX_A: | ||
237 | return true; | ||
238 | default: | ||
239 | return false; | ||
240 | }; | ||
241 | } | ||
242 | |||
243 | static bool tegra20_spdif_precious_reg(struct device *dev, unsigned int reg) | ||
244 | { | ||
245 | switch (reg) { | ||
246 | case TEGRA20_SPDIF_DATA_OUT: | ||
247 | case TEGRA20_SPDIF_DATA_IN: | ||
248 | case TEGRA20_SPDIF_USR_STA_RX_A: | ||
249 | case TEGRA20_SPDIF_USR_DAT_TX_A: | ||
250 | return true; | ||
251 | default: | ||
252 | return false; | ||
253 | }; | ||
254 | } | ||
255 | |||
256 | static const struct regmap_config tegra20_spdif_regmap_config = { | ||
257 | .reg_bits = 32, | ||
258 | .reg_stride = 4, | ||
259 | .val_bits = 32, | ||
260 | .max_register = TEGRA20_SPDIF_USR_DAT_TX_A, | ||
261 | .writeable_reg = tegra20_spdif_wr_rd_reg, | ||
262 | .readable_reg = tegra20_spdif_wr_rd_reg, | ||
263 | .volatile_reg = tegra20_spdif_volatile_reg, | ||
264 | .precious_reg = tegra20_spdif_precious_reg, | ||
265 | .cache_type = REGCACHE_RBTREE, | ||
266 | }; | ||
267 | |||
264 | static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev) | 268 | static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev) |
265 | { | 269 | { |
266 | struct tegra20_spdif *spdif; | 270 | struct tegra20_spdif *spdif; |
267 | struct resource *mem, *memregion, *dmareq; | 271 | struct resource *mem, *memregion, *dmareq; |
272 | void __iomem *regs; | ||
268 | int ret; | 273 | int ret; |
269 | 274 | ||
270 | spdif = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_spdif), | 275 | spdif = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_spdif), |
@@ -305,13 +310,21 @@ static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev) | |||
305 | goto err_clk_put; | 310 | goto err_clk_put; |
306 | } | 311 | } |
307 | 312 | ||
308 | spdif->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 313 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
309 | if (!spdif->regs) { | 314 | if (!regs) { |
310 | dev_err(&pdev->dev, "ioremap failed\n"); | 315 | dev_err(&pdev->dev, "ioremap failed\n"); |
311 | ret = -ENOMEM; | 316 | ret = -ENOMEM; |
312 | goto err_clk_put; | 317 | goto err_clk_put; |
313 | } | 318 | } |
314 | 319 | ||
320 | spdif->regmap = devm_regmap_init_mmio(&pdev->dev, regs, | ||
321 | &tegra20_spdif_regmap_config); | ||
322 | if (IS_ERR(spdif->regmap)) { | ||
323 | dev_err(&pdev->dev, "regmap init failed\n"); | ||
324 | ret = PTR_ERR(spdif->regmap); | ||
325 | goto err_clk_put; | ||
326 | } | ||
327 | |||
315 | spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; | 328 | spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; |
316 | spdif->playback_dma_data.wrap = 4; | 329 | spdif->playback_dma_data.wrap = 4; |
317 | spdif->playback_dma_data.width = 32; | 330 | spdif->playback_dma_data.width = 32; |
@@ -337,8 +350,6 @@ static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev) | |||
337 | goto err_unregister_dai; | 350 | goto err_unregister_dai; |
338 | } | 351 | } |
339 | 352 | ||
340 | tegra20_spdif_debug_add(spdif); | ||
341 | |||
342 | return 0; | 353 | return 0; |
343 | 354 | ||
344 | err_unregister_dai: | 355 | err_unregister_dai: |
@@ -365,8 +376,6 @@ static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev) | |||
365 | tegra_pcm_platform_unregister(&pdev->dev); | 376 | tegra_pcm_platform_unregister(&pdev->dev); |
366 | snd_soc_unregister_dai(&pdev->dev); | 377 | snd_soc_unregister_dai(&pdev->dev); |
367 | 378 | ||
368 | tegra20_spdif_debug_remove(spdif); | ||
369 | |||
370 | clk_put(spdif->clk_spdif_out); | 379 | clk_put(spdif->clk_spdif_out); |
371 | 380 | ||
372 | return 0; | 381 | return 0; |
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h index 823af4c6bb7c..ed756527efea 100644 --- a/sound/soc/tegra/tegra20_spdif.h +++ b/sound/soc/tegra/tegra20_spdif.h | |||
@@ -464,8 +464,7 @@ struct tegra20_spdif { | |||
464 | struct clk *clk_spdif_out; | 464 | struct clk *clk_spdif_out; |
465 | struct tegra_pcm_dma_params capture_dma_data; | 465 | struct tegra_pcm_dma_params capture_dma_data; |
466 | struct tegra_pcm_dma_params playback_dma_data; | 466 | struct tegra_pcm_dma_params playback_dma_data; |
467 | void __iomem *regs; | 467 | struct regmap *regmap; |
468 | struct dentry *debug; | ||
469 | u32 reg_ctrl; | 468 | u32 reg_ctrl; |
470 | }; | 469 | }; |
471 | 470 | ||