forked from Xilinx/linux-xlnx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sound: soc: xilinx: Add ZynqMP DP subsystem audio drivers
The DisplayPort subsystem of Xilinx ZynqMP SOC supports audio through, DPDMA - Audio buffer manager - Audio blender - DP. The DPDMA driver is implemented based on DMA engine API, and the audio driver is based on snd dmaengine pcm helpers. Signed-off-by: Hyun Kwon <[email protected]> Signed-off-by: Michal Simek <[email protected]>
- Loading branch information
1 parent
f9f0f1d
commit dad01aa
Showing
7 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
config SND_SOC_XILINX_DP | ||
tristate "Audio support for the the Xilinx DisplayPort" | ||
select SND_DMAENGINE_PCM | ||
help | ||
Audio support the for Xilinx DisplayPort. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
snd-soc-xilinx-dp-objs := xilinx-dp-pcm.o xilinx-dp-codec.o xilinx-dp-card.o | ||
|
||
obj-$(CONFIG_SND_SOC_XILINX_DP) += snd-soc-xilinx-dp.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Xilinx DisplayPort SoC Sound Card support | ||
* | ||
* Copyright (C) 2015 Xilinx, Inc. | ||
* | ||
* Author: Hyun Woo Kwon <[email protected]> | ||
* | ||
* This software is licensed under the terms of the GNU General Public | ||
* License version 2, as published by the Free Software Foundation, and | ||
* may be copied, distributed, and modified under those terms. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/of.h> | ||
#include <linux/platform_device.h> | ||
|
||
#include <sound/soc.h> | ||
|
||
static struct snd_soc_dai_link xilinx_dp_dai_links[] = { | ||
{ | ||
.name = "xilinx-dp0", | ||
.codec_dai_name = "xilinx-dp-snd-codec-dai", | ||
}, | ||
{ | ||
.name = "xilinx-dp1", | ||
.codec_dai_name = "xilinx-dp-snd-codec-dai", | ||
}, | ||
|
||
}; | ||
|
||
static struct snd_soc_card xilinx_dp_card = { | ||
.name = "DisplayPort monitor", | ||
.owner = THIS_MODULE, | ||
.dai_link = xilinx_dp_dai_links, | ||
.num_links = 2, | ||
}; | ||
|
||
static int xilinx_dp_probe(struct platform_device *pdev) | ||
{ | ||
struct snd_soc_card *card = &xilinx_dp_card; | ||
struct device_node *node = pdev->dev.of_node; | ||
struct device_node *codec, *pcm; | ||
int ret; | ||
|
||
card->dev = &pdev->dev; | ||
|
||
codec = of_parse_phandle(node, "xlnx,dp-snd-codec", 0); | ||
if (!codec) | ||
return -ENODEV; | ||
|
||
pcm = of_parse_phandle(node, "xlnx,dp-snd-pcm", 0); | ||
if (!pcm) | ||
return -ENODEV; | ||
xilinx_dp_dai_links[0].platform_of_node = pcm; | ||
xilinx_dp_dai_links[0].cpu_of_node = codec; | ||
xilinx_dp_dai_links[0].codec_of_node = codec; | ||
|
||
pcm = of_parse_phandle(node, "xlnx,dp-snd-pcm", 1); | ||
if (!pcm) | ||
return -ENODEV; | ||
xilinx_dp_dai_links[1].platform_of_node = pcm; | ||
xilinx_dp_dai_links[1].cpu_of_node = codec; | ||
xilinx_dp_dai_links[1].codec_of_node = codec; | ||
|
||
ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
if (ret) | ||
return ret; | ||
|
||
dev_info(&pdev->dev, "Xilinx DisplayPort Sound Card probed\n"); | ||
|
||
return 0; | ||
} | ||
|
||
static int xilinx_dp_remove(struct platform_device *pdev) | ||
{ | ||
return 0; | ||
} | ||
|
||
static const struct of_device_id xilinx_dp_of_match[] = { | ||
{ .compatible = "xlnx,dp-snd-card", }, | ||
{}, | ||
}; | ||
MODULE_DEVICE_TABLE(of, xilinx_dp_of_match); | ||
|
||
static struct platform_driver xilinx_dp_aud_driver = { | ||
.driver = { | ||
.name = "xilinx-dp-snd-card", | ||
.of_match_table = xilinx_dp_of_match, | ||
.pm = &snd_soc_pm_ops, | ||
}, | ||
.probe = xilinx_dp_probe, | ||
.remove = xilinx_dp_remove, | ||
}; | ||
module_platform_driver(xilinx_dp_aud_driver); | ||
|
||
MODULE_DESCRIPTION("Xilinx DisplayPort Sound Card module"); | ||
MODULE_LICENSE("GPL v2"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Xilinx DisplayPort Sound Codec support | ||
* | ||
* Copyright (C) 2015 Xilinx, Inc. | ||
* | ||
* Author: Hyun Woo Kwon <[email protected]> | ||
* | ||
* This software is licensed under the terms of the GNU General Public | ||
* License version 2, as published by the Free Software Foundation, and | ||
* may be copied, distributed, and modified under those terms. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <linux/clk.h> | ||
#include <linux/device.h> | ||
#include <linux/module.h> | ||
#include <linux/platform_device.h> | ||
|
||
#include <sound/soc.h> | ||
|
||
/** | ||
* struct xilinx_dp_codec - DisplayPort codec | ||
* @aud_clk: audio clock | ||
*/ | ||
struct xilinx_dp_codec { | ||
struct clk *aud_clk; | ||
}; | ||
|
||
static struct snd_soc_dai_driver xilinx_dp_codec_dai = { | ||
.name = "xilinx-dp-snd-codec-dai", | ||
.playback = { | ||
.channels_min = 2, | ||
.channels_max = 2, | ||
.rates = SNDRV_PCM_RATE_44100, | ||
.formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
}, | ||
}; | ||
|
||
static const struct snd_soc_codec_driver xilinx_dp_codec_codec_driver = { | ||
}; | ||
|
||
static int xilinx_dp_codec_probe(struct platform_device *pdev) | ||
{ | ||
struct xilinx_dp_codec *codec; | ||
int rate, ret; | ||
|
||
codec = devm_kzalloc(&pdev->dev, sizeof(*codec), GFP_KERNEL); | ||
if (!codec) | ||
return -ENOMEM; | ||
|
||
codec->aud_clk = devm_clk_get(&pdev->dev, NULL); | ||
if (IS_ERR(codec->aud_clk)) | ||
return PTR_ERR(codec->aud_clk); | ||
|
||
ret = clk_prepare_enable(codec->aud_clk); | ||
if (ret) { | ||
dev_err(&pdev->dev, "failed to enable the aud_clk\n"); | ||
return ret; | ||
} | ||
|
||
rate = clk_get_rate(codec->aud_clk) / 512; | ||
if (rate == 44100) { | ||
xilinx_dp_codec_dai.playback.rates = SNDRV_PCM_RATE_44100; | ||
} else if (rate == 48000) { | ||
xilinx_dp_codec_dai.playback.rates = SNDRV_PCM_RATE_48000; | ||
} else { | ||
ret = -EINVAL; | ||
goto error_clk; | ||
} | ||
|
||
ret = snd_soc_register_codec(&pdev->dev, &xilinx_dp_codec_codec_driver, | ||
&xilinx_dp_codec_dai, 1); | ||
if (ret) | ||
goto error_clk; | ||
|
||
platform_set_drvdata(pdev, codec); | ||
|
||
dev_info(&pdev->dev, "Xilinx DisplayPort Sound Codec probed\n"); | ||
|
||
return 0; | ||
|
||
error_clk: | ||
clk_disable_unprepare(codec->aud_clk); | ||
return ret; | ||
} | ||
|
||
static int xilinx_dp_codec_dev_remove(struct platform_device *pdev) | ||
{ | ||
struct xilinx_dp_codec *codec = platform_get_drvdata(pdev); | ||
|
||
snd_soc_unregister_codec(&pdev->dev); | ||
clk_disable_unprepare(codec->aud_clk); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct of_device_id xilinx_dp_codec_of_match[] = { | ||
{ .compatible = "xlnx,dp-snd-codec", }, | ||
{ /* end of table */ }, | ||
}; | ||
MODULE_DEVICE_TABLE(of, xilinx_dp_codec_of_match); | ||
|
||
static struct platform_driver xilinx_dp_codec_driver = { | ||
.driver = { | ||
.name = "xilinx-dp-snd-codec", | ||
.of_match_table = xilinx_dp_codec_of_match, | ||
}, | ||
.probe = xilinx_dp_codec_probe, | ||
.remove = xilinx_dp_codec_dev_remove, | ||
}; | ||
module_platform_driver(xilinx_dp_codec_driver); | ||
|
||
MODULE_DESCRIPTION("Xilinx DisplayPort Sound Codec module"); | ||
MODULE_LICENSE("GPL v2"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* Xilinx DisplayPort Sound PCM support | ||
* | ||
* Copyright (C) 2015 Xilinx, Inc. | ||
* | ||
* Author: Hyun Woo Kwon <[email protected]> | ||
* | ||
* This software is licensed under the terms of the GNU General Public | ||
* License version 2, as published by the Free Software Foundation, and | ||
* may be copied, distributed, and modified under those terms. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <linux/device.h> | ||
#include <linux/module.h> | ||
#include <linux/platform_device.h> | ||
|
||
#include <sound/dmaengine_pcm.h> | ||
#include <sound/pcm.h> | ||
#include <sound/soc.h> | ||
|
||
static const struct snd_pcm_hardware xilinx_pcm_hw = { | ||
.info = SNDRV_PCM_INFO_MMAP | | ||
SNDRV_PCM_INFO_MMAP_VALID | | ||
SNDRV_PCM_INFO_INTERLEAVED | | ||
SNDRV_PCM_INFO_PAUSE | | ||
SNDRV_PCM_INFO_RESUME | | ||
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
.buffer_bytes_max = 128 * 1024, | ||
.period_bytes_min = 256, | ||
.period_bytes_max = 1024 * 1024, | ||
.periods_min = 2, | ||
.periods_max = 256, | ||
}; | ||
|
||
static const struct snd_dmaengine_pcm_config xilinx_dmaengine_pcm_config = { | ||
.pcm_hardware = &xilinx_pcm_hw, | ||
.prealloc_buffer_size = 64 * 1024, | ||
}; | ||
|
||
static int xilinx_dp_pcm_probe(struct platform_device *pdev) | ||
{ | ||
int ret; | ||
|
||
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, | ||
&xilinx_dmaengine_pcm_config, 0); | ||
if (ret) | ||
return ret; | ||
|
||
dev_info(&pdev->dev, "Xilinx DisplayPort Sound PCM probed\n"); | ||
|
||
return 0; | ||
} | ||
|
||
static int xilinx_dp_pcm_dev_remove(struct platform_device *pdev) | ||
{ | ||
return 0; | ||
} | ||
|
||
static const struct of_device_id xilinx_dp_pcm_of_match[] = { | ||
{ .compatible = "xlnx,dp-snd-pcm", }, | ||
{ /* end of table */ }, | ||
}; | ||
MODULE_DEVICE_TABLE(of, xilinx_dp_pcm_of_match); | ||
|
||
static struct platform_driver xilinx_dp_pcm_driver = { | ||
.driver = { | ||
.name = "xilinx-dp-snd-pcm", | ||
.of_match_table = xilinx_dp_pcm_of_match, | ||
}, | ||
.probe = xilinx_dp_pcm_probe, | ||
.remove = xilinx_dp_pcm_dev_remove, | ||
}; | ||
module_platform_driver(xilinx_dp_pcm_driver); | ||
|
||
MODULE_DESCRIPTION("Xilinx DisplayPort Sound PCM module"); | ||
MODULE_LICENSE("GPL v2"); |