⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtv_ref2_audio.c

📁 用于TM1300/PNX1300系列DSP(主要用于视频处理)的设备库的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
    else if (sRate < 46050.0)
    {
        outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_44100_HZ;
    }
    else
    {
        outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_48000_HZ;
    }
    
    sRate = sRate * sckdiv * wsdiv * sfdiv;
    
    /* double output clock for modes that require it (e.g. 8-channel 32-bits) */
    if (dtvRef2DoubleDDSEnable)
    {
        sRate *= 2;
    }
    
    if (dtvRef2CPUisTM1100)
    {
        val = 0.5 + (477218588.0 * (sRate / dtvRef2CPUClock));    /* 2**32 / 9 */
        aoSetFREQ(((UInt) val) | 0x80000000);
    }
    else
    {
        val = 0.5 + (1431655765.0 * (sRate / dtvRef2CPUClock));    /* 2**32 / 3 */
        aoSetFREQ((UInt) val);
    }
    
    if (old_val != outputL3Regs[_CHANNEL_STATUS_REGISTER]) 
    {
        if (dtvRef2AoRunning)
        {
            outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
            err = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
        }
        else
        {
            dtvRef2AoNeedToConfigureTDA1315 = True;
        }
    }

    return err;
}

/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_GetSRate(Float * sRate)
{
    UInt                serial  = MMIO(AO_SERIAL);
    UInt                freq    = MMIO(AO_FREQ);
    UInt                sckdiv  = 1 + aoExtractSCKDIV(serial);
    UInt                wsdiv   = 1 + aoExtractWSDIV(serial);
    UInt                sfdiv   = 1 + aoExtractSFDIV(serial);
    Float               rate;

    if (dtvRef2CPUisTM1100)
    {
        rate = (Float) (freq & 0x7fffffff) * dtvRef2CPUClock / 477218588.0;
    }
    else
    {
        rate = (Float) freq * dtvRef2CPUClock / 1431655765.0;
    }
    rate = rate / ((Float) sckdiv * (Float) wsdiv * (Float) sfdiv);

    *sRate = rate;

    return TMLIBDEV_OK;
}

/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_Config(UInt32 subaddr, Pointer value)
{
    return AIO_ERR_COMMAND_NOT_SUPPORTED;
}


/************************** INPUT **********************************/

/* Input IIC expander, the interrupt pin of this iic expander (low active) is
   connected to the  user IRQ pin of the TriMedia. An interrupt is generated when
   the level changes on one of its inputs.
   
   address 0x72
   bit 0    unused
   bit 1    unused
   bit 2    copyprotection  input
   bit 3    powerdown       output
   bit 4    lock/unlock     input
   bit 5    48.0 kHz        input
   bit 6    44.1 kHz        input
   bit 7    32.0 kHz        input
*/

/* L3 IIC expander:
   address: 0x74
   bit 0  Dout L3 mode
   bit 1  Dout L3 clock
   bit 2  Dout L3 data
   bit 3  Dout L3 strobe
   bit 4  Din L3 mode
   bit 5  Din L3 clock
   bit 6  Din L3 data
   bit 7  Din L3 strobe
*/

/* function called in aiInstanceSetup():  On success, must leave
 * the audio input system "stopped" but otherwise ready for action.
 * MMIO setup will be done, as well as other board or codec specific 
 * actions like setting IIC control bits or initializing codec registers.
 */
