Lines Matching +full:playback +full:- +full:codecs
1 // SPDX-License-Identifier: GPL-2.0
3 * ZynqMP DisplayPort Subsystem Driver - Audio support
5 * Copyright (C) 2015 - 2024 Xilinx, Inc.
8 * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
9 * - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
53 * - enabled_streams
54 * - volumes
55 * - current_rate
82 struct snd_pcm_runtime *runtime = substream->runtime;
97 writel(val, audio->base + reg);
107 struct zynqmp_dpsub_audio *audio = dpsub->audio;
116 return -EINVAL;
118 guard(mutex)(&audio->enable_lock);
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;
126 if (audio->enabled_streams > 0) {
128 audio->enabled_streams++;
132 audio->current_rate = sample_rate;
135 ret = clk_set_rate(dpsub->aud_clk,
138 dev_err(dpsub->dev, "can't set aud_clk to %u err:%d\n",
143 clk_prepare_enable(dpsub->aud_clk);
145 rate = clk_get_rate(dpsub->aud_clk);
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;
155 pm_runtime_get_sync(dpsub->dev);
158 audio->volumes[0] | (audio->volumes[1] << 16));
160 /* Clear the audio soft reset register as it's an non-reset flop. */
164 zynqmp_dp_audio_set_channels(dpsub->dp, 2);
166 zynqmp_dp_audio_write_n_m(dpsub->dp);
186 zynqmp_dp_audio_enable(dpsub->dp);
188 audio->enabled_streams++;
199 struct zynqmp_dpsub_audio *audio = dpsub->audio;
201 guard(mutex)(&audio->enable_lock);
204 if (audio->enabled_streams > 1) {
205 audio->enabled_streams--;
209 pm_runtime_put(dpsub->dev);
211 zynqmp_dp_audio_disable(dpsub->dp);
223 clk_disable_unprepare(dpsub->aud_clk);
225 audio->current_rate = 0;
226 audio->enabled_streams--;
237 * Min = 10 * log10(0x1 / 0x2000) = -39.13
241 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, -3913, 1),
242 0x1, 0x2000, TLV_DB_LINEAR_ITEM(-3913, 0),
247 SOC_SINGLE_TLV("Input0 Playback Volume", 0,
249 SOC_SINGLE_TLV("Input1 Playback Volume", 1,
265 struct zynqmp_dpsub *dpsub = dev_get_drvdata(component->dev);
266 struct zynqmp_dpsub_audio *audio = dpsub->audio;
268 return audio->volumes[reg];
274 struct zynqmp_dpsub *dpsub = dev_get_drvdata(component->dev);
275 struct zynqmp_dpsub_audio *audio = dpsub->audio;
277 guard(mutex)(&audio->enable_lock);
279 audio->volumes[reg] = val;
281 if (audio->enabled_streams)
283 audio->volumes[0] |
284 (audio->volumes[1] << 16));
301 struct platform_device *pdev = to_platform_device(dpsub->dev);
302 struct device *dev = dpsub->dev;
308 if (!dpsub->aud_clk)
313 return -ENOMEM;
315 dpsub->audio = audio;
317 mutex_init(&audio->enable_lock);
320 audio->volumes[0] = 0x2000;
321 audio->volumes[1] = 0x2000;
323 audio->dai_name = devm_kasprintf(dev, GFP_KERNEL,
324 "%s-dai", dev_name(dev));
325 if (!audio->dai_name)
326 return -ENOMEM;
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;
337 audio->base = devm_platform_ioremap_resource_byname(pdev, "aud");
338 if (IS_ERR(audio->base))
339 return PTR_ERR(audio->base);
343 audio->dai_driver = (struct snd_soc_dai_driver) {
344 .name = audio->dai_name,
346 .playback = {
355 &audio->dai_driver, 1);
365 &audio->pcm_configs[i];
368 .name = audio->pcm_names[i],
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;
394 struct snd_soc_dai_link *link = &card->dai_link[i];
396 link->ops = &zynqmp_dp_ops;
398 link->name = audio->link_names[i];
399 link->stream_name = audio->link_names[i];
401 link->cpus = &audio->components[i].cpu;
402 link->num_cpus = 1;
403 link->cpus[0].dai_name = audio->dai_name;
405 link->codecs = &snd_soc_dummy_dlc;
406 link->num_codecs = 1;
408 link->platforms = &audio->components[i].platform;
409 link->num_platforms = 1;
410 link->platforms[0].name = audio->pcm_names[i];
429 dpsub->audio = NULL;
439 struct zynqmp_dpsub_audio *audio = dpsub->audio;
444 if (!dpsub->aud_clk)
447 mutex_destroy(&audio->enable_lock);