]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - sound/soc/tegra/tegra30_ahub.c
tegra: sound: export symbols for module access
[sojka/nv-tegra/linux-3.10.git] / sound / soc / tegra / tegra30_ahub.c
1 /*
2  * tegra30_ahub.c - Tegra30 AHUB driver
3  *
4  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/clk.h>
20 #include <linux/device.h>
21 #include <linux/io.h>
22 #include <linux/module.h>
23 #include <linux/of_platform.h>
24 #include <linux/platform_device.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/regmap.h>
27 #include <linux/slab.h>
28 #include <linux/clk/tegra.h>
29 #include <sound/soc.h>
30 #include "tegra30_ahub.h"
31
32 #define DRV_NAME "tegra30-ahub"
33
34 static struct tegra30_ahub *ahub;
35
36 static inline void tegra30_apbif_write(u32 reg, u32 val)
37 {
38         regmap_write(ahub->regmap_apbif, reg, val);
39 }
40
41 static inline u32 tegra30_apbif_read(u32 reg)
42 {
43         u32 val;
44         regmap_read(ahub->regmap_apbif, reg, &val);
45         return val;
46 }
47
48 static inline void tegra30_audio_write(u32 reg, u32 val)
49 {
50         regmap_write(ahub->regmap_ahub, reg, val);
51 }
52
53 static int tegra30_ahub_runtime_suspend(struct device *dev)
54 {
55         regcache_cache_only(ahub->regmap_apbif, true);
56         regcache_cache_only(ahub->regmap_ahub, true);
57
58         clk_disable_unprepare(ahub->clk_apbif);
59         clk_disable_unprepare(ahub->clk_d_audio);
60
61         return 0;
62 }
63
64 /*
65  * clk_apbif isn't required for an I2S<->I2S configuration where no PCM data
66  * is read from or sent to memory. However, that's not something the rest of
67  * the driver supports right now, so we'll just treat the two clocks as one
68  * for now.
69  *
70  * These functions should not be a plain ref-count. Instead, each active stream
71  * contributes some requirement to the minimum clock rate, so starting or
72  * stopping streams should dynamically adjust the clock as required.  However,
73  * this is not yet implemented.
74  */
75 static int tegra30_ahub_runtime_resume(struct device *dev)
76 {
77         int ret;
78
79         ret = clk_prepare_enable(ahub->clk_d_audio);
80         if (ret) {
81                 dev_err(dev, "clk_enable d_audio failed: %d\n", ret);
82                 return ret;
83         }
84         ret = clk_prepare_enable(ahub->clk_apbif);
85         if (ret) {
86                 dev_err(dev, "clk_enable apbif failed: %d\n", ret);
87                 clk_disable(ahub->clk_d_audio);
88                 return ret;
89         }
90
91         regcache_cache_only(ahub->regmap_apbif, false);
92         regcache_cache_only(ahub->regmap_ahub, false);
93
94         return 0;
95 }
96
97 /*
98  * for TDM mode, ahub has to run faster than I2S controller.  This will avoid
99  * FIFO overflow/underflow, the causes of slot-hopping symptoms
100  */
101 void tegra30_ahub_clock_set_rate(int rate)
102 {
103         clk_set_rate(ahub->clk_d_audio, rate);
104 }
105 EXPORT_SYMBOL_GPL(tegra30_ahub_clock_set_rate);
106
107 void tegra30_ahub_enable_clocks(void)
108 {
109         pm_runtime_get_sync(ahub->dev);
110 }
111 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_clocks);
112
113 void tegra30_ahub_disable_clocks(void)
114 {
115         pm_runtime_put(ahub->dev);
116 }
117 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_clocks);
118
119 static int tegra30_ahub_soft_reset_rx_channel(int channel)
120 {
121         u32 reg, val;
122
123         reg = TEGRA30_AHUB_CHANNEL_CLEAR +
124               (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
125         val = TEGRA30_AHUB_CHANNEL_CLEAR_RX_SOFT_RESET;
126         tegra30_apbif_write(reg, val);
127         return 0;
128 }
129
130 static int tegra30_ahub_soft_reset_tx_channel(int channel)
131 {
132         u32 reg, val;
133
134         reg = TEGRA30_AHUB_CHANNEL_CLEAR +
135               (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
136         val = TEGRA30_AHUB_CHANNEL_CLEAR_TX_SOFT_RESET;
137         tegra30_apbif_write(reg, val);
138         return 0;
139 }
140
141 int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
142                                   unsigned long *fiforeg,
143                                   unsigned long *reqsel)
144 {
145         int channel;
146         u32 reg, val;
147
148         channel = find_first_zero_bit(ahub->rx_usage,
149                                       TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
150         if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
151                 return -EBUSY;
152
153         __set_bit(channel, ahub->rx_usage);
154
155         *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel;
156         *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO +
157                    (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE);
158         *reqsel = ahub->dma_sel + channel;
159
160         tegra30_ahub_soft_reset_rx_channel(channel);
161
162         reg = TEGRA30_AHUB_CHANNEL_CTRL +
163               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
164         val = tegra30_apbif_read(reg);
165         val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK |
166                  TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK);
167         val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) |
168                TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN |
169                TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
170         tegra30_apbif_write(reg, val);
171
172         reg = TEGRA30_AHUB_CIF_RX_CTRL +
173               (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
174         val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
175               (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
176               (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
177               TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
178               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
179               TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
180         tegra30_apbif_write(reg, val);
181
182         return 0;
183 }
184 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_rx_fifo);
185
186 int tegra30_ahub_rx_fifo_is_enabled(int i2s_id)
187 {
188         int val, mask;
189
190         val = tegra30_apbif_read(TEGRA30_AHUB_I2S_LIVE_STATUS);
191         mask = (TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_ENABLED << (i2s_id*2));
192         val &= mask;
193         return val;
194 }
195 EXPORT_SYMBOL_GPL(tegra30_ahub_rx_fifo_is_enabled);
196
197 int tegra30_ahub_tx_fifo_is_enabled(int i2s_id)
198 {
199         int val, mask;
200
201         val = tegra30_apbif_read(TEGRA30_AHUB_I2S_LIVE_STATUS);
202         mask = (TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_ENABLED << (i2s_id*2));
203         val &= mask;
204
205         return val;
206 }
207 EXPORT_SYMBOL_GPL(tegra30_ahub_tx_fifo_is_enabled);
208
209
210 int tegra30_ahub_rx_fifo_is_empty(int i2s_id)
211 {
212         int val, mask;
213
214         val = tegra30_apbif_read(TEGRA30_AHUB_I2S_LIVE_STATUS);
215         mask = (TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_EMPTY << (i2s_id*2));
216         val &= mask;
217         return val;
218 }
219 EXPORT_SYMBOL(tegra30_ahub_rx_fifo_is_empty);
220
221 int tegra30_ahub_tx_fifo_is_empty(int i2s_id)
222 {
223         int val, mask;
224
225         val = tegra30_apbif_read(TEGRA30_AHUB_I2S_LIVE_STATUS);
226         mask = (TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_EMPTY << (i2s_id*2));
227         val &= mask;
228
229         return val;
230 }
231 EXPORT_SYMBOL(tegra30_ahub_tx_fifo_is_empty);
232
233
234 int tegra30_ahub_dam_ch0_is_enabled(int dam_id)
235 {
236         int val, mask;
237
238         val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
239                         (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
240         mask = TEGRA30_AHUB_DAM_LIVE_STATUS_RX0_ENABLED;
241         val &= mask;
242
243         return val;
244 }
245 EXPORT_SYMBOL_GPL(tegra30_ahub_dam_ch0_is_enabled);
246
247 int tegra30_ahub_dam_ch1_is_enabled(int dam_id)
248 {
249         int val, mask;
250
251         val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
252                         (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
253         mask = TEGRA30_AHUB_DAM_LIVE_STATUS_RX1_ENABLED;
254         val &= mask;
255
256         return val;
257 }
258 EXPORT_SYMBOL_GPL(tegra30_ahub_dam_ch1_is_enabled);
259
260 int tegra30_ahub_dam_tx_is_enabled(int dam_id)
261 {
262         int val, mask;
263
264         val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
265                         (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
266         mask = TEGRA30_AHUB_DAM_LIVE_STATUS_TX_ENABLED;
267         val &= mask;
268
269         return val;
270 }
271 EXPORT_SYMBOL_GPL(tegra30_ahub_dam_tx_is_enabled);
272
273
274 int tegra30_ahub_dam_ch0_is_empty(int dam_id)
275 {
276         int val, mask;
277
278         val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
279                         (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
280         mask = TEGRA30_AHUB_DAM_LIVE_STATUS_RX0FIFO_EMPTY;
281         val &= mask;
282
283         return val;
284 }
285 EXPORT_SYMBOL(tegra30_ahub_dam_ch0_is_empty);
286
287 int tegra30_ahub_dam_ch1_is_empty(int dam_id)
288 {
289         int val, mask;
290
291         val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
292                         (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
293         mask = TEGRA30_AHUB_DAM_LIVE_STATUS_RX1FIFO_EMPTY;
294         val &= mask;
295
296         return val;
297 }
298 EXPORT_SYMBOL(tegra30_ahub_dam_ch1_is_empty);
299
300 int tegra30_ahub_dam_tx_is_empty(int dam_id)
301 {
302         int val, mask;
303
304         val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
305                         (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
306         mask = TEGRA30_AHUB_DAM_LIVE_STATUS_TXFIFO_EMPTY;
307         val &= mask;
308
309         return val;
310 }
311 EXPORT_SYMBOL(tegra30_ahub_dam_tx_is_empty);
312
313
314 int tegra30_ahub_set_rx_fifo_pack_mode(enum tegra30_ahub_rxcif rxcif,
315                                                         unsigned int pack_mode)
316 {
317         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
318         int reg, val;
319
320         reg = TEGRA30_AHUB_CHANNEL_CTRL +
321               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
322         val = tegra30_apbif_read(reg);
323
324         val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK;
325         val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN;
326
327         if ((pack_mode == TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16) ||
328                 (pack_mode == TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_8_4))
329                 val |= (TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN |
330                                                 pack_mode);
331         tegra30_apbif_write(reg, val);
332
333         return 0;
334 }
335 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_fifo_pack_mode);
336
337 int tegra30_ahub_set_tx_fifo_pack_mode(enum tegra30_ahub_txcif txcif,
338                                                         unsigned int pack_mode)
339 {
340         int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
341         int reg, val;
342
343         reg = TEGRA30_AHUB_CHANNEL_CTRL +
344               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
345         val = tegra30_apbif_read(reg);
346
347         val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK;
348         val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN;
349
350         if ((pack_mode == TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16) ||
351                 (pack_mode == TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_8_4))
352                 val |= (TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN |
353                                                 pack_mode);
354         tegra30_apbif_write(reg, val);
355
356         return 0;
357 }
358 EXPORT_SYMBOL_GPL(tegra30_ahub_set_tx_fifo_pack_mode);
359
360 int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
361 {
362         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
363         int reg, val;
364
365         reg = TEGRA30_AHUB_CHANNEL_CTRL +
366               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
367         val = tegra30_apbif_read(reg);
368         val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
369         tegra30_apbif_write(reg, val);
370
371         return 0;
372 }
373 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_rx_fifo);
374
375 int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
376 {
377         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
378         int reg, val;
379
380         reg = TEGRA30_AHUB_CHANNEL_CTRL +
381               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
382         val = tegra30_apbif_read(reg);
383         val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
384         tegra30_apbif_write(reg, val);
385
386         return 0;
387 }
388 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_rx_fifo);
389
390 int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
391 {
392         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
393
394         __clear_bit(channel, ahub->rx_usage);
395
396         return 0;
397 }
398 EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo);
399
400 int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
401                                   unsigned long *fiforeg,
402                                   unsigned long *reqsel)
403 {
404         int channel;
405         u32 reg, val;
406
407         channel = find_first_zero_bit(ahub->tx_usage,
408                                       TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
409         if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
410                 return -EBUSY;
411
412         __set_bit(channel, ahub->tx_usage);
413
414         *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel;
415         *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO +
416                    (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE);
417         *reqsel = ahub->dma_sel + channel;
418
419         tegra30_ahub_soft_reset_tx_channel(channel);
420
421         reg = TEGRA30_AHUB_CHANNEL_CTRL +
422               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
423         val = tegra30_apbif_read(reg);
424         val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK |
425                  TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK);
426         val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) |
427                TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN |
428                TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
429         tegra30_apbif_write(reg, val);
430
431         reg = TEGRA30_AHUB_CIF_TX_CTRL +
432               (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
433         val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
434               (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
435               (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
436               TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
437               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
438               TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
439         tegra30_apbif_write(reg, val);
440
441         return 0;
442 }
443 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_tx_fifo);
444
445 int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif)
446 {
447         int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
448         int reg, val;
449
450         reg = TEGRA30_AHUB_CHANNEL_CTRL +
451               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
452         val = tegra30_apbif_read(reg);
453         val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
454         tegra30_apbif_write(reg, val);
455
456         return 0;
457 }
458 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_tx_fifo);
459
460 int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif)
461 {
462         int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
463         int reg, val;
464
465         reg = TEGRA30_AHUB_CHANNEL_CTRL +
466               (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
467         val = tegra30_apbif_read(reg);
468         val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
469         tegra30_apbif_write(reg, val);
470
471         return 0;
472 }
473 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_tx_fifo);
474
475 int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif)
476 {
477         int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
478
479         __clear_bit(channel, ahub->tx_usage);
480
481         return 0;
482 }
483 EXPORT_SYMBOL_GPL(tegra30_ahub_free_tx_fifo);
484
485 int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
486                                    enum tegra30_ahub_txcif txcif)
487 {
488         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
489         int reg;
490
491         reg = TEGRA30_AHUB_AUDIO_RX +
492               (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
493         tegra30_audio_write(reg, 1 << txcif);
494
495         return 0;
496 }
497 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_source);
498
499 int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
500 {
501         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
502         int reg;
503
504         reg = TEGRA30_AHUB_AUDIO_RX +
505               (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
506         tegra30_audio_write(reg, 0);
507
508         return 0;
509 }
510 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
511
512 int tegra30_ahub_set_rx_cif_channels(enum tegra30_ahub_rxcif rxcif,
513                                      unsigned int audio_ch,
514                                      unsigned int client_ch)
515 {
516         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
517         unsigned int reg, val;
518
519         reg = TEGRA30_AHUB_CIF_RX_CTRL +
520               (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
521         val = tegra30_apbif_read(reg);
522         val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
523                 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
524         val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
525               ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
526         tegra30_apbif_write(reg, val);
527
528         return 0;
529 }
530 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_channels);
531
532 int tegra30_ahub_set_rx_cif_stereo_conv(enum tegra30_ahub_rxcif rxcif)
533 {
534         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
535         unsigned int reg, val;
536
537         tegra30_ahub_enable_clocks();
538
539         reg = TEGRA30_AHUB_CIF_RX_CTRL +
540               (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
541         val = tegra30_apbif_read(reg);
542         val &= ~TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK;
543         val |= TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG;
544         tegra30_apbif_write(reg, val);
545
546         tegra30_ahub_disable_clocks();
547
548         return 0;
549 }
550
551 int tegra30_ahub_set_tx_cif_channels(enum tegra30_ahub_txcif txcif,
552                                      unsigned int audio_ch,
553                                      unsigned int client_ch)
554 {
555         int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
556         unsigned int reg, val;
557
558         reg = TEGRA30_AHUB_CIF_TX_CTRL +
559               (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
560         val = tegra30_apbif_read(reg);
561         val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
562                 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
563         val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
564               ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
565
566         tegra30_apbif_write(reg, val);
567
568         return 0;
569 }
570 EXPORT_SYMBOL_GPL(tegra30_ahub_set_tx_cif_channels);
571
572 int tegra30_ahub_set_rx_cif_bits(enum tegra30_ahub_rxcif rxcif,
573                                      unsigned int audio_bits,
574                                      unsigned int client_bits)
575 {
576         int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
577         unsigned int reg, val;
578
579         reg = TEGRA30_AHUB_CIF_RX_CTRL +
580               (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
581         val = tegra30_apbif_read(reg);
582         val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
583                 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
584         val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
585               ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
586         tegra30_apbif_write(reg, val);
587
588         return 0;
589 }
590 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_bits);
591
592 int tegra30_ahub_set_tx_cif_bits(enum tegra30_ahub_txcif txcif,
593                                      unsigned int audio_bits,
594                                      unsigned int client_bits)
595 {
596         int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
597         unsigned int reg, val;
598
599         reg = TEGRA30_AHUB_CIF_TX_CTRL +
600               (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
601         val = tegra30_apbif_read(reg);
602         val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
603                 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
604         val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
605               ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
606
607         tegra30_apbif_write(reg, val);
608
609         return 0;
610 }
611 EXPORT_SYMBOL_GPL(tegra30_ahub_set_tx_cif_bits);
612
613 static const char * const configlink_clocks[] = {
614         "i2s0",
615         "i2s1",
616         "i2s2",
617         "i2s3",
618         "i2s4",
619         "dam0",
620         "dam1",
621         "dam2",
622 /*No SPDIF in 14x*/
623 #ifndef CONFIG_ARCH_TEGRA_14x_SOC
624         "spdif_in",
625 #endif
626 #if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_12x_SOC)
627         "amx",
628         "adx",
629 #endif
630 #ifdef CONFIG_ARCH_TEGRA_12x_SOC
631         "amx1",
632         "adx1",
633         "afc0",
634         "afc1",
635         "afc2",
636         "afc3",
637         "afc4",
638         "afc5",
639 #endif
640 };
641
642 struct of_dev_auxdata ahub_auxdata[] = {
643         OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL),
644         OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL),
645         OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL),
646         OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080600, "tegra30-i2s.3", NULL),
647         OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080700, "tegra30-i2s.4", NULL),
648         OF_DEV_AUXDATA("nvidia,tegra30-dam", 0x70080800, "tegra30-dam.0", NULL),
649         OF_DEV_AUXDATA("nvidia,tegra30-dam", 0x70080900, "tegra30-dam.1", NULL),
650         OF_DEV_AUXDATA("nvidia,tegra30-dam", 0x70080A00, "tegra30-dam.2", NULL),
651         OF_DEV_AUXDATA("nvidia,tegra30-spdif", 0x70080B00, "tegra30-spdif",
652                 NULL),
653         {}
654 };
655
656 #define LAST_REG(name) \
657         (TEGRA30_AHUB_##name + \
658          (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4)
659
660 #define REG_IN_ARRAY(reg, name) \
661         ((reg >= TEGRA30_AHUB_##name) && \
662          (reg <= LAST_REG(name) && \
663          (!((reg - TEGRA30_AHUB_##name) % TEGRA30_AHUB_##name##_STRIDE))))
664
665 static bool tegra30_ahub_apbif_wr_rd_reg(struct device *dev, unsigned int reg)
666 {
667         switch (reg) {
668         case TEGRA30_AHUB_CONFIG_LINK_CTRL:
669         case TEGRA30_AHUB_MISC_CTRL:
670         case TEGRA30_AHUB_APBDMA_LIVE_STATUS:
671         case TEGRA30_AHUB_I2S_LIVE_STATUS:
672         case TEGRA30_AHUB_SPDIF_LIVE_STATUS:
673         case TEGRA30_AHUB_I2S_INT_MASK:
674         case TEGRA30_AHUB_DAM_INT_MASK:
675         case TEGRA30_AHUB_SPDIF_INT_MASK:
676         case TEGRA30_AHUB_APBIF_INT_MASK:
677         case TEGRA30_AHUB_I2S_INT_STATUS:
678         case TEGRA30_AHUB_DAM_INT_STATUS:
679         case TEGRA30_AHUB_SPDIF_INT_STATUS:
680         case TEGRA30_AHUB_APBIF_INT_STATUS:
681         case TEGRA30_AHUB_I2S_INT_SOURCE:
682         case TEGRA30_AHUB_DAM_INT_SOURCE:
683         case TEGRA30_AHUB_SPDIF_INT_SOURCE:
684         case TEGRA30_AHUB_APBIF_INT_SOURCE:
685         case TEGRA30_AHUB_I2S_INT_SET:
686         case TEGRA30_AHUB_DAM_INT_SET:
687         case TEGRA30_AHUB_SPDIF_INT_SET:
688         case TEGRA30_AHUB_APBIF_INT_SET:
689                 return true;
690         default:
691                 break;
692         };
693
694         if (REG_IN_ARRAY(reg, CHANNEL_CTRL) ||
695             REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
696             REG_IN_ARRAY(reg, CHANNEL_STATUS) ||
697             REG_IN_ARRAY(reg, CHANNEL_TXFIFO) ||
698             REG_IN_ARRAY(reg, CHANNEL_RXFIFO) ||
699             REG_IN_ARRAY(reg, CIF_TX_CTRL) ||
700             REG_IN_ARRAY(reg, CIF_RX_CTRL) ||
701             REG_IN_ARRAY(reg, DAM_LIVE_STATUS))
702                 return true;
703
704         return false;
705 }
706
707 static bool tegra30_ahub_apbif_volatile_reg(struct device *dev,
708                                             unsigned int reg)
709 {
710         switch (reg) {
711         case TEGRA30_AHUB_CONFIG_LINK_CTRL:
712         case TEGRA30_AHUB_MISC_CTRL:
713         case TEGRA30_AHUB_APBDMA_LIVE_STATUS:
714         case TEGRA30_AHUB_I2S_LIVE_STATUS:
715         case TEGRA30_AHUB_SPDIF_LIVE_STATUS:
716         case TEGRA30_AHUB_I2S_INT_STATUS:
717         case TEGRA30_AHUB_DAM_INT_STATUS:
718         case TEGRA30_AHUB_SPDIF_INT_STATUS:
719         case TEGRA30_AHUB_APBIF_INT_STATUS:
720         case TEGRA30_AHUB_I2S_INT_SET:
721         case TEGRA30_AHUB_DAM_INT_SET:
722         case TEGRA30_AHUB_SPDIF_INT_SET:
723         case TEGRA30_AHUB_APBIF_INT_SET:
724                 return true;
725         default:
726                 break;
727         };
728
729         if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
730             REG_IN_ARRAY(reg, CHANNEL_STATUS) ||
731             REG_IN_ARRAY(reg, CHANNEL_TXFIFO) ||
732             REG_IN_ARRAY(reg, CHANNEL_RXFIFO) ||
733             REG_IN_ARRAY(reg, DAM_LIVE_STATUS))
734                 return true;
735
736         return false;
737 }
738
739 static bool tegra30_ahub_apbif_precious_reg(struct device *dev,
740                                             unsigned int reg)
741 {
742         if (REG_IN_ARRAY(reg, CHANNEL_TXFIFO) ||
743             REG_IN_ARRAY(reg, CHANNEL_RXFIFO))
744                 return true;
745
746         return false;
747 }
748
749 static const struct regmap_config tegra30_ahub_apbif_regmap_config = {
750         .name = "apbif",
751         .reg_bits = 32,
752         .val_bits = 32,
753         .reg_stride = 4,
754         .max_register = TEGRA30_AHUB_APBIF_INT_SET,
755         .writeable_reg = tegra30_ahub_apbif_wr_rd_reg,
756         .readable_reg = tegra30_ahub_apbif_wr_rd_reg,
757         .volatile_reg = tegra30_ahub_apbif_volatile_reg,
758         .precious_reg = tegra30_ahub_apbif_precious_reg,
759         .cache_type = REGCACHE_RBTREE,
760 };
761
762 static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg)
763 {
764         if (REG_IN_ARRAY(reg, AUDIO_RX))
765                 return true;
766
767         return false;
768 }
769
770 static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
771         .name = "ahub",
772         .reg_bits = 32,
773         .val_bits = 32,
774         .reg_stride = 4,
775         .max_register = LAST_REG(AUDIO_RX),
776         .writeable_reg = tegra30_ahub_ahub_wr_rd_reg,
777         .readable_reg = tegra30_ahub_ahub_wr_rd_reg,
778         .cache_type = REGCACHE_RBTREE,
779 };
780
781 static int tegra30_ahub_probe(struct platform_device *pdev)
782 {
783         struct clk *clk;
784         int i;
785         struct resource *res0, *res1, *region;
786         u32 of_dma[2];
787         void __iomem *regs_apbif, *regs_ahub;
788         int ret = 0;
789
790         if (ahub)
791                 return -ENODEV;
792
793         /*
794          * The AHUB hosts a register bus: the "configlink". For this to
795          * operate correctly, all devices on this bus must be out of reset.
796          * Ensure that here.
797          */
798         for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
799                 clk = clk_get_sys(NULL, configlink_clocks[i]);
800                 if (IS_ERR(clk)) {
801                         dev_err(&pdev->dev, "Can't get clock %s\n",
802                                 configlink_clocks[i]);
803                         ret = PTR_ERR(clk);
804                         goto err;
805                 }
806                 tegra_periph_reset_deassert(clk);
807                 clk_put(clk);
808         }
809
810         ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
811                             GFP_KERNEL);
812         if (!ahub) {
813                 dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n");
814                 ret = -ENOMEM;
815                 goto err;
816         }
817         dev_set_drvdata(&pdev->dev, ahub);
818
819         ahub->dev = &pdev->dev;
820
821         ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
822         if (IS_ERR(ahub->clk_d_audio)) {
823                 dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
824                 ret = PTR_ERR(ahub->clk_d_audio);
825                 goto err;
826         }
827
828         ahub->clk_apbif = clk_get(&pdev->dev, "apbif");
829         if (IS_ERR(ahub->clk_apbif)) {
830                 dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
831                 ret = PTR_ERR(ahub->clk_apbif);
832                 goto err_clk_put_d_audio;
833         }
834
835         if (!(pdev->dev.of_node))
836                 ahub->dma_sel = 1;
837         else {
838                 if (of_property_read_u32_array(pdev->dev.of_node,
839                                         "nvidia,dma-request-selector",
840                                         of_dma, 2) < 0) {
841                         dev_err(&pdev->dev,
842                                 "Missing property nvidia,dma-request-selector\n");
843                         ret = -ENODEV;
844                         goto err_clk_put_d_audio;
845                 }
846                 ahub->dma_sel = of_dma[1];
847         }
848
849         res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
850         if (!res0) {
851                 dev_err(&pdev->dev, "No apbif memory resource\n");
852                 ret = -ENODEV;
853                 goto err_clk_put_apbif;
854         }
855
856         region = devm_request_mem_region(&pdev->dev, res0->start,
857                                          resource_size(res0), DRV_NAME);
858         if (!region) {
859                 dev_err(&pdev->dev, "request region apbif failed\n");
860                 ret = -EBUSY;
861                 goto err_clk_put_apbif;
862         }
863         ahub->apbif_addr = res0->start;
864
865         regs_apbif = devm_ioremap(&pdev->dev, res0->start,
866                                   resource_size(res0));
867         if (!regs_apbif) {
868                 dev_err(&pdev->dev, "ioremap apbif failed\n");
869                 ret = -ENOMEM;
870                 goto err_clk_put_apbif;
871         }
872
873         ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif,
874                                         &tegra30_ahub_apbif_regmap_config);
875         if (IS_ERR(ahub->regmap_apbif)) {
876                 dev_err(&pdev->dev, "apbif regmap init failed\n");
877                 ret = PTR_ERR(ahub->regmap_apbif);
878                 goto err_clk_put_apbif;
879         }
880         regcache_cache_only(ahub->regmap_apbif, true);
881
882         res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
883         if (!res1) {
884                 dev_err(&pdev->dev, "No ahub memory resource\n");
885                 ret = -ENODEV;
886                 goto err_clk_put_apbif;
887         }
888
889         region = devm_request_mem_region(&pdev->dev, res1->start,
890                                          resource_size(res1), DRV_NAME);
891         if (!region) {
892                 dev_err(&pdev->dev, "request region ahub failed\n");
893                 ret = -EBUSY;
894                 goto err_clk_put_apbif;
895         }
896
897         regs_ahub = devm_ioremap(&pdev->dev, res1->start,
898                                  resource_size(res1));
899         if (!regs_ahub) {
900                 dev_err(&pdev->dev, "ioremap ahub failed\n");
901                 ret = -ENOMEM;
902                 goto err_clk_put_apbif;
903         }
904
905         ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub,
906                                         &tegra30_ahub_ahub_regmap_config);
907         if (IS_ERR(ahub->regmap_ahub)) {
908                 dev_err(&pdev->dev, "ahub regmap init failed\n");
909                 ret = PTR_ERR(ahub->regmap_ahub);
910                 goto err_clk_put_apbif;
911         }
912         regcache_cache_only(ahub->regmap_ahub, true);
913
914         pm_runtime_enable(&pdev->dev);
915         if (!pm_runtime_enabled(&pdev->dev)) {
916                 ret = tegra30_ahub_runtime_resume(&pdev->dev);
917                 if (ret)
918                         goto err_pm_disable;
919         }
920
921         if (pdev->dev.of_node)
922                 of_platform_populate(pdev->dev.of_node, NULL, ahub_auxdata,
923                                      &pdev->dev);
924
925         return 0;
926
927 err_pm_disable:
928         pm_runtime_disable(&pdev->dev);
929 err_clk_put_apbif:
930         clk_put(ahub->clk_apbif);
931 err_clk_put_d_audio:
932         clk_put(ahub->clk_d_audio);
933         ahub = 0;
934 err:
935         return ret;
936 }
937
938 static int tegra30_ahub_remove(struct platform_device *pdev)
939 {
940         if (!ahub)
941                 return -ENODEV;
942
943         pm_runtime_disable(&pdev->dev);
944         if (!pm_runtime_status_suspended(&pdev->dev))
945                 tegra30_ahub_runtime_suspend(&pdev->dev);
946
947         clk_put(ahub->clk_apbif);
948         clk_put(ahub->clk_d_audio);
949
950         ahub = 0;
951
952         return 0;
953 }
954
955 static const struct of_device_id tegra30_ahub_of_match[] = {
956         { .compatible = "nvidia,tegra30-ahub", },
957         {},
958 };
959
960 static const struct dev_pm_ops tegra30_ahub_pm_ops = {
961         SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
962                            tegra30_ahub_runtime_resume, NULL)
963 };
964
965 static struct platform_driver tegra30_ahub_driver = {
966         .probe = tegra30_ahub_probe,
967         .remove = tegra30_ahub_remove,
968         .driver = {
969                 .name = DRV_NAME,
970                 .owner = THIS_MODULE,
971                 .of_match_table = tegra30_ahub_of_match,
972                 .pm = &tegra30_ahub_pm_ops,
973         },
974 };
975 module_platform_driver(tegra30_ahub_driver);
976
977 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
978 MODULE_DESCRIPTION("Tegra30 AHUB driver");
979 MODULE_LICENSE("GPL v2");
980 MODULE_ALIAS("platform:" DRV_NAME);
981 MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match);