📄 codec.c
字号:
codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, 0x0000); codsp_set_slic(duslic_id, channel, SS_RING_PAUSE); /* Start Ringing */ /* select source for the levelmeter to be IO4-IO3 */ codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, LMCR2_LM_SEL_IO4_MINUS_IO3); udelay(40000); /* Before Enabling Level Meter Programm the apropriate shift factor K_INTDC=(4 if Rectifier Enabled and 2 if Rectifier Disabled) */ codsp_write_cop_char(duslic_id, channel, RING_PARAMS_START_ADDR + 7, K_INTDC_RECT_OFF); udelay(10000); /* Enable LevelMeter to Integrate only once (Rectifier Disabled) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); udelay(40000); /* Integration Period == Ring Period = 40ms (for 25Hz Ring) */ if (wait_level_metering_finish(duslic_id, channel)) { udelay(10000); /* To be sure that Integration Results are Valid wait at least 500us !!! */ /* Now Read the LM Result Registers (Will be valid until LM_EN becomes zero again( after that the Result is updated every 500us) ) */ Offset_Compensation = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); Offset_Compensation = (-1) * ((Offset_Compensation * (1 << K_INTDC_RECT_OFF)) / N_SAMPLES); /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_ONCE); /* Now programm Integrator Offset Registers !!! */ codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, Offset_Compensation); codsp_set_slic(duslic_id, channel, SS_RINGING); /* Start Ringing */ udelay(40000); /* Reenable Level Meter Integrator (The Result will be valid after Integration Period=Ring Period and until LN_EN become zero again) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); udelay(40000); /* Integration Period == Ring Period = 40ms (for 25Hz Ring) */ /* Poll the LM_OK bit to see when Integration Result is Ready */ if (wait_level_metering_finish(duslic_id, channel)) { udelay(10000); /* wait at least 500us to be sure that the Integration Result are valid !!! */ /* Now Read the LM Result Registers (They will hold their value until LM_EN become zero again */ /* ==>After that Result Regs will be updated every 500us !!!) */ LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); V_in = (-1) * ( ( (((long int)LM_Result) * V_AD_x10000) / N_SAMPLES) >> (15 - K_INTDC_RECT_OFF)) ; /* Vin x 10000*/ V_out = (V_in * Divider_Ratio) / 10000L ; /* Vout x100 */ if (V_out < 0) V_out= -V_out; if (V_out > MAX_V_RING_MEANx100) err_mask |= 8; *ring_mean_v = V_out; } else { err_mask |= 8; *ring_mean_v = 0; } } else { err_mask |= 8; *ring_mean_v = 0; } /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_ONCE); codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, 0x0000); codsp_set_slic(duslic_id, channel, SS_RING_PAUSE); /* Start Ringing */ /* Now Enable Rectifier */ /* select source for the levelmeter to be IO4-IO3 */ codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, LMCR2_LM_SEL_IO4_MINUS_IO3 | LMCR2_LM_RECT); /* Program the apropriate shift factor K_INTDC (in order to avoid Overflow at Integtation Result !!!) */ codsp_write_cop_char(duslic_id, channel, RING_PARAMS_START_ADDR + 7, K_INTDC_RECT_ON); udelay(40000); /* Reenable Level Meter Integrator (The Result will be valid after Integration Period=Ring Period and until LN_EN become zero again) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); udelay(40000); /* Poll the LM_OK bit to see when Integration Result is Ready */ if (wait_level_metering_finish(duslic_id, channel)) { udelay(10000); /* Now Read the LM Result Registers (They will hold their value until LM_EN become zero again */ /* ==>After that Result Regs will be updated every 500us !!!) */ Offset_Compensation = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); Offset_Compensation = (-1) * ((Offset_Compensation * (1 << K_INTDC_RECT_ON)) / N_SAMPLES); /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_ONCE); /* Now programm Integrator Offset Registers !!! */ codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, Offset_Compensation); /* Be sure that a Ring is generated !!!! */ codsp_set_slic(duslic_id, channel, SS_RINGING); /* Start Ringing again */ udelay(40000); /* Reenable Level Meter Integrator (The Result will be valid after Integration Period=Ring Period and until LN_EN become zero again) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); udelay(40000); /* Poll the LM_OK bit to see when Integration Result is Ready */ if (wait_level_metering_finish(duslic_id, channel)) { udelay(10000); /* Now Read the LM Result Registers (They will hold their value until LM_EN become zero again */ /* ==>After that Result Regs will be updated every 500us !!!) */ LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); V_in = (-1) * ( ( (((long int)LM_Result) * V_AD_x10000) / N_SAMPLES) >> (15 - K_INTDC_RECT_ON) ) ; /* Vin x 10000*/ V_out = (((V_in * Divider_Ratio) / 10000L) * RMS_MULTIPLIERx100) / 100 ; /* Vout_RMS x100 */ if (V_out < 0) V_out = -V_out; Vout_diff = (V_out - TARGET_V_RING_RMSx100); if (Vout_diff < 0) Vout_diff = -Vout_diff; if (Vout_diff > V_RMS_RING_MAX_DIFFx100) err_mask |= 16; *ring_rms_v = V_out; } else { err_mask |= 16; *ring_rms_v = 0; } } else { err_mask |= 16; *ring_rms_v = 0; } /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK); retrieve_slic_state(slic_id); return(err_mask);}int test_dtmf(int slic_id){ unsigned char code; unsigned char b; unsigned int intreg; int duslic_id = slic_id >> 1; int channel = slic_id & 1; for (code = 0; code < 16; code++) { b = codsp_read_sop_char(duslic_id, channel, DSCR_ADDR); codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, (b & ~(DSCR_PTG | DSCR_DG_KEY(15))) | DSCR_DG_KEY(code) | DSCR_TG1_EN | DSCR_TG2_EN); udelay(80000); intreg = codsp_read_sop_int(duslic_id, channel, INTREG1_ADDR); if ((intreg & CODSP_INTREG_INT_CH) == 0) break; if ((intreg & CODSP_INTREG_DTMF_OK) == 0 || codsp_dtmf_map[(intreg >> 10) & 15] != codsp_dtmf_map[code]) break; b = codsp_read_sop_char(duslic_id, channel, DSCR_ADDR); codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, b & ~(DSCR_COR8 | DSCR_TG1_EN | DSCR_TG2_EN)); udelay(80000); intreg = codsp_read_sop_int(duslic_id, channel, INTREG1_ADDR); /* for dtmf_pause irq */ } if (code != 16) { b = codsp_read_sop_char(duslic_id, channel, DSCR_ADDR); /* stop dtmf */ codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, b & ~(DSCR_COR8 | DSCR_TG1_EN | DSCR_TG2_EN)); return(1); } return(0);}void data_up_persist_time(int duslic_id, int channel, int time_ms){ unsigned char b; b = codsp_read_sop_char(duslic_id, channel, IOCTL3_ADDR); b = (b & 0x0F) | ((time_ms & 0x0F) << 4); codsp_write_sop_char(duslic_id, channel, IOCTL3_ADDR, b);}static void program_dtmf_params(int duslic_id, int channel){ unsigned char b; codsp_write_pop_char(duslic_id, channel, DTMF_LEV_ADDR, 0x10); codsp_write_pop_char(duslic_id, channel, DTMF_TWI_ADDR, 0x0C); codsp_write_pop_char(duslic_id, channel, DTMF_NCF_H_ADDR, 0x79); codsp_write_pop_char(duslic_id, channel, DTMF_NCF_L_ADDR, 0x10); codsp_write_pop_char(duslic_id, channel, DTMF_NBW_H_ADDR, 0x02); codsp_write_pop_char(duslic_id, channel, DTMF_NBW_L_ADDR, 0xFB); codsp_write_pop_char(duslic_id, channel, DTMF_GAIN_ADDR, 0x91); codsp_write_pop_char(duslic_id, channel, DTMF_RES1_ADDR, 0x00); codsp_write_pop_char(duslic_id, channel, DTMF_RES2_ADDR, 0x00); codsp_write_pop_char(duslic_id, channel, DTMF_RES3_ADDR, 0x00); b = codsp_read_sop_char(duslic_id, channel, BCR5_ADDR); codsp_write_sop_char(duslic_id, channel, BCR5_ADDR, b | BCR5_DTMF_EN);}static void codsp_channel_full_reset(int duslic_id, int channel){ program_coeffs(duslic_id, channel, ac_coeffs, sizeof(ac_coeffs) / sizeof(struct _coeffs)); program_coeffs(duslic_id, channel, dc_coeffs, sizeof(dc_coeffs) / sizeof(struct _coeffs)); /* program basic configuration registers */ codsp_write_sop_char(duslic_id, channel, BCR1_ADDR, 0x01); codsp_write_sop_char(duslic_id, channel, BCR2_ADDR, 0x41); codsp_write_sop_char(duslic_id, channel, BCR3_ADDR, 0x43); codsp_write_sop_char(duslic_id, channel, BCR4_ADDR, 0x00); codsp_write_sop_char(duslic_id, channel, BCR5_ADDR, 0x00); codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, 0x04); /* PG */ program_dtmf_params(duslic_id, channel); codsp_write_sop_char(duslic_id, channel, LMCR3_ADDR, 0x40); /* RingTRip_SEL */ data_up_persist_time(duslic_id, channel, 4); codsp_write_sop_char(duslic_id, channel, MASK_ADDR, 0xFF); /* All interrupts masked */ codsp_set_slic(duslic_id, channel, SS_ACTIVE_HIGH);}static int codsp_chip_full_reset(int duslic_id){ int i, cnt; int intreg[NUM_CHANNELS]; unsigned char pcm_resync; unsigned char revision; codsp_reset_chip(duslic_id); udelay(2000); for (i = 0; i < NUM_CHANNELS; i++) intreg[i] = codsp_read_sop_int(duslic_id, i, INTREG1_ADDR); udelay(1500); if (_PORTC_GET(com_hook_mask_tab[duslic_id]) == 0) { printf("_HOOK(%d) stayed low\n", duslic_id); return -1; } for (pcm_resync = 0, i = 0; i < NUM_CHANNELS; i++) { if (intreg[i] & CODSP_INTREG_SYNC_FAIL) pcm_resync |= 1 << i; } for (cnt = 0; cnt < 5 && pcm_resync; cnt++) { for (i = 0; i < NUM_CHANNELS; i++) codsp_resync_channel(duslic_id, i); udelay(2000); pcm_resync = 0; for (i = 0; i < NUM_CHANNELS; i++) { if (codsp_read_sop_int(duslic_id, i, INTREG1_ADDR) & CODSP_INTREG_SYNC_FAIL) pcm_resync |= 1 << i; } } if (cnt == 5) { printf("PCM_Resync(%u) not completed\n", duslic_id); return -2; } revision = codsp_read_sop_char(duslic_id, 0, REVISION_ADDR); printf("DuSLIC#%d hardware version %d.%d\r\n", duslic_id, (revision & 0xF0) >> 4, revision & 0x0F); codsp_write_sop_char(duslic_id, 0, XCR_ADDR, 0x80); /* EDSP_EN */ for (i = 0; i < NUM_CHANNELS; i++) { codsp_write_sop_char(duslic_id, i, PCMC1_ADDR, 0x01); codsp_channel_full_reset(duslic_id, i); } return 0;}int slic_self_test(int duslic_mask){ int slic; int i; int r; long vdd, v_oh_H, v_oh_L, ring_mean_v, ring_rms_v; const char *err_txt[] = { "VDD", "V_OH_H", "V_OH_L", "V_RING_MEAN", "V_RING_RMS" }; int error = 0; for (slic = 0; slic < MAX_SLICS; slic++) { /* voltages self test */ if (duslic_mask & (1 << (slic >> 1))) { r = measure_on_hook_voltages(slic, &vdd, &v_oh_H, &v_oh_L, &ring_mean_v, &ring_rms_v); printf("SLIC %u measured voltages (x100):\n\t" "VDD = %ld\tV_OH_H = %ld\tV_OH_L = %ld\tV_RING_MEAN = %ld\tV_RING_RMS = %ld\n", slic, vdd, v_oh_H, v_oh_L, ring_mean_v, ring_rms_v); if (r != 0) error |= 1 << slic; for (i = 0; i < 5; i++) if (r & (1 << i)) printf("\t%s out of range\n", err_txt[i]); } } for (slic = 0; slic < MAX_SLICS; slic++) { /* voice path self test */ if (duslic_mask & (1 << (slic >> 1))) { printf("SLIC %u VOICE PATH...CHECKING", slic); printf("\rSLIC %u VOICE PATH...%s\n", slic, (r = test_dtmf(slic)) != 0 ? "FAILED " : "PASSED "); if (r != 0) error |= 1 << slic; } } return(error);}#if defined(CONFIG_NETTA_ISDN)#define SPIENS1 (1 << (31 - 15))#define SPIENS2 (1 << (31 - 19))static const int spiens_mask_tab[2] = { SPIENS1, SPIENS2 };int s_initialized = 0;static inline unsigned int s_transfer_internal(int s_id, unsigned int address, unsigned int value){ unsigned int rx, v; _PORTB_SET(spiens_mask_tab[s_id], 0); rx = __SPI_Transfer(address); switch (address & 0xF0) { case 0x60: /* write byte register */ case 0x70: rx = __SPI_Transfer(value); break; case 0xE0: /* read R6 register */ v = __SPI_Transfer(0); rx = (rx << 8) | v; break; case 0xF0: /* read byte register */ rx = __SPI_Transfer(0); break; } _PORTB_SET(spiens_mask_tab[s_id], 1); return rx;}static void s_write_BR(int s_id, unsigned int regno, unsigned int val){ unsigned int address; unsigned int v; address = 0x70 | (regno & 15); val &= 0xff; v = s_transfer_internal(s_id, address, val);}static void s_write_OR(int s_id, unsigned int regno, unsigned int val){ unsigned int address; unsigned int v; address = 0x70 | (regno & 15); val &= 0xff; v = s_transfer_internal(s_id, address, val);}static void s_write_NR(int s_id, unsigned int regno, unsigned int val){ unsigned int address; unsigned int v; address = (regno & 7) << 4; val &= 0xf; v = s_transfer_internal(s_id, address | val, 0x00);}#define BR7_IFR 0x08 /* IDL2 free run */#define BR7_ICSLSB 0x04 /* IDL2 clock speed LSB */#define BR15_OVRL_REG_EN 0x80#define OR7_D3VR 0x80 /* disable 3V regulator */#define OR8_TEME 0x10 /* TE mode enable */#define OR8_MME 0x08 /* master mode enable */void s_initialize(void){ int s_id; for (s_id = 0; s_id < 2; s_id++) { s_write_BR(s_id, 7, BR7_IFR | BR7_ICSLSB); s_write_BR(s_id, 15, BR15_OVRL_REG_EN); s_write_OR(s_id, 8, OR8_TEME | OR8_MME); s_write_OR(s_id, 7, OR7_D3VR); s_write_OR(s_id, 6, 0); s_write_BR(s_id, 15, 0); s_write_NR(s_id, 3, 0); }}#endifint board_post_codec(int flags){ int j; int r; int duslic_mask; printf("board_post_dsp\n");#if defined(CONFIG_NETTA_ISDN) if (s_initialized == 0) { s_initialize(); s_initialized = 1; printf("s_initialized\n"); udelay(20000); }#endif duslic_mask = 0; for (j = 0; j < MAX_DUSLIC; j++) { if (codsp_chip_full_reset(j) < 0) printf("Error initializing DuSLIC#%d\n", j); else duslic_mask |= 1 << j; } if (duslic_mask != 0) { printf("Testing SLICs...\n"); r = slic_self_test(duslic_mask); for (j = 0; j < MAX_SLICS; j++) { if (duslic_mask & (1 << (j >> 1))) printf("SLIC %u...%s\n", j, r & (1 << j) ? "FAULTY" : "OK"); } } printf("DuSLIC self test finished\n"); return 0; /* return -1 on error */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -