📄 ixj.c
字号:
case PORT_HANDSET: if (j->cardtype != QTI_PHONEJACK) { return 5; } else { j->gpio.bytes.high = 0x0B; j->gpio.bits.gpio6 = 1; j->gpio.bits.gpio7 = 0; ixj_WriteDSPCommand(j->gpio.word, j); j->port = PORT_HANDSET; } break; default: return 6; break; } return 0;}static int ixj_set_pots(IXJ *j, int arg){ if (j->cardtype == QTI_LINEJACK) { if (arg) { if (j->port == PORT_PSTN) { j->pld_slicw.bits.rly1 = 0; outb(j->pld_slicw.byte, j->XILINXbase + 0x01); j->flags.pots_pstn = 1; return 1; } else { j->flags.pots_pstn = 0; return 0; } } else { j->pld_slicw.bits.rly1 = 1; outb(j->pld_slicw.byte, j->XILINXbase + 0x01); j->flags.pots_pstn = 0; return 1; } } else { return 0; }}static void ixj_ring_on(IXJ *j){ if (j->dsp.low == 0x20) /* Internet PhoneJACK */ { if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); j->gpio.bytes.high = 0x0B; j->gpio.bytes.low = 0x00; j->gpio.bits.gpio1 = 1; j->gpio.bits.gpio2 = 1; j->gpio.bits.gpio5 = 0; ixj_WriteDSPCommand(j->gpio.word, j); /* send the ring signal */ } else /* Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI */ { if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); SLIC_SetState(PLD_SLIC_STATE_RINGING, j); }}static int ixj_siadc(IXJ *j, int val){ if(j->cardtype == QTI_PHONECARD){ if(j->flags.pcmciascp){ if(val == -1) return j->siadc.bits.rxg; if(val < 0 || val > 0x1F) return -1; j->siadc.bits.hom = 0; /* Handset Out Mute */ j->siadc.bits.lom = 0; /* Line Out Mute */ j->siadc.bits.rxg = val; /*(0xC000 - 0x41C8) / 0x4EF; RX PGA Gain */ j->psccr.bits.addr = 6; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->siadc.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); return j->siadc.bits.rxg; } } return -1;}static int ixj_sidac(IXJ *j, int val){ if(j->cardtype == QTI_PHONECARD){ if(j->flags.pcmciascp){ if(val == -1) return j->sidac.bits.txg; if(val < 0 || val > 0x1F) return -1; j->sidac.bits.srm = 1; /* Speaker Right Mute */ j->sidac.bits.slm = 1; /* Speaker Left Mute */ j->sidac.bits.txg = val; /* (0xC000 - 0x45E4) / 0x5D3; TX PGA Gain */ j->psccr.bits.addr = 7; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->sidac.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); return j->sidac.bits.txg; } } return -1;}static int ixj_pcmcia_cable_check(IXJ *j){ j->pccr1.byte = inb_p(j->XILINXbase + 0x03); if (!j->flags.pcmciastate) { j->pccr2.byte = inb_p(j->XILINXbase + 0x02); if (j->pccr1.bits.drf || j->pccr2.bits.rstc) { j->flags.pcmciastate = 4; return 0; } if (j->pccr1.bits.ed) { j->pccr1.bits.ed = 0; j->psccr.bits.dev = 3; j->psccr.bits.rw = 1; outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); ixj_PCcontrol_wait(j); j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0; j->psccr.bits.dev = 3; j->psccr.bits.rw = 0; outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); ixj_PCcontrol_wait(j); return j->pslic.bits.led2 ? 1 : 0; } else if (j->flags.pcmciasct) { return j->r_hook; } else { return 1; } } else if (j->flags.pcmciastate == 4) { if (!j->pccr1.bits.drf) { j->flags.pcmciastate = 3; } return 0; } else if (j->flags.pcmciastate == 3) { j->pccr2.bits.pwr = 0; j->pccr2.bits.rstc = 1; outb(j->pccr2.byte, j->XILINXbase + 0x02); j->checkwait = jiffies + (hertz * 2); j->flags.incheck = 1; j->flags.pcmciastate = 2; return 0; } else if (j->flags.pcmciastate == 2) { if (j->flags.incheck) { if (time_before(jiffies, j->checkwait)) { return 0; } else { j->flags.incheck = 0; } } j->pccr2.bits.pwr = 0; j->pccr2.bits.rstc = 0; outb_p(j->pccr2.byte, j->XILINXbase + 0x02); j->flags.pcmciastate = 1; return 0; } else if (j->flags.pcmciastate == 1) { j->flags.pcmciastate = 0; if (!j->pccr1.bits.drf) { j->psccr.bits.dev = 3; j->psccr.bits.rw = 1; outb_p(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); j->flags.pcmciascp = 1; /* Set Cable Present Flag */ j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03; /* Get Cable Type */ if (j->flags.pcmciasct == 3) { j->flags.pcmciastate = 4; return 0; } else if (j->flags.pcmciasct == 0) { j->pccr2.bits.pwr = 1; j->pccr2.bits.rstc = 0; outb_p(j->pccr2.byte, j->XILINXbase + 0x02); j->port = PORT_SPEAKER; } else { j->port = PORT_POTS; } j->sic1.bits.cpd = 0; /* Chip Power Down */ j->sic1.bits.mpd = 0; /* MIC Bias Power Down */ j->sic1.bits.hpd = 0; /* Handset Bias Power Down */ j->sic1.bits.lpd = 0; /* Line Bias Power Down */ j->sic1.bits.spd = 1; /* Speaker Drive Power Down */ j->psccr.bits.addr = 1; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->sic1.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); j->sic2.bits.al = 0; /* Analog Loopback DAC analog -> ADC analog */ j->sic2.bits.dl2 = 0; /* Digital Loopback DAC -> ADC one bit */ j->sic2.bits.dl1 = 0; /* Digital Loopback ADC -> DAC one bit */ j->sic2.bits.pll = 0; /* 1 = div 10, 0 = div 5 */ j->sic2.bits.hpd = 0; /* HPF disable */ j->psccr.bits.addr = 2; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->sic2.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); j->psccr.bits.addr = 3; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(0x00, j->XILINXbase + 0x00); /* PLL Divide N1 */ outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); j->psccr.bits.addr = 4; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(0x09, j->XILINXbase + 0x00); /* PLL Multiply M1 */ outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); j->sirxg.bits.lig = 1; /* Line In Gain */ j->sirxg.bits.lim = 1; /* Line In Mute */ j->sirxg.bits.mcg = 0; /* MIC In Gain was 3 */ j->sirxg.bits.mcm = 0; /* MIC In Mute */ j->sirxg.bits.him = 0; /* Handset In Mute */ j->sirxg.bits.iir = 1; /* IIR */ j->psccr.bits.addr = 5; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->sirxg.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); ixj_siadc(j, 0x17); ixj_sidac(j, 0x1D); j->siaatt.bits.sot = 0; j->psccr.bits.addr = 9; /* R/W Smart Cable Register Address */ j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->siaatt.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) { j->psccr.byte = j->pslic.byte = 0; j->pslic.bits.powerdown = 1; j->psccr.bits.dev = 3; j->psccr.bits.rw = 0; outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); ixj_PCcontrol_wait(j); } } return 0; } else { j->flags.pcmciascp = 0; return 0; } return 0;}static int ixj_hookstate(IXJ *j){ unsigned long det; int fOffHook = 0; switch (j->cardtype) { case QTI_PHONEJACK: ixj_gpio_read(j); fOffHook = j->gpio.bits.gpio3read ? 1 : 0; break; case QTI_LINEJACK: case QTI_PHONEJACK_LITE: case QTI_PHONEJACK_PCI: SLIC_GetState(j); if(j->cardtype == QTI_LINEJACK && j->flags.pots_pstn == 1 && (j->readers || j->writers)) { fOffHook = j->pld_slicr.bits.potspstn ? 1 : 0; if(fOffHook != j->p_hook) { if(!j->checkwait) { j->checkwait = jiffies; } if(time_before(jiffies, j->checkwait + 2)) { fOffHook ^= 1; } else { j->checkwait = 0; } j->p_hook = fOffHook; printk("IXJ : /dev/phone%d pots-pstn hookstate check %d at %ld\n", j->board, fOffHook, jiffies); } } else { if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE || j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) { if (j->flags.ringing || j->flags.cringing) { if (!in_interrupt()) { det = jiffies + (hertz / 50); while (time_before(jiffies, det)) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } } SLIC_GetState(j); if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) { ixj_ring_on(j); } } if (j->cardtype == QTI_PHONEJACK_PCI) { j->pld_scrr.byte = inb_p(j->XILINXbase); fOffHook = j->pld_scrr.pcib.det ? 1 : 0; } else fOffHook = j->pld_slicr.bits.det ? 1 : 0; } } break; case QTI_PHONECARD: fOffHook = ixj_pcmcia_cable_check(j); break; } if (j->r_hook != fOffHook) { j->r_hook = fOffHook; if (j->port == PORT_SPEAKER || j->port == PORT_HANDSET) { // || (j->port == PORT_PSTN && j->flags.pots_pstn == 0)) { j->ex.bits.hookstate = 1; ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); } else if (!fOffHook) { j->flash_end = jiffies + ((60 * hertz) / 100); } } if (fOffHook) { if(time_before(jiffies, j->flash_end)) { j->ex.bits.flash = 1; j->flash_end = 0; ixj_kill_fasync(j, SIG_FLASH, POLL_IN); } } else { if(time_before(jiffies, j->flash_end)) { fOffHook = 1; } } if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION) fOffHook |= 2; if (j->port == PORT_SPEAKER) { if(j->cardtype == QTI_PHONECARD) { if(j->flags.pcmciascp && j->flags.pcmciasct) { fOffHook |= 2; } } else { fOffHook |= 2; } } if (j->port == PORT_HANDSET) fOffHook |= 2; return fOffHook;}static void ixj_ring_off(IXJ *j){ if (j->dsp.low == 0x20) /* Internet PhoneJACK */ { if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Ring Off\n"); j->gpio.bytes.high = 0x0B; j->gpio.bytes.low = 0x00; j->gpio.bits.gpio1 = 0; j->gpio.bits.gpio2 = 1; j->gpio.bits.gpio5 = 0; ixj_WriteDSPCommand(j->gpio.word, j); } else /* Internet LineJACK */ { if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Ring Off\n"); if(!j->flags.cidplay) SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); SLIC_GetState(j); }}static void ixj_ring_start(IXJ *j){ j->flags.cringing = 1; if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Cadence Ringing Start /dev/phone%d\n", j->board); if (ixj_hookstate(j) & 1) { if (j->port == PORT_POTS) ixj_ring_off(j); j->flags.cringing = 0; if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Cadence Ringing Stopped /dev/phone%d off hook\n", j->board); } else if(j->cadence_f[5].enable && (!j->cadence_f[5].en_filter)) { j->ring_cadence_jif = jiffies; j->flags.cidsent = j->flags.cidring = 0; j->cadence_f[5].state = 0; if(j->cadence_f[5].on1) ixj_ring_on(j); } else { j->ring_cadence_jif = jiffies; j->ring_cadence_t = 15; if (j->ring_cadence & 1 << j->ring_cadence_t) { ixj_ring_on(j); } else { ixj_ring_off(j); } j->flags.cidsent = j->flags.cidring = j->flags.firstring = 0; }}static int ixj_ring(IXJ *j){ char cntr; unsigned long jif, det; j->flags.ringing = 1; if (ixj_hookstate(j) & 1) { ixj_ring_off(j); j->flags.ringing = 0; return 1; } det = 0; for (cntr = 0; cntr < j->maxrings; cntr++) { jif = jiffies + (1 * hertz); ixj_ring_on(j); while (time_before(jiffies, jif)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -