xref: /linux/sound/soc/mediatek/common/mtk-afe-fe-dai.c (revision af50e4ba34f4c45e92535364133d4deb5931c1c5)
1 /*
2  * mtk-afe-fe-dais.c  --  Mediatek afe fe dai operator
3  *
4  * Copyright (c) 2016 MediaTek Inc.
5  * Author: Garlic Tseng <garlic.tseng@mediatek.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 and
9  * only version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <sound/soc.h>
21 #include "mtk-afe-platform-driver.h"
22 #include "mtk-afe-fe-dai.h"
23 #include "mtk-base-afe.h"
24 
25 #define AFE_BASE_END_OFFSET 8
26 
27 static int mtk_regmap_update_bits(struct regmap *map, int reg,
28 			   unsigned int mask,
29 			   unsigned int val)
30 {
31 	if (reg < 0)
32 		return 0;
33 	return regmap_update_bits(map, reg, mask, val);
34 }
35 
36 static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
37 {
38 	if (reg < 0)
39 		return 0;
40 	return regmap_write(map, reg, val);
41 }
42 
43 int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
44 		       struct snd_soc_dai *dai)
45 {
46 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
47 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
48 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
49 	struct snd_pcm_runtime *runtime = substream->runtime;
50 	int memif_num = rtd->cpu_dai->id;
51 	struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
52 	const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware;
53 	int ret;
54 
55 	memif->substream = substream;
56 
57 	snd_pcm_hw_constraint_step(substream->runtime, 0,
58 				   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
59 	/* enable agent */
60 	mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
61 			       1 << memif->data->agent_disable_shift,
62 			       0 << memif->data->agent_disable_shift);
63 
64 	snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware);
65 
66 	/*
67 	 * Capture cannot use ping-pong buffer since hw_ptr at IRQ may be
68 	 * smaller than period_size due to AFE's internal buffer.
69 	 * This easily leads to overrun when avail_min is period_size.
70 	 * One more period can hold the possible unread buffer.
71 	 */
72 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
73 		int periods_max = mtk_afe_hardware->periods_max;
74 
75 		ret = snd_pcm_hw_constraint_minmax(runtime,
76 						   SNDRV_PCM_HW_PARAM_PERIODS,
77 						   3, periods_max);
78 		if (ret < 0) {
79 			dev_err(afe->dev, "hw_constraint_minmax failed\n");
80 			return ret;
81 		}
82 	}
83 
84 	ret = snd_pcm_hw_constraint_integer(runtime,
85 					    SNDRV_PCM_HW_PARAM_PERIODS);
86 	if (ret < 0)
87 		dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
88 
89 	/* dynamic allocate irq to memif */
90 	if (memif->irq_usage < 0) {
91 		int irq_id = mtk_dynamic_irq_acquire(afe);
92 
93 		if (irq_id != afe->irqs_size) {
94 			/* link */
95 			memif->irq_usage = irq_id;
96 		} else {
97 			dev_err(afe->dev, "%s() error: no more asys irq\n",
98 				__func__);
99 			ret = -EBUSY;
100 		}
101 	}
102 	return ret;
103 }
104 EXPORT_SYMBOL_GPL(mtk_afe_fe_startup);
105 
106 void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream,
107 			 struct snd_soc_dai *dai)
108 {
109 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
110 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
111 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
112 	struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
113 	int irq_id;
114 
115 	irq_id = memif->irq_usage;
116 
117 	mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
118 			       1 << memif->data->agent_disable_shift,
119 			       1 << memif->data->agent_disable_shift);
120 
121 	if (!memif->const_irq) {
122 		mtk_dynamic_irq_release(afe, irq_id);
123 		memif->irq_usage = -1;
124 		memif->substream = NULL;
125 	}
126 }
127 EXPORT_SYMBOL_GPL(mtk_afe_fe_shutdown);
128 
129 int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
130 			 struct snd_pcm_hw_params *params,
131 			 struct snd_soc_dai *dai)
132 {
133 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
134 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
135 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
136 	struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
137 	int msb_at_bit33 = 0;
138 	int ret, fs = 0;
139 
140 	ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
141 	if (ret < 0)
142 		return ret;
143 
144 	msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0;
145 	memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr);
146 	memif->buffer_size = substream->runtime->dma_bytes;
147 
148 	/* start */
149 	mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base,
150 			 memif->phys_buf_addr);
151 	/* end */
152 	mtk_regmap_write(afe->regmap,
153 			 memif->data->reg_ofs_base + AFE_BASE_END_OFFSET,
154 			 memif->phys_buf_addr + memif->buffer_size - 1);
155 
156 	/* set MSB to 33-bit */
157 	mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
158 			       1 << memif->data->msb_shift,
159 			       msb_at_bit33 << memif->data->msb_shift);
160 
161 	/* set channel */
162 	if (memif->data->mono_shift >= 0) {
163 		unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
164 
165 		mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
166 				       1 << memif->data->mono_shift,
167 				       mono << memif->data->mono_shift);
168 	}
169 
170 	/* set rate */
171 	if (memif->data->fs_shift < 0)
172 		return 0;
173 
174 	fs = afe->memif_fs(substream, params_rate(params));
175 
176 	if (fs < 0)
177 		return -EINVAL;
178 
179 	mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg,
180 			       memif->data->fs_maskbit << memif->data->fs_shift,
181 			       fs << memif->data->fs_shift);
182 
183 	return 0;
184 }
185 EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_params);
186 
187 int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream,
188 		       struct snd_soc_dai *dai)
189 {
190 	return snd_pcm_lib_free_pages(substream);
191 }
192 EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free);
193 
194 int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
195 		       struct snd_soc_dai *dai)
196 {
197 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
198 	struct snd_pcm_runtime * const runtime = substream->runtime;
199 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
200 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
201 	struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
202 	struct mtk_base_afe_irq *irqs = &afe->irqs[memif->irq_usage];
203 	const struct mtk_base_irq_data *irq_data = irqs->irq_data;
204 	unsigned int counter = runtime->period_size;
205 	int fs;
206 
207 	dev_dbg(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd);
208 
209 	switch (cmd) {
210 	case SNDRV_PCM_TRIGGER_START:
211 	case SNDRV_PCM_TRIGGER_RESUME:
212 		if (memif->data->enable_shift >= 0)
213 			mtk_regmap_update_bits(afe->regmap,
214 					       memif->data->enable_reg,
215 					       1 << memif->data->enable_shift,
216 					       1 << memif->data->enable_shift);
217 
218 		/* set irq counter */
219 		mtk_regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
220 				       irq_data->irq_cnt_maskbit
221 				       << irq_data->irq_cnt_shift,
222 				       counter << irq_data->irq_cnt_shift);
223 
224 		/* set irq fs */
225 		fs = afe->irq_fs(substream, runtime->rate);
226 
227 		if (fs < 0)
228 			return -EINVAL;
229 
230 		mtk_regmap_update_bits(afe->regmap, irq_data->irq_fs_reg,
231 				       irq_data->irq_fs_maskbit
232 				       << irq_data->irq_fs_shift,
233 				       fs << irq_data->irq_fs_shift);
234 
235 		/* enable interrupt */
236 		mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg,
237 				       1 << irq_data->irq_en_shift,
238 				       1 << irq_data->irq_en_shift);
239 
240 		return 0;
241 	case SNDRV_PCM_TRIGGER_STOP:
242 	case SNDRV_PCM_TRIGGER_SUSPEND:
243 		mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg,
244 				       1 << memif->data->enable_shift, 0);
245 		/* disable interrupt */
246 		mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg,
247 				       1 << irq_data->irq_en_shift,
248 				       0 << irq_data->irq_en_shift);
249 		/* and clear pending IRQ */
250 		mtk_regmap_write(afe->regmap, irq_data->irq_clr_reg,
251 				 1 << irq_data->irq_clr_shift);
252 		return 0;
253 	default:
254 		return -EINVAL;
255 	}
256 }
257 EXPORT_SYMBOL_GPL(mtk_afe_fe_trigger);
258 
259 int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
260 		       struct snd_soc_dai *dai)
261 {
262 	struct snd_soc_pcm_runtime *rtd  = substream->private_data;
263 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
264 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
265 	struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
266 	int hd_audio = 0;
267 
268 	/* set hd mode */
269 	switch (substream->runtime->format) {
270 	case SNDRV_PCM_FORMAT_S16_LE:
271 		hd_audio = 0;
272 		break;
273 	case SNDRV_PCM_FORMAT_S32_LE:
274 		hd_audio = 1;
275 		break;
276 	case SNDRV_PCM_FORMAT_S24_LE:
277 		hd_audio = 1;
278 		break;
279 	default:
280 		dev_err(afe->dev, "%s() error: unsupported format %d\n",
281 			__func__, substream->runtime->format);
282 		break;
283 	}
284 
285 	mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg,
286 			       1 << memif->data->hd_shift,
287 			       hd_audio << memif->data->hd_shift);
288 
289 	return 0;
290 }
291 EXPORT_SYMBOL_GPL(mtk_afe_fe_prepare);
292 
293 const struct snd_soc_dai_ops mtk_afe_fe_ops = {
294 	.startup	= mtk_afe_fe_startup,
295 	.shutdown	= mtk_afe_fe_shutdown,
296 	.hw_params	= mtk_afe_fe_hw_params,
297 	.hw_free	= mtk_afe_fe_hw_free,
298 	.prepare	= mtk_afe_fe_prepare,
299 	.trigger	= mtk_afe_fe_trigger,
300 };
301 EXPORT_SYMBOL_GPL(mtk_afe_fe_ops);
302 
303 static DEFINE_MUTEX(irqs_lock);
304 int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe)
305 {
306 	int i;
307 
308 	mutex_lock(&afe->irq_alloc_lock);
309 	for (i = 0; i < afe->irqs_size; ++i) {
310 		if (afe->irqs[i].irq_occupyed == 0) {
311 			afe->irqs[i].irq_occupyed = 1;
312 			mutex_unlock(&afe->irq_alloc_lock);
313 			return i;
314 		}
315 	}
316 	mutex_unlock(&afe->irq_alloc_lock);
317 	return afe->irqs_size;
318 }
319 EXPORT_SYMBOL_GPL(mtk_dynamic_irq_acquire);
320 
321 int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id)
322 {
323 	mutex_lock(&afe->irq_alloc_lock);
324 	if (irq_id >= 0 && irq_id < afe->irqs_size) {
325 		afe->irqs[irq_id].irq_occupyed = 0;
326 		mutex_unlock(&afe->irq_alloc_lock);
327 		return 0;
328 	}
329 	mutex_unlock(&afe->irq_alloc_lock);
330 	return -EINVAL;
331 }
332 EXPORT_SYMBOL_GPL(mtk_dynamic_irq_release);
333 
334 int mtk_afe_dai_suspend(struct snd_soc_dai *dai)
335 {
336 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
337 	struct device *dev = afe->dev;
338 	struct regmap *regmap = afe->regmap;
339 	int i;
340 
341 	if (pm_runtime_status_suspended(dev) || afe->suspended)
342 		return 0;
343 
344 	if (!afe->reg_back_up)
345 		afe->reg_back_up =
346 			devm_kcalloc(dev, afe->reg_back_up_list_num,
347 				     sizeof(unsigned int), GFP_KERNEL);
348 
349 	for (i = 0; i < afe->reg_back_up_list_num; i++)
350 		regmap_read(regmap, afe->reg_back_up_list[i],
351 			    &afe->reg_back_up[i]);
352 
353 	afe->suspended = true;
354 	afe->runtime_suspend(dev);
355 	return 0;
356 }
357 EXPORT_SYMBOL_GPL(mtk_afe_dai_suspend);
358 
359 int mtk_afe_dai_resume(struct snd_soc_dai *dai)
360 {
361 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
362 	struct device *dev = afe->dev;
363 	struct regmap *regmap = afe->regmap;
364 	int i = 0;
365 
366 	if (pm_runtime_status_suspended(dev) || !afe->suspended)
367 		return 0;
368 
369 	afe->runtime_resume(dev);
370 
371 	if (!afe->reg_back_up)
372 		dev_dbg(dev, "%s no reg_backup\n", __func__);
373 
374 	for (i = 0; i < afe->reg_back_up_list_num; i++)
375 		mtk_regmap_write(regmap, afe->reg_back_up_list[i],
376 				 afe->reg_back_up[i]);
377 
378 	afe->suspended = false;
379 	return 0;
380 }
381 EXPORT_SYMBOL_GPL(mtk_afe_dai_resume);
382 
383 MODULE_DESCRIPTION("Mediatek simple fe dai operator");
384 MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>");
385 MODULE_LICENSE("GPL v2");
386 
387