#define FS450_DIRECTREG 0
#include "tv_fs450.h"
#undef fsmax
#undef fsmin
#define fsmax(a, b) ((a) > (b) ? (a) : (b))
#define fsmin(a, b) ((a) < (b) ? (a) : (b))
#undef range_limit
#define range_limit(val,min_val,max_val) (fsmax((min_val),fsmin((val),(max_val))))
#define MAX_REGISTERS 32
#define MAX_BITS 32
#define READ 1
#define WRITE 2
#define READ_WRITE (READ | WRITE)
typedef struct
{
char *name;
unsigned long offset;
unsigned char bit_length;
unsigned char valid_bits;
unsigned char read_write;
char *bitfield_names[MAX_BITS];
}
S_REGISTER_DESCRIP;
typedef struct
{
int source;
char *name;
S_REGISTER_DESCRIP registers[MAX_REGISTERS];
}
S_SET_DESCRIP;
const S_SET_DESCRIP *houston_regs(void);
const S_SET_DESCRIP *encoder_regs(void);
const S_SET_DESCRIP *macrovision_regs(void);
const S_SET_DESCRIP *gcc_regs(void);
#define HOUSTON_IHO 0x00
#define HOUSTON_IVO 0x02
#define HOUSTON_IHA 0x04
#define HOUSTON_VSC 0x06
#define HOUSTON_HSC 0x08
#define HOUSTON_BYP 0x0A
#define HOUSTON_CR 0x0C
#define HOUSTON_SP 0x0E
#define HOUSTON_NCONL 0x10
#define HOUSTON_NCONH 0x12
#define HOUSTON_NCODL 0x14
#define HOUSTON_NCODH 0x16
#define HOUSTON_APO 0x18
#define HOUSTON_ALO 0x1A
#define HOUSTON_AFO 0x1C
#define HOUSTON_HSOUTWID 0x1E
#define HOUSTON_HSOUTST 0x20
#define HOUSTON_HSOUTEND 0x22
#define HOUSTON_SHP 0x24
#define HOUSTON_FLK 0x26
#define HOUSTON_BCONTL 0x28
#define HOUSTON_BCONTH 0x2A
#define HOUSTON_BDONE 0x2C
#define HOUSTON_BDIAGL 0x2E
#define HOUSTON_BDIAGH 0x30
#define HOUSTON_REV 0x32
#define HOUSTON_MISC 0x34
#define HOUSTON_FFO 0x36
#define HOUSTON_FFO_LAT 0x38
#define HOUSTON_VSOUTWID 0x3A
#define HOUSTON_VSOUTST 0x3C
#define HOUSTON_VSOUTEND 0x3E
#define BYP_RGB_BYPASS 0x0001
#define BYP_HDS_BYPASS 0x0002
#define BYP_HDS_TBYPASS 0x0004
#define BYP_CAC_BYPASS 0x0008
#define BYP_R2V_SBYPASS 0x0010
#define BYP_R2V_BYPASS 0x0020
#define BYP_VDS_BYPASS 0x0040
#define BYP_FFT_BYPASS 0x0080
#define BYP_FIF_BYPASS 0x0100
#define BYP_FIF_TBYPASS 0x0200
#define BYP_HUS_BYPASS 0x0400
#define BYP_HUS_TBYPASS 0x0800
#define BYP_CCR_BYPASS 0x1000
#define BYP_PLL_BYPASS 0x2000
#define BYP_NCO_BYPASS 0x4000
#define BYP_ENC_BYPASS 0x8000
#define CR_RESET 0x0001
#define CR_CLKOFF 0x0002
#define CR_NCO_EN 0x0004
#define CR_COMPOFF 0x0008
#define CR_YCOFF 0x0010
#define CR_LP_EN 0x0020
#define CR_CACQ_CLR 0x0040
#define CR_FFO_CLR 0x0080
#define CR_656_PAL_NTSC 0x0100
#define CR_656_STD_VMI 0x0200
#define CR_OFMT 0x0400
#define CR_UIM_CLK 0x0800
#define CR_UIM_DEC 0x1000
#define CR_BIPGEN_EN1 0x2000
#define CR_UIM_MOD0 0x4000
#define CR_UIM_MOD1 0x8000
#define SP_CACQ_ST 0x0001
#define SP_FFO_ST 0x0002
#define SP_REVID_MASK 0x7FFC
#define SP_MV_EN 0x8000
#define BDONE_BIST_DONE_A 0x0001
#define BDONE_BIST_DONE_B 0x0002
#define BDONE_BIST_DONE_C 0x0004
#define BDONE_BIST_DONE_D 0x0008
#define BDONE_BIST_DONE_E 0x0010
#define BDONE_BIST_DONE_F 0x0020
#define BDONE_BIST_DONE_G 0x0040
#define BDIAGL_BIST_DIAG_A 0x000F
#define BDIAGL_BIST_DIAG_B 0x00F0
#define BDIAGL_BIST_DIAG_C 0x0F00
#define BDIAGL_BIST_DIAG_D 0xF000
#define BDIAGH_BIST_DIAG_E 0x000F
#define BDIAGH_BIST_DIAG_F 0x000F
#define BDIAGH_BIST_DIAG_G 0x000F
#define MISC_TV_SHORT_FLD 0x0001
#define MISC_ENC_TEST 0x0002
#define MISC_DAC_TEST 0x0004
#define MISC_MV_SOFT_EN 0x0008
#define MISC_NCO_LOAD0 0x0010
#define MISC_NCO_LOAD1 0x0020
#define MISC_VGACKDIV 0x0200
#define MISC_BRIDGE_SYNC 0x0400
#define MISC_GTLIO_PD 0x8000
#define ENC_CHROMA_FREQ 0x40
#define ENC_CHROMA_PHASE 0x44
#define ENC_REG05 0x45
#define ENC_REG06 0x46
#define ENC_REG07 0x47
#define ENC_HSYNC_WIDTH 0x48
#define ENC_BURST_WIDTH 0x49
#define ENC_BACK_PORCH 0x4A
#define ENC_CB_BURST_LEVEL 0x4B
#define ENC_CR_BURST_LEVEL 0x4C
#define ENC_SLAVE_MODE 0x4D
#define ENC_BLACK_LEVEL 0x4e
#define ENC_BLANK_LEVEL 0x50
#define ENC_NUM_LINES 0x57
#define ENC_WHITE_LEVEL 0x5e
#define ENC_CB_GAIN 0x60
#define ENC_CR_GAIN 0x62
#define ENC_TINT 0x65
#define ENC_BREEZE_WAY 0x69
#define ENC_FRONT_PORCH 0x6C
#define ENC_ACTIVELINE 0x71
#define ENC_FIRST_LINE 0x73
#define ENC_REG34 0x74
#define ENC_SYNC_LEVEL 0x75
#define ENC_VBI_BLANK_LEVEL 0x7C
#define ENC_RESET 0x7e
#define ENC_NOTCH_FILTER 0x8d
#define MV_N0 0x59
#define MV_N1 0x52
#define MV_N2 0x7b
#define MV_N3 0x53
#define MV_N4 0x79
#define MV_N5 0x5d
#define MV_N6 0x7a
#define MV_N7 0x64
#define MV_N8 0x54
#define MV_N9 0x55
#define MV_N10 0x56
#define MV_N11 0x6d
#define MV_N12 0x6f
#define MV_N13 0x5a
#define MV_N14 0x5b
#define MV_N15 0x5c
#define MV_N16 0x63
#define MV_N17 0x66
#define MV_N18 0x68
#define MV_N19 0x67
#define MV_N20 0x61
#define MV_N21 0x6a
#define MV_N22 0x76
#define MV_AGC_PULSE_LEVEL 0x77
#define MV_BP_PULSE_LEVEL 0x78
#define TRACE(parameters) {}
typedef struct _S_TIMING_SPECS
{
int vga_width;
int vga_lines;
int tv_width;
int tv_lines;
int h_total;
int h_sync;
int v_total;
int v_sync;
}
S_TIMING_SPECS;
#define HOUSTON_REV_A 0
#define HOUSTON_REV_B 1
static int houston_Rev(void);
static int houston_init(void);
static unsigned char PLAL_FS450_i2c_address(void);
static int PLAL_FS450_UIM_mode(void);
static int PLAL_ReadRegister(S_REG_INFO * p_reg);
static int PLAL_WriteRegister(const S_REG_INFO * p_reg);
static int PLAL_IsTVOn(void);
static int PLAL_EnableVga(void);
static int PLAL_PrepForTVout(void);
static int PLAL_SetTVTimingRegisters(const S_TIMING_SPECS * p_specs);
static int PLAL_FinalEnableTVout(unsigned long vga_mode);
static int
DMAL_ReadUInt32(unsigned long phys_addr, unsigned long *p_data)
{
*p_data = READ_REG32(phys_addr);
return 0;
}
static int
DMAL_WriteUInt32(unsigned long phys_addr, unsigned long data)
{
WRITE_REG32(phys_addr, data);
return 0;
}
static int
houston_ReadReg(unsigned int reg, unsigned long *p_value, unsigned int bytes)
{
return gfx_i2c_read(1, PLAL_FS450_i2c_address(), (unsigned char)reg,
(unsigned char)bytes, (unsigned char *)p_value);
}
static int
houston_WriteReg(unsigned int reg, unsigned long value, unsigned int bytes)
{
return gfx_i2c_write(1, PLAL_FS450_i2c_address(), (unsigned char)reg,
(unsigned char)bytes, (unsigned char *)&value);
}
static int config_init(void);
static const S_TIMING_SPECS *p_specs(void);
static void config_power(int on);
static void config_vga_mode(unsigned long vga_mode);
static void config_tv_std(unsigned long tv_std, unsigned int trigger_bits);
static void conget_tv_std(unsigned long *p_tv_std);
static unsigned long supported_standards(void);
static void config_tvout_mode(unsigned long tvout_mode);
static void conget_tvout_mode(unsigned long *p_tvout_mode);
static void config_overscan_xy(unsigned long tv_std, unsigned long vga_mode,
int overscan_x, int overscan_y, int pos_x,
int pos_y);
static void config_nco(unsigned long tv_std, unsigned long vga_mode);
static void config_sharpness(int sharpness);
static void conget_sharpness(int *p_sharpness);
static void config_flicker(int flicker);
static void conget_flicker(int *p_flicker);
static void config_color(int color);
static void conget_color(int *p_color);
static void config_brightness_contrast(unsigned long tv_std,
unsigned int trigger_bits,
int brightness, int contrast);
static void conget_brightness_contrast(unsigned long tv_std,
unsigned int trigger_bits,
int *p_brightness, int *p_contrast);
static void config_yc_filter(unsigned long tv_std, int luma_filter,
int chroma_filter);
static void conget_yc_filter(int *p_luma_filter, int *p_chroma_filter);
static void config_macrovision(unsigned long tv_std,
unsigned int cp_trigger_bits);
static void conget_macrovision(unsigned long tv_std,
unsigned int *p_cp_trigger_bits);
typedef struct _S_DEVICE_SETTINGS
{
int tv_on;
unsigned long vga_mode;
unsigned long tv_std;
unsigned long tvout_mode;
int overscan_x;
int overscan_y;
int position_x;
int position_y;
int sharpness;
int flicker;
int color;
int brightness;
int contrast;
unsigned char yc_filter;
unsigned int aps_trigger_bits;
int last_overscan_y;
}
S_DEVICE_SETTINGS;
static S_DEVICE_SETTINGS d;
static const struct
{
unsigned long chroma_freq[5];
unsigned short chroma_phase[5];
unsigned short cphase_rst[5];
unsigned short color[5];
unsigned short cr_burst_level[5];
unsigned short cb_burst_level[5];
unsigned short sys625_50[5];
unsigned short vsync5[5];
unsigned short pal_mode[5];
unsigned short hsync_width[5];
unsigned short burst_width[5];
unsigned short back_porch[5];
unsigned short front_porch[5];
unsigned short breeze_way[5];
unsigned short activeline[5];
unsigned short blank_level[5];
unsigned short vbi_blank_level[5];
unsigned short black_level[5];
unsigned short white_level[5];
unsigned short hamp_offset[5];
unsigned short sync_level[5];
unsigned short tv_lines[5];
unsigned short tv_width[5];
unsigned short tv_active_lines[5];
unsigned short tv_active_width[5];
unsigned char notch_filter[5];
unsigned short houston_cr[5];
unsigned short houston_ncodl[5];
unsigned short houston_ncodh[5];
}
tvsetup =
{
{
0x1f7cf021, 0xcb8a092a, 0x1f7cf021, 0xe3efe621, 0xcb8a092a}
,
{
0, 0, 0, 0, 0}
,
{
2, 0, 2, 0, 0}
,
{
54, 43, 54, 43, 43}
,
{
0, 31, 0, 29, 29}
,
{
59, 44, 59, 41, 41}
,
{
0, 1, 0, 0, 1}
,
{
0, 1, 0, 0, 0}
,
{
0, 1, 0, 1, 1}
,
{
0x7a, 0x7a, 0x7a, 0x7a, 0x7a}
,
{
0x40, 0x3c, 0x40, 0x40, 0x3c}
,
{
0x80, 0x9a, 0x80, 0x80, 0x9a}
,
{
0x24, 0x1e, 0x24, 0x24, 0x1e}
,
{
0x19, 0x1a, 0x19, 0x12, 0x1a}
,
{
0xb4, 0xb4, 0xb4, 0xb4, 0xb4}
,
{
240, 251, 240, 240, 240}
,
{
240, 251, 240, 240, 240}
,
{
284, 252, 240, 252, 252}
,
{
823, 821, 823, 821, 821}
,
{
60, 48, 60, 48, 48}
,
{
0x08, 0x08, 0x08, 0x08, 0x08}
,
{
525, 625, 525, 525, 625}
,
{
858, 864, 858, 858, 864}
,
{
487, 576, 487, 487, 576}
,
{
800, 800, 800, 800, 800}
,
{
0x1a, 0x1d, 0x1a, 0x1d, 0x1d}
,
{
0x0000, 0x0100, 0x0000, 0x0000, 0x0100}
,
{
0x7e48, 0xf580, 0x7e48, 0x7e48, 0xf580}
,
{
0x001b, 0x0020, 0x001b, 0x001b, 0x0020}
};
#define SCANTABLE_ENTRIES 5
struct _scantable
{
unsigned long mode;
unsigned short v_total[5];
unsigned short v_sync[5];
unsigned short iha[5];
signed short iho[5];
signed short hsc[5];
};
static struct _scantable scantable[SCANTABLE_ENTRIES] = {
{
GFX_VGA_MODE_640X480,
{617, 624, 617, 624, 624},
{69, 88, 69, 88, 88},
{720, 720, 720, 720, 720},
{0, 0, 0, 0, 0},
{-12, 0, -6, 0, 0}
},
{
GFX_VGA_MODE_800X600,
{740, 740, 740, 740, 740},
{90, 88, 90, 88, 88},
{720, 720, 508, 720, 720},
{-8, 11, -8, -8, 11},
{-27, -27, -27, -27, -27}
},
{
GFX_VGA_MODE_720X487,
{525, 720, 525, 720, 720},
{23, 230, 23, 230, 230},
{720, 720, 720, 720, 720},
{0xa2, 0xa2, 0xa2, 0xa2, 0xa2},
{0, 0, 0, 0, 0}
},
{
GFX_VGA_MODE_720X576,
{720, 625, 720, 625, 625},
{129, 25, 129, 25, 25},
{720, 720, 720, 720, 720},
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
{0, 0, 0, 0, 0}
},
{
GFX_VGA_MODE_1024X768,
{933, 942, 933, 806, 806},
{121, 112, 121, 88, 88},
{600, 600, 600, 600, 600},
{0x3c, 0x23, 0x3c, 0x65, 0x65},
{35, 26, 35, 26, 26}
},
};
struct _ffolat
{
int v_total;
unsigned short ffolat;
};
struct _ffolativo
{
int v_total;
unsigned short ivo;
unsigned short ffolat;
};
#define SIZE6X4NTSC 66
static struct _ffolat ffo6x4ntsc[SIZE6X4NTSC + 1] = {
{541, 0x40}, {545, 0x40}, {549, 0x40}, {553, 0x40},
{557, 0x58}, {561, 0x40}, {565, 0x40}, {569, 0x40},
{573, 0x48}, {577, 0x40}, {581, 0x40}, {585, 0x40},
{589, 0x40}, {593, 0x48}, {597, 0x40}, {601, 0x40},
{605, 0x40}, {609, 0x40}, {613, 0x5b}, {617, 0x48},
{621, 0x60}, {625, 0x48}, {629, 0x48}, {633, 0x40},
{637, 0x5e}, {641, 0x40}, {645, 0x50}, {649, 0x56},
{653, 0x58}, {657, 0x6c}, {661, 0x40}, {665, 0x40},
{669, 0x40}, {673, 0x40}, {677, 0x40}, {681, 0x40},
{685, 0x40}, {689, 0x40}, {693, 0x40}, {697, 0x40},
{701, 0x40}, {705, 0x40}, {709, 0x40}, {713, 0x40},
{717, 0x40}, {721, 0x40}, {725, 0x40}, {729, 0x40},
{733, 0x40}, {737, 0x40}, {741, 0x40}, {745, 0x40},
{749, 0x40}, {753, 0x40}, {757, 0x40}, {761, 0x40},
{765, 0x40}, {769, 0x40}, {773, 0x40}, {777, 0x40},
{781, 0x40}, {785, 0x40}, {789, 0x40}, {793, 0x40},
{797, 0x30}, {801, 0x40},
{-1, 0}
};
#define SIZE6X4PAL 45
static struct _ffolat ffo6x4pal[SIZE6X4PAL + 1] = {
{625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60},
{641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60},
{657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60},
{673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60},
{689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60},
{705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60},
{721, 0x60}, {725, 0x60}, {729, 0x60}, {733, 0x60},
{737, 0x60}, {741, 0x60}, {745, 0x60}, {749, 0x60},
{753, 0x60}, {757, 0x60}, {761, 0x60}, {765, 0x60},
{769, 0x60}, {773, 0x60}, {777, 0x60}, {781, 0x60},
{785, 0x60}, {789, 0x60}, {793, 0x60}, {797, 0x60},
{801, 0x60},
{-1, 0}
};
#define SIZE7X4NTSC 40
static struct _ffolat ffo7x4ntsc[SIZE7X4NTSC + 1] = {
{525, 0x52}, {529, 0x52}, {533, 0x52}, {537, 0x52},
{541, 0x52}, {545, 0x40}, {549, 0x40}, {553, 0x40},
{557, 0x58}, {561, 0x40}, {565, 0x58}, {569, 0x40},
{573, 0x48}, {577, 0x40}, {581, 0x40}, {585, 0x40},
{589, 0x40}, {593, 0x48}, {597, 0x40}, {601, 0x40},
{605, 0x40}, {609, 0x40}, {613, 0x5b}, {617, 0x48},
{621, 0x60}, {625, 0x48}, {629, 0x48}, {633, 0x40},
{637, 0x5e}, {641, 0x40}, {645, 0x50}, {649, 0x56},
{653, 0x58}, {657, 0x6c}, {661, 0x40}, {665, 0x40},
{669, 0x40}, {673, 0x40}, {677, 0x40}, {681, 0x40},
{-1, 0}
};
#define SIZE7X4PAL 24
static struct _ffolat ffo7x4pal[SIZE7X4PAL + 1] = {
{625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60},
{641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60},
{657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60},
{673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60},
{689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60},
{705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60},
{-1, 0}
};
#define SIZE7X5NTSC 54
static struct _ffolat ffo7x5ntsc[SIZE7X5NTSC + 1] = {
{590, 0x40}, {594, 0x48}, {598, 0x40}, {602, 0x40},
{606, 0x40}, {610, 0x40}, {614, 0x5b}, {618, 0x48},
{622, 0x60}, {626, 0x48}, {630, 0x48}, {634, 0x40},
{638, 0x5e}, {642, 0x40}, {646, 0x50}, {650, 0x56},
{654, 0x58}, {658, 0x6c}, {662, 0x40}, {666, 0x40},
{670, 0x40}, {674, 0x40}, {678, 0x40}, {682, 0x40},
{686, 0x40}, {690, 0x40}, {694, 0x40}, {698, 0x40},
{702, 0x40}, {706, 0x40}, {710, 0x40}, {714, 0x40},
{718, 0x40}, {722, 0x40}, {726, 0x40}, {730, 0x40},
{734, 0x40}, {738, 0x40}, {742, 0x40}, {746, 0x40},
{750, 0x40}, {754, 0x40}, {758, 0x40}, {762, 0x40},
{766, 0x40}, {770, 0x40}, {774, 0x40}, {778, 0x40},
{782, 0x40}, {786, 0x40}, {790, 0x40}, {794, 0x40},
{798, 0x30}, {802, 0x40},
{-1, 0}
};
#define SIZE7X5PAL 45
static struct _ffolat ffo7x5pal[SIZE7X5PAL + 1] = {
{625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60},
{641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60},
{657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60},
{673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60},
{689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60},
{705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60},
{721, 0x60}, {725, 0x60}, {729, 0x60}, {733, 0x60},
{737, 0x60}, {741, 0x60}, {745, 0x60}, {749, 0x60},
{753, 0x60}, {757, 0x60}, {761, 0x60}, {765, 0x60},
{769, 0x60}, {773, 0x60}, {777, 0x60}, {781, 0x60},
{785, 0x60}, {789, 0x60}, {793, 0x60}, {797, 0x60},
{801, 0x60},
{-1, 0}
};
#define SIZE8X6NTSC 37
static struct _ffolat ffo8x6ntsc[SIZE8X6NTSC + 1] = {
{620, 0x40},
{625, 0x58}, {630, 0x40}, {635, 0x40}, {640, 0x40},
{645, 0x46}, {650, 0x46}, {655, 0x4f}, {660, 0x4c},
{665, 0x4a}, {670, 0x50}, {675, 0x2f}, {680, 0x48},
{685, 0x38}, {690, 0x31}, {695, 0x40}, {700, 0x21},
{705, 0x25}, {710, 0x40}, {715, 0x48}, {720, 0x50},
{725, 0x30}, {730, 0x50}, {735, 0x50}, {740, 0x50},
{745, 0x40}, {750, 0x38}, {755, 0x50}, {760, 0x50},
{765, 0x40}, {770, 0x38}, {775, 0x40}, {780, 0x40},
{785, 0x40}, {790, 0x38}, {795, 0x50}, {800, 0x50},
{-1, 0}
};
#define SIZE8X6PAL 36
static struct _ffolat ffo8x6pal[SIZE8X6PAL + 1] = {
{625, 0x80}, {630, 0x80}, {635, 0x5a}, {640, 0x55},
{645, 0x48}, {650, 0x65}, {655, 0x65}, {660, 0x50},
{665, 0x80}, {670, 0x70}, {675, 0x56}, {680, 0x80},
{685, 0x58}, {690, 0x31}, {695, 0x80}, {700, 0x60},
{705, 0x45}, {710, 0x4a}, {715, 0x50}, {720, 0x50},
{725, 0x50}, {730, 0x45}, {735, 0x50}, {740, 0x50},
{745, 0x50}, {750, 0x50}, {755, 0x50}, {760, 0x50},
{765, 0x50}, {770, 0x50}, {775, 0x50}, {780, 0x50},
{785, 0x50}, {790, 0x50}, {795, 0x50}, {800, 0x50},
{-1, 0}
};
#define SIZE10X7NTSC 45
static struct _ffolativo ffo10x7ntsc[SIZE10X7NTSC] = {
{783, 0x4d, 0x40},
{789, 0x47, 0x14},
{795, 0x47, 0x7f},
{801, 0x47, 0x53},
{807, 0x47, 0x11},
{813, 0x47, 0x78},
{819, 0x47, 0x54},
{825, 0x47, 0x40},
{831, 0x47, 0x0f},
{837, 0x4d, 0x40},
{843, 0x47, 0x5a},
{849, 0x4d, 0x40},
{855, 0x47, 0x4b},
{861, 0x4d, 0x40},
{867, 0x47, 0x4b},
{873, 0x4d, 0x40},
{879, 0x47, 0x07},
{885, 0x48, 0x20},
{891, 0x47, 0x82},
{897, 0x47, 0x60},
{903, 0x47, 0x7f},
{909, 0x4d, 0x40},
{915, 0x48, 0x40},
{921, 0x4c, 0x40},
{927, 0x49, 0x40},
{933, 0x48, 0x40},
{939, 0x4a, 0x40},
{945, 0x46, 0x40},
{951, 0x4a, 0x40},
{957, 0x4a, 0x40},
{963, 0x4b, 0x40},
{969, 0x4b, 0x40},
{975, 0x48, 0x40},
{981, 0x47, 0x40},
{987, 0x47, 0x40},
{993, 0x47, 0x40},
{999, 0x48, 0x40},
{1005, 0x48, 0x40},
{1011, 0x47, 0x40},
{1017, 0x47, 0x40},
{1023, 0x48, 0x40},
{1029, 0x48, 0x40},
{1035, 0x46, 0x40},
{1041, 0x47, 0x40},
{1047, 0x47, 0x40}
};
#define SIZE10X7PAL 46
static struct _ffolativo ffo10x7pal[SIZE10X7PAL] = {
{781, 0x49, 0x40},
{787, 0x46, 0x40},
{793, 0x48, 0x40},
{799, 0x46, 0x40},
{805, 0x49, 0x40},
{811, 0x47, 0x40},
{817, 0x46, 0x40},
{823, 0x46, 0x56},
{829, 0x46, 0x2d},
{835, 0x46, 0x40},
{841, 0x46, 0x2d},
{847, 0x46, 0x3f},
{853, 0x46, 0x10},
{859, 0x46, 0x86},
{865, 0x46, 0xc9},
{871, 0x46, 0x83},
{877, 0x46, 0xa8},
{883, 0x46, 0x81},
{889, 0x46, 0xa5},
{895, 0x46, 0xa9},
{901, 0x46, 0x81},
{907, 0x46, 0xa4},
{913, 0x46, 0xa5},
{919, 0x46, 0x7f},
{925, 0x46, 0xa2},
{931, 0x46, 0x9d},
{937, 0x46, 0xc1},
{943, 0x46, 0x96},
{949, 0x46, 0xb7},
{955, 0x46, 0xb1},
{961, 0x46, 0x8a},
{967, 0x46, 0xa9},
{973, 0x46, 0xa0},
{979, 0x46, 0x40},
{985, 0x46, 0x97},
{991, 0x46, 0xb5},
{997, 0x46, 0xaa},
{1003, 0x46, 0x83},
{1009, 0x46, 0x9f},
{1015, 0x47, 0x40},
{1021, 0x46, 0xad},
{1027, 0x46, 0x87},
{1033, 0x46, 0xa2},
{1039, 0x47, 0x40},
{1045, 0x46, 0xac},
{1051, 0x46, 0x86}
};
static void
initialize_houston_static_registers(void)
{
houston_WriteReg(HOUSTON_BYP, 0, 2);
houston_WriteReg(HOUSTON_APO, 0, 2);
houston_WriteReg(HOUSTON_ALO, 0, 2);
houston_WriteReg(HOUSTON_AFO, 0, 2);
houston_WriteReg(HOUSTON_BCONTL, 0, 2);
houston_WriteReg(HOUSTON_BCONTH, 0, 2);
houston_WriteReg(HOUSTON_BDONE, 0, 2);
houston_WriteReg(HOUSTON_BDIAGL, 0, 2);
houston_WriteReg(HOUSTON_BDIAGH, 0, 2);
houston_WriteReg(HOUSTON_MISC, 0, 2);
}
int
FS450_init(void)
{
int err;
TRACE(("FS450_Init()\n"))
err = houston_init();
if (err)
return err;
initialize_houston_static_registers();
#if 1
d.tv_on = PLAL_IsTVOn()? 1 : 0;
#else
d.tv_on = 0;
#endif
#if 1
conget_tv_std(&d.tv_std);
#else
d.tv_std = VP_TV_STANDARD_NTSC_M;
config_tv_std(d.tv_std);
#endif
d.vga_mode = 0;
#if 0
conget_tvout_mode(&d.tvout_mode);
#else
d.tvout_mode = GFX_TVOUT_MODE_CVBS_YC;
#endif
#if 0
conget_sharpness(d.sharpness);
#else
d.sharpness = 1000;
config_sharpness(d.sharpness);
#endif
#if 0
conget_flicker(d.flicker);
#else
d.flicker = 800;
config_flicker(d.flicker);
#endif
#if 0
#else
d.overscan_x = 0;
d.overscan_y = 0;
d.position_x = 0;
d.position_y = 0;
#endif
#if 0
conget_color(d.color);
#else
d.color = 50;
config_color(d.color);
#endif
#if 0
conget_brightness_contrast(d.tv_std, d.aps_trigger_bits, d.brightness,
d.contrast);
#else
d.brightness = 50;
d.contrast = 60;
config_brightness_contrast(d.tv_std, d.aps_trigger_bits, d.brightness,
d.contrast);
#endif
#if 1
{
int luma_filter, chroma_filter;
conget_yc_filter(&luma_filter, &chroma_filter);
d.yc_filter = 0;
if (luma_filter)
d.yc_filter |= GFX_LUMA_FILTER;
if (chroma_filter)
d.yc_filter |= GFX_CHROMA_FILTER;
}
#else
d.yc_filter = GFX_LUMA_FILTER + GFX_CHROMA_FILTER;
#endif
#if 0
conget_macrovision(d.tv_std, &d.aps_trigger_bits);
#else
d.aps_trigger_bits = 0;
config_macrovision(d.tv_std, d.aps_trigger_bits);
#endif
d.last_overscan_y = -10000;
return 0;
}
void
FS450_cleanup(void)
{
}
#define REQ_TV_STANDARD_BIT 0x0002
#define REQ_VGA_MODE_BIT 0x0004
#define REQ_TVOUT_MODE_BIT 0x0008
#define REQ_SHARPNESS_BIT 0x0010
#define REQ_FLICKER_BIT 0x0020
#define REQ_OVERSCAN_POSITION_BIT 0x0040
#define REQ_COLOR_BIT 0x0080
#define REQ_BRIGHTNESS_CONTRAST_BIT 0x0100
#define REQ_YC_FILTER_BIT 0x0200
#define REQ_MACROVISION_BIT 0x0400
#define REQ_NCO_BIT 0x1000
#define REQ_TV_STANDARD (REQ_TV_STANDARD_BIT | REQ_OVERSCAN_POSITION | REQ_BRIGHTNESS_CONTRAST | REQ_MACROVISION_BIT | REQ_YC_FILTER)
#define REQ_VGA_MODE (REQ_VGA_MODE_BIT | REQ_OVERSCAN_POSITION)
#define REQ_TVOUT_MODE (REQ_TVOUT_MODE_BIT)
#define REQ_SHARPNESS (REQ_SHARPNESS_BIT)
#define REQ_FLICKER (REQ_FLICKER_BIT)
#define REQ_OVERSCAN_POSITION (REQ_OVERSCAN_POSITION_BIT | REQ_NCO)
#define REQ_COLOR (REQ_COLOR_BIT)
#define REQ_BRIGHTNESS_CONTRAST (REQ_BRIGHTNESS_CONTRAST_BIT)
#define REQ_YC_FILTER (REQ_YC_FILTER_BIT)
#define REQ_MACROVISION (REQ_TV_STANDARD_BIT | REQ_BRIGHTNESS_CONTRAST_BIT | REQ_MACROVISION_BIT)
#define REQ_NCO (REQ_NCO_BIT)
#define REQ_ENCODER (REQ_TV_STANDARD | REQ_COLOR | REQ_BRIGHTNESS_CONTRAST | REQ_YC_FILTER)
static int
write_config(int req)
{
unsigned long reg, reg_encoder_reset = 0;
int reset;
reset = ((REQ_NCO_BIT & req) && (d.overscan_y != d.last_overscan_y));
if (reset) {
houston_ReadReg(ENC_RESET, ®, 1);
houston_WriteReg(ENC_RESET, reg | 0x01, 1);
reg_encoder_reset = reg & 0x01;
}
if (REQ_TV_STANDARD_BIT & req)
config_tv_std(d.tv_std, d.aps_trigger_bits);
if (REQ_VGA_MODE_BIT & req)
config_vga_mode(d.vga_mode);
if (REQ_TVOUT_MODE_BIT & req)
config_tvout_mode(d.tvout_mode);
if (REQ_OVERSCAN_POSITION_BIT & req) {
config_overscan_xy(d.tv_std,
d.vga_mode,
d.overscan_x,
d.overscan_y, d.position_x, d.position_y);
if (PLAL_IsTVOn())
PLAL_SetTVTimingRegisters(p_specs());
}
if (REQ_NCO_BIT & req)
config_nco(d.tv_std, d.vga_mode);
if (REQ_SHARPNESS_BIT & req)
config_sharpness(d.sharpness);
if (REQ_FLICKER_BIT & req)
config_flicker(d.flicker);
if (REQ_COLOR_BIT & req)
config_color(d.color);
if (REQ_BRIGHTNESS_CONTRAST_BIT & req) {
config_brightness_contrast(d.tv_std,
d.aps_trigger_bits,
d.brightness, d.contrast);
}
if (REQ_YC_FILTER_BIT & req) {
config_yc_filter(d.tv_std,
(d.yc_filter & GFX_LUMA_FILTER),
(d.yc_filter & GFX_CHROMA_FILTER));
}
if (REQ_MACROVISION_BIT & req)
config_macrovision(d.tv_std, d.aps_trigger_bits);
if (reset) {
houston_ReadReg(ENC_RESET, ®, 1);
houston_WriteReg(ENC_RESET, reg_encoder_reset | (reg & ~0x01), 1);
d.last_overscan_y = d.overscan_y;
}
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_get_tv_enable(unsigned int *p_on)
#else
int
gfx_get_tv_enable(unsigned int *p_on)
#endif
{
if (!p_on)
return ERR_INVALID_PARAMETER;
*p_on = d.tv_on;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_enable(int on)
#else
int
gfx_set_tv_enable(int on)
#endif
{
unsigned long reg;
if ((d.tv_on && on) || (!d.tv_on && !on))
return 0;
if (!on) {
PLAL_EnableVga();
config_power(0);
d.tv_on = 0;
return 0;
}
config_power(1);
houston_WriteReg(ENC_RESET, 0x01, 1);
PLAL_PrepForTVout();
write_config(REQ_VGA_MODE |
REQ_TV_STANDARD |
REQ_TVOUT_MODE |
REQ_OVERSCAN_POSITION | REQ_YC_FILTER | REQ_MACROVISION);
houston_ReadReg(HOUSTON_CR, ®, 2);
reg |= CR_LP_EN;
reg &= ~(CR_UIM_MOD0 | CR_UIM_MOD1);
reg |= (PLAL_FS450_UIM_mode() << 14);
houston_WriteReg(HOUSTON_CR, reg, 2);
PLAL_SetTVTimingRegisters(p_specs());
PLAL_FinalEnableTVout(d.vga_mode);
{
int retry_count = 0;
while (retry_count++ < 50) {
houston_ReadReg(HOUSTON_MISC, ®, 2);
reg |= MISC_BRIDGE_SYNC;
houston_WriteReg(HOUSTON_MISC, reg, 2);
reg &= ~MISC_BRIDGE_SYNC;
houston_WriteReg(HOUSTON_MISC, reg, 2);
}
}
houston_WriteReg(ENC_RESET, 0x00, 1);
d.tv_on = 1;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_defaults(int format)
#else
int
gfx_set_tv_defaults(int format)
#endif
{
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_get_tv_standard(unsigned long *p_standard)
#else
int
gfx_get_tv_standard(unsigned long *p_standard)
#endif
{
if (!p_standard)
return ERR_INVALID_PARAMETER;
*p_standard = d.tv_std;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_get_available_tv_standards(unsigned long *p_standards)
#else
int
gfx_get_available_tv_standards(unsigned long *p_standards)
#endif
{
if (!p_standards)
return ERR_INVALID_PARAMETER;
*p_standards = supported_standards();
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_standard(unsigned long standard)
#else
int
gfx_set_tv_standard(unsigned long standard)
#endif
{
if (!(standard & supported_standards()))
return ERR_INVALID_PARAMETER;
if (d.tv_on)
return ERR_CANNOT_CHANGE_WHILE_TV_ON;
d.tv_std = standard;
return write_config(REQ_TV_STANDARD);
}
#if GFX_TV_DYNAMIC
int
fs450_get_tv_vga_mode(unsigned long *p_vga_mode)
#else
int
gfx_get_tv_vga_mode(unsigned long *p_vga_mode)
#endif
{
if (!p_vga_mode)
return ERR_INVALID_PARAMETER;
*p_vga_mode = d.vga_mode;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_get_available_tv_vga_modes(unsigned long *p_vga_modes)
#else
int
gfx_get_available_tv_vga_modes(unsigned long *p_vga_modes)
#endif
{
if (!p_vga_modes)
return ERR_INVALID_PARAMETER;
*p_vga_modes =
GFX_VGA_MODE_640X480 |
GFX_VGA_MODE_720X487 | GFX_VGA_MODE_720X576 | GFX_VGA_MODE_800X600;
if (houston_Rev() >= HOUSTON_REV_B)
*p_vga_modes |= GFX_VGA_MODE_1024X768;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_vga_mode(unsigned long vga_mode)
#else
int
gfx_set_tv_vga_mode(unsigned long vga_mode)
#endif
{
switch (vga_mode) {
default:
return ERR_INVALID_PARAMETER;
case GFX_VGA_MODE_640X480:
case GFX_VGA_MODE_720X487:
case GFX_VGA_MODE_720X576:
case GFX_VGA_MODE_800X600:
break;
case GFX_VGA_MODE_1024X768:
if (houston_Rev() >= HOUSTON_REV_B)
break;
return ERR_INVALID_PARAMETER;
}
if (vga_mode != d.vga_mode) {
d.vga_mode = vga_mode;
return write_config(REQ_VGA_MODE);
}
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_get_tvout_mode(unsigned long *p_tvout_mode)
#else
int
gfx_get_tvout_mode(unsigned long *p_tvout_mode)
#endif
{
if (!p_tvout_mode)
return ERR_INVALID_PARAMETER;
*p_tvout_mode = d.tvout_mode;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_tvout_mode(unsigned long tvout_mode)
#else
int
gfx_set_tvout_mode(unsigned long tvout_mode)
#endif
{
d.tvout_mode = tvout_mode;
return write_config(REQ_TVOUT_MODE);
}
#if GFX_TV_DYNAMIC
int
fs450_get_sharpness(int *p_sharpness)
#else
int
gfx_get_sharpness(int *p_sharpness)
#endif
{
if (!p_sharpness)
return ERR_INVALID_PARAMETER;
*p_sharpness = d.sharpness;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_sharpness(int sharpness)
#else
int
gfx_set_sharpness(int sharpness)
#endif
{
d.sharpness = range_limit(sharpness, 0, 1000);
return write_config(REQ_SHARPNESS);
}
#if GFX_TV_DYNAMIC
int
fs450_get_flicker_filter(int *p_flicker)
#else
int
gfx_get_flicker_filter(int *p_flicker)
#endif
{
if (!p_flicker)
return ERR_INVALID_PARAMETER;
*p_flicker = d.flicker;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_flicker_filter(int flicker)
#else
int
gfx_set_flicker_filter(int flicker)
#endif
{
d.flicker = range_limit(flicker, 0, 1000);
return write_config(REQ_FLICKER);
}
#if GFX_TV_DYNAMIC
int
fs450_get_overscan(int *p_x, int *p_y)
#else
int
gfx_get_overscan(int *p_x, int *p_y)
#endif
{
if (!p_x || !p_y)
return ERR_INVALID_PARAMETER;
*p_x = d.overscan_x;
*p_y = d.overscan_y;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_overscan(int x, int y)
#else
int
gfx_set_overscan(int x, int y)
#endif
{
d.overscan_x = range_limit(x, -1000, 1000);
d.overscan_y = range_limit(y, -1000, 1000);
return write_config(REQ_OVERSCAN_POSITION);
}
#if GFX_TV_DYNAMIC
int
fs450_get_position(int *p_x, int *p_y)
#else
int
gfx_get_position(int *p_x, int *p_y)
#endif
{
if (!p_x || !p_y)
return ERR_INVALID_PARAMETER;
*p_x = d.position_x;
*p_y = d.position_y;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_position(int x, int y)
#else
int
gfx_set_position(int x, int y)
#endif
{
d.position_x = range_limit(x, -1000, 1000);
d.position_y = range_limit(y, -1000, 1000);
return write_config(REQ_OVERSCAN_POSITION);
}
#if GFX_TV_DYNAMIC
int
fs450_get_color(int *p_color)
#else
int
gfx_get_color(int *p_color)
#endif
{
if (!p_color)
return ERR_INVALID_PARAMETER;
*p_color = d.color;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_color(int color)
#else
int
gfx_set_color(int color)
#endif
{
d.color = range_limit(color, 0, 100);
return write_config(REQ_COLOR);
}
#if GFX_TV_DYNAMIC
int
fs450_get_brightness(int *p_brightness)
#else
int
gfx_get_brightness(int *p_brightness)
#endif
{
if (!p_brightness)
return ERR_INVALID_PARAMETER;
*p_brightness = d.brightness;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_brightness(int brightness)
#else
int
gfx_set_brightness(int brightness)
#endif
{
d.brightness = range_limit(brightness, 0, 100);
return write_config(REQ_BRIGHTNESS_CONTRAST);
}
#if GFX_TV_DYNAMIC
int
fs450_get_contrast(int *p_contrast)
#else
int
gfx_get_contrast(int *p_contrast)
#endif
{
if (!p_contrast)
return ERR_INVALID_PARAMETER;
*p_contrast = d.contrast;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_contrast(int constrast)
#else
int
gfx_set_contrast(int constrast)
#endif
{
d.contrast = range_limit(constrast, 0, 100);
return write_config(REQ_BRIGHTNESS_CONTRAST);
}
#if GFX_TV_DYNAMIC
int
fs450_get_yc_filter(unsigned int *p_yc_filter)
#else
int
gfx_get_yc_filter(unsigned int *p_yc_filter)
#endif
{
if (!p_yc_filter)
return ERR_INVALID_PARAMETER;
if (houston_Rev() < HOUSTON_REV_B)
return ERR_NOT_SUPPORTED;
*p_yc_filter = d.yc_filter;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_yc_filter(unsigned int yc_filter)
#else
int
gfx_set_yc_filter(unsigned int yc_filter)
#endif
{
if (houston_Rev() < HOUSTON_REV_B)
return ERR_NOT_SUPPORTED;
if (yc_filter & GFX_LUMA_FILTER)
d.yc_filter |= GFX_LUMA_FILTER;
else
d.yc_filter &= ~GFX_LUMA_FILTER;
if (yc_filter & GFX_CHROMA_FILTER)
d.yc_filter |= GFX_CHROMA_FILTER;
else
d.yc_filter &= ~GFX_CHROMA_FILTER;
return write_config(REQ_YC_FILTER);
}
#if GFX_TV_DYNAMIC
int
fs450_get_aps_trigger_bits(unsigned int *p_trigger_bits)
#else
int
gfx_get_aps_trigger_bits(unsigned int *p_trigger_bits)
#endif
{
if (!p_trigger_bits)
return ERR_INVALID_PARAMETER;
*p_trigger_bits = d.aps_trigger_bits;
return 0;
}
#if GFX_TV_DYNAMIC
int
fs450_set_aps_trigger_bits(unsigned int trigger_bits)
#else
int
gfx_set_aps_trigger_bits(unsigned int trigger_bits)
#endif
{
d.aps_trigger_bits = trigger_bits;
return write_config(REQ_MACROVISION);
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_format(TVStandardType format, GfxOnTVType resolution)
#else
int
gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution)
#endif
{
return (0);
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_output(int output)
#else
int
gfx_set_tv_output(int output)
#endif
{
return (0);
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_cc_enable(int enable)
#else
int
gfx_set_tv_cc_enable(int enable)
#endif
{
return (0);
}
#if GFX_TV_DYNAMIC
int
fs450_set_tv_cc_data(unsigned char data1, unsigned char data2)
#else
int
gfx_set_tv_cc_data(unsigned char data1, unsigned char data2)
#endif
{
return (0);
}
#ifdef FS450_DIRECTREG
int
FS450_ReadRegister(S_REG_INFO * p_reg)
{
unsigned long tmp;
if (PLAL_ReadRegister(p_reg))
return 0;
if (SOURCE_HOUSTON == p_reg->source) {
switch (p_reg->size) {
case 1:
case 2:
{
houston_ReadReg((int)p_reg->offset, &tmp, (int)p_reg->size);
p_reg->value = tmp;
}
return 0;
case 4:
{
houston_ReadReg((unsigned int)p_reg->offset, &tmp, 2);
p_reg->value = (tmp << 16);
houston_ReadReg((unsigned int)(p_reg->offset + 2), &tmp, 2);
p_reg->value |= tmp;
}
return 0;
}
}
return ERR_INVALID_PARAMETER;
}
int
FS450_WriteRegister(S_REG_INFO * p_reg)
{
if (PLAL_WriteRegister(p_reg))
return 0;
if (SOURCE_HOUSTON == p_reg->source) {
houston_WriteReg((unsigned int)p_reg->offset, p_reg->value,
p_reg->size);
return 0;
}
return ERR_INVALID_PARAMETER;
}
#endif
static int g_houston_rev = -1;
static int
houston_init(void)
{
unsigned long write, read;
TRACE(("houston_init()\n"))
read = READ_VID32(CS5530_DISPLAY_CONFIG);
read |= CS5530_DCFG_FP_PWR_EN | CS5530_DCFG_FP_DATA_EN;
WRITE_VID32(CS5530_DISPLAY_CONFIG, read);
write = 0x0055;
read = 0;
houston_WriteReg(HOUSTON_IHO, write, 2);
houston_ReadReg(HOUSTON_IHO, &read, 2);
if (read != write) {
houston_WriteReg(HOUSTON_IHO, write, 2);
houston_ReadReg(HOUSTON_IHO, &read, 2);
if (read != write) {
TRACE(("wrote HOUSTON_IHO=0x0055, read 0x%04x\n", read))
return ERR_DEVICE_NOT_FOUND;
}
}
houston_ReadReg(HOUSTON_REV, &read, 2);
g_houston_rev = (int)read;
return 0;
}
static int
houston_Rev(void)
{
return g_houston_rev;
}
static S_TIMING_SPECS g_specs;
static const S_TIMING_SPECS *
p_specs(void)
{
return &g_specs;
}
static int
config_init(void)
{
int err;
TRACE(("config_init()\n"))
err = houston_init();
if (err)
return err;
return 0;
}
static unsigned short
w10bit2z(unsigned short w)
{
return (w >> 2) | ((w & 0x03) << 8);
}
static unsigned short
z2w10bit(unsigned short z)
{
return (0x03 & (z >> 8)) | ((0xFF & z) << 2);
}
static const struct
{
unsigned long standard;
int tvsetup_index;
}
g_tv_standards[] =
{
{
GFX_TV_STANDARD_NTSC_M, 0}
, {
GFX_TV_STANDARD_NTSC_M_J, 2}
, {
GFX_TV_STANDARD_PAL_B, 1}
, {
GFX_TV_STANDARD_PAL_D, 1}
, {
GFX_TV_STANDARD_PAL_H, 1}
, {
GFX_TV_STANDARD_PAL_I, 1}
, {
GFX_TV_STANDARD_PAL_M, 3}
, {
GFX_TV_STANDARD_PAL_N, 4}
, {
GFX_TV_STANDARD_PAL_G, 1}
,};
static int
map_tvstd_to_index(unsigned long tv_std)
{
unsigned int i;
for (i = 0; i < sizeof(g_tv_standards) / sizeof(*g_tv_standards); i++) {
if (tv_std == g_tv_standards[i].standard)
return g_tv_standards[i].tvsetup_index;
}
return -1;
}
static unsigned long
supported_standards(void)
{
unsigned long standards = 0;
unsigned int i;
for (i = 0; i < sizeof(g_tv_standards) / sizeof(*g_tv_standards); i++) {
if (g_tv_standards[i].tvsetup_index >= 0)
standards |= g_tv_standards[i].standard;
}
return standards;
}
static void
config_power(int on)
{
unsigned long reg;
if (houston_Rev() < HOUSTON_REV_B) {
if (on) {
houston_ReadReg(HOUSTON_CR, ®, 2);
reg &= ~(CR_CLKOFF | CR_RESET);
houston_WriteReg(HOUSTON_CR, reg, 2);
reg |= CR_RESET;
houston_WriteReg(HOUSTON_CR, reg, 2);
reg &= ~CR_RESET;
houston_WriteReg(HOUSTON_CR, reg, 2);
} else {
houston_ReadReg(HOUSTON_CR, ®, 2);
reg |= CR_CLKOFF;
houston_WriteReg(HOUSTON_CR, reg, 2);
}
return;
}
if (on) {
houston_ReadReg(HOUSTON_CR, ®, 2);
reg &= ~(CR_CLKOFF | CR_RESET | CR_COMPOFF | CR_YCOFF);
houston_WriteReg(HOUSTON_CR, reg, 2);
reg |= CR_RESET;
houston_WriteReg(HOUSTON_CR, reg, 2);
reg &= ~CR_RESET;
houston_WriteReg(HOUSTON_CR, reg, 2);
houston_ReadReg(HOUSTON_MISC, ®, 2);
reg &= ~MISC_GTLIO_PD;
houston_WriteReg(HOUSTON_MISC, reg, 2);
} else {
houston_ReadReg(HOUSTON_CR, ®, 2);
reg |= (CR_CLKOFF | CR_COMPOFF | CR_YCOFF);
houston_WriteReg(HOUSTON_CR, reg, 2);
houston_ReadReg(HOUSTON_MISC, ®, 2);
reg |= MISC_GTLIO_PD;
houston_WriteReg(HOUSTON_MISC, reg, 2);
}
}
static void
config_vga_mode(unsigned long vga_mode)
{
static struct
{
unsigned long mode;
int width;
int lines;
int h_total;
}
vgaparams[] =
{
{
GFX_VGA_MODE_640X480, 640, 480, 1056}
, {
GFX_VGA_MODE_720X487, 720, 487, 1056}
, {
GFX_VGA_MODE_720X576, 720, 576, 1056}
, {
GFX_VGA_MODE_800X600, 800, 600, 1056}
, {
GFX_VGA_MODE_1024X768, 1024, 768, 1344}
,};
unsigned long cr, misc, byp;
unsigned int i;
g_specs.vga_width = 0;
g_specs.vga_lines = 0;
g_specs.h_total = 0;
for (i = 0; i < sizeof(vgaparams) / sizeof(*vgaparams); i++) {
if (vga_mode == vgaparams[i].mode) {
g_specs.vga_width = vgaparams[i].width;
g_specs.vga_lines = vgaparams[i].lines;
g_specs.h_total = vgaparams[i].h_total;
break;
}
}
if (!g_specs.h_total)
return;
houston_ReadReg(HOUSTON_CR, &cr, 2);
houston_ReadReg(HOUSTON_MISC, &misc, 2);
houston_ReadReg(HOUSTON_BYP, &byp, 2);
if (vga_mode == GFX_VGA_MODE_1024X768) {
cr |= CR_UIM_DEC;
misc |= MISC_VGACKDIV;
byp |= (BYP_HDS_BYPASS | BYP_CAC_BYPASS);
} else {
cr &= ~CR_UIM_DEC;
misc &= ~MISC_VGACKDIV;
byp &= ~(BYP_HDS_BYPASS | BYP_CAC_BYPASS);
}
houston_WriteReg(HOUSTON_CR, cr, 2);
houston_WriteReg(HOUSTON_MISC, misc, 2);
houston_WriteReg(HOUSTON_BYP, byp, 2);
}
static void
config_tv_std(unsigned long tv_std, unsigned int trigger_bits)
{
int k;
unsigned short reg34;
unsigned long cr, w;
unsigned long l;
k = map_tvstd_to_index(tv_std);
if (k < 0)
return;
g_specs.tv_width = tvsetup.tv_width[k];
g_specs.tv_lines = tvsetup.tv_lines[k];
houston_ReadReg(HOUSTON_CR, &cr, 2);
cr &= ~CR_656_PAL_NTSC;
cr |= tvsetup.houston_cr[k];
houston_WriteReg(HOUSTON_CR, cr, 2);
l = tvsetup.chroma_freq[k];
houston_WriteReg(ENC_CHROMA_FREQ, (int)(l & 0x00ff), 1);
houston_WriteReg(ENC_CHROMA_FREQ + 1, (int)((l >> 8) & 0x00ff), 1);
houston_WriteReg(ENC_CHROMA_FREQ + 2, (int)((l >> 16) & 0x00ff), 1);
houston_WriteReg(ENC_CHROMA_FREQ + 3, (int)((l >> 24) & 0x00ff), 1);
houston_WriteReg(ENC_CHROMA_PHASE, tvsetup.chroma_phase[k], 1);
houston_WriteReg(ENC_REG05, 0x00, 1);
houston_WriteReg(ENC_REG06, 0x89, 1);
houston_WriteReg(ENC_REG07, 0x00, 1);
houston_WriteReg(ENC_HSYNC_WIDTH, tvsetup.hsync_width[k], 1);
houston_WriteReg(ENC_BURST_WIDTH, tvsetup.burst_width[k], 1);
houston_WriteReg(ENC_BACK_PORCH, tvsetup.back_porch[k], 1);
houston_WriteReg(ENC_CB_BURST_LEVEL, tvsetup.cb_burst_level[k], 1);
houston_WriteReg(ENC_CR_BURST_LEVEL, tvsetup.cr_burst_level[k], 1);
houston_WriteReg(ENC_SLAVE_MODE, 0x01, 1);
if (trigger_bits == 0)
w = w10bit2z(tvsetup.blank_level[k]);
else
w = w10bit2z((unsigned short)(tvsetup.blank_level[k] -
tvsetup.hamp_offset[k]));
houston_WriteReg(ENC_BLANK_LEVEL, w & 0x00ff, 1);
houston_WriteReg(ENC_BLANK_LEVEL + 1, w >> 8, 1);
w = w10bit2z(tvsetup.tv_lines[k]);
houston_WriteReg(ENC_NUM_LINES, w & 0x00ff, 1);
houston_WriteReg(ENC_NUM_LINES + 1, w >> 8, 1);
houston_WriteReg(ENC_TINT, 0x00, 1);
houston_WriteReg(ENC_BREEZE_WAY, tvsetup.breeze_way[k], 1);
houston_WriteReg(ENC_FRONT_PORCH, tvsetup.front_porch[k], 1);
houston_WriteReg(ENC_ACTIVELINE, tvsetup.activeline[k], 1);
houston_WriteReg(ENC_FIRST_LINE, 0x15, 1);
reg34 =
0x80 |
(tvsetup.pal_mode[k] << 6) |
(tvsetup.sys625_50[k] << 3) |
(tvsetup.cphase_rst[k] << 1) | (tvsetup.vsync5[k]);
houston_WriteReg(ENC_REG34, reg34, 1);
houston_WriteReg(ENC_SYNC_LEVEL, tvsetup.sync_level[k], 1);
if (trigger_bits == 0)
w = w10bit2z(tvsetup.vbi_blank_level[k]);
else
w = w10bit2z((unsigned short)(tvsetup.vbi_blank_level[k] - 1));
houston_WriteReg(ENC_VBI_BLANK_LEVEL, w & 0x00ff, 1);
houston_WriteReg(ENC_VBI_BLANK_LEVEL + 1, w >> 8, 1);
}
static void
conget_tv_std(unsigned long *p_tv_standard)
{
unsigned long cr;
if (!p_tv_standard)
return;
houston_ReadReg(HOUSTON_CR, &cr, 2);
if (CR_656_PAL_NTSC & cr)
*p_tv_standard = GFX_TV_STANDARD_PAL_B;
else
*p_tv_standard = GFX_TV_STANDARD_NTSC_M;
}
static void
config_tvout_mode(unsigned long tvout_mode)
{
unsigned long cr;
houston_ReadReg(HOUSTON_CR, &cr, 2);
cr |= (CR_COMPOFF | CR_YCOFF);
cr &= ~CR_OFMT;
if (GFX_TVOUT_MODE_CVBS & tvout_mode)
cr &= ~CR_COMPOFF;
if (GFX_TVOUT_MODE_YC & tvout_mode)
cr &= ~CR_YCOFF;
if (GFX_TVOUT_MODE_RGB & tvout_mode) {
cr &= ~(CR_COMPOFF | CR_YCOFF);
cr |= CR_OFMT;
}
houston_WriteReg(HOUSTON_CR, cr, 2);
}
static void
conget_tvout_mode(unsigned long *p_tvout_mode)
{
unsigned long cr;
if (!p_tvout_mode)
return;
houston_ReadReg(HOUSTON_CR, &cr, 2);
if (CR_OFMT & cr)
*p_tvout_mode = GFX_TVOUT_MODE_RGB;
else {
*p_tvout_mode = 0;
if (!(CR_YCOFF & cr))
*p_tvout_mode |= GFX_TVOUT_MODE_YC;
if (!(CR_COMPOFF & cr))
*p_tvout_mode |= GFX_TVOUT_MODE_CVBS;
}
}
#define IS_NTSC(tv_std) (tv_std & ( \
GFX_TV_STANDARD_NTSC_M | \
GFX_TV_STANDARD_NTSC_M_J | \
GFX_TV_STANDARD_PAL_M))
#define IS_PAL(tv_std) (tv_std & ( \
GFX_TV_STANDARD_PAL_B | \
GFX_TV_STANDARD_PAL_D | \
GFX_TV_STANDARD_PAL_H | \
GFX_TV_STANDARD_PAL_I | \
GFX_TV_STANDARD_PAL_N | \
GFX_TV_STANDARD_PAL_G))
static void
get_ffolat_ivo(unsigned long vga_mode,
unsigned long tv_std,
long i, unsigned short *ffolat, unsigned short *ivo)
{
switch (vga_mode) {
case GFX_VGA_MODE_640X480:
if (IS_NTSC(tv_std)) {
if (i > SIZE6X4NTSC - 1)
i = SIZE6X4NTSC - 1;
*ffolat = ffo6x4ntsc[i].ffolat;
*ivo = 0x20;
} else {
if (i > SIZE6X4PAL - 1)
i = SIZE6X4PAL - 1;
*ffolat = ffo6x4pal[i].ffolat;
*ivo = 0x28;
}
break;
case GFX_VGA_MODE_800X600:
if (IS_NTSC(tv_std)) {
if (i > SIZE8X6NTSC - 1)
i = SIZE8X6NTSC - 1;
*ffolat = ffo8x6ntsc[i].ffolat;
*ivo = 0x3a;
} else {
if (i > SIZE8X6PAL - 1)
i = SIZE8X6PAL - 1;
*ffolat = ffo8x6pal[i].ffolat;
*ivo = 0x39;
}
break;
case GFX_VGA_MODE_720X487:
*ffolat = 0x40;
*ivo = 0x1a;
break;
case GFX_VGA_MODE_720X576:
*ffolat = 0x40;
*ivo = 0x1a;
break;
case GFX_VGA_MODE_1024X768:
default:
if (IS_NTSC(tv_std)) {
if (i > SIZE10X7NTSC - 1)
i = SIZE10X7NTSC - 1;
*ffolat = ffo10x7ntsc[i].ffolat;
*ivo = ffo10x7ntsc[i].ivo;
} else {
if (i > SIZE10X7PAL - 1)
i = SIZE10X7PAL - 1;
*ffolat = ffo10x7pal[i].ffolat;
*ivo = ffo10x7pal[i].ivo;
}
break;
}
}
static void
get_vtotal_min_max(unsigned long vga_mode,
unsigned long tv_std,
int *v_total_min, int *v_total_max, int *v_step)
{
int k = map_tvstd_to_index(tv_std);
switch (vga_mode) {
case GFX_VGA_MODE_640X480:
if (IS_NTSC(tv_std)) {
*v_total_min = ffo6x4ntsc[0].v_total;
*v_total_max = ffo6x4ntsc[SIZE6X4NTSC - 1].v_total;
} else {
*v_total_min = ffo6x4pal[0].v_total;
*v_total_max = ffo6x4pal[SIZE6X4PAL - 1].v_total;
}
*v_step = 4;
break;
case GFX_VGA_MODE_800X600:
if (IS_NTSC(tv_std)) {
*v_total_min = ffo8x6ntsc[0].v_total;
*v_total_max = ffo8x6ntsc[SIZE8X6NTSC - 1].v_total;
} else {
*v_total_min = ffo8x6pal[0].v_total;
*v_total_max = ffo8x6pal[SIZE8X6PAL - 1].v_total;
}
*v_step = 5;
break;
case GFX_VGA_MODE_720X487:
case GFX_VGA_MODE_720X576:
*v_total_min = tvsetup.tv_lines[k];
*v_total_max = tvsetup.tv_lines[k];
*v_step = 4;
break;
case GFX_VGA_MODE_1024X768:
if (IS_NTSC(tv_std)) {
*v_total_min = ffo10x7ntsc[0].v_total;
*v_total_max = ffo10x7ntsc[SIZE10X7NTSC - 1].v_total;
} else {
*v_total_min = ffo10x7pal[0].v_total;
*v_total_max = ffo10x7pal[SIZE10X7PAL - 1].v_total;
}
*v_step = 6;
break;
}
}
static void
config_overscan_xy(unsigned long tv_std,
unsigned long vga_mode,
int overscan_x, int overscan_y, int pos_x, int pos_y)
{
unsigned int vga_index;
unsigned long reg;
double vsc;
int k;
unsigned short ffolat, ivo;
int base_v_total, range, v_offset;
int v_total_min, v_total_max, v_step;
float r, f;
int vga_pixels, pre_pixels;
float hscale, hscale_min, hscale_max;
int hsc;
int iho, iho_max, ihw;
k = map_tvstd_to_index(tv_std);
g_specs.tv_width = tvsetup.tv_width[k];
g_specs.tv_lines = tvsetup.tv_lines[k];
for (vga_index = 0; vga_index < SCANTABLE_ENTRIES; vga_index++) {
if (scantable[vga_index].mode == vga_mode)
break;
}
if (vga_index >= SCANTABLE_ENTRIES)
return;
get_vtotal_min_max(vga_mode, tv_std, &v_total_min, &v_total_max, &v_step);
TRACE(("v_total min=%d, max=%d\n", v_total_min, v_total_max))
base_v_total = scantable[vga_index].v_total[k];
range = fsmax(base_v_total - v_total_min, v_total_max - base_v_total);
TRACE(("v_total range = %d\n", range))
v_offset = (int)((((float)overscan_y * range) / 1000.f) + .5f);
TRACE(("v_offset = %d\n", v_offset))
g_specs.v_total =
range_limit(base_v_total + v_offset, v_total_min, v_total_max);
v_offset = (g_specs.v_total - v_total_min + (v_step / 2)) / v_step;
g_specs.v_total = v_total_min + v_offset * v_step;
TRACE(("desired v_total=%d\n", g_specs.v_total))
get_ffolat_ivo(vga_mode, tv_std, v_offset, &ffolat, &ivo);
houston_WriteReg(HOUSTON_IVO, ivo, 2);
r = (float)g_specs.v_total / (float)base_v_total;
v_offset = (int)(r * (float)scantable[vga_index].v_sync[k]);
f = (float)ivo;
v_offset -= (int)(f - f / r);
f = (float)tvsetup.tv_active_lines[k] / 2.f;
v_offset += (int)(f * r - f);
g_specs.v_sync = g_specs.v_total - v_offset + pos_y;
TRACE(("desired v_total=%d, desired v_sync=%d\n", g_specs.v_total,
g_specs.v_sync))
if (g_specs.v_sync < g_specs.vga_lines + 10) {
TRACE(("vsync too low\n"))
g_specs.v_sync = g_specs.vga_lines + 10;
} else if (g_specs.v_sync > g_specs.v_total - 10) {
TRACE(("vsync too high\n"))
g_specs.v_sync = g_specs.v_total - 10;
}
TRACE(("v_total=%d v_sync=%d\n", g_specs.v_total, g_specs.v_sync))
houston_WriteReg(HOUSTON_FFO_LAT, ffolat, 2);
vsc = (65536.0f *
(1.0f - (double)g_specs.tv_lines / (double)g_specs.v_total)) + 0.5f;
reg = ((unsigned long)-vsc) & 0xffff;
TRACE(("vsc=%04x, tv_lines=%d, v_total=%d\n", reg, g_specs.tv_lines,
g_specs.v_total))
houston_WriteReg(HOUSTON_VSC, (int)reg, 2);
vga_pixels = g_specs.vga_width;
if (1024 == vga_pixels)
vga_pixels /= 2;
hscale_max = (720.0f / vga_pixels);
hscale_min = fsmax((0.75f * hscale_max), (1.0f - (63.0f / 128.0f)));
TRACE(("hscale_min = %u.%u, hscale_max = %u.%u\n",
(int)hscale_min,
(int)((hscale_min - (int)hscale_min) * 1000),
(int)hscale_max, (int)((hscale_max - (int)hscale_max) * 1000)))
hscale =
hscale_min + ((overscan_x + 1000.0f) / 2000.0f) * (hscale_max -
hscale_min);
TRACE(("hscale = %u.%u\n", (int)hscale,
(int)((hscale - (int)hscale) * 1000)))
if (hscale >= 1.0f)
hsc = (int)(128.f * (hscale - 1.0f) + .5f);
else
hsc = (int)(128.f * (hscale - 1.0f) - .5f);
TRACE(("hsc = %d\n", hsc))
if (hsc >= 0)
houston_WriteReg(HOUSTON_HSC, hsc << 8, 2);
else
houston_WriteReg(HOUSTON_HSC, hsc & 0xFF, 2);
hscale = 1.0f + (hsc / 128.0f);
TRACE(("recalculated hscale = %u.%u\n", (int)hscale,
(int)((hscale - (int)hscale) * 1000)))
g_specs.h_sync =
fsmax((g_specs.h_total + g_specs.vga_width) / 2 - 40,
g_specs.vga_width + 10);
g_specs.h_sync &= ~1;
TRACE(("hsync = %u\n", g_specs.h_sync))
pre_pixels =
(int)((long)(g_specs.h_total - g_specs.h_sync) * vga_pixels /
g_specs.vga_width);
iho_max = (2 * pre_pixels) - ((int)(720.0f / hscale + 0.5f) - vga_pixels);
TRACE(("iho_max = %u\n", iho_max))
iho =
(int)range_limit(((long)(1000 - pos_x) * iho_max / 2000) +
scantable[vga_index].iho[k], 0, iho_max);
TRACE(("iho = %u\n", iho))
houston_WriteReg(HOUSTON_IHO, iho, 2);
ihw = fsmin(vga_pixels + pre_pixels - iho, (int)(720.0f / hscale));
if (hsc < 0)
ihw = (int)fsmin(ihw, 253L * 128 / (-hsc));
ihw &= ~1;
TRACE(("ihw = %u\n", ihw))
houston_WriteReg(HOUSTON_IHA, ihw, 2);
f = (((float)g_specs.h_total * g_specs.v_total) * 27.f) /
((float)g_specs.tv_width * g_specs.tv_lines);
TRACE(("freq=%u.%uMHz\n", (int)f, (int)((f - (int)f) * 1000)))
}
static void
config_nco(unsigned long tv_std, unsigned long vga_mode)
{
unsigned long cr, misc;
unsigned long reg;
int k = map_tvstd_to_index(tv_std);
houston_ReadReg(HOUSTON_CR, &cr, 2);
cr &= ~CR_NCO_EN;
houston_WriteReg(HOUSTON_CR, cr, 2);
houston_ReadReg(HOUSTON_MISC, &misc, 2);
misc &= ~(MISC_NCO_LOAD1 + MISC_NCO_LOAD0);
houston_WriteReg(HOUSTON_MISC, misc, 2);
if (vga_mode == GFX_VGA_MODE_1024X768) {
misc |= (MISC_NCO_LOAD0);
houston_WriteReg(HOUSTON_MISC, misc, 2);
houston_WriteReg(HOUSTON_NCONL, 1024 - 2, 2);
houston_WriteReg(HOUSTON_NCODL, 128 - 1, 2);
cr |= CR_NCO_EN;
houston_WriteReg(HOUSTON_CR, cr, 2);
cr &= ~CR_NCO_EN;
houston_WriteReg(HOUSTON_CR, cr, 2);
misc &= ~(MISC_NCO_LOAD1 + MISC_NCO_LOAD0);
houston_WriteReg(HOUSTON_MISC, misc, 2);
reg = ((unsigned long)g_specs.v_total * g_specs.h_total) / 2;
houston_WriteReg(HOUSTON_NCONH, reg >> 16, 2);
houston_WriteReg(HOUSTON_NCONL, reg & 0xffff, 2);
houston_WriteReg(HOUSTON_NCODL, tvsetup.houston_ncodl[k], 2);
houston_WriteReg(HOUSTON_NCODH, tvsetup.houston_ncodh[k], 2);
} else {
misc |= (MISC_NCO_LOAD1);
houston_WriteReg(HOUSTON_MISC, misc, 2);
reg = (unsigned long)g_specs.v_total * g_specs.h_total;
houston_WriteReg(HOUSTON_NCONH, reg >> 16, 2);
houston_WriteReg(HOUSTON_NCONL, reg & 0xffff, 2);
houston_WriteReg(HOUSTON_NCODL, tvsetup.houston_ncodl[k], 2);
houston_WriteReg(HOUSTON_NCODH, tvsetup.houston_ncodh[k], 2);
TRACE(("NCON = %lu (0x%08lx), NCOD = %lu (0x%08lx)\n",
reg,
reg,
((unsigned long)tvsetup.houston_ncodh[k] << 16) +
tvsetup.houston_ncodl[k],
((unsigned long)tvsetup.houston_ncodh[k] << 16) +
tvsetup.houston_ncodl[k]))
}
cr |= CR_NCO_EN;
houston_WriteReg(HOUSTON_CR, cr, 2);
cr &= ~CR_NCO_EN;
houston_WriteReg(HOUSTON_CR, cr, 2);
}
static void
config_sharpness(int sharpness)
{
unsigned int shp;
shp = (unsigned int)(0.5f + ((float)sharpness * 20.0f / 1000.0f));
shp = range_limit(shp, 0, 20);
houston_WriteReg(HOUSTON_SHP, shp, 2);
}
static void
conget_sharpness(int *p_sharpness)
{
unsigned long shp;
if (!p_sharpness)
return;
houston_ReadReg(HOUSTON_SHP, &shp, 2);
*p_sharpness = (int)(0.5f + ((float)shp * 1000.0f / 20.0f));
}
static void
config_flicker(int flicker)
{
unsigned int flk;
flk = (unsigned int)(0.5f + ((float)flicker * 16.0f / 1000.0f));
flk = range_limit(flk, 0, 16);
houston_WriteReg(HOUSTON_FLK, flk, 2);
}
static void
conget_flicker(int *p_flicker)
{
unsigned long flk;
if (!p_flicker)
return;
houston_ReadReg(HOUSTON_FLK, &flk, 2);
*p_flicker = (int)(0.5f + ((float)flk * 1000.0f / 16.0f));
}
static void
config_color(int color)
{
unsigned long clr;
clr = (unsigned long)(0.8f + ((float)color * 255.0f / 100.0f));
clr = range_limit(clr, 0, 255);
houston_WriteReg(ENC_CR_GAIN, clr, 1);
houston_WriteReg(ENC_CB_GAIN, clr, 1);
}
static void
conget_color(int *p_color)
{
unsigned long cr_gain;
if (!p_color)
return;
houston_ReadReg(ENC_CR_GAIN, &cr_gain, 1);
*p_color = (int)(0.5f + ((float)cr_gain * 100.0f / 255.0f));
}
#define NTSC_BLANK_LEVEL 240
static const int min_black_level = NTSC_BLANK_LEVEL + 1;
static const int max_white_level = 1023;
static void
config_brightness_contrast(unsigned long tv_std, unsigned int trigger_bits,
int brightness, int contrast)
{
int brightness_off;
float contrast_mult;
int black, white;
unsigned short w;
int k = map_tvstd_to_index(tv_std);
brightness_off = (int)(0.5f + ((float)brightness * 440.0f / 100.0f)) - 220;
contrast_mult = ((float)contrast * 0.5f / 100.0f) + 0.75f;
black = tvsetup.black_level[k];
if (trigger_bits != 0)
black -= tvsetup.hamp_offset[k];
white = tvsetup.white_level[k];
if (trigger_bits != 0)
white -= tvsetup.hamp_offset[k];
black = (int)((float)(black + brightness_off) * contrast_mult);
white = (int)((float)(white + brightness_off) * contrast_mult);
if (black < min_black_level)
black = min_black_level;
if (white > max_white_level)
white = max_white_level;
w = w10bit2z((unsigned short)black);
houston_WriteReg(ENC_BLACK_LEVEL, w & 0x00ff, 1);
houston_WriteReg(ENC_BLACK_LEVEL + 1, w >> 8, 1);
w = w10bit2z((unsigned short)white);
houston_WriteReg(ENC_WHITE_LEVEL, w & 0x00ff, 1);
houston_WriteReg(ENC_WHITE_LEVEL + 1, w >> 8, 1);
}
static void
conget_brightness_contrast(unsigned long tv_std, unsigned int trigger_bits,
int *p_brightness, int *p_contrast)
{
int brightness_off;
float contrast_mult;
unsigned short black, white;
unsigned long zh, zl;
int k;
if (!p_brightness || !p_contrast)
return;
k = map_tvstd_to_index(tv_std);
houston_ReadReg(ENC_BLACK_LEVEL, &zl, 1);
houston_ReadReg(ENC_BLACK_LEVEL + 1, &zh, 1);
black = z2w10bit((unsigned short)(zl + (zh << 8)));
if (trigger_bits != 0)
black += tvsetup.hamp_offset[k];
houston_ReadReg(ENC_WHITE_LEVEL, &zl, 1);
houston_ReadReg(ENC_WHITE_LEVEL + 1, &zh, 1);
white = z2w10bit((unsigned short)(zl + (zh << 8)));
if (trigger_bits != 0)
white += tvsetup.hamp_offset[k];
contrast_mult =
((float)white - (float)black) / ((float)tvsetup.white_level[k] -
(float)tvsetup.black_level[k]);
brightness_off =
(int)(((float)black / contrast_mult) - tvsetup.black_level[k]);
*p_brightness =
range_limit((int)
(0.5f +
((float)(brightness_off + 220) * 100.0f / 440.0f)), 0,
100);
*p_contrast =
range_limit((int)
(0.5f +
((float)(contrast_mult - 0.75f) * 100.0f / 0.5f)), 0,
100);
}
static void
config_yc_filter(unsigned long tv_std, int luma_filter, int chroma_filter)
{
unsigned long reg, reg07, reg34;
if (houston_Rev() < HOUSTON_REV_B)
return;
if (luma_filter)
reg = tvsetup.notch_filter[map_tvstd_to_index(tv_std)];
else
reg = 0;
houston_WriteReg(ENC_NOTCH_FILTER, reg, 1);
houston_ReadReg(ENC_REG07, ®07, 1);
houston_ReadReg(ENC_REG34, ®34, 1);
if (chroma_filter) {
reg07 &= ~0x08;
reg34 &= ~0x20;
} else {
reg07 |= 0x08;
reg34 |= 0x20;
}
houston_WriteReg(ENC_REG07, reg07, 1);
houston_WriteReg(ENC_REG34, reg34, 1);
}
static void
conget_yc_filter(int *p_luma_filter, int *p_chroma_filter)
{
unsigned long reg, reg07, reg34;
if (!p_luma_filter || !p_chroma_filter)
return;
if (houston_Rev() < HOUSTON_REV_B) {
*p_luma_filter = 0;
*p_chroma_filter = 0;
return;
}
houston_ReadReg(ENC_NOTCH_FILTER, ®, 1);
*p_luma_filter = (reg ? 1 : 0);
houston_ReadReg(ENC_REG07, ®07, 1);
houston_ReadReg(ENC_REG34, ®34, 1);
*p_chroma_filter = !((0x08 & reg07) || (0x20 & reg34));
}
static void
config_macrovision(unsigned long tv_std, unsigned int trigger_bits)
{
#define nNTSC_APS00 0
#define nNTSC_APS01 1
#define nNTSC_APS10 2
#define nNTSC_APS11 3
#define nPAL_APS00 4
#define nPAL_APSXX 5
#define nMVModes 6
static const struct mvparms
{
unsigned short n0[nMVModes];
unsigned short n1[nMVModes];
unsigned short n2[nMVModes];
unsigned short n3[nMVModes];
unsigned short n4[nMVModes];
unsigned short n5[nMVModes];
unsigned short n6[nMVModes];
unsigned short n7[nMVModes];
unsigned short n8[nMVModes];
unsigned short n9[nMVModes];
unsigned short n10[nMVModes];
unsigned short n11[nMVModes];
unsigned short n12[nMVModes];
unsigned short n13[nMVModes];
unsigned short n14[nMVModes];
unsigned short n15[nMVModes];
unsigned short n16[nMVModes];
unsigned short n17[nMVModes];
unsigned short n18[nMVModes];
unsigned short n19[nMVModes];
unsigned short n20[nMVModes];
unsigned short n21[nMVModes];
unsigned short n22[nMVModes];
unsigned short agc_pulse_level[nMVModes];
unsigned short bp_pulse_level[nMVModes];
}
mvsetup =
{
{
0x00, 0x36, 0x3e, 0x3e, 0x00, 0x3e}
,
{
0x1d, 0x1d, 0x1d, 0x17, 0x1a, 0x1a}
,
{
0x11, 0x11, 0x11, 0x15, 0x22, 0x22}
,
{
0x25, 0x25, 0x25, 0x21, 0x2a, 0x2a}
,
{
0x11, 0x11, 0x11, 0x15, 0x22, 0x22}
,
{
0x01, 0x01, 0x01, 0x05, 0x05, 0x05}
,
{
0x07, 0x07, 0x07, 0x05, 0x02, 0x02}
,
{
0x00, 0x00, 0x00, 0x02, 0x00, 0x00}
,
{
0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c}
,
{
0x1b, 0x1b, 0x1b, 0x1b, 0x3d, 0x3d}
,
{
0x24, 0x24, 0x24, 0x24, 0x14, 0x14}
,
{
0x780f, 0x780f, 0x780f, 0x780f, 0x7e07, 0x7e07}
,
{
0x0000, 0x0000, 0x0000, 0x0000, 0x5402, 0x5402}
,
{
0x0f, 0x0f, 0x0f, 0x0f, 0xfe, 0xfe}
,
{
0x0f, 0x0f, 0x0f, 0x0f, 0x7e, 0x7e}
,
{
0x60, 0x60, 0x60, 0x60, 0x60, 0x60}
,
{
0x01, 0x01, 0x01, 0x01, 0x00, 0x00}
,
{
0x0a, 0x0a, 0x0a, 0x0a, 0x08, 0x08}
,
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
,
{
0x05, 0x05, 0x05, 0x05, 0x04, 0x04}
,
{
0x04, 0x04, 0x04, 0x04, 0x07, 0x07}
,
{
0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x0155, 0x0155}
,
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
,
{
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3}
,
{
0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8}
,
};
int nMode;
unsigned long misc;
unsigned short n0;
trigger_bits &= 0x3;
if (IS_NTSC(tv_std)) {
if (trigger_bits == 0) {
nMode = nNTSC_APS00;
} else if (trigger_bits == 1) {
nMode = nNTSC_APS01;
} else if (trigger_bits == 2) {
nMode = nNTSC_APS10;
} else {
nMode = nNTSC_APS11;
}
} else {
if (trigger_bits == 0) {
nMode = nPAL_APS00;
} else {
nMode = nPAL_APSXX;
}
}
if (tv_std != GFX_TV_STANDARD_PAL_M)
n0 = mvsetup.n0[nMode];
else {
if ((trigger_bits & 0x03) == 0)
n0 = mvsetup.n0[nPAL_APS00];
else
n0 = mvsetup.n0[nPAL_APSXX];
}
houston_WriteReg(MV_N0, n0, 1);
houston_WriteReg(MV_N1, mvsetup.n1[nMode], 1);
houston_WriteReg(MV_N2, mvsetup.n2[nMode], 1);
houston_WriteReg(MV_N3, mvsetup.n3[nMode], 1);
houston_WriteReg(MV_N4, mvsetup.n4[nMode], 1);
houston_WriteReg(MV_N5, mvsetup.n5[nMode], 1);
houston_WriteReg(MV_N6, mvsetup.n6[nMode], 1);
houston_WriteReg(MV_N7, mvsetup.n7[nMode], 1);
houston_WriteReg(MV_N8, mvsetup.n8[nMode], 1);
houston_WriteReg(MV_N9, mvsetup.n9[nMode], 1);
houston_WriteReg(MV_N10, mvsetup.n10[nMode], 1);
houston_WriteReg(MV_N11, mvsetup.n11[nMode] & 0xff, 1);
houston_WriteReg(MV_N11 + 1, mvsetup.n11[nMode] >> 8, 1);
houston_WriteReg(MV_N12, mvsetup.n12[nMode] & 0xff, 1);
houston_WriteReg(MV_N12 + 1, mvsetup.n12[nMode] >> 8, 1);
houston_WriteReg(MV_N13, mvsetup.n13[nMode], 1);
houston_WriteReg(MV_N14, mvsetup.n14[nMode], 1);
houston_WriteReg(MV_N15, mvsetup.n15[nMode], 1);
houston_WriteReg(MV_N16, mvsetup.n16[nMode], 1);
houston_WriteReg(MV_N17, mvsetup.n17[nMode], 1);
houston_WriteReg(MV_N18, mvsetup.n18[nMode], 1);
houston_WriteReg(MV_N19, mvsetup.n19[nMode], 1);
houston_WriteReg(MV_N20, mvsetup.n20[nMode], 1);
houston_WriteReg(MV_N21, mvsetup.n21[nMode] & 0xff, 1);
houston_WriteReg(MV_N21 + 1, mvsetup.n21[nMode] >> 8, 1);
houston_WriteReg(MV_N22, mvsetup.n22[nMode], 1);
houston_WriteReg(MV_AGC_PULSE_LEVEL, mvsetup.agc_pulse_level[nMode], 1);
houston_WriteReg(MV_BP_PULSE_LEVEL, mvsetup.bp_pulse_level[nMode], 1);
houston_ReadReg(HOUSTON_MISC, &misc, 2);
if (trigger_bits == 0)
misc &= ~MISC_MV_SOFT_EN;
else
misc |= MISC_MV_SOFT_EN;
houston_WriteReg(HOUSTON_MISC, misc, 2);
}
static void
conget_macrovision(unsigned long tv_std, unsigned int *p_cp_trigger_bits)
{
unsigned long n0, n1;
if (!p_cp_trigger_bits)
return;
houston_ReadReg(MV_N0, &n0, 1);
houston_ReadReg(MV_N1, &n1, 1);
*p_cp_trigger_bits = 0;
if (IS_NTSC(tv_std)) {
switch (n0) {
case 0:
*p_cp_trigger_bits = 0;
break;
case 0x36:
*p_cp_trigger_bits = 1;
break;
case 0x3E:
{
if (0x1D == n1)
*p_cp_trigger_bits = 2;
else
*p_cp_trigger_bits = 3;
}
break;
}
} else if (IS_PAL(tv_std)) {
if (0 == n0)
*p_cp_trigger_bits = 0;
else {
*p_cp_trigger_bits = 1;
}
}
}
#define CCR3 0xC3
#define GCR 0xb8
#define GX_DCLK_MUL 0x00c0
#define GX_DCLKx1 0x0040
#define GX_DCLKx2 0x0080
#define GX_DCLKx4 0x00c0
#define GX_TGEN 0x0020
#define CX_DISPLAY_CONFIG 0x10004
#define CX_DOT_CLK 0x10024
#define CX_TV_CONFIG 0x10028
#define CX_FPVSYNC_POL 0x0800
#define CX_FPHSYNC_POL 0x0400
#define CX_FPDATA_ENB 0x0080
#define CX_FPPOWER_ENB 0x0040
#define CX_CRTVSYNC_POL 0x0200
#define CX_CRTHSYNC_POL 0x0100
#define CX_TVCLK_SELECT 0x0400
#define CX_INVERT_FPCLK (1 << 6)
#define FS450_I2C_ADDRESS (0x4A)
static unsigned char
PLAL_FS450_i2c_address(void)
{
return FS450_I2C_ADDRESS;
}
static int
PLAL_FS450_UIM_mode(void)
{
return 3;
}
static unsigned long
ReadGx(unsigned long inRegAddr)
{
unsigned long data;
DMAL_ReadUInt32(inRegAddr, &data);
return data;
}
static void
WriteGx(unsigned long inRegAddr, unsigned long inData)
{
int is_timing_register;
unsigned long reg_timing_cfg;
DMAL_WriteUInt32(DC_UNLOCK, 0x4758);
is_timing_register =
(DC_H_TIMING_1 == inRegAddr) ||
(DC_H_TIMING_2 == inRegAddr) ||
(DC_H_TIMING_3 == inRegAddr) ||
(DC_FP_H_TIMING == inRegAddr) ||
(DC_V_TIMING_1 == inRegAddr) ||
(DC_V_TIMING_2 == inRegAddr) ||
(DC_V_TIMING_3 == inRegAddr) || (DC_FP_V_TIMING == inRegAddr);
if (is_timing_register) {
DMAL_ReadUInt32(DC_TIMING_CFG, ®_timing_cfg);
DMAL_WriteUInt32(DC_TIMING_CFG, reg_timing_cfg & ~GX_TGEN);
}
DMAL_WriteUInt32(inRegAddr, inData);
if (is_timing_register) {
DMAL_WriteUInt32(DC_TIMING_CFG, reg_timing_cfg);
}
}
#ifdef FS450_DIRECTREG
static int
PLAL_ReadRegister(S_REG_INFO * p_reg)
{
if (!p_reg)
return 0;
if (SOURCE_GCC == p_reg->source) {
p_reg->value = ReadGx(p_reg->offset);
return 1;
}
return 0;
}
static int
PLAL_WriteRegister(const S_REG_INFO * p_reg)
{
if (!p_reg)
return 0;
if (SOURCE_GCC == p_reg->source) {
WriteGx(p_reg->offset, p_reg->value);
return 1;
}
return 0;
}
#endif
static int
PLAL_IsTVOn(void)
{
unsigned long reg;
reg = ReadGx(CX_DOT_CLK);
return (reg & CX_TVCLK_SELECT) ? 1 : 0;
}
static int
PLAL_EnableVga(void)
{
unsigned long reg;
reg = ReadGx(DC_GENERAL_CFG);
reg &= ~GX_DCLK_MUL;
reg |= GX_DCLKx2;
WriteGx(DC_GENERAL_CFG, reg);
reg = ReadGx(CX_DOT_CLK);
reg &= ~CX_TVCLK_SELECT;
WriteGx(CX_DOT_CLK, reg);
reg = ReadGx(DC_TIMING_CFG);
reg &= ~GX_TGEN;
WriteGx(DC_TIMING_CFG, reg);
reg |= GX_TGEN;
WriteGx(DC_TIMING_CFG, reg);
reg = ReadGx(CX_TV_CONFIG);
reg &= ~CX_INVERT_FPCLK;
WriteGx(CX_TV_CONFIG, reg);
return 0;
}
static int
PLAL_PrepForTVout(void)
{
unsigned int reg;
reg = 0;
WriteGx(CX_TV_CONFIG, reg);
reg = (int)ReadGx(CX_TV_CONFIG);
reg |= CX_INVERT_FPCLK;
WriteGx(CX_TV_CONFIG, reg);
return 0;
}
static int
PLAL_SetTVTimingRegisters(const S_TIMING_SPECS * p_specs)
{
unsigned long reg;
reg = ReadGx(DC_TIMING_CFG);
reg &= ~GX_TGEN;
WriteGx(DC_TIMING_CFG, reg);
reg = ((p_specs->h_total - 1) << 16) | (p_specs->vga_width - 1);
WriteGx(DC_H_TIMING_1, reg);
reg = ((p_specs->h_total - 1) << 16) | (p_specs->vga_width - 1);
WriteGx(DC_H_TIMING_2, reg);
reg = ((p_specs->h_sync + 63) << 16) | p_specs->h_sync;
WriteGx(DC_H_TIMING_3, reg);
WriteGx(DC_FP_H_TIMING, reg);
reg = ((p_specs->v_total - 1) << 16) | (p_specs->vga_lines - 1);
WriteGx(DC_V_TIMING_1, reg);
reg = ((p_specs->v_total - 1) << 16) | (p_specs->vga_lines - 1);
WriteGx(DC_V_TIMING_2, reg);
reg = ((p_specs->v_sync) << 16) | (p_specs->v_sync - 1);
WriteGx(DC_V_TIMING_3, reg);
reg = ((p_specs->v_sync - 1) << 16) | (p_specs->v_sync - 2);
WriteGx(DC_FP_V_TIMING, reg);
reg = ReadGx(DC_TIMING_CFG);
reg |= GX_TGEN;
WriteGx(DC_TIMING_CFG, reg);
return 0;
}
static int
PLAL_FinalEnableTVout(unsigned long vga_mode)
{
unsigned int reg;
reg = (int)ReadGx(CX_DOT_CLK);
reg |= CX_TVCLK_SELECT;
WriteGx(CX_DOT_CLK, reg);
reg = (int)ReadGx(DC_GENERAL_CFG);
reg &= ~GX_DCLK_MUL;
WriteGx(DC_GENERAL_CFG, reg);
reg |= GX_DCLKx2;
WriteGx(DC_GENERAL_CFG, reg);
reg = (int)ReadGx(CX_DISPLAY_CONFIG);
reg |= (CX_FPVSYNC_POL | CX_FPHSYNC_POL | CX_FPDATA_ENB | CX_FPPOWER_ENB);
WriteGx(CX_DISPLAY_CONFIG, reg);
#if 0
reg = ReadGx(DC_GENERAL_CFG);
reg &= ~GX_DCLK_MUL;
WriteGx(DC_GENERAL_CFG, reg);
reg |= GX_DCLKx2;
WriteGx(DC_GENERAL_CFG, reg);
#endif
return 0;
}