Linux alsa驱动中的CODEC寄存器配置问题 |
您所在的位置:网站首页 › lookat怎么读语音 › Linux alsa驱动中的CODEC寄存器配置问题 |
调试Audio CODEC时,有时候需要读codec寄存器的值以确认是否配置寄存器成功。 记得之前调试wm8978时,发现这个CODEC的寄存器不能读,每次读的结果都是0xff. 后来在linux上调试wm8978时,用snd_soc_read()又能读到所配置的值,感觉很诧异。当时也没有细究。 这两天有空,在linux内核中看了一下相关代码,发现关于通过I2C读写CODEC的代码在 sound/soc/soc-cache.c中。 在这个.c文件中定义了不少类似 snd_soc_X_Y_read() 和 snd_soc_X_Y_write()的函数,X代表地址位数,Y代码 数据位数,例如snd_soc_7_9_read()用于地址是7位,数据是9位的CODEC,wolfson的CODEC大多数是这种情况。 另外有个用于具体的CODEC驱动去设置X,Y值的接口,以便选择对应的读写函数,这个接口是: int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, int addr_bits, int data_bits, enum snd_soc_control_type control) 例如wm8960.c中有如下配置调用: ret =snd_soc_codec_set_cache_io(codec,7,9,control); 现在说一下snd_soc_X_Y_write()这类函数,例如: static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; if (reg >= codec->reg_cache_size) return -1; return cache[reg]; } 一看代码,原来这里的读,竟然不是从CODEC的寄存器中读出来的,而是从一个cache缓存中读出来的。 再看一下对应的write函数就一清二楚了,原来在write时将所写的寄存器的值同时缓存到cache中,read时 直接从cache中读出。 static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { u16 *cache = codec->reg_cache; u8 data[2]; int ret; BUG_ON(codec->volatile_register); data[0] = (reg > 8) & 0x0001); data[1] = value & 0x00ff; if (reg < codec->reg_cache_size) cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; return 0; } dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value); ret = codec->hw_write(codec->control_data, data, 2); if (ret == 2) return 0; if (ret < 0) return ret; else return -EIO; } 这样,近期一个奇怪的问题又有好解释了: 通过I2C配置sensor后,通过aplay播放音乐无动静(无声音),但通过snd_soc_read()读CODEC(wm8960)各寄存器的值 又是正常的(和能正常播放时的配置一样),用示波器量了一下CODEC的LRCK管脚,没有任何东西(本应该有clock输出的,因为 CODEC被配置为master模式)。原来snd_soc_read()读到的值根本就是之前写进去的缓存,并不是真正CODEC中已经配置的值, 显然CODEC没有正常配置,所以没有LRCK信号输出。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |