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

📄 merlin.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*+++ *******************************************************************\
*
*  Copyright and Disclaimer:
*
*     ---------------------------------------------------------------
*     This software is provided "AS IS" without warranty of any kind,
*     either expressed or implied, including but not limited to the
*     implied warranties of noninfringement, merchantability and/or
*     fitness for a particular purpose.
*     ---------------------------------------------------------------
*
*     Copyright (c) 2008 Conexant Systems, Inc.
*     All rights reserved.
*
\******************************************************************* ---*/

#include "Merlin.h"
#include "hammerhead_registers.h"
#include "DirectIF.h"
#include "device.h"
#include "debug.h"
#include "registryAccess.h"
#include "miscfuncs.h"
#include "cusbintf.h"

#define PREF_MODE_MONO_LANGA        0
#define PREF_MODE_MONO_LANGB        1
#define PREF_MODE_MONO_LANGC        2
#define PREF_MODE_FALLBACK          3
#define PREF_MODE_STEREO            4
#define PREF_MODE_DUAL_LANG_AC      5
#define PREF_MODE_DUAL_LANG_BC      6
#define PREF_MODE_DUAL_LANG_AB      7


#define DETECT_STEREO               1
#define DETECT_DUAL                 2
#define DETECT_TRI                  4
#define DETECT_SAP                  0x10
#define DETECT_NO_SIGNAL            0xFF
#define DETECT_FM_LOCKED            0x0E

#define PREF_AUDIO_STANDARD_BG                    0xF0  //NICAM BG and A2 BG
#define PREF_AUDIO_STANDARD_DK                    0xF1
#define PREF_AUDIO_STANDARD_I                     0xF4  //NICAM I and A1
#define PREF_AUDIO_STANDARD_L                     0xF5  //NICAM L and System L AM
#define PREF_AUDIO_STANDARD_BTSC                  0xF6
#define PREF_AUDIO_STANDARD_EIAJ                  0xF7
#define PREF_AUDIO_STANDARD_M                     0xF8
#define PREF_AUDIO_STANDARD_FM_10_7               0x4F9 // IF = 10.7 MHz
#define PREF_AUDIO_STANDARD_FM_5_5                0x4FA // IF =  5.5 MHz
#define PREF_AUDIO_STANDARD_AUTO                  0xFF

/////////////////////////////////////////////////////////////////////////////////////////
Merlin::Merlin(Device *p_device,DEVICE_OBJECT* p_do, SyncRegIo* p_registers, DirectIF* p_DIF):
_p_registers(p_registers),
_tv_audio_preferred_mode(PREF_MODE_STEREO),
_current_audio_input(AUDIO_INPUT_LINE),
_audio_standard(AUDIO_STANDARD_BTSC),
_audio_fw_version(0),
_frequency(48000),
_p_device(p_device),
_p_DIF(p_DIF)
{
}

