File Index
Files and directories
Sign in
FILE

zynqmp_dp_audio.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * ZynqMP DisplayPort Subsystem Driver - Audio support
  4 *
  5 * Copyright (C) 2015 - 2024 Xilinx, Inc.
  6 *
  7 * Authors:
  8 * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
  9 * - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
 10 */
 11
 12#include <linux/clk.h>
 13#include <linux/device.h>
 14#include <linux/mutex.h>
 15#include <linux/pm_runtime.h>
 16
 17#include <sound/asoundef.h>
 18#include <sound/core.h>
 19#include <sound/dmaengine_pcm.h>
 20#include <sound/initval.h>
 21#include <sound/pcm.h>
 22#include <sound/soc.h>
 23#include <sound/tlv.h>
 24
 25#include "zynqmp_disp_regs.h"
 26#include "zynqmp_dp.h"
 27#include "zynqmp_dpsub.h"
 28
 29#define ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK 512
 30#define ZYNQMP_NUM_PCMS 2
 31
 32struct zynqmp_dpsub_audio {
 33	void __iomem *base;
 34
 35	struct snd_soc_card card;
 36
 37	const char *dai_name;
 38	const char *link_names[ZYNQMP_NUM_PCMS];
 39	const char *pcm_names[ZYNQMP_NUM_PCMS];
 40
 41	struct snd_soc_dai_driver dai_driver;
 42	struct snd_dmaengine_pcm_config pcm_configs[2];
 43
 44	struct snd_soc_dai_link links[ZYNQMP_NUM_PCMS];
 45
 46	struct {
 47		struct snd_soc_dai_link_component cpu;
 48		struct snd_soc_dai_link_component platform;
 49	} components[ZYNQMP_NUM_PCMS];
 50
 51	/*
 52	 * Protects:
 53	 * - enabled_streams
 54	 * - volumes
 55	 * - current_rate
 56	 */
 57	struct mutex enable_lock;
 58
 59	u32 enabled_streams;
 60	u32 current_rate;
 61
 62	u16 volumes[2];
 63};
 64
 65static const struct snd_pcm_hardware zynqmp_dp_pcm_hw = {
 66	.info = SNDRV_PCM_INFO_MMAP |
 67		SNDRV_PCM_INFO_MMAP_VALID |
 68		SNDRV_PCM_INFO_INTERLEAVED |
 69		SNDRV_PCM_INFO_PAUSE |
 70		SNDRV_PCM_INFO_RESUME |
 71		SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
 72
 73	.buffer_bytes_max       = 128 * 1024,
 74	.period_bytes_min       = 256,
 75	.period_bytes_max       = 1024 * 1024,
 76	.periods_min            = 2,
 77	.periods_max            = 256,
 78};
 79
 80static int zynqmp_dp_startup(struct snd_pcm_substream *substream)
 81{
 82	struct snd_pcm_runtime *runtime = substream->runtime;
 83
 84	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
 85				   256);
 86
 87	return 0;
 88}
 89
 90static const struct snd_soc_ops zynqmp_dp_ops = {
 91	.startup = zynqmp_dp_startup,
 92};
 93
 94static void zynqmp_dp_audio_write(struct zynqmp_dpsub_audio *audio, int reg,
 95				  u32 val)
 96{
 97	writel(val, audio->base + reg);
 98}
 99
