ASoC: qcom: move ipq806x specific bits out of lpass driver.
[firefly-linux-kernel-4.4.55.git] / sound / soc / qcom / lpass-cpu.c
1 /*
2  * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 and
6  * only version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * lpass-cpu.c -- ALSA SoC CPU DAI driver for QTi LPASS
14  */
15
16 #include <linux/clk.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/of_device.h>
21 #include <linux/platform_device.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <linux/regmap.h>
25 #include <sound/soc.h>
26 #include <sound/soc-dai.h>
27 #include "lpass-lpaif-reg.h"
28 #include "lpass.h"
29
30 static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
31                 unsigned int freq, int dir)
32 {
33         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
34         int ret;
35
36         ret = clk_set_rate(drvdata->mi2s_osr_clk, freq);
37         if (ret)
38                 dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n",
39                                 __func__, freq, ret);
40
41         return ret;
42 }
43
44 static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream,
45                 struct snd_soc_dai *dai)
46 {
47         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
48         int ret;
49
50         ret = clk_prepare_enable(drvdata->mi2s_osr_clk);
51         if (ret) {
52                 dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n",
53                                 __func__, ret);
54                 return ret;
55         }
56
57         ret = clk_prepare_enable(drvdata->mi2s_bit_clk);
58         if (ret) {
59                 dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n",
60                                 __func__, ret);
61                 clk_disable_unprepare(drvdata->mi2s_osr_clk);
62                 return ret;
63         }
64
65         return 0;
66 }
67
68 static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream,
69                 struct snd_soc_dai *dai)
70 {
71         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
72
73         clk_disable_unprepare(drvdata->mi2s_bit_clk);
74         clk_disable_unprepare(drvdata->mi2s_osr_clk);
75 }
76
77 static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
78                 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
79 {
80         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
81         snd_pcm_format_t format = params_format(params);
82         unsigned int channels = params_channels(params);
83         unsigned int rate = params_rate(params);
84         unsigned int regval;
85         int bitwidth, ret;
86
87         bitwidth = snd_pcm_format_width(format);
88         if (bitwidth < 0) {
89                 dev_err(dai->dev, "%s() invalid bit width given: %d\n",
90                                 __func__, bitwidth);
91                 return bitwidth;
92         }
93
94         regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
95                         LPAIF_I2SCTL_WSSRC_INTERNAL;
96
97         switch (bitwidth) {
98         case 16:
99                 regval |= LPAIF_I2SCTL_BITWIDTH_16;
100                 break;
101         case 24:
102                 regval |= LPAIF_I2SCTL_BITWIDTH_24;
103                 break;
104         case 32:
105                 regval |= LPAIF_I2SCTL_BITWIDTH_32;
106                 break;
107         default:
108                 dev_err(dai->dev, "%s() invalid bitwidth given: %d\n",
109                                 __func__, bitwidth);
110                 return -EINVAL;
111         }
112
113         switch (channels) {
114         case 1:
115                 regval |= LPAIF_I2SCTL_SPKMODE_SD0;
116                 regval |= LPAIF_I2SCTL_SPKMONO_MONO;
117                 break;
118         case 2:
119                 regval |= LPAIF_I2SCTL_SPKMODE_SD0;
120                 regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
121                 break;
122         case 4:
123                 regval |= LPAIF_I2SCTL_SPKMODE_QUAD01;
124                 regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
125                 break;
126         case 6:
127                 regval |= LPAIF_I2SCTL_SPKMODE_6CH;
128                 regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
129                 break;
130         case 8:
131                 regval |= LPAIF_I2SCTL_SPKMODE_8CH;
132                 regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
133                 break;
134         default:
135                 dev_err(dai->dev, "%s() invalid channels given: %u\n",
136                                 __func__, channels);
137                 return -EINVAL;
138         }
139
140         ret = regmap_write(drvdata->lpaif_map,
141                            LPAIF_I2SCTL_REG(drvdata->variant,
142                            LPAIF_I2S_PORT_MI2S),
143                            regval);
144         if (ret) {
145                 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
146                                 __func__, ret);
147                 return ret;
148         }
149
150         ret = clk_set_rate(drvdata->mi2s_bit_clk, rate * bitwidth * 2);
151         if (ret) {
152                 dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n",
153                                 __func__, rate * bitwidth * 2, ret);
154                 return ret;
155         }
156
157         return 0;
158 }
159
160 static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream,
161                 struct snd_soc_dai *dai)
162 {
163         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
164         int ret;
165
166         ret = regmap_write(drvdata->lpaif_map,
167                            LPAIF_I2SCTL_REG(drvdata->variant,
168                            LPAIF_I2S_PORT_MI2S), 0);
169         if (ret)
170                 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
171                                 __func__, ret);
172
173         return ret;
174 }
175
176 static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
177                 struct snd_soc_dai *dai)
178 {
179         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
180         int ret;
181
182         ret = regmap_update_bits(drvdata->lpaif_map,
183                         LPAIF_I2SCTL_REG(drvdata->variant, LPAIF_I2S_PORT_MI2S),
184                         LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE);
185         if (ret)
186                 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
187                                 __func__, ret);
188
189         return ret;
190 }
191
192 static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
193                 int cmd, struct snd_soc_dai *dai)
194 {
195         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
196         int ret;
197
198         switch (cmd) {
199         case SNDRV_PCM_TRIGGER_START:
200         case SNDRV_PCM_TRIGGER_RESUME:
201         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
202                 ret = regmap_update_bits(drvdata->lpaif_map,
203                                 LPAIF_I2SCTL_REG(drvdata->variant,
204                                 LPAIF_I2S_PORT_MI2S),
205                                 LPAIF_I2SCTL_SPKEN_MASK,
206                                 LPAIF_I2SCTL_SPKEN_ENABLE);
207                 if (ret)
208                         dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
209                                         __func__, ret);
210                 break;
211         case SNDRV_PCM_TRIGGER_STOP:
212         case SNDRV_PCM_TRIGGER_SUSPEND:
213         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
214                 ret = regmap_update_bits(drvdata->lpaif_map,
215                                 LPAIF_I2SCTL_REG(drvdata->variant,
216                                 LPAIF_I2S_PORT_MI2S),
217                                 LPAIF_I2SCTL_SPKEN_MASK,
218                                 LPAIF_I2SCTL_SPKEN_DISABLE);
219                 if (ret)
220                         dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
221                                         __func__, ret);
222                 break;
223         }
224
225         return ret;
226 }
227
228 struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = {
229         .set_sysclk     = lpass_cpu_daiops_set_sysclk,
230         .startup        = lpass_cpu_daiops_startup,
231         .shutdown       = lpass_cpu_daiops_shutdown,
232         .hw_params      = lpass_cpu_daiops_hw_params,
233         .hw_free        = lpass_cpu_daiops_hw_free,
234         .prepare        = lpass_cpu_daiops_prepare,
235         .trigger        = lpass_cpu_daiops_trigger,
236 };
237 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops);
238
239 int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai)
240 {
241         struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
242         int ret;
243
244         /* ensure audio hardware is disabled */
245         ret = regmap_write(drvdata->lpaif_map,
246                            LPAIF_I2SCTL_REG(drvdata->variant,
247                            LPAIF_I2S_PORT_MI2S), 0);
248         if (ret)
249                 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
250                                 __func__, ret);
251
252         return ret;
253 }
254 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe);
255
256 static const struct snd_soc_component_driver lpass_cpu_comp_driver = {
257         .name = "lpass-cpu",
258 };
259
260 static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg)
261 {
262         struct lpass_data *drvdata = dev_get_drvdata(dev);
263         struct lpass_variant *v = drvdata->variant;
264         int i;
265
266         for (i = 0; i < v->i2s_ports; ++i)
267                 if (reg == LPAIF_I2SCTL_REG(v, i))
268                         return true;
269
270         for (i = 0; i < v->irq_ports; ++i) {
271                 if (reg == LPAIF_IRQEN_REG(v, i))
272                         return true;
273                 if (reg == LPAIF_IRQCLEAR_REG(v, i))
274                         return true;
275         }
276
277         for (i = 0; i < v->rdma_channels; ++i) {
278                 if (reg == LPAIF_RDMACTL_REG(v, i))
279                         return true;
280                 if (reg == LPAIF_RDMABASE_REG(v, i))
281                         return true;
282                 if (reg == LPAIF_RDMABUFF_REG(v, i))
283                         return true;
284                 if (reg == LPAIF_RDMAPER_REG(v, i))
285                         return true;
286         }
287
288         return false;
289 }
290
291 static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg)
292 {
293         struct lpass_data *drvdata = dev_get_drvdata(dev);
294         struct lpass_variant *v = drvdata->variant;
295         int i;
296
297         for (i = 0; i < v->i2s_ports; ++i)
298                 if (reg == LPAIF_I2SCTL_REG(v, i))
299                         return true;
300
301         for (i = 0; i < v->irq_ports; ++i) {
302                 if (reg == LPAIF_IRQEN_REG(v, i))
303                         return true;
304                 if (reg == LPAIF_IRQSTAT_REG(v, i))
305                         return true;
306         }
307
308         for (i = 0; i < v->rdma_channels; ++i) {
309                 if (reg == LPAIF_RDMACTL_REG(v, i))
310                         return true;
311                 if (reg == LPAIF_RDMABASE_REG(v, i))
312                         return true;
313                 if (reg == LPAIF_RDMABUFF_REG(v, i))
314                         return true;
315                 if (reg == LPAIF_RDMACURR_REG(v, i))
316                         return true;
317                 if (reg == LPAIF_RDMAPER_REG(v, i))
318                         return true;
319         }
320
321         return false;
322 }
323
324 static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
325 {
326         struct lpass_data *drvdata = dev_get_drvdata(dev);
327         struct lpass_variant *v = drvdata->variant;
328         int i;
329
330         for (i = 0; i < v->irq_ports; ++i)
331                 if (reg == LPAIF_IRQSTAT_REG(v, i))
332                         return true;
333
334         for (i = 0; i < v->rdma_channels; ++i)
335                 if (reg == LPAIF_RDMACURR_REG(v, i))
336                         return true;
337
338         return false;
339 }
340
341 static struct regmap_config lpass_cpu_regmap_config = {
342         .reg_bits = 32,
343         .reg_stride = 4,
344         .val_bits = 32,
345         .writeable_reg = lpass_cpu_regmap_writeable,
346         .readable_reg = lpass_cpu_regmap_readable,
347         .volatile_reg = lpass_cpu_regmap_volatile,
348         .cache_type = REGCACHE_FLAT,
349 };
350
351 int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
352 {
353         struct lpass_data *drvdata;
354         struct device_node *dsp_of_node;
355         struct resource *res;
356         struct lpass_variant *variant;
357         struct device *dev = &pdev->dev;
358         const struct of_device_id *match;
359         int ret;
360
361         dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0);
362         if (dsp_of_node) {
363                 dev_err(&pdev->dev, "%s() DSP exists and holds audio resources\n",
364                                 __func__);
365                 return -EBUSY;
366         }
367
368         drvdata = devm_kzalloc(&pdev->dev, sizeof(struct lpass_data),
369                         GFP_KERNEL);
370         if (!drvdata)
371                 return -ENOMEM;
372         platform_set_drvdata(pdev, drvdata);
373
374         match = of_match_device(dev->driver->of_match_table, dev);
375         if (!match || !match->data)
376                 return -EINVAL;
377
378         drvdata->variant = (struct lpass_variant *)match->data;
379         variant = drvdata->variant;
380
381         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif");
382
383         drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res);
384         if (IS_ERR((void const __force *)drvdata->lpaif)) {
385                 dev_err(&pdev->dev, "%s() error mapping reg resource: %ld\n",
386                                 __func__,
387                                 PTR_ERR((void const __force *)drvdata->lpaif));
388                 return PTR_ERR((void const __force *)drvdata->lpaif);
389         }
390
391         lpass_cpu_regmap_config.max_register = LPAIF_RDMAPER_REG(variant,
392                                                 variant->rdma_channels);
393
394         drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif,
395                         &lpass_cpu_regmap_config);
396         if (IS_ERR(drvdata->lpaif_map)) {
397                 dev_err(&pdev->dev, "%s() error initializing regmap: %ld\n",
398                                 __func__, PTR_ERR(drvdata->lpaif_map));
399                 return PTR_ERR(drvdata->lpaif_map);
400         }
401
402         if (variant->init)
403                 variant->init(pdev);
404
405         drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk");
406         if (IS_ERR(drvdata->mi2s_osr_clk)) {
407                 dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n",
408                                 __func__, PTR_ERR(drvdata->mi2s_osr_clk));
409                 return PTR_ERR(drvdata->mi2s_osr_clk);
410         }
411
412         drvdata->mi2s_bit_clk = devm_clk_get(&pdev->dev, "mi2s-bit-clk");
413         if (IS_ERR(drvdata->mi2s_bit_clk)) {
414                 dev_err(&pdev->dev, "%s() error getting mi2s-bit-clk: %ld\n",
415                                 __func__, PTR_ERR(drvdata->mi2s_bit_clk));
416                 return PTR_ERR(drvdata->mi2s_bit_clk);
417         }
418
419         drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
420         if (IS_ERR(drvdata->ahbix_clk)) {
421                 dev_err(&pdev->dev, "%s() error getting ahbix-clk: %ld\n",
422                                 __func__, PTR_ERR(drvdata->ahbix_clk));
423                 return PTR_ERR(drvdata->ahbix_clk);
424         }
425
426         ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY);
427         if (ret) {
428                 dev_err(&pdev->dev, "%s() error setting rate on ahbix_clk: %d\n",
429                                 __func__, ret);
430                 return ret;
431         }
432         dev_dbg(&pdev->dev, "%s() set ahbix_clk rate to %lu\n", __func__,
433                         clk_get_rate(drvdata->ahbix_clk));
434
435         ret = clk_prepare_enable(drvdata->ahbix_clk);
436         if (ret) {
437                 dev_err(&pdev->dev, "%s() error enabling ahbix_clk: %d\n",
438                                 __func__, ret);
439                 return ret;
440         }
441
442         ret = devm_snd_soc_register_component(&pdev->dev,
443                                               &lpass_cpu_comp_driver,
444                                               variant->dai_driver,
445                                               variant->num_dai);
446         if (ret) {
447                 dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n",
448                                 __func__, ret);
449                 goto err_clk;
450         }
451
452         ret = asoc_qcom_lpass_platform_register(pdev);
453         if (ret) {
454                 dev_err(&pdev->dev, "%s() error registering platform driver: %d\n",
455                                 __func__, ret);
456                 goto err_clk;
457         }
458
459         return 0;
460
461 err_clk:
462         clk_disable_unprepare(drvdata->ahbix_clk);
463         return ret;
464 }
465 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe);
466
467 int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev)
468 {
469         struct lpass_data *drvdata = platform_get_drvdata(pdev);
470
471         if (drvdata->variant->exit)
472                 drvdata->variant->exit(pdev);
473
474         clk_disable_unprepare(drvdata->ahbix_clk);
475
476         return 0;
477 }
478 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove);