📄 merlin.cpp
字号:
/*+++ *******************************************************************\
*
* 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 + -