现在由于公司要上手wm8976的芯片的支持,主要是用于3G的通话的通道的打开:
1:现在我们的构思就是,3G通话的平板电脑的输入是mic/mip 输入 然后由wm8976的LOUT3口输出到3G上面去,然后我们电话那头的说话声音是如何输入到平板的呐,就是3G模块的声音的输入是经过wm8976的AUX口的输入,然后是经过hp的输出,我们通过平板的耳机或者是喇叭就可以听见电话那头的声音
2:有与项目时间比较急,我就没有按照音频的标准驱动来做,就是上层调用下层驱动的标准方式,我是采用有3G的上层写proc来做的。
3:下面让我们看看我的一些代码吧
a:我在wm8976的驱动里面是如何建立proc的文件呐,细看哦!
/*********wangyulu add down******/
extern char sound_codec[];
if(!strcmp(sound_codec, "wm8976")){
#define MODEM_SWITCH_PROC_NAME "sound8976_galley_select"
#define PROC_NAME "sound8976"
extern struct proc_dir_entry proc_root;
static struct proc_dir_entry *root_entry;
static struct proc_dir_entry *entry;
root_entry = proc_mkdir(PROC_NAME, &proc_root);
s_proc = create_proc_entry(MODEM_SWITCH_PROC_NAME, 0666, root_entry);
if (s_proc != NULL){
s_proc->write_proc = modem_switch_writeproc;
s_proc->read_proc = modem_switch_readproc;
}
}
//printk(KERN_INFO "Initializing wm8976_modinit...\n");
/********wangyulu add up********/
这是我在proc里面建立的文件,通过上层可以对proc的文件读和写就可以调用proc的读写函数,就可以达到上层调用下层驱动的目的。
b:呵呵,我向大家肯定是想问问proc的驱动的读写何在?别急来也!
extern int Sound_Flag;
static int sound8976_galley_select_flag = 0;
static struct proc_dir_entry * s_proc = NULL;
static int modem_switch_writeproc(struct file *file,const char *buffer,
unsigned long count, void *data)
{
int value;
value = 0;
sscanf(buffer, "%d", &value);
switch(value)
{
case 0:
wm8976_set_register_sound(value);
break;
case 1:
wm8976_set_register_sound(value);
break;
default:
//printk("************************wangyulu sound8976_galley_select_flag ==null***********************\n");
break;
}
return count;
}
对于写函数主要是看看控制3G的java的代码是对proc的写的是1或是0就可以调用wm8976_set_register_sound(value);
函数了
static int modem_switch_readproc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", sound8976_galley_select_flag==0?0:(sound8976_galley_select_flag==1?1:(sound8976_galley_select_flag==2?2:3))); //wangyulu
if (off + count >= len)
*eof = 1;
if (len < off)
return 0;
*start = page + off;
return ((count < len - off) ? count : len - off);
}
这就是proc驱动里面的读写函数
c:下面贴出我在上层做得事情:目的就是3G来电就是想proc写1 ,调用wm8976_set_register_sound(1);,打开wm8976的3G的声音输入输出通道。
private static final String MODEM_MAYBE_PLUGED = "proc/sound8976/sound8976_galley_select"; //wangyulu
//private static final String MODEM_MAYBE_PLUGED = "proc/sound5621/sound5621_galley_select"; //wangyulu
private void updateScreen() {
if (true) log("updateScreen()...");
if (true) log("/*************************wangyulu updateScreen Phone ***************************/ ");
File awakeTimeFile = new File("proc/sound8976/sound8976_galley_select");
File awakeTimeFile5621 = new File("proc/sound5621/sound5621_galley_select");
//if (!awakeTimeFile.exists()) return 0;
FileWriter fr;
FileWriter wr;
try {
fr = new FileWriter(awakeTimeFile);
wr = new FileWriter(awakeTimeFile5621);
fr.write("1");
wr.write("1");
if (true) log("/*************************wangyulu updateScreen write success ***************************/ ");
fr.close();
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
// Don't update anything if we're not in the foreground (there's
// no point updating our UI widgets since we're not visible!)
// Also note this check also ensures we won't update while we're
// in the middle of pausing, which could cause a visible glitch in
// the "activity ending" transition.
if (!mIsForegroundActivity) {
if (DBG) log("- updateScreen: not the foreground Activity! Bailing out...");
return;
}
d:当3G挂断的时候就关闭3G的通道是
if (!mIsForegroundActivity) {
if (DBG) log("onPhoneStateChanged: Activity not in foreground! Bailing out...");
/*************wangyulu add down************/
File awakeTimeFile = new File("proc/sound8976/sound8976_galley_select");
File awakeTimeFile5621 = new File("proc/sound5621/sound5621_galley_select");
//if (!awakeTimeFile.exists()) return 0;
FileWriter fr;
FileWriter wr;
try {
fr = new FileWriter(awakeTimeFile);
wr = new FileWriter(awakeTimeFile5621);
fr.write("0");
wr.write("0");
if (true) log("/*************************wangyulu updateScreen write success ***************************/ ");
fr.close();
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
在来看看我对wm8976的通道打开的函数吧
static int wm8976_set_register_sound( int val)
{
int i;
unsigned int reg;
#if 1
if ((val ==1) && (wm8976_flag == 1)){
for (i=0; i<58; i++) {
reg = wm8976_read_reg_cache(g_codec, i);
reg_buf[i] = reg;
//printk("reg_buf=0x%02X\n", reg_buf[i]);
}
printk("************************wangyulu 888888888888888888888888888888************************\n");
}
#endif
//************ urbetter ***************
sound8976_galley_select_flag = 0;
if(val == 0){
//R0
reg = wm8976_read_reg_cache(g_codec,WM8976_RESET);
wm8976_write(g_codec, WM8976_RESET, (reg |0x0000) & 0x0000);
//R1
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER1);
wm8976_write(g_codec, WM8976_POWER1, (reg | 0x001D) & 0x0000);
//R2
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER2);
wm8976_write(g_codec, WM8976_POWER2, (reg | 0x0015) & 0x0000);
//R3
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER3);
wm8976_write(g_codec, WM8976_POWER3, (reg | 0x006E) & 0x0000);
printk("************************wangyulu val=00000000000000000000000000************************\n");
for(i=4 ; i<58; i++) {
wm8976_write(g_codec, i, reg_buf[i]);
//printk("reg_buf=0x%02X\n", reg_buf[i]); 0
wm8976_flag =3;
}
}
else if(val == 1) {
printk("**********************wangyulu wm8976_set_register_sound ====1***********************\n");
printk("wangyulu2 wm8976 LIN_LIP\n");
wm8976_flag = 2;
#if 1
//R0
reg = wm8976_read_reg_cache(g_codec,WM8976_RESET );
wm8976_write(g_codec, WM8976_RESET, (reg |0x0000) & 0x0000);
//R1
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER1);
//wm8976_write(g_codec, WM8976_POWER1, (reg | 0x001D) & 0x001D);//yuanlai
wm8976_write(g_codec, WM8976_POWER1, (reg | 0x01D9) & 0x01D9);//LU
//R2
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER2);
wm8976_write(g_codec, WM8976_POWER2, (reg | 0x0195) & 0x0195);//yuanlai
//R3
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER3);
//wm8976_write(g_codec, WM8976_POWER3, (reg | 0x006E) & 0x006E);//yuanlai
wm8976_write(g_codec, WM8976_POWER3, (reg | 0x01ef) & 0x01ef); //LU
//R4
reg = wm8976_read_reg_cache(g_codec,WM8976_IFACE );
wm8976_write(g_codec, WM8976_IFACE, (reg | 0x0010) & 0x0010);
//R5
reg = wm8976_read_reg_cache(g_codec,WM8976_COMP );
wm8976_write(g_codec, WM8976_COMP, (reg | 0x0000) & 0x0000);
//R6
reg = wm8976_read_reg_cache(g_codec,WM8976_CLOCK );
wm8976_write(g_codec, WM8976_CLOCK, reg | 0x0000);
//R7
reg = wm8976_read_reg_cache(g_codec,WM8976_ADD);
wm8976_write(g_codec, WM8976_ADD, reg | 0x0000);
//R8
reg = wm8976_read_reg_cache(g_codec,WM8976_GPIO );
wm8976_write(g_codec, WM8976_GPIO, reg | 0x0000);
//R9
reg = wm8976_read_reg_cache(g_codec,WM8976_JACK1);
wm8976_write(g_codec, WM8976_JACK1, reg | 0x0000 );
//R10
reg = wm8976_read_reg_cache(g_codec,WM8976_DAC);
wm8976_write(g_codec, WM8976_DAC, reg | 0x0000);
//R11
reg = wm8976_read_reg_cache(g_codec,WM8976_DACVOLL);
wm8976_write(g_codec, WM8976_DACVOLL, reg |0x01ff );
//R12
reg = wm8976_read_reg_cache(g_codec,WM8976_DACVOLR );
wm8976_write(g_codec, WM8976_DACVOLR, reg | 0x01ff);
//R13
reg = wm8976_read_reg_cache(g_codec,WM8976_JACK2);
wm8976_write(g_codec, WM8976_JACK2, reg |0x0000);
//R14
reg = wm8976_read_reg_cache(g_codec,WM8976_ADC);
wm8976_write(g_codec, WM8976_ADC, reg | 0x0100);
//R15
reg = wm8976_read_reg_cache(g_codec,WM8976_ADCVOL);
wm8976_write(g_codec, WM8976_ADCVOL, reg | 0x01ff);
/*
//R16
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ1);
wm8976_write(g_codec, WM8976_EQ1, reg | );
//R17
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ2);
wm8976_write(g_codec, WM8976_EQ2, reg | );
*/
//R18
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ1);
wm8976_write(g_codec, WM8976_EQ1, reg | 0x012c);
//R19
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ2);
wm8976_write(g_codec, WM8976_EQ2, reg | 0x002c);
//R20
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ3);
wm8976_write(g_codec, WM8976_EQ3, reg | 0x002c);
//R21
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ4);
wm8976_write(g_codec, WM8976_EQ4, reg | 0x002c);
//R22
reg = wm8976_read_reg_cache(g_codec,WM8976_EQ5);
wm8976_write(g_codec, WM8976_EQ5, reg | 0x002c);
/*
//R23
reg = wm8976_read_reg_cache(g_codec,WM8976_DACLIM2);
wm8976_write(g_codec, WM8976_DACLIM2, reg | );
*/
//R24
reg = wm8976_read_reg_cache(g_codec,WM8976_DACLIM1);
wm8976_write(g_codec, WM8976_DACLIM1, reg | 0x0032);
//R25
reg = wm8976_read_reg_cache(g_codec,WM8976_DACLIM2);
wm8976_write(g_codec, WM8976_DACLIM2, reg | 0x0000);
/*
//R26
reg = wm8976_read_reg_cache(g_codec,WM8976_NOTCH3);
wm8976_write(g_codec, WM8976_NOTCH3, reg | );
*/
//R27
reg = wm8976_read_reg_cache(g_codec,WM8976_NOTCH1);
wm8976_write(g_codec, WM8976_NOTCH1, reg | 0x0000);
//R28
reg = wm8976_read_reg_cache(g_codec,WM8976_NOTCH2);
wm8976_write(g_codec, WM8976_NOTCH2, reg | 0x0000);
//R29
reg = wm8976_read_reg_cache(g_codec,WM8976_NOTCH3);
wm8976_write(g_codec, WM8976_NOTCH3, reg | 0x0000);
//R30
reg = wm8976_read_reg_cache(g_codec,WM8976_NOTCH4);
wm8976_write(g_codec, WM8976_NOTCH4, reg | 0x0000);
/*
//R31
reg = wm8976_read_reg_cache(g_codec,WM8976_NGATE);
wm8976_write(g_codec, WM8976_NGATE, reg | );
*/
//R32
reg = wm8976_read_reg_cache(g_codec, WM8976_ALC1);
wm8976_write(g_codec, WM8976_ALC1, (reg | 0x0038) & 0x0038);
//R33
reg = wm8976_read_reg_cache(g_codec,WM8976_ALC2);
wm8976_write(g_codec, WM8976_ALC2, reg | 0x000b );
//R34
reg = wm8976_read_reg_cache(g_codec,WM8976_ALC3);
wm8976_write(g_codec, WM8976_ALC3, reg | 0x0032);
//R35
reg = wm8976_read_reg_cache(g_codec,WM8976_NGATE);
wm8976_write(g_codec, WM8976_NGATE, reg | 0x0000);
//R36
reg = wm8976_read_reg_cache(g_codec,WM8976_PLLN);
wm8976_write(g_codec, WM8976_PLLN, reg | 0x0008);
//R37
reg = wm8976_read_reg_cache(g_codec,WM8976_PLLK1);
wm8976_write(g_codec, WM8976_PLLK1, reg | 0x000c);
//R38
reg = wm8976_read_reg_cache(g_codec,WM8976_PLLK2);
wm8976_write(g_codec, WM8976_PLLK2, reg | 0x0093);
//R39
reg = wm8976_read_reg_cache(g_codec,WM8976_PLLK3);
wm8976_write(g_codec, WM8976_PLLK3, reg | 0x00e9);
/*
//R40
reg = wm8976_read_reg_cache(g_codec,WM8976_DAC);
wm8976_write(g_codec, WM8976_DAC, reg | );
*/
//R41
reg = wm8976_read_reg_cache(g_codec,WM8976_3D);
wm8976_write(g_codec, WM8976_3D, reg | 0x0000 );
/*
//R42
reg = wm8976_read_reg_cache(g_codec,WM8976_DAC);
wm8976_write(g_codec, WM8976_DAC, reg | );
*/
//R43
reg = wm8976_read_reg_cache(g_codec,WM8976_BEEP);
wm8976_write(g_codec, WM8976_BEEP, reg | 0x0010);
//R44
reg = wm8976_read_reg_cache(g_codec, WM8976_INPUT);
wm8976_write(g_codec, WM8976_INPUT, reg | 0x0003);
//R45
//reg = wm8976_read_reg_cache(g_codec, WM8976_INPPGA);
//wm8976_write(g_codec, WM8976_INPPGA, (reg | 0x01B8) & 0x01B8);//yuan
//wm8976_write(g_codec, WM8976_INPPGA, (reg | 0x01f8) & 0x01f8);
//lu
//R45 lu out4
reg = wm8976_read_reg_cache(g_codec, WM8976_INPPGA);
//wm8976_write(g_codec, WM8976_INPPGA, (reg | 0x007f) & 0x0000);
wm8976_write(g_codec, WM8976_INPPGA, (reg | 0x007f) & 0xFF3F);
/*
//R46
reg = wm8976_read_reg_cache(g_codec,WM8976_DAC);
wm8976_write(g_codec, WM8976_DAC, reg | );
*/
//R47
reg = wm8976_read_reg_cache(g_codec, WM8976_ADCBOOST);
wm8976_write(g_codec, WM8976_ADCBOOST, (reg | 0x0100) & 0x0100);
/*
//R48
reg = wm8976_read_reg_cache(g_codec,WM8976_DAC);
wm8976_write(g_codec, WM8976_DAC, reg | );
*/
//R49
reg = wm8976_read_reg_cache(g_codec, WM8976_OUTPUT);
wm8976_write(g_codec, WM8976_OUTPUT, (reg | 0x0018) & 0x0018);//yuan
//R50 //yuanlai
//reg = wm8976_read_reg_cache(g_codec, WM8976_MIXL);
//wm8976_write(g_codec, WM8976_MIXL, (reg | 0x01E0) & 0x01E0);
//R50 //lu youyong out3
reg = wm8976_read_reg_cache(g_codec, WM8976_MIXL);
//wm8976_write(g_codec, WM8976_MIXL, (reg | 0xffff) & 0xffff);
wm8976_write(g_codec, WM8976_MIXL, (reg | 0xfffd) & 0xfffd);
//R51
reg = wm8976_read_reg_cache(g_codec, WM8976_MIXR);
wm8976_write(g_codec, WM8976_MIXR, (reg | 0x01e0) & 0x01e0);
//R52
reg = wm8976_read_reg_cache(g_codec, WM8976_HPVOLL);
wm8976_write(g_codec, WM8976_HPVOLL, (reg | 0x0135) & 0x0135);
//R53
reg = wm8976_read_reg_cache(g_codec, WM8976_HPVOLR);
wm8976_write(g_codec, WM8976_HPVOLR, (reg | 0x0135) & 0x0135);
//R54
reg = wm8976_read_reg_cache(g_codec,WM8976_SPKVOLL);
wm8976_write(g_codec, WM8976_SPKVOLL, reg | 0x013a);
//R55
reg = wm8976_read_reg_cache(g_codec,WM8976_SPKVOLR);
wm8976_write(g_codec, WM8976_SPKVOLR, reg | 0x013a);
//R56
reg = wm8976_read_reg_cache(g_codec, WM8976_OUT3MIX);
//wm8976_write(g_codec, WM8976_OUT3MIX, (reg | 0x000f) & 0x000f);
wm8976_write(g_codec, WM8976_OUT3MIX, (reg | 0x0004) & 0x0004);
//R57
reg = wm8976_read_reg_cache(g_codec, WM8976_MONOMIX);
wm8976_write(g_codec, WM8976_MONOMIX, (reg | 0x0019) & 0x0019);
#endif
#if 0//out3 shihaode
//lulu wm8976_write(g_codec, WM8976_POWER1, pwr_reg|0x01D);//off
printk("************************wangyulu sound8976_galley_select_flag ====1***********************\n");
//R0
reg = wm8976_read_reg_cache(g_codec,WM8976_RESET );
wm8976_write(g_codec, WM8976_RESET, (reg |0x0000) & 0x0000);
//R1
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER1);
//wm8976_write(g_codec, WM8976_POWER1, (reg | 0x001D) & 0x001D);//yuanlai
wm8976_write(g_codec, WM8976_POWER1, (reg | 0x01D9) & 0x01D9);//LU
//R2
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER2);
wm8976_write(g_codec, WM8976_POWER2, (reg | 0x0195) & 0x0195);//yuanlai
//R3
reg = wm8976_read_reg_cache(g_codec, WM8976_POWER3);
//wm8976_write(g_codec, WM8976_POWER3, (reg | 0x006E) & 0x006E);//yuanlai
wm8976_write(g_codec, WM8976_POWER3, (reg | 0x01ef) & 0x01ef); //LU
//R32
reg = wm8976_read_reg_cache(g_codec, WM8976_ALC1);
wm8976_write(g_codec, WM8976_ALC1, (reg | 0x0000) & 0xfeff);
//R44
reg = wm8976_read_reg_cache(g_codec, WM8976_INPUT);
wm8976_write(g_codec, WM8976_INPUT, (reg | 0x0003) & 0xffff);
//R45 out3
reg = wm8976_read_reg_cache(g_codec, WM8976_INPPGA);
wm8976_write(g_codec, WM8976_INPPGA, (reg | 0x007f) & 0xFF3F);
//R47
reg = wm8976_read_reg_cache(g_codec, WM8976_ADCBOOST);
wm8976_write(g_codec, WM8976_ADCBOOST, (reg | 0x0170) & 0xFFF0);
//R47
reg = wm8976_read_reg_cache(g_codec, WM8976_ADCBOOST);
wm8976_write(g_codec, WM8976_ADCBOOST, (reg | 0x01F0) & 0xFFF0);
//R49
reg = wm8976_read_reg_cache(g_codec, WM8976_OUTPUT);
wm8976_write(g_codec, WM8976_OUTPUT, (reg | 0x001b) & 0xFEFF);
printk("wangyulu2 wm8976 MIX_out4 lululu\n");
//R50
reg = wm8976_read_reg_cache(g_codec, WM8976_MIXL);
wm8976_write(g_codec, WM8976_MIXL, reg | 0x01FE);
//R50
reg = wm8976_read_reg_cache(g_codec, WM8976_MIXL);
//wm8976_write(codec, WM8976_MIXL, (reg | 0x01FE) & 0xfffd);
wm8976_write(g_codec, WM8976_MIXL, (reg | 0xffff) & 0xffff);
//R51
reg = wm8976_read_reg_cache(g_codec, WM8976_MIXR);
//wm8976_write(codec, WM8976_MIXR, reg | 0x0020);
wm8976_write(g_codec, WM8976_MIXR, reg | 0x01e0);
//R52
reg = wm8976_read_reg_cache(g_codec, WM8976_HPVOLL);
wm8976_write(g_codec, WM8976_HPVOLL, (reg | 0x003F) & 0xFFBF);
//R53
reg = wm8976_read_reg_cache(g_codec, WM8976_HPVOLR);
wm8976_write(g_codec, WM8976_HPVOLR, (reg | 0x003F)& 0xFFBF);
printk("wangyulu2 wm8976 MIX_out3\n");
//R56
reg = wm8976_read_reg_cache(g_codec, WM8976_OUT3MIX);
wm8976_write(g_codec, WM8976_OUT3MIX, (reg | 0x0006) & 0xffbf); //6=0
//R57
reg = wm8976_read_reg_cache(g_codec, WM8976_MONOMIX);
wm8976_write(g_codec, WM8976_MONOMIX, (reg | 0x0000) & 0xff00);
#endif
//************ urbetter ***************
}
sound8976_galley_select_flag = val;
}
上面是我打开wm8976的3G的通道,同时又不影响wm8976的其他的工作方式。
以上是我调试wm8976用于3G的主要思路,现在已经完成,下面有时间写写wm8976的通道打开注意的问题,同时我也做了RT5621的音频驱动,还有就是把wm8976移植到2.3系统上的问题和rt621移植到2.3上的问题,陆续会和大家分享我的心得。不足之处请大家指教。