1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
3 
4 #include <linux/interrupt.h>
5 #include <linux/slab.h>
6 
7 #include <sound/asoundef.h>
8 
9 #include "bcm2835.h"
10 
11 /* hardware definition */
12 static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
13 	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
14 		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
15 		 SNDRV_PCM_INFO_SYNC_APPLPTR),
16 	.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
17 	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
18 	.rate_min = 8000,
19 	.rate_max = 48000,
20 	.channels_min = 1,
21 	.channels_max = 2,
22 	.buffer_bytes_max = 128 * 1024,
23 	.period_bytes_min = 1 * 1024,
24 	.period_bytes_max = 128 * 1024,
25 	.periods_min = 1,
26 	.periods_max = 128,
27 };
28 
29 static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
30 	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
31 		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
32 		 SNDRV_PCM_INFO_SYNC_APPLPTR),
33 	.formats = SNDRV_PCM_FMTBIT_S16_LE,
34 	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
35 	SNDRV_PCM_RATE_48000,
36 	.rate_min = 44100,
37 	.rate_max = 48000,
38 	.channels_min = 2,
39 	.channels_max = 2,
40 	.buffer_bytes_max = 128 * 1024,
41 	.period_bytes_min = 1 * 1024,
42 	.period_bytes_max = 128 * 1024,
43 	.periods_min = 1,
44 	.periods_max = 128,
45 };
46 
snd_bcm2835_playback_free(struct snd_pcm_runtime * runtime)47 static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
48 {
49 	kfree(runtime->private_data);
50 }
51 
bcm2835_playback_fifo(struct bcm2835_alsa_stream * alsa_stream,unsigned int bytes)52 void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
53 			   unsigned int bytes)
54 {
55 	struct snd_pcm_substream *substream = alsa_stream->substream;
56 	unsigned int pos;
57 
58 	if (!alsa_stream->period_size)
59 		return;
60 
61 	if (bytes >= alsa_stream->buffer_size) {
62 		snd_pcm_stream_lock(substream);
63 		snd_pcm_stop(substream,
64 			     alsa_stream->draining ?
65 			     SNDRV_PCM_STATE_SETUP :
66 			     SNDRV_PCM_STATE_XRUN);
67 		snd_pcm_stream_unlock(substream);
68 		return;
69 	}
70 
71 	pos = atomic_read(&alsa_stream->pos);
72 	pos += bytes;
73 	pos %= alsa_stream->buffer_size;
74 	atomic_set(&alsa_stream->pos, pos);
75 
76 	alsa_stream->period_offset += bytes;
77 	alsa_stream->interpolate_start = ktime_get();
78 	if (alsa_stream->period_offset >= alsa_stream->period_size) {
79 		alsa_stream->period_offset %= alsa_stream->period_size;
80 		snd_pcm_period_elapsed(substream);
81 	}
82 }
83 
84 /* open callback */
snd_bcm2835_playback_open_generic(struct snd_pcm_substream * substream,int spdif)85 static int snd_bcm2835_playback_open_generic(
86 	struct snd_pcm_substream *substream, int spdif)
87 {
88 	struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
89 	struct snd_pcm_runtime *runtime = substream->runtime;
90 	struct bcm2835_alsa_stream *alsa_stream;
91 	int idx;
92 	int err;
93 
94 	mutex_lock(&chip->audio_mutex);
95 	idx = substream->number;
96 
97 	if (spdif && chip->opened) {
98 		err = -EBUSY;
99 		goto out;
100 	} else if (!spdif && (chip->opened & (1 << idx))) {
101 		err = -EBUSY;
102 		goto out;
103 	}
104 	if (idx >= MAX_SUBSTREAMS) {
105 		dev_err(chip->dev,
106 			"substream(%d) device doesn't exist max(%d) substreams allowed\n",
107 			idx, MAX_SUBSTREAMS);
108 		err = -ENODEV;
109 		goto out;
110 	}
111 
112 	alsa_stream = kzalloc(sizeof(*alsa_stream), GFP_KERNEL);
113 	if (!alsa_stream) {
114 		err = -ENOMEM;
115 		goto out;
116 	}
117 
118 	/* Initialise alsa_stream */
119 	alsa_stream->chip = chip;
120 	alsa_stream->substream = substream;
121 	alsa_stream->idx = idx;
122 
123 	err = bcm2835_audio_open(alsa_stream);
124 	if (err) {
125 		kfree(alsa_stream);
126 		goto out;
127 	}
128 	runtime->private_data = alsa_stream;
129 	runtime->private_free = snd_bcm2835_playback_free;
130 	if (spdif) {
131 		runtime->hw = snd_bcm2835_playback_spdif_hw;
132 	} else {
133 		/* clear spdif status, as we are not in spdif mode */
134 		chip->spdif_status = 0;
135 		runtime->hw = snd_bcm2835_playback_hw;
136 	}
137 	/* minimum 16 bytes alignment (for vchiq bulk transfers) */
138 	snd_pcm_hw_constraint_step(runtime,
139 				   0,
140 				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
141 				   16);
142 
143 	/* position update is in 10ms order */
144 	snd_pcm_hw_constraint_minmax(runtime,
145 				     SNDRV_PCM_HW_PARAM_PERIOD_TIME,
146 				     10 * 1000, UINT_MAX);
147 
148 	chip->alsa_stream[idx] = alsa_stream;
149 
150 	chip->opened |= (1 << idx);
151 
152 out:
153 	mutex_unlock(&chip->audio_mutex);
154 
155 	return err;
156 }
157 
snd_bcm2835_playback_open(struct snd_pcm_substream * substream)158 static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
159 {
160 	return snd_bcm2835_playback_open_generic(substream, 0);
161 }
162 
snd_bcm2835_playback_spdif_open(struct snd_pcm_substream * substream)163 static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream)
164 {
165 	return snd_bcm2835_playback_open_generic(substream, 1);
166 }
167 
snd_bcm2835_playback_close(struct snd_pcm_substream * substream)168 static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
169 {
170 	struct bcm2835_alsa_stream *alsa_stream;
171 	struct snd_pcm_runtime *runtime;
172 	struct bcm2835_chip *chip;
173 
174 	chip = snd_pcm_substream_chip(substream);
175 	mutex_lock(&chip->audio_mutex);
176 	runtime = substream->runtime;
177 	alsa_stream = runtime->private_data;
178 
179 	alsa_stream->period_size = 0;
180 	alsa_stream->buffer_size = 0;
181 
182 	bcm2835_audio_close(alsa_stream);
183 	alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
184 	/*
185 	 * Do not free up alsa_stream here, it will be freed up by
186 	 * runtime->private_free callback we registered in *_open above
187 	 */
188 
189 	chip->opened &= ~(1 << substream->number);
190 
191 	mutex_unlock(&chip->audio_mutex);
192 
193 	return 0;
194 }
195 
snd_bcm2835_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)196 static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
197 	struct snd_pcm_hw_params *params)
198 {
199 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
200 }
201 
snd_bcm2835_pcm_hw_free(struct snd_pcm_substream * substream)202 static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
203 {
204 	return snd_pcm_lib_free_pages(substream);
205 }
206 
snd_bcm2835_pcm_prepare(struct snd_pcm_substream * substream)207 static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
208 {
209 	struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
210 	struct snd_pcm_runtime *runtime = substream->runtime;
211 	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
212 	int channels;
213 	int err;
214 
215 	/* notify the vchiq that it should enter spdif passthrough mode by
216 	 * setting channels=0 (see
217 	 * https://github.com/raspberrypi/linux/issues/528)
218 	 */
219 	if (chip->spdif_status & IEC958_AES0_NONAUDIO)
220 		channels = 0;
221 	else
222 		channels = runtime->channels;
223 
224 	err = bcm2835_audio_set_params(alsa_stream, channels,
225 				       runtime->rate,
226 				       snd_pcm_format_width(runtime->format));
227 	if (err < 0)
228 		return err;
229 
230 	memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
231 
232 	alsa_stream->pcm_indirect.hw_buffer_size =
233 		alsa_stream->pcm_indirect.sw_buffer_size =
234 		snd_pcm_lib_buffer_bytes(substream);
235 
236 	alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
237 	alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
238 	atomic_set(&alsa_stream->pos, 0);
239 	alsa_stream->period_offset = 0;
240 	alsa_stream->draining = false;
241 	alsa_stream->interpolate_start = ktime_get();
242 
243 	return 0;
244 }
245 
snd_bcm2835_pcm_transfer(struct snd_pcm_substream * substream,struct snd_pcm_indirect * rec,size_t bytes)246 static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
247 	struct snd_pcm_indirect *rec, size_t bytes)
248 {
249 	struct snd_pcm_runtime *runtime = substream->runtime;
250 	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
251 	void *src = (void *) (substream->runtime->dma_area + rec->sw_data);
252 
253 	bcm2835_audio_write(alsa_stream, bytes, src);
254 }
255 
snd_bcm2835_pcm_ack(struct snd_pcm_substream * substream)256 static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
257 {
258 	struct snd_pcm_runtime *runtime = substream->runtime;
259 	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
260 	struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect;
261 
262 	return snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
263 						  snd_bcm2835_pcm_transfer);
264 }
265 
266 /* trigger callback */
snd_bcm2835_pcm_trigger(struct snd_pcm_substream * substream,int cmd)267 static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
268 {
269 	struct snd_pcm_runtime *runtime = substream->runtime;
270 	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
271 
272 	switch (cmd) {
273 	case SNDRV_PCM_TRIGGER_START:
274 		return bcm2835_audio_start(alsa_stream);
275 	case SNDRV_PCM_TRIGGER_DRAIN:
276 		alsa_stream->draining = true;
277 		return bcm2835_audio_drain(alsa_stream);
278 	case SNDRV_PCM_TRIGGER_STOP:
279 		return bcm2835_audio_stop(alsa_stream);
280 	default:
281 		return -EINVAL;
282 	}
283 }
284 
285 /* pointer callback */
286 static snd_pcm_uframes_t
snd_bcm2835_pcm_pointer(struct snd_pcm_substream * substream)287 snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream)
288 {
289 	struct snd_pcm_runtime *runtime = substream->runtime;
290 	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
291 	ktime_t now = ktime_get();
292 
293 	/* Give userspace better delay reporting by interpolating between GPU
294 	 * notifications, assuming audio speed is close enough to the clock
295 	 * used for ktime
296 	 */
297 
298 	if ((ktime_to_ns(alsa_stream->interpolate_start)) &&
299 	    (ktime_compare(alsa_stream->interpolate_start, now) < 0)) {
300 		u64 interval =
301 			(ktime_to_ns(ktime_sub(now,
302 				alsa_stream->interpolate_start)));
303 		u64 frames_output_in_interval =
304 			div_u64((interval * runtime->rate), 1000000000);
305 		snd_pcm_sframes_t frames_output_in_interval_sized =
306 			-frames_output_in_interval;
307 		runtime->delay = frames_output_in_interval_sized;
308 	}
309 
310 	return snd_pcm_indirect_playback_pointer(substream,
311 		&alsa_stream->pcm_indirect,
312 		atomic_read(&alsa_stream->pos));
313 }
314 
315 /* operators */
316 static const struct snd_pcm_ops snd_bcm2835_playback_ops = {
317 	.open = snd_bcm2835_playback_open,
318 	.close = snd_bcm2835_playback_close,
319 	.ioctl = snd_pcm_lib_ioctl,
320 	.hw_params = snd_bcm2835_pcm_hw_params,
321 	.hw_free = snd_bcm2835_pcm_hw_free,
322 	.prepare = snd_bcm2835_pcm_prepare,
323 	.trigger = snd_bcm2835_pcm_trigger,
324 	.pointer = snd_bcm2835_pcm_pointer,
325 	.ack = snd_bcm2835_pcm_ack,
326 };
327 
328 static const struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
329 	.open = snd_bcm2835_playback_spdif_open,
330 	.close = snd_bcm2835_playback_close,
331 	.ioctl = snd_pcm_lib_ioctl,
332 	.hw_params = snd_bcm2835_pcm_hw_params,
333 	.hw_free = snd_bcm2835_pcm_hw_free,
334 	.prepare = snd_bcm2835_pcm_prepare,
335 	.trigger = snd_bcm2835_pcm_trigger,
336 	.pointer = snd_bcm2835_pcm_pointer,
337 	.ack = snd_bcm2835_pcm_ack,
338 };
339 
340 /* create a pcm device */
snd_bcm2835_new_pcm(struct bcm2835_chip * chip,const char * name,int idx,enum snd_bcm2835_route route,u32 numchannels,bool spdif)341 int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
342 			int idx, enum snd_bcm2835_route route,
343 			u32 numchannels, bool spdif)
344 {
345 	struct snd_pcm *pcm;
346 	int err;
347 
348 	err = snd_pcm_new(chip->card, name, idx, numchannels, 0, &pcm);
349 	if (err)
350 		return err;
351 
352 	pcm->private_data = chip;
353 	pcm->nonatomic = true;
354 	strcpy(pcm->name, name);
355 	if (!spdif) {
356 		chip->dest = route;
357 		chip->volume = 0;
358 		chip->mute = CTRL_VOL_UNMUTE;
359 	}
360 
361 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
362 			spdif ? &snd_bcm2835_playback_spdif_ops :
363 			&snd_bcm2835_playback_ops);
364 
365 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
366 		chip->card->dev, 128 * 1024, 128 * 1024);
367 
368 	if (spdif)
369 		chip->pcm_spdif = pcm;
370 	else
371 		chip->pcm = pcm;
372 	return 0;
373 }
374