xref: /linux/sound/soc/qcom/lpass-platform.c (revision 93df8a1ed6231727c5db94a80b1a6bd5ee67cec3)
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-platform.c -- ALSA SoC platform driver for QTi LPASS
14  */
15 
16 #include <linux/dma-mapping.h>
17 #include <linux/export.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <sound/pcm_params.h>
22 #include <linux/regmap.h>
23 #include <sound/soc.h>
24 #include "lpass-lpaif-reg.h"
25 #include "lpass.h"
26 
27 struct lpass_pcm_data {
28 	int rdma_ch;
29 	int i2s_port;
30 };
31 
32 #define LPASS_PLATFORM_BUFFER_SIZE	(16 * 1024)
33 #define LPASS_PLATFORM_PERIODS		2
34 
35 static struct snd_pcm_hardware lpass_platform_pcm_hardware = {
36 	.info			=	SNDRV_PCM_INFO_MMAP |
37 					SNDRV_PCM_INFO_MMAP_VALID |
38 					SNDRV_PCM_INFO_INTERLEAVED |
39 					SNDRV_PCM_INFO_PAUSE |
40 					SNDRV_PCM_INFO_RESUME,
41 	.formats		=	SNDRV_PCM_FMTBIT_S16 |
42 					SNDRV_PCM_FMTBIT_S24 |
43 					SNDRV_PCM_FMTBIT_S32,
44 	.rates			=	SNDRV_PCM_RATE_8000_192000,
45 	.rate_min		=	8000,
46 	.rate_max		=	192000,
47 	.channels_min		=	1,
48 	.channels_max		=	8,
49 	.buffer_bytes_max	=	LPASS_PLATFORM_BUFFER_SIZE,
50 	.period_bytes_max	=	LPASS_PLATFORM_BUFFER_SIZE /
51 						LPASS_PLATFORM_PERIODS,
52 	.period_bytes_min	=	LPASS_PLATFORM_BUFFER_SIZE /
53 						LPASS_PLATFORM_PERIODS,
54 	.periods_min		=	LPASS_PLATFORM_PERIODS,
55 	.periods_max		=	LPASS_PLATFORM_PERIODS,
56 	.fifo_size		=	0,
57 };
58 
59 static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
60 {
61 	struct snd_pcm_runtime *runtime = substream->runtime;
62 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
63 	int ret;
64 
65 	snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
66 
67 	runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max;
68 
69 	ret = snd_pcm_hw_constraint_integer(runtime,
70 			SNDRV_PCM_HW_PARAM_PERIODS);
71 	if (ret < 0) {
72 		dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n",
73 				__func__, ret);
74 		return -EINVAL;
75 	}
76 
77 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
78 
79 	return 0;
80 }
81 
82 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
83 		struct snd_pcm_hw_params *params)
84 {
85 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
86 	struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
87 	struct lpass_data *drvdata =
88 		snd_soc_platform_get_drvdata(soc_runtime->platform);
89 	struct lpass_variant *v = drvdata->variant;
90 	snd_pcm_format_t format = params_format(params);
91 	unsigned int channels = params_channels(params);
92 	unsigned int regval;
93 	int bitwidth;
94 	int ret, rdma_port = pcm_data->i2s_port + v->rdmactl_audif_start;
95 
96 	bitwidth = snd_pcm_format_width(format);
97 	if (bitwidth < 0) {
98 		dev_err(soc_runtime->dev, "%s() invalid bit width given: %d\n",
99 				__func__, bitwidth);
100 		return bitwidth;
101 	}
102 
103 	regval = LPAIF_RDMACTL_BURSTEN_INCR4 |
104 			LPAIF_RDMACTL_AUDINTF(rdma_port) |
105 			LPAIF_RDMACTL_FIFOWM_8;
106 
107 	switch (bitwidth) {
108 	case 16:
109 		switch (channels) {
110 		case 1:
111 		case 2:
112 			regval |= LPAIF_RDMACTL_WPSCNT_ONE;
113 			break;
114 		case 4:
115 			regval |= LPAIF_RDMACTL_WPSCNT_TWO;
116 			break;
117 		case 6:
118 			regval |= LPAIF_RDMACTL_WPSCNT_THREE;
119 			break;
120 		case 8:
121 			regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
122 			break;
123 		default:
124 			dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
125 					__func__, bitwidth, channels);
126 			return -EINVAL;
127 		}
128 		break;
129 	case 24:
130 	case 32:
131 		switch (channels) {
132 		case 1:
133 			regval |= LPAIF_RDMACTL_WPSCNT_ONE;
134 			break;
135 		case 2:
136 			regval |= LPAIF_RDMACTL_WPSCNT_TWO;
137 			break;
138 		case 4:
139 			regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
140 			break;
141 		case 6:
142 			regval |= LPAIF_RDMACTL_WPSCNT_SIX;
143 			break;
144 		case 8:
145 			regval |= LPAIF_RDMACTL_WPSCNT_EIGHT;
146 			break;
147 		default:
148 			dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
149 					__func__, bitwidth, channels);
150 			return -EINVAL;
151 		}
152 		break;
153 	default:
154 		dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
155 				__func__, bitwidth, channels);
156 		return -EINVAL;
157 	}
158 
159 	ret = regmap_write(drvdata->lpaif_map,
160 			LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), regval);
161 	if (ret) {
162 		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
163 				__func__, ret);
164 		return ret;
165 	}
166 
167 	return 0;
168 }
169 
170 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
171 {
172 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
173 	struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
174 	struct lpass_data *drvdata =
175 		snd_soc_platform_get_drvdata(soc_runtime->platform);
176 	struct lpass_variant *v = drvdata->variant;
177 	int ret;
178 
179 	ret = regmap_write(drvdata->lpaif_map,
180 			LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), 0);
181 	if (ret)
182 		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
183 				__func__, ret);
184 
185 	return ret;
186 }
187 
188 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
189 {
190 	struct snd_pcm_runtime *runtime = substream->runtime;
191 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
192 	struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
193 	struct lpass_data *drvdata =
194 		snd_soc_platform_get_drvdata(soc_runtime->platform);
195 	struct lpass_variant *v = drvdata->variant;
196 	int ret, ch = pcm_data->rdma_ch;
197 
198 	ret = regmap_write(drvdata->lpaif_map,
199 			LPAIF_RDMABASE_REG(v, ch),
200 			runtime->dma_addr);
201 	if (ret) {
202 		dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n",
203 				__func__, ret);
204 		return ret;
205 	}
206 
207 	ret = regmap_write(drvdata->lpaif_map,
208 			LPAIF_RDMABUFF_REG(v, ch),
209 			(snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
210 	if (ret) {
211 		dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n",
212 				__func__, ret);
213 		return ret;
214 	}
215 
216 	ret = regmap_write(drvdata->lpaif_map,
217 			LPAIF_RDMAPER_REG(v, ch),
218 			(snd_pcm_lib_period_bytes(substream) >> 2) - 1);
219 	if (ret) {
220 		dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n",
221 				__func__, ret);
222 		return ret;
223 	}
224 
225 	ret = regmap_update_bits(drvdata->lpaif_map,
226 			LPAIF_RDMACTL_REG(v, ch),
227 			LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON);
228 	if (ret) {
229 		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
230 				__func__, ret);
231 		return ret;
232 	}
233 
234 	return 0;
235 }
236 
237 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
238 		int cmd)
239 {
240 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
241 	struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
242 	struct lpass_data *drvdata =
243 		snd_soc_platform_get_drvdata(soc_runtime->platform);
244 	struct lpass_variant *v = drvdata->variant;
245 	int ret, ch = pcm_data->rdma_ch;
246 
247 	switch (cmd) {
248 	case SNDRV_PCM_TRIGGER_START:
249 	case SNDRV_PCM_TRIGGER_RESUME:
250 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
251 		/* clear status before enabling interrupts */
252 		ret = regmap_write(drvdata->lpaif_map,
253 				LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
254 				LPAIF_IRQ_ALL(ch));
255 		if (ret) {
256 			dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
257 					__func__, ret);
258 			return ret;
259 		}
260 
261 		ret = regmap_update_bits(drvdata->lpaif_map,
262 				LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
263 				LPAIF_IRQ_ALL(ch),
264 				LPAIF_IRQ_ALL(ch));
265 		if (ret) {
266 			dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
267 					__func__, ret);
268 			return ret;
269 		}
270 
271 		ret = regmap_update_bits(drvdata->lpaif_map,
272 				LPAIF_RDMACTL_REG(v, ch),
273 				LPAIF_RDMACTL_ENABLE_MASK,
274 				LPAIF_RDMACTL_ENABLE_ON);
275 		if (ret) {
276 			dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
277 					__func__, ret);
278 			return ret;
279 		}
280 		break;
281 	case SNDRV_PCM_TRIGGER_STOP:
282 	case SNDRV_PCM_TRIGGER_SUSPEND:
283 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
284 		ret = regmap_update_bits(drvdata->lpaif_map,
285 				LPAIF_RDMACTL_REG(v, ch),
286 				LPAIF_RDMACTL_ENABLE_MASK,
287 				LPAIF_RDMACTL_ENABLE_OFF);
288 		if (ret) {
289 			dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
290 					__func__, ret);
291 			return ret;
292 		}
293 
294 		ret = regmap_update_bits(drvdata->lpaif_map,
295 				LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
296 				LPAIF_IRQ_ALL(ch), 0);
297 		if (ret) {
298 			dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
299 					__func__, ret);
300 			return ret;
301 		}
302 		break;
303 	}
304 
305 	return 0;
306 }
307 
308 static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
309 		struct snd_pcm_substream *substream)
310 {
311 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
312 	struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
313 	struct lpass_data *drvdata =
314 			snd_soc_platform_get_drvdata(soc_runtime->platform);
315 	struct lpass_variant *v = drvdata->variant;
316 	unsigned int base_addr, curr_addr;
317 	int ret, ch = pcm_data->rdma_ch;
318 
319 	ret = regmap_read(drvdata->lpaif_map,
320 			LPAIF_RDMABASE_REG(v, ch), &base_addr);
321 	if (ret) {
322 		dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n",
323 				__func__, ret);
324 		return ret;
325 	}
326 
327 	ret = regmap_read(drvdata->lpaif_map,
328 			LPAIF_RDMACURR_REG(v, ch), &curr_addr);
329 	if (ret) {
330 		dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n",
331 				__func__, ret);
332 		return ret;
333 	}
334 
335 	return bytes_to_frames(substream->runtime, curr_addr - base_addr);
336 }
337 
338 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
339 		struct vm_area_struct *vma)
340 {
341 	struct snd_pcm_runtime *runtime = substream->runtime;
342 
343 	return dma_mmap_coherent(substream->pcm->card->dev, vma,
344 			runtime->dma_area, runtime->dma_addr,
345 			runtime->dma_bytes);
346 }
347 
348 static struct snd_pcm_ops lpass_platform_pcm_ops = {
349 	.open		= lpass_platform_pcmops_open,
350 	.ioctl		= snd_pcm_lib_ioctl,
351 	.hw_params	= lpass_platform_pcmops_hw_params,
352 	.hw_free	= lpass_platform_pcmops_hw_free,
353 	.prepare	= lpass_platform_pcmops_prepare,
354 	.trigger	= lpass_platform_pcmops_trigger,
355 	.pointer	= lpass_platform_pcmops_pointer,
356 	.mmap		= lpass_platform_pcmops_mmap,
357 };
358 
359 static irqreturn_t lpass_dma_interrupt_handler(
360 			struct snd_pcm_substream *substream,
361 			struct lpass_data *drvdata,
362 			int chan, u32 interrupts)
363 {
364 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
365 	struct lpass_variant *v = drvdata->variant;
366 	irqreturn_t ret = IRQ_NONE;
367 	int rv;
368 
369 	if (interrupts & LPAIF_IRQ_PER(chan)) {
370 		rv = regmap_write(drvdata->lpaif_map,
371 				LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
372 				LPAIF_IRQ_PER(chan));
373 		if (rv) {
374 			dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
375 					__func__, rv);
376 			return IRQ_NONE;
377 		}
378 		snd_pcm_period_elapsed(substream);
379 		ret = IRQ_HANDLED;
380 	}
381 
382 	if (interrupts & LPAIF_IRQ_XRUN(chan)) {
383 		rv = regmap_write(drvdata->lpaif_map,
384 				LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
385 				LPAIF_IRQ_XRUN(chan));
386 		if (rv) {
387 			dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
388 					__func__, rv);
389 			return IRQ_NONE;
390 		}
391 		dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__);
392 		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
393 		ret = IRQ_HANDLED;
394 	}
395 
396 	if (interrupts & LPAIF_IRQ_ERR(chan)) {
397 		rv = regmap_write(drvdata->lpaif_map,
398 				LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
399 				LPAIF_IRQ_ERR(chan));
400 		if (rv) {
401 			dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
402 					__func__, rv);
403 			return IRQ_NONE;
404 		}
405 		dev_err(soc_runtime->dev, "%s() bus access error\n", __func__);
406 		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
407 		ret = IRQ_HANDLED;
408 	}
409 
410 	return ret;
411 }
412 
413 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
414 {
415 	struct lpass_data *drvdata = data;
416 	struct lpass_variant *v = drvdata->variant;
417 	unsigned int irqs;
418 	int rv, chan;
419 
420 	rv = regmap_read(drvdata->lpaif_map,
421 			LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
422 	if (rv) {
423 		pr_err("%s() error reading from irqstat reg: %d\n",
424 				__func__, rv);
425 		return IRQ_NONE;
426 	}
427 
428 	/* Handle per channel interrupts */
429 	for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) {
430 		if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) {
431 			rv = lpass_dma_interrupt_handler(
432 						drvdata->substream[chan],
433 						drvdata, chan, irqs);
434 			if (rv != IRQ_HANDLED)
435 				return rv;
436 		}
437 	}
438 
439 	return IRQ_HANDLED;
440 }
441 
442 static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream,
443 		struct snd_soc_pcm_runtime *soc_runtime)
444 {
445 	struct snd_dma_buffer *buf = &substream->dma_buffer;
446 	size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
447 
448 	buf->dev.type = SNDRV_DMA_TYPE_DEV;
449 	buf->dev.dev = soc_runtime->dev;
450 	buf->private_data = NULL;
451 	buf->area = dma_alloc_coherent(soc_runtime->dev, size, &buf->addr,
452 			GFP_KERNEL);
453 	if (!buf->area) {
454 		dev_err(soc_runtime->dev, "%s: Could not allocate DMA buffer\n",
455 				__func__);
456 		return -ENOMEM;
457 	}
458 	buf->bytes = size;
459 
460 	return 0;
461 }
462 
463 static void lpass_platform_free_buffer(struct snd_pcm_substream *substream,
464 		struct snd_soc_pcm_runtime *soc_runtime)
465 {
466 	struct snd_dma_buffer *buf = &substream->dma_buffer;
467 
468 	if (buf->area) {
469 		dma_free_coherent(soc_runtime->dev, buf->bytes, buf->area,
470 				buf->addr);
471 	}
472 	buf->area = NULL;
473 }
474 
475 static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
476 {
477 	struct snd_pcm *pcm = soc_runtime->pcm;
478 	struct snd_pcm_substream *substream =
479 		pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
480 	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
481 	struct lpass_data *drvdata =
482 		snd_soc_platform_get_drvdata(soc_runtime->platform);
483 	struct lpass_variant *v = drvdata->variant;
484 	int ret;
485 	struct lpass_pcm_data *data;
486 
487 	data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
488 	if (!data)
489 		return -ENOMEM;
490 
491 	if (v->alloc_dma_channel)
492 		data->rdma_ch = v->alloc_dma_channel(drvdata);
493 
494 	if (IS_ERR_VALUE(data->rdma_ch))
495 		return data->rdma_ch;
496 
497 	drvdata->substream[data->rdma_ch] = substream;
498 	data->i2s_port = cpu_dai->driver->id;
499 
500 	snd_soc_pcm_set_drvdata(soc_runtime, data);
501 
502 	soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32);
503 	soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask;
504 
505 	ret = lpass_platform_alloc_buffer(substream, soc_runtime);
506 	if (ret)
507 		return ret;
508 
509 	ret = regmap_write(drvdata->lpaif_map,
510 			LPAIF_RDMACTL_REG(v, data->rdma_ch), 0);
511 	if (ret) {
512 		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
513 				__func__, ret);
514 		goto err_buf;
515 	}
516 
517 	return 0;
518 
519 err_buf:
520 	lpass_platform_free_buffer(substream, soc_runtime);
521 	return ret;
522 }
523 
524 static void lpass_platform_pcm_free(struct snd_pcm *pcm)
525 {
526 	struct snd_pcm_substream *substream =
527 		pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
528 	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
529 	struct lpass_data *drvdata =
530 		snd_soc_platform_get_drvdata(soc_runtime->platform);
531 	struct lpass_pcm_data *data = snd_soc_pcm_get_drvdata(soc_runtime);
532 	struct lpass_variant *v = drvdata->variant;
533 
534 	drvdata->substream[data->rdma_ch] = NULL;
535 
536 	if (v->free_dma_channel)
537 		v->free_dma_channel(drvdata, data->rdma_ch);
538 
539 	lpass_platform_free_buffer(substream, soc_runtime);
540 }
541 
542 static struct snd_soc_platform_driver lpass_platform_driver = {
543 	.pcm_new	= lpass_platform_pcm_new,
544 	.pcm_free	= lpass_platform_pcm_free,
545 	.ops		= &lpass_platform_pcm_ops,
546 };
547 
548 int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
549 {
550 	struct lpass_data *drvdata = platform_get_drvdata(pdev);
551 	struct lpass_variant *v = drvdata->variant;
552 	int ret;
553 
554 	drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
555 	if (drvdata->lpaif_irq < 0) {
556 		dev_err(&pdev->dev, "%s() error getting irq handle: %d\n",
557 				__func__, drvdata->lpaif_irq);
558 		return -ENODEV;
559 	}
560 
561 	/* ensure audio hardware is disabled */
562 	ret = regmap_write(drvdata->lpaif_map,
563 			LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
564 	if (ret) {
565 		dev_err(&pdev->dev, "%s() error writing to irqen reg: %d\n",
566 				__func__, ret);
567 		return ret;
568 	}
569 
570 	ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq,
571 			lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
572 			"lpass-irq-lpaif", drvdata);
573 	if (ret) {
574 		dev_err(&pdev->dev, "%s() irq request failed: %d\n",
575 				__func__, ret);
576 		return ret;
577 	}
578 
579 
580 	return devm_snd_soc_register_platform(&pdev->dev,
581 			&lpass_platform_driver);
582 }
583 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
584 
585 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
586 MODULE_LICENSE("GPL v2");
587