100static int dp_dai_hw_params(struct snd_pcm_substream *substream,
101			    struct snd_pcm_hw_params *params,
102			    struct snd_soc_dai *socdai)
103{
104	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
105	struct zynqmp_dpsub *dpsub =
106		snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
107	struct zynqmp_dpsub_audio *audio = dpsub->audio;
108	int ret;
109	u32 sample_rate;
110	struct snd_aes_iec958 iec = { 0 };
111	unsigned long rate;
112
113	sample_rate = params_rate(params);
114
115	if (sample_rate != 48000 && sample_rate != 44100)
116		return -EINVAL;
117
118	guard(mutex)(&audio->enable_lock);
119
120	if (audio->enabled_streams && audio->current_rate != sample_rate) {
121		dev_err(dpsub->dev,
122			"Can't change rate while playback enabled\n");
123		return -EINVAL;
124	}
125
126	if (audio->enabled_streams > 0) {
127		/* Nothing to do */
128		audio->enabled_streams++;
129		return 0;
130	}
131
132	audio->current_rate = sample_rate;
133
134	/* Note: clock rate can only be changed if the clock is disabled */
135	ret = clk_set_rate(dpsub->aud_clk,
136			   sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK);
137	if (ret) {
138		dev_err(dpsub->dev, "can't set aud_clk to %u err:%d\n",
139			sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK, ret);
140		return ret;
141	}
142
143	clk_prepare_enable(dpsub->aud_clk);
144
145	rate = clk_get_rate(dpsub->aud_clk);
146
147	/* Ignore some offset +- 10 */
148	if (abs(sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK - rate) > 10) {
149		dev_err(dpsub->dev, "aud_clk offset is higher: %ld\n",
150			sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK - rate);
151		clk_disable_unprepare(dpsub->aud_clk);
152		return -EINVAL;
153	}
154
155	pm_runtime_get_sync(dpsub->dev);
156
157	zynqmp_dp_audio_write(audio, ZYNQMP_DISP_AUD_MIXER_VOLUME,
158			      audio->volumes[0] | (audio->volumes[1] << 16));
159
160	/* Clear the audio soft reset register as it's an non-reset flop. */
161	zynqmp_dp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
162
163	/* Only 2 channel audio is supported now */
164	zynqmp_dp_audio_set_channels(dpsub->dp, 2);
165
166	zynqmp_dp_audio_write_n_m(dpsub->dp);
167
168	/* Channel status */
169
170	if (sample_rate == 48000)
171		iec.status[3] = IEC958_AES3_CON_FS_48000;
172	else
173		iec.status[3] = IEC958_AES3_CON_FS_44100;
174
175	for (unsigned int i = 0; i < AES_IEC958_STATUS_SIZE / 4; ++i) {
176		u32 v;
177
178		v = (iec.status[(i * 4) + 0] << 0) |
179		    (iec.status[(i * 4) + 1] << 8) |
180		    (iec.status[(i * 4) + 2] << 16) |
181		    (iec.status[(i * 4) + 3] << 24);
182
183		zynqmp_dp_audio_write(audio, ZYNQMP_DISP_AUD_CH_STATUS(i), v);
184	}
185
186	zynqmp_dp_audio_enable(dpsub->dp);
187
188	audio->enabled_streams++;
189
190	return 0;
191}
192
193static int dp_dai_hw_free(struct snd_pcm_substream *substream,
194			  struct snd_soc_dai *socdai)
195{
196	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
197	struct zynqmp_dpsub *dpsub =
198		snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
199	struct zynqmp_dpsub_audio *audio = dpsub->audio;
200
201	guard(mutex)(&audio->enable_lock);
202
203	/* Nothing to do */
204	if (audio->enabled_streams > 1) {
205		audio->enabled_streams--;
206		return 0;
207	}
208
209	pm_runtime_put(dpsub->dev);
210
211	zynqmp_dp_audio_disable(dpsub->dp);
212
213	/*
214	 * Reset doesn't work. If we assert reset between audio stop and start,
215	 * the audio won't start anymore. Probably we are missing writing
216	 * some audio related registers. A/B buf?
217	 */
218	/*
219	zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET,
220				ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
221	*/
222
223	clk_disable_unprepare(dpsub->aud_clk);
224
225	audio->current_rate = 0;
226	audio->enabled_streams--;
227
228	return 0;
229}
230
231static const struct snd_soc_dai_ops zynqmp_dp_dai_ops = {
232	.hw_params	= dp_dai_hw_params,
233	.hw_free	= dp_dai_hw_free,
234};
235
236/*
237 * Min = 10 * log10(0x1 / 0x2000) = -39.13
238 * Max = 10 * log10(0xffffff / 0x2000) = 9.03
239 */
240static const DECLARE_TLV_DB_RANGE(zynqmp_dp_tlv,
241	0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, -3913, 1),
242	0x1, 0x2000, TLV_DB_LINEAR_ITEM(-3913, 0),
243	0x2000, 0xffff, TLV_DB_LINEAR_ITEM(0, 903),
244);
245
246static const struct snd_kcontrol_new zynqmp_dp_snd_controls[] = {
247	SOC_SINGLE_TLV("Input0 Playback Volume", 0,
248		       0, 0xffff, 0, zynqmp_dp_tlv),
249	SOC_SINGLE_TLV("Input1 Playback Volume", 1,
250		       0, 0xffff, 0, zynqmp_dp_tlv),
251};
252
253/*
254 * Note: these read & write functions only support two "registers", 0 and 1,
255 * for volume 0 and 1. In other words, these are not real register read/write
256 * functions.
257 *
258 * This is done to support caching the volume value for the case where the
259 * hardware is not enabled, and also to support locking as volumes 0 and 1
260 * are in the same register.
261 */
262static unsigned int zynqmp_dp_dai_read(struct snd_soc_component *component,
263				       unsigned int reg)
264{
265	struct zynqmp_dpsub *dpsub = dev_get_drvdata(component->dev);
266	struct zynqmp_dpsub_audio *audio = dpsub->audio;
267
268	return audio->volumes[reg];
269}
270
271static int zynqmp_dp_dai_write(struct snd_soc_component *component,
272			       unsigned int reg, unsigned int val)
273{
274	struct zynqmp_dpsub *dpsub = dev_get_drvdata(component->dev);
275	struct zynqmp_dpsub_audio *audio = dpsub->audio;
276
277	guard(mutex)(&audio->enable_lock);
278
279	audio->volumes[reg] = val;
280
281	if (audio->enabled_streams)
282		zynqmp_dp_audio_write(audio, ZYNQMP_DISP_AUD_MIXER_VOLUME,
283				      audio->volumes[0] |
284				      (audio->volumes[1] << 16));
285
286	return 0;
287}
288
289static const struct snd_soc_component_driver zynqmp_dp_component_driver = {
290	.idle_bias_on		= 1,
291	.use_pmdown_time	= 1,
292	.endianness		= 1,
293	.controls		= zynqmp_dp_snd_controls,
294	.num_controls		= ARRAY_SIZE(zynqmp_dp_snd_controls),
295	.read			= zynqmp_dp_dai_read,
296	.write			= zynqmp_dp_dai_write,
297};
298
299int zynqmp_audio_init(struct zynqmp_dpsub *dpsub)
300{
301	struct platform_device *pdev = to_platform_device(dpsub->dev);
302	struct device *dev = dpsub->dev;
303	struct zynqmp_dpsub_audio *audio;
304	struct snd_soc_card *card;
305	void *dev_data;
306	int ret;
307
308	if (!dpsub->aud_clk)
309		return 0;
310
311	audio = devm_kzalloc(dev, sizeof(*audio), GFP_KERNEL);
312	if (!audio)
313		return -ENOMEM;
314
315	dpsub->audio = audio;
316
317	mutex_init(&audio->enable_lock);
318
319	/* 0x2000 is the zero level, no change */
320	audio->volumes[0] = 0x2000;
321	audio->volumes[1] = 0x2000;
322
323	audio->dai_name = devm_kasprintf(dev, GFP_KERNEL,
324					 "%s-dai", dev_name(dev));
325	if (!audio->dai_name)
326		return -ENOMEM;
327
328	for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) {
329		audio->link_names[i] = devm_kasprintf(dev, GFP_KERNEL,
330						      "%s-dp-%u", dev_name(dev), i);
331		audio->pcm_names[i] = devm_kasprintf(dev, GFP_KERNEL,
332						     "%s-pcm-%u", dev_name(dev), i);
333		if (!audio->link_names[i] || !audio->pcm_names[i])
334			return -ENOMEM;
335	}
336
337	audio->base = devm_platform_ioremap_resource_byname(pdev, "aud");
338	if (IS_ERR(audio->base))
339		return PTR_ERR(audio->base);
340
341	/* Create CPU DAI */
342
343	audio->dai_driver = (struct snd_soc_dai_driver) {
344		.name		= audio->dai_name,
345		.ops		= &zynqmp_dp_dai_ops,
346		.playback	= {
347			.channels_min	= 2,
348			.channels_max	= 2,
349			.rates		= SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
350			.formats	= SNDRV_PCM_FMTBIT_S16_LE,
351		},
352	};
353
354	ret = devm_snd_soc_register_component(dev, &zynqmp_dp_component_driver,
355					      &audio->dai_driver, 1);
356	if (ret) {
357		dev_err(dev, "Failed to register CPU DAI\n");
358		return ret;
359	}
360
361	/* Create PCMs */
362
363	for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) {
364		struct snd_dmaengine_pcm_config *pcm_config =
365			&audio->pcm_configs[i];
366
367		*pcm_config = (struct snd_dmaengine_pcm_config){
368			.name = audio->pcm_names[i],
369			.pcm_hardware = &zynqmp_dp_pcm_hw,
370			.prealloc_buffer_size = 64 * 1024,
371			.chan_names[SNDRV_PCM_STREAM_PLAYBACK] =
372				i == 0 ? "aud0" : "aud1",
373		};
374
375		ret = devm_snd_dmaengine_pcm_register(dev, pcm_config, 0);
376		if (ret) {
377			dev_err(dev, "Failed to register PCM %u\n", i);
378			return ret;
379		}
380	}
381
382	/* Create card */
383
384	card = &audio->card;
385	card->name = "DisplayPort";
386	card->long_name = "DisplayPort Monitor";
387	card->driver_name = "zynqmp_dpsub";
388	card->dev = dev;
389	card->owner = THIS_MODULE;
390	card->num_links = ZYNQMP_NUM_PCMS;
391	card->dai_link = audio->links;
392
393	for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) {
394		struct snd_soc_dai_link *link = &card->dai_link[i];
395
396		link->ops = &zynqmp_dp_ops;
397
398		link->name = audio->link_names[i];
399		link->stream_name = audio->link_names[i];
400
401		link->cpus = &audio->components[i].cpu;
402		link->num_cpus = 1;
403		link->cpus[0].dai_name = audio->dai_name;
404
405		link->codecs = &snd_soc_dummy_dlc;
406		link->num_codecs = 1;
407
408		link->platforms = &audio->components[i].platform;
409		link->num_platforms = 1;
410		link->platforms[0].name = audio->pcm_names[i];
411	}
412
413	/*
414	 * HACK: devm_snd_soc_register_card() overwrites current drvdata
415	 * so we need to hack it back.
416	 */
417	dev_data = dev_get_drvdata(dev);
418	ret = devm_snd_soc_register_card(dev, card);
419	dev_set_drvdata(dev, dev_data);
420	if (ret) {
421		/*
422		 * As older dtbs may not have the audio channel dmas defined,
423		 * instead of returning an error here we'll continue and just
424		 * mark the audio as disabled.
425		 */
426		dev_err(dev, "Failed to register sound card, disabling audio support\n");
427
428		devm_kfree(dev, audio);
429		dpsub->audio = NULL;
430
431		return 0;
432	}
433
434	return 0;
435}
436
437void zynqmp_audio_uninit(struct zynqmp_dpsub *dpsub)
438{
439	struct zynqmp_dpsub_audio *audio = dpsub->audio;
440
441	if (!audio)
442		return;
443
444	if (!dpsub->aud_clk)
445		return;
446
447	mutex_destroy(&audio->enable_lock);
448}
~/ Read-only file preview.