#include "radeon_interface.h"
#include "radeon_accelerant.h"
#include "tv_out_regs.h"
#include "pll_access.h"
#include "mmio.h"
#include "utils.h"
#include "set_mode.h"
#include <stdlib.h>
typedef struct register_mapping {
uint16 address;
uint16 offset;
} register_mapping;
static const register_mapping intern_reg_mapping_before_pll[] = {
{ RADEON_TV_MASTER_CNTL, offsetof( impactv_regs, tv_master_cntl ) },
{ RADEON_TV_HRESTART, offsetof( impactv_regs, tv_hrestart ) },
{ RADEON_TV_VRESTART, offsetof( impactv_regs, tv_vrestart ) },
{ RADEON_TV_FRESTART, offsetof( impactv_regs, tv_frestart ) },
{ RADEON_TV_FTOTAL, offsetof( impactv_regs, tv_ftotal ) },
{ 0, 0 }
};
static const register_mapping intern_reg_mapping_pll[] = {
{ RADEON_TV_PLL_CNTL, offsetof( impactv_regs, tv_tv_pll_cntl ) },
{ RADEON_TV_PLL_CNTL1, offsetof( impactv_regs, tv_pll_cntl1 ) },
{ RADEON_TV_PLL_FINE_CNTL, offsetof( impactv_regs, tv_pll_fine_cntl ) },
{ 0, 0 }
};
static const register_mapping intern_reg_mapping_after_pll[] = {
{ RADEON_TV_HTOTAL, offsetof( impactv_regs, tv_htotal ) },
{ RADEON_TV_HDISP, offsetof( impactv_regs, tv_hdisp ) },
{ RADEON_TV_HSTART, offsetof( impactv_regs, tv_hstart ) },
{ RADEON_TV_VTOTAL, offsetof( impactv_regs, tv_vtotal ) },
{ RADEON_TV_VDISP, offsetof( impactv_regs, tv_vdisp ) },
{ RADEON_TV_TIMING_CNTL, offsetof( impactv_regs, tv_timing_cntl ) },
{ RADEON_TV_VSCALER_CNTL1, offsetof( impactv_regs, tv_vscaler_cntl1 ) },
{ RADEON_TV_VSCALER_CNTL2, offsetof( impactv_regs, tv_vscaler_cntl2 ) },
{ RADEON_TV_Y_SAW_TOOTH_CNTL, offsetof( impactv_regs, tv_y_saw_tooth_cntl ) },
{ RADEON_TV_Y_RISE_CNTL, offsetof( impactv_regs, tv_y_rise_cntl ) },
{ RADEON_TV_Y_FALL_CNTL, offsetof( impactv_regs, tv_y_fall_cntl ) },
{ RADEON_TV_MODULATOR_CNTL1, offsetof( impactv_regs, tv_modulator_cntl1 ) },
{ RADEON_TV_MODULATOR_CNTL2, offsetof( impactv_regs, tv_modulator_cntl2 ) },
{ RADEON_TV_RGB_CNTL, offsetof( impactv_regs, tv_rgb_cntl ) },
{ RADEON_TV_UV_ADR, offsetof( impactv_regs, tv_uv_adr ) },
{ RADEON_TV_PRE_DAC_MUX_CNTL, offsetof( impactv_regs, tv_pre_dac_mux_cntl ) },
{ RADEON_TV_CRC_CNTL, offsetof( impactv_regs, tv_crc_cntl ) },
{ 0, 0 }
};
static const register_mapping intern_reg_mapping_finish[] = {
{ RADEON_TV_GAIN_LIMIT_SETTINGS, offsetof( impactv_regs, tv_gain_limit_settings ) },
{ RADEON_TV_LINEAR_GAIN_SETTINGS, offsetof( impactv_regs, tv_linear_gain_settings ) },
{ RADEON_TV_UPSAMP_AND_GAIN_CNTL, offsetof( impactv_regs, tv_upsamp_and_gain_cntl ) },
{ RADEON_TV_DAC_CNTL, offsetof( impactv_regs, tv_dac_cntl ) },
{ RADEON_TV_MASTER_CNTL, offsetof( impactv_regs, tv_master_cntl ) },
{ 0, 0 }
};
static void writeMMIORegList(
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
{
vuint8 *regs = ai->regs;
for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) {
OUTREG( regs, mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );
}
}
static void writePLLRegList(
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
{
for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) {
Radeon_OUTPLL( ai->regs, ai->si->asic,
mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );
}
}
#if 0
static uint32 Radeon_InternalTVOutReadFIFO(
accelerator_info *ai, uint16 addr )
{
vuint8 *regs = ai->regs;
bigtime_t start_time;
uint32 res = ~0;
OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_TV_HOST_RD_WT_CNTL_RD);
start_time = system_time();
do {
uint32 status;
status = INREG( regs, RADEON_TV_HOST_RD_WT_CNTL );
if( (status & RADEON_TV_HOST_RD_WT_CNTL_RD_ACK) != 0 )
break;
} while( system_time() - start_time < 2000000 );
OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, 0);
res = INREG( regs, RADEON_TV_HOST_READ_DATA );
return res;
}
#endif
static void Radeon_InternalTVOutWriteFIFO(
accelerator_info *ai, uint16 addr, uint32 value )
{
vuint8 *regs = ai->regs;
bigtime_t start_time;
OUTREG( regs, RADEON_TV_HOST_WRITE_DATA, value );
OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_TV_HOST_RD_WT_CNTL_WT );
start_time = system_time();
do {
uint32 status;
status = INREG( regs, RADEON_TV_HOST_RD_WT_CNTL );
if( (status & RADEON_TV_HOST_RD_WT_CNTL_WT_ACK) != 0 )
break;
} while( system_time() - start_time < 2000000 );
OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, 0 );
}
void Radeon_InternalTVOutProgramRegisters(
accelerator_info *ai, impactv_regs *values )
{
uint32 orig_tv_master_cntl = values->tv_master_cntl;
SHOW_FLOW0( 2, "" );
values->tv_master_cntl |=
RADEON_TV_MASTER_CNTL_TV_ASYNC_RST |
RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST |
RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST |
RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST |
RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST |
RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST;
writeMMIORegList( ai, values, intern_reg_mapping_before_pll );
writePLLRegList( ai, values, intern_reg_mapping_pll );
writeMMIORegList( ai, values, intern_reg_mapping_after_pll );
OUTREG( ai->regs, RADEON_TV_MASTER_CNTL,
orig_tv_master_cntl |
RADEON_TV_MASTER_CNTL_TV_ASYNC_RST |
RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST |
RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST |
RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST |
RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST );
Radeon_ImpacTVwriteHorTimingTable( ai, Radeon_InternalTVOutWriteFIFO, values, true );
Radeon_ImpacTVwriteVertTimingTable( ai, Radeon_InternalTVOutWriteFIFO, values );
snooze( 50000 );
values->tv_master_cntl = orig_tv_master_cntl;
writeMMIORegList( ai, values, intern_reg_mapping_finish );
}
static void readMMIORegList(
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
{
vuint8 *regs = ai->regs;
for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) {
*(uint32 *)((char *)(values) + mapping->offset) =
INREG( regs, mapping->address );
}
}
static void readPLLRegList(
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
{
for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) {
*(uint32 *)((char *)(values) + mapping->offset) =
Radeon_INPLL( ai->regs, ai->si->asic, mapping->address );
}
}
void Radeon_InternalTVOutReadRegisters(
accelerator_info *ai, impactv_regs *values )
{
readMMIORegList( ai, values, intern_reg_mapping_before_pll );
readPLLRegList( ai, values, intern_reg_mapping_pll );
readMMIORegList( ai, values, intern_reg_mapping_after_pll );
readMMIORegList( ai, values, intern_reg_mapping_finish );
}