mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
ASoC: rockchip: multicodecs: support DPCM
Change-Id: I1e856b305bb949791962a1c157bae8981b2663f9 Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user