Пример #1
0
/**
 * 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 */
Пример #2
0
/**
 * 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 */