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