ASoC: tegra-virt: apbif stop playback fix
[linux-3.10.git] / sound / soc / tegra-virtual / tegra124_virt_apbif_slave.c
1 /*
2  * tegra124_virt_apbif_slave.c - Tegra APBIF slave 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 #include <linux/device.h>
19 #include <linux/io.h>
20 #include <linux/module.h>
21 #include <linux/of_platform.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/slab.h>
25 #include <sound/soc.h>
26 #include <sound/pcm_params.h>
27
28 #include "tegra_pcm_alt.h"
29 #include "tegra124_virt_apbif_slave.h"
30
31 #define DRV_NAME        "tegra124-virt-ahub-slave"
32
33 static int tegra124_virt_apbif_hw_params(struct snd_pcm_substream *substream,
34                                  struct snd_pcm_hw_params *params,
35                                  struct snd_soc_dai *dai)
36 {
37         struct device *dev = dai->dev;
38         struct tegra124_virt_apbif_slave *apbif_slave =
39                 snd_soc_dai_get_drvdata(dai);
40         struct tegra124_virt_apbif_slave_data *data = &apbif_slave->slave_data;
41         struct tegra124_virt_audio_cif *cif_conf = &data->cif;
42         struct slave_remap_add *phandle = &(data->phandle);
43         int ret = 0, value;
44
45         data->apbif_id = dai->id;
46
47         /* find amx channel for latest amixer settings */
48         tegra_find_amx_info((unsigned long)data);
49
50         /* initialize the audio cif */
51         cif_conf->audio_channels = params_channels(params);
52         cif_conf->client_channels = params_channels(params);
53
54         switch (params_format(params)) {
55         case SNDRV_PCM_FORMAT_S8:
56                 cif_conf->audio_bits = AUDIO_BITS_8;
57                 cif_conf->client_bits = AUDIO_BITS_8;
58                 break;
59         case SNDRV_PCM_FORMAT_S16_LE:
60                 cif_conf->audio_bits = AUDIO_BITS_16;
61                 cif_conf->client_bits = AUDIO_BITS_16;
62                 break;
63         case SNDRV_PCM_FORMAT_S24_LE:
64                 cif_conf->audio_bits = AUDIO_BITS_24;
65                 cif_conf->client_bits = AUDIO_BITS_24;
66                 break;
67         case SNDRV_PCM_FORMAT_S32_LE:
68                 cif_conf->audio_bits = AUDIO_BITS_32;
69                 cif_conf->client_bits = AUDIO_BITS_32;
70                 break;
71         default:
72                 dev_err(dev, "Wrong format!\n");
73                 return -EINVAL;
74         }
75         cif_conf->direction = substream->stream;
76         cif_conf->threshold = 0;
77         cif_conf->expand = 0;
78         cif_conf->stereo_conv = 0;
79         cif_conf->replicate = 0;
80         cif_conf->truncate = 0;
81         cif_conf->mono_conv = 0;
82
83         /* set the audio cif */
84         value = (cif_conf->threshold << 24) |
85                         ((cif_conf->audio_channels - 1) << 20) |
86                         ((cif_conf->client_channels - 1) << 16) |
87                         (cif_conf->audio_bits << 12) |
88                         (cif_conf->client_bits << 8) |
89                         (cif_conf->expand << 6) |
90                         (cif_conf->stereo_conv << 4) |
91                         (cif_conf->replicate << 3) |
92                         (cif_conf->direction << 2) |
93                         (cif_conf->truncate << 1) |
94                         (cif_conf->mono_conv << 0);
95
96         if (!cif_conf->direction)
97                 reg_write(phandle->apbif_base[data->apbif_id],
98                                   TEGRA_AHUB_CIF_TX_CTRL, value);
99         else
100                 reg_write(phandle->apbif_base[data->apbif_id],
101                                  TEGRA_AHUB_CIF_RX_CTRL, value);
102
103         return ret;
104 }
105
106 static void tegra124_virt_apbif_start_playback(struct snd_soc_dai *dai)
107 {
108         struct tegra124_virt_apbif_slave *apbif_slave =
109                 snd_soc_dai_get_drvdata(dai);
110         struct tegra124_virt_apbif_slave_data *data = &apbif_slave->slave_data;
111         struct slave_remap_add *phandle = &(data->phandle);
112         int value;
113
114         /* enable the amx in channel */
115         if (data->amx_id < AMX_MAX_INSTANCE) {
116                 value = reg_read(phandle->amx_base[data->amx_id],
117                                                 TEGRA_AMX_IN_CH_CTRL);
118                 value |= (TEGRA_AMX_IN_CH_ENABLE << data->amx_in_channel);
119                 reg_write(phandle->amx_base[data->amx_id],
120                                                 TEGRA_AMX_IN_CH_CTRL,   value);
121         }
122
123         /* enable APBIF TX bit */
124         value = reg_read(phandle->apbif_base[data->apbif_id],
125                                                 TEGRA_AHUB_CHANNEL_CTRL);
126         value |= TEGRA_AHUB_CHANNEL_CTRL_TX_EN;
127         value |= ((7 << TEGRA_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) |
128                                         TEGRA_AHUB_CHANNEL_CTRL_TX_PACK_EN |
129                                         TEGRA_AHUB_CHANNEL_CTRL_TX_PACK_16);
130         reg_write(phandle->apbif_base[data->apbif_id],
131                 TEGRA_AHUB_CHANNEL_CTRL, value);
132
133 }
134
135 static void tegra124_virt_apbif_stop_playback(struct snd_soc_dai *dai)
136 {
137         struct tegra124_virt_apbif_slave *apbif_slave =
138                 snd_soc_dai_get_drvdata(dai);
139         struct tegra124_virt_apbif_slave_data *data = &apbif_slave->slave_data;
140         struct slave_remap_add *phandle = &(data->phandle);
141         int value;
142
143         data->apbif_id = dai->id;
144         /* find amx channel for latest amixer settings */
145         tegra_find_amx_info((unsigned long)data);
146
147         /* disable the amx in channel */
148         if (data->amx_id < AMX_MAX_INSTANCE) {
149                 value = reg_read(phandle->amx_base[data->amx_id],
150                                                 TEGRA_AMX_IN_CH_CTRL);
151                 value &= ~(TEGRA_AMX_IN_CH_ENABLE << data->amx_in_channel);
152                 reg_write(phandle->amx_base[data->amx_id],
153                                                 TEGRA_AMX_IN_CH_CTRL,   value);
154         }
155
156         /* disable APBIF TX bit */
157         value = reg_read(phandle->apbif_base[data->apbif_id],
158                                         TEGRA_AHUB_CHANNEL_CTRL);
159         value &= ~(TEGRA_AHUB_CHANNEL_CTRL_TX_EN);
160         reg_write(phandle->apbif_base[data->apbif_id],
161                                         TEGRA_AHUB_CHANNEL_CTRL, value);
162 }
163
164 static void tegra124_virt_apbif_start_capture(struct snd_soc_dai *dai)
165 {
166         struct tegra124_virt_apbif_slave *apbif_slave =
167                 snd_soc_dai_get_drvdata(dai);
168         struct tegra124_virt_apbif_slave_data *data = &apbif_slave->slave_data;
169         struct slave_remap_add *phandle = &(data->phandle);
170         int value;
171
172         /*enable APBIF RX bit*/
173         value = reg_read(phandle->apbif_base[data->apbif_id],
174                                                 TEGRA_AHUB_CHANNEL_CTRL);
175         value |= TEGRA_AHUB_CHANNEL_CTRL_RX_EN;
176         value |= ((7 << TEGRA_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) |
177                                         TEGRA_AHUB_CHANNEL_CTRL_RX_PACK_EN |
178                                         TEGRA_AHUB_CHANNEL_CTRL_RX_PACK_16);
179         reg_write(phandle->apbif_base[data->apbif_id],
180                 TEGRA_AHUB_CHANNEL_CTRL, value);
181 }
182
183 static void tegra124_virt_apbif_stop_capture(struct snd_soc_dai *dai)
184 {
185         struct tegra124_virt_apbif_slave *apbif_slave =
186                 snd_soc_dai_get_drvdata(dai);
187         struct tegra124_virt_apbif_slave_data *data = &apbif_slave->slave_data;
188         struct slave_remap_add *phandle = &(data->phandle);
189         int value;
190
191         /* disable APBIF RX bit */
192         value = reg_read(phandle->apbif_base[data->apbif_id],
193                                                 TEGRA_AHUB_CHANNEL_CTRL);
194         value &= ~(TEGRA_AHUB_CHANNEL_CTRL_RX_EN);
195         reg_write(phandle->apbif_base[data->apbif_id],
196                 TEGRA_AHUB_CHANNEL_CTRL, value);
197 }
198
199 static int tegra124_virt_apbif_trigger(struct snd_pcm_substream *substream,
200                 int cmd, struct snd_soc_dai *dai)
201 {
202         switch (cmd) {
203         case SNDRV_PCM_TRIGGER_START:
204         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
205         case SNDRV_PCM_TRIGGER_RESUME:
206                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
207                         tegra124_virt_apbif_start_playback(dai);
208                 else
209                         tegra124_virt_apbif_start_capture(dai);
210                 break;
211         case SNDRV_PCM_TRIGGER_STOP:
212         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
213         case SNDRV_PCM_TRIGGER_SUSPEND:
214                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
215                         tegra124_virt_apbif_stop_playback(dai);
216                 else
217                         tegra124_virt_apbif_stop_capture(dai);
218                 break;
219         default:
220                 return -EINVAL;
221         }
222
223         return 0;
224 }
225
226 static struct snd_soc_dai_ops tegra124_virt_apbif_dai_ops = {
227         .hw_params      = tegra124_virt_apbif_hw_params,
228         .trigger        = tegra124_virt_apbif_trigger,
229 };
230
231 static int tegra124_virt_apbif_dai_probe(struct snd_soc_dai *dai)
232 {
233         struct tegra124_virt_apbif_slave *apbif =
234                 snd_soc_dai_get_drvdata(dai);
235
236         dai->capture_dma_data = &apbif->capture_dma_data[dai->id];
237         dai->playback_dma_data = &apbif->playback_dma_data[dai->id];
238
239         return 0;
240 }
241
242 #define APBIF_DAI(id)                                                   \
243         {                                                       \
244                 .name = "SLAVE APBIF" #id,                              \
245                 .probe = tegra124_virt_apbif_dai_probe,         \
246                 .playback = {                                   \
247                         .stream_name = "Playback " #id,         \
248                         .channels_min = 1,                      \
249                         .channels_max = 16,                     \
250                         .rates = SNDRV_PCM_RATE_8000_96000,     \
251                         .formats = SNDRV_PCM_FMTBIT_S8 | \
252                                 SNDRV_PCM_FMTBIT_S16_LE | \
253                                 SNDRV_PCM_FMTBIT_S24_LE | \
254                                 SNDRV_PCM_FMTBIT_S32_LE,        \
255                 },                                              \
256                 .capture = {                                    \
257                         .stream_name = "Capture " #id,          \
258                         .channels_min = 1,                      \
259                         .channels_max = 16,                     \
260                         .rates = SNDRV_PCM_RATE_8000_96000,     \
261                         .formats = SNDRV_PCM_FMTBIT_S8 | \
262                                 SNDRV_PCM_FMTBIT_S16_LE | \
263                                 SNDRV_PCM_FMTBIT_S24_LE | \
264                                 SNDRV_PCM_FMTBIT_S32_LE,        \
265                 },                                              \
266                 .ops = &tegra124_virt_apbif_dai_ops,                    \
267         }
268
269 static struct snd_soc_dai_driver tegra124_apbif_dais[] = {
270         APBIF_DAI(0),
271         APBIF_DAI(1),
272         APBIF_DAI(2),
273         APBIF_DAI(3),
274         APBIF_DAI(4),
275         APBIF_DAI(5),
276         APBIF_DAI(6),
277         APBIF_DAI(7),
278         APBIF_DAI(8),
279         APBIF_DAI(9),
280 };
281
282 static struct platform_device spdif_dit = {
283         .name = "spdif-dit",
284         .id = -1,
285 };
286
287 struct of_dev_auxdata tegra124_virt_apbif_slave_auxdata[] = {
288         OF_DEV_AUXDATA("nvidia,tegra124-virt-machine-slave", 0x0,
289                                 "tegra124-virt-machine-slave", NULL),
290         {}
291 };
292
293 static const struct snd_soc_component_driver tegra124_virt_apbif_dai_driver = {
294         .name           = DRV_NAME,
295 };
296
297 static const struct of_device_id tegra124_virt_apbif_virt_slave_of_match[] = {
298         { .compatible = "nvidia,tegra124-virt-ahub-slave", },
299         {},
300 };
301
302 static int tegra124_virt_apbif_probe(struct platform_device *pdev)
303 {
304         int i, ret;
305         struct tegra124_virt_apbif_slave *apbif_slave;
306         struct slave_remap_add *phandle;
307         u32 of_dma[20][2];
308
309         apbif_slave = devm_kzalloc(&pdev->dev,
310                                         sizeof(*apbif_slave),   GFP_KERNEL);
311         if (!apbif_slave) {
312                 dev_err(&pdev->dev, "Can't allocate tegra124_virt_apbif\n");
313                 ret = -ENOMEM;
314                 goto err;
315         }
316
317         dev_set_drvdata(&pdev->dev, apbif_slave);
318
319         platform_device_register(&spdif_dit);
320
321         apbif_slave->capture_dma_data = devm_kzalloc(&pdev->dev,
322                         sizeof(struct tegra_alt_pcm_dma_params) *
323                                 MAX_APBIF_IDS,
324                         GFP_KERNEL);
325         if (!apbif_slave->capture_dma_data) {
326                 dev_err(&pdev->dev, "Can't allocate tegra_alt_pcm_dma_params\n");
327                 ret = -ENOMEM;
328                 goto err;
329         }
330
331         apbif_slave->playback_dma_data = devm_kzalloc(&pdev->dev,
332                         sizeof(struct tegra_alt_pcm_dma_params) *
333                                 MAX_APBIF_IDS,
334                         GFP_KERNEL);
335         if (!apbif_slave->playback_dma_data) {
336                 dev_err(&pdev->dev, "Can't allocate tegra_alt_pcm_dma_params\n");
337                 ret = -ENOMEM;
338                 goto err;
339         }
340
341         if (of_property_read_u32_array(pdev->dev.of_node,
342                                 "dmas",
343                                 &of_dma[0][0],
344                                 MAX_APBIF_IDS * 2) < 0) {
345                         dev_err(&pdev->dev,
346                         "Missing property nvidia,dma-request-selector\n");
347                         ret = -ENODEV;
348                 goto err;
349         }
350
351         /* default DAI number is 4 */
352         for (i = 0; i < MAX_APBIF_IDS; i++) {
353                 if (i < APBIF_ID_4) {
354                         apbif_slave->playback_dma_data[i].addr =
355                         TEGRA_APBIF_BASE + TEGRA_APBIF_CHANNEL_TXFIFO +
356                         (i * TEGRA_APBIF_CHANNEL_TXFIFO_STRIDE);
357
358                         apbif_slave->capture_dma_data[i].addr =
359                         TEGRA_APBIF_BASE + TEGRA_APBIF_CHANNEL_RXFIFO +
360                         (i * TEGRA_APBIF_CHANNEL_RXFIFO_STRIDE);
361                 } else {
362                         apbif_slave->playback_dma_data[i].addr =
363                         TEGRA_APBIF2_BASE2 + TEGRA_APBIF_CHANNEL_TXFIFO +
364                         ((i - APBIF_ID_4) * TEGRA_APBIF_CHANNEL_TXFIFO_STRIDE);
365
366                         apbif_slave->capture_dma_data[i].addr =
367                         TEGRA_APBIF2_BASE2 + TEGRA_APBIF_CHANNEL_RXFIFO +
368                         ((i - APBIF_ID_4) * TEGRA_APBIF_CHANNEL_RXFIFO_STRIDE);
369                 }
370
371                 apbif_slave->playback_dma_data[i].wrap = 4;
372                 apbif_slave->playback_dma_data[i].width = 32;
373                 apbif_slave->playback_dma_data[i].req_sel =
374                         of_dma[(i * 2) + 1][1];
375
376                 if (of_property_read_string_index(pdev->dev.of_node,
377                         "dma-names",
378                         (i * 2) + 1,
379                         &apbif_slave->playback_dma_data[i].chan_name) < 0) {
380                                 dev_err(&pdev->dev,
381                                 "Missing property nvidia,dma-names\n");
382                                 ret = -ENODEV;
383                                 goto err;
384                 }
385
386                 apbif_slave->capture_dma_data[i].wrap = 4;
387                 apbif_slave->capture_dma_data[i].width = 32;
388                 apbif_slave->capture_dma_data[i].req_sel = of_dma[(i * 2)][1];
389                 if (of_property_read_string_index(pdev->dev.of_node,
390                         "dma-names",
391                         (i * 2),
392                         &apbif_slave->capture_dma_data[i].chan_name) < 0) {
393                                 dev_err(&pdev->dev,
394                                                                 "Missing property nvidia,dma-names\n");
395                                 ret = -ENODEV;
396                                 goto err;
397                 }
398         }
399
400         ret = snd_soc_register_component(&pdev->dev,
401                                         &tegra124_virt_apbif_dai_driver,
402                                         tegra124_apbif_dais,
403                                         ARRAY_SIZE(tegra124_apbif_dais));
404         if (ret) {
405                 dev_err(&pdev->dev, "Could not register DAIs %d: %d\n",
406                         i, ret);
407                 ret = -ENOMEM;
408                 goto err;
409         }
410
411         ret = tegra_alt_pcm_platform_register(&pdev->dev);
412         if (ret) {
413                 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
414                 goto err_unregister_dais;
415         }
416         phandle = &(apbif_slave->slave_data.phandle);
417
418         ret = create_ioremap(&pdev->dev, phandle);
419         if (ret)
420                         goto err_unregister_dais;
421
422         of_platform_populate(pdev->dev.of_node, NULL,
423                                         tegra124_virt_apbif_slave_auxdata,
424                                         &pdev->dev);
425
426         return 0;
427
428 err_unregister_dais:
429         snd_soc_unregister_component(&pdev->dev);
430 err:
431         return ret;
432 }
433
434 static int tegra124_virt_apbif_remove(struct platform_device *pdev)
435 {
436         struct tegra124_virt_apbif_slave *apbif_slave =
437                 dev_get_drvdata(&pdev->dev);
438         struct slave_remap_add *phandle = &(apbif_slave->slave_data.phandle);
439
440         remove_ioremap(&pdev->dev, phandle);
441
442         tegra_alt_pcm_platform_unregister(&pdev->dev);
443
444         snd_soc_unregister_component(&pdev->dev);
445
446         return 0;
447 }
448
449 static struct platform_driver tegra124_virt_apbif_virt_slave_driver = {
450         .probe = tegra124_virt_apbif_probe,
451         .remove = tegra124_virt_apbif_remove,
452         .driver = {
453                 .name = DRV_NAME,
454                 .owner = THIS_MODULE,
455                 .of_match_table =
456                         of_match_ptr(tegra124_virt_apbif_virt_slave_of_match),
457         },
458 };
459 module_platform_driver(tegra124_virt_apbif_virt_slave_driver);
460
461 MODULE_AUTHOR("Aniket Bahadarpurkar <aniketb@nvidia.com>");
462 MODULE_DESCRIPTION("Tegra124 virt APBIF Slave driver");
463 MODULE_LICENSE("GPL v2");
464 MODULE_DEVICE_TABLE(of, tegra124_virt_apbif_virt_slave_of_match);
465 MODULE_ALIAS("platform:" DRV_NAME);