I had some progress with registering the driver, but I think that’s not the correct way to do it.
What I’ve done is to add the following in arch/arm/mach-tegra/board-ardbeg.c
struct platform_device pcm271_dit_driver = {
.name = "pcm271a",
.id = -1,
};
static struct tegra_asoc_platform_data ardbeg_audio_pdata_pcm271 = {
.gpio_hp_det = -1,
.gpio_ldo1_en = -1,
.gpio_spkr_en = -1,
.gpio_int_mic_en = -1,
.gpio_ext_mic_en = -1,
.gpio_hp_mute = -1,
.gpio_codec1 = -1,
.gpio_codec2 = -1,
.gpio_codec3 = -1,
.i2s_param[1] = { // 1= DAP2 -> I2S1
.audio_port_id = 1,
.is_i2s_master = 0,
.i2s_mode = TEGRA_DAIFMT_I2S,
.sample_size = 32,
.channels = 8,
},
.i2s_param[3] = {// 3= DAP4 -> I2S3
.audio_port_id = 3,
.is_i2s_master = 0,
.i2s_mode = TEGRA_DAIFMT_I2S,
.sample_size = 32,
.channels = 8,
},
};
static void ardbeg_audio_init(void)
{
ardbeg_audio_pdata_pcm271.codec_name = "pcm271a";
ardbeg_audio_pdata_pcm271.codec_dai_name = "pcm271a-hifi";
}
static struct platform_device ardbeg_audio_device_pcm271_codec = {
.name = "tegra-snd-pcm271",
.id = 0,
.dev = {
.platform_data = &ardbeg_audio_pdata_pcm271,
},
};
static void __init tegra_ardbeg_late_init(void)
{
...
ret = platform_device_register(&pcm271_dit_driver);
pr_info("pcm271-codec: register pcm271a codec, ret: %d\n", ret);
ret = platform_device_register(&ardbeg_audio_device_pcm271_codec);
pr_info("pcm271-driver: register pcm271a driver, ret: %d\n", ret);
...
}
My codec driver is the following one:
#include <asm/mach-types.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/initval.h>
static int pcm271_codec_probe(struct snd_soc_codec *codec)
{
codec->dapm.idle_bias_off = 1;
return 0;
}
static int pcm271_codec_write(struct snd_soc_codec * codec, unsigned int reg,
unsigned int val){
return 0;
}
static unsigned int pcm271_codec_read(struct snd_soc_codec *codec, unsigned int reg) {
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_pcm271 = {
.probe = pcm271_codec_probe,
.read = pcm271_codec_read,
.write = pcm271_codec_write,
};
static struct snd_soc_dai_driver pcm271_codec_dai = {
.name = "pcm271a-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_96000,
.formats = SNDRV_PCM_FMTBIT_FLOAT_LE,
},
.capture = {
.stream_name = "Capture",
.channels_min = 8,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_96000,
.formats = SNDRV_PCM_FMTBIT_FLOAT_LE,
},
};
static int pcm271_dit_probe(struct platform_device *pdev)
{
int ret = snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_pcm271, &pcm271_codec_dai, 1);
dev_info(NULL, "pcm271-codec: probe res: %d\n", ret);
return ret;
}
static int pcm271_dit_remove(struct platform_device *pdev)
{
dev_info(NULL, "pcm271-codec: remove\n");
snd_soc_unregister_codec(&pdev->dev);
return 0;
}
/**
* I2S Digital audio Interface Transmittion (DIT) device
*/
static struct platform_driver pcm271_dit_driver = {
.driver = {
.name = "pcm271a",
.owner = THIS_MODULE,
},
.probe = pcm271_dit_probe,
.remove = pcm271_dit_remove,
};
#ifdef CONFIG_OF
static const struct of_device_id pcm271_codec_dt_ids[] = {
{ .compatible = "midas,pcm271a", },
{ }
};
MODULE_DEVICE_TABLE(of, pcm271_codec_dt_ids);
#endif
module_platform_driver(pcm271_dit_driver);
MODULE_DESCRIPTION("PCM271A ASoC driver (pcm271a)");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
And in sound/soc/tegra/tegra_rt5639.c I’ve change several things, but the important ones are the following:
static struct snd_soc_dai_link tegra_pcm271_dai[NUM_DAI_LINKS] = {
[DAI_LINK_I2S_A] = {
.name = "PCM271A",
.stream_name = "Playback",
.codec_name = "pcm271a",
.platform_name = "tegra-pcm-audio",
.cpu_dai_name = "tegra30-i2s.1",
.codec_dai_name = "pcm271a-hifi",
.init = tegra_pcm271_init,
.ops = &tegra_pcm271_ops,
},
}
static struct snd_soc_card snd_soc_tegra_pcm271 = {
.name = "tegra-pcm271a",
.owner = THIS_MODULE,
.dai_link = tegra_pcm271_dai,
.num_links = ARRAY_SIZE(tegra_pcm271_dai),
}
static const struct of_device_id tegra_rt5639_of_match[] = {
{ .compatible = "nvidia,tegra-audio-rt5639", },
{},
};
static struct platform_driver tegra_pcm271_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
.of_match_table = tegra_rt5639_of_match,
},
.probe = tegra_pcm271_driver_probe,
.remove = tegra_pcm271_driver_remove,
};
static int __init tegra_rt5639_modinit(void)
{
return platform_driver_register(&tegra_pcm271_driver);
}
module_init(tegra_rt5639_modinit);
static void __exit tegra_rt5639_modexit(void)
{
platform_driver_unregister(&tegra_pcm271_driver);
}
module_exit(tegra_rt5639_modexit);
MODULE_DESCRIPTION("Tegra+pcm271a machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
Now when the kernel boots I can see both the codec and the DAI:
[ 6.040879] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: snd_soc_register_card()
[ 6.048885] tegra-snd-pcm271 tegra-snd-pcm271.0: codec name: pcm271a
[ 6.055330] tegra-snd-pcm271 tegra-snd-pcm271.0: codec dai name: pcm271a-hifi
[ 6.062554] tegra-snd-pcm271 tegra-snd-pcm271.0: platform name: tegra30-i2s.0
[ 6.069777] tegra-snd-pcm271 tegra-snd-pcm271.0: cpu name: (null)
[ 6.075982] tegra-snd-pcm271 tegra-snd-pcm271.0: ASoC: binding PCM271A at idx 0
[ 6.083295] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra30-spdif
[ 6.092167] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra30-i2s.4
[ 6.101039] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra30-i2s.3
[ 6.109913] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra30-i2s.1
[ 6.118785] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra30-i2s.0
[ 6.127655] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra-offload-compr
[ 6.137048] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: tegra-offload-pcm
[ 6.146265] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: pcm271a-hifi
[ 6.155050] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: dit-hifi
[ 6.163488] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: dit-hifi
[ 6.171933] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: dit-hifi
[ 6.180371] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: CPU DAI name found: snd-soc-dummy-dai
[ 6.189591] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: Codec found: pcm271a
[ 6.197336] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: Codec found: spdif-dit.2
[ 6.205427] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: Codec found: spdif-dit.1
[ 6.213516] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: Codec found: spdif-dit.0
[ 6.221605] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: Codec found: snd-soc-dummy
[ 6.229870] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: tegra30-spdif
[ 6.238394] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: tegra30-i2s.4
[ 6.246916] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: tegra30-i2s.3
[ 6.255440] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: tegra30-i2s.1
[ 6.263964] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: tegra30-i2s.0
[ 6.272487] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: tegra-offload
[ 6.281010] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: platform found: snd-soc-dummy
[ 6.290160] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271a-hifi <-> tegra30-i2s.0 mapping ok
[ 6.299377] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271: snd_soc_register_card: 0
[ 6.306877] sysedp_create_consumer: unable to create speaker, no consumer_data for speaker found
[ 6.315491] tegra-snd-pcm271 tegra-snd-pcm271.0: pcm271-driver: probe finished
And when if I list the alsa devices I get:
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Tegra [HDA NVIDIA Tegra], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrapcm271a [tegra-pcm271a], device 0: Playback pcm271a-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
Now, the thing is that if in arch/arm/mach-tegra/board-ardbeg.c I change the codec name in the ardbeg_audio_pdata_pcm271 struct, then the ASOC driver fails to load, eg:
static void ardbeg_audio_init(void)
{
ardbeg_audio_pdata_pcm271.codec_name = "pcm271a.c001";
ardbeg_audio_pdata_pcm271.codec_dai_name = "pcm271a-hifi";
}
That will return an error that the ‘ASoC: CODEC pcm271a.c001 not registered’. Why is that happens? Shouldn’t snd_soc_dai_link.name in sound/soc/tegra/tegra_rt5639.c be a random name? It supposed to be a random name in there and only ‘snd_soc_dai_link.codec_name’, ‘snd_soc_dai_link.stream_name’, ‘snd_soc_dai_link.cpu_dai_name’ and ‘snd_soc_dai_link.codec_dai_name’ point to the codec and cpu names.
It seems like the registration is correct.
Any ideas?
P.S. I don’t get audio yet.