1f74028e1SSameer Pujar // SPDX-License-Identifier: GPL-2.0-only
24a91fe4cSSheetal // SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES.
34204ecccSRitu Chaudhary // All rights reserved.
4f74028e1SSameer Pujar //
5f74028e1SSameer Pujar // tegra210_admaif.c - Tegra ADMAIF driver
6f74028e1SSameer Pujar
7f74028e1SSameer Pujar #include <linux/clk.h>
8f74028e1SSameer Pujar #include <linux/device.h>
9f74028e1SSameer Pujar #include <linux/module.h>
10f74028e1SSameer Pujar #include <linux/of_platform.h>
11f74028e1SSameer Pujar #include <linux/platform_device.h>
12f74028e1SSameer Pujar #include <linux/pm_runtime.h>
13f74028e1SSameer Pujar #include <linux/regmap.h>
14f74028e1SSameer Pujar #include <sound/pcm_params.h>
15f74028e1SSameer Pujar #include <sound/soc.h>
164a91fe4cSSheetal #include "tegra_isomgr_bw.h"
17f74028e1SSameer Pujar #include "tegra210_admaif.h"
18f74028e1SSameer Pujar #include "tegra_cif.h"
19f74028e1SSameer Pujar #include "tegra_pcm.h"
20f74028e1SSameer Pujar
21f74028e1SSameer Pujar #define CH_REG(offset, reg, id) \
22f74028e1SSameer Pujar ((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id)))
23f74028e1SSameer Pujar
24f74028e1SSameer Pujar #define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id)
25f74028e1SSameer Pujar
26f74028e1SSameer Pujar #define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
27f74028e1SSameer Pujar
28*7668c637SSheetal #define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base, cif_ctrl) \
29f74028e1SSameer Pujar { CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 }, \
30*7668c637SSheetal { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), cif_ctrl }, \
31f74028e1SSameer Pujar { CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl }, \
32f74028e1SSameer Pujar { CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 }, \
33*7668c637SSheetal { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), cif_ctrl }, \
34f74028e1SSameer Pujar { CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
35f74028e1SSameer Pujar
36f74028e1SSameer Pujar #define ADMAIF_REG_DEFAULTS(id, chip) \
37f74028e1SSameer Pujar REG_DEFAULTS((id) - 1, \
38f74028e1SSameer Pujar chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT, \
39f74028e1SSameer Pujar chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT, \
40f74028e1SSameer Pujar chip ## _ADMAIF_TX_BASE, \
41*7668c637SSheetal chip ## _ADMAIF_RX_BASE, \
42*7668c637SSheetal chip ## _ADMAIF_CIF_REG_DEFAULT)
43f74028e1SSameer Pujar
44f74028e1SSameer Pujar static const struct reg_default tegra186_admaif_reg_defaults[] = {
45f74028e1SSameer Pujar {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
46f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(1, TEGRA186),
47f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(2, TEGRA186),
48f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(3, TEGRA186),
49f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(4, TEGRA186),
50f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(5, TEGRA186),
51f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(6, TEGRA186),
52f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(7, TEGRA186),
53f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(8, TEGRA186),
54f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(9, TEGRA186),
55f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(10, TEGRA186),
56f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(11, TEGRA186),
57f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(12, TEGRA186),
58f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(13, TEGRA186),
59f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(14, TEGRA186),
60f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(15, TEGRA186),
61f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(16, TEGRA186),
62f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(17, TEGRA186),
63f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(18, TEGRA186),
64f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(19, TEGRA186),
65f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(20, TEGRA186)
66f74028e1SSameer Pujar };
67f74028e1SSameer Pujar
68f74028e1SSameer Pujar static const struct reg_default tegra210_admaif_reg_defaults[] = {
69f74028e1SSameer Pujar {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003},
70f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(1, TEGRA210),
71f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(2, TEGRA210),
72f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(3, TEGRA210),
73f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(4, TEGRA210),
74f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(5, TEGRA210),
75f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(6, TEGRA210),
76f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(7, TEGRA210),
77f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(8, TEGRA210),
78f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(9, TEGRA210),
79f74028e1SSameer Pujar ADMAIF_REG_DEFAULTS(10, TEGRA210)
80f74028e1SSameer Pujar };
81f74028e1SSameer Pujar
82*7668c637SSheetal static const struct reg_default tegra264_admaif_reg_defaults[] = {
83*7668c637SSheetal {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA264_ADMAIF_GLOBAL_BASE), 0x00000003},
84*7668c637SSheetal ADMAIF_REG_DEFAULTS(1, TEGRA264),
85*7668c637SSheetal ADMAIF_REG_DEFAULTS(2, TEGRA264),
86*7668c637SSheetal ADMAIF_REG_DEFAULTS(3, TEGRA264),
87*7668c637SSheetal ADMAIF_REG_DEFAULTS(4, TEGRA264),
88*7668c637SSheetal ADMAIF_REG_DEFAULTS(5, TEGRA264),
89*7668c637SSheetal ADMAIF_REG_DEFAULTS(6, TEGRA264),
90*7668c637SSheetal ADMAIF_REG_DEFAULTS(7, TEGRA264),
91*7668c637SSheetal ADMAIF_REG_DEFAULTS(8, TEGRA264),
92*7668c637SSheetal ADMAIF_REG_DEFAULTS(9, TEGRA264),
93*7668c637SSheetal ADMAIF_REG_DEFAULTS(10, TEGRA264),
94*7668c637SSheetal ADMAIF_REG_DEFAULTS(11, TEGRA264),
95*7668c637SSheetal ADMAIF_REG_DEFAULTS(12, TEGRA264),
96*7668c637SSheetal ADMAIF_REG_DEFAULTS(13, TEGRA264),
97*7668c637SSheetal ADMAIF_REG_DEFAULTS(14, TEGRA264),
98*7668c637SSheetal ADMAIF_REG_DEFAULTS(15, TEGRA264),
99*7668c637SSheetal ADMAIF_REG_DEFAULTS(16, TEGRA264),
100*7668c637SSheetal ADMAIF_REG_DEFAULTS(17, TEGRA264),
101*7668c637SSheetal ADMAIF_REG_DEFAULTS(18, TEGRA264),
102*7668c637SSheetal ADMAIF_REG_DEFAULTS(19, TEGRA264),
103*7668c637SSheetal ADMAIF_REG_DEFAULTS(20, TEGRA264),
104*7668c637SSheetal ADMAIF_REG_DEFAULTS(21, TEGRA264),
105*7668c637SSheetal ADMAIF_REG_DEFAULTS(22, TEGRA264),
106*7668c637SSheetal ADMAIF_REG_DEFAULTS(23, TEGRA264),
107*7668c637SSheetal ADMAIF_REG_DEFAULTS(24, TEGRA264),
108*7668c637SSheetal ADMAIF_REG_DEFAULTS(25, TEGRA264),
109*7668c637SSheetal ADMAIF_REG_DEFAULTS(26, TEGRA264),
110*7668c637SSheetal ADMAIF_REG_DEFAULTS(27, TEGRA264),
111*7668c637SSheetal ADMAIF_REG_DEFAULTS(28, TEGRA264),
112*7668c637SSheetal ADMAIF_REG_DEFAULTS(29, TEGRA264),
113*7668c637SSheetal ADMAIF_REG_DEFAULTS(30, TEGRA264),
114*7668c637SSheetal ADMAIF_REG_DEFAULTS(31, TEGRA264),
115*7668c637SSheetal ADMAIF_REG_DEFAULTS(32, TEGRA264)
116*7668c637SSheetal };
117*7668c637SSheetal
tegra_admaif_wr_reg(struct device * dev,unsigned int reg)118f74028e1SSameer Pujar static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
119f74028e1SSameer Pujar {
120f74028e1SSameer Pujar struct tegra_admaif *admaif = dev_get_drvdata(dev);
121f74028e1SSameer Pujar unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
122f74028e1SSameer Pujar unsigned int num_ch = admaif->soc_data->num_ch;
123f74028e1SSameer Pujar unsigned int rx_base = admaif->soc_data->rx_base;
124f74028e1SSameer Pujar unsigned int tx_base = admaif->soc_data->tx_base;
125f74028e1SSameer Pujar unsigned int global_base = admaif->soc_data->global_base;
126f74028e1SSameer Pujar unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
127f74028e1SSameer Pujar unsigned int rx_max = rx_base + (num_ch * ch_stride);
128f74028e1SSameer Pujar unsigned int tx_max = tx_base + (num_ch * ch_stride);
129f74028e1SSameer Pujar
130f74028e1SSameer Pujar if ((reg >= rx_base) && (reg < rx_max)) {
131f74028e1SSameer Pujar reg = (reg - rx_base) % ch_stride;
132f74028e1SSameer Pujar if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
133f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
134f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
135f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
136f74028e1SSameer Pujar return true;
137f74028e1SSameer Pujar } else if ((reg >= tx_base) && (reg < tx_max)) {
138f74028e1SSameer Pujar reg = (reg - tx_base) % ch_stride;
139f74028e1SSameer Pujar if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
140f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
141f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
142f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
143f74028e1SSameer Pujar return true;
144f74028e1SSameer Pujar } else if ((reg >= global_base) && (reg < reg_max)) {
145f74028e1SSameer Pujar if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE))
146f74028e1SSameer Pujar return true;
147f74028e1SSameer Pujar }
148f74028e1SSameer Pujar
149f74028e1SSameer Pujar return false;
150f74028e1SSameer Pujar }
151f74028e1SSameer Pujar
tegra_admaif_rd_reg(struct device * dev,unsigned int reg)152f74028e1SSameer Pujar static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg)
153f74028e1SSameer Pujar {
154f74028e1SSameer Pujar struct tegra_admaif *admaif = dev_get_drvdata(dev);
155f74028e1SSameer Pujar unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
156f74028e1SSameer Pujar unsigned int num_ch = admaif->soc_data->num_ch;
157f74028e1SSameer Pujar unsigned int rx_base = admaif->soc_data->rx_base;
158f74028e1SSameer Pujar unsigned int tx_base = admaif->soc_data->tx_base;
159f74028e1SSameer Pujar unsigned int global_base = admaif->soc_data->global_base;
160f74028e1SSameer Pujar unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
161f74028e1SSameer Pujar unsigned int rx_max = rx_base + (num_ch * ch_stride);
162f74028e1SSameer Pujar unsigned int tx_max = tx_base + (num_ch * ch_stride);
163f74028e1SSameer Pujar
164f74028e1SSameer Pujar if ((reg >= rx_base) && (reg < rx_max)) {
165f74028e1SSameer Pujar reg = (reg - rx_base) % ch_stride;
166f74028e1SSameer Pujar if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
167f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_STATUS) ||
168f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
169f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
170f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
171f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
172f74028e1SSameer Pujar return true;
173f74028e1SSameer Pujar } else if ((reg >= tx_base) && (reg < tx_max)) {
174f74028e1SSameer Pujar reg = (reg - tx_base) % ch_stride;
175f74028e1SSameer Pujar if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
176f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_STATUS) ||
177f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
178f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
179f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
180f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
181f74028e1SSameer Pujar return true;
182f74028e1SSameer Pujar } else if ((reg >= global_base) && (reg < reg_max)) {
183f74028e1SSameer Pujar if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) ||
184f74028e1SSameer Pujar (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) ||
185f74028e1SSameer Pujar (reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
186f74028e1SSameer Pujar (reg == (global_base +
187f74028e1SSameer Pujar TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
188f74028e1SSameer Pujar (reg == (global_base +
189f74028e1SSameer Pujar TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
190f74028e1SSameer Pujar return true;
191f74028e1SSameer Pujar }
192f74028e1SSameer Pujar
193f74028e1SSameer Pujar return false;
194f74028e1SSameer Pujar }
195f74028e1SSameer Pujar
tegra_admaif_volatile_reg(struct device * dev,unsigned int reg)196f74028e1SSameer Pujar static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg)
197f74028e1SSameer Pujar {
198f74028e1SSameer Pujar struct tegra_admaif *admaif = dev_get_drvdata(dev);
199f74028e1SSameer Pujar unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
200f74028e1SSameer Pujar unsigned int num_ch = admaif->soc_data->num_ch;
201f74028e1SSameer Pujar unsigned int rx_base = admaif->soc_data->rx_base;
202f74028e1SSameer Pujar unsigned int tx_base = admaif->soc_data->tx_base;
203f74028e1SSameer Pujar unsigned int global_base = admaif->soc_data->global_base;
204f74028e1SSameer Pujar unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
205f74028e1SSameer Pujar unsigned int rx_max = rx_base + (num_ch * ch_stride);
206f74028e1SSameer Pujar unsigned int tx_max = tx_base + (num_ch * ch_stride);
207f74028e1SSameer Pujar
208f74028e1SSameer Pujar if ((reg >= rx_base) && (reg < rx_max)) {
209f74028e1SSameer Pujar reg = (reg - rx_base) % ch_stride;
210f74028e1SSameer Pujar if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
211f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_STATUS) ||
212f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
213f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_RX_SOFT_RESET))
214f74028e1SSameer Pujar return true;
215f74028e1SSameer Pujar } else if ((reg >= tx_base) && (reg < tx_max)) {
216f74028e1SSameer Pujar reg = (reg - tx_base) % ch_stride;
217f74028e1SSameer Pujar if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
218f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_STATUS) ||
219f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
220f74028e1SSameer Pujar (reg == TEGRA_ADMAIF_TX_SOFT_RESET))
221f74028e1SSameer Pujar return true;
222f74028e1SSameer Pujar } else if ((reg >= global_base) && (reg < reg_max)) {
223f74028e1SSameer Pujar if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
224f74028e1SSameer Pujar (reg == (global_base +
225f74028e1SSameer Pujar TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
226f74028e1SSameer Pujar (reg == (global_base +
227f74028e1SSameer Pujar TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
228f74028e1SSameer Pujar return true;
229f74028e1SSameer Pujar }
230f74028e1SSameer Pujar
231f74028e1SSameer Pujar return false;
232f74028e1SSameer Pujar }
233f74028e1SSameer Pujar
234f74028e1SSameer Pujar static const struct regmap_config tegra210_admaif_regmap_config = {
235f74028e1SSameer Pujar .reg_bits = 32,
236f74028e1SSameer Pujar .reg_stride = 4,
237f74028e1SSameer Pujar .val_bits = 32,
238f74028e1SSameer Pujar .max_register = TEGRA210_ADMAIF_LAST_REG,
239f74028e1SSameer Pujar .writeable_reg = tegra_admaif_wr_reg,
240f74028e1SSameer Pujar .readable_reg = tegra_admaif_rd_reg,
241f74028e1SSameer Pujar .volatile_reg = tegra_admaif_volatile_reg,
242f74028e1SSameer Pujar .reg_defaults = tegra210_admaif_reg_defaults,
243f74028e1SSameer Pujar .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
244f74028e1SSameer Pujar .cache_type = REGCACHE_FLAT,
245f74028e1SSameer Pujar };
246f74028e1SSameer Pujar
247f74028e1SSameer Pujar static const struct regmap_config tegra186_admaif_regmap_config = {
248f74028e1SSameer Pujar .reg_bits = 32,
249f74028e1SSameer Pujar .reg_stride = 4,
250f74028e1SSameer Pujar .val_bits = 32,
251f74028e1SSameer Pujar .max_register = TEGRA186_ADMAIF_LAST_REG,
252f74028e1SSameer Pujar .writeable_reg = tegra_admaif_wr_reg,
253f74028e1SSameer Pujar .readable_reg = tegra_admaif_rd_reg,
254f74028e1SSameer Pujar .volatile_reg = tegra_admaif_volatile_reg,
255f74028e1SSameer Pujar .reg_defaults = tegra186_admaif_reg_defaults,
256f74028e1SSameer Pujar .num_reg_defaults = TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1,
257f74028e1SSameer Pujar .cache_type = REGCACHE_FLAT,
258f74028e1SSameer Pujar };
259f74028e1SSameer Pujar
260*7668c637SSheetal static const struct regmap_config tegra264_admaif_regmap_config = {
261*7668c637SSheetal .reg_bits = 32,
262*7668c637SSheetal .reg_stride = 4,
263*7668c637SSheetal .val_bits = 32,
264*7668c637SSheetal .max_register = TEGRA264_ADMAIF_LAST_REG,
265*7668c637SSheetal .writeable_reg = tegra_admaif_wr_reg,
266*7668c637SSheetal .readable_reg = tegra_admaif_rd_reg,
267*7668c637SSheetal .volatile_reg = tegra_admaif_volatile_reg,
268*7668c637SSheetal .reg_defaults = tegra264_admaif_reg_defaults,
269*7668c637SSheetal .num_reg_defaults = TEGRA264_ADMAIF_CHANNEL_COUNT * 6 + 1,
270*7668c637SSheetal .cache_type = REGCACHE_FLAT,
271*7668c637SSheetal };
272*7668c637SSheetal
tegra_admaif_runtime_suspend(struct device * dev)273083c6a6fSTakashi Iwai static int tegra_admaif_runtime_suspend(struct device *dev)
274f74028e1SSameer Pujar {
275f74028e1SSameer Pujar struct tegra_admaif *admaif = dev_get_drvdata(dev);
276f74028e1SSameer Pujar
277f74028e1SSameer Pujar regcache_cache_only(admaif->regmap, true);
278f74028e1SSameer Pujar regcache_mark_dirty(admaif->regmap);
279f74028e1SSameer Pujar
280f74028e1SSameer Pujar return 0;
281f74028e1SSameer Pujar }
282f74028e1SSameer Pujar
tegra_admaif_runtime_resume(struct device * dev)283083c6a6fSTakashi Iwai static int tegra_admaif_runtime_resume(struct device *dev)
284f74028e1SSameer Pujar {
285f74028e1SSameer Pujar struct tegra_admaif *admaif = dev_get_drvdata(dev);
286f74028e1SSameer Pujar
287f74028e1SSameer Pujar regcache_cache_only(admaif->regmap, false);
288f74028e1SSameer Pujar regcache_sync(admaif->regmap);
289f74028e1SSameer Pujar
290f74028e1SSameer Pujar return 0;
291f74028e1SSameer Pujar }
292f74028e1SSameer Pujar
tegra_admaif_set_pack_mode(struct regmap * map,unsigned int reg,int valid_bit)293f74028e1SSameer Pujar static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
294f74028e1SSameer Pujar int valid_bit)
295f74028e1SSameer Pujar {
296f74028e1SSameer Pujar switch (valid_bit) {
297f74028e1SSameer Pujar case DATA_8BIT:
298f74028e1SSameer Pujar regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN);
299f74028e1SSameer Pujar regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
300f74028e1SSameer Pujar break;
301f74028e1SSameer Pujar case DATA_16BIT:
302f74028e1SSameer Pujar regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN);
303f74028e1SSameer Pujar regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
304f74028e1SSameer Pujar break;
305f74028e1SSameer Pujar case DATA_32BIT:
306f74028e1SSameer Pujar regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
307f74028e1SSameer Pujar regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
308f74028e1SSameer Pujar break;
309f74028e1SSameer Pujar default:
310f74028e1SSameer Pujar return -EINVAL;
311f74028e1SSameer Pujar }
312f74028e1SSameer Pujar
313f74028e1SSameer Pujar return 0;
314f74028e1SSameer Pujar }
315f74028e1SSameer Pujar
tegra_admaif_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)3164a91fe4cSSheetal static int tegra_admaif_prepare(struct snd_pcm_substream *substream,
3174a91fe4cSSheetal struct snd_soc_dai *dai)
3184a91fe4cSSheetal {
3194a91fe4cSSheetal return tegra_isomgr_adma_setbw(substream, dai, true);
3204a91fe4cSSheetal }
3214a91fe4cSSheetal
tegra_admaif_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)3224a91fe4cSSheetal static void tegra_admaif_shutdown(struct snd_pcm_substream *substream,
3234a91fe4cSSheetal struct snd_soc_dai *dai)
3244a91fe4cSSheetal {
3254a91fe4cSSheetal tegra_isomgr_adma_setbw(substream, dai, false);
3264a91fe4cSSheetal }
3274a91fe4cSSheetal
tegra_admaif_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)328f74028e1SSameer Pujar static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
329f74028e1SSameer Pujar struct snd_pcm_hw_params *params,
330f74028e1SSameer Pujar struct snd_soc_dai *dai)
331f74028e1SSameer Pujar {
332f74028e1SSameer Pujar struct device *dev = dai->dev;
333f74028e1SSameer Pujar struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
334f74028e1SSameer Pujar struct tegra_cif_conf cif_conf;
335f74028e1SSameer Pujar unsigned int reg, path;
336f74028e1SSameer Pujar int valid_bit, channels;
337f74028e1SSameer Pujar
338f74028e1SSameer Pujar memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
339f74028e1SSameer Pujar
340f74028e1SSameer Pujar switch (params_format(params)) {
341f74028e1SSameer Pujar case SNDRV_PCM_FORMAT_S8:
342f74028e1SSameer Pujar cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
343f74028e1SSameer Pujar cif_conf.client_bits = TEGRA_ACIF_BITS_8;
344f74028e1SSameer Pujar valid_bit = DATA_8BIT;
345f74028e1SSameer Pujar break;
346f74028e1SSameer Pujar case SNDRV_PCM_FORMAT_S16_LE:
347f74028e1SSameer Pujar cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
348f74028e1SSameer Pujar cif_conf.client_bits = TEGRA_ACIF_BITS_16;
349f74028e1SSameer Pujar valid_bit = DATA_16BIT;
350f74028e1SSameer Pujar break;
3514204ecccSRitu Chaudhary case SNDRV_PCM_FORMAT_S24_LE:
3524204ecccSRitu Chaudhary cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
3534204ecccSRitu Chaudhary cif_conf.client_bits = TEGRA_ACIF_BITS_24;
3544204ecccSRitu Chaudhary valid_bit = DATA_32BIT;
3554204ecccSRitu Chaudhary break;
356f74028e1SSameer Pujar case SNDRV_PCM_FORMAT_S32_LE:
357f74028e1SSameer Pujar cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
358f74028e1SSameer Pujar cif_conf.client_bits = TEGRA_ACIF_BITS_32;
359f74028e1SSameer Pujar valid_bit = DATA_32BIT;
360f74028e1SSameer Pujar break;
361f74028e1SSameer Pujar default:
362f74028e1SSameer Pujar dev_err(dev, "unsupported format!\n");
363f74028e1SSameer Pujar return -EOPNOTSUPP;
364f74028e1SSameer Pujar }
365f74028e1SSameer Pujar
366f74028e1SSameer Pujar channels = params_channels(params);
367f74028e1SSameer Pujar cif_conf.client_ch = channels;
368f74028e1SSameer Pujar cif_conf.audio_ch = channels;
369f74028e1SSameer Pujar
370f74028e1SSameer Pujar if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
371f74028e1SSameer Pujar path = ADMAIF_TX_PATH;
372f74028e1SSameer Pujar reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id);
373f74028e1SSameer Pujar } else {
374f74028e1SSameer Pujar path = ADMAIF_RX_PATH;
375f74028e1SSameer Pujar reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id);
376f74028e1SSameer Pujar }
377f74028e1SSameer Pujar
378f74028e1SSameer Pujar cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
379f74028e1SSameer Pujar cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
380f74028e1SSameer Pujar
381f74028e1SSameer Pujar tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
382f74028e1SSameer Pujar
383*7668c637SSheetal if (admaif->soc_data->max_stream_ch == TEGRA264_ADMAIF_MAX_CHANNEL)
384*7668c637SSheetal tegra264_set_cif(admaif->regmap, reg, &cif_conf);
385*7668c637SSheetal else
386f74028e1SSameer Pujar tegra_set_cif(admaif->regmap, reg, &cif_conf);
387f74028e1SSameer Pujar
388f74028e1SSameer Pujar return 0;
389f74028e1SSameer Pujar }
390f74028e1SSameer Pujar
tegra_admaif_start(struct snd_soc_dai * dai,int direction)391f74028e1SSameer Pujar static int tegra_admaif_start(struct snd_soc_dai *dai, int direction)
392f74028e1SSameer Pujar {
393f74028e1SSameer Pujar struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
394f74028e1SSameer Pujar unsigned int reg, mask, val;
395f74028e1SSameer Pujar
396f74028e1SSameer Pujar switch (direction) {
397f74028e1SSameer Pujar case SNDRV_PCM_STREAM_PLAYBACK:
398f74028e1SSameer Pujar mask = TX_ENABLE_MASK;
399f74028e1SSameer Pujar val = TX_ENABLE;
400f74028e1SSameer Pujar reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
401f74028e1SSameer Pujar break;
402f74028e1SSameer Pujar case SNDRV_PCM_STREAM_CAPTURE:
403f74028e1SSameer Pujar mask = RX_ENABLE_MASK;
404f74028e1SSameer Pujar val = RX_ENABLE;
405f74028e1SSameer Pujar reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
406f74028e1SSameer Pujar break;
407f74028e1SSameer Pujar default:
408f74028e1SSameer Pujar return -EINVAL;
409f74028e1SSameer Pujar }
410f74028e1SSameer Pujar
411f74028e1SSameer Pujar regmap_update_bits(admaif->regmap, reg, mask, val);
412f74028e1SSameer Pujar
413f74028e1SSameer Pujar return 0;
414f74028e1SSameer Pujar }
415f74028e1SSameer Pujar
tegra_admaif_stop(struct snd_soc_dai * dai,int direction)416f74028e1SSameer Pujar static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
417f74028e1SSameer Pujar {
418f74028e1SSameer Pujar struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
419f74028e1SSameer Pujar unsigned int enable_reg, status_reg, reset_reg, mask, val;
420f74028e1SSameer Pujar char *dir_name;
421f74028e1SSameer Pujar int err, enable;
422f74028e1SSameer Pujar
423f74028e1SSameer Pujar switch (direction) {
424f74028e1SSameer Pujar case SNDRV_PCM_STREAM_PLAYBACK:
425f74028e1SSameer Pujar mask = TX_ENABLE_MASK;
426f74028e1SSameer Pujar enable = TX_ENABLE;
427f74028e1SSameer Pujar dir_name = "TX";
428f74028e1SSameer Pujar enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
429f74028e1SSameer Pujar status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id);
430f74028e1SSameer Pujar reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id);
431f74028e1SSameer Pujar break;
432f74028e1SSameer Pujar case SNDRV_PCM_STREAM_CAPTURE:
433f74028e1SSameer Pujar mask = RX_ENABLE_MASK;
434f74028e1SSameer Pujar enable = RX_ENABLE;
435f74028e1SSameer Pujar dir_name = "RX";
436f74028e1SSameer Pujar enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
437f74028e1SSameer Pujar status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id);
438f74028e1SSameer Pujar reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id);
439f74028e1SSameer Pujar break;
440f74028e1SSameer Pujar default:
441f74028e1SSameer Pujar return -EINVAL;
442f74028e1SSameer Pujar }
443f74028e1SSameer Pujar
444f74028e1SSameer Pujar /* Disable TX/RX channel */
445f74028e1SSameer Pujar regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
446f74028e1SSameer Pujar
447f74028e1SSameer Pujar /* Wait until ADMAIF TX/RX status is disabled */
448f74028e1SSameer Pujar err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val,
449f74028e1SSameer Pujar !(val & enable), 10, 10000);
450f74028e1SSameer Pujar if (err < 0)
451f74028e1SSameer Pujar dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n",
452f74028e1SSameer Pujar dai->id + 1, dir_name);
453f74028e1SSameer Pujar
454f74028e1SSameer Pujar /* SW reset */
455f74028e1SSameer Pujar regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
456f74028e1SSameer Pujar
457f74028e1SSameer Pujar /* Wait till SW reset is complete */
458f74028e1SSameer Pujar err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val,
459f74028e1SSameer Pujar !(val & SW_RESET_MASK & SW_RESET),
460f74028e1SSameer Pujar 10, 10000);
461f74028e1SSameer Pujar if (err) {
462f74028e1SSameer Pujar dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n",
463f74028e1SSameer Pujar dai->id + 1, dir_name);
464f74028e1SSameer Pujar return err;
465f74028e1SSameer Pujar }
466f74028e1SSameer Pujar
467f74028e1SSameer Pujar return 0;
468f74028e1SSameer Pujar }
469f74028e1SSameer Pujar
tegra_admaif_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)470f74028e1SSameer Pujar static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
471f74028e1SSameer Pujar struct snd_soc_dai *dai)
472f74028e1SSameer Pujar {
473f74028e1SSameer Pujar int err;
474f74028e1SSameer Pujar
475f74028e1SSameer Pujar err = snd_dmaengine_pcm_trigger(substream, cmd);
476f74028e1SSameer Pujar if (err)
477f74028e1SSameer Pujar return err;
478f74028e1SSameer Pujar
479f74028e1SSameer Pujar switch (cmd) {
480f74028e1SSameer Pujar case SNDRV_PCM_TRIGGER_START:
481f74028e1SSameer Pujar case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
482f74028e1SSameer Pujar case SNDRV_PCM_TRIGGER_RESUME:
483f74028e1SSameer Pujar return tegra_admaif_start(dai, substream->stream);
484f74028e1SSameer Pujar case SNDRV_PCM_TRIGGER_STOP:
485f74028e1SSameer Pujar case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
486f74028e1SSameer Pujar case SNDRV_PCM_TRIGGER_SUSPEND:
487f74028e1SSameer Pujar return tegra_admaif_stop(dai, substream->stream);
488f74028e1SSameer Pujar default:
489f74028e1SSameer Pujar return -EINVAL;
490f74028e1SSameer Pujar }
491f74028e1SSameer Pujar }
492f74028e1SSameer Pujar
tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)493e2b87a18SSameer Pujar static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
494f74028e1SSameer Pujar struct snd_ctl_elem_value *ucontrol)
495f74028e1SSameer Pujar {
496f74028e1SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
497f74028e1SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
498e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
499f74028e1SSameer Pujar
500e2b87a18SSameer Pujar ucontrol->value.enumerated.item[0] =
501e2b87a18SSameer Pujar admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
502f74028e1SSameer Pujar
503f74028e1SSameer Pujar return 0;
504f74028e1SSameer Pujar }
505f74028e1SSameer Pujar
tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)506e2b87a18SSameer Pujar static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
507f74028e1SSameer Pujar struct snd_ctl_elem_value *ucontrol)
508f74028e1SSameer Pujar {
509f74028e1SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
510f74028e1SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
511e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
512884c6cb3SSameer Pujar unsigned int value = ucontrol->value.enumerated.item[0];
513f74028e1SSameer Pujar
514e2b87a18SSameer Pujar if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
515e2b87a18SSameer Pujar return 0;
516e2b87a18SSameer Pujar
517f74028e1SSameer Pujar admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
518e2b87a18SSameer Pujar
519e2b87a18SSameer Pujar return 1;
520e2b87a18SSameer Pujar }
521e2b87a18SSameer Pujar
tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)522e2b87a18SSameer Pujar static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
523e2b87a18SSameer Pujar struct snd_ctl_elem_value *ucontrol)
524e2b87a18SSameer Pujar {
525e2b87a18SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
526e2b87a18SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
527e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
528e2b87a18SSameer Pujar
529e2b87a18SSameer Pujar ucontrol->value.enumerated.item[0] =
530e2b87a18SSameer Pujar admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
531f74028e1SSameer Pujar
532f74028e1SSameer Pujar return 0;
533f74028e1SSameer Pujar }
534f74028e1SSameer Pujar
tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)535e2b87a18SSameer Pujar static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
536e2b87a18SSameer Pujar struct snd_ctl_elem_value *ucontrol)
537e2b87a18SSameer Pujar {
538e2b87a18SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
539e2b87a18SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
540e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
541e2b87a18SSameer Pujar unsigned int value = ucontrol->value.enumerated.item[0];
542e2b87a18SSameer Pujar
543e2b87a18SSameer Pujar if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
544e2b87a18SSameer Pujar return 0;
545e2b87a18SSameer Pujar
546e2b87a18SSameer Pujar admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
547e2b87a18SSameer Pujar
548e2b87a18SSameer Pujar return 1;
549e2b87a18SSameer Pujar }
550e2b87a18SSameer Pujar
tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)551e2b87a18SSameer Pujar static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
552e2b87a18SSameer Pujar struct snd_ctl_elem_value *ucontrol)
553e2b87a18SSameer Pujar {
554e2b87a18SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
555e2b87a18SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
556e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
557e2b87a18SSameer Pujar
558e2b87a18SSameer Pujar ucontrol->value.enumerated.item[0] =
559e2b87a18SSameer Pujar admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
560e2b87a18SSameer Pujar
561e2b87a18SSameer Pujar return 0;
562e2b87a18SSameer Pujar }
563e2b87a18SSameer Pujar
tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)564e2b87a18SSameer Pujar static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
565e2b87a18SSameer Pujar struct snd_ctl_elem_value *ucontrol)
566e2b87a18SSameer Pujar {
567e2b87a18SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
568e2b87a18SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
569e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
570e2b87a18SSameer Pujar unsigned int value = ucontrol->value.enumerated.item[0];
571e2b87a18SSameer Pujar
572e2b87a18SSameer Pujar if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
573e2b87a18SSameer Pujar return 0;
574e2b87a18SSameer Pujar
575e2b87a18SSameer Pujar admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
576e2b87a18SSameer Pujar
577e2b87a18SSameer Pujar return 1;
578e2b87a18SSameer Pujar }
579e2b87a18SSameer Pujar
tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)580e2b87a18SSameer Pujar static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
581e2b87a18SSameer Pujar struct snd_ctl_elem_value *ucontrol)
582e2b87a18SSameer Pujar {
583e2b87a18SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
584e2b87a18SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
585e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
586e2b87a18SSameer Pujar
587e2b87a18SSameer Pujar ucontrol->value.enumerated.item[0] =
588e2b87a18SSameer Pujar admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
589e2b87a18SSameer Pujar
590e2b87a18SSameer Pujar return 0;
591e2b87a18SSameer Pujar }
592e2b87a18SSameer Pujar
tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)593e2b87a18SSameer Pujar static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
594e2b87a18SSameer Pujar struct snd_ctl_elem_value *ucontrol)
595e2b87a18SSameer Pujar {
596e2b87a18SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
597e2b87a18SSameer Pujar struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
598e2b87a18SSameer Pujar struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
599e2b87a18SSameer Pujar unsigned int value = ucontrol->value.enumerated.item[0];
600e2b87a18SSameer Pujar
601e2b87a18SSameer Pujar if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
602e2b87a18SSameer Pujar return 0;
603e2b87a18SSameer Pujar
604e2b87a18SSameer Pujar admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
605e2b87a18SSameer Pujar
606e2b87a18SSameer Pujar return 1;
607e2b87a18SSameer Pujar }
608e2b87a18SSameer Pujar
tegra_admaif_dai_probe(struct snd_soc_dai * dai)609f74028e1SSameer Pujar static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
610f74028e1SSameer Pujar {
611f74028e1SSameer Pujar struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
612f74028e1SSameer Pujar
6131c1a7784SKuninori Morimoto snd_soc_dai_init_dma_data(dai, &admaif->playback_dma_data[dai->id],
6141c1a7784SKuninori Morimoto &admaif->capture_dma_data[dai->id]);
615f74028e1SSameer Pujar
616f74028e1SSameer Pujar return 0;
617f74028e1SSameer Pujar }
618f74028e1SSameer Pujar
619516ee700SKuninori Morimoto static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
620516ee700SKuninori Morimoto .probe = tegra_admaif_dai_probe,
621516ee700SKuninori Morimoto .hw_params = tegra_admaif_hw_params,
622516ee700SKuninori Morimoto .trigger = tegra_admaif_trigger,
6234a91fe4cSSheetal .shutdown = tegra_admaif_shutdown,
6244a91fe4cSSheetal .prepare = tegra_admaif_prepare,
625516ee700SKuninori Morimoto };
626516ee700SKuninori Morimoto
627*7668c637SSheetal #define DAI(dai_name, channel) \
628f74028e1SSameer Pujar { \
629f74028e1SSameer Pujar .name = dai_name, \
630f74028e1SSameer Pujar .playback = { \
631f74028e1SSameer Pujar .stream_name = dai_name " Playback", \
632f74028e1SSameer Pujar .channels_min = 1, \
633*7668c637SSheetal .channels_max = channel, \
634f74028e1SSameer Pujar .rates = SNDRV_PCM_RATE_8000_192000, \
635f74028e1SSameer Pujar .formats = SNDRV_PCM_FMTBIT_S8 | \
636f74028e1SSameer Pujar SNDRV_PCM_FMTBIT_S16_LE | \
6374204ecccSRitu Chaudhary SNDRV_PCM_FMTBIT_S24_LE | \
638f74028e1SSameer Pujar SNDRV_PCM_FMTBIT_S32_LE, \
639f74028e1SSameer Pujar }, \
640f74028e1SSameer Pujar .capture = { \
641f74028e1SSameer Pujar .stream_name = dai_name " Capture", \
642f74028e1SSameer Pujar .channels_min = 1, \
643*7668c637SSheetal .channels_max = channel, \
644f74028e1SSameer Pujar .rates = SNDRV_PCM_RATE_8000_192000, \
645f74028e1SSameer Pujar .formats = SNDRV_PCM_FMTBIT_S8 | \
646f74028e1SSameer Pujar SNDRV_PCM_FMTBIT_S16_LE | \
6474204ecccSRitu Chaudhary SNDRV_PCM_FMTBIT_S24_LE | \
648f74028e1SSameer Pujar SNDRV_PCM_FMTBIT_S32_LE, \
649f74028e1SSameer Pujar }, \
650f74028e1SSameer Pujar .ops = &tegra_admaif_dai_ops, \
651f74028e1SSameer Pujar }
652f74028e1SSameer Pujar
653f74028e1SSameer Pujar static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
654*7668c637SSheetal DAI("ADMAIF1", TEGRA210_ADMAIF_MAX_CHANNEL),
655*7668c637SSheetal DAI("ADMAIF2", TEGRA210_ADMAIF_MAX_CHANNEL),
656*7668c637SSheetal DAI("ADMAIF3", TEGRA210_ADMAIF_MAX_CHANNEL),
657*7668c637SSheetal DAI("ADMAIF4", TEGRA210_ADMAIF_MAX_CHANNEL),
658*7668c637SSheetal DAI("ADMAIF5", TEGRA210_ADMAIF_MAX_CHANNEL),
659*7668c637SSheetal DAI("ADMAIF6", TEGRA210_ADMAIF_MAX_CHANNEL),
660*7668c637SSheetal DAI("ADMAIF7", TEGRA210_ADMAIF_MAX_CHANNEL),
661*7668c637SSheetal DAI("ADMAIF8", TEGRA210_ADMAIF_MAX_CHANNEL),
662*7668c637SSheetal DAI("ADMAIF9", TEGRA210_ADMAIF_MAX_CHANNEL),
663*7668c637SSheetal DAI("ADMAIF10", TEGRA210_ADMAIF_MAX_CHANNEL),
664f74028e1SSameer Pujar };
665f74028e1SSameer Pujar
666f74028e1SSameer Pujar static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
667*7668c637SSheetal DAI("ADMAIF1", TEGRA186_ADMAIF_MAX_CHANNEL),
668*7668c637SSheetal DAI("ADMAIF2", TEGRA186_ADMAIF_MAX_CHANNEL),
669*7668c637SSheetal DAI("ADMAIF3", TEGRA186_ADMAIF_MAX_CHANNEL),
670*7668c637SSheetal DAI("ADMAIF4", TEGRA186_ADMAIF_MAX_CHANNEL),
671*7668c637SSheetal DAI("ADMAIF5", TEGRA186_ADMAIF_MAX_CHANNEL),
672*7668c637SSheetal DAI("ADMAIF6", TEGRA186_ADMAIF_MAX_CHANNEL),
673*7668c637SSheetal DAI("ADMAIF7", TEGRA186_ADMAIF_MAX_CHANNEL),
674*7668c637SSheetal DAI("ADMAIF8", TEGRA186_ADMAIF_MAX_CHANNEL),
675*7668c637SSheetal DAI("ADMAIF9", TEGRA186_ADMAIF_MAX_CHANNEL),
676*7668c637SSheetal DAI("ADMAIF10", TEGRA186_ADMAIF_MAX_CHANNEL),
677*7668c637SSheetal DAI("ADMAIF11", TEGRA186_ADMAIF_MAX_CHANNEL),
678*7668c637SSheetal DAI("ADMAIF12", TEGRA186_ADMAIF_MAX_CHANNEL),
679*7668c637SSheetal DAI("ADMAIF13", TEGRA186_ADMAIF_MAX_CHANNEL),
680*7668c637SSheetal DAI("ADMAIF14", TEGRA186_ADMAIF_MAX_CHANNEL),
681*7668c637SSheetal DAI("ADMAIF15", TEGRA186_ADMAIF_MAX_CHANNEL),
682*7668c637SSheetal DAI("ADMAIF16", TEGRA186_ADMAIF_MAX_CHANNEL),
683*7668c637SSheetal DAI("ADMAIF17", TEGRA186_ADMAIF_MAX_CHANNEL),
684*7668c637SSheetal DAI("ADMAIF18", TEGRA186_ADMAIF_MAX_CHANNEL),
685*7668c637SSheetal DAI("ADMAIF19", TEGRA186_ADMAIF_MAX_CHANNEL),
686*7668c637SSheetal DAI("ADMAIF20", TEGRA186_ADMAIF_MAX_CHANNEL),
687*7668c637SSheetal };
688*7668c637SSheetal
689*7668c637SSheetal static struct snd_soc_dai_driver tegra264_admaif_cmpnt_dais[] = {
690*7668c637SSheetal DAI("ADMAIF1", TEGRA264_ADMAIF_MAX_CHANNEL),
691*7668c637SSheetal DAI("ADMAIF2", TEGRA264_ADMAIF_MAX_CHANNEL),
692*7668c637SSheetal DAI("ADMAIF3", TEGRA264_ADMAIF_MAX_CHANNEL),
693*7668c637SSheetal DAI("ADMAIF4", TEGRA264_ADMAIF_MAX_CHANNEL),
694*7668c637SSheetal DAI("ADMAIF5", TEGRA264_ADMAIF_MAX_CHANNEL),
695*7668c637SSheetal DAI("ADMAIF6", TEGRA264_ADMAIF_MAX_CHANNEL),
696*7668c637SSheetal DAI("ADMAIF7", TEGRA264_ADMAIF_MAX_CHANNEL),
697*7668c637SSheetal DAI("ADMAIF8", TEGRA264_ADMAIF_MAX_CHANNEL),
698*7668c637SSheetal DAI("ADMAIF9", TEGRA264_ADMAIF_MAX_CHANNEL),
699*7668c637SSheetal DAI("ADMAIF10", TEGRA264_ADMAIF_MAX_CHANNEL),
700*7668c637SSheetal DAI("ADMAIF11", TEGRA264_ADMAIF_MAX_CHANNEL),
701*7668c637SSheetal DAI("ADMAIF12", TEGRA264_ADMAIF_MAX_CHANNEL),
702*7668c637SSheetal DAI("ADMAIF13", TEGRA264_ADMAIF_MAX_CHANNEL),
703*7668c637SSheetal DAI("ADMAIF14", TEGRA264_ADMAIF_MAX_CHANNEL),
704*7668c637SSheetal DAI("ADMAIF15", TEGRA264_ADMAIF_MAX_CHANNEL),
705*7668c637SSheetal DAI("ADMAIF16", TEGRA264_ADMAIF_MAX_CHANNEL),
706*7668c637SSheetal DAI("ADMAIF17", TEGRA264_ADMAIF_MAX_CHANNEL),
707*7668c637SSheetal DAI("ADMAIF18", TEGRA264_ADMAIF_MAX_CHANNEL),
708*7668c637SSheetal DAI("ADMAIF19", TEGRA264_ADMAIF_MAX_CHANNEL),
709*7668c637SSheetal DAI("ADMAIF20", TEGRA264_ADMAIF_MAX_CHANNEL),
710*7668c637SSheetal DAI("ADMAIF21", TEGRA264_ADMAIF_MAX_CHANNEL),
711*7668c637SSheetal DAI("ADMAIF22", TEGRA264_ADMAIF_MAX_CHANNEL),
712*7668c637SSheetal DAI("ADMAIF23", TEGRA264_ADMAIF_MAX_CHANNEL),
713*7668c637SSheetal DAI("ADMAIF24", TEGRA264_ADMAIF_MAX_CHANNEL),
714*7668c637SSheetal DAI("ADMAIF25", TEGRA264_ADMAIF_MAX_CHANNEL),
715*7668c637SSheetal DAI("ADMAIF26", TEGRA264_ADMAIF_MAX_CHANNEL),
716*7668c637SSheetal DAI("ADMAIF27", TEGRA264_ADMAIF_MAX_CHANNEL),
717*7668c637SSheetal DAI("ADMAIF28", TEGRA264_ADMAIF_MAX_CHANNEL),
718*7668c637SSheetal DAI("ADMAIF29", TEGRA264_ADMAIF_MAX_CHANNEL),
719*7668c637SSheetal DAI("ADMAIF30", TEGRA264_ADMAIF_MAX_CHANNEL),
720*7668c637SSheetal DAI("ADMAIF31", TEGRA264_ADMAIF_MAX_CHANNEL),
721*7668c637SSheetal DAI("ADMAIF32", TEGRA264_ADMAIF_MAX_CHANNEL),
722f74028e1SSameer Pujar };
723f74028e1SSameer Pujar
724f74028e1SSameer Pujar static const char * const tegra_admaif_stereo_conv_text[] = {
725f74028e1SSameer Pujar "CH0", "CH1", "AVG",
726f74028e1SSameer Pujar };
727f74028e1SSameer Pujar
728f74028e1SSameer Pujar static const char * const tegra_admaif_mono_conv_text[] = {
729f74028e1SSameer Pujar "Zero", "Copy",
730f74028e1SSameer Pujar };
731f74028e1SSameer Pujar
732f74028e1SSameer Pujar /*
733f74028e1SSameer Pujar * Below macro is added to avoid looping over all ADMAIFx controls related
734f74028e1SSameer Pujar * to mono/stereo conversions in get()/put() callbacks.
735f74028e1SSameer Pujar */
736f74028e1SSameer Pujar #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \
737f74028e1SSameer Pujar { \
738f74028e1SSameer Pujar .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
739f74028e1SSameer Pujar .info = snd_soc_info_enum_double, \
740f74028e1SSameer Pujar .name = xname, \
741f74028e1SSameer Pujar .get = xhandler_get, \
742f74028e1SSameer Pujar .put = xhandler_put, \
743f74028e1SSameer Pujar .private_value = (unsigned long)&(struct soc_enum) \
744f74028e1SSameer Pujar SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \
745f74028e1SSameer Pujar }
746f74028e1SSameer Pujar
747f74028e1SSameer Pujar #define TEGRA_ADMAIF_CIF_CTRL(reg) \
748f74028e1SSameer Pujar NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \
749e2b87a18SSameer Pujar tegra210_admaif_pget_mono_to_stereo, \
750e2b87a18SSameer Pujar tegra210_admaif_pput_mono_to_stereo, \
751f74028e1SSameer Pujar tegra_admaif_mono_conv_text), \
752f74028e1SSameer Pujar NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \
753e2b87a18SSameer Pujar tegra210_admaif_pget_stereo_to_mono, \
754e2b87a18SSameer Pujar tegra210_admaif_pput_stereo_to_mono, \
755f74028e1SSameer Pujar tegra_admaif_stereo_conv_text), \
756f74028e1SSameer Pujar NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
757e2b87a18SSameer Pujar tegra210_admaif_cget_mono_to_stereo, \
758e2b87a18SSameer Pujar tegra210_admaif_cput_mono_to_stereo, \
759f74028e1SSameer Pujar tegra_admaif_mono_conv_text), \
760f74028e1SSameer Pujar NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
761e2b87a18SSameer Pujar tegra210_admaif_cget_stereo_to_mono, \
762e2b87a18SSameer Pujar tegra210_admaif_cput_stereo_to_mono, \
763f74028e1SSameer Pujar tegra_admaif_stereo_conv_text)
764f74028e1SSameer Pujar
765f74028e1SSameer Pujar static struct snd_kcontrol_new tegra210_admaif_controls[] = {
766f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(1),
767f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(2),
768f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(3),
769f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(4),
770f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(5),
771f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(6),
772f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(7),
773f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(8),
774f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(9),
775f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(10),
776f74028e1SSameer Pujar };
777f74028e1SSameer Pujar
778f74028e1SSameer Pujar static struct snd_kcontrol_new tegra186_admaif_controls[] = {
779f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(1),
780f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(2),
781f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(3),
782f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(4),
783f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(5),
784f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(6),
785f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(7),
786f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(8),
787f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(9),
788f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(10),
789f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(11),
790f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(12),
791f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(13),
792f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(14),
793f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(15),
794f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(16),
795f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(17),
796f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(18),
797f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(19),
798f74028e1SSameer Pujar TEGRA_ADMAIF_CIF_CTRL(20),
799f74028e1SSameer Pujar };
800f74028e1SSameer Pujar
801*7668c637SSheetal static struct snd_kcontrol_new tegra264_admaif_controls[] = {
802*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(1),
803*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(2),
804*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(3),
805*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(4),
806*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(5),
807*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(6),
808*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(7),
809*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(8),
810*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(9),
811*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(10),
812*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(11),
813*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(12),
814*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(13),
815*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(14),
816*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(15),
817*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(16),
818*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(17),
819*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(18),
820*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(19),
821*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(20),
822*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(21),
823*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(22),
824*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(23),
825*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(24),
826*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(25),
827*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(26),
828*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(27),
829*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(28),
830*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(29),
831*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(30),
832*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(31),
833*7668c637SSheetal TEGRA_ADMAIF_CIF_CTRL(32),
834*7668c637SSheetal };
835*7668c637SSheetal
836f74028e1SSameer Pujar static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
837f74028e1SSameer Pujar .controls = tegra210_admaif_controls,
838f74028e1SSameer Pujar .num_controls = ARRAY_SIZE(tegra210_admaif_controls),
839f74028e1SSameer Pujar .pcm_construct = tegra_pcm_construct,
840f74028e1SSameer Pujar .open = tegra_pcm_open,
841f74028e1SSameer Pujar .close = tegra_pcm_close,
842f74028e1SSameer Pujar .hw_params = tegra_pcm_hw_params,
843f74028e1SSameer Pujar .pointer = tegra_pcm_pointer,
844f74028e1SSameer Pujar };
845f74028e1SSameer Pujar
846f74028e1SSameer Pujar static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
847f74028e1SSameer Pujar .controls = tegra186_admaif_controls,
848f74028e1SSameer Pujar .num_controls = ARRAY_SIZE(tegra186_admaif_controls),
849f74028e1SSameer Pujar .pcm_construct = tegra_pcm_construct,
850f74028e1SSameer Pujar .open = tegra_pcm_open,
851f74028e1SSameer Pujar .close = tegra_pcm_close,
852f74028e1SSameer Pujar .hw_params = tegra_pcm_hw_params,
853f74028e1SSameer Pujar .pointer = tegra_pcm_pointer,
854f74028e1SSameer Pujar };
855f74028e1SSameer Pujar
856*7668c637SSheetal static const struct snd_soc_component_driver tegra264_admaif_cmpnt = {
857*7668c637SSheetal .controls = tegra264_admaif_controls,
858*7668c637SSheetal .num_controls = ARRAY_SIZE(tegra264_admaif_controls),
859*7668c637SSheetal .pcm_construct = tegra_pcm_construct,
860*7668c637SSheetal .open = tegra_pcm_open,
861*7668c637SSheetal .close = tegra_pcm_close,
862*7668c637SSheetal .hw_params = tegra_pcm_hw_params,
863*7668c637SSheetal .pointer = tegra_pcm_pointer,
864*7668c637SSheetal };
865*7668c637SSheetal
866f74028e1SSameer Pujar static const struct tegra_admaif_soc_data soc_data_tegra210 = {
867f74028e1SSameer Pujar .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT,
868*7668c637SSheetal .max_stream_ch = TEGRA210_ADMAIF_MAX_CHANNEL,
869f74028e1SSameer Pujar .cmpnt = &tegra210_admaif_cmpnt,
870f74028e1SSameer Pujar .dais = tegra210_admaif_cmpnt_dais,
871f74028e1SSameer Pujar .regmap_conf = &tegra210_admaif_regmap_config,
872f74028e1SSameer Pujar .global_base = TEGRA210_ADMAIF_GLOBAL_BASE,
873f74028e1SSameer Pujar .tx_base = TEGRA210_ADMAIF_TX_BASE,
874f74028e1SSameer Pujar .rx_base = TEGRA210_ADMAIF_RX_BASE,
875f74028e1SSameer Pujar };
876f74028e1SSameer Pujar
877f74028e1SSameer Pujar static const struct tegra_admaif_soc_data soc_data_tegra186 = {
878f74028e1SSameer Pujar .num_ch = TEGRA186_ADMAIF_CHANNEL_COUNT,
879*7668c637SSheetal .max_stream_ch = TEGRA186_ADMAIF_MAX_CHANNEL,
880f74028e1SSameer Pujar .cmpnt = &tegra186_admaif_cmpnt,
881f74028e1SSameer Pujar .dais = tegra186_admaif_cmpnt_dais,
882f74028e1SSameer Pujar .regmap_conf = &tegra186_admaif_regmap_config,
883f74028e1SSameer Pujar .global_base = TEGRA186_ADMAIF_GLOBAL_BASE,
884f74028e1SSameer Pujar .tx_base = TEGRA186_ADMAIF_TX_BASE,
885f74028e1SSameer Pujar .rx_base = TEGRA186_ADMAIF_RX_BASE,
886f74028e1SSameer Pujar };
887f74028e1SSameer Pujar
888*7668c637SSheetal static const struct tegra_admaif_soc_data soc_data_tegra264 = {
889*7668c637SSheetal .num_ch = TEGRA264_ADMAIF_CHANNEL_COUNT,
890*7668c637SSheetal .max_stream_ch = TEGRA264_ADMAIF_MAX_CHANNEL,
891*7668c637SSheetal .cmpnt = &tegra264_admaif_cmpnt,
892*7668c637SSheetal .dais = tegra264_admaif_cmpnt_dais,
893*7668c637SSheetal .regmap_conf = &tegra264_admaif_regmap_config,
894*7668c637SSheetal .global_base = TEGRA264_ADMAIF_GLOBAL_BASE,
895*7668c637SSheetal .tx_base = TEGRA264_ADMAIF_TX_BASE,
896*7668c637SSheetal .rx_base = TEGRA264_ADMAIF_RX_BASE,
897*7668c637SSheetal };
898*7668c637SSheetal
899f74028e1SSameer Pujar static const struct of_device_id tegra_admaif_of_match[] = {
900f74028e1SSameer Pujar { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
901f74028e1SSameer Pujar { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
902*7668c637SSheetal { .compatible = "nvidia,tegra264-admaif", .data = &soc_data_tegra264 },
903f74028e1SSameer Pujar {},
904f74028e1SSameer Pujar };
905f74028e1SSameer Pujar MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
906f74028e1SSameer Pujar
tegra_admaif_probe(struct platform_device * pdev)907f74028e1SSameer Pujar static int tegra_admaif_probe(struct platform_device *pdev)
908f74028e1SSameer Pujar {
909f74028e1SSameer Pujar struct tegra_admaif *admaif;
910f74028e1SSameer Pujar void __iomem *regs;
911f74028e1SSameer Pujar struct resource *res;
912f74028e1SSameer Pujar int err, i;
913f74028e1SSameer Pujar
914f74028e1SSameer Pujar admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
915f74028e1SSameer Pujar if (!admaif)
916f74028e1SSameer Pujar return -ENOMEM;
917f74028e1SSameer Pujar
918f74028e1SSameer Pujar admaif->soc_data = of_device_get_match_data(&pdev->dev);
919f74028e1SSameer Pujar
920f74028e1SSameer Pujar dev_set_drvdata(&pdev->dev, admaif);
921f74028e1SSameer Pujar
922f74028e1SSameer Pujar admaif->capture_dma_data =
923f74028e1SSameer Pujar devm_kcalloc(&pdev->dev,
924f74028e1SSameer Pujar admaif->soc_data->num_ch,
925f74028e1SSameer Pujar sizeof(struct snd_dmaengine_dai_dma_data),
926f74028e1SSameer Pujar GFP_KERNEL);
927f74028e1SSameer Pujar if (!admaif->capture_dma_data)
928f74028e1SSameer Pujar return -ENOMEM;
929f74028e1SSameer Pujar
930f74028e1SSameer Pujar admaif->playback_dma_data =
931f74028e1SSameer Pujar devm_kcalloc(&pdev->dev,
932f74028e1SSameer Pujar admaif->soc_data->num_ch,
933f74028e1SSameer Pujar sizeof(struct snd_dmaengine_dai_dma_data),
934f74028e1SSameer Pujar GFP_KERNEL);
935f74028e1SSameer Pujar if (!admaif->playback_dma_data)
936f74028e1SSameer Pujar return -ENOMEM;
937f74028e1SSameer Pujar
938f74028e1SSameer Pujar for (i = 0; i < ADMAIF_PATHS; i++) {
939f74028e1SSameer Pujar admaif->mono_to_stereo[i] =
940f74028e1SSameer Pujar devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
941f74028e1SSameer Pujar sizeof(unsigned int), GFP_KERNEL);
942f74028e1SSameer Pujar if (!admaif->mono_to_stereo[i])
943f74028e1SSameer Pujar return -ENOMEM;
944f74028e1SSameer Pujar
945f74028e1SSameer Pujar admaif->stereo_to_mono[i] =
946f74028e1SSameer Pujar devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
947f74028e1SSameer Pujar sizeof(unsigned int), GFP_KERNEL);
948f74028e1SSameer Pujar if (!admaif->stereo_to_mono[i])
949f74028e1SSameer Pujar return -ENOMEM;
950f74028e1SSameer Pujar }
951f74028e1SSameer Pujar
952c29b6382SYang Yingliang regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
953f74028e1SSameer Pujar if (IS_ERR(regs))
954f74028e1SSameer Pujar return PTR_ERR(regs);
955f74028e1SSameer Pujar
956f74028e1SSameer Pujar admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
957f74028e1SSameer Pujar admaif->soc_data->regmap_conf);
958f74028e1SSameer Pujar if (IS_ERR(admaif->regmap)) {
959f74028e1SSameer Pujar dev_err(&pdev->dev, "regmap init failed\n");
960f74028e1SSameer Pujar return PTR_ERR(admaif->regmap);
961f74028e1SSameer Pujar }
962f74028e1SSameer Pujar
963f74028e1SSameer Pujar regcache_cache_only(admaif->regmap, true);
964f74028e1SSameer Pujar
9654a91fe4cSSheetal err = tegra_isomgr_adma_register(&pdev->dev);
9664a91fe4cSSheetal if (err) {
9674a91fe4cSSheetal dev_err(&pdev->dev, "Failed to add interconnect path\n");
9684a91fe4cSSheetal return err;
9694a91fe4cSSheetal }
9704a91fe4cSSheetal
971f74028e1SSameer Pujar regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
972f74028e1SSameer Pujar TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
973f74028e1SSameer Pujar
974f74028e1SSameer Pujar for (i = 0; i < admaif->soc_data->num_ch; i++) {
975f74028e1SSameer Pujar admaif->playback_dma_data[i].addr = res->start +
976f74028e1SSameer Pujar CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
977f74028e1SSameer Pujar
978f74028e1SSameer Pujar admaif->capture_dma_data[i].addr = res->start +
979f74028e1SSameer Pujar CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
980f74028e1SSameer Pujar
981f74028e1SSameer Pujar admaif->playback_dma_data[i].addr_width = 32;
982f74028e1SSameer Pujar
983f74028e1SSameer Pujar if (of_property_read_string_index(pdev->dev.of_node,
984f74028e1SSameer Pujar "dma-names", (i * 2) + 1,
985f74028e1SSameer Pujar &admaif->playback_dma_data[i].chan_name) < 0) {
986f74028e1SSameer Pujar dev_err(&pdev->dev,
987f74028e1SSameer Pujar "missing property nvidia,dma-names\n");
988f74028e1SSameer Pujar
989f74028e1SSameer Pujar return -ENODEV;
990f74028e1SSameer Pujar }
991f74028e1SSameer Pujar
992f74028e1SSameer Pujar admaif->capture_dma_data[i].addr_width = 32;
993f74028e1SSameer Pujar
994f74028e1SSameer Pujar if (of_property_read_string_index(pdev->dev.of_node,
995f74028e1SSameer Pujar "dma-names",
996f74028e1SSameer Pujar (i * 2),
997f74028e1SSameer Pujar &admaif->capture_dma_data[i].chan_name) < 0) {
998f74028e1SSameer Pujar dev_err(&pdev->dev,
999f74028e1SSameer Pujar "missing property nvidia,dma-names\n");
1000f74028e1SSameer Pujar
1001f74028e1SSameer Pujar return -ENODEV;
1002f74028e1SSameer Pujar }
1003f74028e1SSameer Pujar }
1004f74028e1SSameer Pujar
1005f74028e1SSameer Pujar err = devm_snd_soc_register_component(&pdev->dev,
1006f74028e1SSameer Pujar admaif->soc_data->cmpnt,
1007f74028e1SSameer Pujar admaif->soc_data->dais,
1008f74028e1SSameer Pujar admaif->soc_data->num_ch);
1009f74028e1SSameer Pujar if (err) {
1010f74028e1SSameer Pujar dev_err(&pdev->dev,
1011f74028e1SSameer Pujar "can't register ADMAIF component, err: %d\n", err);
1012f74028e1SSameer Pujar return err;
1013f74028e1SSameer Pujar }
1014f74028e1SSameer Pujar
1015f74028e1SSameer Pujar pm_runtime_enable(&pdev->dev);
1016f74028e1SSameer Pujar
1017f74028e1SSameer Pujar return 0;
1018f74028e1SSameer Pujar }
1019f74028e1SSameer Pujar
tegra_admaif_remove(struct platform_device * pdev)10208097e8afSUwe Kleine-König static void tegra_admaif_remove(struct platform_device *pdev)
1021f74028e1SSameer Pujar {
10224a91fe4cSSheetal tegra_isomgr_adma_unregister(&pdev->dev);
1023f74028e1SSameer Pujar pm_runtime_disable(&pdev->dev);
1024f74028e1SSameer Pujar }
1025f74028e1SSameer Pujar
1026f74028e1SSameer Pujar static const struct dev_pm_ops tegra_admaif_pm_ops = {
1027083c6a6fSTakashi Iwai RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
1028f74028e1SSameer Pujar tegra_admaif_runtime_resume, NULL)
1029083c6a6fSTakashi Iwai SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
1030f74028e1SSameer Pujar };
1031f74028e1SSameer Pujar
1032f74028e1SSameer Pujar static struct platform_driver tegra_admaif_driver = {
1033f74028e1SSameer Pujar .probe = tegra_admaif_probe,
1034130af75bSUwe Kleine-König .remove = tegra_admaif_remove,
1035f74028e1SSameer Pujar .driver = {
1036f74028e1SSameer Pujar .name = "tegra210-admaif",
1037f74028e1SSameer Pujar .of_match_table = tegra_admaif_of_match,
1038083c6a6fSTakashi Iwai .pm = pm_ptr(&tegra_admaif_pm_ops),
1039f74028e1SSameer Pujar },
1040f74028e1SSameer Pujar };
1041f74028e1SSameer Pujar module_platform_driver(tegra_admaif_driver);
1042f74028e1SSameer Pujar
1043f74028e1SSameer Pujar MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
1044f74028e1SSameer Pujar MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
1045f74028e1SSameer Pujar MODULE_LICENSE("GPL v2");
1046