📄 omap-audio-tsc2101.c
字号:
* ********************************************************************************/static int mixer_release(struct inode *inode, struct file *file){ /* Any mixer specific Un-initialization */ omap_tsc2101_disable(); return 0;}/********************************************************************************* * * mixer_ioctl() * ********************************************************************************/static intmixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg){ int val; int gain; int ret = 0; int nr = _IOC_NR(cmd); /* * We only accept mixer (type 'M') ioctls. */ FN_IN; if (_IOC_TYPE(cmd) != 'M') return -EINVAL; DPRINTK(" 0x%08x\n", cmd); if (cmd == SOUND_MIXER_INFO) { struct mixer_info mi; strncpy(mi.id, "TSC2101", sizeof(mi.id)); strncpy(mi.name, "TI TSC2101", sizeof(mi.name)); mi.modify_counter = tsc2101_local.mod_cnt; FN_OUT(1); return copy_to_user((void *)arg, &mi, sizeof(mi)); } if (_IOC_DIR(cmd) & _IOC_WRITE) { ret = get_user(val, (int *)arg); if (ret) goto out; /* Ignore separate left/right channel for now, * even the codec does support it. */ gain = val & 255; switch (nr) { case SOUND_MIXER_VOLUME: tsc2101_local.volume = val; tsc2101_local.mod_cnt++; ret = tsc2101_update(SET_VOLUME, gain); break; case SOUND_MIXER_LINE: tsc2101_local.line = val; tsc2101_local.mod_cnt++; ret = tsc2101_update(SET_LINE, gain); break; case SOUND_MIXER_MIC: tsc2101_local.mic = val; tsc2101_local.mod_cnt++; ret = tsc2101_update(SET_LINE, gain); break; case SOUND_MIXER_RECSRC: break; default: ret = -EINVAL; } } if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) { ret = 0; switch (nr) { case SOUND_MIXER_VOLUME: val = tsc2101_local.volume; break; case SOUND_MIXER_LINE: val = tsc2101_local.line; break; case SOUND_MIXER_MIC: val = tsc2101_local.mic; break; case SOUND_MIXER_RECSRC: val = REC_MASK; break; case SOUND_MIXER_RECMASK: val = REC_MASK; break; case SOUND_MIXER_DEVMASK: val = DEV_MASK; break; case SOUND_MIXER_CAPS: val = 0; break; case SOUND_MIXER_STEREODEVS: val = 0; break; default: val = 0; ret = -EINVAL; break; } if (ret == 0) ret = put_user(val, (int *)arg); } out: FN_OUT(0); return ret;}/********************************************************************************* * * omap_set_samplerate() * ********************************************************************************/int omap_set_samplerate(long sample_rate){ u8 count = 0; u16 data = 0; /* wait for any frame to complete */ udelay(125); /* Search for the right sample rate */ while ((reg_info[count].sample_rate != sample_rate) && (count < NUMBER_SAMPLE_RATES_SUPPORTED)) { count++; } if (count == NUMBER_SAMPLE_RATES_SUPPORTED) { printk(KERN_ERR "Invalid Sample Rate %d requested\n", (int)sample_rate); return -EPERM; } /* Set AC1 */ data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1); /*Clear prev settings */ data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07)); data |= AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count]. divisor); audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data); /* Set the AC3 */ data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3); /*Clear prev settings */ data &= ~(AC3_REFFS | AC3_SLVMS); data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;#ifdef TSC_MASTER data |= AC3_SLVMS;#endif /* #ifdef TSC_MASTER */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data); /* program the PLLs */ if (reg_info[count].fs_44kHz) { /* 44.1 khz - 12 MHz Mclk */ audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */ audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */ } else { /* 48 khz - 12 Mhz Mclk */ audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */ audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */ } audio_samplerate = sample_rate; /* Call Mcbsp Sample rate function */ omap_mcbsp_set_rate(AUDIO_MCBSP, sample_rate, DEFAULT_BITPERSAMPLE); return 0;}/********************************************************************************* * * omap_tsc2101_initialize() [hw_init() ] * ********************************************************************************/static void omap_tsc2101_initialize(void *dummy){ DPRINTK("omap_tsc2101_initialize entry\n"); /* initialize with default sample rate */ audio_samplerate = AUDIO_RATE_DEFAULT; omap_mcbsp_begin(AUDIO_MCBSP); omap_tsc2101_enable(); tsc2101_configure();#ifdef TEST_KEYCLICK tsc2101_testkeyclick();#endif#ifdef TONE_GEN toneGen();#endif DPRINTK("omap_tsc2101_initialize exit\n");}/********************************************************************************* * * omap_tsc2101_shutdown() [hw_shutdown() ] * ********************************************************************************/static void omap_tsc2101_shutdown(void *dummy){ /* Turn off codec after it is done. Can't do it immediately, since it may still have buffered data. Wait 20ms (arbitrary value) and then turn it off. */ FN_IN; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(2); omap_mcbsp_end(AUDIO_MCBSP); audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC)); omap_tsc2101_disable(); FN_OUT(0);}/********************************************************************************* * * tsc2101_configure * ********************************************************************************/static inline void tsc2101_configure(){ FN_IN; audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000); /*Headset Input not muted */ /*AGC for Headset In off */ audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL, HGC_ADPGA_HED(0x7D)); /*Mute Analog Sidetone */ /*Select MIC_INHED input for headset */ /*Cell Phone In not connected */ audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC); /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */ /* 1dB AGC hysteresis */ /* MICes bias 2V */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0)); /* Set codec output volume */ audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000); /* DAC left and right routed to SPK2 */ /* SPK1/2 unmuted */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_5, AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 | AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 | AC5_HDSCPTC); /* OUT8P/N muted, CPOUT muted */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_6, AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC | AC6_VGNDSCPTC); /* Headset/Hook switch detect disabled */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000); /* Initialize the AIC23 internal state */ /* The AIC23 uses 9 bits for register control. The extra bit gets placed in the LSB of the subregister address, and the address is shifted by one. the volume control is only for earphone not line out line input volume can be controlled but not in following code which pick the default value 0dB */ /* Left line input volume control */ tsc2101_local.line = DEFAULT_INPUT_VOLUME; tsc2101_local.mic = DEFAULT_INPUT_VOLUME; tsc2101_update(SET_LINE, DEFAULT_INPUT_VOLUME); /* Left/Right headphone channel volume control */ /* Zero-cross detect on */ tsc2101_local.volume = DEFAULT_VOLUME; tsc2101_update(SET_VOLUME, DEFAULT_VOLUME); /* clock configuration */ omap_set_samplerate(audio_samplerate);#ifdef TSC_DUMP_REGISTERS tsc2101_dumpRegisters();#endif FN_OUT(0);}#ifdef PROC_SUPPORTstatic void tsc2101_start(){ FN_IN; audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000); /*Headset Input not muted */ /*AGC for Headset In off */ audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL, HGC_ADPGA_HED(0x7D)); /*Mute Analog Sidetone */ /*Select MIC_INHED input for headset */ /*Cell Phone In not connected */ audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC); /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */ /* 1dB AGC hysteresis */ /* MICes bias 2V */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0)); /* Set codec output volume */ audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000); /* DAC left and right routed to SPK2 */ /* SPK1/2 unmuted */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_5, AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 | AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 | AC5_HDSCPTC); /* OUT8P/N muted, CPOUT muted */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_6, AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC | AC6_VGNDSCPTC); /* Headset/Hook switch detect disabled */ audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000); /* Initialize the AIC23 internal state */ /* The AIC23 uses 9 bits for register control. The extra bit gets placed in the LSB of the subregister address, and the address is shifted by one. the volume control is only for earphone not line out line input volume can be controlled but not in following code which pick the default value 0dB */ /* Left line input volume control */ tsc2101_local.line = DEFAULT_INPUT_VOLUME; tsc2101_local.mic = DEFAULT_INPUT_VOLUME; tsc2101_update(SET_LINE, DEFAULT_INPUT_VOLUME); /* Left/Right headphone channel volume control */ /* Zero-cross detect on */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -