aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2015-05-16 08:32:17 -0400
committerMark Brown <broonie@kernel.org>2015-05-21 16:12:30 -0400
commit9bae4880acee1cd7340d0566b55b927f92de89fb (patch)
tree18237c3cf8cecfb86bc1ebf07f3a30dbb5717a8f
parenta7310c496f376b945e7e61f64d69c9c0a93ee1ee (diff)
ASoC: qcom: move ipq806x specific bits out of lpass driver.
This patch tries to make the lpass driver more generic by moving the ipq806x specific bits out of the cpu and platform driver, also allows the SOC specific drivers to add the correct register offsets. This patch also renames the register definition header file into more generic header file. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Tested-by: Kenneth Westfield <kwestfie@codeaurora.org> Acked-by: Kenneth Westfield <kwestfie@codeaurora.org> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/qcom/Kconfig9
-rw-r--r--sound/soc/qcom/Makefile2
-rw-r--r--sound/soc/qcom/lpass-cpu.c157
-rw-r--r--sound/soc/qcom/lpass-ipq806x.c96
-rw-r--r--sound/soc/qcom/lpass-lpaif-reg.h (renamed from sound/soc/qcom/lpass-lpaif-ipq806x.h)92
-rw-r--r--sound/soc/qcom/lpass-platform.c49
-rw-r--r--sound/soc/qcom/lpass.h28
7 files changed, 261 insertions, 172 deletions
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index b07f183fc47f..b30c2baa7501 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -12,11 +12,16 @@ config SND_SOC_LPASS_PLATFORM
12 tristate 12 tristate
13 select REGMAP_MMIO 13 select REGMAP_MMIO
14 14
15config SND_SOC_LPASS_IPQ806X
16 tristate
17 depends on SND_SOC_QCOM
18 select SND_SOC_LPASS_CPU
19 select SND_SOC_LPASS_PLATFORM
20
15config SND_SOC_STORM 21config SND_SOC_STORM
16 tristate "ASoC I2S support for Storm boards" 22 tristate "ASoC I2S support for Storm boards"
17 depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST 23 depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST
18 select SND_SOC_LPASS_CPU 24 select SND_SOC_LPASS_IPQ806X
19 select SND_SOC_LPASS_PLATFORM
20 select SND_SOC_MAX98357A 25 select SND_SOC_MAX98357A
21 help 26 help
22 Say Y or M if you want add support for SoC audio on the 27 Say Y or M if you want add support for SoC audio on the
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
index c5ce96c761c4..f8aab91c9117 100644
--- a/sound/soc/qcom/Makefile
+++ b/sound/soc/qcom/Makefile
@@ -1,9 +1,11 @@
1# Platform 1# Platform
2snd-soc-lpass-cpu-objs := lpass-cpu.o 2snd-soc-lpass-cpu-objs := lpass-cpu.o
3snd-soc-lpass-platform-objs := lpass-platform.o 3snd-soc-lpass-platform-objs := lpass-platform.o
4snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o
4 5
5obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o 6obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o
6obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o 7obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
8obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o
7 9
8# Machine 10# Machine
9snd-soc-storm-objs := storm.o 11snd-soc-storm-objs := storm.o
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index 40842958f423..5544bfc57357 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -17,14 +17,14 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_device.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <sound/pcm.h> 22#include <sound/pcm.h>
22#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
23#include <linux/regmap.h> 24#include <linux/regmap.h>
24#include <sound/soc.h> 25#include <sound/soc.h>
25#include <sound/soc-dai.h> 26#include <sound/soc-dai.h>
26 27#include "lpass-lpaif-reg.h"
27#include "lpass-lpaif-ipq806x.h"
28#include "lpass.h" 28#include "lpass.h"
29 29
30static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, 30static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
@@ -138,7 +138,9 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
138 } 138 }
139 139
140 ret = regmap_write(drvdata->lpaif_map, 140 ret = regmap_write(drvdata->lpaif_map,
141 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), regval); 141 LPAIF_I2SCTL_REG(drvdata->variant,
142 LPAIF_I2S_PORT_MI2S),
143 regval);
142 if (ret) { 144 if (ret) {
143 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 145 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
144 __func__, ret); 146 __func__, ret);
@@ -162,7 +164,8 @@ static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream,
162 int ret; 164 int ret;
163 165
164 ret = regmap_write(drvdata->lpaif_map, 166 ret = regmap_write(drvdata->lpaif_map,
165 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); 167 LPAIF_I2SCTL_REG(drvdata->variant,
168 LPAIF_I2S_PORT_MI2S), 0);
166 if (ret) 169 if (ret)
167 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 170 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
168 __func__, ret); 171 __func__, ret);
@@ -177,7 +180,7 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
177 int ret; 180 int ret;
178 181
179 ret = regmap_update_bits(drvdata->lpaif_map, 182 ret = regmap_update_bits(drvdata->lpaif_map,
180 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 183 LPAIF_I2SCTL_REG(drvdata->variant, LPAIF_I2S_PORT_MI2S),
181 LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); 184 LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE);
182 if (ret) 185 if (ret)
183 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 186 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
@@ -197,7 +200,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
197 case SNDRV_PCM_TRIGGER_RESUME: 200 case SNDRV_PCM_TRIGGER_RESUME:
198 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 201 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
199 ret = regmap_update_bits(drvdata->lpaif_map, 202 ret = regmap_update_bits(drvdata->lpaif_map,
200 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 203 LPAIF_I2SCTL_REG(drvdata->variant,
204 LPAIF_I2S_PORT_MI2S),
201 LPAIF_I2SCTL_SPKEN_MASK, 205 LPAIF_I2SCTL_SPKEN_MASK,
202 LPAIF_I2SCTL_SPKEN_ENABLE); 206 LPAIF_I2SCTL_SPKEN_ENABLE);
203 if (ret) 207 if (ret)
@@ -208,7 +212,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
208 case SNDRV_PCM_TRIGGER_SUSPEND: 212 case SNDRV_PCM_TRIGGER_SUSPEND:
209 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 213 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
210 ret = regmap_update_bits(drvdata->lpaif_map, 214 ret = regmap_update_bits(drvdata->lpaif_map,
211 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 215 LPAIF_I2SCTL_REG(drvdata->variant,
216 LPAIF_I2S_PORT_MI2S),
212 LPAIF_I2SCTL_SPKEN_MASK, 217 LPAIF_I2SCTL_SPKEN_MASK,
213 LPAIF_I2SCTL_SPKEN_DISABLE); 218 LPAIF_I2SCTL_SPKEN_DISABLE);
214 if (ret) 219 if (ret)
@@ -220,7 +225,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
220 return ret; 225 return ret;
221} 226}
222 227
223static struct snd_soc_dai_ops lpass_cpu_dai_ops = { 228struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = {
224 .set_sysclk = lpass_cpu_daiops_set_sysclk, 229 .set_sysclk = lpass_cpu_daiops_set_sysclk,
225 .startup = lpass_cpu_daiops_startup, 230 .startup = lpass_cpu_daiops_startup,
226 .shutdown = lpass_cpu_daiops_shutdown, 231 .shutdown = lpass_cpu_daiops_shutdown,
@@ -229,41 +234,24 @@ static struct snd_soc_dai_ops lpass_cpu_dai_ops = {
229 .prepare = lpass_cpu_daiops_prepare, 234 .prepare = lpass_cpu_daiops_prepare,
230 .trigger = lpass_cpu_daiops_trigger, 235 .trigger = lpass_cpu_daiops_trigger,
231}; 236};
237EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops);
232 238
233static int lpass_cpu_dai_probe(struct snd_soc_dai *dai) 239int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai)
234{ 240{
235 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 241 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
236 int ret; 242 int ret;
237 243
238 /* ensure audio hardware is disabled */ 244 /* ensure audio hardware is disabled */
239 ret = regmap_write(drvdata->lpaif_map, 245 ret = regmap_write(drvdata->lpaif_map,
240 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); 246 LPAIF_I2SCTL_REG(drvdata->variant,
247 LPAIF_I2S_PORT_MI2S), 0);
241 if (ret) 248 if (ret)
242 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 249 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
243 __func__, ret); 250 __func__, ret);
244 251
245 return ret; 252 return ret;
246} 253}
247 254EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe);
248static struct snd_soc_dai_driver lpass_cpu_dai_driver = {
249 .playback = {
250 .stream_name = "lpass-cpu-playback",
251 .formats = SNDRV_PCM_FMTBIT_S16 |
252 SNDRV_PCM_FMTBIT_S24 |
253 SNDRV_PCM_FMTBIT_S32,
254 .rates = SNDRV_PCM_RATE_8000 |
255 SNDRV_PCM_RATE_16000 |
256 SNDRV_PCM_RATE_32000 |
257 SNDRV_PCM_RATE_48000 |
258 SNDRV_PCM_RATE_96000,
259 .rate_min = 8000,
260 .rate_max = 96000,
261 .channels_min = 1,
262 .channels_max = 8,
263 },
264 .probe = &lpass_cpu_dai_probe,
265 .ops = &lpass_cpu_dai_ops,
266};
267 255
268static const struct snd_soc_component_driver lpass_cpu_comp_driver = { 256static const struct snd_soc_component_driver lpass_cpu_comp_driver = {
269 .name = "lpass-cpu", 257 .name = "lpass-cpu",
@@ -271,27 +259,29 @@ static const struct snd_soc_component_driver lpass_cpu_comp_driver = {
271 259
272static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) 260static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg)
273{ 261{
262 struct lpass_data *drvdata = dev_get_drvdata(dev);
263 struct lpass_variant *v = drvdata->variant;
274 int i; 264 int i;
275 265
276 for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) 266 for (i = 0; i < v->i2s_ports; ++i)
277 if (reg == LPAIF_I2SCTL_REG(i)) 267 if (reg == LPAIF_I2SCTL_REG(v, i))
278 return true; 268 return true;
279 269
280 for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { 270 for (i = 0; i < v->irq_ports; ++i) {
281 if (reg == LPAIF_IRQEN_REG(i)) 271 if (reg == LPAIF_IRQEN_REG(v, i))
282 return true; 272 return true;
283 if (reg == LPAIF_IRQCLEAR_REG(i)) 273 if (reg == LPAIF_IRQCLEAR_REG(v, i))
284 return true; 274 return true;
285 } 275 }
286 276
287 for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { 277 for (i = 0; i < v->rdma_channels; ++i) {
288 if (reg == LPAIF_RDMACTL_REG(i)) 278 if (reg == LPAIF_RDMACTL_REG(v, i))
289 return true; 279 return true;
290 if (reg == LPAIF_RDMABASE_REG(i)) 280 if (reg == LPAIF_RDMABASE_REG(v, i))
291 return true; 281 return true;
292 if (reg == LPAIF_RDMABUFF_REG(i)) 282 if (reg == LPAIF_RDMABUFF_REG(v, i))
293 return true; 283 return true;
294 if (reg == LPAIF_RDMAPER_REG(i)) 284 if (reg == LPAIF_RDMAPER_REG(v, i))
295 return true; 285 return true;
296 } 286 }
297 287
@@ -300,29 +290,31 @@ static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg)
300 290
301static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) 291static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg)
302{ 292{
293 struct lpass_data *drvdata = dev_get_drvdata(dev);
294 struct lpass_variant *v = drvdata->variant;
303 int i; 295 int i;
304 296
305 for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) 297 for (i = 0; i < v->i2s_ports; ++i)
306 if (reg == LPAIF_I2SCTL_REG(i)) 298 if (reg == LPAIF_I2SCTL_REG(v, i))
307 return true; 299 return true;
308 300
309 for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { 301 for (i = 0; i < v->irq_ports; ++i) {
310 if (reg == LPAIF_IRQEN_REG(i)) 302 if (reg == LPAIF_IRQEN_REG(v, i))
311 return true; 303 return true;
312 if (reg == LPAIF_IRQSTAT_REG(i)) 304 if (reg == LPAIF_IRQSTAT_REG(v, i))
313 return true; 305 return true;
314 } 306 }
315 307
316 for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { 308 for (i = 0; i < v->rdma_channels; ++i) {
317 if (reg == LPAIF_RDMACTL_REG(i)) 309 if (reg == LPAIF_RDMACTL_REG(v, i))
318 return true; 310 return true;
319 if (reg == LPAIF_RDMABASE_REG(i)) 311 if (reg == LPAIF_RDMABASE_REG(v, i))
320 return true; 312 return true;
321 if (reg == LPAIF_RDMABUFF_REG(i)) 313 if (reg == LPAIF_RDMABUFF_REG(v, i))
322 return true; 314 return true;
323 if (reg == LPAIF_RDMACURR_REG(i)) 315 if (reg == LPAIF_RDMACURR_REG(v, i))
324 return true; 316 return true;
325 if (reg == LPAIF_RDMAPER_REG(i)) 317 if (reg == LPAIF_RDMAPER_REG(v, i))
326 return true; 318 return true;
327 } 319 }
328 320
@@ -331,35 +323,39 @@ static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg)
331 323
332static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) 324static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
333{ 325{
326 struct lpass_data *drvdata = dev_get_drvdata(dev);
327 struct lpass_variant *v = drvdata->variant;
334 int i; 328 int i;
335 329
336 for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) 330 for (i = 0; i < v->irq_ports; ++i)
337 if (reg == LPAIF_IRQSTAT_REG(i)) 331 if (reg == LPAIF_IRQSTAT_REG(v, i))
338 return true; 332 return true;
339 333
340 for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) 334 for (i = 0; i < v->rdma_channels; ++i)
341 if (reg == LPAIF_RDMACURR_REG(i)) 335 if (reg == LPAIF_RDMACURR_REG(v, i))
342 return true; 336 return true;
343 337
344 return false; 338 return false;
345} 339}
346 340
347static const struct regmap_config lpass_cpu_regmap_config = { 341static struct regmap_config lpass_cpu_regmap_config = {
348 .reg_bits = 32, 342 .reg_bits = 32,
349 .reg_stride = 4, 343 .reg_stride = 4,
350 .val_bits = 32, 344 .val_bits = 32,
351 .max_register = LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MAX),
352 .writeable_reg = lpass_cpu_regmap_writeable, 345 .writeable_reg = lpass_cpu_regmap_writeable,
353 .readable_reg = lpass_cpu_regmap_readable, 346 .readable_reg = lpass_cpu_regmap_readable,
354 .volatile_reg = lpass_cpu_regmap_volatile, 347 .volatile_reg = lpass_cpu_regmap_volatile,
355 .cache_type = REGCACHE_FLAT, 348 .cache_type = REGCACHE_FLAT,
356}; 349};
357 350
358static int lpass_cpu_platform_probe(struct platform_device *pdev) 351int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
359{ 352{
360 struct lpass_data *drvdata; 353 struct lpass_data *drvdata;
361 struct device_node *dsp_of_node; 354 struct device_node *dsp_of_node;
362 struct resource *res; 355 struct resource *res;
356 struct lpass_variant *variant;
357 struct device *dev = &pdev->dev;
358 const struct of_device_id *match;
363 int ret; 359 int ret;
364 360
365 dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); 361 dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0);
@@ -375,6 +371,13 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev)
375 return -ENOMEM; 371 return -ENOMEM;
376 platform_set_drvdata(pdev, drvdata); 372 platform_set_drvdata(pdev, drvdata);
377 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
378 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); 381 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif");
379 382
380 drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); 383 drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res);
@@ -385,6 +388,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev)
385 return PTR_ERR((void const __force *)drvdata->lpaif); 388 return PTR_ERR((void const __force *)drvdata->lpaif);
386 } 389 }
387 390
391 lpass_cpu_regmap_config.max_register = LPAIF_RDMAPER_REG(variant,
392 variant->rdma_channels);
393
388 drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, 394 drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif,
389 &lpass_cpu_regmap_config); 395 &lpass_cpu_regmap_config);
390 if (IS_ERR(drvdata->lpaif_map)) { 396 if (IS_ERR(drvdata->lpaif_map)) {
@@ -393,6 +399,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev)
393 return PTR_ERR(drvdata->lpaif_map); 399 return PTR_ERR(drvdata->lpaif_map);
394 } 400 }
395 401
402 if (variant->init)
403 variant->init(pdev);
404
396 drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk"); 405 drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk");
397 if (IS_ERR(drvdata->mi2s_osr_clk)) { 406 if (IS_ERR(drvdata->mi2s_osr_clk)) {
398 dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n", 407 dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n",
@@ -431,7 +440,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev)
431 } 440 }
432 441
433 ret = devm_snd_soc_register_component(&pdev->dev, 442 ret = devm_snd_soc_register_component(&pdev->dev,
434 &lpass_cpu_comp_driver, &lpass_cpu_dai_driver, 1); 443 &lpass_cpu_comp_driver,
444 variant->dai_driver,
445 variant->num_dai);
435 if (ret) { 446 if (ret) {
436 dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", 447 dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n",
437 __func__, ret); 448 __func__, ret);
@@ -451,33 +462,17 @@ err_clk:
451 clk_disable_unprepare(drvdata->ahbix_clk); 462 clk_disable_unprepare(drvdata->ahbix_clk);
452 return ret; 463 return ret;
453} 464}
465EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe);
454 466
455static int lpass_cpu_platform_remove(struct platform_device *pdev) 467int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev)
456{ 468{
457 struct lpass_data *drvdata = platform_get_drvdata(pdev); 469 struct lpass_data *drvdata = platform_get_drvdata(pdev);
458 470
471 if (drvdata->variant->exit)
472 drvdata->variant->exit(pdev);
473
459 clk_disable_unprepare(drvdata->ahbix_clk); 474 clk_disable_unprepare(drvdata->ahbix_clk);
460 475
461 return 0; 476 return 0;
462} 477}
463 478EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove);
464#ifdef CONFIG_OF
465static const struct of_device_id lpass_cpu_device_id[] = {
466 { .compatible = "qcom,lpass-cpu" },
467 {}
468};
469MODULE_DEVICE_TABLE(of, lpass_cpu_device_id);
470#endif
471
472static struct platform_driver lpass_cpu_platform_driver = {
473 .driver = {
474 .name = "lpass-cpu",
475 .of_match_table = of_match_ptr(lpass_cpu_device_id),
476 },
477 .probe = lpass_cpu_platform_probe,
478 .remove = lpass_cpu_platform_remove,
479};
480module_platform_driver(lpass_cpu_platform_driver);
481
482MODULE_DESCRIPTION("QTi LPASS CPU Driver");
483MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c
new file mode 100644
index 000000000000..4a0e3fbb384b
--- /dev/null
+++ b/sound/soc/qcom/lpass-ipq806x.c
@@ -0,0 +1,96 @@
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-ipq806x.c -- ALSA SoC CPU DAI driver for QTi LPASS
14 * Splited out the IPQ8064 soc specific from lpass-cpu.c
15 */
16
17#include <linux/clk.h>
18#include <linux/device.h>
19#include <linux/err.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/platform_device.h>
24#include <sound/pcm.h>
25#include <sound/soc.h>
26#include <sound/soc-dai.h>
27
28#include "lpass-lpaif-reg.h"
29#include "lpass.h"
30
31enum lpaif_i2s_ports {
32 IPQ806X_LPAIF_I2S_PORT_CODEC_SPK,
33 IPQ806X_LPAIF_I2S_PORT_CODEC_MIC,
34 IPQ806X_LPAIF_I2S_PORT_SEC_SPK,
35 IPQ806X_LPAIF_I2S_PORT_SEC_MIC,
36 IPQ806X_LPAIF_I2S_PORT_MI2S,
37};
38
39enum lpaif_dma_channels {
40 IPQ806X_LPAIF_RDMA_CHAN_MI2S,
41 IPQ806X_LPAIF_RDMA_CHAN_PCM0,
42 IPQ806X_LPAIF_RDMA_CHAN_PCM1,
43};
44
45static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = {
46 .playback = {
47 .stream_name = "lpass-cpu-playback",
48 .formats = SNDRV_PCM_FMTBIT_S16 |
49 SNDRV_PCM_FMTBIT_S24 |
50 SNDRV_PCM_FMTBIT_S32,
51 .rates = SNDRV_PCM_RATE_8000 |
52 SNDRV_PCM_RATE_16000 |
53 SNDRV_PCM_RATE_32000 |
54 SNDRV_PCM_RATE_48000 |
55 SNDRV_PCM_RATE_96000,
56 .rate_min = 8000,
57 .rate_max = 96000,
58 .channels_min = 1,
59 .channels_max = 8,
60 },
61 .probe = &asoc_qcom_lpass_cpu_dai_probe,
62 .ops = &asoc_qcom_lpass_cpu_dai_ops,
63};
64
65struct lpass_variant ipq806x_data = {
66 .i2sctrl_reg_base = 0x0010,
67 .i2sctrl_reg_stride = 0x04,
68 .i2s_ports = 5,
69 .irq_reg_base = 0x3000,
70 .irq_reg_stride = 0x1000,
71 .irq_ports = 3,
72 .rdma_reg_base = 0x6000,
73 .rdma_reg_stride = 0x1000,
74 .rdma_channels = 4,
75 .dai_driver = &ipq806x_lpass_cpu_dai_driver,
76 .num_dai = 1,
77};
78
79static const struct of_device_id ipq806x_lpass_cpu_device_id[] = {
80 { .compatible = "qcom,lpass-cpu", .data = &ipq806x_data },
81 {}
82};
83MODULE_DEVICE_TABLE(of, ipq806x_lpass_cpu_device_id);
84
85static struct platform_driver ipq806x_lpass_cpu_platform_driver = {
86 .driver = {
87 .name = "lpass-cpu",
88 .of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id),
89 },
90 .probe = asoc_qcom_lpass_cpu_platform_probe,
91 .remove = asoc_qcom_lpass_cpu_platform_remove,
92};
93module_platform_driver(ipq806x_lpass_cpu_platform_driver);
94
95MODULE_DESCRIPTION("QTi LPASS CPU Driver");
96MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/lpass-lpaif-ipq806x.h b/sound/soc/qcom/lpass-lpaif-reg.h
index dc423b888842..95e22f131052 100644
--- a/sound/soc/qcom/lpass-lpaif-ipq806x.h
+++ b/sound/soc/qcom/lpass-lpaif-reg.h
@@ -9,37 +9,17 @@
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 *
13 * lpass-lpaif-ipq806x.h -- Definitions for the QTi LPAIF in the ipq806x LPASS
14 */ 12 */
15 13
16#ifndef __LPASS_LPAIF_H__ 14#ifndef __LPASS_LPAIF_REG_H__
17#define __LPASS_LPAIF_H__ 15#define __LPASS_LPAIF_REG_H__
18
19#define LPAIF_BANK_OFFSET 0x1000
20 16
21/* LPAIF I2S */ 17/* LPAIF I2S */
22 18
23#define LPAIF_I2SCTL_REG_BASE 0x0010 19#define LPAIF_I2SCTL_REG_ADDR(v, addr, port) \
24#define LPAIF_I2SCTL_REG_STRIDE 0x4 20 (v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port))
25#define LPAIF_I2SCTL_REG_ADDR(addr, port) \
26 (LPAIF_I2SCTL_REG_BASE + (addr) + (LPAIF_I2SCTL_REG_STRIDE * (port)))
27
28enum lpaif_i2s_ports {
29 LPAIF_I2S_PORT_MIN = 0,
30
31 LPAIF_I2S_PORT_CODEC_SPK = 0,
32 LPAIF_I2S_PORT_CODEC_MIC = 1,
33 LPAIF_I2S_PORT_SEC_SPK = 2,
34 LPAIF_I2S_PORT_SEC_MIC = 3,
35 LPAIF_I2S_PORT_MI2S = 4,
36
37 LPAIF_I2S_PORT_MAX = 4,
38 LPAIF_I2S_PORT_NUM = 5,
39};
40
41#define LPAIF_I2SCTL_REG(port) LPAIF_I2SCTL_REG_ADDR(0x0, (port))
42 21
22#define LPAIF_I2SCTL_REG(v, port) LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port))
43#define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 23#define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000
44#define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 24#define LPAIF_I2SCTL_LOOPBACK_SHIFT 15
45#define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) 25#define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
@@ -79,55 +59,36 @@ enum lpaif_i2s_ports {
79#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) 59#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
80 60
81/* LPAIF IRQ */ 61/* LPAIF IRQ */
62#define LPAIF_IRQ_REG_ADDR(v, addr, port) \
63 (v->irq_reg_base + (addr) + v->irq_reg_stride * (port))
82 64
83#define LPAIF_IRQ_REG_BASE 0x3000 65#define LPAIF_IRQ_PORT_HOST 0
84#define LPAIF_IRQ_REG_STRIDE 0x1000
85#define LPAIF_IRQ_REG_ADDR(addr, port) \
86 (LPAIF_IRQ_REG_BASE + (addr) + (LPAIF_IRQ_REG_STRIDE * (port)))
87
88enum lpaif_irq_ports {
89 LPAIF_IRQ_PORT_MIN = 0,
90 66
91 LPAIF_IRQ_PORT_HOST = 0, 67#define LPAIF_IRQEN_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x0, (port))
92 LPAIF_IRQ_PORT_ADSP = 1, 68#define LPAIF_IRQSTAT_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x4, (port))
93 69#define LPAIF_IRQCLEAR_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0xC, (port))
94 LPAIF_IRQ_PORT_MAX = 2,
95 LPAIF_IRQ_PORT_NUM = 3,
96};
97
98#define LPAIF_IRQEN_REG(port) LPAIF_IRQ_REG_ADDR(0x0, (port))
99#define LPAIF_IRQSTAT_REG(port) LPAIF_IRQ_REG_ADDR(0x4, (port))
100#define LPAIF_IRQCLEAR_REG(port) LPAIF_IRQ_REG_ADDR(0xC, (port))
101 70
102#define LPAIF_IRQ_BITSTRIDE 3 71#define LPAIF_IRQ_BITSTRIDE 3
72
103#define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan))) 73#define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan)))
104#define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan))) 74#define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan)))
105#define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan))) 75#define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan)))
76
106#define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan))) 77#define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan)))
107 78
108/* LPAIF DMA */ 79/* LPAIF DMA */
109 80
110#define LPAIF_RDMA_REG_BASE 0x6000 81#define LPAIF_RDMA_REG_ADDR(v, addr, chan) \
111#define LPAIF_RDMA_REG_STRIDE 0x1000 82 (v->rdma_reg_base + (addr) + v->rdma_reg_stride * (chan))
112#define LPAIF_RDMA_REG_ADDR(addr, chan) \
113 (LPAIF_RDMA_REG_BASE + (addr) + (LPAIF_RDMA_REG_STRIDE * (chan)))
114
115enum lpaif_dma_channels {
116 LPAIF_RDMA_CHAN_MIN = 0,
117
118 LPAIF_RDMA_CHAN_MI2S = 0,
119 LPAIF_RDMA_CHAN_PCM0 = 1,
120 LPAIF_RDMA_CHAN_PCM1 = 2,
121 83
122 LPAIF_RDMA_CHAN_MAX = 4, 84#define LPAIF_RDMACTL_AUDINTF(id) (id << LPAIF_RDMACTL_AUDINTF_SHIFT)
123 LPAIF_RDMA_CHAN_NUM = 5,
124};
125 85
126#define LPAIF_RDMACTL_REG(chan) LPAIF_RDMA_REG_ADDR(0x00, (chan)) 86#define LPAIF_RDMACTL_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x00, (chan))
127#define LPAIF_RDMABASE_REG(chan) LPAIF_RDMA_REG_ADDR(0x04, (chan)) 87#define LPAIF_RDMABASE_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x04, (chan))
128#define LPAIF_RDMABUFF_REG(chan) LPAIF_RDMA_REG_ADDR(0x08, (chan)) 88#define LPAIF_RDMABUFF_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x08, (chan))
129#define LPAIF_RDMACURR_REG(chan) LPAIF_RDMA_REG_ADDR(0x0C, (chan)) 89#define LPAIF_RDMACURR_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x0C, (chan))
130#define LPAIF_RDMAPER_REG(chan) LPAIF_RDMA_REG_ADDR(0x10, (chan)) 90#define LPAIF_RDMAPER_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x10, (chan))
91#define LPAIF_RDMAPERCNT_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x14, (chan))
131 92
132#define LPAIF_RDMACTL_BURSTEN_MASK 0x800 93#define LPAIF_RDMACTL_BURSTEN_MASK 0x800
133#define LPAIF_RDMACTL_BURSTEN_SHIFT 11 94#define LPAIF_RDMACTL_BURSTEN_SHIFT 11
@@ -145,13 +106,6 @@ enum lpaif_dma_channels {
145 106
146#define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0 107#define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0
147#define LPAIF_RDMACTL_AUDINTF_SHIFT 4 108#define LPAIF_RDMACTL_AUDINTF_SHIFT 4
148#define LPAIF_RDMACTL_AUDINTF_NONE (0 << LPAIF_RDMACTL_AUDINTF_SHIFT)
149#define LPAIF_RDMACTL_AUDINTF_CODEC (1 << LPAIF_RDMACTL_AUDINTF_SHIFT)
150#define LPAIF_RDMACTL_AUDINTF_PCM (2 << LPAIF_RDMACTL_AUDINTF_SHIFT)
151#define LPAIF_RDMACTL_AUDINTF_SEC_I2S (3 << LPAIF_RDMACTL_AUDINTF_SHIFT)
152#define LPAIF_RDMACTL_AUDINTF_MI2S (4 << LPAIF_RDMACTL_AUDINTF_SHIFT)
153#define LPAIF_RDMACTL_AUDINTF_HDMI (5 << LPAIF_RDMACTL_AUDINTF_SHIFT)
154#define LPAIF_RDMACTL_AUDINTF_SEC_PCM (7 << LPAIF_RDMACTL_AUDINTF_SHIFT)
155 109
156#define LPAIF_RDMACTL_FIFOWM_MASK 0x00E 110#define LPAIF_RDMACTL_FIFOWM_MASK 0x00E
157#define LPAIF_RDMACTL_FIFOWM_SHIFT 1 111#define LPAIF_RDMACTL_FIFOWM_SHIFT 1
@@ -169,4 +123,4 @@ enum lpaif_dma_channels {
169#define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT) 123#define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT)
170#define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT) 124#define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT)
171 125
172#endif /* __LPASS_LPAIF_H__ */ 126#endif /* __LPASS_LPAIF_REG_H__ */
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index ffc09287af7c..a38e7ecf244f 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -21,7 +21,7 @@
21#include <sound/pcm_params.h> 21#include <sound/pcm_params.h>
22#include <linux/regmap.h> 22#include <linux/regmap.h>
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include "lpass-lpaif-ipq806x.h" 24#include "lpass-lpaif-reg.h"
25#include "lpass.h" 25#include "lpass.h"
26 26
27#define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) 27#define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024)
@@ -80,6 +80,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
80 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 80 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
81 struct lpass_data *drvdata = 81 struct lpass_data *drvdata =
82 snd_soc_platform_get_drvdata(soc_runtime->platform); 82 snd_soc_platform_get_drvdata(soc_runtime->platform);
83 struct lpass_variant *v = drvdata->variant;
83 snd_pcm_format_t format = params_format(params); 84 snd_pcm_format_t format = params_format(params);
84 unsigned int channels = params_channels(params); 85 unsigned int channels = params_channels(params);
85 unsigned int regval; 86 unsigned int regval;
@@ -150,7 +151,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
150 } 151 }
151 152
152 ret = regmap_write(drvdata->lpaif_map, 153 ret = regmap_write(drvdata->lpaif_map,
153 LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), regval); 154 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), regval);
154 if (ret) { 155 if (ret) {
155 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 156 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
156 __func__, ret); 157 __func__, ret);
@@ -165,10 +166,11 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
165 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 166 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
166 struct lpass_data *drvdata = 167 struct lpass_data *drvdata =
167 snd_soc_platform_get_drvdata(soc_runtime->platform); 168 snd_soc_platform_get_drvdata(soc_runtime->platform);
169 struct lpass_variant *v = drvdata->variant;
168 int ret; 170 int ret;
169 171
170 ret = regmap_write(drvdata->lpaif_map, 172 ret = regmap_write(drvdata->lpaif_map,
171 LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0); 173 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0);
172 if (ret) 174 if (ret)
173 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 175 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
174 __func__, ret); 176 __func__, ret);
@@ -182,10 +184,11 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
182 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 184 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
183 struct lpass_data *drvdata = 185 struct lpass_data *drvdata =
184 snd_soc_platform_get_drvdata(soc_runtime->platform); 186 snd_soc_platform_get_drvdata(soc_runtime->platform);
187 struct lpass_variant *v = drvdata->variant;
185 int ret; 188 int ret;
186 189
187 ret = regmap_write(drvdata->lpaif_map, 190 ret = regmap_write(drvdata->lpaif_map,
188 LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), 191 LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S),
189 runtime->dma_addr); 192 runtime->dma_addr);
190 if (ret) { 193 if (ret) {
191 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", 194 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n",
@@ -194,7 +197,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
194 } 197 }
195 198
196 ret = regmap_write(drvdata->lpaif_map, 199 ret = regmap_write(drvdata->lpaif_map,
197 LPAIF_RDMABUFF_REG(LPAIF_RDMA_CHAN_MI2S), 200 LPAIF_RDMABUFF_REG(v, LPAIF_RDMA_CHAN_MI2S),
198 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); 201 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
199 if (ret) { 202 if (ret) {
200 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", 203 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n",
@@ -203,7 +206,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
203 } 206 }
204 207
205 ret = regmap_write(drvdata->lpaif_map, 208 ret = regmap_write(drvdata->lpaif_map,
206 LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MI2S), 209 LPAIF_RDMAPER_REG(v, LPAIF_RDMA_CHAN_MI2S),
207 (snd_pcm_lib_period_bytes(substream) >> 2) - 1); 210 (snd_pcm_lib_period_bytes(substream) >> 2) - 1);
208 if (ret) { 211 if (ret) {
209 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", 212 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n",
@@ -212,7 +215,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
212 } 215 }
213 216
214 ret = regmap_update_bits(drvdata->lpaif_map, 217 ret = regmap_update_bits(drvdata->lpaif_map,
215 LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 218 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S),
216 LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); 219 LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON);
217 if (ret) { 220 if (ret) {
218 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 221 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
@@ -229,6 +232,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
229 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 232 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
230 struct lpass_data *drvdata = 233 struct lpass_data *drvdata =
231 snd_soc_platform_get_drvdata(soc_runtime->platform); 234 snd_soc_platform_get_drvdata(soc_runtime->platform);
235 struct lpass_variant *v = drvdata->variant;
232 int ret; 236 int ret;
233 237
234 switch (cmd) { 238 switch (cmd) {
@@ -237,7 +241,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
237 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 241 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
238 /* clear status before enabling interrupts */ 242 /* clear status before enabling interrupts */
239 ret = regmap_write(drvdata->lpaif_map, 243 ret = regmap_write(drvdata->lpaif_map,
240 LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), 244 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
241 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); 245 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S));
242 if (ret) { 246 if (ret) {
243 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 247 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
@@ -246,7 +250,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
246 } 250 }
247 251
248 ret = regmap_update_bits(drvdata->lpaif_map, 252 ret = regmap_update_bits(drvdata->lpaif_map,
249 LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), 253 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
250 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 254 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S),
251 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); 255 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S));
252 if (ret) { 256 if (ret) {
@@ -256,7 +260,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
256 } 260 }
257 261
258 ret = regmap_update_bits(drvdata->lpaif_map, 262 ret = regmap_update_bits(drvdata->lpaif_map,
259 LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 263 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S),
260 LPAIF_RDMACTL_ENABLE_MASK, 264 LPAIF_RDMACTL_ENABLE_MASK,
261 LPAIF_RDMACTL_ENABLE_ON); 265 LPAIF_RDMACTL_ENABLE_ON);
262 if (ret) { 266 if (ret) {
@@ -269,7 +273,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
269 case SNDRV_PCM_TRIGGER_SUSPEND: 273 case SNDRV_PCM_TRIGGER_SUSPEND:
270 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 274 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
271 ret = regmap_update_bits(drvdata->lpaif_map, 275 ret = regmap_update_bits(drvdata->lpaif_map,
272 LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 276 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S),
273 LPAIF_RDMACTL_ENABLE_MASK, 277 LPAIF_RDMACTL_ENABLE_MASK,
274 LPAIF_RDMACTL_ENABLE_OFF); 278 LPAIF_RDMACTL_ENABLE_OFF);
275 if (ret) { 279 if (ret) {
@@ -279,7 +283,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
279 } 283 }
280 284
281 ret = regmap_update_bits(drvdata->lpaif_map, 285 ret = regmap_update_bits(drvdata->lpaif_map,
282 LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), 286 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
283 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0); 287 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0);
284 if (ret) { 288 if (ret) {
285 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", 289 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
@@ -298,11 +302,13 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
298 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 302 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
299 struct lpass_data *drvdata = 303 struct lpass_data *drvdata =
300 snd_soc_platform_get_drvdata(soc_runtime->platform); 304 snd_soc_platform_get_drvdata(soc_runtime->platform);
305 struct lpass_variant *v = drvdata->variant;
301 unsigned int base_addr, curr_addr; 306 unsigned int base_addr, curr_addr;
302 int ret; 307 int ret;
303 308
304 ret = regmap_read(drvdata->lpaif_map, 309 ret = regmap_read(drvdata->lpaif_map,
305 LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), &base_addr); 310 LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S),
311 &base_addr);
306 if (ret) { 312 if (ret) {
307 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", 313 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n",
308 __func__, ret); 314 __func__, ret);
@@ -310,7 +316,8 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
310 } 316 }
311 317
312 ret = regmap_read(drvdata->lpaif_map, 318 ret = regmap_read(drvdata->lpaif_map,
313 LPAIF_RDMACURR_REG(LPAIF_RDMA_CHAN_MI2S), &curr_addr); 319 LPAIF_RDMACURR_REG(v, LPAIF_RDMA_CHAN_MI2S),
320 &curr_addr);
314 if (ret) { 321 if (ret) {
315 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", 322 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n",
316 __func__, ret); 323 __func__, ret);
@@ -347,12 +354,13 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
347 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 354 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
348 struct lpass_data *drvdata = 355 struct lpass_data *drvdata =
349 snd_soc_platform_get_drvdata(soc_runtime->platform); 356 snd_soc_platform_get_drvdata(soc_runtime->platform);
357 struct lpass_variant *v = drvdata->variant;
350 unsigned int interrupts; 358 unsigned int interrupts;
351 irqreturn_t ret = IRQ_NONE; 359 irqreturn_t ret = IRQ_NONE;
352 int rv; 360 int rv;
353 361
354 rv = regmap_read(drvdata->lpaif_map, 362 rv = regmap_read(drvdata->lpaif_map,
355 LPAIF_IRQSTAT_REG(LPAIF_IRQ_PORT_HOST), &interrupts); 363 LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts);
356 if (rv) { 364 if (rv) {
357 dev_err(soc_runtime->dev, "%s() error reading from irqstat reg: %d\n", 365 dev_err(soc_runtime->dev, "%s() error reading from irqstat reg: %d\n",
358 __func__, rv); 366 __func__, rv);
@@ -362,7 +370,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
362 370
363 if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) { 371 if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) {
364 rv = regmap_write(drvdata->lpaif_map, 372 rv = regmap_write(drvdata->lpaif_map,
365 LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), 373 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
366 LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)); 374 LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S));
367 if (rv) { 375 if (rv) {
368 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 376 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
@@ -375,7 +383,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
375 383
376 if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) { 384 if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) {
377 rv = regmap_write(drvdata->lpaif_map, 385 rv = regmap_write(drvdata->lpaif_map,
378 LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), 386 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
379 LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)); 387 LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S));
380 if (rv) { 388 if (rv) {
381 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 389 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
@@ -389,7 +397,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
389 397
390 if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) { 398 if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) {
391 rv = regmap_write(drvdata->lpaif_map, 399 rv = regmap_write(drvdata->lpaif_map,
392 LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), 400 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
393 LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)); 401 LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S));
394 if (rv) { 402 if (rv) {
395 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 403 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
@@ -444,6 +452,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
444 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 452 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
445 struct lpass_data *drvdata = 453 struct lpass_data *drvdata =
446 snd_soc_platform_get_drvdata(soc_runtime->platform); 454 snd_soc_platform_get_drvdata(soc_runtime->platform);
455 struct lpass_variant *v = drvdata->variant;
447 int ret; 456 int ret;
448 457
449 soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32); 458 soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32);
@@ -464,14 +473,14 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
464 473
465 /* ensure audio hardware is disabled */ 474 /* ensure audio hardware is disabled */
466 ret = regmap_write(drvdata->lpaif_map, 475 ret = regmap_write(drvdata->lpaif_map,
467 LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), 0); 476 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
468 if (ret) { 477 if (ret) {
469 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", 478 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
470 __func__, ret); 479 __func__, ret);
471 return ret; 480 return ret;
472 } 481 }
473 ret = regmap_write(drvdata->lpaif_map, 482 ret = regmap_write(drvdata->lpaif_map,
474 LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0); 483 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0);
475 if (ret) { 484 if (ret) {
476 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 485 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
477 __func__, ret); 486 __func__, ret);
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
index 5c99b3dace86..fa00be43e923 100644
--- a/sound/soc/qcom/lpass.h
+++ b/sound/soc/qcom/lpass.h
@@ -43,9 +43,37 @@ struct lpass_data {
43 43
44 /* interrupts from the low-power audio interface (LPAIF) */ 44 /* interrupts from the low-power audio interface (LPAIF) */
45 int lpaif_irq; 45 int lpaif_irq;
46
47 /* SOC specific variations in the LPASS IP integration */
48 struct lpass_variant *variant;
49};
50
51/* Vairant data per each SOC */
52struct lpass_variant {
53 u32 i2sctrl_reg_base;
54 u32 i2sctrl_reg_stride;
55 u32 i2s_ports;
56 u32 irq_reg_base;
57 u32 irq_reg_stride;
58 u32 irq_ports;
59 u32 rdma_reg_base;
60 u32 rdma_reg_stride;
61 u32 rdma_channels;
62
63 /* SOC specific intialization like clocks */
64 int (*init)(struct platform_device *pdev);
65 int (*exit)(struct platform_device *pdev);
66
67 /* SOC specific dais */
68 struct snd_soc_dai_driver *dai_driver;
69 int num_dai;
46}; 70};
47 71
48/* register the platform driver from the CPU DAI driver */ 72/* register the platform driver from the CPU DAI driver */
49int asoc_qcom_lpass_platform_register(struct platform_device *); 73int asoc_qcom_lpass_platform_register(struct platform_device *);
74int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev);
75int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev);
76int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai);
77extern struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops;
50 78
51#endif /* __LPASS_H__ */ 79#endif /* __LPASS_H__ */