2 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
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.
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.
13 * lpass-cpu.c -- ALSA SoC CPU DAI driver for QTi LPASS
16 #include <linux/clk.h>
17 #include <linux/kernel.h>
18 #include <linux/module.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"
30 static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
31 unsigned int freq
, int dir
)
33 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
36 ret
= clk_set_rate(drvdata
->mi2s_osr_clk
[dai
->driver
->id
], freq
);
38 dev_err(dai
->dev
, "error setting mi2s osrclk to %u: %d\n",
44 static int lpass_cpu_daiops_startup(struct snd_pcm_substream
*substream
,
45 struct snd_soc_dai
*dai
)
47 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
50 ret
= clk_prepare_enable(drvdata
->mi2s_osr_clk
[dai
->driver
->id
]);
52 dev_err(dai
->dev
, "error in enabling mi2s osr clk: %d\n", ret
);
56 ret
= clk_prepare_enable(drvdata
->mi2s_bit_clk
[dai
->driver
->id
]);
58 dev_err(dai
->dev
, "error in enabling mi2s bit clk: %d\n", ret
);
59 clk_disable_unprepare(drvdata
->mi2s_osr_clk
[dai
->driver
->id
]);
66 static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream
*substream
,
67 struct snd_soc_dai
*dai
)
69 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
71 clk_disable_unprepare(drvdata
->mi2s_bit_clk
[dai
->driver
->id
]);
73 clk_disable_unprepare(drvdata
->mi2s_osr_clk
[dai
->driver
->id
]);
76 static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream
*substream
,
77 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
79 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
80 snd_pcm_format_t format
= params_format(params
);
81 unsigned int channels
= params_channels(params
);
82 unsigned int rate
= params_rate(params
);
86 bitwidth
= snd_pcm_format_width(format
);
88 dev_err(dai
->dev
, "invalid bit width given: %d\n", bitwidth
);
92 regval
= LPAIF_I2SCTL_LOOPBACK_DISABLE
|
93 LPAIF_I2SCTL_WSSRC_INTERNAL
;
97 regval
|= LPAIF_I2SCTL_BITWIDTH_16
;
100 regval
|= LPAIF_I2SCTL_BITWIDTH_24
;
103 regval
|= LPAIF_I2SCTL_BITWIDTH_32
;
106 dev_err(dai
->dev
, "invalid bitwidth given: %d\n", bitwidth
);
110 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
113 regval
|= LPAIF_I2SCTL_SPKMODE_SD0
;
114 regval
|= LPAIF_I2SCTL_SPKMONO_MONO
;
117 regval
|= LPAIF_I2SCTL_SPKMODE_SD0
;
118 regval
|= LPAIF_I2SCTL_SPKMONO_STEREO
;
121 regval
|= LPAIF_I2SCTL_SPKMODE_QUAD01
;
122 regval
|= LPAIF_I2SCTL_SPKMONO_STEREO
;
125 regval
|= LPAIF_I2SCTL_SPKMODE_6CH
;
126 regval
|= LPAIF_I2SCTL_SPKMONO_STEREO
;
129 regval
|= LPAIF_I2SCTL_SPKMODE_8CH
;
130 regval
|= LPAIF_I2SCTL_SPKMONO_STEREO
;
133 dev_err(dai
->dev
, "invalid channels given: %u\n",
140 regval
|= LPAIF_I2SCTL_MICMODE_SD0
;
141 regval
|= LPAIF_I2SCTL_MICMONO_MONO
;
144 regval
|= LPAIF_I2SCTL_MICMODE_SD0
;
145 regval
|= LPAIF_I2SCTL_MICMONO_STEREO
;
148 regval
|= LPAIF_I2SCTL_MICMODE_QUAD01
;
149 regval
|= LPAIF_I2SCTL_MICMONO_STEREO
;
152 regval
|= LPAIF_I2SCTL_MICMODE_6CH
;
153 regval
|= LPAIF_I2SCTL_MICMONO_STEREO
;
156 regval
|= LPAIF_I2SCTL_MICMODE_8CH
;
157 regval
|= LPAIF_I2SCTL_MICMONO_STEREO
;
160 dev_err(dai
->dev
, "invalid channels given: %u\n",
166 ret
= regmap_write(drvdata
->lpaif_map
,
167 LPAIF_I2SCTL_REG(drvdata
->variant
, dai
->driver
->id
),
170 dev_err(dai
->dev
, "error writing to i2sctl reg: %d\n", ret
);
174 ret
= clk_set_rate(drvdata
->mi2s_bit_clk
[dai
->driver
->id
],
175 rate
* bitwidth
* 2);
177 dev_err(dai
->dev
, "error setting mi2s bitclk to %u: %d\n",
178 rate
* bitwidth
* 2, ret
);
185 static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream
*substream
,
186 struct snd_soc_dai
*dai
)
188 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
191 ret
= regmap_write(drvdata
->lpaif_map
,
192 LPAIF_I2SCTL_REG(drvdata
->variant
, dai
->driver
->id
),
195 dev_err(dai
->dev
, "error writing to i2sctl reg: %d\n", ret
);
200 static int lpass_cpu_daiops_prepare(struct snd_pcm_substream
*substream
,
201 struct snd_soc_dai
*dai
)
203 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
205 unsigned int val
, mask
;
207 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
208 val
= LPAIF_I2SCTL_SPKEN_ENABLE
;
209 mask
= LPAIF_I2SCTL_SPKEN_MASK
;
211 val
= LPAIF_I2SCTL_MICEN_ENABLE
;
212 mask
= LPAIF_I2SCTL_MICEN_MASK
;
215 ret
= regmap_update_bits(drvdata
->lpaif_map
,
216 LPAIF_I2SCTL_REG(drvdata
->variant
, dai
->driver
->id
),
219 dev_err(dai
->dev
, "error writing to i2sctl reg: %d\n", ret
);
224 static int lpass_cpu_daiops_trigger(struct snd_pcm_substream
*substream
,
225 int cmd
, struct snd_soc_dai
*dai
)
227 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
229 unsigned int val
, mask
;
232 case SNDRV_PCM_TRIGGER_START
:
233 case SNDRV_PCM_TRIGGER_RESUME
:
234 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
235 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
236 val
= LPAIF_I2SCTL_SPKEN_ENABLE
;
237 mask
= LPAIF_I2SCTL_SPKEN_MASK
;
239 val
= LPAIF_I2SCTL_MICEN_ENABLE
;
240 mask
= LPAIF_I2SCTL_MICEN_MASK
;
243 ret
= regmap_update_bits(drvdata
->lpaif_map
,
244 LPAIF_I2SCTL_REG(drvdata
->variant
,
248 dev_err(dai
->dev
, "error writing to i2sctl reg: %d\n",
251 case SNDRV_PCM_TRIGGER_STOP
:
252 case SNDRV_PCM_TRIGGER_SUSPEND
:
253 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
254 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
255 val
= LPAIF_I2SCTL_SPKEN_DISABLE
;
256 mask
= LPAIF_I2SCTL_SPKEN_MASK
;
258 val
= LPAIF_I2SCTL_MICEN_DISABLE
;
259 mask
= LPAIF_I2SCTL_MICEN_MASK
;
262 ret
= regmap_update_bits(drvdata
->lpaif_map
,
263 LPAIF_I2SCTL_REG(drvdata
->variant
,
267 dev_err(dai
->dev
, "error writing to i2sctl reg: %d\n",
275 const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops
= {
276 .set_sysclk
= lpass_cpu_daiops_set_sysclk
,
277 .startup
= lpass_cpu_daiops_startup
,
278 .shutdown
= lpass_cpu_daiops_shutdown
,
279 .hw_params
= lpass_cpu_daiops_hw_params
,
280 .hw_free
= lpass_cpu_daiops_hw_free
,
281 .prepare
= lpass_cpu_daiops_prepare
,
282 .trigger
= lpass_cpu_daiops_trigger
,
284 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops
);
286 int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai
*dai
)
288 struct lpass_data
*drvdata
= snd_soc_dai_get_drvdata(dai
);
291 /* ensure audio hardware is disabled */
292 ret
= regmap_write(drvdata
->lpaif_map
,
293 LPAIF_I2SCTL_REG(drvdata
->variant
, dai
->driver
->id
), 0);
295 dev_err(dai
->dev
, "error writing to i2sctl reg: %d\n", ret
);
299 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe
);
301 static const struct snd_soc_component_driver lpass_cpu_comp_driver
= {
305 static bool lpass_cpu_regmap_writeable(struct device
*dev
, unsigned int reg
)
307 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
308 struct lpass_variant
*v
= drvdata
->variant
;
311 for (i
= 0; i
< v
->i2s_ports
; ++i
)
312 if (reg
== LPAIF_I2SCTL_REG(v
, i
))
315 for (i
= 0; i
< v
->irq_ports
; ++i
) {
316 if (reg
== LPAIF_IRQEN_REG(v
, i
))
318 if (reg
== LPAIF_IRQCLEAR_REG(v
, i
))
322 for (i
= 0; i
< v
->rdma_channels
; ++i
) {
323 if (reg
== LPAIF_RDMACTL_REG(v
, i
))
325 if (reg
== LPAIF_RDMABASE_REG(v
, i
))
327 if (reg
== LPAIF_RDMABUFF_REG(v
, i
))
329 if (reg
== LPAIF_RDMAPER_REG(v
, i
))
333 for (i
= 0; i
< v
->wrdma_channels
; ++i
) {
334 if (reg
== LPAIF_WRDMACTL_REG(v
, i
+ v
->wrdma_channel_start
))
336 if (reg
== LPAIF_WRDMABASE_REG(v
, i
+ v
->wrdma_channel_start
))
338 if (reg
== LPAIF_WRDMABUFF_REG(v
, i
+ v
->wrdma_channel_start
))
340 if (reg
== LPAIF_WRDMAPER_REG(v
, i
+ v
->wrdma_channel_start
))
347 static bool lpass_cpu_regmap_readable(struct device
*dev
, unsigned int reg
)
349 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
350 struct lpass_variant
*v
= drvdata
->variant
;
353 for (i
= 0; i
< v
->i2s_ports
; ++i
)
354 if (reg
== LPAIF_I2SCTL_REG(v
, i
))
357 for (i
= 0; i
< v
->irq_ports
; ++i
) {
358 if (reg
== LPAIF_IRQEN_REG(v
, i
))
360 if (reg
== LPAIF_IRQSTAT_REG(v
, i
))
364 for (i
= 0; i
< v
->rdma_channels
; ++i
) {
365 if (reg
== LPAIF_RDMACTL_REG(v
, i
))
367 if (reg
== LPAIF_RDMABASE_REG(v
, i
))
369 if (reg
== LPAIF_RDMABUFF_REG(v
, i
))
371 if (reg
== LPAIF_RDMACURR_REG(v
, i
))
373 if (reg
== LPAIF_RDMAPER_REG(v
, i
))
377 for (i
= 0; i
< v
->wrdma_channels
; ++i
) {
378 if (reg
== LPAIF_WRDMACTL_REG(v
, i
+ v
->wrdma_channel_start
))
380 if (reg
== LPAIF_WRDMABASE_REG(v
, i
+ v
->wrdma_channel_start
))
382 if (reg
== LPAIF_WRDMABUFF_REG(v
, i
+ v
->wrdma_channel_start
))
384 if (reg
== LPAIF_WRDMACURR_REG(v
, i
+ v
->wrdma_channel_start
))
386 if (reg
== LPAIF_WRDMAPER_REG(v
, i
+ v
->wrdma_channel_start
))
393 static bool lpass_cpu_regmap_volatile(struct device
*dev
, unsigned int reg
)
395 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
396 struct lpass_variant
*v
= drvdata
->variant
;
399 for (i
= 0; i
< v
->irq_ports
; ++i
)
400 if (reg
== LPAIF_IRQSTAT_REG(v
, i
))
403 for (i
= 0; i
< v
->rdma_channels
; ++i
)
404 if (reg
== LPAIF_RDMACURR_REG(v
, i
))
407 for (i
= 0; i
< v
->wrdma_channels
; ++i
)
408 if (reg
== LPAIF_WRDMACURR_REG(v
, i
+ v
->wrdma_channel_start
))
414 static struct regmap_config lpass_cpu_regmap_config
= {
418 .writeable_reg
= lpass_cpu_regmap_writeable
,
419 .readable_reg
= lpass_cpu_regmap_readable
,
420 .volatile_reg
= lpass_cpu_regmap_volatile
,
421 .cache_type
= REGCACHE_FLAT
,
424 int asoc_qcom_lpass_cpu_platform_probe(struct platform_device
*pdev
)
426 struct lpass_data
*drvdata
;
427 struct device_node
*dsp_of_node
;
428 struct resource
*res
;
429 struct lpass_variant
*variant
;
430 struct device
*dev
= &pdev
->dev
;
431 const struct of_device_id
*match
;
434 dsp_of_node
= of_parse_phandle(pdev
->dev
.of_node
, "qcom,adsp", 0);
436 dev_err(&pdev
->dev
, "DSP exists and holds audio resources\n");
440 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(struct lpass_data
),
444 platform_set_drvdata(pdev
, drvdata
);
446 match
= of_match_device(dev
->driver
->of_match_table
, dev
);
447 if (!match
|| !match
->data
)
450 drvdata
->variant
= (struct lpass_variant
*)match
->data
;
451 variant
= drvdata
->variant
;
453 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "lpass-lpaif");
455 drvdata
->lpaif
= devm_ioremap_resource(&pdev
->dev
, res
);
456 if (IS_ERR((void const __force
*)drvdata
->lpaif
)) {
457 dev_err(&pdev
->dev
, "error mapping reg resource: %ld\n",
458 PTR_ERR((void const __force
*)drvdata
->lpaif
));
459 return PTR_ERR((void const __force
*)drvdata
->lpaif
);
462 lpass_cpu_regmap_config
.max_register
= LPAIF_WRDMAPER_REG(variant
,
463 variant
->wrdma_channels
+
464 variant
->wrdma_channel_start
);
466 drvdata
->lpaif_map
= devm_regmap_init_mmio(&pdev
->dev
, drvdata
->lpaif
,
467 &lpass_cpu_regmap_config
);
468 if (IS_ERR(drvdata
->lpaif_map
)) {
469 dev_err(&pdev
->dev
, "error initializing regmap: %ld\n",
470 PTR_ERR(drvdata
->lpaif_map
));
471 return PTR_ERR(drvdata
->lpaif_map
);
477 for (i
= 0; i
< variant
->num_dai
; i
++) {
478 dai_id
= variant
->dai_driver
[i
].id
;
479 drvdata
->mi2s_osr_clk
[dai_id
] = devm_clk_get(&pdev
->dev
,
480 variant
->dai_osr_clk_names
[i
]);
481 if (IS_ERR(drvdata
->mi2s_osr_clk
[dai_id
])) {
483 "%s() error getting optional %s: %ld\n",
485 variant
->dai_osr_clk_names
[i
],
486 PTR_ERR(drvdata
->mi2s_osr_clk
[dai_id
]));
488 drvdata
->mi2s_osr_clk
[dai_id
] = NULL
;
491 drvdata
->mi2s_bit_clk
[dai_id
] = devm_clk_get(&pdev
->dev
,
492 variant
->dai_bit_clk_names
[i
]);
493 if (IS_ERR(drvdata
->mi2s_bit_clk
[dai_id
])) {
495 "error getting %s: %ld\n",
496 variant
->dai_bit_clk_names
[i
],
497 PTR_ERR(drvdata
->mi2s_bit_clk
[dai_id
]));
498 return PTR_ERR(drvdata
->mi2s_bit_clk
[dai_id
]);
502 drvdata
->ahbix_clk
= devm_clk_get(&pdev
->dev
, "ahbix-clk");
503 if (IS_ERR(drvdata
->ahbix_clk
)) {
504 dev_err(&pdev
->dev
, "error getting ahbix-clk: %ld\n",
505 PTR_ERR(drvdata
->ahbix_clk
));
506 return PTR_ERR(drvdata
->ahbix_clk
);
509 ret
= clk_set_rate(drvdata
->ahbix_clk
, LPASS_AHBIX_CLOCK_FREQUENCY
);
511 dev_err(&pdev
->dev
, "error setting rate on ahbix_clk: %d\n",
515 dev_dbg(&pdev
->dev
, "set ahbix_clk rate to %lu\n",
516 clk_get_rate(drvdata
->ahbix_clk
));
518 ret
= clk_prepare_enable(drvdata
->ahbix_clk
);
520 dev_err(&pdev
->dev
, "error enabling ahbix_clk: %d\n", ret
);
524 ret
= devm_snd_soc_register_component(&pdev
->dev
,
525 &lpass_cpu_comp_driver
,
529 dev_err(&pdev
->dev
, "error registering cpu driver: %d\n", ret
);
533 ret
= asoc_qcom_lpass_platform_register(pdev
);
535 dev_err(&pdev
->dev
, "error registering platform driver: %d\n",
543 clk_disable_unprepare(drvdata
->ahbix_clk
);
546 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe
);
548 int asoc_qcom_lpass_cpu_platform_remove(struct platform_device
*pdev
)
550 struct lpass_data
*drvdata
= platform_get_drvdata(pdev
);
552 if (drvdata
->variant
->exit
)
553 drvdata
->variant
->exit(pdev
);
555 clk_disable_unprepare(drvdata
->ahbix_clk
);
559 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove
);
561 MODULE_DESCRIPTION("QTi LPASS CPU Driver");
562 MODULE_LICENSE("GPL v2");