1/*
2 * Intel Baytrail SST PCM Support
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/module.h>
16#include <linux/dma-mapping.h>
17#include <linux/slab.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include "sst-baytrail-ipc.h"
23#include "../common/sst-dsp-priv.h"
24#include "../common/sst-dsp.h"
25
26#define BYT_PCM_COUNT		2
27
28static const struct snd_pcm_hardware sst_byt_pcm_hardware = {
29	.info			= SNDRV_PCM_INFO_MMAP |
30				  SNDRV_PCM_INFO_MMAP_VALID |
31				  SNDRV_PCM_INFO_INTERLEAVED |
32				  SNDRV_PCM_INFO_PAUSE |
33				  SNDRV_PCM_INFO_RESUME,
34	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
35				  SNDRV_PCM_FMTBIT_S24_LE,
36	.period_bytes_min	= 384,
37	.period_bytes_max	= 48000,
38	.periods_min		= 2,
39	.periods_max		= 250,
40	.buffer_bytes_max	= 96000,
41};
42
43/* private data for each PCM DSP stream */
44struct sst_byt_pcm_data {
45	struct sst_byt_stream *stream;
46	struct snd_pcm_substream *substream;
47	struct mutex mutex;
48
49	/* latest DSP DMA hw pointer */
50	u32 hw_ptr;
51
52	struct work_struct work;
53};
54
55/* private data for the driver */
56struct sst_byt_priv_data {
57	/* runtime DSP */
58	struct sst_byt *byt;
59
60	/* DAI data */
61	struct sst_byt_pcm_data pcm[BYT_PCM_COUNT];
62
63	/* flag indicating is stream context restore needed after suspend */
64	bool restore_stream;
65};
66
67/* this may get called several times by oss emulation */
68static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream,
69				 struct snd_pcm_hw_params *params)
70{
71	struct snd_soc_pcm_runtime *rtd = substream->private_data;
72	struct sst_byt_priv_data *pdata =
73		snd_soc_platform_get_drvdata(rtd->platform);
74	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
75	struct sst_byt *byt = pdata->byt;
76	u32 rate, bits;
77	u8 channels;
78	int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
79
80	dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data);
81
82	ret = sst_byt_stream_type(byt, pcm_data->stream,
83				  1, 1, !playback);
84	if (ret < 0) {
85		dev_err(rtd->dev, "failed to set stream format %d\n", ret);
86		return ret;
87	}
88
89	rate = params_rate(params);
90	ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate);
91	if (ret < 0) {
92		dev_err(rtd->dev, "could not set rate %d\n", rate);
93		return ret;
94	}
95
96	bits = snd_pcm_format_width(params_format(params));
97	ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits);
98	if (ret < 0) {
99		dev_err(rtd->dev, "could not set formats %d\n",
100			params_rate(params));
101		return ret;
102	}
103
104	channels = (u8)(params_channels(params) & 0xF);
105	ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels);
106	if (ret < 0) {
107		dev_err(rtd->dev, "could not set channels %d\n",
108			params_rate(params));
109		return ret;
110	}
111
112	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
113
114	ret = sst_byt_stream_buffer(byt, pcm_data->stream,
115				    substream->dma_buffer.addr,
116				    params_buffer_bytes(params));
117	if (ret < 0) {
118		dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret);
119		return ret;
120	}
121
122	ret = sst_byt_stream_commit(byt, pcm_data->stream);
123	if (ret < 0) {
124		dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret);
125		return ret;
126	}
127
128	return 0;
129}
130
131static int sst_byt_pcm_hw_free(struct snd_pcm_substream *substream)
132{
133	struct snd_soc_pcm_runtime *rtd = substream->private_data;
134
135	dev_dbg(rtd->dev, "PCM: hw_free\n");
136	snd_pcm_lib_free_pages(substream);
137
138	return 0;
139}
140
141static int sst_byt_pcm_restore_stream_context(struct snd_pcm_substream *substream)
142{
143	struct snd_soc_pcm_runtime *rtd = substream->private_data;
144	struct sst_byt_priv_data *pdata =
145		snd_soc_platform_get_drvdata(rtd->platform);
146	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
147	struct sst_byt *byt = pdata->byt;
148	int ret;
149
150	/* commit stream using existing stream params */
151	ret = sst_byt_stream_commit(byt, pcm_data->stream);
152	if (ret < 0) {
153		dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret);
154		return ret;
155	}
156
157	sst_byt_stream_start(byt, pcm_data->stream, pcm_data->hw_ptr);
158
159	dev_dbg(rtd->dev, "stream context restored at offset %d\n",
160		pcm_data->hw_ptr);
161
162	return 0;
163}
164
165static void sst_byt_pcm_work(struct work_struct *work)
166{
167	struct sst_byt_pcm_data *pcm_data =
168		container_of(work, struct sst_byt_pcm_data, work);
169
170	if (snd_pcm_running(pcm_data->substream))
171		sst_byt_pcm_restore_stream_context(pcm_data->substream);
172}
173
174static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
175{
176	struct snd_soc_pcm_runtime *rtd = substream->private_data;
177	struct sst_byt_priv_data *pdata =
178		snd_soc_platform_get_drvdata(rtd->platform);
179	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
180	struct sst_byt *byt = pdata->byt;
181
182	dev_dbg(rtd->dev, "PCM: trigger %d\n", cmd);
183
184	switch (cmd) {
185	case SNDRV_PCM_TRIGGER_START:
186		pcm_data->hw_ptr = 0;
187		sst_byt_stream_start(byt, pcm_data->stream, 0);
188		break;
189	case SNDRV_PCM_TRIGGER_RESUME:
190		if (pdata->restore_stream == true)
191			schedule_work(&pcm_data->work);
192		else
193			sst_byt_stream_resume(byt, pcm_data->stream);
194		break;
195	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
196		sst_byt_stream_resume(byt, pcm_data->stream);
197		break;
198	case SNDRV_PCM_TRIGGER_STOP:
199		sst_byt_stream_stop(byt, pcm_data->stream);
200		break;
201	case SNDRV_PCM_TRIGGER_SUSPEND:
202		pdata->restore_stream = false;
203	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
204		sst_byt_stream_pause(byt, pcm_data->stream);
205		break;
206	default:
207		break;
208	}
209
210	return 0;
211}
212
213static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data)
214{
215	struct sst_byt_pcm_data *pcm_data = data;
216	struct snd_pcm_substream *substream = pcm_data->substream;
217	struct snd_pcm_runtime *runtime = substream->runtime;
218	struct snd_soc_pcm_runtime *rtd = substream->private_data;
219	struct sst_byt_priv_data *pdata =
220		snd_soc_platform_get_drvdata(rtd->platform);
221	struct sst_byt *byt = pdata->byt;
222	u32 pos, hw_pos;
223
224	hw_pos = sst_byt_get_dsp_position(byt, pcm_data->stream,
225					  snd_pcm_lib_buffer_bytes(substream));
226	pcm_data->hw_ptr = hw_pos;
227	pos = frames_to_bytes(runtime,
228			      (runtime->control->appl_ptr %
229			       runtime->buffer_size));
230
231	dev_dbg(rtd->dev, "PCM: App/DMA pointer %u/%u bytes\n", pos, hw_pos);
232
233	snd_pcm_period_elapsed(substream);
234	return pos;
235}
236
237static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream)
238{
239	struct snd_soc_pcm_runtime *rtd = substream->private_data;
240	struct snd_pcm_runtime *runtime = substream->runtime;
241	struct sst_byt_priv_data *pdata =
242		snd_soc_platform_get_drvdata(rtd->platform);
243	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
244
245	dev_dbg(rtd->dev, "PCM: DMA pointer %u bytes\n", pcm_data->hw_ptr);
246
247	return bytes_to_frames(runtime, pcm_data->hw_ptr);
248}
249
250static int sst_byt_pcm_open(struct snd_pcm_substream *substream)
251{
252	struct snd_soc_pcm_runtime *rtd = substream->private_data;
253	struct sst_byt_priv_data *pdata =
254		snd_soc_platform_get_drvdata(rtd->platform);
255	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
256	struct sst_byt *byt = pdata->byt;
257
258	dev_dbg(rtd->dev, "PCM: open\n");
259
260	mutex_lock(&pcm_data->mutex);
261
262	pcm_data->substream = substream;
263
264	snd_soc_set_runtime_hwparams(substream, &sst_byt_pcm_hardware);
265
266	pcm_data->stream = sst_byt_stream_new(byt, substream->stream + 1,
267					      byt_notify_pointer, pcm_data);
268	if (pcm_data->stream == NULL) {
269		dev_err(rtd->dev, "failed to create stream\n");
270		mutex_unlock(&pcm_data->mutex);
271		return -EINVAL;
272	}
273
274	mutex_unlock(&pcm_data->mutex);
275	return 0;
276}
277
278static int sst_byt_pcm_close(struct snd_pcm_substream *substream)
279{
280	struct snd_soc_pcm_runtime *rtd = substream->private_data;
281	struct sst_byt_priv_data *pdata =
282		snd_soc_platform_get_drvdata(rtd->platform);
283	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
284	struct sst_byt *byt = pdata->byt;
285	int ret;
286
287	dev_dbg(rtd->dev, "PCM: close\n");
288
289	cancel_work_sync(&pcm_data->work);
290	mutex_lock(&pcm_data->mutex);
291	ret = sst_byt_stream_free(byt, pcm_data->stream);
292	if (ret < 0) {
293		dev_dbg(rtd->dev, "Free stream fail\n");
294		goto out;
295	}
296	pcm_data->stream = NULL;
297
298out:
299	mutex_unlock(&pcm_data->mutex);
300	return ret;
301}
302
303static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream,
304			    struct vm_area_struct *vma)
305{
306	struct snd_soc_pcm_runtime *rtd = substream->private_data;
307
308	dev_dbg(rtd->dev, "PCM: mmap\n");
309	return snd_pcm_lib_default_mmap(substream, vma);
310}
311
312static struct snd_pcm_ops sst_byt_pcm_ops = {
313	.open		= sst_byt_pcm_open,
314	.close		= sst_byt_pcm_close,
315	.ioctl		= snd_pcm_lib_ioctl,
316	.hw_params	= sst_byt_pcm_hw_params,
317	.hw_free	= sst_byt_pcm_hw_free,
318	.trigger	= sst_byt_pcm_trigger,
319	.pointer	= sst_byt_pcm_pointer,
320	.mmap		= sst_byt_pcm_mmap,
321};
322
323static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd)
324{
325	struct snd_pcm *pcm = rtd->pcm;
326	size_t size;
327	struct snd_soc_platform *platform = rtd->platform;
328	struct sst_pdata *pdata = dev_get_platdata(platform->dev);
329	int ret = 0;
330
331	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
332	    pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
333		size = sst_byt_pcm_hardware.buffer_bytes_max;
334		ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
335							    SNDRV_DMA_TYPE_DEV,
336							    pdata->dma_dev,
337							    size, size);
338		if (ret) {
339			dev_err(rtd->dev, "dma buffer allocation failed %d\n",
340				ret);
341			return ret;
342		}
343	}
344
345	return ret;
346}
347
348static struct snd_soc_dai_driver byt_dais[] = {
349	{
350		.name  = "Baytrail PCM",
351		.playback = {
352			.stream_name = "System Playback",
353			.channels_min = 2,
354			.channels_max = 2,
355			.rates = SNDRV_PCM_RATE_48000,
356			.formats = SNDRV_PCM_FMTBIT_S24_3LE |
357				   SNDRV_PCM_FMTBIT_S16_LE,
358		},
359		.capture = {
360			.stream_name = "Analog Capture",
361			.channels_min = 2,
362			.channels_max = 2,
363			.rates = SNDRV_PCM_RATE_48000,
364			.formats = SNDRV_PCM_FMTBIT_S16_LE,
365		},
366	},
367};
368
369static int sst_byt_pcm_probe(struct snd_soc_platform *platform)
370{
371	struct sst_pdata *plat_data = dev_get_platdata(platform->dev);
372	struct sst_byt_priv_data *priv_data;
373	int i;
374
375	if (!plat_data)
376		return -ENODEV;
377
378	priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data),
379				 GFP_KERNEL);
380	priv_data->byt = plat_data->dsp;
381	snd_soc_platform_set_drvdata(platform, priv_data);
382
383	for (i = 0; i < BYT_PCM_COUNT; i++) {
384		mutex_init(&priv_data->pcm[i].mutex);
385		INIT_WORK(&priv_data->pcm[i].work, sst_byt_pcm_work);
386	}
387
388	return 0;
389}
390
391static int sst_byt_pcm_remove(struct snd_soc_platform *platform)
392{
393	return 0;
394}
395
396static struct snd_soc_platform_driver byt_soc_platform = {
397	.probe		= sst_byt_pcm_probe,
398	.remove		= sst_byt_pcm_remove,
399	.ops		= &sst_byt_pcm_ops,
400	.pcm_new	= sst_byt_pcm_new,
401};
402
403static const struct snd_soc_component_driver byt_dai_component = {
404	.name		= "byt-dai",
405};
406
407#ifdef CONFIG_PM
408static int sst_byt_pcm_dev_suspend_late(struct device *dev)
409{
410	struct sst_pdata *sst_pdata = dev_get_platdata(dev);
411	struct sst_byt_priv_data *priv_data = dev_get_drvdata(dev);
412	int ret;
413
414	dev_dbg(dev, "suspending late\n");
415
416	ret = sst_byt_dsp_suspend_late(dev, sst_pdata);
417	if (ret < 0) {
418		dev_err(dev, "failed to suspend %d\n", ret);
419		return ret;
420	}
421
422	priv_data->restore_stream = true;
423
424	return ret;
425}
426
427static int sst_byt_pcm_dev_resume_early(struct device *dev)
428{
429	struct sst_pdata *sst_pdata = dev_get_platdata(dev);
430	int ret;
431
432	dev_dbg(dev, "resume early\n");
433
434	/* load fw and boot DSP */
435	ret = sst_byt_dsp_boot(dev, sst_pdata);
436	if (ret)
437		return ret;
438
439	/* wait for FW to finish booting */
440	return sst_byt_dsp_wait_for_ready(dev, sst_pdata);
441}
442
443static const struct dev_pm_ops sst_byt_pm_ops = {
444	.suspend_late = sst_byt_pcm_dev_suspend_late,
445	.resume_early = sst_byt_pcm_dev_resume_early,
446};
447
448#define SST_BYT_PM_OPS	(&sst_byt_pm_ops)
449#else
450#define SST_BYT_PM_OPS	NULL
451#endif
452
453static int sst_byt_pcm_dev_probe(struct platform_device *pdev)
454{
455	struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev);
456	int ret;
457
458	ret = sst_byt_dsp_init(&pdev->dev, sst_pdata);
459	if (ret < 0)
460		return -ENODEV;
461
462	ret = snd_soc_register_platform(&pdev->dev, &byt_soc_platform);
463	if (ret < 0)
464		goto err_plat;
465
466	ret = snd_soc_register_component(&pdev->dev, &byt_dai_component,
467					 byt_dais, ARRAY_SIZE(byt_dais));
468	if (ret < 0)
469		goto err_comp;
470
471	return 0;
472
473err_comp:
474	snd_soc_unregister_platform(&pdev->dev);
475err_plat:
476	sst_byt_dsp_free(&pdev->dev, sst_pdata);
477	return ret;
478}
479
480static int sst_byt_pcm_dev_remove(struct platform_device *pdev)
481{
482	struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev);
483
484	snd_soc_unregister_platform(&pdev->dev);
485	snd_soc_unregister_component(&pdev->dev);
486	sst_byt_dsp_free(&pdev->dev, sst_pdata);
487
488	return 0;
489}
490
491static struct platform_driver sst_byt_pcm_driver = {
492	.driver = {
493		.name = "baytrail-pcm-audio",
494		.pm = SST_BYT_PM_OPS,
495	},
496
497	.probe = sst_byt_pcm_dev_probe,
498	.remove = sst_byt_pcm_dev_remove,
499};
500module_platform_driver(sst_byt_pcm_driver);
501
502MODULE_AUTHOR("Jarkko Nikula");
503MODULE_DESCRIPTION("Baytrail PCM");
504MODULE_LICENSE("GPL v2");
505MODULE_ALIAS("platform:baytrail-pcm-audio");
506