对于回放来说,userspace 送过来的音频数据是经过采样量化的数字信号,在 codec 经过 DAC 转换成模拟信号然后输出到外放或耳机,
这样我们就可以听到声音了。Codec 字面意思是编解码器,但芯片里面的功能部件很多,常见的有 AIF、DAC、ADC、Mixer、PGA、
Line-in、Line-out,有些高端的 codec 芯片还有 EQ、DSP、SRC、DRC、AGC、Echo-Canceller、Noise-Suppression 等部件。
/* codec driver */
struct snd_soc_codec_driver {
/* driver ops */
int (*probe)(struct snd_soc_codec *);
int (*remove)(struct snd_soc_codec *);
int (*suspend)(struct snd_soc_codec *);
int (*resume)(struct snd_soc_codec *);
struct snd_soc_component_driver component_driver;
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes;
/* codec wide operations */
int (*set_sysclk)(struct snd_soc_codec *codec,
int clk_id, int source, unsigned int freq, int dir);
int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out);
/* codec IO */
struct regmap *(*get_regmap)(struct device *);
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
unsigned int reg_cache_size;
short reg_cache_step;
short reg_word_size;
const void *reg_cache_default;
/* codec bias level */
int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level);
bool idle_bias_off;
bool suspend_bias_off;
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
};
struct snd_soc_dai_driver {
/* DAI description */
const char *name;
unsigned int id;
int ac97_control;
unsigned int base;
/* DAI driver callbacks */
int (*probe)(struct snd_soc_dai *dai);
int (*remove)(struct snd_soc_dai *dai);
int (*suspend)(struct snd_soc_dai *dai);
int (*resume)(struct snd_soc_dai *dai);
/* compress dai */
bool compress_dai;
/* ops */
const struct snd_soc_dai_ops *ops;
/* DAI capabilities */
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};
mt_soc_codec_63xx.c
static int __init mtk_mt6331_codec_init(void)
{
int ret = 0;
soc_mtk_codec6331_dev = platform_device_alloc(MT_SOC_CODEC_NAME, -1);
ret = platform_device_add(soc_mtk_codec6331_dev);
InitGlobalVarDefault();
return platform_driver_register(&mtk_codec_6331_driver);
}
//platform driver的实例,mtk_codec_6331_driver和soc_mtk_codec6331_dev匹配会调用probe函数
/*static struct platform_driver mtk_codec_6331_driver = {
.driver = {
.name = MT_SOC_CODEC_NAME,
.owner = THIS_MODULE,
},
.probe = mtk_mt6331_codec_dev_probe,
.remove = mtk_mt6331_codec_dev_remove,
};*/
static int mtk_mt6331_codec_dev_probe(struct platform_device *pdev)
{
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
if (pdev->dev.dma_mask == NULL)
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
if (pdev->dev.of_node)
dev_set_name(&pdev->dev, "%s", MT_SOC_CODEC_NAME);
return snd_soc_register_codec(&pdev->dev,
&soc_mtk_codec, mtk_6331_dai_codecs,
ARRAY_SIZE(mtk_6331_dai_codecs));