extern tmLibdevErr_t dtv_ref2_AI_Init(pboardAIParam_t param)
{
    UInt                iicd;
    Float               val;
    pprocCapabilities_t procCap;
    Int                 err = TMLIBDEV_OK;

    /* get the clock frequency of the TriMedia CPU */       
    err = procGetCapabilities(&procCap);
    if (err) return err;
    dtvRef2CPUClock = (Float) procCap->cpuClockFrequency;

    if (procCap->deviceID == PROC_DEVICE_TM1100)
    {
        dtvRef2CPUisTM1100 = True;
    }
    
    /* set strobe to zero */
    err  = iicReadReg(L3_IIC_EXPANDER_ADDRESS, -1, &iicd);
    iicd &= ~(REF2_INPUT_L3_STROBE);
    err |= iicWriteReg(L3_IIC_EXPANDER_ADDRESS, -1, iicd);
    if (err) return err;
    

    aiRESET();
 
    /* clock freq is in hz.  Math is 32 bit- should be 64 bit!
       In the digital input mode the clock is only needed to use the L3 interface.
       In this case is the TriMedia clock slave.
       In the analog input mode the clocks are needed because the CS5331 is clock 
       slave. */
       
    val = param->sRate * 256; /* 256 * sampleRate */
    if (dtvRef2CPUisTM1100)
    {
        val = 0.5 + (477218588.0 * (val / dtvRef2CPUClock));    /* 2**32 / 9 */
        aiSetFREQ(((UInt) val) | 0x80000000);
    }
    else
    {
        val = 0.5 + (1431655765.0 * (val / dtvRef2CPUClock));    /* 2**32 / 3 */
        aiSetFREQ((UInt) val);
    }
    
    if (param->input == aaaNone) 
    {
        param->input = aaaDigitalInput; /* digital input is the default */
    }
    
    switch (param->input)
    {
    case aaaDigitalInput:   /* use TDA 1315 */
        /* set a small value for the input DDS frequency to disable the CS5331 */
        aiSetFREQ((UInt) (( ((UInt)val) & 0x7fffffff) / 10));
        /* set powerdown for input TDA1315 to zero (normal operation) */
        err = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
        tmAssert(err == TMLIBDEV_OK, err);
        iicd &= ~(REF2_TDA1315_IN_IIC_POWERDOWN);
        err = iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
        tmAssert(err == TMLIBDEV_OK, err);
        microsleep(1000);

        /* initalize the tda1315 */
        inputL3Params.data = &inputL3Regs[0];
        err = tda1315InitInput(&inputL3Params, param);

        aiDisableSER_MASTER();  /* tda1315 is master of clock */
        microsleep(10);         /* wait until internal state of audio in unit is stable */
        
        if (err == TMLIBDEV_OK)
        {    
            aiSetCAP_MODE(3);               /* Stereo 16 bits per sample */
            aiDisableSIGN_CONVERT();
            aiMsbFirst();                   /* MSB first */
            aiSetFRAMEMODE(0);              /* ignore valid bit */
            aiSampleRisingCLOCK_EDGE();     /* sample on rising edge */
            aiStartFallingEdgeWS();
            aiSetSSPOS(0);    
            aiSetLEFTPOS(0);            
            aiSetRIGHTPOS(32);
            aiSetSIZE(param->size);

#ifdef __LITTLE_ENDIAN__
            aiEnableLITTLE_ENDIAN();
#else
            aiDisableLITTLE_ENDIAN();
#endif
        }
        else return err;
        
        dtvRef2AiInput = aaaDigitalInput;
        break;
    case aaaLineInput:  /* use CS5331 */
        aiEnableSER_MASTER();   /* TM is master of clock */
        microsleep(2);          /* wait until internal state of audio in unit is stable */
        
        /* set powerdown for input TDA1315 to one (disable it) */
        err  = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
        iicd |= REF2_TDA1315_IN_IIC_POWERDOWN;
        err |= iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
        if (err) return err;
        microsleep(1000);

        aiSetWSDIV(63);
        aiSetSCKDIV(5);
        aiSetCAP_MODE(3);               /* Stereo 16 bits per sample */
        aiDisableSIGN_CONVERT();
        aiMsbFirst();                   /* MSB first */
        aiSetFRAMEMODE(0);              /* ignore valid bit */
        aiSampleRisingCLOCK_EDGE();     /* sample on rising edge */
        aiStartFallingEdgeWS();         /* left sample starts on neg. AI_WS */
        aiSetSSPOS(0);    
        aiSetLEFTPOS(0);            
        aiSetRIGHTPOS(32);
        aiSetSIZE(param->size);

#ifdef __LITTLE_ENDIAN__
        aiEnableLITTLE_ENDIAN();
#else
        aiDisableLITTLE_ENDIAN();
#endif
        dtvRef2AiInput = aaaLineInput;
        break;
    default:
        err = AIO_ERR_UNSUPPORTED_INPUT;
        break;
    }

    /* store parameters */
    dtvRef2AiAudioTypeFormat      = param->audioTypeFormat;       
    dtvRef2AiAudioSubtypeFormat   = param->audioSubtypeFormat;
    dtvRef2AiSRate                = param->sRate;
    dtvRef2AiSize                 = param->size;
    
    return err;

}

/* called in aiClose().  Should leave audio input system shut down */
extern tmLibdevErr_t dtv_ref2_AI_Term(void)
{
    return TMLIBDEV_OK;
}

/* called in aiStart(). */
extern tmLibdevErr_t dtv_ref2_AI_Start(void)
{
    aiEnableCAP_ENABLE();
    
    return TMLIBDEV_OK;
}

/* called in aiStop(). */
extern tmLibdevErr_t dtv_ref2_AI_Stop(void)
{
    aiDisableCAP_ENABLE();

    return TMLIBDEV_OK;
}

/* called from aiSetSampleRate(). */
extern tmLibdevErr_t dtv_ref2_AI_SetSrate(Float sRate)
{
    Float               val;
    
    /* it's not possible to change the input rate for digital input */
    if (dtvRef2AiInput == aaaDigitalInput)
    {
        return TMLIBDEV_OK;
    }
    
    val = sRate * 256.0; /* oversampling clock is 256 * fs */
    if (dtvRef2CPUisTM1100)
    {
        val = 0.5 + (477218588.0 * (val / dtvRef2CPUClock));    /* 2**32 / 9 */
        aiSetFREQ(((UInt) val) | 0x80000000);
    }
    else
    {
        val = 0.5 + (1431655765.0 * (val / dtvRef2CPUClock));    /* 2**32 / 3 */
        aiSetFREQ((UInt) val);
    }

    return TMLIBDEV_OK;
}

/* called from aiGetSampleRate().  
 * Should return an accurate value from the hardware. 
 */
