?? pxa-wm8971.c
字號:
ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCTL1,0x00c0); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCTL2,0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCIN, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LADCIN,0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RADCIN,0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUTM1,0x0150); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUTM2,0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUTM1,0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUTM2,0x0150); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_MOUTM1,0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_MOUTM2, 0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUT2V, 0x0179); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUT2V, 0x0179); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_MOUTV, 0x0079); /* ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LINVOL, 0x0097); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RINVOL, 0x0097); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUT1V, 0x0040); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUT1V, 0x0040); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LDAC, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RDAC, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUT1V, 0x0179); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUT1V, 0x0179); //ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCDAC, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_AUDIO, 0x0002); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_SRATE, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LDAC, 0x01e0); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RDAC, 0x01e0); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_BASS, 0x000f); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_TREBLE, 0x000f); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ALC1, 0x007b); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ALC2, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ALC3, 0x0032); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_NGATE, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LADC, 0x00c3); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RADC, 0x00c3); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCTL1, 0x00c0); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCTL2, 0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ADCIN, 0x0100); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LADCIN, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RADCIN, 0x0000); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUTM1, 0x0150); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUTM2, 0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUTM1, 0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUTM2, 0x0150); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_MOUTM1, 0x0050); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_MOUTM2, 0x0150); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUT2V, 0x0179); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUT2V, 0x0179); ret += wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_MOUTV, 0x0079); */out: return ret != 0 ? -EIO : 0;}
#if 1static struct wm8971_mixer_t wm8971_mixer;
static int wm8971_mixer_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int i, val = 0; if (cmd == SOUND_MIXER_INFO) { mixer_info info; strncpy(info.id, wm8971_codec.name, sizeof(info.id)); strncpy(info.name, wm8971_codec.name, sizeof(info.name)); info.modify_counter = wm8971_codec.modcnt; if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == SOUND_OLD_MIXER_INFO) { _old_mixer_info info; strncpy(info.id, wm8971_codec.name, sizeof(info.id)); strncpy(info.name, wm8971_codec.name, sizeof(info.name)); if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; } if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_DEVMASK: /* give them the supported mixers */ val = wm8971_codec.supported_mixers; break; //case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ // val = wm8971_codec.record_sources; // break; case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ val = wm8971_codec.stereo_mixers; break; case SOUND_MIXER_CAPS: val = SOUND_CAP_EXCL_INPUT; break; default: /* read a specific mixer */ i = _IOC_NR(cmd); //if (!supported_mixer(&wm8971_codec, i)) // return -EINVAL; val = wm8971_get_mixer(i); break; } return put_user(val, (int *)arg); } if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) { wm8971_codec.modcnt++; if (get_user(val, (int *)arg)) return -EFAULT; switch (_IOC_NR(cmd)) { default: /* write a specific mixer */ i = _IOC_NR(cmd); //if (!supported_mixer(&wm8971_codec, i)) // return -EINVAL; return wm8971_set_mixer(i, val); } } return -EINVAL;} /* ** NOT TESTED ** */ static int wm8971_get_mixer(int cmd){ int val = 0; u16 r = 0,l = 0; switch (cmd) { case SOUND_MIXER_VOLUME: /* OUT1 Volume */ l = wm8971_read_reg_cache(WM8971_LOUT1V) & 0x7f; r = wm8971_read_reg_cache(WM8971_ROUT1V) & 0x7f; break; case SOUND_MIXER_BASS: /* bass */ l = wm8971_read_reg_cache(WM8971_BASS) & 0x0f; break; case SOUND_MIXER_TREBLE: /* treble */ l = wm8971_read_reg_cache(WM8971_TREBLE) & 0x0f; break; case SOUND_MIXER_SYNTH: break; case SOUND_MIXER_PCM: break; case SOUND_MIXER_SPEAKER: /* OUT2 Volume */ l = wm8971_read_reg_cache(WM8971_LOUT2V) & 0x7f; r = wm8971_read_reg_cache(WM8971_ROUT2V) & 0x7f; break; case SOUND_MIXER_LINE: break; case SOUND_MIXER_MIC: //l = wm8971_read_reg_cache(WM8971_INCTL1) & 0x060; //r = wm8971_read_reg_cache(WM8971_INCTL1) & 0x180; break; case SOUND_MIXER_CD: break; case SOUND_MIXER_IMIX: /* Recording monitor */ break; case SOUND_MIXER_ALTPCM: break; case SOUND_MIXER_RECLEV: /* Recording level */ break; case SOUND_MIXER_IGAIN: /* Input gain */ l = wm8971_read_reg_cache(WM8971_LADC) & 0xff; r = wm8971_read_reg_cache(WM8971_RADC) & 0xff; break; case SOUND_MIXER_OGAIN: /* Output gain */ l = wm8971_read_reg_cache(WM8971_LDAC) & 0xff; r = wm8971_read_reg_cache(WM8971_RDAC) & 0xff; break; default: warn("unknown mixer IOCTL"); return -EINVAL; } /* mix left and right */ val = ((l << 8) & 0xff00) + (r & 0xff); return val;}/* ** NOT TESTED ** */static int wm8971_set_mixer(int cmd, int val){ int ret = 0; u16 reg; unsigned int left,right; /* separate left and right settings */ right = ((val >> 8) & 0xff) ; left = (val & 0xff) ; if (right > 100) right = 100; if (left > 100) left = 100; switch (cmd) { case SOUND_MIXER_VOLUME: /* volume OUT1 */ reg = wm8971_read_reg_cache(WM8971_LOUT1V) & 0x180; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUT1V, reg | left); reg = wm8971_read_reg_cache(WM8971_ROUT1V) & 0x180; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUT1V, reg | right); break; case SOUND_MIXER_BASS: /* bass */ reg = wm8971_read_reg_cache(WM8971_BASS) & 0x1f0; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_BASS, reg | (left & 0x0f)); break; case SOUND_MIXER_TREBLE: /* treble */ reg = wm8971_read_reg_cache(WM8971_TREBLE) & 0x1f0; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_TREBLE, reg | (left & 0x0f)); break; case SOUND_MIXER_SYNTH: break; case SOUND_MIXER_PCM: break; case SOUND_MIXER_SPEAKER: /* volume OUT2 */ reg = wm8971_read_reg_cache(WM8971_LOUT2V) & 0x180; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LOUT2V, reg | left); reg = wm8971_read_reg_cache(WM8971_ROUT1V) & 0x180; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_ROUT2V, reg | right); break; case SOUND_MIXER_LINE: break; case SOUND_MIXER_MIC: break; case SOUND_MIXER_CD: break; case SOUND_MIXER_IMIX: /* Recording monitor */ break; case SOUND_MIXER_ALTPCM: break; case SOUND_MIXER_RECLEV: /* Recording level */ break; case SOUND_MIXER_IGAIN: /* Input gain LR ADC */ reg = wm8971_read_reg_cache(WM8971_LADC) & 0x100; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LADC, reg | left); reg = wm8971_read_reg_cache(WM8971_RADC) & 0x100; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RADC, reg | right); break; case SOUND_MIXER_OGAIN: /* Output gain LR DAC*/ reg = wm8971_read_reg_cache(WM8971_LDAC) & 0x100; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_LDAC, reg | left); reg = wm8971_read_reg_cache(WM8971_RDAC) & 0x100; wm8971_2w_write(wm8971_codec.wm8971_2w_client, WM8971_RDAC, reg | right); break; default: warn("unknown mixer IOCTL"); ret = -EINVAL; break; } return ret;}static struct file_operations wm8971_mixer_fops = { ioctl: wm8971_mixer_ioctl, llseek: no_llseek, owner: THIS_MODULE};#endifstatic struct file_operations wm8971_pcm_fops = { open: wm8971_pcm_open, owner: THIS_MODULE};/* WM8971 2 Wire layer */
static int __init pxa_wm8971_init(void){ int ret; char proc_str[64]; printk("Wolfson WM8971 Audio Codec\n"); printk("Victor add audio driver\n", WM8971_VERSION); /* get Bulverde I2C adapter */ if ((ret = i2c_add_driver(&wm8971_driver)) != 0) { err("can't add i2c driver"); goto out; } /* initialise WM8971 */ if ((ret = wm8971_init()) != 0) { err("can't initialise WM8971\n"); goto out; } /* register audio interfaces with kernel */ wm8971_pcm.dev_dsp = register_sound_dsp(&wm8971_pcm_fops, -1); wm8971_mixer.dev_mixer = register_sound_mixer(&wm8971_mixer_fops, -1); #ifdef CONFIG_PROC_FS /* register proc interface */ sprintf(proc_str, "driver/%s", AUDIO_NAME); if ((wm8971_codec.ps = create_proc_read_entry (proc_str, 0, NULL, wm8971_read_proc, &wm8971_codec)) == 0) err("could not register proc interface /proc/%s", proc_str);#endif#ifdef CONFIG_PM /* register with power manager */ if ((wm8971_codec.pm = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, wm8971_pm_event)) == 0) err("could not register with power management");#endif#if defined (CONFIG_ARCH_MAINSTONE) /* enable USB on the go MUX so we can use SSPFRM2 */ MST_MSCWR2 |= (1 << 5); MST_MSCWR2 &= ~(1 << 6); MST_MSCWR2 &= ~(1 << 2);#endif return 0; out: return ret;}/* * unregister interfaces and clean up */static void __exit pxa_wm8971_exit(void){#if defined (CONFIG_ARCH_MAINSTONE) /* disable USB on the go MUX so we can use ttyS0 */ MST_MSCWR2 &= ~(1 << 5); MST_MSCWR2 |= (1 << 6); MST_MSCWR2 |= (1 << 2);#endif #ifdef CONFIG_PM pm_unregister (wm8971_codec.pm);#endif wm8971_power_down(); //unregister_sound_mixer(wm8971_mixer.dev_mixer); wm8971_detach(wm8971_codec.wm8971_2w_client); i2c_del_driver(&wm8971_driver); ssp_exit(&wm8971_codec.ssp);}module_init(pxa_wm8971_init);module_exit(pxa_wm8971_exit);MODULE_DESCRIPTION("WM8971 driver");MODULE_AUTHOR("foxt");MODULE_LICENSE("GPL");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -