硬件平台mini2440开发板(S3C2440+UDA1341)
linux版本:linux-3.4.99
ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。在ASoc出现之前,内核对于SoC中的音频已经有部分的支持,不过会有一些局限性:
通常,就像软件领域里的抽象和重用一样,嵌入式设备的音频系统可以被划分为板载硬件(Machine)、Soc(Platform)、Codec三大部分,如下图所示:
下面就3大部分分别看下相关代码
1.platform:在该开发板中,platform包含了DMA和IIS的实现。
DMA:在/sound/soc/samsung/dma.c文件中,相关代码为:
static struct platform_driver asoc_dma_driver = { .driver = { .name = "samsung-audio", .owner = THIS_MODULE, }, .probe = samsung_asoc_platform_probe, .remove = __devexit_p(samsung_asoc_platform_remove), }; Static struct snd_soc_platform_driver samsung_asoc_platform = { .ops = &dma_ops, .pcm_new = dma_new, .pcm_free = dma_free_dm_buffers, }; static struct snd_pcm_ops dma_ops = { .open = dma_open, .close = dma_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = dma_hw_params, .hw_free = dma_hw_free, .prepare = dma_prepare, .trigger = dma_trigger, .pointer = dma_pointer, .mmap = dma_mmap, };
struct platform_device samsung_asoc_dma = { .name = "samsung-audio", .id = -1, .dev = { .dma_mask = &samsung_device_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), } };
IIS:在\sound\soc\samsung\S3c24xx-i2s.c中实现了相关代码:
static struct platform_driver s3c24xx_iis_driver = { .probe = s3c24xx_iis_dev_probe, .remove = __devexit_p(s3c24xx_iis_dev_remove), .driver = { .name = "s3c24xx-iis", .owner = THIS_MODULE, }, };
static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { .trigger = s3c24xx_i2s_trigger, .hw_params = s3c24xx_i2s_hw_params, .set_fmt = s3c24xx_i2s_set_fmt, .set_clkdiv = s3c24xx_i2s_set_clkdiv, .set_sysclk = s3c24xx_i2s_set_sysclk, }; static struct snd_soc_dai_driver s3c24xx_i2s_dai = { .probe = s3c24xx_i2s_probe, .suspend = s3c24xx_i2s_suspend, .resume = s3c24xx_i2s_resume, .playback = { .channels_min = 2, .channels_max = 2, .rates = S3C24XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, .capture = { .channels_min = 2, .channels_max = 2, .rates = S3C24XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, .ops = &s3c24xx_i2s_dai_ops, };
struct platform_device s3c_device_iis = { .name = "s3c24xx-iis", .id = -1, .num_resources = ARRAY_SIZE(s3c_iis_resource), .resource = s3c_iis_resource, .dev = { .dma_mask = &samsung_device_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), } };
static struct platform_driver uda134x_codec_driver = { .driver = { .name = "uda134x-codec", .owner = THIS_MODULE, }, .probe = uda134x_codec_probe, .remove = __devexit_p(uda134x_codec_remove), };
static const struct snd_soc_dai_ops uda134x_dai_ops = { .startup = uda134x_startup, .shutdown = uda134x_shutdown, .hw_params = uda134x_hw_params, .digital_mute = uda134x_mute, .set_sysclk = uda134x_set_dai_sysclk, .set_fmt = uda134x_set_dai_fmt, }; static struct snd_soc_dai_driver uda134x_dai = { .name = "uda134x-hifi", /* playback capabilities */ .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = UDA134X_RATES, .formats = UDA134X_FORMATS, }, /* capture capabilities */ .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 2, .rates = UDA134X_RATES, .formats = UDA134X_FORMATS, }, /* pcm operations */ .ops = &uda134x_dai_ops, };
static struct snd_soc_codec_driver soc_codec_dev_uda134x = { .probe = uda134x_soc_probe, .remove = uda134x_soc_remove, .suspend = uda134x_soc_suspend, .resume = uda134x_soc_resume, .reg_cache_size = sizeof(uda134x_reg), .reg_word_size = sizeof(u8), .reg_cache_default = uda134x_reg, .reg_cache_step = 1, .read = uda134x_read_reg_cache, .write = uda134x_write, .set_bias_level = uda134x_set_bias_level, }; static int __devinit uda134x_codec_probe(struct platform_device *pdev) { return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_uda134x, &uda134x_dai, 1); }
static struct platform_device uda1340_codec = { .name = "uda134x-codec", .id = -1, };
sound\soc\samsung\s3c24xx_uda134x.c
static struct platform_driver s3c24xx_uda134x_driver = { .probe = s3c24xx_uda134x_probe, .remove = s3c24xx_uda134x_remove, .driver = { .name = "s3c24xx_uda134x", .owner = THIS_MODULE, }, };
static struct platform_device smdk2440_audio = { .name = "s3c24xx_uda134x", .id = 0, .dev = { .platform_data = &smdk2440_audio_pins, }, };
s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1); if (!s3c24xx_uda134x_snd_device) { printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " "Unable to register\n"); return -ENOMEM; } platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x); platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x)); ret = platform_device_add(s3c24xx_uda134x_snd_device); if (ret) { printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); platform_device_put(s3c24xx_uda134x_snd_device); }
static struct snd_soc_ops s3c24xx_uda134x_ops = { .startup = s3c24xx_uda134x_startup, .shutdown = s3c24xx_uda134x_shutdown, .hw_params = s3c24xx_uda134x_hw_params, }; static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { .name = "UDA134X", .stream_name = "UDA134X", .codec_name = "uda134x-codec", .codec_dai_name = "uda134x-hifi", .cpu_dai_name = "s3c24xx-iis", .ops = &s3c24xx_uda134x_ops, .platform_name = "samsung-audio", }; static struct snd_soc_card snd_soc_s3c24xx_uda134x = { .name = "S3C24XX_UDA134X", .owner = THIS_MODULE, .dai_link = &s3c24xx_uda134x_dai_link, .num_links = 1, };