extern tmLibdevErr_t dtv_ref2_AI_GetSrate(Float * sRate)
{
    UInt    iicd;
    Int     err = TMLIBDEV_OK;

    tmAssert(sRate, TMLIBDEV_ERR_NULL_PARAMETER);

    if (dtvRef2AiInput == aaaDigitalInput)
    {
        err     = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
        iicd    |= REF2_TDA1315_IN_IIC_FREQUENCY_MASK;
        err     |= iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
        err     |= iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
        if (err) return err;

        switch (iicd & REF2_TDA1315_IN_IIC_FREQUENCY_MASK)
        {
        case REF2_TDA1315_IN_IIC_44100_HZ:
            *sRate = 44100.0;
            break;
        case REF2_TDA1315_IN_IIC_48000_HZ:
            *sRate = 48000.0;
            break;
        case REF2_TDA1315_IN_IIC_32000_HZ:
            *sRate = 32000.0;
            break;
        default:
            *sRate = 0.0;
            break;
        }    
    }
    else
    {
        if (dtvRef2CPUisTM1100)
        {
            *sRate = (Float) (MMIO(AI_FREQ) & 0x7fffffff) * dtvRef2CPUClock / 477218588.0 / 256.0;
        }
        else
        {
            *sRate = (Float) MMIO(AI_FREQ) * dtvRef2CPUClock / 1431655765.0 / 256.0;
        }
    }
    return TMLIBDEV_OK;
}

/* called from aiSetInput() */
extern tmLibdevErr_t dtv_ref2_AI_SetInput(tmAudioAnalogAdapter_t input)
{
    boardAIParam_t  param;
    UInt            err;
    static Bool     capEnable = False;
    UInt32          buf1 = MMIO(AI_BASE1);
    UInt32          buf2 = MMIO(AI_BASE2);
    UInt32          size = MMIO(AI_SIZE);
    UInt32          aiIntControl = MMIO(AI_CTL) & (AI_BUF1_INTEN | AI_BUF2_INTEN | AI_OVR_INTEN | AI_HBE_INTEN);
    
    /* check if we realy have to change the input */
    if (input == dtvRef2AiInput)
    {
        return TMLIBDEV_OK;
    }
    
    /* stop audio in */
    if (MMIO(AI_CTL) & AI_CAP_ENABLE)
    {
        aiDisableCAP_ENABLE();
        capEnable = True;
    }
    
    param.audioTypeFormat      = dtvRef2AiAudioTypeFormat;       
    param.audioSubtypeFormat   = dtvRef2AiAudioSubtypeFormat;
    param.sRate                = dtvRef2AiSRate;
    param.size                 = dtvRef2AiSize;
    param.input                = input;
    dtvRef2AiInput           = input;
    
    
    err = dtv_ref2_AI_Init(&param);

    /* restore MMIO registers */
    MMIO(AI_BASE1)  = buf1;
    MMIO(AI_BASE2)  = buf2;
    MMIO(AI_SIZE)   = size;
    MMIO(AI_CTL)   |= aiIntControl;
    
    if (err)
    {
        return err;
    }
    
    if (capEnable)
    {
        aiEnableCAP_ENABLE();
    }
    
    return TMLIBDEV_OK;
}

/* called from aiGetInput() */
extern tmLibdevErr_t dtv_ref2_AI_GetInput(tmAudioAnalogAdapter_t * input)
{
    tmAssert(input, TMLIBDEV_ERR_NULL_PARAMETER);
    
    *input = dtvRef2AiInput;
    
    return TMLIBDEV_OK;
}

/* called from aiGetInputFormat */
extern tmLibdevErr_t dtv_ref2_AI_GetFormat(ptmAudioFormat_t inputFormat)
{
    Float   sRate;
    Int     err;
    Char    statusReg[2] = {0,0};

    /* initialize the inputFormat */
    inputFormat->size           = sizeof(tmAudioFormat_t);
    inputFormat->dataClass      = avdcAudio;
    inputFormat->dataType       = atfNone;
    inputFormat->dataSubtype    = apfNone;
    inputFormat->sampleRate     = 0.0;
    
    /* get sample rate, if sample rate is 0.0 -> TDA 1315 is not locked */
    err = dtv_ref2_AI_GetSrate(&sRate);
    if (err) return err;
    
    if (sRate == 0.0)
    {
        return TMLIBDEV_OK;
    }
    
    inputFormat->sampleRate     = sRate;
    inputFormat->dataType       = atfLinearPCM;
    inputFormat->dataSubtype    = apfStereo16;

    /* get channel status information */
    inputL3Params.data = statusReg;
    err = tda1315AccessL3(&inputL3Params, READ_CHANNEL_STATUS_REGISTER);
    if (err)
        return err;
    
    if ((statusReg[0] & TDA1315_L3_CHAN_STAT_DATA_MASK) == TDA1315_L3_CHAN_STAT_DATA)
    {
        inputFormat->dataType = atf1937;
        inputFormat->dataSubtype = apfGeneric;
    }
    
    return err;
}    

/* a backdoor to support features not forseen in the initial design */
extern tmLibdevErr_t dtv_ref2_AI_Config(UInt32 subaddr, Pointer value)
{
    return TMLIBDEV_OK;
}





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -