ASoC: rockchip: multicodecs: support DPCM

Change-Id: I1e856b305bb949791962a1c157bae8981b2663f9
Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
This commit is contained in:
Jason Zhu
2024-06-19 17:30:06 +08:00
committed by Tao Huang
parent b39062142f
commit d4a03cf620

View File

@@ -41,6 +41,7 @@
#define DRV_NAME "rk-multicodecs"
#define WAIT_CARDS (SNDRV_CARDS - 1)
#define DEFAULT_MCLK_FS 256
#define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF)
struct adc_keys_button {
u32 voltage;
@@ -57,7 +58,7 @@ struct input_dev_poller {
struct multicodecs_data {
struct snd_soc_card snd_card;
struct snd_soc_dai_link dai_link;
struct snd_soc_dai_link dai_link[3];
struct snd_soc_jack *jack_headset;
struct gpio_desc *hp_ctl_gpio;
struct gpio_desc *spk_ctl_gpio;
@@ -312,7 +313,6 @@ static int mc_spk_event(struct snd_soc_dapm_widget *w,
break;
default:
return 0;
}
return 0;
@@ -321,6 +321,8 @@ static int mc_spk_event(struct snd_soc_dapm_widget *w,
static const struct snd_soc_dapm_widget mc_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone", mc_hp_event),
SND_SOC_DAPM_SPK("Speaker", mc_spk_event),
SND_SOC_DAPM_LINE("Line Out Jack", NULL),
SND_SOC_DAPM_LINE("Line In Jack", NULL),
SND_SOC_DAPM_MIC("Main Mic", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -492,7 +494,7 @@ static int rk_multicodecs_parse_daifmt(struct device_node *node,
struct multicodecs_data *mc_data,
const char *prefix)
{
struct snd_soc_dai_link *dai_link = &mc_data->dai_link;
struct snd_soc_dai_link *dai_link = &mc_data->dai_link[0];
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
unsigned int daifmt;
@@ -592,17 +594,56 @@ static struct snd_soc_ops rk_ops = {
.hw_params = rk_multicodecs_hw_params,
};
SND_SOC_DAILINK_DEFS(hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hifi_fe,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hifi_be,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_DUMMY()));
static const struct snd_soc_dai_link rk_multicodecs_card_dai[] = {
/* Default ASoC DAI Link*/
{
.name = "HiFi",
.stream_name = "HiFi",
.ops = &rk_ops,
SND_SOC_DAILINK_REG(hifi),
},
/* DPCM Link between Front-End and Back-End (Optional) */
{
.name = "HiFi-ASRC-FE",
.stream_name = "HiFi-ASRC-FE",
.dpcm_playback = 1,
.dpcm_capture = 1,
.dynamic = 1,
SND_SOC_DAILINK_REG(hifi_fe),
},
{
.name = "HiFi-ASRC-BE",
.stream_name = "HiFi-ASRC-BE",
.ops = &rk_ops,
.dpcm_playback = 1,
.dpcm_capture = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(hifi_be),
},
};
static int rk_multicodecs_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
struct device_node *np = pdev->dev.of_node;
struct snd_soc_dai_link *link;
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link_component *platforms;
struct device_node *np = pdev->dev.of_node, *node, *asrc_np;
struct snd_soc_dai_link_component *codecs;
struct multicodecs_data *mc_data;
struct of_phandle_args args;
struct device_node *node;
struct input_dev *input;
u32 val;
int count, value, irq;
@@ -619,13 +660,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
if (!mc_data)
return -ENOMEM;
cpus = devm_kzalloc(&pdev->dev, sizeof(*cpus), GFP_KERNEL);
if (!cpus)
return -ENOMEM;
platforms = devm_kzalloc(&pdev->dev, sizeof(*platforms), GFP_KERNEL);
if (!platforms)
return -ENOMEM;
memcpy(mc_data->dai_link, rk_multicodecs_card_dai, sizeof(mc_data->dai_link));
card = &mc_data->snd_card;
card->dev = &pdev->dev;
@@ -635,18 +670,15 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
link = &mc_data->dai_link;
link->name = "dailink-multicodecs";
link->stream_name = link->name;
link->init = rk_dailink_init;
link->ops = &rk_ops;
link->cpus = cpus;
link->platforms = platforms;
link->num_cpus = 1;
link->num_platforms = 1;
link->ignore_pmdown_time = 1;
mc_data->dai_link[0].name = "dailink-multicodecs";
mc_data->dai_link[0].stream_name = mc_data->dai_link[0].name;
mc_data->dai_link[0].init = rk_dailink_init;
mc_data->dai_link[0].ops = &rk_ops;
mc_data->dai_link[0].num_cpus = 1;
mc_data->dai_link[0].num_platforms = 1;
mc_data->dai_link[0].ignore_pmdown_time = 1;
card->dai_link = link;
card->dai_link = mc_data->dai_link;
card->num_links = 1;
card->dapm_widgets = mc_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(mc_dapm_widgets);
@@ -675,8 +707,8 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
if (!codecs)
return -ENOMEM;
link->codecs = codecs;
link->num_codecs = idx;
mc_data->dai_link[0].codecs = codecs;
mc_data->dai_link[0].num_codecs = idx;
idx = 0;
for (i = 0; i < count; i++) {
node = of_parse_phandle(np, "rockchip,codec", i);
@@ -700,11 +732,26 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
/* Only reference the codecs[0].of_node which maybe as master. */
rk_multicodecs_parse_daifmt(np, codecs[0].of_node, mc_data, prefix);
link->cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0);
if (!link->cpus->of_node)
mc_data->dai_link[0].cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0);
if (!mc_data->dai_link[0].cpus->of_node)
return -ENODEV;
link->platforms->of_node = link->cpus->of_node;
mc_data->dai_link[0].platforms->of_node = mc_data->dai_link[0].cpus->of_node;
asrc_np = of_parse_phandle(np, "rockchip,asrc", 0);
if (asrc_np) {
mc_data->dai_link[1].cpus->of_node = asrc_np;
mc_data->dai_link[1].platforms->of_node = asrc_np;
mc_data->dai_link[1].num_cpus = 1;
mc_data->dai_link[1].num_platforms = 1;
/* Support multicodec in future */
mc_data->dai_link[2].codecs->dai_name = "dummy_codec";
mc_data->dai_link[2].codecs->of_node = of_parse_phandle(np, "rockchip,codec", 0);
mc_data->dai_link[2].cpus->of_node = mc_data->dai_link[0].cpus->of_node;
card->num_links = 3;
}
mc_data->mclk_fs = DEFAULT_MCLK_FS;
if (!of_property_read_u32(np, "rockchip,mclk-fs", &val))
@@ -814,7 +861,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
snd_soc_of_parse_audio_routing(card, "rockchip,audio-routing");
snd_soc_card_set_drvdata(card, mc_data);
platform_set_drvdata(pdev, card);
platform_set_drvdata(pdev, mc_data);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
@@ -832,8 +879,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
static int rk_multicodec_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(card);
struct multicodecs_data *mc_data = platform_get_drvdata(pdev);
cancel_delayed_work_sync(&mc_data->handler);
@@ -842,8 +888,7 @@ static int rk_multicodec_remove(struct platform_device *pdev)
static void rk_multicodec_shutdown(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(card);
struct multicodecs_data *mc_data = platform_get_drvdata(pdev);
cancel_delayed_work_sync(&mc_data->handler);
}