static inline void aic33_configure() { DPRINTK(" CONFIGURING AIC33\n"); /* Page select register */ audio_aic33_write(REGISTER_ADDR0, 0x0); /* audio_aic33_write(REGISTER_ADDR38, 0x10); */ davinci_set_mono_stereo(aic33_local.nochan); #ifdef AIC33_MASTER /* Enable bit and word clock as Master mode, 3-d disabled */ audio_aic33_write(REGISTER_ADDR8, 0xc0 /*0xc4 */ ); #endif aic33_update(SET_LINE, aic33_local.line); aic33_update(SET_VOLUME, aic33_local.volume); aic33_update(SET_RECSRC, aic33_local.recsrc); aic33_update(SET_IGAIN, aic33_local.igain); aic33_update(SET_OGAIN, aic33_local.ogain); aic33_update(SET_MICBIAS, aic33_local.micbias); }
int davinci_set_samplerate(long sample_rate) { u8 count = 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) { DPRINTK("Invalid Sample Rate %d requested\n", (int)sample_rate); return -EPERM; } /* CODEC DATAPATH SETUP */ /* Fsref to 48kHz, dual rate mode upto 96kHz */ if (reg_info[count].Fsref == 96000) audio_aic33_write(7, FS_REF_DEFAULT_48 | ADC_DUAL_RATE_MODE | DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 44.1kHz, dual rate mode upto 88.2kHz */ else if (reg_info[count].Fsref == 88200) audio_aic33_write(7, FS_REF_44_1 | ADC_DUAL_RATE_MODE | DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 48kHz */ else if (reg_info[count].Fsref == 48000) audio_aic33_write(7, FS_REF_DEFAULT_48 | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 44.1kHz */ else if (reg_info[count].Fsref == 44100) audio_aic33_write(7, FS_REF_44_1 | LDAC_LCHAN | RDAC_RCHAN); /* Codec sample rate select */ audio_aic33_write(2, reg_info[count].data); /* If PLL is to be used for generation of Fsref Generate the Fsref using the PLL */ #if(MCLK==33) if ((reg_info[count].Fsref == 96000) | (reg_info[count].Fsref == 48000)) { /* For MCLK = 33.8688 MHz and to get Fsref = 48kHz Fsref = (MCLK * k * R)/(2048 * p); Select P = 2, R= 1, K = 5.8049, which results in J = 5, D = 8049 */ /*Enable the PLL | Q-value | P-value */ audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02); audio_aic33_write(4, 0x14); /* J-value */ audio_aic33_write(5, 0x7D); /* D-value 8-MSB's */ audio_aic33_write(6, 0x04); /* D-value 6-LSB's */ } else if ((reg_info[count].Fsref == 88200) | (reg_info[count].Fsref == 44100)) { /* MCLK = 33.8688 MHz and to get Fsref = 44.1kHz Fsref = (MCLK * k * R)/(2048 * p); Select P = 2, R =1, K = 5.3333, which results in J = 5, D = 3333 */ /*Enable the PLL | Q-value | P-value */ audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02); audio_aic33_write(4, 0x14); /* J-value */ audio_aic33_write(5, 0x34); /* D-value 8-MSB's */ audio_aic33_write(6, 0x14); /* D-value 6-LSB's */ } #elif(MCLK==22) if ((reg_info[count].Fsref == 96000) | (reg_info[count].Fsref == 48000)) { /* For MCLK = 22.5792 MHz and to get Fsref = 48kHz Fsref = (MCLK * k * R)/(2048 * p); Select P = 2, R= 1, K = 8.7075, which results in J = 8, D = 7075 */ /*Enable the PLL | Q-value | P-value */ audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02); audio_aic33_write(4, (8 << 2)); /* J-value */ audio_aic33_write(5, (unsigned char)(7075 >> 6)); /* D-value 8-MSB's */ audio_aic33_write(6, (unsigned char)(7075 << 2)); /* D-value 6-LSB's */ }
static int aic33_update(int flag, int val) { u16 volume; s16 left_gain, left_val, right_gain, right_val; switch (flag) { case SET_VOLUME: /* Ignore separate left/right channel for now, even the codec does support it. */ val &= 0xff; if (val < 0 || val > 100) { DPRINTK("Trying a bad volume value(%d)!\n", val); return -EPERM; } // Convert 0 -> 100 volume to 0x77 (LHV_MIN) -> 0x00 (LHV_MAX) volume = ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN; aic33_local.volume_reg = OUTPUT_VOLUME_MAX - volume; if (aic33_local.nochan == STEREO) { audio_aic33_write(47, LOPM_ON | aic33_local.volume_reg); audio_aic33_write(64, LOPM_ON | aic33_local.volume_reg); audio_aic33_write(82, LOPM_ON | aic33_local.volume_reg); audio_aic33_write(92, LOPM_ON | aic33_local.volume_reg); } else if (aic33_local.nochan == MONO) { #ifdef CONFIG_MONOSTEREO_DIFFJACK /* DACL1 to MONO_LOP/M routing and volume control */ audio_aic33_write(75, LOPM_ON | aic33_local.volume_reg); /* DACR1 to MONO_LOP/M routing and volume control */ audio_aic33_write(78, LOPM_ON | aic33_local.volume_reg); #else audio_aic33_write(47, LOPM_ON | aic33_local.volume_reg); audio_aic33_write(64, LOPM_ON | aic33_local.volume_reg); audio_aic33_write(82, LOPM_ON | aic33_local.volume_reg); audio_aic33_write(92, LOPM_ON | aic33_local.volume_reg); #endif } break; case SET_LINE: case SET_MIC: /* Ignore separate left/right channel for now, even the codec does support it. */ val &= 0xff; if (val < 0 || val > 100) { DPRINTK("Trying a bad volume value(%d)!\n", val); return -EPERM; } volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN; aic33_local.input_volume_reg = volume; audio_aic33_write(15, aic33_local.input_volume_reg); audio_aic33_write(16, aic33_local.input_volume_reg); break; case SET_RECSRC: /* Ignore separate left/right channel for now, even the codec does support it. */ val &= 0xff; if (hweight32(val) > 1) val &= ~aic33_local.recsrc; if (val == SOUND_MASK_MIC) { /* enable the mic input*/ DPRINTK("Enabling mic\n"); audio_aic33_write(17, 0x0); audio_aic33_write(18, 0x0); /* enable ADC's and disable the line input*/ audio_aic33_write(19, 0x7C); audio_aic33_write(22, 0x7C); } else if (val == SOUND_MASK_LINE) { /* enable ADC's, enable line iput */ DPRINTK(" Enabling line in\n"); audio_aic33_write(19, 0x4); audio_aic33_write(22, 0x4); /* disable the mic input */ audio_aic33_write(17, 0xff); audio_aic33_write(18, 0xff); } else { /* do nothing */ } aic33_local.recsrc = val; break; case SET_IGAIN: left_val = val & 0xFF; right_val = val >> 8; if (left_val < 0 || left_val > 100) { DPRINTK("Trying a bad igain value(%d)!\n", left_val); return -EPERM; } if (right_val < 0 || right_val > 100) { DPRINTK("Trying a bad igain value(%d)!\n", right_val); return -EPERM; } left_gain = ((left_val * INPUT_GAIN_RANGE) / 100) + INPUT_GAIN_MIN; right_gain = ((right_val * INPUT_GAIN_RANGE) / 100) + INPUT_GAIN_MIN; DPRINTK("left gain reg val = 0x%x", left_gain << 1); DPRINTK("right gain reg val = 0x%x", left_gain << 1); /* Left AGC control */ audio_aic33_write(26, 0x80); audio_aic33_write(27, left_gain << 1); audio_aic33_write(28, 0x0); /* Right AGC control */ audio_aic33_write(29, 0x80); audio_aic33_write(30, right_gain << 1); audio_aic33_write(31, 0x0); break; case SET_OGAIN: left_val = val & 0xFF; right_val = val >> 8; if (left_val < 0 || left_val > 100) { DPRINTK("Trying a bad igain value(%d)!\n", left_val); return -EPERM; } if (right_val < 0 || right_val > 100) { DPRINTK("Trying a bad igain value(%d)!\n", right_val); return -EPERM; } left_gain = ((left_val * OUTPUT_GAIN_RANGE) / 100) + OUTPUT_GAIN_MIN; left_gain = OUTPUT_GAIN_MAX - left_gain; right_gain = ((right_val * OUTPUT_GAIN_RANGE) / 100) + OUTPUT_GAIN_MIN; right_gain = OUTPUT_GAIN_MAX - right_gain; /* Left/Right DAC digital volume gain */ audio_aic33_write(43, left_gain); audio_aic33_write(44, right_gain); break; case SET_MICBIAS: /* Ignore separate left/right channel for now, even the codec does support it. */ val &= 0xff; if (val < 0 || val > 3) { DPRINTK ("Request for non supported mic bias level(%d)!\n", val); return -EPERM; } if (val == 0) audio_aic33_write(25, 0x00); else if (val == 1) audio_aic33_write(25, MICBIAS_OUTPUT_2_0V); else if (val == 2) audio_aic33_write(25, MICBIAS_OUTPUT_2_5V); else if (val == 3) audio_aic33_write(25, MICBIAS_OUTPUT_AVDD); break; case SET_BASS: break; case SET_TREBLE: break; } return 0; }
static void davinci_set_mono_stereo(int mode) { if (mode == MONO) { #ifdef CONFIG_MONOSTEREO_DIFFJACK /* MONO_LOP/M Output level control register */ audio_aic33_write(REGISTER_ADDR79, 0x99); #else /* Driver power ON pop control */ audio_aic33_write(REGISTER_ADDR42, 0x6C); /* HPLOUT/HPROUT output level control */ audio_aic33_write(REGISTER_ADDR51, 0x99); audio_aic33_write(REGISTER_ADDR65, 0x99); /* LEFT_LOP/M, RIGHT_LOP/M output level control */ audio_aic33_write(REGISTER_ADDR86, 0x99); audio_aic33_write(REGISTER_ADDR93, 0x99); #endif /* Left DAC power up, Right DAC power down */ audio_aic33_write(REGISTER_ADDR37, 0xa0); } else if (mode == STEREO) { /* Driver power ON pop control */ audio_aic33_write(REGISTER_ADDR42, 0x6C); /* HPLOUT/HPROUT output level control */ audio_aic33_write(REGISTER_ADDR51, 0x99); audio_aic33_write(REGISTER_ADDR65, 0x99); /* LEFT_LOP/M, RIGHT_LOP/M output level control */ audio_aic33_write(REGISTER_ADDR86, 0x99); audio_aic33_write(REGISTER_ADDR93, 0x99); /* Left/Right DAC power up */ audio_aic33_write(REGISTER_ADDR37, 0xe0); } else DPRINTK(" REQUEST FOR INVALID MODE\n"); }
int davinci_set_samplerate(long sample_rate) { u8 count = 0; u8 j_val = 0; u16 d_val = 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) { DPRINTK("Invalid Sample Rate %d requested\n", (int)sample_rate); return -EPERM; } /* CODEC DATAPATH SETUP */ /* Fsref to 48kHz, dual rate mode upto 96kHz */ if (reg_info[count].Fsref == 96000) audio_aic33_write(REGISTER_ADDR7, FS_REF_DEFAULT_48 | ADC_DUAL_RATE_MODE | DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 44.1kHz, dual rate mode upto 88.2kHz */ else if (reg_info[count].Fsref == 88200) audio_aic33_write(REGISTER_ADDR7, FS_REF_44_1 | ADC_DUAL_RATE_MODE | DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 48kHz */ else if (reg_info[count].Fsref == 48000) audio_aic33_write(REGISTER_ADDR7, FS_REF_DEFAULT_48 | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 44.1kHz */ else if (reg_info[count].Fsref == 44100) audio_aic33_write(REGISTER_ADDR7, FS_REF_44_1 | LDAC_LCHAN | RDAC_RCHAN); /* Codec sample rate select */ audio_aic33_write(REGISTER_ADDR2, reg_info[count].data); /* If PLL is to be used for generation of Fsref Generate the Fsref using the PLL */ /*Enable the PLL | Q-value | P-value */ audio_aic33_write(REGISTER_ADDR3, PLL_ENABLE | 0x10 | 0x02); if ((reg_info[count].Fsref == 96000) || (reg_info[count].Fsref == 48000)) { /* * For MCLK = 22.5792 MHz and to get Fsref = 48kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R= 1, K = 8.7075, which results in J = 8, * D = 7075 * * For MCLK = 27 MHz and to get Fsref = 48kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R= 1, K = 7.2818, which results in J = 7, * D = 2818 * * For MCLK = 33.8688 MHz and to get Fsref = 48kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R= 1, K = 5.8049, which results in J = 5, * D = 8049 */ switch (aic33_mclk) { case MCLK_22: j_val = 8; d_val = 7075; break; case MCLK_27: j_val = 7; d_val = 2818; break; case MCLK_33: j_val = 5; d_val = 8049; break; default: printk(KERN_ERR "unknown audio codec frequency \n"); } } else if ((reg_info[count].Fsref == 88200) || (reg_info[count].Fsref == 44100)) { /* * MCLK = 22.5792 MHz and to get Fsref = 44.1kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R =1, K = 8.0000, which results in J = 8, * D = 0000 * * MCLK = 27 MHz and to get Fsref = 44.1kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R =1, K = 6.6901, which results in J = 6, * D = 6901 * * MCLK = 33.8688 MHz and to get Fsref = 44.1kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R =1, K = 5.3333, which results in J = 5, * D = 3333 */ switch (aic33_mclk) { case MCLK_22: j_val = 8; d_val = 0; break; case MCLK_27: j_val = 6; d_val = 6901; break; case MCLK_33: j_val = 5; d_val = 3333; break; default: printk(KERN_ERR "unknown audio codec frequency \n"); } } /* J-value */ audio_aic33_write(REGISTER_ADDR4, j_val << 2); /* D-value 8-MSB's */ audio_aic33_write(REGISTER_ADDR5, (unsigned char)(d_val >> 6)); /* D-value 6-LSB's */ audio_aic33_write(REGISTER_ADDR6, (unsigned char)(d_val << 2)); audio_samplerate = sample_rate; #ifndef AIC33_MASTER { int clkgdv = 0; unsigned long clkval = 0; struct clk *mbspclk; /* Set Sample Rate at McBSP Formula : Codec System Clock = Input clock to McBSP; clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1); FWID = BitsPerSample - 1; FPER = (BitsPerSample * 2) - 1; */ mbspclk = davinci_mcbsp_get_clock(); if (mbspclk == NULL) { DPRINTK(" Failed to get internal clock to MCBSP"); return -EPERM; } clkval = clk_get_rate(mbspclk); DPRINTK("mcbsp_clk = %ld\n", clkval); if (clkval) clkgdv = (clkval / (sample_rate * DEFAULT_BITPERSAMPLE * 2)) - 1; else { DPRINTK(" Failed to get the MCBSP clock\n"); return -EPERM; } DPRINTK("clkgdv = %d\n", clkgdv); if (clkgdv > 255 || clkgdv < 0) { /* For requested sampling rate, the input clock to MCBSP cant be devided down to get the in range clock divider value for 16 bits sample */ DPRINTK("Invalid Sample Rate %d requested\n", (int)sample_rate); return -EPERM; } initial_config.srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); initial_config.srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)); davinci_mcbsp_stop_tx(AUDIO_MCBSP); davinci_mcbsp_stop_rx(AUDIO_MCBSP); davinci_mcbsp_config(AUDIO_MCBSP, &initial_config); } #endif /* AIC33_MASTER */ return 0; }