/////////////////////////////////////////////////////////////////////////////////////////
Merlin::~Merlin()
{
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID Merlin::setAudioInput(AUDIO_INPUT audio_input)
{
    DWORD dwval;
    NTSTATUS status;

    _current_audio_input = audio_input;

    setFrequency(_frequency);

    _p_registers->lock();

    //Put it in soft reset
    BYTE gen_ctrl;
    _p_registers->readByte(GENERAL_CTL, &gen_ctrl);
    gen_ctrl |= 1;
    _p_registers->writeByte(GENERAL_CTL, gen_ctrl);

    switch(audio_input)
    {
    case AUDIO_INPUT_LINE:
        _p_registers->stopAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);
        //_p_registers->writeDword(PATH1_CTL1, 0x01011012);

        //setup AUD_IO control from Merlin paralle output
        _p_registers->writeDword(AUD_IO_CTRL, _p_registers->Set_Field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL));

        //setup input to Merlin, SRC2 connect to AC97
        //bypass upsample-by-2, slave mode, sony mode, left justify
        //adr 091c, dat 01000000
        _p_registers->readDword(AC97_CTL,&dwval);

        _p_registers->writeDword(AC97_CTL, dwval | FLD_AC97_UP2X_BYPASS);

        //select the parallel1 and SRC3
        _p_registers->writeDword(BAND_OUT_SEL,
                     _p_registers->Set_Field(FLD_SRC3_IN_SEL, 0x0)|
                     _p_registers->Set_Field(FLD_SRC3_CLK_SEL, 0x0)|
                     _p_registers->Set_Field(FLD_PARALLEL1_SRC_SEL, 0x0));

        //unmute all, AC97 in, independence mode
        //adr 08d0, data 0x00063073
        _p_registers->writeDword(PATH1_CTL1, 0x00063073);

        //set AVC maximum threshold, adr 08d4, dat ffff0024
        _p_registers->readDword(PATH1_VOL_CTL,&dwval);
        _p_registers->writeDword(PATH1_VOL_CTL, dwval | FLD_PATH1_AVC_THRESHOLD);

        //set SC maximum threshold, adr 08ec, dat ffffb3a3
        _p_registers->readDword(PATH1_SC_CTL,&dwval);
        _p_registers->writeDword(PATH1_SC_CTL, dwval | FLD_PATH1_SC_THRESHOLD);
        break;

    case AUDIO_INPUT_TUNER_TV:
    default:
        _p_registers->stopAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);

     // Setup SRC sources and clocks
     _p_registers->writeDword(BAND_OUT_SEL,
            _p_registers->Set_Field(FLD_SRC6_IN_SEL, 0x00)|
            _p_registers->Set_Field(FLD_SRC6_CLK_SEL, 0x01)|
            _p_registers->Set_Field(FLD_SRC5_IN_SEL, 0x00)|
            _p_registers->Set_Field(FLD_SRC5_CLK_SEL, 0x02)|
            _p_registers->Set_Field(FLD_SRC4_IN_SEL, 0x02)|
            _p_registers->Set_Field(FLD_SRC4_CLK_SEL, 0x03)|
            _p_registers->Set_Field(FLD_SRC3_IN_SEL, 0x00)|
            _p_registers->Set_Field(FLD_SRC3_CLK_SEL, 0x00)|
            _p_registers->Set_Field(FLD_BASEBAND_BYPASS_CTL, 0x00)|
            _p_registers->Set_Field(FLD_AC97_SRC_SEL, 0x03)|
            _p_registers->Set_Field(FLD_I2S_SRC_SEL, 0x00)|
            _p_registers->Set_Field(FLD_PARALLEL2_SRC_SEL, 0x02)|
            _p_registers->Set_Field(FLD_PARALLEL1_SRC_SEL, 0x01));

     // Setup the AUD_IO control
     _p_registers->writeDword(AUD_IO_CTRL,
            _p_registers->Set_Field(FLD_I2S_PORT_DIR, 0x00)|
            _p_registers->Set_Field(FLD_I2S_OUT_SRC, 0x00)|
            _p_registers->Set_Field(FLD_AUD_CHAN3_SRC,0x00)|
            _p_registers->Set_Field(FLD_AUD_CHAN2_SRC, 0x00)|
            _p_registers->Set_Field(FLD_AUD_CHAN1_SRC,0x03 ));

     _p_registers->writeDword(PATH1_CTL1, 0x1F063870);

     setAudioStandard(_audio_standard);

     _p_registers->writeDword(PATH1_CTL1, 0x00063870);

     _p_registers->restartAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);
        break;

    case AUDIO_INPUT_SPDIF:
        _p_registers->stopAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);
        //set I2S port direction to input, default is 0x0
        _p_registers->writeDword(AUD_IO_CTRL,
            _p_registers->Set_Field(FLD_I2S_PORT_DIR , 0x1));

        // Select I2S as input to Merlin 0x2 .. from flatiron value is 0x3
        _p_registers->writeDword(PATH1_CTL1,
            _p_registers->Set_Field(FLD_PATH1_SEL_CTL, 0x2));
         break;

    case AUDIO_INPUT_TUNER_FM:
        DWORD value;
        _p_registers->stopAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);

        // use SIF for FM radio
        setupFM();


        setAudioStandard(_audio_standard);

        _p_registers->restartAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);
        
        

        break;

    case AUDIO_INPUT_MUTE:
        _p_registers->stopAudioFirmware(FIRMWARE_STOP_REASON_CROSSBAR);
        _p_registers->writeDword(PATH1_CTL1, 0x1F011012);
        break;
    }

    //Take it out of soft reset
    _p_registers->readByte(GENERAL_CTL, &gen_ctrl);
    gen_ctrl &= ~1;
    _p_registers->writeByte(GENERAL_CTL, gen_ctrl);

    _p_registers->unlock();

  }


