/** * Vp790InitLine * This function initializes a line of a device with the specified parameters * and API default values. It is a "Line Reset". * * Preconditions: * The device associated with this line must be initialized. * * Postconditions: * The line pointed to be the line context passed is initialized with the * profile data specified. This function returns the success code if the device * associated with this line is initialized. */ VpStatusType Vp790InitLine( VpLineCtxType *pLineCtx, VpProfilePtrType pAcProfile, /**< Pointer to AC coefficient data or * profile index to be applied to this line. */ VpProfilePtrType pDcOrFxoProfile, /**< Pointer to DC Feed (FXS) or Cfg * (FX0) profile or profile index to be * applied to this line. */ VpProfilePtrType pRingProfile) /**< Pointer to Ringing profile or profile * index to apply to this line */ { Vp790LineObjectType *pLineObj = pLineCtx->pLineObj; VpDevCtxType *pDevCtx = pLineCtx->pDevCtx; Vp790DeviceObjectType *pDevObj = pDevCtx->pDevObj; uint8 ecVal[] = {VP790_EC_CH1, VP790_EC_CH2, VP790_EC_CH3, VP790_EC_CH4}; uint8 channelId = pLineObj->channelId; uint8 data; #ifdef VP_CSLAC_SEQ_EN uint8 seqByte; #endif uint8 ioReg[VP790_IO_REG_LEN]; uint8 disableVals[VP790_LOOP_SUP_LEN] = {0x0D, 0x64, 0x0D, 0x01, 0x30, 0x00, 0x00, 0x7F}; VpDeviceIdType deviceId = pDevObj->deviceId; /* Proceed if initialized or in progress, and not calibrating */ if (pDevObj->status.state & (VP_DEV_INIT_CMP | VP_DEV_INIT_IN_PROGRESS)) { if (pDevObj->status.state & VP_DEV_IN_CAL) { return VP_STATUS_DEVICE_BUSY; } } else { return VP_STATUS_DEV_NOT_INITIALIZED; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); #ifdef VP_CSLAC_SEQ_EN for (seqByte = 0; seqByte < VP790_INT_SEQ_LEN; seqByte++) { pLineObj->intSequence[seqByte] = 0x00; } pLineObj->callerId.status = VP_CID_RESET_VALUE; pLineObj->thisFskCid = FALSE; #endif pLineObj->pRingingCadence = VP_PTABLE_NULL; pLineObj->pCidProfileType1 = VP_PTABLE_NULL; pLineObj->pCidProfileType2 = VP_PTABLE_NULL; pLineObj->lineState.currentState = VP_LINE_DISCONNECT; pLineObj->lineState.previous = VP_LINE_DISCONNECT; pLineObj->codec = VP_NUM_OPTION_CODEC_TYPE_IDS; pLineObj->lineTimers.type = VP_CSLAC_FXS_TIMER; InitTimerVars(pLineCtx); #ifdef VP_CSLAC_SEQ_EN VpMemSet(&pLineObj->cadence, 0, sizeof(VpSeqDataType)); #endif /* Software reset the channel */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_SW_RESET_CMD, NO_DATA, &data); VpSysWait(3); VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_LOOP_SUP_WRT, VP790_LOOP_SUP_LEN, disableVals); VpSysWait(1); /* Set the default line state */ Vp790SetLineState(pLineCtx, VP_LINE_DISCONNECT); /* Deactiveate the CODEC for the channel */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_DEACTIVATE_CMD, NO_DATA, &data); /***************** C3 Operational Issue 3 ******************/ /* This errata fix does not harm D3 operation */ data = 0x00; VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_CCR9_WRT, VP790_CCR9_LEN, &data); /* We've already deactivated the device */ VpSysWait(3); /**************** End Operational Issue 3 ******************/ pLineObj->ringCtrl.zeroCross = VP_OPTION_DEFAULT_ZERO_CROSS; Vp790ConfigLine(pLineCtx, pAcProfile, pDcOrFxoProfile, pRingProfile); VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_IO_REG_RD, VP790_IO_REG_LEN, ioReg); ioReg[0] |= VP790_IO_REG_RD1_MANUAL; VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_IO_REG_WRT, VP790_IO_REG_LEN, ioReg); VpImplementDefaultSettings(VP_NULL, pLineCtx); /* Force an initial test of the hook state */ pLineObj->lineState.condition = VP_CSLAC_STATUS_INVALID; pLineObj->dpStruct.hookSt = FALSE; VpInitDP(&pLineObj->dpStruct); /* Re-activate the channel due to a silicon bug -- and it doesn't hurt */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_ACTIVATE_CMD, NO_DATA, VP_NULL); /* Post the line init complete event */ pLineObj->lineEvents.response |= VP_LINE_EVID_LINE_INIT_CMP; VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_SUCCESS; } /* Vp790InitLine */
/** * Vp790Init * This function initializes the device, and (contrary to InitDevice) does * not initialize any channels. This function should be called internal to the * API only. * * Preconditions: * The device context must be of a Vp790 device type. * * Postconditions: * This function returns a failure code if the clock configuration is not set * correctly based on the device data set in InitDevice. */ VpStatusType Vp790Init( VpDevCtxType *pDevCtx) { VpLineCtxType *pLineCtx; Vp790DeviceObjectType *pDevObj = pDevCtx->pDevObj; VpDeviceIdType deviceId = pDevObj->deviceId; uint8 data, chanId, maxChan, gdStat; uint8 deviceFailure; uint8 testCount; uint8 mpiReset[] = { VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_NO_OP, VP790_HW_RESET_CMD }; /* Initialize the API's device dynamic variables */ pDevObj->dynamicInfo.lastChan = 0; /* * When the device timing is cleared, so are the lines associated with * this device */ maxChan = pDevObj->staticInfo.maxChannels; for (chanId = 0; chanId < maxChan; chanId++) { /* * It is possible that any channel on a device is not used and therefore * points to a NULL pointer. Check it and jump over if this is the case * to the next line until all possible line numbers for this device have * been checked. */ pLineCtx = pDevCtx->pLineCtx[chanId]; if (pLineCtx != VP_NULL) { /* * If the device is "dumping" it's timers, the lines associated with * this device better not be relying on timers. */ InitTimerVars(pLineCtx); } } /*********** Errata D2.1 and/or C3.9-10 (Part 1)************/ /* * If the MPI Bus gets out of sequence for any reason, a HW reset command * will not work and this function may fail. To be sure a reset occurs, the * following sequence is required. */ VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_NO_OP, 16, mpiReset); VpSysWait(20); VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_DEVTYPE_CMD, VP790_DEVTYPE_LEN, pDevObj->staticInfo.rcnPcn); if ((pDevObj->staticInfo.rcnPcn[0] == 0x00) || (pDevObj->staticInfo.rcnPcn[0] == 0xFF)) { return VP_STATUS_FAILURE; } /*************** End Errata D2.1 (Part 1) ******************/ /* * Setup mclk. The MCLK mask set the mclk frequency, sets the mclk source * (the MCLK pin or the PCLK pin), and sets the interrupt pin output drive * mode (TTL or open collector) */ data = pDevObj->devProfileData.devCfg1; VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_DCR1_WRT, VP790_DCR1_LEN, &data); /* * The MCLK correction register is used if the desired MCLK frequency is * NOT a multipal of 512kHz (for example 1.544MHz != n*512kHz, n an integer) */ data = pDevObj->devProfileData.mClkCorrection; VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_MCCR_WRT, VP790_MCCR_LEN, &data); /* * Wait for the CFAIL bit to clear before proceding. If the CFAIL bit * does not clear after several trys, give up and return an error * condition. Wait between each read of the status register. */ /* Setup parameters to clear interrupts .. or at least try */ deviceFailure = VP790_GD_STAT_CFAIL; testCount = MAX_CFAIL_TEST*10; while(deviceFailure && (--testCount) != 0) { VpSysWait(CFAIL_TEST_INTERVAL); VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_GD_STAT_RD, VP790_GD_STAT_LEN, &data); deviceFailure = data & VP790_GD_STAT_CFAIL; VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_INTRPT_RD, VP790_INTRPT_LEN, &data); } /* * The CFAIL bit did not clear so the part will not complete initialization. * Return error status to indicate failure. */ if(deviceFailure) { return VP_STATUS_FAILURE; } /* * The PCM mask tells the device which clock edge to grab and xmit the * PCM data on and also which clock period LSB of the PCM data starts on */ data = pDevObj->devProfileData.clockSlot; VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_XR_CS_WRT, VP790_XR_CS_LEN, &data); /* Clear all Device Interrupt Masks except Pos Bat */ data = VP790_GD_MASK_PINT; VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_GD_MASK_WRT, VP790_GD_MASK_LEN, &data); /* Clear all interrupts that resulted from power-up and reset */ data = 0x01; while(data != 0x00) { VpSysWait(2); VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_INTRPT_RD, VP790_INTRPT_LEN, &data); /* Clear a device interrupt if one is pending */ if(data & VP790_INTR_GLOB) { VpMpiCmdWrapper(deviceId, VP790_EC_CH1, VP790_GD_STAT_RD, VP790_GD_STAT_LEN, &gdStat); } } return VP_STATUS_SUCCESS; } /* Vp790Init */