xref: /linux/sound/soc/intel/catpt/pcm.c (revision 06152e33686112d5d49a44301eb0d55d0012d48d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2020 Intel Corporation
4 //
5 // Author: Cezary Rojewski <cezary.rojewski@intel.com>
6 //
7 
8 #include <linux/cleanup.h>
9 #include <linux/pm_runtime.h>
10 #include <sound/soc.h>
11 #include <sound/pcm_params.h>
12 #include <uapi/sound/tlv.h>
13 #include "core.h"
14 #include "messages.h"
15 
16 struct catpt_stream_template {
17 	enum catpt_path_id path_id;
18 	enum catpt_stream_type type;
19 	u32 persistent_size;
20 	u8 num_entries;
21 	struct catpt_module_entry entries[];
22 };
23 
24 static struct catpt_stream_template system_pb = {
25 	.path_id = CATPT_PATH_SSP0_OUT,
26 	.type = CATPT_STRM_TYPE_SYSTEM,
27 	.num_entries = 1,
28 	.entries = {{ CATPT_MODID_PCM_SYSTEM, 0 }},
29 };
30 
31 static struct catpt_stream_template system_cp = {
32 	.path_id = CATPT_PATH_SSP0_IN,
33 	.type = CATPT_STRM_TYPE_CAPTURE,
34 	.num_entries = 1,
35 	.entries = {{ CATPT_MODID_PCM_CAPTURE, 0 }},
36 };
37 
38 static struct catpt_stream_template offload_pb = {
39 	.path_id = CATPT_PATH_SSP0_OUT,
40 	.type = CATPT_STRM_TYPE_RENDER,
41 	.num_entries = 1,
42 	.entries = {{ CATPT_MODID_PCM, 0 }},
43 };
44 
45 static struct catpt_stream_template loopback_cp = {
46 	.path_id = CATPT_PATH_SSP0_OUT,
47 	.type = CATPT_STRM_TYPE_LOOPBACK,
48 	.num_entries = 1,
49 	.entries = {{ CATPT_MODID_PCM_REFERENCE, 0 }},
50 };
51 
52 static struct catpt_stream_template bluetooth_pb = {
53 	.path_id = CATPT_PATH_SSP1_OUT,
54 	.type = CATPT_STRM_TYPE_BLUETOOTH_RENDER,
55 	.num_entries = 1,
56 	.entries = {{ CATPT_MODID_BLUETOOTH_RENDER, 0 }},
57 };
58 
59 static struct catpt_stream_template bluetooth_cp = {
60 	.path_id = CATPT_PATH_SSP1_IN,
61 	.type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE,
62 	.num_entries = 1,
63 	.entries = {{ CATPT_MODID_BLUETOOTH_CAPTURE, 0 }},
64 };
65 
66 static struct catpt_stream_template *catpt_topology[] = {
67 	[CATPT_STRM_TYPE_RENDER]		= &offload_pb,
68 	[CATPT_STRM_TYPE_SYSTEM]		= &system_pb,
69 	[CATPT_STRM_TYPE_CAPTURE]		= &system_cp,
70 	[CATPT_STRM_TYPE_LOOPBACK]		= &loopback_cp,
71 	[CATPT_STRM_TYPE_BLUETOOTH_RENDER]	= &bluetooth_pb,
72 	[CATPT_STRM_TYPE_BLUETOOTH_CAPTURE]	= &bluetooth_cp,
73 };
74 
75 static struct catpt_stream_template *
76 catpt_get_stream_template(struct snd_pcm_substream *substream)
77 {
78 	struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream);
79 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtm, 0);
80 	enum catpt_stream_type type;
81 
82 	type = cpu_dai->driver->id;
83 
84 	/* account for capture in bidirectional dais */
85 	switch (type) {
86 	case CATPT_STRM_TYPE_SYSTEM:
87 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
88 			type = CATPT_STRM_TYPE_CAPTURE;
89 		break;
90 	case CATPT_STRM_TYPE_BLUETOOTH_RENDER:
91 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
92 			type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE;
93 		break;
94 	default:
95 		break;
96 	}
97 
98 	return catpt_topology[type];
99 }
100 
101 /* Caller responsible for holding ->stream_mutex. */
102 struct catpt_stream_runtime *catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
103 {
104 	struct catpt_stream_runtime *stream;
105 
106 	list_for_each_entry(stream, &cdev->stream_list, node)
107 		if (stream->info.stream_hw_id == stream_hw_id)
108 			return stream;
109 
110 	return NULL;
111 }
112 
113 /* Caller responsible for holding ->stream_mutex. */
114 static u8 catpt_stream_hw_id(struct catpt_dev *cdev, enum catpt_pin_id pin_id)
115 {
116 	struct catpt_stream_runtime *stream;
117 
118 	switch (pin_id) {
119 	default:
120 		stream = catpt_stream_find(cdev, pin_id);
121 		if (stream)
122 			return stream->info.stream_hw_id;
123 		break;
124 	case CATPT_PIN_ID_MIXER:
125 		if (!list_empty(&cdev->stream_list))
126 			return cdev->mixer.mixer_hw_id;
127 		break;
128 	}
129 
130 	return CATPT_PIN_ID_INVALID;
131 }
132 
133 /* Caller responsible for holding ->stream_mutex. */
134 static u32 *catpt_stream_volume_regs(struct catpt_dev *cdev, enum catpt_pin_id pin_id)
135 {
136 	struct catpt_stream_runtime *stream;
137 
138 	switch (pin_id) {
139 	case CATPT_PIN_ID_MIXER:
140 		if (!list_empty(&cdev->stream_list))
141 			return &cdev->mixer.volume_regaddr[0];
142 		break;
143 	default:
144 		stream = catpt_stream_find(cdev, pin_id);
145 		if (stream)
146 			return &stream->info.volume_regaddr[0];
147 		break;
148 	}
149 
150 	return NULL;
151 }
152 
153 static void catpt_stream_read_position(struct catpt_dev *cdev,
154 				       struct catpt_stream_runtime *stream, u32 *pos)
155 {
156 	memcpy_fromio(pos, cdev->lpe_ba + stream->info.read_pos_regaddr, sizeof(*pos));
157 }
158 
159 static void catpt_arrange_page_table(struct snd_pcm_substream *substream,
160 				     struct snd_dma_buffer *pgtbl)
161 {
162 	struct snd_pcm_runtime *rtm = substream->runtime;
163 	struct snd_dma_buffer *databuf = snd_pcm_get_dma_buf(substream);
164 	int i, pages;
165 
166 	pages = snd_sgbuf_aligned_pages(rtm->dma_bytes);
167 
168 	for (i = 0; i < pages; i++) {
169 		u32 pfn, offset;
170 		u32 *page_table;
171 
172 		pfn = PFN_DOWN(snd_sgbuf_get_addr(databuf, i * PAGE_SIZE));
173 		/* incrementing by 2 on even and 3 on odd */
174 		offset = ((i << 2) + i) >> 1;
175 		page_table = (u32 *)(pgtbl->area + offset);
176 
177 		if (i & 1)
178 			*page_table |= (pfn << 4);
179 		else
180 			*page_table |= pfn;
181 	}
182 }
183 
184 static u32 catpt_get_channel_map(enum catpt_channel_config config)
185 {
186 	switch (config) {
187 	case CATPT_CHANNEL_CONFIG_MONO:
188 		return GENMASK(31, 4) | CATPT_CHANNEL_CENTER;
189 
190 	case CATPT_CHANNEL_CONFIG_STEREO:
191 		return GENMASK(31, 8) | CATPT_CHANNEL_LEFT
192 				      | (CATPT_CHANNEL_RIGHT << 4);
193 
194 	case CATPT_CHANNEL_CONFIG_2_POINT_1:
195 		return GENMASK(31, 12) | CATPT_CHANNEL_LEFT
196 				       | (CATPT_CHANNEL_RIGHT << 4)
197 				       | (CATPT_CHANNEL_LFE << 8);
198 
199 	case CATPT_CHANNEL_CONFIG_3_POINT_0:
200 		return GENMASK(31, 12) | CATPT_CHANNEL_LEFT
201 				       | (CATPT_CHANNEL_CENTER << 4)
202 				       | (CATPT_CHANNEL_RIGHT << 8);
203 
204 	case CATPT_CHANNEL_CONFIG_3_POINT_1:
205 		return GENMASK(31, 16) | CATPT_CHANNEL_LEFT
206 				       | (CATPT_CHANNEL_CENTER << 4)
207 				       | (CATPT_CHANNEL_RIGHT << 8)
208 				       | (CATPT_CHANNEL_LFE << 12);
209 
210 	case CATPT_CHANNEL_CONFIG_QUATRO:
211 		return GENMASK(31, 16) | CATPT_CHANNEL_LEFT
212 				       | (CATPT_CHANNEL_RIGHT << 4)
213 				       | (CATPT_CHANNEL_LEFT_SURROUND << 8)
214 				       | (CATPT_CHANNEL_RIGHT_SURROUND << 12);
215 
216 	case CATPT_CHANNEL_CONFIG_4_POINT_0:
217 		return GENMASK(31, 16) | CATPT_CHANNEL_LEFT
218 				       | (CATPT_CHANNEL_CENTER << 4)
219 				       | (CATPT_CHANNEL_RIGHT << 8)
220 				       | (CATPT_CHANNEL_CENTER_SURROUND << 12);
221 
222 	case CATPT_CHANNEL_CONFIG_5_POINT_0:
223 		return GENMASK(31, 20) | CATPT_CHANNEL_LEFT
224 				       | (CATPT_CHANNEL_CENTER << 4)
225 				       | (CATPT_CHANNEL_RIGHT << 8)
226 				       | (CATPT_CHANNEL_LEFT_SURROUND << 12)
227 				       | (CATPT_CHANNEL_RIGHT_SURROUND << 16);
228 
229 	case CATPT_CHANNEL_CONFIG_5_POINT_1:
230 		return GENMASK(31, 24) | CATPT_CHANNEL_CENTER
231 				       | (CATPT_CHANNEL_LEFT << 4)
232 				       | (CATPT_CHANNEL_RIGHT << 8)
233 				       | (CATPT_CHANNEL_LEFT_SURROUND << 12)
234 				       | (CATPT_CHANNEL_RIGHT_SURROUND << 16)
235 				       | (CATPT_CHANNEL_LFE << 20);
236 
237 	case CATPT_CHANNEL_CONFIG_DUAL_MONO:
238 		return GENMASK(31, 8) | CATPT_CHANNEL_LEFT
239 				      | (CATPT_CHANNEL_LEFT << 4);
240 
241 	default:
242 		return U32_MAX;
243 	}
244 }
245 
246 static enum catpt_channel_config catpt_get_channel_config(u32 num_channels)
247 {
248 	switch (num_channels) {
249 	case 6:
250 		return CATPT_CHANNEL_CONFIG_5_POINT_1;
251 	case 5:
252 		return CATPT_CHANNEL_CONFIG_5_POINT_0;
253 	case 4:
254 		return CATPT_CHANNEL_CONFIG_QUATRO;
255 	case 3:
256 		return CATPT_CHANNEL_CONFIG_2_POINT_1;
257 	case 1:
258 		return CATPT_CHANNEL_CONFIG_MONO;
259 	case 2:
260 	default:
261 		return CATPT_CHANNEL_CONFIG_STEREO;
262 	}
263 }
264 
265 static int catpt_dai_startup(struct snd_pcm_substream *substream,
266 			     struct snd_soc_dai *dai)
267 {
268 	struct catpt_stream_template *template;
269 	struct catpt_stream_runtime *stream;
270 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
271 	struct resource *res;
272 	int ret;
273 
274 	template = catpt_get_stream_template(substream);
275 
276 	stream = kzalloc_obj(*stream);
277 	if (!stream)
278 		return -ENOMEM;
279 
280 	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, cdev->dev, PAGE_SIZE,
281 				  &stream->pgtbl);
282 	if (ret)
283 		goto err_pgtbl;
284 
285 	res = catpt_request_region(&cdev->dram, template->persistent_size);
286 	if (!res) {
287 		ret = -EBUSY;
288 		goto err_request;
289 	}
290 
291 	catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask);
292 
293 	stream->template = template;
294 	stream->persistent = res;
295 	stream->substream = substream;
296 	INIT_LIST_HEAD(&stream->node);
297 	snd_soc_dai_set_dma_data(dai, substream, stream);
298 
299 	return 0;
300 
301 err_request:
302 	snd_dma_free_pages(&stream->pgtbl);
303 err_pgtbl:
304 	kfree(stream);
305 	return ret;
306 }
307 
308 static void catpt_dai_shutdown(struct snd_pcm_substream *substream,
309 			       struct snd_soc_dai *dai)
310 {
311 	struct catpt_stream_runtime *stream;
312 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
313 
314 	stream = snd_soc_dai_get_dma_data(dai, substream);
315 
316 	release_resource(stream->persistent);
317 	kfree(stream->persistent);
318 	catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask);
319 
320 	snd_dma_free_pages(&stream->pgtbl);
321 	kfree(stream);
322 	snd_soc_dai_set_dma_data(dai, substream, NULL);
323 }
324 
325 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol);
326 
327 struct catpt_control_data {
328 	enum catpt_pin_id pin_id;
329 	long volumes[CATPT_CHANNELS_MAX];
330 };
331 
332 static int catpt_apply_volume(struct catpt_dev *cdev, struct snd_soc_card *card, const char *name)
333 {
334 	struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card->snd_card, name);
335 	struct catpt_control_data *data;
336 
337 	if (!kctl)
338 		return -ENOENT;
339 	data = (struct catpt_control_data *)kctl->private_value;
340 
341 	return catpt_set_dspvol(cdev, data->pin_id, data->volumes);
342 }
343 
344 static int catpt_apply_mute(struct catpt_dev *cdev, struct snd_soc_card *card)
345 {
346 	struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card->snd_card, "Loopback Mute");
347 	bool mute;
348 	int ret;
349 
350 	if (!kctl)
351 		return -ENOENT;
352 	mute = *(bool *)kctl->private_value;
353 
354 	ret = catpt_ipc_mute_loopback(cdev, CATPT_PIN_ID_REFERENCE, mute);
355 	return CATPT_IPC_RET(ret);
356 }
357 
358 static int catpt_apply_controls(struct catpt_dev *cdev, struct snd_soc_card *card,
359 				struct catpt_stream_runtime *stream)
360 {
361 	int ret;
362 
363 	/* Update the master volume when the first stream is opened. */
364 	if (list_empty(&cdev->stream_list)) {
365 		ret = catpt_apply_volume(cdev, card, "Master Playback Volume");
366 		if (ret)
367 			return ret;
368 	}
369 
370 	/* Only selected streams have individual controls. */
371 	switch (stream->info.stream_hw_id) {
372 	case CATPT_PIN_ID_OFFLOAD1:
373 		return catpt_apply_volume(cdev, card, "Media0 Playback Volume");
374 	case CATPT_PIN_ID_OFFLOAD2:
375 		return catpt_apply_volume(cdev, card, "Media1 Playback Volume");
376 	case CATPT_PIN_ID_CAPTURE1:
377 		return catpt_apply_volume(cdev, card, "Mic Capture Volume");
378 	case CATPT_PIN_ID_REFERENCE:
379 		return catpt_apply_mute(cdev, card);
380 	default:
381 		return 0;
382 	}
383 }
384 
385 static int catpt_dai_hw_params(struct snd_pcm_substream *substream,
386 			       struct snd_pcm_hw_params *params,
387 			       struct snd_soc_dai *dai)
388 {
389 	struct snd_pcm_runtime *rtm = substream->runtime;
390 	struct snd_dma_buffer *dmab;
391 	struct catpt_stream_runtime *stream;
392 	struct catpt_audio_format afmt;
393 	struct catpt_ring_info rinfo;
394 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
395 	int ret;
396 
397 	stream = snd_soc_dai_get_dma_data(dai, substream);
398 	if (stream->allocated)
399 		return 0;
400 
401 	memset(&afmt, 0, sizeof(afmt));
402 	afmt.sample_rate = params_rate(params);
403 	afmt.bit_depth = params_physical_width(params);
404 	afmt.valid_bit_depth = params_width(params);
405 	afmt.num_channels = params_channels(params);
406 	afmt.channel_config = catpt_get_channel_config(afmt.num_channels);
407 	afmt.channel_map = catpt_get_channel_map(afmt.channel_config);
408 	afmt.interleaving = CATPT_INTERLEAVING_PER_CHANNEL;
409 
410 	dmab = snd_pcm_get_dma_buf(substream);
411 	catpt_arrange_page_table(substream, &stream->pgtbl);
412 
413 	memset(&rinfo, 0, sizeof(rinfo));
414 	rinfo.page_table_addr = stream->pgtbl.addr;
415 	rinfo.num_pages = DIV_ROUND_UP(rtm->dma_bytes, PAGE_SIZE);
416 	rinfo.size = rtm->dma_bytes;
417 	rinfo.offset = 0;
418 	rinfo.ring_first_page_pfn = PFN_DOWN(snd_sgbuf_get_addr(dmab, 0));
419 
420 	ret = catpt_ipc_alloc_stream(cdev, stream->template->path_id,
421 				     stream->template->type,
422 				     &afmt, &rinfo,
423 				     stream->template->num_entries,
424 				     stream->template->entries,
425 				     stream->persistent,
426 				     cdev->scratch,
427 				     &stream->info);
428 	if (ret)
429 		return CATPT_IPC_RET(ret);
430 
431 	guard(mutex)(&cdev->stream_mutex);
432 
433 	ret = catpt_apply_controls(cdev, dai->component->card, stream);
434 	if (ret) {
435 		catpt_ipc_free_stream(cdev, stream->info.stream_hw_id);
436 		return ret;
437 	}
438 
439 	list_add_tail(&stream->node, &cdev->stream_list);
440 	stream->allocated = true;
441 	return 0;
442 }
443 
444 static int catpt_dai_hw_free(struct snd_pcm_substream *substream,
445 			     struct snd_soc_dai *dai)
446 {
447 	struct catpt_stream_runtime *stream;
448 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
449 
450 	stream = snd_soc_dai_get_dma_data(dai, substream);
451 	if (!stream->allocated)
452 		return 0;
453 
454 	mutex_lock(&cdev->stream_mutex);
455 	list_del(&stream->node);
456 	mutex_unlock(&cdev->stream_mutex);
457 
458 	catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id);
459 	catpt_ipc_free_stream(cdev, stream->info.stream_hw_id);
460 
461 	stream->allocated = false;
462 	return 0;
463 }
464 
465 static int catpt_dai_prepare(struct snd_pcm_substream *substream,
466 			     struct snd_soc_dai *dai)
467 {
468 	struct catpt_stream_runtime *stream;
469 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
470 	int ret;
471 
472 	stream = snd_soc_dai_get_dma_data(dai, substream);
473 	if (stream->prepared)
474 		return 0;
475 
476 	ret = catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id);
477 	if (ret)
478 		return CATPT_IPC_RET(ret);
479 
480 	ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id);
481 	if (ret)
482 		return CATPT_IPC_RET(ret);
483 
484 	stream->prepared = true;
485 	return 0;
486 }
487 
488 static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd,
489 			     struct snd_soc_dai *dai)
490 {
491 	struct snd_pcm_runtime *runtime = substream->runtime;
492 	struct catpt_stream_runtime *stream;
493 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
494 	snd_pcm_uframes_t pos;
495 	int ret;
496 
497 	stream = snd_soc_dai_get_dma_data(dai, substream);
498 
499 	switch (cmd) {
500 	case SNDRV_PCM_TRIGGER_START:
501 		/* only offload is set_write_pos driven */
502 		if (stream->template->type != CATPT_STRM_TYPE_RENDER)
503 			goto resume_stream;
504 
505 		pos = frames_to_bytes(runtime, runtime->start_threshold);
506 		/*
507 		 * Dsp operates on buffer halves, thus max 2x set_write_pos
508 		 * (entire buffer filled) prior to stream start.
509 		 */
510 		ret = catpt_ipc_set_write_pos(cdev, stream->info.stream_hw_id,
511 					      pos, false, false);
512 		if (ret)
513 			return CATPT_IPC_RET(ret);
514 		fallthrough;
515 	case SNDRV_PCM_TRIGGER_RESUME:
516 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
517 	resume_stream:
518 		catpt_dsp_update_lpclock(cdev);
519 		ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id);
520 		if (ret)
521 			return CATPT_IPC_RET(ret);
522 		break;
523 
524 	case SNDRV_PCM_TRIGGER_STOP:
525 		stream->prepared = false;
526 		fallthrough;
527 	case SNDRV_PCM_TRIGGER_SUSPEND:
528 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
529 		ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id);
530 		catpt_dsp_update_lpclock(cdev);
531 		if (ret)
532 			return CATPT_IPC_RET(ret);
533 		break;
534 
535 	default:
536 		break;
537 	}
538 
539 	return 0;
540 }
541 
542 void catpt_stream_update_position(struct catpt_dev *cdev,
543 				  struct catpt_stream_runtime *stream,
544 				  struct catpt_notify_position *pos)
545 {
546 	struct snd_pcm_substream *substream = stream->substream;
547 	struct snd_pcm_runtime *r = substream->runtime;
548 	snd_pcm_uframes_t dsppos, newpos;
549 	int ret;
550 
551 	dsppos = bytes_to_frames(r, pos->stream_position);
552 
553 	if (!stream->prepared)
554 		goto exit;
555 	/* only offload is set_write_pos driven */
556 	if (stream->template->type != CATPT_STRM_TYPE_RENDER)
557 		goto exit;
558 
559 	if (dsppos >= r->buffer_size / 2)
560 		newpos = r->buffer_size / 2;
561 	else
562 		newpos = 0;
563 	/*
564 	 * Dsp operates on buffer halves, thus on every notify position
565 	 * (buffer half consumed) update wp to allow stream progression.
566 	 */
567 	ret = catpt_ipc_set_write_pos(cdev, stream->info.stream_hw_id,
568 				      frames_to_bytes(r, newpos),
569 				      false, false);
570 	if (ret) {
571 		dev_err(cdev->dev, "update position for stream %d failed: %d\n",
572 			stream->info.stream_hw_id, ret);
573 		return;
574 	}
575 exit:
576 	snd_pcm_period_elapsed(substream);
577 }
578 
579 /* 200 ms for 2 32-bit channels at 48kHz (native format) */
580 #define CATPT_BUFFER_MAX_SIZE	76800
581 #define CATPT_PCM_PERIODS_MAX	4
582 #define CATPT_PCM_PERIODS_MIN	2
583 
584 static const struct snd_pcm_hardware catpt_pcm_hardware = {
585 	.info			= SNDRV_PCM_INFO_MMAP |
586 				  SNDRV_PCM_INFO_MMAP_VALID |
587 				  SNDRV_PCM_INFO_INTERLEAVED |
588 				  SNDRV_PCM_INFO_PAUSE |
589 				  SNDRV_PCM_INFO_RESUME |
590 				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
591 	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
592 				  SNDRV_PCM_FMTBIT_S32_LE,
593 	.subformats		= SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
594 				  SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
595 	.period_bytes_min	= PAGE_SIZE,
596 	.period_bytes_max	= CATPT_BUFFER_MAX_SIZE / CATPT_PCM_PERIODS_MIN,
597 	.periods_min		= CATPT_PCM_PERIODS_MIN,
598 	.periods_max		= CATPT_PCM_PERIODS_MAX,
599 	.buffer_bytes_max	= CATPT_BUFFER_MAX_SIZE,
600 };
601 
602 static int catpt_component_pcm_new(struct snd_soc_component *component,
603 				   struct snd_soc_pcm_runtime *rtm)
604 {
605 	struct catpt_dev *cdev = dev_get_drvdata(component->dev);
606 
607 	snd_pcm_set_managed_buffer_all(rtm->pcm, SNDRV_DMA_TYPE_DEV_SG,
608 				       cdev->dev,
609 				       catpt_pcm_hardware.buffer_bytes_max,
610 				       catpt_pcm_hardware.buffer_bytes_max);
611 
612 	return 0;
613 }
614 
615 static int catpt_component_open(struct snd_soc_component *component,
616 				struct snd_pcm_substream *substream)
617 {
618 	struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream);
619 
620 	if (!rtm->dai_link->no_pcm)
621 		snd_soc_set_runtime_hwparams(substream, &catpt_pcm_hardware);
622 	return 0;
623 }
624 
625 static snd_pcm_uframes_t
626 catpt_component_pointer(struct snd_soc_component *component,
627 			struct snd_pcm_substream *substream)
628 {
629 	struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream);
630 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtm, 0);
631 	struct catpt_stream_runtime *stream;
632 	struct catpt_dev *cdev = dev_get_drvdata(component->dev);
633 	u32 pos;
634 
635 	if (rtm->dai_link->no_pcm)
636 		return 0;
637 
638 	stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
639 	catpt_stream_read_position(cdev, stream, &pos);
640 
641 	return bytes_to_frames(substream->runtime, pos);
642 }
643 
644 static const struct snd_soc_dai_ops catpt_fe_dai_ops = {
645 	.startup = catpt_dai_startup,
646 	.shutdown = catpt_dai_shutdown,
647 	.hw_params = catpt_dai_hw_params,
648 	.hw_free = catpt_dai_hw_free,
649 	.prepare = catpt_dai_prepare,
650 	.trigger = catpt_dai_trigger,
651 };
652 
653 static int catpt_dai_pcm_new(struct snd_soc_pcm_runtime *rtm,
654 			     struct snd_soc_dai *dai)
655 {
656 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtm, 0);
657 	struct catpt_ssp_device_format devfmt;
658 	struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
659 	int ret;
660 
661 	devfmt.iface = dai->driver->id;
662 	devfmt.channels = codec_dai->driver->capture.channels_max;
663 
664 	switch (devfmt.iface) {
665 	case CATPT_SSP_IFACE_0:
666 		devfmt.mclk = CATPT_MCLK_FREQ_24_MHZ;
667 
668 		switch (devfmt.channels) {
669 		case 4:
670 			devfmt.mode = CATPT_SSP_MODE_TDM_PROVIDER;
671 			devfmt.clock_divider = 4;
672 			break;
673 		case 2:
674 		default:
675 			devfmt.mode = CATPT_SSP_MODE_I2S_PROVIDER;
676 			devfmt.clock_divider = 9;
677 			break;
678 		}
679 		break;
680 
681 	case CATPT_SSP_IFACE_1:
682 		devfmt.mclk = CATPT_MCLK_OFF;
683 		devfmt.mode = CATPT_SSP_MODE_I2S_CONSUMER;
684 		devfmt.clock_divider = 0;
685 		break;
686 	}
687 
688 	/* see if this is a new configuration */
689 	if (!memcmp(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt)))
690 		return 0;
691 
692 	ret = pm_runtime_resume_and_get(cdev->dev);
693 	if (ret)
694 		return ret;
695 
696 	ret = catpt_ipc_set_device_format(cdev, &devfmt);
697 
698 	pm_runtime_put_autosuspend(cdev->dev);
699 
700 	if (ret)
701 		return CATPT_IPC_RET(ret);
702 
703 	/* store device format set for given SSP */
704 	memcpy(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt));
705 	return 0;
706 }
707 
708 static const struct snd_soc_dai_ops catpt_dai_ops = {
709 	.pcm_new = catpt_dai_pcm_new,
710 };
711 
712 static struct snd_soc_dai_driver dai_drivers[] = {
713 /* FE DAIs */
714 {
715 	.name = "System Pin",
716 	.id = CATPT_STRM_TYPE_SYSTEM,
717 	.ops = &catpt_fe_dai_ops,
718 	.playback = {
719 		.stream_name = "System Playback",
720 		.channels_min = 2,
721 		.channels_max = 2,
722 		.rates = SNDRV_PCM_RATE_48000,
723 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
724 		.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
725 			      SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
726 	},
727 	.capture = {
728 		.stream_name = "Analog Capture",
729 		.channels_min = 2,
730 		.channels_max = 4,
731 		.rates = SNDRV_PCM_RATE_48000,
732 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
733 		.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
734 			      SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
735 	},
736 },
737 {
738 	.name = "Offload0 Pin",
739 	.id = CATPT_STRM_TYPE_RENDER,
740 	.ops = &catpt_fe_dai_ops,
741 	.playback = {
742 		.stream_name = "Offload0 Playback",
743 		.channels_min = 2,
744 		.channels_max = 2,
745 		.rates = SNDRV_PCM_RATE_8000_192000,
746 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
747 		.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
748 			      SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
749 	},
750 },
751 {
752 	.name = "Offload1 Pin",
753 	.id = CATPT_STRM_TYPE_RENDER,
754 	.ops = &catpt_fe_dai_ops,
755 	.playback = {
756 		.stream_name = "Offload1 Playback",
757 		.channels_min = 2,
758 		.channels_max = 2,
759 		.rates = SNDRV_PCM_RATE_8000_192000,
760 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
761 		.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
762 			      SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
763 	},
764 },
765 {
766 	.name = "Loopback Pin",
767 	.id = CATPT_STRM_TYPE_LOOPBACK,
768 	.ops = &catpt_fe_dai_ops,
769 	.capture = {
770 		.stream_name = "Loopback Capture",
771 		.channels_min = 2,
772 		.channels_max = 2,
773 		.rates = SNDRV_PCM_RATE_48000,
774 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
775 		.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
776 			      SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
777 	},
778 },
779 {
780 	.name = "Bluetooth Pin",
781 	.id = CATPT_STRM_TYPE_BLUETOOTH_RENDER,
782 	.ops = &catpt_fe_dai_ops,
783 	.playback = {
784 		.stream_name = "Bluetooth Playback",
785 		.channels_min = 1,
786 		.channels_max = 1,
787 		.rates = SNDRV_PCM_RATE_8000,
788 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
789 	},
790 	.capture = {
791 		.stream_name = "Bluetooth Capture",
792 		.channels_min = 1,
793 		.channels_max = 1,
794 		.rates = SNDRV_PCM_RATE_8000,
795 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
796 	},
797 },
798 /* BE DAIs */
799 {
800 	.name = "ssp0-port",
801 	.id = CATPT_SSP_IFACE_0,
802 	.playback = {
803 		.channels_min = 1,
804 		.channels_max = 8,
805 	},
806 	.capture = {
807 		.channels_min = 1,
808 		.channels_max = 8,
809 	},
810 	.ops = &catpt_dai_ops,
811 },
812 {
813 	.name = "ssp1-port",
814 	.id = CATPT_SSP_IFACE_1,
815 	.playback = {
816 		.channels_min = 1,
817 		.channels_max = 8,
818 	},
819 	.capture = {
820 		.channels_min = 1,
821 		.channels_max = 8,
822 	},
823 	.ops = &catpt_dai_ops,
824 },
825 };
826 
827 #define DSP_VOLUME_MAX		S32_MAX /* 0db */
828 #define DSP_VOLUME_STEP_MAX	30
829 
830 static u32 ctlvol_to_dspvol(u32 value)
831 {
832 	if (value > DSP_VOLUME_STEP_MAX)
833 		value = 0;
834 	return DSP_VOLUME_MAX >> (DSP_VOLUME_STEP_MAX - value);
835 }
836 
837 static u32 dspvol_to_ctlvol(u32 volume)
838 {
839 	if (volume > DSP_VOLUME_MAX)
840 		return DSP_VOLUME_STEP_MAX;
841 	return volume ? __fls(volume) : 0;
842 }
843 
844 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol)
845 {
846 	u32 dspvol;
847 	int ret, i;
848 
849 	for (i = 1; i < CATPT_CHANNELS_MAX; i++)
850 		if (ctlvol[i] != ctlvol[0])
851 			break;
852 
853 	if (i == CATPT_CHANNELS_MAX) {
854 		dspvol = ctlvol_to_dspvol(ctlvol[0]);
855 
856 		ret = catpt_ipc_set_volume(cdev, stream_id,
857 					   CATPT_ALL_CHANNELS_MASK, dspvol,
858 					   0, CATPT_AUDIO_CURVE_NONE);
859 	} else {
860 		for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
861 			dspvol = ctlvol_to_dspvol(ctlvol[i]);
862 
863 			ret = catpt_ipc_set_volume(cdev, stream_id,
864 						   i, dspvol,
865 						   0, CATPT_AUDIO_CURVE_NONE);
866 			if (ret)
867 				break;
868 		}
869 	}
870 
871 	return CATPT_IPC_RET(ret);
872 }
873 
874 static int catpt_volume_info(struct snd_kcontrol *kcontrol,
875 			     struct snd_ctl_elem_info *uinfo)
876 {
877 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
878 	uinfo->count = CATPT_CHANNELS_MAX;
879 	uinfo->value.integer.min = 0;
880 	uinfo->value.integer.max = DSP_VOLUME_STEP_MAX;
881 	return 0;
882 }
883 
884 static int catpt_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
885 {
886 	struct snd_soc_component *component = snd_kcontrol_chip(kctl);
887 	struct catpt_dev *cdev = dev_get_drvdata(component->dev);
888 	struct catpt_control_data *data;
889 	u32 dspvol, *regs;
890 	long *uvolumes;
891 	int i;
892 
893 	data = (struct catpt_control_data *)kctl->private_value;
894 	uvolumes = &uctl->value.integer.value[0];
895 
896 	guard(mutex)(&cdev->stream_mutex);
897 
898 	regs = catpt_stream_volume_regs(cdev, data->pin_id);
899 	if (regs) {
900 		for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
901 			dspvol = readl(cdev->lpe_ba + regs[i]);
902 			data->volumes[i] = dspvol_to_ctlvol(dspvol);
903 		}
904 	}
905 
906 	memcpy(uvolumes, data->volumes, sizeof(data->volumes));
907 	return 0;
908 }
909 
910 static int catpt_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
911 {
912 	struct snd_soc_component *component = snd_kcontrol_chip(kctl);
913 	struct catpt_dev *cdev = dev_get_drvdata(component->dev);
914 	struct catpt_control_data *data;
915 	u8 stream_hw_id;
916 	long *uvolumes;
917 	int ret;
918 
919 	data = (struct catpt_control_data *)kctl->private_value;
920 	uvolumes = &uctl->value.integer.value[0];
921 
922 	if (!memcmp(data->volumes, uvolumes, sizeof(data->volumes)))
923 		return 0;
924 
925 	guard(mutex)(&cdev->stream_mutex);
926 
927 	stream_hw_id = catpt_stream_hw_id(cdev, data->pin_id);
928 	if (stream_hw_id != CATPT_PIN_ID_INVALID) {
929 		ret = catpt_set_dspvol(cdev, stream_hw_id, uvolumes);
930 		if (ret)
931 			return ret;
932 	}
933 
934 	memcpy(data->volumes, uvolumes, sizeof(data->volumes));
935 	return 1;
936 }
937 
938 static int catpt_loopback_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
939 {
940 	uctl->value.integer.value[0] = *(bool *)kctl->private_value;
941 	return 0;
942 }
943 
944 static int catpt_loopback_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
945 {
946 	struct snd_soc_component *component = snd_kcontrol_chip(kctl);
947 	struct catpt_dev *cdev = dev_get_drvdata(component->dev);
948 	bool *kmute, cmute;
949 	u8 stream_hw_id;
950 	int ret;
951 
952 	kmute = (bool *)kctl->private_value;
953 	cmute = (bool)uctl->value.integer.value[0];
954 
955 	if (*kmute == cmute)
956 		return 0;
957 
958 	guard(mutex)(&cdev->stream_mutex);
959 
960 	stream_hw_id = catpt_stream_hw_id(cdev, CATPT_PIN_ID_REFERENCE);
961 	if (stream_hw_id != CATPT_PIN_ID_INVALID) {
962 		ret = catpt_ipc_mute_loopback(cdev, stream_hw_id, cmute);
963 		if (ret)
964 			return CATPT_IPC_RET(ret);
965 	}
966 
967 	*kmute = cmute;
968 	return 1;
969 }
970 
971 static bool catpt_loopback_mute;
972 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1);
973 
974 #define CATPT_VOLUME_CTL(kname, pname) {		\
975 	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,		\
976 	.name	= kname,				\
977 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |	\
978 		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,	\
979 	.info	= catpt_volume_info,			\
980 	.get	= catpt_volume_get,			\
981 	.put	= catpt_volume_put,			\
982 	.tlv.p	= catpt_volume_tlv,			\
983 	.private_value = (unsigned long)		\
984 		&(struct catpt_control_data) { CATPT_PIN_ID_##pname } \
985 }
986 
987 static const struct snd_kcontrol_new component_kcontrols[] = {
988 	CATPT_VOLUME_CTL("Master Playback Volume", MIXER),
989 	CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1),
990 	CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2),
991 	CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1),
992 	SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&catpt_loopback_mute,
993 			    catpt_loopback_mute_get, catpt_loopback_mute_put),
994 };
995 
996 static const struct snd_soc_dapm_widget component_widgets[] = {
997 	SND_SOC_DAPM_AIF_IN("SSP0 CODEC IN", NULL, 0, SND_SOC_NOPM, 0, 0),
998 	SND_SOC_DAPM_AIF_OUT("SSP0 CODEC OUT", NULL, 0, SND_SOC_NOPM, 0, 0),
999 	SND_SOC_DAPM_AIF_IN("SSP1 BT IN", NULL, 0, SND_SOC_NOPM, 0, 0),
1000 	SND_SOC_DAPM_AIF_OUT("SSP1 BT OUT", NULL, 0, SND_SOC_NOPM, 0, 0),
1001 
1002 	SND_SOC_DAPM_MIXER("Playback VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1003 };
1004 
1005 static const struct snd_soc_dapm_route component_routes[] = {
1006 	{"Playback VMixer", NULL, "System Playback"},
1007 	{"Playback VMixer", NULL, "Offload0 Playback"},
1008 	{"Playback VMixer", NULL, "Offload1 Playback"},
1009 
1010 	{"SSP0 CODEC OUT", NULL, "Playback VMixer"},
1011 
1012 	{"Analog Capture", NULL, "SSP0 CODEC IN"},
1013 	{"Loopback Capture", NULL, "SSP0 CODEC IN"},
1014 
1015 	{"SSP1 BT OUT", NULL, "Bluetooth Playback"},
1016 	{"Bluetooth Capture", NULL, "SSP1 BT IN"},
1017 };
1018 
1019 static const struct snd_soc_component_driver catpt_comp_driver = {
1020 	.name = "catpt-platform",
1021 
1022 	.pcm_new = catpt_component_pcm_new,
1023 	.open = catpt_component_open,
1024 	.pointer = catpt_component_pointer,
1025 
1026 	.controls = component_kcontrols,
1027 	.num_controls = ARRAY_SIZE(component_kcontrols),
1028 	.dapm_widgets = component_widgets,
1029 	.num_dapm_widgets = ARRAY_SIZE(component_widgets),
1030 	.dapm_routes = component_routes,
1031 	.num_dapm_routes = ARRAY_SIZE(component_routes),
1032 };
1033 
1034 int catpt_arm_stream_templates(struct catpt_dev *cdev)
1035 {
1036 	struct resource *res;
1037 	u32 scratch_size = 0;
1038 	int i, j;
1039 
1040 	for (i = 0; i < ARRAY_SIZE(catpt_topology); i++) {
1041 		struct catpt_stream_template *template;
1042 		struct catpt_module_entry *entry;
1043 		struct catpt_module_type *type;
1044 
1045 		template = catpt_topology[i];
1046 		template->persistent_size = 0;
1047 
1048 		for (j = 0; j < template->num_entries; j++) {
1049 			entry = &template->entries[j];
1050 			type = &cdev->modules[entry->module_id];
1051 
1052 			if (!type->loaded)
1053 				return -ENOENT;
1054 
1055 			entry->entry_point = type->entry_point;
1056 			template->persistent_size += type->persistent_size;
1057 			if (type->scratch_size > scratch_size)
1058 				scratch_size = type->scratch_size;
1059 		}
1060 	}
1061 
1062 	if (scratch_size) {
1063 		/* allocate single scratch area for all modules */
1064 		res = catpt_request_region(&cdev->dram, scratch_size);
1065 		if (!res)
1066 			return -EBUSY;
1067 		cdev->scratch = res;
1068 	}
1069 
1070 	return 0;
1071 }
1072 
1073 int catpt_register_plat_component(struct catpt_dev *cdev)
1074 {
1075 	struct snd_soc_component *component;
1076 	int ret;
1077 
1078 	component = devm_kzalloc(cdev->dev, sizeof(*component), GFP_KERNEL);
1079 	if (!component)
1080 		return -ENOMEM;
1081 
1082 	ret = snd_soc_component_initialize(component, &catpt_comp_driver,
1083 					   cdev->dev);
1084 	if (ret)
1085 		return ret;
1086 
1087 	component->name = catpt_comp_driver.name;
1088 	return snd_soc_add_component(component, dai_drivers,
1089 				     ARRAY_SIZE(dai_drivers));
1090 }
1091