Merlin::AUDIO_INPUT Merlin::getAudioInput()
{
    return _current_audio_input;
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID Merlin::setFrequency(DWORD frequency)
{
    _frequency = frequency;
    _p_registers->lock();
    
    switch(frequency)
    {
        // MAE 16 Sep 2006 - Need to calc correct values for 32 and 44.1 KHz, these
        case 32000:
            // Set audio AUX PLL for 32 KHz 81.920 MHz for A, 24.576 MHz for B
            // Aux PLL INT =     0x08 = 8
            // Aux PLL FRAC =    0x012A0869 = 19531881
            // Aux PLL POST_A =  0x03 = 3
            // Aux PLL POST_B =  0x0A = 10
            // Polaris change this to DC_CTRL4
            //_p_registers->writeDword(AUX_PLL_FRAC,     0x012A0869);
            // Polaris change this to DC_CTRL3
            //_p_registers->writeDword(AUX_PLL_INT_POST, 0x000A0308);
            _p_registers->writeDword(SRC1_CTL, 0x08010000);
            _p_registers->writeDword(SRC3_CTL, 0x08020000);
            _p_registers->writeDword(SRC4_CTL, 0x08020000);
            _p_registers->writeDword(SRC6_CTL, 0x08020000);
            break;

        case 44100:
            // Set audio AUX PLL for 44.1 KHz 112.896 MHz for A, 33.8688 MHz for B
            // Aux PLL INT =     0x0B = 11
            // Aux PLL FRAC =    0x01A786CA = 27756234
            // Aux PLL POST_A =  0x03 = 3
            // Aux PLL POST_B =  0x0A = 10
            // Polaris change this to DC_CTRL4
            //_p_registers->writeDword(AUX_PLL_FRAC,     0x01A786CA);
            // Polaris change this to DC_CTRL3
            //_p_registers->writeDword(AUX_PLL_INT_POST, 0x000A030B);
            _p_registers->writeDword(SRC1_CTL, 0x080160CD);
            _p_registers->writeDword(SRC3_CTL, 0x08017385);
            _p_registers->writeDword(SRC4_CTL, 0x08017385);
            _p_registers->writeDword(SRC6_CTL, 0x08017385);
            break;

        case 48000:
            // Set audio AUX PLL for 48 KHz initially = 122.880 MHz for A, 36.864 MHz for B
            // Will also have code in audio object for specific sample rates
            //setup audio pll to clock Flatiron ADC with 122.88 MHz
            //7680*48000/25000000 = 14.7456
            //INT = 14, POSTA = 3, POSTB = 10

             // Set audio AUX PLL for 48 KHz initially = 122.880 MHz for A, 36.864 MHz for B
            // Will also have code in audio object for specific sample rates
            // Aux PLL INT =     0x0E = 14
            // Aux PLL FRAC =    0x017DBF48 = 25018184
            // Aux PLL POST_A =  0x03 = 3
            // Aux PLL POST_B =  0x0A = 10
            // Polaris change this to DC_CTRL4
            //_p_registers->writeDword(AUX_PLL_FRAC,     0x017DBF48);
            // Polaris change this to DC_CTRL3
            //_p_registers->writeDword(AUX_PLL_INT_POST, 0x000A030E);
            _p_registers->writeDword(SRC1_CTL, 0x0801867C);
            _p_registers->writeDword(SRC2_CTL, 0x0801867C);
            _p_registers->writeDword(SRC3_CTL, 0x08014FAA);
            _p_registers->writeDword(SRC4_CTL, 0x08014FAA);
            _p_registers->writeDword(SRC6_CTL, 0x08014FAA);
            break;
    }

    _p_registers->unlock();
    
}

VOID Merlin::setAudioStandard(AUDIO_STANDARD audio_standard)
{
    _audio_standard = audio_standard;

    //Read the detected modes
    DWORD std_ctrl_reg;
    _p_registers->readDword(STD_DET_CTL, &std_ctrl_reg);

    std_ctrl_reg &= 0xFFFFFF00;
    
    DWORD new_setting = PREF_AUDIO_STANDARD_BTSC;
    
    if(_current_audio_input == AUDIO_INPUT_TUNER_TV)
    {
        
        switch(audio_standard)
        {
        default:
            DbgLogInfo(("Unknown audio standard\n"));

        case AUDIO_STANDARD_BTSC:
            new_setting = PREF_AUDIO_STANDARD_BTSC;
            break;

        case AUDIO_STANDARD_EIAJ:
            new_setting = PREF_AUDIO_STANDARD_EIAJ;
            break;

        case AUDIO_STANDARD_A2_M:
            new_setting = PREF_AUDIO_STANDARD_M;
            break;

        case AUDIO_STANDARD_NICAM_BG:
            new_setting = PREF_AUDIO_STANDARD_BG;
            break;

        case AUDIO_STANDARD_NICAM_DK:
            new_setting = PREF_AUDIO_STANDARD_DK;
            break;

        case AUDIO_STANDARD_NICAM_I:
            new_setting = PREF_AUDIO_STANDARD_I;
            break;

       case AUDIO_STANDARD_NICAM_L:
            new_setting = PREF_AUDIO_STANDARD_L;
            break;
        }

        //Using the firmware to set AUTOCONFIG register and setting the Prefered modes

        std_ctrl_reg |=new_setting;

        _p_registers->writeDword(STD_DET_CTL, std_ctrl_reg);
    }
    else if(_current_audio_input == AUDIO_INPUT_TUNER_FM)
    {
        new_setting = PREF_AUDIO_STANDARD_FM_5_5;        
        std_ctrl_reg |=new_setting;
        _p_registers->writeDword(STD_DET_CTL, std_ctrl_reg);
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS Merlin::openFirmwareFile(HANDLE* p_file)
{
    UNICODE_STRING file_name;
    RtlInitUnicodeString(&file_name, L"\\systemroot\\system32\\drivers\\merlinD.rom");

    //Open the file
    OBJECT_ATTRIBUTES attributes;
    InitializeObjectAttributes(
        &attributes,
        &file_name,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL);

    IO_STATUS_BLOCK status_block;

    NTSTATUS status = ZwCreateFile(
        p_file,                                                 //FileHandle
        FILE_GENERIC_READ | SYNCHRONIZE,                        //DesiredAccess
        &attributes,                                            //ObjectAttributes
        &status_block,                                          //IoStatusBlock
        NULL,                                                   //AllocationSize
        0,                                                      //FileAttributes
        FILE_SHARE_READ,                                        //ShareAccess
        FILE_OPEN,                                              //CreateDisposition
        FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, //CreateOptions
        NULL,                                                   //EaBuffer
        0);                                                     //EaLength

    if(!(*p_file))
    {
        return STATUS_UNSUCCESSFUL;
    }

    return status;
}

⌨️ 快捷键说明

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