Updated radeon driver to the latest BeBits release 5.1.0.1.
Probably only works under Haiku due to the new area flags. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12219 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -15,8 +15,6 @@
|
||||
// additional timing flags for GetMode/SetMode
|
||||
enum {
|
||||
RADEON_MODE_STANDARD = 0 << 16,
|
||||
RADEON_MODE_MIRROR = 1 << 16,
|
||||
RADEON_MODE_CLONE = 2 << 16,
|
||||
RADEON_MODE_COMBINE = 3 << 16,
|
||||
|
||||
RADEON_MODE_MASK = 7 << 16,
|
||||
@@ -32,8 +30,9 @@ enum {
|
||||
|
||||
// operation codes tunneled via ProposeDisplayMode
|
||||
typedef enum {
|
||||
ms_swap,
|
||||
ms_overlay_port
|
||||
ms_swap = 'sw',
|
||||
ms_use_laptop_panel = 'up',
|
||||
ms_tv_standard = 'tv'
|
||||
} multi_mon_settings;
|
||||
|
||||
|
||||
|
||||
@@ -137,27 +137,4 @@
|
||||
#define RADEON_CUR2_OFFSET 0x0360
|
||||
# define RADEON_CUR2_LOCK (1 << 31)
|
||||
|
||||
#define RADEON_GRPH_BUFFER_CNTL 0x02f0
|
||||
# define RADEON_GRPH_START_REQ_MASK (0x7f)
|
||||
# define RADEON_GRPH_START_REQ_SHIFT 0
|
||||
# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8)
|
||||
# define RADEON_GRPH_STOP_REQ_SHIFT 8
|
||||
# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16)
|
||||
# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16
|
||||
# define RADEON_GRPH_CRITICAL_CNTL (1<<28)
|
||||
# define RADEON_GRPH_BUFFER_SIZE (1<<29)
|
||||
# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30)
|
||||
# define RADEON_GRPH_STOP_CNTL (1<<31)
|
||||
#define RADEON_GRPH2_BUFFER_CNTL 0x03f0
|
||||
# define RADEON_GRPH2_START_REQ_MASK (0x7f)
|
||||
# define RADEON_GRPH2_START_REQ_SHIFT 0
|
||||
# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8)
|
||||
# define RADEON_GRPH2_STOP_REQ_SHIFT 8
|
||||
# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16)
|
||||
# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16
|
||||
# define RADEON_GRPH2_CRITICAL_CNTL (1<<28)
|
||||
# define RADEON_GRPH2_BUFFER_SIZE (1<<29)
|
||||
# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30)
|
||||
# define RADEON_GRPH2_STOP_CNTL (1<<31)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# define RADEON_DAC_CMP_EN (1 << 3)
|
||||
# define RADEON_DAC_CMP_OUTPUT (1 << 7)
|
||||
# define RADEON_DAC_8BIT_EN (1 << 8)
|
||||
# define RADEON_DAC_TVO_EN (1 << 10)
|
||||
# define RADEON_DAC_VGA_ADR_EN (1 << 13)
|
||||
# define RADEON_DAC_PDWN (1 << 15)
|
||||
# define RADEON_DAC_MASK_ALL (0xff << 24)
|
||||
@@ -57,12 +58,40 @@
|
||||
#define RADEON_DAC_W_INDEX 0x03c8 /* VGA */
|
||||
|
||||
#define RADEON_DISP_OUTPUT_CNTL 0x0d64
|
||||
# define RADEON_DISP_DAC_SOURCE_MASK 0x03
|
||||
# define RADEON_DISP_DAC_SOURCE_CRTC1 0x00
|
||||
# define RADEON_DISP_DAC_SOURCE_CRTC2 0x01
|
||||
# define RADEON_DISP_DAC_SOURCE_RMX 0x02
|
||||
# define RADEON_DISP_TVDAC_SOURCE_MASK 0x0c
|
||||
# define RADEON_DISP_TVDAC_SOURCE_CRTC2 0x04
|
||||
# define RADEON_DISP_DAC_SOURCE_MASK 3
|
||||
# define RADEON_DISP_DAC_SOURCE_CRTC1 0
|
||||
# define RADEON_DISP_DAC_SOURCE_CRTC2 1
|
||||
# define RADEON_DISP_DAC_SOURCE_RMX 2
|
||||
# define RADEON_DISP_TVDAC_SOURCE_MASK (3 << 2)
|
||||
# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (1 << 2)
|
||||
# define RADEON_DISP_TV_SOURCE (1 << 16)
|
||||
# define RADEON_DISP_TV_MODE_MASK (3 << 17)
|
||||
# define RADEON_DISP_TV_MODE_888 (0 << 17)
|
||||
# define RADEON_DISP_TV_MODE_565 (1 << 17)
|
||||
# define RADEON_DISP_TV_YG_DITH_EN (1 << 19)
|
||||
# define RADEON_DISP_TV_CBB_CRR_DITH_EN (1 << 20)
|
||||
# define RADEON_DISP_TV_BIT_WIDTH (1 << 21)
|
||||
# define RADEON_DISP_TV_SYNC_MODE_SHIFT 22
|
||||
# define RADEON_DISP_TV_SYNC_MODE_MASK (3 << 22)
|
||||
# define RADEON_DISP_TV_SYNC_COLOR_MASK (3 << 25)
|
||||
|
||||
#define RADEON_DISP_TV_OUT_CNTL 0x0d6c
|
||||
# define RADEON_DISP_TV_OUT_YG_FILTER_MASK (3 << 0)
|
||||
# define RADEON_DISP_TV_OUT_YG_SAMPLE (1 << 2)
|
||||
# define RADEON_DISP_TV_OUT_CrR_FILTER_MASK (3 << 4)
|
||||
# define RADEON_DISP_TV_OUT_CrR_SAMPLE (1 << 6)
|
||||
# define RADEON_DISP_TV_OUT_CbB_FILTER_MASK (3 << 8)
|
||||
# define RADEON_DISP_TV_OUT_CbB_SAMPLE (1 << 10)
|
||||
# define RADEON_DISP_TV_SUBSAMPLE_CNTL_MASK (3 << 12)
|
||||
# define RADEON_DISP_TV_H_DOWNSCALE (1 << 15)
|
||||
# define RADEON_DISP_TV_PATH_SRC (1 << 16)
|
||||
# define RADEON_DISP_TV_COLOR_SPACE (1 << 17)
|
||||
# define RADEON_DISP_TV_DITH_MODE (1 << 18)
|
||||
# define RADEON_DISP_TV_DATA_ZERO_SEL (1 << 19)
|
||||
# define RADEON_DISP_TV_CLKO_SEL (1 << 20)
|
||||
# define RADEON_DISP_TV_CLKO_OUT_EN (1 << 21)
|
||||
# define RADEON_DISP_TV_DOWNSCALE_CNTL (3 << 24)
|
||||
|
||||
|
||||
#define RADEON_DISP_HW_DEBUG 0x0d14
|
||||
# define RADEON_CRT2_DISP1_SEL (1 << 5)
|
||||
|
||||
@@ -25,4 +25,27 @@
|
||||
#define RADEON_CRTC2_DISPLAY_BASE_ADDRESS 0x033c
|
||||
#define RADEON_OV0_BASE_ADDRESS 0x043c
|
||||
|
||||
#define RADEON_GRPH_BUFFER_CNTL 0x02f0
|
||||
# define RADEON_GRPH_START_REQ_MASK (0x7f)
|
||||
# define RADEON_GRPH_START_REQ_SHIFT 0
|
||||
# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8)
|
||||
# define RADEON_GRPH_STOP_REQ_SHIFT 8
|
||||
# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16)
|
||||
# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16
|
||||
# define RADEON_GRPH_CRITICAL_CNTL (1<<28)
|
||||
# define RADEON_GRPH_BUFFER_SIZE (1<<29)
|
||||
# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30)
|
||||
# define RADEON_GRPH_STOP_CNTL (1<<31)
|
||||
#define RADEON_GRPH2_BUFFER_CNTL 0x03f0
|
||||
# define RADEON_GRPH2_START_REQ_MASK (0x7f)
|
||||
# define RADEON_GRPH2_START_REQ_SHIFT 0
|
||||
# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8)
|
||||
# define RADEON_GRPH2_STOP_REQ_SHIFT 8
|
||||
# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16)
|
||||
# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16
|
||||
# define RADEON_GRPH2_CRITICAL_CNTL (1<<28)
|
||||
# define RADEON_GRPH2_BUFFER_SIZE (1<<29)
|
||||
# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30)
|
||||
# define RADEON_GRPH2_STOP_CNTL (1<<31)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,14 @@ class BScreen;
|
||||
|
||||
status_t GetSwapDisplays( BScreen *screen, bool *swap );
|
||||
status_t SetSwapDisplays( BScreen *screen, bool swap );
|
||||
|
||||
status_t GetUseLaptopPanel( BScreen *screen, bool *use );
|
||||
status_t SetUseLaptopPanel( BScreen *screen, bool use );
|
||||
|
||||
status_t GetNthSupportedTVStandard( BScreen *screen, int idx, uint32 *standard );
|
||||
status_t GetTVStandard( BScreen *screen, uint32 *standard );
|
||||
status_t SetTVStandard( BScreen *screen, uint32 standard );
|
||||
|
||||
status_t TestMultiMonSupport( BScreen *screen );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,12 +47,14 @@
|
||||
# define RADEON_VCLK_SRC_PSCAN_CLK (1 << 0)
|
||||
# define RADEON_VCLK_SRC_BYTE_CLK (2 << 0)
|
||||
# define RADEON_VCLK_SRC_PPLL_CLK (3 << 0)
|
||||
# define RADEON_PIXCLK_ALWAYS_ONb (1 << 6) // negated
|
||||
# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1 << 7) // negated
|
||||
# define RADEON_ECP_DIV_SHIFT 8
|
||||
# define RADEON_ECP_DIV_MASK (3 << 8)
|
||||
# define RADEON_ECP_DIV_VCLK (0 << 8)
|
||||
# define RADEON_ECP_DIV_VCLK_2 (1 << 8)
|
||||
# define RADEON_PIXCLK_ALWAYS_ONb (1 << 6) // negated
|
||||
# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1 << 7) // negated
|
||||
# define RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_SHIFT 16
|
||||
# define RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_MASK (3 << 16)
|
||||
#define RADEON_HTOTAL_CNTL 0x0009
|
||||
#define RADEON_SCLK_CNTL 0x000d
|
||||
# define RADEON_DYN_STOP_LAT_MASK 0x00007ff8
|
||||
|
||||
@@ -102,14 +102,16 @@ typedef enum {
|
||||
rt_rs200, // IGP 330M/340M/350M
|
||||
rt_r200, // Radeon 8500/9100
|
||||
rt_rv250, // Radeon 9000
|
||||
rt_rv280, // Radeon 9200
|
||||
rt_m9, // mobile Radeon 9000
|
||||
rt_rv280, // Radeon 9200
|
||||
rt_m9plus, // mobile Radeon 9200
|
||||
|
||||
// from here on, r300 and up must be located as ATI modified the PLL
|
||||
// with r300 and the code only tests for >= rt_r300
|
||||
rt_r300, // Radeon 9700
|
||||
rt_r300_4p, // Radeon 9500
|
||||
rt_rv350, // Radeon 9600
|
||||
rt_m10, // mobile Radeon 9600
|
||||
rt_rv360, // Radeon 9600
|
||||
rt_r350, // Radeon 9800
|
||||
rt_r360 // Radeon 9800
|
||||
@@ -118,13 +120,15 @@ typedef enum {
|
||||
|
||||
// TV standard
|
||||
typedef enum {
|
||||
ts_off,
|
||||
ts_ntsc,
|
||||
ts_pal,
|
||||
ts_palm,
|
||||
ts_palcn,
|
||||
ts_pal_bdghi,
|
||||
ts_pal_m,
|
||||
ts_pal_nc,
|
||||
ts_scart_pal,
|
||||
ts_pal60
|
||||
} tv_standard;
|
||||
ts_pal_60,
|
||||
ts_max = ts_pal_60
|
||||
} tv_standard_e;
|
||||
|
||||
|
||||
// type of TV-Chip
|
||||
@@ -151,13 +155,6 @@ typedef struct {
|
||||
} cursor_info;
|
||||
|
||||
|
||||
// head as seen by accelerant
|
||||
typedef struct {
|
||||
int physical_head; // idx of physical head
|
||||
uint32 rel_x, rel_y; // relative position in multi-monitor mode
|
||||
} virtual_head;
|
||||
|
||||
|
||||
// info about flat panel connected to LVDS or DVI port
|
||||
typedef struct {
|
||||
uint panel_pwr_delay;
|
||||
@@ -175,16 +172,18 @@ typedef struct {
|
||||
} fp_info;
|
||||
|
||||
|
||||
// physical head
|
||||
// crtc info
|
||||
typedef struct {
|
||||
bool is_crtc2; // true, if connected to crtc2
|
||||
display_device_e active_displays; // currently driven displays
|
||||
display_device_e chosen_displays; // displays to be driven by next mode switch
|
||||
sem_id vblank; // vertical blank interrupt semaphore
|
||||
bool cursor_on_screen; // cursor is visible on this head
|
||||
display_mode mode; // display mode of this head
|
||||
//bool is_crtc2; // true, if crtc2
|
||||
int8 flatpanel_port; // linked flat panel port (-1 if none)
|
||||
} physical_head;
|
||||
bool cursor_on_screen; // cursor is visible on this head
|
||||
int crtc_idx; // index of CRTC
|
||||
display_device_e active_displays; // currently driven displays
|
||||
display_device_e chosen_displays; // displays to be driven after next mode switch
|
||||
sem_id vblank; // vertical blank interrupt semaphore
|
||||
uint32 rel_x, rel_y; // relative position in multi-monitor mode
|
||||
display_mode mode; // display mode of this head
|
||||
} crtc_info;
|
||||
|
||||
|
||||
// info about PLLs on graphics card as retrieved from BIOS
|
||||
@@ -220,146 +219,6 @@ typedef struct {
|
||||
} pll_info;
|
||||
|
||||
|
||||
// PLL divider values
|
||||
typedef struct {
|
||||
uint32 post_code; // code for post divider
|
||||
uint32 post; // value of post divider
|
||||
uint32 extra_post_code; // code for extra post divider
|
||||
uint32 extra_post; // value of extra post divider
|
||||
uint32 ref; // reference divider
|
||||
uint32 feedback; // feedback divider
|
||||
uint32 freq; // resulting frequency
|
||||
} pll_dividers;
|
||||
|
||||
|
||||
// TV-Out parameters
|
||||
typedef struct {
|
||||
uint16 y_accum_init;
|
||||
uint16 uv_accum_init;
|
||||
uint16 uv_inc;
|
||||
uint16 h_inc;
|
||||
uint32 tv_clocks_to_active;
|
||||
|
||||
uint16 f_restart;
|
||||
uint16 v_restart;
|
||||
uint16 h_restart;
|
||||
bool mode888;
|
||||
|
||||
uint16 y_saw_tooth_slope;
|
||||
uint16 y_saw_tooth_amp;
|
||||
uint16 y_rise_accum_init;
|
||||
uint16 y_fall_accum_init;
|
||||
bool y_coeff_enable;
|
||||
uint8 y_coeff_value;
|
||||
|
||||
pll_dividers tv_dividers;
|
||||
pll_dividers crt_dividers;
|
||||
} tv_params;
|
||||
|
||||
|
||||
// TV-timing
|
||||
typedef struct {
|
||||
uint32 freq; // TV sub carrier frequency x12
|
||||
uint16 h_total;
|
||||
uint16 h_sync_len;
|
||||
uint16 h_genclk_delay;
|
||||
uint16 h_setup_delay;
|
||||
uint16 h_active_delay;
|
||||
uint16 h_active_len;
|
||||
uint16 v_total;
|
||||
uint16 v_active_lines;
|
||||
uint16 v_field_total;
|
||||
uint16 v_fields;
|
||||
uint16 f_total;
|
||||
uint16 frame_size_adjust;
|
||||
uint32 scale;
|
||||
} tv_timing;
|
||||
|
||||
|
||||
// list of register content (used for mode changes)
|
||||
typedef struct {
|
||||
// CRTC regs
|
||||
uint32 crtc_h_total_disp;
|
||||
uint32 crtc_h_sync_strt_wid;
|
||||
uint32 crtc_v_total_disp;
|
||||
uint32 crtc_v_sync_strt_wid;
|
||||
uint32 crtc_pitch;
|
||||
uint32 crtc_gen_cntl;
|
||||
uint32 crtc_ext_cntl;
|
||||
uint32 crtc_offset_cntl;
|
||||
|
||||
// RMX registers
|
||||
uint32 fp_horz_stretch;
|
||||
uint32 fp_vert_stretch;
|
||||
|
||||
// Flat panel regs
|
||||
uint32 fp_gen_cntl;
|
||||
uint32 fp_panel_cntl;
|
||||
uint32 lvds_gen_cntl;
|
||||
uint32 fp_h_sync_strt_wid;
|
||||
uint32 fp_v_sync_strt_wid;
|
||||
uint32 fp2_gen_cntl;
|
||||
|
||||
uint32 fp2_h_sync_strt_wid;
|
||||
uint32 fp2_v_sync_strt_wid;
|
||||
|
||||
// DAC regs
|
||||
uint32 dac_cntl2;
|
||||
uint32 dac_cntl;
|
||||
uint32 disp_hw_debug;
|
||||
|
||||
// PLL regs
|
||||
uint32 ppll_div_3;
|
||||
uint32 ppll_ref_div;
|
||||
uint32 htotal_cntl;
|
||||
|
||||
// pure information
|
||||
uint32 dot_clock_freq; // in 10 kHz
|
||||
uint32 pll_output_freq;// in 10 kHz
|
||||
int feedback_div;
|
||||
int post_div;
|
||||
|
||||
// Common regs
|
||||
uint32 surface_cntl;
|
||||
uint32 disp_output_cntl;
|
||||
|
||||
// TV-Out registers
|
||||
uint32 tv_ftotal;
|
||||
uint32 tv_vscaler_cntl1;
|
||||
uint32 tv_y_saw_tooth_cntl;
|
||||
uint32 tv_y_fall_cntl;
|
||||
uint32 tv_y_rise_cntl;
|
||||
uint32 tv_vscaler_cntl2;
|
||||
uint32 tv_hrestart;
|
||||
uint32 tv_vrestart;
|
||||
uint32 tv_frestart;
|
||||
uint32 tv_tv_pll_cntl;
|
||||
uint32 tv_crt_pll_cntl;
|
||||
uint32 tv_clock_sel_cntl;
|
||||
uint32 tv_clkout_cntl;
|
||||
uint32 tv_htotal;
|
||||
uint32 tv_hsize;
|
||||
uint32 tv_hdisp;
|
||||
uint32 tv_hstart;
|
||||
uint32 tv_vtotal;
|
||||
uint32 tv_vdisp;
|
||||
uint32 tv_sync_size;
|
||||
uint32 tv_timing_cntl;
|
||||
uint32 tv_dac_cntl; // affects CRT connected to TV-DAC
|
||||
uint32 tv_modulator_cntl1;
|
||||
uint32 tv_modulator_cntl2;
|
||||
uint32 tv_data_delay_a;
|
||||
uint32 tv_data_delay_b;
|
||||
uint32 tv_frame_lock_cntl;
|
||||
uint32 tv_pll_cntl1;
|
||||
uint32 tv_rgb_cntl;
|
||||
uint32 tv_pre_dac_mux_cntl;
|
||||
uint32 tv_master_cntl;
|
||||
uint32 tv_uv_adr;
|
||||
uint32 tv_pll_fine_cntl;
|
||||
} port_regs;
|
||||
|
||||
|
||||
// one overlay buffer
|
||||
typedef struct overlay_buffer_node {
|
||||
struct overlay_buffer_node *next, *prev;
|
||||
@@ -382,7 +241,7 @@ typedef struct {
|
||||
|
||||
overlay_buffer_node *on; // current buffer
|
||||
overlay_buffer_node *prev_on; // previous buffer (for temporal deinterlace, currently unused)
|
||||
int8 head; // physical head where the overlay is shown on
|
||||
int crtc_idx; // crtc where the overlay is shown on
|
||||
uint32 rel_offset; // offset of overlay source due to clipping
|
||||
} overlay_info;
|
||||
|
||||
@@ -393,8 +252,11 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint32 id; // identifier used to know which card the 2D accelerator
|
||||
// is prepared for (we use area_id of this structure)
|
||||
virtual_head heads[2]; // heads assigned to virtual card
|
||||
uint8 num_heads; // number of heads assigned to virtual card
|
||||
bool assigned_crtc[2]; // mask of heads assigned to virtual card
|
||||
bool used_crtc[2]; // mask of heads assigned to virtual card
|
||||
|
||||
display_device_e controlled_displays; // displays devices controlled byvc
|
||||
display_device_e connected_displays; // bit-field of connected displays
|
||||
|
||||
int8 independant_heads; // number of heads to be programmed independantly
|
||||
int8 different_heads; // number of heads showing different parts of framebuffer
|
||||
@@ -410,9 +272,12 @@ typedef struct {
|
||||
|
||||
cursor_info cursor;
|
||||
|
||||
multi_mode_e wanted_multi_mode; // multi monitor mode as requested by user
|
||||
|
||||
bool swap_displays; // true to swap monitors
|
||||
bool use_laptop_panel; // true to always use laptop panel
|
||||
tv_standard_e tv_standard; // standard to use for TV Out
|
||||
bool enforce_mode_change; // set to make sure next display mode change
|
||||
// is executed even if display mode seems to be
|
||||
// still the same
|
||||
|
||||
frame_buffer_config fbc; // data for direct frame buffer access
|
||||
|
||||
@@ -528,6 +393,7 @@ typedef struct {
|
||||
radeon_type asic; // ASIC version
|
||||
bool is_mobility; // mobility version
|
||||
tv_chip_type tv_chip; // type of TV-Out encoder
|
||||
bool new_pll; // r300 style PLL
|
||||
|
||||
uint8 theatre_channel; // VIP channel of Rage Theatre (if applicable)
|
||||
|
||||
@@ -539,11 +405,9 @@ typedef struct {
|
||||
void *framebuffer_pci; // physical address of frame buffer (aka local memory)
|
||||
// this is a hack needed by BeOS
|
||||
|
||||
physical_head heads[2]; // physical heads
|
||||
uint8 num_heads; // number of physical heads
|
||||
crtc_info crtc[2]; // info about each crtc
|
||||
uint8 num_crtc; // number of physical heads
|
||||
|
||||
display_device_e connected_displays; // bit-field of connected displays
|
||||
|
||||
fp_info flatpanels[2]; // info about connected flat panels (if any)
|
||||
|
||||
memory_type_info memory[mt_last]; // info about memory types
|
||||
@@ -618,6 +482,7 @@ typedef struct {
|
||||
uint channel; // channel, i.e. device
|
||||
uint address; // address
|
||||
uint32 data; // read data
|
||||
bool lock; // true, if CP lock must be acquired
|
||||
} radeon_vip_read;
|
||||
|
||||
// write VIP register
|
||||
@@ -626,6 +491,7 @@ typedef struct {
|
||||
uint channel; // channel, i.e. device
|
||||
uint address; // address
|
||||
uint32 data; // data to write
|
||||
bool lock; // true, if CP lock must be acquired
|
||||
} radeon_vip_write;
|
||||
|
||||
// find channel of device with given ID
|
||||
|
||||
@@ -250,12 +250,10 @@
|
||||
#define RADEON_TRAIL_X 0x1618
|
||||
#define RADEON_TRAIL_X_SUB 0x1620
|
||||
|
||||
#define RADEON_VCLK_ECP_CNTL 0x0008 /* PLL */
|
||||
#define RADEON_VGA_DDA_CONFIG 0x02e8
|
||||
#define RADEON_VGA_DDA_CONFIG 0x02e8 // Rage 128 reg
|
||||
#define RADEON_VGA_DDA_ON_OFF 0x02ec
|
||||
#define RADEON_VID_BUFFER_CONTROL 0x0900
|
||||
#define RADEON_VIDEOMUX_CNTL 0x0190
|
||||
#define RADEON_VIPH_CONTROL 0x0c40 /* ? */
|
||||
|
||||
#define RADEON_OVR_CLR 0x0230
|
||||
#define RADEON_OVR_WID_LEFT_RIGHT 0x0234
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
#define THEATRE_VIP_Y_FALL_CNTL 0x01cc
|
||||
#define THEATRE_VIP_Y_RISE_CNTL 0x01d0
|
||||
#define THEATRE_VIP_Y_SAW_TOOTH_CNTL 0x01d4
|
||||
#define THEATRE_VIP_UPSAMP_AND_GAIN_CNTL 0x01e0
|
||||
#define THEATRE_VIP_GAIN_LIMIT_SETTINGS 0x01e4
|
||||
#define THEATRE_VIP_LINEAR_GAIN_SETTINGS 0x01e8
|
||||
#define THEATRE_VIP_MODULATOR_CNTL1 0x0200
|
||||
#define THEATRE_VIP_MODULATOR_CNTL2 0x0204
|
||||
#define THEATRE_VIP_PRE_DAC_MUX_CNTL 0x0240
|
||||
@@ -67,6 +70,21 @@
|
||||
#define THEATRE_VIP_VBI_20BIT_CNTL 0x02d0
|
||||
#define THEATRE_VIP_VBI_LEVEL_CNTL 0x02d8
|
||||
#define THEATRE_VIP_UV_ADR 0x0300
|
||||
#define THEATRE_VIP_UPSAMP_COEFF0_0 0x0340
|
||||
#define THEATRE_VIP_UPSAMP_COEFF0_1 0x0344
|
||||
#define THEATRE_VIP_UPSAMP_COEFF0_2 0x0348
|
||||
#define THEATRE_VIP_UPSAMP_COEFF1_0 0x034c
|
||||
#define THEATRE_VIP_UPSAMP_COEFF1_1 0x0350
|
||||
#define THEATRE_VIP_UPSAMP_COEFF1_2 0x0354
|
||||
#define THEATRE_VIP_UPSAMP_COEFF2_0 0x0358
|
||||
#define THEATRE_VIP_UPSAMP_COEFF2_1 0x035c
|
||||
#define THEATRE_VIP_UPSAMP_COEFF2_2 0x0360
|
||||
#define THEATRE_VIP_UPSAMP_COEFF3_0 0x0364
|
||||
#define THEATRE_VIP_UPSAMP_COEFF3_1 0x0368
|
||||
#define THEATRE_VIP_UPSAMP_COEFF3_2 0x036c
|
||||
#define THEATRE_VIP_UPSAMP_COEFF4_0 0x0370
|
||||
#define THEATRE_VIP_UPSAMP_COEFF4_1 0x0374
|
||||
#define THEATRE_VIP_UPSAMP_COEFF4_2 0x0378
|
||||
#define THEATRE_VIP_HSCALER_CONTROL 0x0600
|
||||
#define THEATRE_VIP_VSCALER_CONTROL 0x0604
|
||||
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
# define RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST (1 << 1)
|
||||
# define RADEON_TV_MASTER_CNTL_RESTART_PHASE_FIX (1 << 3)
|
||||
# define RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST (1 << 4)
|
||||
# define RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST (1 << 5)
|
||||
# define RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST (1 << 6)
|
||||
# define RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST (1 << 7)
|
||||
# define RADEON_TV_MASTER_CNTL_CRT_FIFO_CE_EN (1 << 9)
|
||||
# define RADEON_TV_MASTER_CNTL_TV_FIFO_CE_EN (1 << 10)
|
||||
# define RADEON_TV_MASTER_CNTL_RE_SYNC_NOW_SEL_MASK (3 << 14)
|
||||
# define RADEON_TV_MASTER_CNTL_TV_CLK_ALWAYS_ONb (1 << 30)
|
||||
# define RADEON_TV_MASTER_CNTL_TVCLK_ALWAYS_ONb (1 << 30)
|
||||
# define RADEON_TV_MASTER_CNTL_TV_ON (1 << 31)
|
||||
|
||||
#define RADEON_TV_RGB_CNTL 0x0804
|
||||
@@ -37,9 +40,24 @@
|
||||
#define RADEON_TV_HRESTART 0x0838
|
||||
#define RADEON_TV_VRESTART 0x083c
|
||||
|
||||
#define RADEON_TV_HOST_READ_DATA 0x0840
|
||||
#define RADEON_TV_HOST_WRITE_DATA 0x0844
|
||||
#define RADEON_TV_HOST_RD_WT_CNTL 0x0848
|
||||
# define RADEON_TV_HOST_RD_WT_CNTL_RD (1 << 12)
|
||||
# define RADEON_TV_HOST_RD_WT_CNTL_RD_ACK (1 << 13)
|
||||
# define RADEON_TV_HOST_RD_WT_CNTL_WT (1 << 14)
|
||||
# define RADEON_TV_HOST_RD_WT_CNTL_WT_ACK (1 << 15)
|
||||
|
||||
|
||||
#define RADEON_TV_VSCALER_CNTL1 0x084c
|
||||
# define RADEON_TV_VSCALER_CNTL1_RESTART_FIELD (1 << 29)
|
||||
# define RADEON_TV_VSCALER_CNTL1_UV_INC_SHIFT 0
|
||||
# define RADEON_TV_VSCALER_CNTL1_UV_INC_MASK 0x0000ffff
|
||||
# define RADEON_TV_VSCALER_CNTL1_UV_THINNER_SHIFT 16
|
||||
# define RADEON_TV_VSCALER_CNTL1_UV_THINNER_MASK 0x003f0000
|
||||
# define RADEON_TV_VSCALER_CNTL1_Y_W_EN (1 << 24)
|
||||
# define RADEON_TV_VSCALER_CNTL1_Y_DEL_W_SIG_SHIFT 26
|
||||
# define RADEON_TV_VSCALER_CNTL1_RESTART_FIELD (1 << 29)
|
||||
|
||||
|
||||
#define RADEON_TV_TIMING_CNTL 0x0850
|
||||
# define RADEON_TV_TIMING_CNTL_UV_OUTPUT_POST_SCALE_SHIFT 24
|
||||
@@ -57,18 +75,26 @@
|
||||
# define RADEON_TV_Y_FALL_CNTL_Y_COEFF_VALUE_SHIFT 24
|
||||
|
||||
#define RADEON_TV_Y_RISE_CNTL 0x085c
|
||||
# define RADEON_TV_Y_RISE_CNTL_Y_RISE_PING_PONG 16
|
||||
# define RADEON_TV_Y_RISE_CNTL_Y_RISE_PING_PONG (1 << 16)
|
||||
|
||||
#define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860
|
||||
# define RADEON_TV_Y_SAW_TOOTH_CNTL_SLOPE_SHIFT 16
|
||||
|
||||
#define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864
|
||||
#define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868
|
||||
#define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c
|
||||
|
||||
#define RADEON_TV_MODULATOR_CNTL1 0x0870
|
||||
# define RADEON_TV_MODULATOR_CNTL1_YFLT_EN (1 << 2)
|
||||
# define RADEON_TV_MODULATOR_CNTL1_UVFLT_EN (1 << 3)
|
||||
# define RADEON_TV_MODULATOR_CNTL1_ALT_PHASE_EN (1 << 6)
|
||||
# define RADEON_TV_MODULATOR_CNTL1_SYNC_TIP_LEVEL (1 << 7)
|
||||
# define RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT 18
|
||||
# define RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT 8
|
||||
# define RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_MASK 0x00007f00
|
||||
# define RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT 16
|
||||
# define RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_MASK 0x007f0000
|
||||
# define RADEON_TV_MODULATOR_CNTL1_SLEW_RATE_LIMIT (1 << 23)
|
||||
# define RADEON_TV_MODULATOR_CNTL1_CY_FILT_BLEND_SHIFT 28
|
||||
|
||||
#define RADEON_TV_MODULATOR_CNTL2 0x0874
|
||||
# define TV_MODULATOR_CNTL2_U_BURST_LEVEL_MASK 0x1ff
|
||||
@@ -90,6 +116,7 @@
|
||||
# define RADEON_TV_DAC_CNTL_NBLANK (1 << 0)
|
||||
# define RADEON_TV_DAC_CNTL_NHOLD (1 << 1)
|
||||
# define RADEON_TV_DAC_CNTL_PEDESTAL (1 << 2)
|
||||
# define RADEON_TV_DAC_CNTL_DASLEEP (1 << 3) // Theatre only
|
||||
# define RADEON_TV_DAC_CNTL_DETECT (1 << 4)
|
||||
# define RADEON_TV_DAC_CNTL_CMPOUT (1 << 5)
|
||||
# define RADEON_TV_DAC_CNTL_BGSLEEP (1 << 6)
|
||||
@@ -99,11 +126,29 @@
|
||||
# define RADEON_TV_DAC_CNTL_STD_RS343 (3 << 8)
|
||||
# define RADEON_TV_DAC_CNTL_BGADJ_SHIFT 16
|
||||
# define RADEON_TV_DAC_CNTL_DACADJ_SHIFT 20
|
||||
# define RADEON_TV_DAC_CNTL_RDACPD (1 << 24)
|
||||
# define RADEON_TV_DAC_CNTL_GDACPD (1 << 25)
|
||||
# define RADEON_TV_DAC_CNTL_BDACPD (1 << 26)
|
||||
# define RADEON_TV_DAC_CNTL_RDACDET (1 << 29)
|
||||
# define RADEON_TV_DAC_CNTL_GDACDET (1 << 30)
|
||||
# define RADEON_TV_DAC_CNTL_BDACDET (1 << 31)
|
||||
|
||||
#define RADEON_TV_CRC_CNTL 0x0890
|
||||
|
||||
#define RADEON_TV_UV_ADR 0x08ac
|
||||
# define RADEON_TV_UV_ADR_MAX_UV_ADR_MASK 0x000000ff
|
||||
# define RADEON_TV_UV_ADR_MAX_UV_ADR_SHIFT 0
|
||||
# define RADEON_TV_UV_ADR_TABLE1_BOT_ADR_MASK 0x0000ff00
|
||||
# define RADEON_TV_UV_ADR_TABLE1_BOT_ADR_SHIFT 8
|
||||
# define RADEON_TV_UV_ADR_TABLE3_TOP_ADR_MASK 0x00ff0000
|
||||
# define RADEON_TV_UV_ADR_TABLE3_TOP_ADR_SHIFT 16
|
||||
# define RADEON_TV_UV_ADR_HCODE_TABLE_SEL_MASK 0x06000000
|
||||
# define RADEON_TV_UV_ADR_HCODE_TABLE_SEL_SHIFT 25
|
||||
# define RADEON_TV_UV_ADR_VCODE_TABLE_SEL_MASK 0x18000000
|
||||
# define RADEON_TV_UV_ADR_VCODE_TABLE_SEL_SHIFT 27
|
||||
#define RADEON_TV_MAX_FIFO_ADDR 0x1a7
|
||||
#define RADEON_TV_MAX_FIFO_ADDR_INTERN 0x1ff
|
||||
|
||||
|
||||
#define RADEON_TV_PLL_FINE_CNTL 0x20
|
||||
|
||||
@@ -138,4 +183,7 @@
|
||||
# define RADEON_TV_PLL_CNTL1_TVPLL_TEST (1 << 31)
|
||||
|
||||
|
||||
# define RADEON_TV_CLOCK_SEL_CNTL_BYTCLK_SHIFT 2
|
||||
# define RADEON_TV_CLOCK_SEL_CNTL_BYTCLKD_SHIFT 8
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
*/
|
||||
|
||||
// current version
|
||||
#define RADEON_DRIVER_VERSION "Version: 4.1.0.0"
|
||||
#define RADEON_DRIVER_VERSION "Version: 5.1.0.1"
|
||||
|
||||
@@ -122,7 +122,7 @@ void Radeon_FreeIndirectBuffers( accelerator_info *ai )
|
||||
|
||||
// wait until an indirect buffer becomes available;
|
||||
// lock must be hold
|
||||
void Radeon_WaitForFreeIndirectBuffers( accelerator_info *ai )
|
||||
static void Radeon_WaitForFreeIndirectBuffers( accelerator_info *ai )
|
||||
{
|
||||
bigtime_t start_time;
|
||||
CP_info *cp = &ai->si->cp;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -14,20 +14,19 @@
|
||||
#include "mmio.h"
|
||||
#include "crtc_regs.h"
|
||||
|
||||
static void doShowCursor( accelerator_info *ai, physical_head *head );
|
||||
static void moveOneCursor( accelerator_info *ai, virtual_head *virtual_head, int x, int y );
|
||||
static void moveOneCursor( accelerator_info *ai, int crtc_idx, int x, int y );
|
||||
|
||||
// set standard foreground/background colours
|
||||
void Radeon_SetCursorColors( accelerator_info *ai, physical_head *head )
|
||||
void Radeon_SetCursorColors( accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
if( head->is_crtc2 ) {
|
||||
OUTREG( ai->regs, RADEON_CUR2_CLR0, 0xffffff );
|
||||
OUTREG( ai->regs, RADEON_CUR2_CLR1, 0 );
|
||||
} else {
|
||||
if( crtc_idx == 0 ) {
|
||||
OUTREG( ai->regs, RADEON_CUR_CLR0, 0xffffff );
|
||||
OUTREG( ai->regs, RADEON_CUR_CLR1, 0 );
|
||||
} else {
|
||||
OUTREG( ai->regs, RADEON_CUR2_CLR0, 0xffffff );
|
||||
OUTREG( ai->regs, RADEON_CUR2_CLR1, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,9 +114,10 @@ void MOVE_CURSOR(uint16 x, uint16 y)
|
||||
y -= vds;
|
||||
|
||||
// go
|
||||
moveOneCursor( ai, &vc->heads[0], x, y );
|
||||
if( vc->independant_heads > 1 )
|
||||
moveOneCursor( ai, &vc->heads[1], x, y );
|
||||
if( vc->used_crtc[0] )
|
||||
moveOneCursor( ai, 0, x, y );
|
||||
if( vc->used_crtc[1] )
|
||||
moveOneCursor( ai, 1, x, y );
|
||||
|
||||
RELEASE_BEN( ai->si->engine.lock );
|
||||
}
|
||||
@@ -137,9 +137,10 @@ void SHOW_CURSOR( bool is_visible )
|
||||
|
||||
// the following functions take also care to not
|
||||
// show the cursor if it's on the other port
|
||||
doShowCursor( ai, &ai->si->heads[vc->heads[0].physical_head] );
|
||||
if( vc->independant_heads > 1 )
|
||||
doShowCursor( ai, &ai->si->heads[vc->heads[1].physical_head] );
|
||||
if( vc->used_crtc[0] )
|
||||
Radeon_ShowCursor( ai, 0 );
|
||||
if( vc->used_crtc[1] )
|
||||
Radeon_ShowCursor( ai, 1 );
|
||||
|
||||
RELEASE_BEN( ai->si->engine.lock );
|
||||
}
|
||||
@@ -147,38 +148,38 @@ void SHOW_CURSOR( bool is_visible )
|
||||
|
||||
// move cursor on one port
|
||||
// main_port - common data is stored here
|
||||
void moveOneCursor( accelerator_info *ai, virtual_head *virtual_head, int x, int y )
|
||||
void moveOneCursor( accelerator_info *ai, int crtc_idx, int x, int y )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
physical_head *head = &ai->si->heads[virtual_head->physical_head];
|
||||
crtc_info *crtc = &ai->si->crtc[crtc_idx];
|
||||
int xorigin, yorigin;
|
||||
bool prev_state;
|
||||
|
||||
// adjust according to relative screen position
|
||||
x -= virtual_head->rel_x;
|
||||
y -= virtual_head->rel_y;
|
||||
x -= crtc->rel_x;
|
||||
y -= crtc->rel_y;
|
||||
|
||||
// and to hot spot
|
||||
x -= vc->cursor.hot_x;
|
||||
y -= vc->cursor.hot_y;
|
||||
|
||||
// check whether the cursor is (partially) visible on this screen
|
||||
prev_state = head->cursor_on_screen;
|
||||
head->cursor_on_screen = true;
|
||||
prev_state = crtc->cursor_on_screen;
|
||||
crtc->cursor_on_screen = true;
|
||||
|
||||
// in theory, cursor can be up to 64 pixels off screen,
|
||||
// but there were display errors
|
||||
if( y > head->mode.timing.v_display ||
|
||||
x > head->mode.timing.h_display ||
|
||||
if( y > crtc->mode.timing.v_display ||
|
||||
x > crtc->mode.timing.h_display ||
|
||||
x <= -16 || y <= -16 )
|
||||
{
|
||||
head->cursor_on_screen = false;
|
||||
crtc->cursor_on_screen = false;
|
||||
}
|
||||
|
||||
if( prev_state != head->cursor_on_screen )
|
||||
doShowCursor( ai, head );
|
||||
if( prev_state != crtc->cursor_on_screen )
|
||||
Radeon_ShowCursor( ai, crtc_idx );
|
||||
|
||||
if( !head->cursor_on_screen )
|
||||
if( !crtc->cursor_on_screen )
|
||||
return;
|
||||
|
||||
// if upper-left corner of cursor is outside of
|
||||
@@ -192,17 +193,7 @@ void moveOneCursor( accelerator_info *ai, virtual_head *virtual_head, int x, int
|
||||
if( y < 0 )
|
||||
yorigin = -y;
|
||||
|
||||
if( head->is_crtc2 ) {
|
||||
OUTREG( ai->regs, RADEON_CUR2_HORZ_VERT_OFF, RADEON_CUR2_LOCK
|
||||
| (xorigin << 16)
|
||||
| yorigin );
|
||||
OUTREG( ai->regs, RADEON_CUR2_HORZ_VERT_POSN, RADEON_CUR2_LOCK
|
||||
| ((xorigin ? 0 : x) << 16)
|
||||
| (yorigin ? 0 : y) );
|
||||
OUTREG( ai->regs, RADEON_CUR2_OFFSET,
|
||||
vc->cursor.fb_offset + xorigin + yorigin * 16 );
|
||||
|
||||
} else {
|
||||
if( crtc_idx == 0 ) {
|
||||
OUTREG( ai->regs, RADEON_CUR_HORZ_VERT_OFF, RADEON_CUR_LOCK
|
||||
| (xorigin << 16)
|
||||
| yorigin );
|
||||
@@ -211,36 +202,46 @@ void moveOneCursor( accelerator_info *ai, virtual_head *virtual_head, int x, int
|
||||
| (yorigin ? 0 : y) );
|
||||
OUTREG( ai->regs, RADEON_CUR_OFFSET,
|
||||
vc->cursor.fb_offset + xorigin + yorigin * 16 );
|
||||
} else {
|
||||
OUTREG( ai->regs, RADEON_CUR2_HORZ_VERT_OFF, RADEON_CUR2_LOCK
|
||||
| (xorigin << 16)
|
||||
| yorigin );
|
||||
OUTREG( ai->regs, RADEON_CUR2_HORZ_VERT_POSN, RADEON_CUR2_LOCK
|
||||
| ((xorigin ? 0 : x) << 16)
|
||||
| (yorigin ? 0 : y) );
|
||||
OUTREG( ai->regs, RADEON_CUR2_OFFSET,
|
||||
vc->cursor.fb_offset + xorigin + yorigin * 16 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// show cursor on one port, depending on official whishes and whether
|
||||
// cursor is located on this subscreen
|
||||
void doShowCursor( accelerator_info *ai, physical_head *head )
|
||||
void Radeon_ShowCursor( accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
crtc_info *crtc = &ai->si->crtc[crtc_idx];
|
||||
uint32 tmp;
|
||||
|
||||
if( head->is_crtc2 ) {
|
||||
tmp = INREG( ai->regs, RADEON_CRTC2_GEN_CNTL );
|
||||
|
||||
if( vc->cursor.is_visible && head->cursor_on_screen )
|
||||
tmp |= RADEON_CRTC2_CUR_EN;
|
||||
else
|
||||
tmp &= ~RADEON_CRTC2_CUR_EN;
|
||||
|
||||
OUTREG( ai->regs, RADEON_CRTC2_GEN_CNTL, tmp );
|
||||
|
||||
} else {
|
||||
if( crtc_idx == 0 ) {
|
||||
tmp = INREG( ai->regs, RADEON_CRTC_GEN_CNTL );
|
||||
|
||||
if( vc->cursor.is_visible && head->cursor_on_screen ) {
|
||||
if( vc->cursor.is_visible && crtc->cursor_on_screen ) {
|
||||
tmp |= RADEON_CRTC_CUR_EN;
|
||||
} else {
|
||||
tmp &= ~RADEON_CRTC_CUR_EN;
|
||||
}
|
||||
|
||||
OUTREG( ai->regs, RADEON_CRTC_GEN_CNTL, tmp );
|
||||
|
||||
} else {
|
||||
tmp = INREG( ai->regs, RADEON_CRTC2_GEN_CNTL );
|
||||
|
||||
if( vc->cursor.is_visible && crtc->cursor_on_screen )
|
||||
tmp |= RADEON_CRTC2_CUR_EN;
|
||||
else
|
||||
tmp &= ~RADEON_CRTC2_CUR_EN;
|
||||
|
||||
OUTREG( ai->regs, RADEON_CRTC2_GEN_CNTL, tmp );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,15 @@ sem_id ACCELERANT_RETRACE_SEMAPHORE(void)
|
||||
// with multi-monitor mode, we have two vertical blanks!
|
||||
// until we find a better solution, we always return virtual port 0,
|
||||
// which may be either physical port 0 or 1
|
||||
int physical_head = vc->heads[0].physical_head;
|
||||
int crtc_idx;
|
||||
|
||||
if( vc->used_crtc[0] )
|
||||
crtc_idx = 0;
|
||||
else
|
||||
crtc_idx = 1;
|
||||
|
||||
//SHOW_INFO( 3, "semaphore: %x", ai->si->ports[physical_port].vblank );
|
||||
|
||||
return ai->si->heads[physical_head].vblank;
|
||||
return ai->si->crtc[crtc_idx].vblank;
|
||||
//return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static status_t init_common( int the_fd, bool accelerant_is_clone )
|
||||
radeon_get_private_data gpd;
|
||||
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
|
||||
ai = malloc( sizeof( *ai ));
|
||||
if( ai == NULL )
|
||||
return B_NO_MEMORY;
|
||||
@@ -151,7 +151,7 @@ status_t INIT_ACCELERANT( int the_fd )
|
||||
result = init_common( the_fd, 0 );
|
||||
if (result != B_OK)
|
||||
goto err;
|
||||
|
||||
|
||||
si = ai->si;
|
||||
vc = ai->vc;
|
||||
|
||||
@@ -189,8 +189,8 @@ status_t INIT_ACCELERANT( int the_fd )
|
||||
si->overlay_mgr.inuse = 0;
|
||||
|
||||
// mark overlay as inactive
|
||||
si->active_overlay.head = -1;
|
||||
si->pending_overlay.head = -1;
|
||||
si->active_overlay.crtc_idx = -1;
|
||||
si->pending_overlay.crtc_idx = -1;
|
||||
|
||||
// reset list of allocated overlays
|
||||
vc->overlay_buffers = NULL;
|
||||
|
||||
@@ -20,6 +20,8 @@ Addon radeon.accelerant : accelerants :
|
||||
dpms.c
|
||||
driver_wrapper.c
|
||||
flat_panel.c
|
||||
impactv.c
|
||||
internal_tv_out.c
|
||||
monitor_detection.c
|
||||
monitor_routing.c
|
||||
multimon.c
|
||||
@@ -28,12 +30,13 @@ Addon radeon.accelerant : accelerants :
|
||||
palette.c
|
||||
pll.c
|
||||
settings.cpp
|
||||
tv_out.c
|
||||
theatre_out.c
|
||||
vesa_modes.c
|
||||
: false
|
||||
: libaccelerantscommon.a libgraphicscommon.a libradeon.a
|
||||
: libaccelerantscommon.a libradeon.a
|
||||
;
|
||||
|
||||
LinkSharedOSLibs radeon.accelerant : root be ;
|
||||
LinkSharedOSLibs radeon.accelerant : be ;
|
||||
|
||||
Package haiku-radeon-cvs :
|
||||
radeon.accelerant :
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "crtc_regs.h"
|
||||
#include "utils.h"
|
||||
#include "set_mode.h"
|
||||
|
||||
// standard mode list
|
||||
// all drivers contain this list - this should really be moved to
|
||||
@@ -24,8 +25,10 @@
|
||||
//#define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
|
||||
|
||||
static const display_mode base_mode_list[] = {
|
||||
// PAL
|
||||
// test for PAL
|
||||
//{ { 25175, 640, 656, 752, 816, 480, 490, 492, 625, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
|
||||
// test for NTSC
|
||||
//{ { 43956, 800, 824, 952, 992, 600, 632, 635, 740, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */
|
||||
|
||||
{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
|
||||
{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */
|
||||
@@ -35,6 +38,14 @@ static const display_mode base_mode_list[] = {
|
||||
{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
|
||||
{ { 25175, 640, 656, 752, 800, 400, 412, 414, 449, B_POSITIVE_VSYNC}, B_CMAP8, 640, 400, 0, 0, MODE_FLAGS}, /* 640x400 - www.epanorama.net/documents/pc/vga_timing.html) */
|
||||
{ { 25175, 640, 656, 752, 800, 350, 387, 389, 449, B_POSITIVE_HSYNC}, B_CMAP8, 640, 350, 0, 0, MODE_FLAGS}, /* 640x350 - www.epanorama.net/documents/pc/vga_timing.html) */
|
||||
|
||||
// NTSC non-isometric resolution (isometric resolution is 640x480)
|
||||
{ { 26720, 720, 736, 808, 896, 480, 481, 484, 497, B_POSITIVE_VSYNC}, B_CMAP8, 720, 480, 0, 0, MODE_FLAGS}, /* 720x480@60Hz according to GMTF */
|
||||
|
||||
// PAL resolutions
|
||||
{ { 26570, 720, 736, 808, 896, 576, 577, 580, 593, B_POSITIVE_VSYNC}, B_CMAP8, 720, 576, 0, 0, MODE_FLAGS}, /* 720x576@50Hz according to GMTF */
|
||||
{ { 28460, 768, 784, 864, 960, 576, 577, 580, 593, B_POSITIVE_VSYNC}, B_CMAP8, 768, 576, 0, 0, MODE_FLAGS}, /* 768x576@50Hz according to GMTF */
|
||||
|
||||
{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */
|
||||
{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */
|
||||
{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */
|
||||
@@ -47,6 +58,10 @@ static const display_mode base_mode_list[] = {
|
||||
{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
|
||||
{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */
|
||||
{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */
|
||||
|
||||
{ { 108000, 1280, 1376, 1488, 1800, 960, 961, 964, 1000, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X960X8.Z1) - not in Be's list */
|
||||
{ { 148500, 1280, 1344, 1504, 1728, 960, 961, 964, 1011, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X960X8.Z1) - not in Be's list */
|
||||
|
||||
{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */
|
||||
{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */
|
||||
{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */
|
||||
@@ -59,7 +74,7 @@ static const display_mode base_mode_list[] = {
|
||||
};
|
||||
|
||||
|
||||
// convert Be colour space in Radeon data type
|
||||
// convert Be colour space to Radeon data type
|
||||
// returns true, if supported colour space
|
||||
// space - Be colour space
|
||||
// format - (out) Radeon data type
|
||||
@@ -105,7 +120,8 @@ bool Radeon_GetFormat( int space, int *format, int *bpp )
|
||||
return B_BAD_VALUE.
|
||||
If the mode is both valid AND falls within the limits, return B_OK.
|
||||
*/
|
||||
status_t Radeon_ProposeDisplayMode( shared_info *si, physical_head *head,
|
||||
status_t Radeon_ProposeDisplayMode(
|
||||
shared_info *si, crtc_info *crtc,
|
||||
general_pll_info *pll, display_mode *target,
|
||||
const display_mode *low, const display_mode *high )
|
||||
{
|
||||
@@ -116,7 +132,7 @@ status_t Radeon_ProposeDisplayMode( shared_info *si, physical_head *head,
|
||||
int format, bpp;
|
||||
uint32 row_bytes;
|
||||
int eff_virtual_width;
|
||||
fp_info *flatpanel = &si->flatpanels[head->flatpanel_port];
|
||||
fp_info *flatpanel = &si->flatpanels[crtc->flatpanel_port];
|
||||
|
||||
// save refresh rate - we want to leave this (artifical) value untouched
|
||||
// don't use floating point, we are in kernel mode
|
||||
@@ -133,7 +149,7 @@ status_t Radeon_ProposeDisplayMode( shared_info *si, physical_head *head,
|
||||
// for flat panels, check maximum resolution;
|
||||
// all the other tricks (like fixed resolution and resulting scaling)
|
||||
// are done automagically by set_display_mode
|
||||
if( (head->chosen_displays & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) {
|
||||
if( (crtc->chosen_displays & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) {
|
||||
if( target->timing.h_display > flatpanel->panel_xres )
|
||||
target->timing.h_display = flatpanel->panel_xres;
|
||||
|
||||
@@ -141,6 +157,7 @@ status_t Radeon_ProposeDisplayMode( shared_info *si, physical_head *head,
|
||||
target->timing.v_display = flatpanel->panel_yres;
|
||||
}
|
||||
|
||||
/*
|
||||
// the TV-Out encoder can "only" handle up to 1024x768
|
||||
if( (head->chosen_displays & (dd_ctv | dd_stv)) != 0 ) {
|
||||
if( target->timing.h_display > 1024 )
|
||||
@@ -149,13 +166,14 @@ status_t Radeon_ProposeDisplayMode( shared_info *si, physical_head *head,
|
||||
if( target->timing.v_display > 768 )
|
||||
target->timing.v_display = 768;
|
||||
}
|
||||
*/
|
||||
|
||||
// validate horizontal timings
|
||||
{
|
||||
int h_sync_fudge, h_display, h_sync_start, h_sync_wid, h_total;
|
||||
|
||||
h_display = target->timing.h_display;
|
||||
h_sync_fudge = Radeon_GetHSyncFudge( head, format );
|
||||
h_sync_fudge = Radeon_GetHSyncFudge( crtc, format );
|
||||
h_sync_start = target->timing.h_sync_start;
|
||||
h_sync_wid = target->timing.h_sync_end - target->timing.h_sync_start;
|
||||
h_total = target->timing.h_total;
|
||||
@@ -431,7 +449,7 @@ static void checkAndAddMode( accelerator_info *ai, const display_mode *mode, boo
|
||||
*dst = *mode;
|
||||
dst->space = low.space = high.space = spaces[i];
|
||||
|
||||
if( Radeon_ProposeDisplayMode( si, &si->heads[0],
|
||||
if( Radeon_ProposeDisplayMode( si, &si->crtc[0],
|
||||
&si->pll, dst, &low, &high ) == B_OK )
|
||||
{
|
||||
si->mode_count++;
|
||||
@@ -442,7 +460,7 @@ static void checkAndAddMode( accelerator_info *ai, const display_mode *mode, boo
|
||||
*dst = *mode;
|
||||
dst->space = spaces[i];
|
||||
|
||||
if( Radeon_ProposeDisplayMode( si, &si->heads[1],
|
||||
if( Radeon_ProposeDisplayMode( si, &si->crtc[1],
|
||||
&si->pll, dst, &low, &high ) == B_OK )
|
||||
{
|
||||
si->mode_count++;
|
||||
@@ -480,11 +498,13 @@ static void checkAndAddMultiMode( accelerator_info *ai, const display_mode *mode
|
||||
}
|
||||
|
||||
// add display mode of flat panel to official list
|
||||
static void addFPMode( shared_info *si )
|
||||
static void addFPMode( accelerator_info *ai )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
|
||||
fp_info *fp_info = &si->flatpanels[0];
|
||||
|
||||
if( (si->connected_displays & (dd_dvi | dd_lvds)) != 0 ) {
|
||||
if( (ai->vc->connected_displays & (dd_dvi | dd_lvds)) != 0 ) {
|
||||
display_mode mode;
|
||||
|
||||
mode.virtual_width = mode.timing.h_display = fp_info->panel_xres;
|
||||
@@ -555,7 +575,7 @@ status_t Radeon_CreateModeList( shared_info *si )
|
||||
checkAndAddMultiMode( ai, &base_mode_list[i], false );
|
||||
|
||||
// plus fp mode
|
||||
addFPMode( si );
|
||||
addFPMode( ai );
|
||||
|
||||
// as we've created the list ourself, we don't clone it
|
||||
ai->mode_list_area = si->mode_list_area;
|
||||
@@ -596,7 +616,8 @@ status_t PROPOSE_DISPLAY_MODE( display_mode *target, const display_mode *low,
|
||||
// via successive Propose_Display_Mode; though this doesn't do any _real_ harm
|
||||
// it leads to annoying distortions on screen!!
|
||||
Radeon_DetectDisplays( ai);
|
||||
Radeon_SetupDefaultMonitorRouting( ai, Radeon_DifferentPorts( &tmp_target ) );
|
||||
Radeon_SetupDefaultMonitorRouting(
|
||||
ai, Radeon_DifferentPorts( &tmp_target ), vc->use_laptop_panel );
|
||||
|
||||
// transform to multi-screen mode first
|
||||
Radeon_DetectMultiMode( vc, target );
|
||||
@@ -613,7 +634,7 @@ status_t PROPOSE_DISPLAY_MODE( display_mode *target, const display_mode *low,
|
||||
|
||||
// we must assure that each ProposeMode call doesn't tweak the mode in
|
||||
// a way that it cannot be handled by the other port anymore
|
||||
result1 = Radeon_ProposeDisplayMode( si, &si->heads[vc->heads[0].physical_head],
|
||||
result1 = Radeon_ProposeDisplayMode( si, &si->crtc[0],
|
||||
&si->pll, target, low, high );
|
||||
|
||||
if( result1 == B_ERROR )
|
||||
@@ -621,7 +642,7 @@ status_t PROPOSE_DISPLAY_MODE( display_mode *target, const display_mode *low,
|
||||
|
||||
if( Radeon_NeedsSecondPort( target )) {
|
||||
// if both ports are used, make sure both can handle mode
|
||||
result2 = Radeon_ProposeDisplayMode( si, &si->heads[vc->heads[1].physical_head],
|
||||
result2 = Radeon_ProposeDisplayMode( si, &si->crtc[1],
|
||||
&si->pll, target, low, high );
|
||||
|
||||
if( result2 == B_ERROR )
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -16,16 +16,19 @@
|
||||
#include "crtc_regs.h"
|
||||
#include <GraphicsDefs.h>
|
||||
|
||||
#include "crtc_regs.h"
|
||||
#include "overlay_regs.h"
|
||||
#include "capture_regs.h"
|
||||
#include "rbbm_regs.h"
|
||||
#include "dac_regs.h"
|
||||
|
||||
#include "set_mode.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// round virtual width up to next valid size
|
||||
uint32 Radeon_RoundVWidth( int virtual_width, int bpp )
|
||||
uint32 Radeon_RoundVWidth(
|
||||
int virtual_width, int bpp )
|
||||
{
|
||||
// we have to make both the CRTC and the accelerator happy:
|
||||
// - the CRTC wants virtual width in pixels to be a multiple of 8
|
||||
@@ -58,26 +61,37 @@ static struct {
|
||||
{ RADEON_OVR_CLR, 0 },
|
||||
{ RADEON_OVR_WID_LEFT_RIGHT, 0 },
|
||||
{ RADEON_OVR_WID_TOP_BOTTOM, 0 },
|
||||
{ RADEON_OV0_SCALE_CNTL, 0 },
|
||||
{ RADEON_OV0_SCALE_CNTL, 0 }, // disable overlay
|
||||
{ RADEON_SUBPIC_CNTL, 0 },
|
||||
{ RADEON_VIPH_CONTROL, 0 },
|
||||
{ RADEON_I2C_CNTL_1, 0 },
|
||||
//{ RADEON_GEN_INT_CNTL, 0 }, // VBI irqs are handled seperately
|
||||
//{ RADEON_CAP0_TRIG_CNTL, 0 }, // leave capturing on during mode switch
|
||||
};
|
||||
|
||||
static void Radeon_InitCommonRegs( accelerator_info *ai )
|
||||
|
||||
static void Radeon_InitCommonRegs(
|
||||
accelerator_info *ai )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
uint i;
|
||||
|
||||
for( i = 0; i < sizeof( common_regs) / sizeof( common_regs[0] ); ++i )
|
||||
OUTREG( regs, common_regs[i].reg, common_regs[i].val );
|
||||
|
||||
// enable extended display modes
|
||||
OUTREGP( regs, RADEON_CRTC_GEN_CNTL,
|
||||
RADEON_CRTC_EXT_DISP_EN, ~RADEON_CRTC_EXT_DISP_EN );
|
||||
|
||||
// disable flat panel auto-centering
|
||||
// (if we have a CRT on CRTC1, this must be disabled;
|
||||
// if we have a flat panel on CRTC1, we setup CRTC manually, not
|
||||
// using the auto-centre, automatic-sync-override magic)
|
||||
OUTREG( regs, RADEON_CRTC_MORE_CNTL, 0 );
|
||||
}
|
||||
|
||||
|
||||
// set display mode of one head;
|
||||
// port restrictions, like fixed-sync TFTs connected to it, are taken care of
|
||||
void Radeon_SetMode( accelerator_info *ai, physical_head *head, display_mode *mode )
|
||||
void Radeon_SetMode(
|
||||
accelerator_info *ai, crtc_info *crtc, display_mode *mode, impactv_params *tv_params )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
@@ -86,24 +100,28 @@ void Radeon_SetMode( accelerator_info *ai, physical_head *head, display_mode *mo
|
||||
int bpp;
|
||||
display_device_e disp_devices;
|
||||
fp_info *fp_info;
|
||||
port_regs values;
|
||||
tv_params tv_params;
|
||||
tv_standard tv_format = ts_ntsc;
|
||||
tv_timing *tv_timing = &Radeon_std_tv_timing[tv_format];
|
||||
bool internal_tv_encoder;
|
||||
|
||||
head->mode = *mode;
|
||||
crtc_regs crtc_values;
|
||||
pll_regs pll_values;
|
||||
fp_regs fp_values;
|
||||
impactv_regs impactv_values;
|
||||
uint32 surface_cntl;
|
||||
|
||||
bool internal_tv_encoder;
|
||||
pll_dividers dividers;
|
||||
|
||||
crtc->mode = *mode;
|
||||
|
||||
// don't destroy passed values, use our copy instead
|
||||
mode = &head->mode;
|
||||
mode = &crtc->mode;
|
||||
|
||||
disp_devices = head->chosen_displays;
|
||||
fp_info = &si->flatpanels[head->flatpanel_port];
|
||||
disp_devices = crtc->chosen_displays;
|
||||
fp_info = &si->flatpanels[crtc->flatpanel_port];
|
||||
|
||||
// if using an flat panel or LCD, maximum resolution
|
||||
// is determined by the physical resolution;
|
||||
// also, all timing is fixed
|
||||
if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext )) != 0 ) {
|
||||
if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) {
|
||||
if( mode->timing.h_display > fp_info->panel_xres )
|
||||
mode->timing.h_display = fp_info->panel_xres;
|
||||
if( mode->timing.v_display > fp_info->panel_yres )
|
||||
@@ -118,18 +136,29 @@ void Radeon_SetMode( accelerator_info *ai, physical_head *head, display_mode *mo
|
||||
|
||||
mode->timing.pixel_clock = fp_info->dot_clock;
|
||||
}
|
||||
|
||||
// TV-out supports at most 1024x768
|
||||
if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
if( mode->timing.h_display > 1024 )
|
||||
mode->timing.h_display = 1024;
|
||||
|
||||
if( mode->timing.v_display > 768 )
|
||||
mode->timing.v_display = 768;
|
||||
}
|
||||
|
||||
// if using TV-Out, the timing of the source signal must be tweaked to
|
||||
// get proper timing
|
||||
internal_tv_encoder = si->tv_chip != tc_external_rt1;
|
||||
internal_tv_encoder = IS_INTERNAL_TV_OUT( si->tv_chip );
|
||||
|
||||
// we need higher accuracy then Be thought of;
|
||||
// we need higher accuracy then Be thought of
|
||||
mode->timing.pixel_clock *= 1000;
|
||||
|
||||
// TV stuff must be done first as it tweaks the display mode
|
||||
if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
display_mode tweaked_mode;
|
||||
|
||||
Radeon_CalcTVParams( &si->pll, &tv_params, tv_timing, internal_tv_encoder,
|
||||
Radeon_CalcImpacTVParams(
|
||||
&si->pll, tv_params, vc->tv_standard, internal_tv_encoder,
|
||||
mode, &tweaked_mode );
|
||||
|
||||
*mode = tweaked_mode;
|
||||
@@ -143,90 +172,92 @@ void Radeon_SetMode( accelerator_info *ai, physical_head *head, display_mode *mo
|
||||
// time to read original register content
|
||||
// lock hardware so noone bothers us
|
||||
Radeon_WaitForIdle( ai, true );
|
||||
|
||||
Radeon_ReadCRTCRegisters( ai, head, &values );
|
||||
Radeon_ReadMonitorRoutingRegs( ai, head, &values );
|
||||
|
||||
|
||||
if( (disp_devices & (dd_dvi | dd_lvds | dd_dvi_ext)) != 0 ) {
|
||||
if( !head->is_crtc2 )
|
||||
Radeon_ReadRMXRegisters( ai, &values );
|
||||
if( crtc->crtc_idx == 0 )
|
||||
Radeon_ReadRMXRegisters( ai, &fp_values );
|
||||
|
||||
Radeon_ReadFPRegisters( ai, &values );
|
||||
Radeon_ReadFPRegisters( ai, &fp_values );
|
||||
}
|
||||
|
||||
// calculate all hardware register values
|
||||
Radeon_CalcCRTCRegisters( ai, head, mode, &values );
|
||||
|
||||
values.surface_cntl = RADEON_SURF_TRANSLATION_DIS;
|
||||
|
||||
// for flat panels, we may not have pixel clock if DDC data is missing;
|
||||
// as we don't change effective resolution we can leave it as set by BIOS
|
||||
if( mode->timing.pixel_clock ) {
|
||||
Radeon_CalcPLLRegisters( &si->pll, mode/*->timing.pixel_clock / 10*/,
|
||||
(/*(disp_devices & (dd_stv | dd_ctv)) != 0 ? &tv_params.crt_dividers : */NULL),
|
||||
&values );
|
||||
}
|
||||
|
||||
// for first CRTC1, we need to setup RMX properly
|
||||
if( !head->is_crtc2 )
|
||||
Radeon_CalcRMXRegisters( fp_info, mode,
|
||||
(disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0,
|
||||
&values );
|
||||
|
||||
if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 )
|
||||
Radeon_CalcFPRegisters( ai, head, fp_info, &values );
|
||||
|
||||
if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
Radeon_CalcTVRegisters( ai, mode, tv_timing, &tv_params, &values,
|
||||
head, internal_tv_encoder, tv_format );
|
||||
// some register's content isn't created from scratch but
|
||||
// only modified, so we need the original content first
|
||||
if( internal_tv_encoder )
|
||||
Radeon_InternalTVOutReadRegisters( ai, &impactv_values );
|
||||
else
|
||||
Radeon_TheatreReadTVRegisters( ai, &impactv_values );
|
||||
}
|
||||
|
||||
Radeon_CalcMonitorRouting( ai, head, &values );
|
||||
|
||||
// calculate all hardware register values
|
||||
Radeon_CalcCRTCRegisters( ai, crtc, mode, &crtc_values );
|
||||
|
||||
surface_cntl = RADEON_SURF_TRANSLATION_DIS;
|
||||
|
||||
if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
Radeon_CalcImpacTVRegisters( ai, mode, tv_params, &impactv_values,
|
||||
crtc->crtc_idx, internal_tv_encoder, vc->tv_standard, disp_devices );
|
||||
}
|
||||
|
||||
if( (disp_devices & (dd_stv | dd_ctv)) == 0 )
|
||||
Radeon_CalcCRTPLLDividers( &si->pll, mode, ÷rs );
|
||||
else
|
||||
dividers = tv_params->crt_dividers;
|
||||
|
||||
Radeon_CalcPLLRegisters( mode, ÷rs, &pll_values );
|
||||
|
||||
// for first CRTC1, we need to setup RMX properly
|
||||
if( crtc->crtc_idx == 0 )
|
||||
Radeon_CalcRMXRegisters( fp_info, mode,
|
||||
(disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0,
|
||||
&fp_values );
|
||||
|
||||
if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 )
|
||||
Radeon_CalcFPRegisters( ai, crtc, fp_info, &crtc_values, &fp_values );
|
||||
|
||||
// we don't use pixel clock anymore, so it can be reset to Be's kHz
|
||||
mode->timing.pixel_clock /= 1000;
|
||||
|
||||
// write values to registers
|
||||
// we first switch off all output, so the monitor(s) won't get invalid signals
|
||||
Radeon_SetDPMS( ai, head, B_DPMS_SUSPEND );
|
||||
|
||||
Radeon_InitCommonRegs( ai );
|
||||
|
||||
Radeon_ProgramCRTCRegisters( ai, head, &values );
|
||||
|
||||
Radeon_ProgramCRTCRegisters( ai, crtc->crtc_idx, &crtc_values );
|
||||
|
||||
OUTREG( regs, RADEON_SURFACE_CNTL, surface_cntl );
|
||||
|
||||
OUTREG( regs, RADEON_SURFACE_CNTL, values.surface_cntl );
|
||||
|
||||
if( !head->is_crtc2 )
|
||||
Radeon_ProgramRMXRegisters( ai, &values );
|
||||
if( crtc->crtc_idx == 0 )
|
||||
Radeon_ProgramRMXRegisters( ai, &fp_values );
|
||||
|
||||
if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 )
|
||||
Radeon_ProgramFPRegisters( ai, head, fp_info, &values );
|
||||
|
||||
Radeon_ProgramFPRegisters( ai, crtc, fp_info, &fp_values );
|
||||
|
||||
//if( mode->timing.pixel_clock )
|
||||
Radeon_ProgramPLL( ai, head, &values );
|
||||
|
||||
if( (disp_devices & (dd_ctv | dd_stv)) != 0 )
|
||||
Radeon_ProgramTVRegisters( ai, &values, internal_tv_encoder );
|
||||
|
||||
Radeon_ProgramMonitorRouting( ai, head, &values );
|
||||
Radeon_ProgramPLL( ai, crtc->crtc_idx, &pll_values );
|
||||
|
||||
head->active_displays = disp_devices;
|
||||
if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
if( internal_tv_encoder )
|
||||
Radeon_InternalTVOutProgramRegisters( ai, &impactv_values );
|
||||
else
|
||||
Radeon_TheatreProgramTVRegisters( ai, &impactv_values );
|
||||
}
|
||||
|
||||
crtc->active_displays = disp_devices;
|
||||
|
||||
// programming is over, so hardware can be used again
|
||||
RELEASE_BEN( si->cp.lock );
|
||||
|
||||
// well done - switch display(s) on
|
||||
Radeon_SetDPMS( ai, head, B_DPMS_ON );
|
||||
|
||||
// overlay must be setup again after modeswitch (whoever was using it)
|
||||
// TBD: this won't work if another virtual card was using it,
|
||||
// but currently, virtual cards don't work anyway...
|
||||
si->active_overlay.head = -1;
|
||||
si->active_overlay.crtc_idx = -1;
|
||||
}
|
||||
|
||||
|
||||
// enable or disable VBlank interrupts
|
||||
void Radeon_EnableIRQ( accelerator_info *ai, bool enable )
|
||||
void Radeon_EnableIRQ(
|
||||
accelerator_info *ai, bool enable )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
uint32 int_cntl, int_mask;
|
||||
@@ -234,7 +265,7 @@ void Radeon_EnableIRQ( accelerator_info *ai, bool enable )
|
||||
int_cntl = INREG( ai->regs, RADEON_GEN_INT_CNTL );
|
||||
int_mask =
|
||||
RADEON_CRTC_VBLANK_MASK
|
||||
| (si->num_heads > 1 ? RADEON_CRTC2_VBLANK_MASK : 0);
|
||||
| (si->num_crtc > 1 ? RADEON_CRTC2_VBLANK_MASK : 0);
|
||||
|
||||
if( enable )
|
||||
int_cntl |= int_mask;
|
||||
@@ -254,7 +285,8 @@ void Radeon_EnableIRQ( accelerator_info *ai, bool enable )
|
||||
|
||||
|
||||
// public function: set display mode
|
||||
status_t SET_DISPLAY_MODE( display_mode *mode_in )
|
||||
status_t SET_DISPLAY_MODE(
|
||||
display_mode *mode_in )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
@@ -281,11 +313,16 @@ status_t SET_DISPLAY_MODE( display_mode *mode_in )
|
||||
|
||||
// mode switches can take quite long and are visible,
|
||||
// so avoid them if possible
|
||||
if( memcmp( &mode, &vc->mode, sizeof( display_mode )) == 0 ) {
|
||||
if( memcmp( &mode, &vc->mode, sizeof( display_mode )) == 0 &&
|
||||
!vc->enforce_mode_change ) {
|
||||
RELEASE_BEN( si->engine.lock );
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// this flag was set when some internal parameter has changed that
|
||||
// affects effective display mode
|
||||
vc->enforce_mode_change = false;
|
||||
|
||||
// make sure, we don't get disturbed
|
||||
//Radeon_Finish( ai );
|
||||
Radeon_EnableIRQ( ai, false );
|
||||
@@ -318,9 +355,14 @@ status_t SET_DISPLAY_MODE( display_mode *mode_in )
|
||||
Radeon_VerifyMultiMode( vc, si, &mode );
|
||||
|
||||
// set main flags
|
||||
vc->independant_heads = Radeon_NeedsSecondPort( &mode ) ? 2 : 1;
|
||||
vc->independant_heads = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none;
|
||||
|
||||
if( si->num_crtc > 1 )
|
||||
vc->independant_heads += vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none;
|
||||
|
||||
vc->different_heads = Radeon_DifferentPorts( &mode );
|
||||
SHOW_FLOW( 2, "independant heads: %d", vc->independant_heads );
|
||||
SHOW_FLOW( 2, "independant heads: %d, different heads: %d",
|
||||
vc->independant_heads, vc->different_heads );
|
||||
vc->scroll = mode.flags & B_SCROLL;
|
||||
SHOW_FLOW( 2, "scrolling %s", vc->scroll ? "enabled" : "disabled" );
|
||||
|
||||
@@ -372,14 +414,50 @@ status_t SET_DISPLAY_MODE( display_mode *mode_in )
|
||||
}
|
||||
|
||||
// multi-screen stuff
|
||||
Radeon_InitMultiModeVars( vc, &mode );
|
||||
Radeon_InitMultiModeVars( ai, &mode );
|
||||
|
||||
// GO!
|
||||
Radeon_SetMode( ai, &si->heads[vc->heads[0].physical_head], &mode );
|
||||
|
||||
{
|
||||
routing_regs routing_values;
|
||||
impactv_params tv_params;
|
||||
|
||||
// we first switch off all output, so the monitor(s) won't get invalid signals
|
||||
if( vc->assigned_crtc[0] ) {
|
||||
// overwrite list of active displays to switch off displays
|
||||
// someone else turned on
|
||||
si->crtc[0].active_displays = vc->controlled_displays;
|
||||
Radeon_SetDPMS( ai, 0, B_DPMS_SUSPEND );
|
||||
}
|
||||
if( vc->assigned_crtc[1] ) {
|
||||
si->crtc[1].active_displays = vc->controlled_displays;
|
||||
Radeon_SetDPMS( ai, 1, B_DPMS_SUSPEND );
|
||||
}
|
||||
|
||||
// mark crtc that will be used from now on
|
||||
vc->used_crtc[0] = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none;
|
||||
vc->used_crtc[1] = vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none;
|
||||
|
||||
// then change the mode
|
||||
if( vc->used_crtc[0] )
|
||||
Radeon_SetMode( ai, &si->crtc[0], &mode, &tv_params );
|
||||
if( vc->used_crtc[1] )
|
||||
Radeon_SetMode( ai, &si->crtc[1], &mode, &tv_params );
|
||||
|
||||
// setup signal routing
|
||||
Radeon_ReadMonitorRoutingRegs( ai, &routing_values );
|
||||
Radeon_CalcMonitorRouting( ai, &tv_params, &routing_values );
|
||||
Radeon_ProgramMonitorRouting( ai, &routing_values );
|
||||
|
||||
// finally, switch display(s) on
|
||||
if( vc->used_crtc[0] )
|
||||
Radeon_SetDPMS( ai, 0, B_DPMS_ON );
|
||||
if( vc->used_crtc[1] )
|
||||
Radeon_SetDPMS( ai, 1, B_DPMS_ON );
|
||||
|
||||
OUTREGP( ai->regs, RADEON_CRTC_EXT_CNTL, 0, ~RADEON_CRTC_DISPLAY_DIS );
|
||||
}
|
||||
|
||||
if( vc->independant_heads > 1 )
|
||||
Radeon_SetMode( ai, &si->heads[vc->heads[1].physical_head], &mode );
|
||||
|
||||
SHOW_FLOW( 3, "pitch=%ld", vc->pitch );
|
||||
|
||||
// we'll modify bits of this reg, so save it for async access
|
||||
@@ -399,18 +477,18 @@ status_t SET_DISPLAY_MODE( display_mode *mode_in )
|
||||
Radeon_MoveDisplay( ai, mode.h_display_start, mode.v_display_start );
|
||||
|
||||
// set standard palette in direct-colour modes
|
||||
Radeon_InitPalette( ai, &si->heads[vc->heads[0].physical_head] );
|
||||
if( vc->independant_heads > 1 )
|
||||
Radeon_InitPalette( ai, &si->heads[vc->heads[1].physical_head] );
|
||||
if( vc->used_crtc[0] )
|
||||
Radeon_InitPalette( ai, 0 );
|
||||
if( vc->used_crtc[1] )
|
||||
Radeon_InitPalette( ai, 1 );
|
||||
|
||||
// initialize cursor data
|
||||
Radeon_SetCursorColors( ai, &si->heads[vc->heads[0].physical_head] );
|
||||
if( vc->independant_heads > 1 )
|
||||
Radeon_SetCursorColors( ai, &si->heads[vc->heads[1].physical_head] );
|
||||
if( vc->used_crtc[0] )
|
||||
Radeon_SetCursorColors( ai, 0 );
|
||||
if( vc->used_crtc[1] )
|
||||
Radeon_SetCursorColors( ai, 1 );
|
||||
|
||||
// sync should be settled now, so we can reenable IRQs
|
||||
// TBD: IRQ handling doesn't work correctly and doesn't make sense with two
|
||||
// displays connected, so let's leave them disabled for now
|
||||
Radeon_EnableIRQ( ai, true );
|
||||
|
||||
RELEASE_BEN( si->engine.lock );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2005, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -10,37 +10,35 @@
|
||||
#include "radeon_accelerant.h"
|
||||
#include "mmio.h"
|
||||
#include "crtc_regs.h"
|
||||
#include "dac_regs.h"
|
||||
#include "GlobalData.h"
|
||||
|
||||
|
||||
// read old CRTC register content
|
||||
void Radeon_ReadCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
// only CRTC_EXT_CNTL is programmed by someone else (namely the monitor
|
||||
// router); if more registers are affected, you must read them here too!
|
||||
if( !head->is_crtc2 ) {
|
||||
values->crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL );
|
||||
}
|
||||
}
|
||||
#include "set_mode.h"
|
||||
|
||||
|
||||
// hammer CRTC registers
|
||||
void Radeon_ProgramCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values )
|
||||
void Radeon_ProgramCRTCRegisters( accelerator_info *ai, int crtc_idx,
|
||||
crtc_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
if( head->is_crtc2 ) {
|
||||
if( crtc_idx == 0 ) {
|
||||
OUTREGP( regs, RADEON_CRTC_GEN_CNTL, values->crtc_gen_cntl,
|
||||
RADEON_CRTC_EXT_DISP_EN );
|
||||
|
||||
OUTREG( regs, RADEON_CRTC_H_TOTAL_DISP, values->crtc_h_total_disp );
|
||||
OUTREG( regs, RADEON_CRTC_H_SYNC_STRT_WID, values->crtc_h_sync_strt_wid );
|
||||
OUTREG( regs, RADEON_CRTC_V_TOTAL_DISP, values->crtc_v_total_disp );
|
||||
OUTREG( regs, RADEON_CRTC_V_SYNC_STRT_WID, values->crtc_v_sync_strt_wid );
|
||||
OUTREG( regs, RADEON_CRTC_OFFSET_CNTL, values->crtc_offset_cntl );
|
||||
OUTREG( regs, RADEON_CRTC_PITCH, values->crtc_pitch );
|
||||
|
||||
} else {
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, values->crtc_gen_cntl,
|
||||
RADEON_CRTC2_VSYNC_DIS |
|
||||
RADEON_CRTC2_HSYNC_DIS |
|
||||
RADEON_CRTC2_DISP_DIS );
|
||||
RADEON_CRTC2_DISP_DIS |
|
||||
RADEON_CRTC2_CRT2_ON );
|
||||
|
||||
OUTREG( regs, RADEON_CRTC2_H_TOTAL_DISP, values->crtc_h_total_disp );
|
||||
OUTREG( regs, RADEON_CRTC2_H_SYNC_STRT_WID, values->crtc_h_sync_strt_wid );
|
||||
@@ -48,37 +46,18 @@ void Radeon_ProgramCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
OUTREG( regs, RADEON_CRTC2_V_SYNC_STRT_WID, values->crtc_v_sync_strt_wid );
|
||||
OUTREG( regs, RADEON_CRTC2_OFFSET_CNTL, values->crtc_offset_cntl );
|
||||
OUTREG( regs, RADEON_CRTC2_PITCH, values->crtc_pitch );
|
||||
|
||||
} else {
|
||||
OUTREG( regs, RADEON_CRTC_GEN_CNTL, values->crtc_gen_cntl );
|
||||
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, values->crtc_ext_cntl,
|
||||
RADEON_CRTC_VSYNC_DIS |
|
||||
RADEON_CRTC_HSYNC_DIS |
|
||||
RADEON_CRTC_DISPLAY_DIS |
|
||||
RADEON_CRTC_CRT_ON );
|
||||
|
||||
OUTREGP( regs, RADEON_DAC_CNTL, values->dac_cntl,
|
||||
RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_BLANKING );
|
||||
|
||||
OUTREG( regs, RADEON_CRTC_H_TOTAL_DISP, values->crtc_h_total_disp );
|
||||
OUTREG( regs, RADEON_CRTC_H_SYNC_STRT_WID, values->crtc_h_sync_strt_wid );
|
||||
OUTREG( regs, RADEON_CRTC_V_TOTAL_DISP, values->crtc_v_total_disp );
|
||||
OUTREG( regs, RADEON_CRTC_V_SYNC_STRT_WID, values->crtc_v_sync_strt_wid );
|
||||
OUTREG( regs, RADEON_CRTC_OFFSET_CNTL, values->crtc_offset_cntl );
|
||||
OUTREG( regs, RADEON_CRTC_PITCH, values->crtc_pitch );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get required hsync delay depending on bit depth and output device
|
||||
uint16 Radeon_GetHSyncFudge( physical_head *head, int datatype )
|
||||
uint16 Radeon_GetHSyncFudge( crtc_info *crtc, int datatype )
|
||||
{
|
||||
static int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
|
||||
static int hsync_fudge_fp[] = { 0x02, 0x02, 0x00, 0x00, 0x05, 0x05 };
|
||||
|
||||
// there is an sync delay which depends on colour-depth and output device
|
||||
if( (head->chosen_displays & (dd_dvi | dd_dvi_ext | dd_lvds )) != 0 )
|
||||
if( (crtc->chosen_displays & (dd_dvi | dd_dvi_ext | dd_lvds )) != 0 )
|
||||
return hsync_fudge_fp[datatype - 1];
|
||||
else
|
||||
return hsync_fudge_default[datatype - 1];
|
||||
@@ -86,8 +65,8 @@ uint16 Radeon_GetHSyncFudge( physical_head *head, int datatype )
|
||||
|
||||
|
||||
// calculate CRTC register content
|
||||
void Radeon_CalcCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
display_mode *mode, port_regs *values )
|
||||
void Radeon_CalcCRTCRegisters( accelerator_info *ai, crtc_info *crtc,
|
||||
display_mode *mode, crtc_regs *values )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
int hsync_start;
|
||||
@@ -95,29 +74,21 @@ void Radeon_CalcCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
int hsync_fudge;
|
||||
int vsync_wid;
|
||||
|
||||
hsync_fudge = Radeon_GetHSyncFudge( head, vc->datatype );
|
||||
hsync_fudge = Radeon_GetHSyncFudge( crtc, vc->datatype );
|
||||
|
||||
if( head->is_crtc2 ) {
|
||||
values->crtc_gen_cntl = (RADEON_CRTC2_EN
|
||||
| RADEON_CRTC2_CRT2_ON
|
||||
if( crtc->crtc_idx == 0 ) {
|
||||
// here, we should set interlace/double scan mode
|
||||
// but we don't support them (anyone missing them?)
|
||||
values->crtc_gen_cntl =
|
||||
RADEON_CRTC_EN
|
||||
| (vc->datatype << 8);
|
||||
|
||||
} else {
|
||||
values->crtc_gen_cntl = RADEON_CRTC2_EN
|
||||
| (vc->datatype << 8)
|
||||
| (0/*doublescan*/ ? RADEON_CRTC2_DBL_SCAN_EN : 0)
|
||||
| ((mode->timing.flags & B_TIMING_INTERLACED)
|
||||
? RADEON_CRTC2_INTERLACE_EN : 0));
|
||||
} else {
|
||||
// here, we should set interlace/double scan mode
|
||||
// but we don't support them (anyone missing them?)
|
||||
values->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
|
||||
| RADEON_CRTC_EN
|
||||
| (vc->datatype << 8));
|
||||
|
||||
values->crtc_ext_cntl =
|
||||
RADEON_VGA_ATI_LINEAR |
|
||||
RADEON_XCRT_CNT_EN;
|
||||
|
||||
values->dac_cntl = RADEON_DAC_MASK_ALL
|
||||
| RADEON_DAC_VGA_ADR_EN
|
||||
| RADEON_DAC_8BIT_EN;
|
||||
? RADEON_CRTC2_INTERLACE_EN : 0);
|
||||
}
|
||||
|
||||
values->crtc_h_total_disp =
|
||||
@@ -156,19 +127,19 @@ void Radeon_CalcCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
|
||||
|
||||
// update shown are of one port
|
||||
static void moveOneDisplay( accelerator_info *ai, virtual_head *virtual_head )
|
||||
static void moveOneDisplay( accelerator_info *ai, crtc_info *crtc )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
uint32 offset;
|
||||
|
||||
offset = (vc->mode.v_display_start + virtual_head->rel_y) * vc->pitch +
|
||||
(vc->mode.h_display_start + virtual_head->rel_x) * vc->bpp +
|
||||
offset = (vc->mode.v_display_start + crtc->rel_y) * vc->pitch +
|
||||
(vc->mode.h_display_start + crtc->rel_x) * vc->bpp +
|
||||
vc->fb_offset;
|
||||
|
||||
SHOW_FLOW( 3, "Setting address %x on port %d",
|
||||
offset, virtual_head->physical_head );
|
||||
offset, crtc->crtc_idx );
|
||||
|
||||
OUTREG( ai->regs, virtual_head->physical_head ? RADEON_CRTC2_OFFSET : RADEON_CRTC_OFFSET, offset );
|
||||
OUTREG( ai->regs, crtc->crtc_idx == 0 ? RADEON_CRTC_OFFSET : RADEON_CRTC2_OFFSET, offset );
|
||||
}
|
||||
|
||||
// internal function: pan display
|
||||
@@ -189,10 +160,10 @@ status_t Radeon_MoveDisplay( accelerator_info *ai, uint16 h_display_start, uint1
|
||||
vc->mode.v_display_start = v_display_start;
|
||||
|
||||
// do it
|
||||
moveOneDisplay( ai, &vc->heads[0] );
|
||||
|
||||
if( vc->independant_heads > 1 )
|
||||
moveOneDisplay( ai, &vc->heads[1] );
|
||||
if( vc->used_crtc[0] )
|
||||
moveOneDisplay( ai, &ai->si->crtc[0] );
|
||||
if( vc->used_crtc[1] )
|
||||
moveOneDisplay( ai, &ai->si->crtc[1] );
|
||||
|
||||
// overlay position must be adjusted
|
||||
Radeon_UpdateOverlay( ai );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "fp_regs.h"
|
||||
#include "pll_regs.h"
|
||||
#include "pll_access.h"
|
||||
#include "tv_out_regs.h"
|
||||
#include "theatre_regs.h"
|
||||
#include "GlobalData.h"
|
||||
|
||||
|
||||
@@ -20,15 +22,14 @@
|
||||
status_t SET_DPMS_MODE(uint32 dpms_flags)
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
status_t result1, result2;
|
||||
|
||||
result1 = Radeon_SetDPMS( ai, &si->heads[vc->heads[0].physical_head], dpms_flags );
|
||||
|
||||
if( vc->independant_heads > 1 )
|
||||
result2 = Radeon_SetDPMS( ai, &si->heads[vc->heads[1].physical_head], dpms_flags );
|
||||
else
|
||||
status_t
|
||||
result1 = B_OK,
|
||||
result2 = B_OK;
|
||||
|
||||
if( vc->used_crtc[0] )
|
||||
result1 = Radeon_SetDPMS( ai, 0, dpms_flags );
|
||||
if( vc->used_crtc[0] )
|
||||
result1 = Radeon_SetDPMS( ai, 0, dpms_flags );
|
||||
|
||||
if( result1 == B_OK && result2 == B_OK )
|
||||
return B_OK;
|
||||
@@ -46,8 +47,8 @@ uint32 DPMS_CAPABILITIES(void)
|
||||
// public function: get current DPMS mode
|
||||
uint32 DPMS_MODE(void)
|
||||
{
|
||||
// we just ask the primary head what status it is in
|
||||
return Radeon_GetDPMS( ai, &ai->si->heads[ai->vc->heads[0].physical_head] );
|
||||
// we just ask the primary virtual head what status it is in
|
||||
return Radeon_GetDPMS( ai, ai->vc->used_crtc[0] ? 0 : 1 );
|
||||
}
|
||||
|
||||
|
||||
@@ -137,14 +138,56 @@ static void Radeon_SetDPMS_FP2( accelerator_info *ai, int mode )
|
||||
}
|
||||
|
||||
|
||||
// set DPMS mode for first port
|
||||
// set DPMS mode for CRT DAC.
|
||||
// warning: the CRTC-DAC only obbeys this setting if
|
||||
// connected to CRTC1, else it collides with TV-DAC
|
||||
static void Radeon_SetDPMS_CRT( accelerator_info *ai, int mode )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, 0, ~RADEON_CRTC_DISPLAY_DIS );
|
||||
break;
|
||||
|
||||
case B_DPMS_STAND_BY:
|
||||
case B_DPMS_SUSPEND:
|
||||
case B_DPMS_OFF:
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
|
||||
RADEON_CRTC_DISPLAY_DIS, ~RADEON_CRTC_DISPLAY_DIS );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set DPMS mode for TV-DAC in CRT mode
|
||||
// warning: if the CRT-DAC is connected to CRTC2, it is
|
||||
// affected by this setting too
|
||||
static void Radeon_SetDPMS_TVCRT( accelerator_info *ai, int mode )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_DISP_DIS );
|
||||
break;
|
||||
|
||||
case B_DPMS_STAND_BY:
|
||||
case B_DPMS_SUSPEND:
|
||||
case B_DPMS_OFF:
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL,
|
||||
RADEON_CRTC2_DISP_DIS, ~RADEON_CRTC2_DISP_DIS );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set DPMS mode for first CRTC
|
||||
static void Radeon_SetDPMS_CRTC1( accelerator_info *ai, int mode )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
int mask = RADEON_CRTC_DISPLAY_DIS
|
||||
| RADEON_CRTC_HSYNC_DIS
|
||||
| RADEON_CRTC_VSYNC_DIS;
|
||||
uint32 mask = RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS;
|
||||
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
@@ -154,29 +197,42 @@ static void Radeon_SetDPMS_CRTC1( accelerator_info *ai, int mode )
|
||||
case B_DPMS_STAND_BY:
|
||||
/* Screen: Off; HSync: Off, VSync: On */
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
|
||||
RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS, ~mask );
|
||||
RADEON_CRTC_HSYNC_DIS, ~mask );
|
||||
break;
|
||||
case B_DPMS_SUSPEND:
|
||||
/* Screen: Off; HSync: On, VSync: Off */
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
|
||||
RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS, ~mask );
|
||||
RADEON_CRTC_VSYNC_DIS, ~mask );
|
||||
break;
|
||||
case B_DPMS_OFF:
|
||||
/* Screen: Off; HSync: Off, VSync: Off */
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, mask, ~mask );
|
||||
break;
|
||||
}
|
||||
|
||||
// disable/enable memory requests and cursor
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
/* Screen: On; HSync: On, VSync: On */
|
||||
OUTREGP( regs, RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B );
|
||||
Radeon_ShowCursor( ai, 0 );
|
||||
break;
|
||||
case B_DPMS_STAND_BY:
|
||||
case B_DPMS_SUSPEND:
|
||||
case B_DPMS_OFF:
|
||||
OUTREGP( regs, RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B,
|
||||
~(RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_CUR_EN) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set DPMS mode of second port
|
||||
static void Radeon_SetDPMS_CRTC2( accelerator_info *di, int mode )
|
||||
// set DPMS mode of second CRTC
|
||||
static void Radeon_SetDPMS_CRTC2( accelerator_info *ai, int mode )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
int mask = RADEON_CRTC2_DISP_DIS
|
||||
| RADEON_CRTC2_HSYNC_DIS
|
||||
| RADEON_CRTC2_VSYNC_DIS;
|
||||
int mask = RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_VSYNC_DIS;
|
||||
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
@@ -186,36 +242,54 @@ static void Radeon_SetDPMS_CRTC2( accelerator_info *di, int mode )
|
||||
case B_DPMS_STAND_BY:
|
||||
/* Screen: Off; HSync: Off, VSync: On */
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL,
|
||||
RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, ~mask );
|
||||
RADEON_CRTC2_HSYNC_DIS, ~mask );
|
||||
break;
|
||||
case B_DPMS_SUSPEND:
|
||||
/* Screen: Off; HSync: On, VSync: Off */
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL,
|
||||
RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, ~mask );
|
||||
RADEON_CRTC2_VSYNC_DIS, ~mask );
|
||||
break;
|
||||
case B_DPMS_OFF:
|
||||
/* Screen: Off; HSync: Off, VSync: Off */
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, mask, ~mask );
|
||||
break;
|
||||
}
|
||||
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
/* Screen: On; HSync: On, VSync: On */
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_DISP_REQ_EN_B );
|
||||
Radeon_ShowCursor( ai, 1 );
|
||||
break;
|
||||
case B_DPMS_STAND_BY:
|
||||
case B_DPMS_SUSPEND:
|
||||
case B_DPMS_OFF:
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_REQ_EN_B,
|
||||
~(RADEON_CRTC2_DISP_REQ_EN_B | RADEON_CRTC2_CUR_EN) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set DPMS mode of TV-out
|
||||
static void Radeon_SetDPMS_TVOUT( accelerator_info *ai, int mode )
|
||||
{
|
||||
// we set to gain either to 0 for blank or 1 for normal operation
|
||||
if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) {
|
||||
OUTREG( ai->regs, RADEON_TV_LINEAR_GAIN_SETTINGS,
|
||||
mode == B_DPMS_ON ? 0x01000100 : 0 );
|
||||
} else {
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, RADEON_TV_LINEAR_GAIN_SETTINGS,
|
||||
mode == B_DPMS_ON ? 0x01000100 : 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// set DPMS mode of one port
|
||||
// engine lock is assumed to be hold
|
||||
status_t Radeon_SetDPMS( accelerator_info *ai, physical_head *head, int mode )
|
||||
status_t Radeon_SetDPMS( accelerator_info *ai, int crtc_idx, int mode )
|
||||
{
|
||||
/* // if we have a laptop panel
|
||||
// and we have a second screen connected
|
||||
// and they both show the same content,
|
||||
// then switch the laptop display always off
|
||||
if( ai->si->ports[port->physical_port].disp_type == dt_lvds &&
|
||||
ai->vc->independant_ports > 1 &&
|
||||
ai->vc->different_ports == 1 )
|
||||
{
|
||||
mode = B_DPMS_OFF;
|
||||
}*/
|
||||
|
||||
crtc_info *crtc = &ai->si->crtc[crtc_idx];
|
||||
|
||||
// test validity of mode once and for all
|
||||
switch( mode ) {
|
||||
case B_DPMS_ON:
|
||||
@@ -227,18 +301,34 @@ status_t Radeon_SetDPMS( accelerator_info *ai, physical_head *head, int mode )
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if( head->is_crtc2 )
|
||||
Radeon_SetDPMS_CRTC2( ai, mode );
|
||||
else
|
||||
if( crtc_idx == 0 )
|
||||
Radeon_SetDPMS_CRTC1( ai, mode );
|
||||
|
||||
if( (head->active_displays & dd_lvds) != 0 )
|
||||
else
|
||||
Radeon_SetDPMS_CRTC2( ai, mode );
|
||||
|
||||
// possible ASIC bug: if CRT-DAC is connected to CRTC1, it obbeys
|
||||
// RADEON_CRTC_DISPLAY_DIS; if it is connected to CRTC2, to
|
||||
// RADEON_CRTC2_DISP_DIS - i.e. it follows the CRTC;
|
||||
// but the TV-DAC always listens to RADEON_CRTC2_DISP_DIS, independant
|
||||
// of the CRTC it gets its signal from;
|
||||
// this is a guarantee that two virtual cards will collide!
|
||||
if( crtc_idx == 0 || 1/* && (crtc->active_displays & dd_crt) != 0 */)
|
||||
Radeon_SetDPMS_CRT( ai, mode );
|
||||
|
||||
if( crtc_idx == 1 || (crtc->active_displays & (dd_tv_crt | dd_ctv | dd_stv)) != 0 )
|
||||
Radeon_SetDPMS_TVCRT( ai, mode );
|
||||
|
||||
// TV-Out ignores DPMS completely, including the blank-screen trick
|
||||
if( (crtc->active_displays & (dd_ctv | dd_stv)) != 0 )
|
||||
Radeon_SetDPMS_TVOUT( ai, mode );
|
||||
|
||||
if( (crtc->active_displays & dd_lvds) != 0 )
|
||||
Radeon_SetDPMS_LVDS( ai, mode );
|
||||
|
||||
if( (head->active_displays & dd_dvi) != 0 )
|
||||
if( (crtc->active_displays & dd_dvi) != 0 )
|
||||
Radeon_SetDPMS_DVI( ai, mode );
|
||||
|
||||
if( (head->active_displays & dd_dvi_ext) != 0 )
|
||||
if( (crtc->active_displays & dd_dvi_ext) != 0 )
|
||||
Radeon_SetDPMS_FP2( ai, mode );
|
||||
|
||||
return B_OK;
|
||||
@@ -246,7 +336,7 @@ status_t Radeon_SetDPMS( accelerator_info *ai, physical_head *head, int mode )
|
||||
|
||||
|
||||
// get DPMS mode of first port
|
||||
uint32 Radeon_GetDPMS_CRTC1( accelerator_info *di )
|
||||
static uint32 Radeon_GetDPMS_CRTC1( accelerator_info *di )
|
||||
{
|
||||
uint32 tmp;
|
||||
|
||||
@@ -266,7 +356,7 @@ uint32 Radeon_GetDPMS_CRTC1( accelerator_info *di )
|
||||
|
||||
|
||||
// get DPMS mode of second port
|
||||
uint32 Radeon_GetDPMS_CRTC2( accelerator_info *di )
|
||||
static uint32 Radeon_GetDPMS_CRTC2( accelerator_info *di )
|
||||
{
|
||||
uint32 tmp;
|
||||
|
||||
@@ -286,10 +376,10 @@ uint32 Radeon_GetDPMS_CRTC2( accelerator_info *di )
|
||||
|
||||
|
||||
// get DPMS mode of one port
|
||||
uint32 Radeon_GetDPMS( accelerator_info *ai, physical_head *head )
|
||||
uint32 Radeon_GetDPMS( accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
if( head->is_crtc2 )
|
||||
return Radeon_GetDPMS_CRTC2( ai );
|
||||
else
|
||||
if( crtc_idx == 0 )
|
||||
return Radeon_GetDPMS_CRTC1( ai );
|
||||
else
|
||||
return Radeon_GetDPMS_CRTC2( ai );
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ status_t Radeon_VIPRead( accelerator_info *ai, uint channel, uint address, uint3
|
||||
vr.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
vr.channel = channel;
|
||||
vr.address = address;
|
||||
vr.lock = false;
|
||||
|
||||
res = ioctl( ai->fd, RADEON_VIPREAD, &vr, sizeof( vr ));
|
||||
|
||||
@@ -57,6 +58,7 @@ status_t Radeon_VIPWrite( accelerator_info *ai, uint8 channel, uint address, uin
|
||||
vw.channel = channel;
|
||||
vw.address = address;
|
||||
vw.data = data;
|
||||
vw.lock = false;
|
||||
|
||||
return ioctl( ai->fd, RADEON_VIPWRITE, &vw, sizeof( vw ));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -10,12 +10,13 @@
|
||||
#include "radeon_accelerant.h"
|
||||
#include "mmio.h"
|
||||
#include "fp_regs.h"
|
||||
#include "memcntrl_regs.h"
|
||||
#include "utils.h"
|
||||
#include "crtc_regs.h"
|
||||
#include "pll_regs.h"
|
||||
#include "set_mode.h"
|
||||
|
||||
|
||||
void Radeon_ReadRMXRegisters( accelerator_info *ai, port_regs *values )
|
||||
void Radeon_ReadRMXRegisters(
|
||||
accelerator_info *ai, fp_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
@@ -23,7 +24,8 @@ void Radeon_ReadRMXRegisters( accelerator_info *ai, port_regs *values )
|
||||
values->fp_vert_stretch = INREG( regs, RADEON_FP_VERT_STRETCH );
|
||||
}
|
||||
|
||||
void Radeon_CalcRMXRegisters( fp_info *flatpanel, display_mode *mode, bool use_rmx, port_regs *values )
|
||||
void Radeon_CalcRMXRegisters(
|
||||
fp_info *flatpanel, display_mode *mode, bool use_rmx, fp_regs *values )
|
||||
{
|
||||
uint xres = mode->timing.h_display;
|
||||
uint yres = mode->timing.v_display;
|
||||
@@ -100,7 +102,8 @@ void Radeon_CalcRMXRegisters( fp_info *flatpanel, display_mode *mode, bool use_r
|
||||
}
|
||||
|
||||
// write RMX registers
|
||||
void Radeon_ProgramRMXRegisters( accelerator_info *ai, port_regs *values )
|
||||
void Radeon_ProgramRMXRegisters(
|
||||
accelerator_info *ai, fp_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
@@ -109,7 +112,8 @@ void Radeon_ProgramRMXRegisters( accelerator_info *ai, port_regs *values )
|
||||
}
|
||||
|
||||
|
||||
void Radeon_ReadFPRegisters( accelerator_info *ai, port_regs *values )
|
||||
void Radeon_ReadFPRegisters(
|
||||
accelerator_info *ai, fp_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
@@ -128,18 +132,19 @@ void Radeon_ReadFPRegisters( accelerator_info *ai, port_regs *values )
|
||||
|
||||
// calculcate flat panel crtc registers;
|
||||
// must be called after normal CRTC registers are determined
|
||||
void Radeon_CalcFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
fp_info *fp_port, port_regs *values )
|
||||
void Radeon_CalcFPRegisters(
|
||||
accelerator_info *ai, crtc_info *crtc,
|
||||
fp_info *fp_port, crtc_regs *crtc_values, fp_regs *values )
|
||||
{
|
||||
// setup synchronization position
|
||||
// (most values are ignored according to fp_gen_cntl, but at least polarity
|
||||
// and pixel precise horizontal sync position are always used)
|
||||
if( fp_port->is_fp2 ) {
|
||||
values->fp2_h_sync_strt_wid = values->crtc_h_sync_strt_wid;
|
||||
values->fp2_v_sync_strt_wid = values->crtc_v_sync_strt_wid;
|
||||
values->fp2_h_sync_strt_wid = crtc_values->crtc_h_sync_strt_wid;
|
||||
values->fp2_v_sync_strt_wid = crtc_values->crtc_v_sync_strt_wid;
|
||||
} else {
|
||||
values->fp_h_sync_strt_wid = values->crtc_h_sync_strt_wid;
|
||||
values->fp_v_sync_strt_wid = values->crtc_v_sync_strt_wid;
|
||||
values->fp_h_sync_strt_wid = crtc_values->crtc_h_sync_strt_wid;
|
||||
values->fp_v_sync_strt_wid = crtc_values->crtc_v_sync_strt_wid;
|
||||
}
|
||||
|
||||
if( fp_port->is_fp2 )
|
||||
@@ -147,8 +152,7 @@ void Radeon_CalcFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
else {
|
||||
// setup magic CRTC shadowing
|
||||
values->fp_gen_cntl &=
|
||||
~(RADEON_FP_SEL_CRTC2 |
|
||||
RADEON_FP_RMX_HVSYNC_CONTROL_EN |
|
||||
~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
|
||||
RADEON_FP_DFP_SYNC_SEL |
|
||||
RADEON_FP_CRT_SYNC_SEL |
|
||||
RADEON_FP_CRTC_LOCK_8DOT |
|
||||
@@ -161,7 +165,7 @@ void Radeon_CalcFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
}
|
||||
|
||||
// enable proper transmitter
|
||||
if( (head->chosen_displays & dd_lvds) != 0 ) {
|
||||
if( (crtc->chosen_displays & dd_lvds) != 0 ) {
|
||||
// using LVDS means there cannot be a DVI monitor
|
||||
values->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
|
||||
values->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
|
||||
@@ -188,18 +192,20 @@ void Radeon_CalcFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
|
||||
|
||||
// write flat panel registers
|
||||
void Radeon_ProgramFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
fp_info *fp_port, port_regs *values )
|
||||
void Radeon_ProgramFPRegisters(
|
||||
accelerator_info *ai, crtc_info *crtc,
|
||||
fp_info *fp_port, fp_regs *values )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
OUTREG( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl );
|
||||
OUTREGP( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl, RADEON_FP_SEL_CRTC2 );
|
||||
|
||||
if( fp_port->is_fp2 ) {
|
||||
OUTREG( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl );
|
||||
OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
|
||||
RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 );
|
||||
OUTREG( regs, RADEON_FP_H2_SYNC_STRT_WID, values->fp2_h_sync_strt_wid );
|
||||
OUTREG( regs, RADEON_FP_V2_SYNC_STRT_WID, values->fp2_v_sync_strt_wid );
|
||||
} else {
|
||||
@@ -209,18 +215,13 @@ void Radeon_ProgramFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
|
||||
// workaround for old AIW Radeon having display buffer underflow
|
||||
// in conjunction with DVI
|
||||
if( si->num_heads == 1 ) {
|
||||
if( si->asic == rt_r100 ) {
|
||||
OUTREG( regs, RADEON_GRPH_BUFFER_CNTL,
|
||||
INREG( regs, RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
|
||||
}
|
||||
|
||||
if( (head->chosen_displays & dd_lvds) != 0 ) {
|
||||
if( (crtc->chosen_displays & dd_lvds) != 0 ) {
|
||||
OUTREGP( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl,
|
||||
RADEON_LVDS_ON | RADEON_LVDS_BLON );
|
||||
}
|
||||
|
||||
// disable auto-centering
|
||||
// (we setup everything ourself, and if we switch from flat panel to CRT
|
||||
// on CRTC1, we don't need this stuff anyway)
|
||||
OUTREG( regs, RADEON_CRTC_MORE_CNTL, 0 );
|
||||
}
|
||||
|
||||
+401
-352
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
Copyright (c) 2002/03, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
|
||||
Programming of internal TV-out unit
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
// mapping of offset in impactv_regs to register address
|
||||
typedef struct register_mapping {
|
||||
uint16 address; // register address
|
||||
uint16 offset; // offset in impactv_regs
|
||||
} register_mapping;
|
||||
|
||||
|
||||
// internal TV-encoder:
|
||||
|
||||
// registers to write before programming PLL
|
||||
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 }
|
||||
};
|
||||
|
||||
// PLL registers to program
|
||||
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 }
|
||||
};
|
||||
|
||||
// registers to write after programming of PLL
|
||||
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 }
|
||||
};
|
||||
|
||||
// registers to write when things settled down
|
||||
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 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// write list of MM I/O registers
|
||||
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 ) {
|
||||
/*SHOW_FLOW( 2, "%x=%x", mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );*/
|
||||
|
||||
OUTREG( regs, mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );
|
||||
}
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
|
||||
|
||||
// write list of PLL registers
|
||||
static void writePLLRegList(
|
||||
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
|
||||
{
|
||||
for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) {
|
||||
/*SHOW_FLOW( 2, "%x=%x", mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );*/
|
||||
|
||||
Radeon_OUTPLL( ai->regs, ai->si->asic,
|
||||
mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );
|
||||
}
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// read timing FIFO
|
||||
static uint32 Radeon_InternalTVOutReadFIFO(
|
||||
accelerator_info *ai, uint16 addr )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
bigtime_t start_time;
|
||||
uint32 res = ~0;
|
||||
|
||||
//SHOW_FLOW( 2, "addr=%d", addr );
|
||||
|
||||
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 );
|
||||
|
||||
//SHOW_FLOW( 2, "res=%x %x", res >> 14, res & 0x3fff );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// write to timing FIFO
|
||||
static void Radeon_InternalTVOutWriteFIFO(
|
||||
accelerator_info *ai, uint16 addr, uint32 value )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
bigtime_t start_time;
|
||||
|
||||
//readFIFO( ai, addr, internal_encoder );
|
||||
|
||||
//SHOW_FLOW( 2, "addr=%d, value=%x %x", addr, value >> 14, value & 0x3fff );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
// program TV-Out registers
|
||||
void Radeon_InternalTVOutProgramRegisters(
|
||||
accelerator_info *ai, impactv_regs *values )
|
||||
{
|
||||
uint32 orig_tv_master_cntl = values->tv_master_cntl;
|
||||
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
// disable TV-out when registers are setup
|
||||
// it gets enabled again when things have settled down
|
||||
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 );
|
||||
|
||||
// un-reset FIFO to access timing table
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
// read list of MM I/O registers
|
||||
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 );
|
||||
|
||||
/*SHOW_FLOW( 2, "%x=%x", mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );*/
|
||||
}
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
|
||||
|
||||
// read list of PLL registers
|
||||
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 );
|
||||
|
||||
/*SHOW_FLOW( 2, "%x=%x", mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );*/
|
||||
}
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
|
||||
|
||||
// read TV-Out registers
|
||||
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 );
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002,03 Thomas Kurschel
|
||||
Copyright (c) 2002-2004 Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "ddc_regs.h"
|
||||
#include "gpiopad_regs.h"
|
||||
#include "pll_access.h"
|
||||
#include "theatre_regs.h"
|
||||
#include "set_mode.h"
|
||||
#include "ddc.h"
|
||||
#include <malloc.h>
|
||||
|
||||
@@ -60,38 +62,6 @@ static status_t set_signals( void *cookie, int clk, int data )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// check whether there is a monitor by talking to him via DDC2
|
||||
// ddc_port - register to use for DDC2 communication
|
||||
static bool Radeon_DetectMonitorViaDDC( accelerator_info *ai, uint32 ddc_port )
|
||||
{
|
||||
i2c_bus bus;
|
||||
ddc_port_info info;
|
||||
edid1_info edid;
|
||||
void *vdif;
|
||||
size_t vdif_len;
|
||||
status_t res;
|
||||
|
||||
info.ai = ai;
|
||||
info.port = ddc_port;
|
||||
|
||||
bus.cookie = &info;
|
||||
bus.set_signals = &set_signals;
|
||||
bus.get_signals = &get_signals;
|
||||
|
||||
res = ddc2_read_edid1( &bus, &edid, &vdif, &vdif_len );
|
||||
if( res != B_OK )
|
||||
return false;
|
||||
|
||||
if( vdif != NULL )
|
||||
free( vdif );
|
||||
|
||||
SHOW_INFO( 2, "Found monitor on DDC port 0x%04x", ddc_port );
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
// read EDID information from monitor
|
||||
// ddc_port - register to use for DDC2 communication
|
||||
bool Radeon_ReadEDID( accelerator_info *ai, uint32 ddc_port, edid1_info *edid )
|
||||
@@ -117,7 +87,7 @@ bool Radeon_ReadEDID( accelerator_info *ai, uint32 ddc_port, edid1_info *edid )
|
||||
|
||||
if( vdif != NULL )
|
||||
free( vdif );
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -260,7 +230,10 @@ static bool Radeon_DetectTVCRT_R300( accelerator_info *ai )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
uint32 old_crtc2_gen_cntl, old_tv_dac_cntl, old_dac_cntl2, tmp;
|
||||
uint32 old_radeon_gpiopad_a;
|
||||
bool found;
|
||||
|
||||
old_radeon_gpiopad_a = INREG( regs, RADEON_GPIOPAD_A );
|
||||
|
||||
// whatever these flags mean - let's pray they won't get changed
|
||||
OUTREGP( regs, RADEON_GPIOPAD_EN, 1, ~1 );
|
||||
@@ -307,10 +280,12 @@ static bool Radeon_DetectTVCRT_R300( accelerator_info *ai )
|
||||
found = (INREG( regs, RADEON_DAC_CNTL2 ) & RADEON_DAC2_CMP_OUT_B) != 0;
|
||||
|
||||
// clean up the mess
|
||||
OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
|
||||
OUTREG( regs, RADEON_DAC_EXT_CNTL, 0 );
|
||||
OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
|
||||
OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
|
||||
OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
|
||||
OUTREG( regs, RADEON_DAC_EXT_CNTL, 0 );
|
||||
OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
|
||||
OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
|
||||
|
||||
OUTREGP( regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1 );
|
||||
|
||||
return found;
|
||||
}
|
||||
@@ -323,6 +298,9 @@ static bool Radeon_DetectTVCRT( accelerator_info *ai )
|
||||
case rt_r100:
|
||||
case rt_m6:
|
||||
case rt_m7:
|
||||
case rt_m9:
|
||||
case rt_m9plus:
|
||||
case rt_m10:
|
||||
// original Radeons have pure DVI only and mobility chips
|
||||
// have no DVI connector
|
||||
// TBD: can they have a docking station for CRT on TV-DAC?
|
||||
@@ -332,6 +310,9 @@ static bool Radeon_DetectTVCRT( accelerator_info *ai )
|
||||
case rt_rv200:
|
||||
case rt_rv250:
|
||||
case rt_rv280:
|
||||
// IGP is guessed
|
||||
case rt_rs100:
|
||||
case rt_rs200:
|
||||
return Radeon_DetectTVCRT_RV200( ai );
|
||||
|
||||
case rt_r300:
|
||||
@@ -342,9 +323,10 @@ static bool Radeon_DetectTVCRT( accelerator_info *ai )
|
||||
case rt_r360:
|
||||
return Radeon_DetectTVCRT_R300( ai );
|
||||
|
||||
default:
|
||||
// don't know about IGP
|
||||
;
|
||||
case rt_r200:
|
||||
// r200 has no built-in TV-out and thus no TV-DAC to use for
|
||||
// second CRT
|
||||
return dd_none;
|
||||
}
|
||||
|
||||
return dd_none;
|
||||
@@ -443,6 +425,9 @@ static display_device_e Radeon_DetectTV_R300( accelerator_info *ai )
|
||||
vuint8 *regs = ai->regs;
|
||||
display_device_e displays = dd_none;
|
||||
uint32 tmp, old_dac_cntl2, old_crtc2_gen_cntl, old_dac_ext_cntl, old_tv_dac_cntl;
|
||||
uint32 old_radeon_gpiopad_a;
|
||||
|
||||
old_radeon_gpiopad_a = INREG( regs, RADEON_GPIOPAD_A );
|
||||
|
||||
// whatever these flags mean - let's pray they won't get changed
|
||||
OUTREGP( regs, RADEON_GPIOPAD_EN, 1, ~1 );
|
||||
@@ -511,66 +496,214 @@ static display_device_e Radeon_DetectTV_R300( accelerator_info *ai )
|
||||
OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
|
||||
OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
|
||||
|
||||
// again the magic wire
|
||||
// !if you uncomment this, TV-out gets disabled
|
||||
//OUTREGP( regs, RADEON_GPIOPAD_A, 1, ~1 );
|
||||
OUTREGP( regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1 );
|
||||
|
||||
return displays;
|
||||
}
|
||||
|
||||
|
||||
// save readout of TV detection comparators
|
||||
static bool readTVDetect( accelerator_info *ai )
|
||||
{
|
||||
uint32 tmp;
|
||||
int i;
|
||||
bigtime_t start_time;
|
||||
bool detect;
|
||||
|
||||
// make output constant
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK );
|
||||
|
||||
// check detection result
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp );
|
||||
detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;
|
||||
|
||||
//SHOW_FLOW( 2, "detect=%d", detect );
|
||||
|
||||
start_time = system_time();
|
||||
|
||||
do {
|
||||
// wait for stable detect signal
|
||||
for( i = 0; i < 5; ++i ) {
|
||||
bool cur_detect;
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |
|
||||
RADEON_TV_DAC_CNTL_NHOLD );
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK );
|
||||
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp );
|
||||
cur_detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;
|
||||
|
||||
//SHOW_FLOW( 2, "cur_detect=%d", cur_detect );
|
||||
|
||||
if( cur_detect != detect )
|
||||
break;
|
||||
|
||||
detect = cur_detect;
|
||||
}
|
||||
|
||||
if( i == 5 ) {
|
||||
//SHOW_FLOW( 2, "return %d", detect );
|
||||
return detect;
|
||||
}
|
||||
|
||||
// don't wait forever - give up after 1 second
|
||||
} while( system_time() - start_time < 1000000 );
|
||||
|
||||
SHOW_FLOW0( 2, "timeout" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// detect TV connected to external Theatre-Out
|
||||
static display_device_e Radeon_DetectTV_Theatre( accelerator_info *ai )
|
||||
{
|
||||
uint32
|
||||
old_tv_dac_cntl, old_pre_dac_mux_cntl, old_modulator_cntl1, old_master_cntl;
|
||||
uint32
|
||||
uv_adr, old_last_fifo_entry, old_mid_fifo_entry, last_fifo_addr;
|
||||
display_device_e displays = dd_none;
|
||||
|
||||
if( ai->si->tv_chip != tc_external_rt1 )
|
||||
return dd_none;
|
||||
|
||||
// save previous values (TV-Out may be running)
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &old_tv_dac_cntl );
|
||||
|
||||
// enable DAC and comparators
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT |
|
||||
RADEON_TV_DAC_CNTL_NHOLD | RADEON_TV_DAC_CNTL_NBLANK );
|
||||
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL, &old_pre_dac_mux_cntl );
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1, &old_modulator_cntl1 );
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, &old_master_cntl );
|
||||
|
||||
// save output timing
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_UV_ADR, &uv_adr );
|
||||
|
||||
last_fifo_addr = (uv_adr & RADEON_TV_UV_ADR_MAX_UV_ADR_MASK) * 2 + 1;
|
||||
|
||||
old_last_fifo_entry = Radeon_TheatreReadFIFO( ai, last_fifo_addr );
|
||||
old_mid_fifo_entry = Radeon_TheatreReadFIFO( ai, 0x18f );
|
||||
|
||||
Radeon_TheatreWriteFIFO( ai, last_fifo_addr, 0x20208 );
|
||||
Radeon_TheatreWriteFIFO( ai, 0x18f, 0x3ff2608 );
|
||||
|
||||
// stop TV-Out to savely program it
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
|
||||
RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST | RADEON_TV_MASTER_CNTL_TV_ASYNC_RST );
|
||||
|
||||
// set constant base level
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1,
|
||||
(0x2c << RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT) |
|
||||
(0x2c << RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT) );
|
||||
|
||||
// enable output
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
|
||||
RADEON_TV_MASTER_CNTL_TV_ASYNC_RST );
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
|
||||
0 );
|
||||
|
||||
// set constant Composite output
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
|
||||
RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN |
|
||||
RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN |
|
||||
(9 << RADEON_TV_PRE_DAC_MUX_CNTL_BLU_MX_SHIFT) |
|
||||
(0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT) );
|
||||
|
||||
// check for S-Video connection
|
||||
if( readTVDetect( ai )) {
|
||||
SHOW_FLOW0( 2, "Composite-Out of Rage Theatre is connected" );
|
||||
displays |= dd_ctv;
|
||||
}
|
||||
|
||||
// enable output changes
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |
|
||||
RADEON_TV_DAC_CNTL_NHOLD );
|
||||
|
||||
// set constant Y-output of S-Video adapter
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
|
||||
RADEON_TV_PRE_DAC_MUX_CNTL_Y_RED_EN |
|
||||
RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN |
|
||||
(9 << RADEON_TV_PRE_DAC_MUX_CNTL_RED_MX_SHIFT) |
|
||||
(0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT) );
|
||||
|
||||
// check for composite connection
|
||||
if( readTVDetect( ai )) {
|
||||
SHOW_FLOW0( 2, "S-Video-Out of Rage Theatre is connected" );
|
||||
displays |= dd_stv;
|
||||
}
|
||||
|
||||
// restore everything
|
||||
Radeon_TheatreWriteFIFO( ai, last_fifo_addr, old_last_fifo_entry );
|
||||
Radeon_TheatreWriteFIFO( ai, 0x18f, old_mid_fifo_entry );
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, old_master_cntl );
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1, old_modulator_cntl1 );
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL, old_pre_dac_mux_cntl );
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, old_tv_dac_cntl );
|
||||
|
||||
return displays;
|
||||
}
|
||||
|
||||
// check whether there is a TV connected to TV-DAC
|
||||
// returns bit set, i.e. there can be S-Video or composite or both
|
||||
static display_device_e Radeon_DetectTV( accelerator_info *ai, bool tv_crt_found )
|
||||
{
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r100:
|
||||
case rt_r200:
|
||||
return Radeon_DetectTV_Theatre( ai );
|
||||
|
||||
case rt_ve:
|
||||
case rt_m6:
|
||||
case rt_rv200:
|
||||
case rt_m7:
|
||||
case rt_rv250:
|
||||
case rt_m9:
|
||||
case rt_rv280:
|
||||
case rt_m9plus:
|
||||
// IGP method is guessed
|
||||
case rt_rs100:
|
||||
case rt_rs200:
|
||||
return Radeon_DetectTV_RV200( ai, tv_crt_found );
|
||||
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_rv360:
|
||||
case rt_m10:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
return Radeon_DetectTV_R300( ai );
|
||||
|
||||
default:
|
||||
// don't know about IGP
|
||||
;
|
||||
}
|
||||
|
||||
return dd_none;
|
||||
}
|
||||
|
||||
// read edid data of flat panel and setup its timing accordingly
|
||||
static status_t Radeon_StoreFPEDID( accelerator_info *ai, edid1_info *edid )
|
||||
|
||||
// get native monitor timing, using Detailed Monitor Description
|
||||
static void Radeon_FindFPTiming_DetailedMonitorDesc(
|
||||
const edid1_info *edid, fp_info *fp, uint32 *max_hsize, uint32 *max_vsize )
|
||||
{
|
||||
fp_info *fp = &ai->si->flatpanels[0];
|
||||
uint32 max_hsize, max_vsize;
|
||||
int i;
|
||||
|
||||
SHOW_FLOW0( 2, "EDID data read from DVI port via DDC2:" );
|
||||
edid_dump( edid );
|
||||
|
||||
// find detailed timing with maximum resolution
|
||||
max_hsize = max_vsize = 0;
|
||||
|
||||
|
||||
for( i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i ) {
|
||||
if( edid->detailed_monitor[i].monitor_desc_type == edid1_is_detailed_timing ) {
|
||||
edid1_detailed_timing *timing = &edid->detailed_monitor[i].data.detailed_timing;
|
||||
const edid1_detailed_timing *timing = &edid->detailed_monitor[i].data.detailed_timing;
|
||||
|
||||
if( timing->h_size > max_hsize && timing->v_size > max_vsize ) {
|
||||
SHOW_FLOW( 2, "Found DDC data for mode %dx%d",
|
||||
(int)timing->h_active, (int)timing->v_active );
|
||||
|
||||
max_hsize = timing->h_active;
|
||||
max_vsize = timing->v_active;
|
||||
SHOW_FLOW( 2, "Found detailed timing for mode %dx%d in DDC data",
|
||||
(int)timing->h_active, (int)timing->v_active );
|
||||
|
||||
if( timing->h_active > *max_hsize && timing->v_active > *max_vsize ) {
|
||||
*max_hsize = timing->h_active;
|
||||
*max_vsize = timing->v_active;
|
||||
|
||||
// copy it to timing specification
|
||||
fp->panel_xres = timing->h_active;
|
||||
@@ -588,9 +721,114 @@ static status_t Radeon_StoreFPEDID( accelerator_info *ai, edid1_info *edid )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( max_hsize == 0 )
|
||||
return B_ERROR;
|
||||
// get native monitor timing, using Standard Timing table;
|
||||
// this table doesn't contain the actual timing, so we try to find a
|
||||
// appropriate VESA modes for the resolutions given in the table
|
||||
static void Radeon_FindFPTiming_StandardTiming(
|
||||
const edid1_info *edid, fp_info *fp, uint32 *max_hsize, uint32 *max_vsize )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < EDID1_NUM_STD_TIMING; ++i ) {
|
||||
const edid1_std_timing *std_timing = &edid->std_timing[i];
|
||||
|
||||
int best_fit = -1;
|
||||
int best_refresh_deviation = 10000;
|
||||
int j;
|
||||
|
||||
if( std_timing->h_size <= 256 )
|
||||
continue;
|
||||
|
||||
for( j = 0; j < (int)vesa_mode_list_count; ++j ) {
|
||||
int refresh_rate, cur_refresh_deviation;
|
||||
|
||||
if( vesa_mode_list[j].h_display != std_timing->h_size ||
|
||||
vesa_mode_list[j].v_display != std_timing->v_size )
|
||||
continue;
|
||||
|
||||
// take pixel_clock times 1000 because is is in kHz
|
||||
// further, take it times 1000 again, to get 1/1000 frames
|
||||
// as refresh rate
|
||||
refresh_rate = (int64)vesa_mode_list[j].pixel_clock * 1000*1000 /
|
||||
(vesa_mode_list[j].h_total * vesa_mode_list[j].v_total);
|
||||
|
||||
// standard timing is in frames, so multiple by it to get 1/1000 frames
|
||||
// result is scaled by 100 to get difference in percentage;
|
||||
cur_refresh_deviation =
|
||||
(100 * (refresh_rate - std_timing->refresh * 1000)) / refresh_rate;
|
||||
|
||||
if( cur_refresh_deviation < 0 )
|
||||
cur_refresh_deviation = -cur_refresh_deviation;
|
||||
|
||||
// less then 1 percent difference is (hopefully) OK,
|
||||
// if there are multiple, we take best one
|
||||
// (if the screen is that picky, it should have defined an enhanced timing)
|
||||
if( cur_refresh_deviation < 1 &&
|
||||
cur_refresh_deviation < best_refresh_deviation )
|
||||
{
|
||||
best_fit = j;
|
||||
best_refresh_deviation = cur_refresh_deviation;
|
||||
}
|
||||
}
|
||||
|
||||
if( best_fit < 0 ) {
|
||||
SHOW_FLOW( 2, "Unsupported standard mode %dx%d@%dHz (not VESA)",
|
||||
std_timing->h_size, std_timing->v_size, std_timing->refresh );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( std_timing->h_size > *max_hsize && std_timing->h_size > *max_vsize ) {
|
||||
const display_timing *timing = &vesa_mode_list[best_fit];
|
||||
|
||||
SHOW_FLOW( 2, "Found DDC data for standard mode %dx%d",
|
||||
(int)timing->h_display, (int)timing->v_display );
|
||||
|
||||
*max_hsize = timing->h_display;
|
||||
*max_vsize = timing->h_display;
|
||||
|
||||
// copy it to timing specification
|
||||
fp->panel_xres = timing->h_display;
|
||||
fp->h_blank = timing->h_total - timing->h_display;
|
||||
fp->h_over_plus = timing->h_sync_start - timing->h_display;
|
||||
fp->h_sync_width = timing->h_sync_end - timing->h_sync_start;
|
||||
|
||||
fp->panel_yres = timing->v_display;
|
||||
fp->v_blank = timing->v_total - timing->v_display;
|
||||
fp->v_over_plus = timing->v_sync_start - timing->v_display;
|
||||
fp->v_sync_width = timing->v_sync_end - timing->v_sync_start;
|
||||
|
||||
fp->dot_clock = timing->pixel_clock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read edid data of flat panel and setup its timing accordingly
|
||||
static status_t Radeon_StoreFPEDID( accelerator_info *ai, const edid1_info *edid )
|
||||
{
|
||||
fp_info *fp = &ai->si->flatpanels[0];
|
||||
uint32 max_hsize, max_vsize;
|
||||
|
||||
SHOW_FLOW0( 2, "EDID data read from DVI port via DDC2:" );
|
||||
edid_dump( edid );
|
||||
|
||||
// find detailed timing with maximum resolution
|
||||
max_hsize = max_vsize = 0;
|
||||
|
||||
Radeon_FindFPTiming_DetailedMonitorDesc( edid, fp, &max_hsize, &max_vsize );
|
||||
|
||||
if( max_hsize == 0 ) {
|
||||
SHOW_FLOW0( 2, "Timing is not explicitely defined in DDC - checking standard modes" );
|
||||
|
||||
Radeon_FindFPTiming_StandardTiming(
|
||||
edid, fp, &max_hsize, &max_vsize );
|
||||
|
||||
if( max_hsize == 0 ) {
|
||||
SHOW_FLOW0( 2, "Still found no valid native mode, disabling DVI" );
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
|
||||
fp->panel_xres, fp->h_blank, fp->h_over_plus, fp->h_sync_width );
|
||||
@@ -608,7 +846,11 @@ void Radeon_DetectDisplays( accelerator_info *ai )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
display_device_e displays = 0;
|
||||
display_device_e controlled_displays = ai->vc->controlled_displays;
|
||||
edid1_info edid;
|
||||
|
||||
// lock hardware so noone bothers us
|
||||
Radeon_WaitForIdle( ai, true );
|
||||
|
||||
// mobile chips are for use in laptops - there must be a laptop panel
|
||||
if( si->is_mobility )
|
||||
@@ -636,8 +878,8 @@ void Radeon_DetectDisplays( accelerator_info *ai )
|
||||
// must be the analog portion of DVI
|
||||
// I'm not sure about Radeons with one CRTC - do they have DVI-I or DVI-D?
|
||||
// anyway - if there are two CRTC, analog portion must be connected
|
||||
// to TV-DAC, if there is one CRTC, it must be the normal VGA-DAC
|
||||
if( si->num_heads > 1 ) {
|
||||
// to TV-DAC; if there is one CRTC, it must be the normal VGA-DAC
|
||||
if( si->num_crtc > 1 ) {
|
||||
SHOW_FLOW0( 2, "Must be an analog monitor on DVI port" );
|
||||
displays |= dd_tv_crt;
|
||||
} else {
|
||||
@@ -661,27 +903,30 @@ void Radeon_DetectDisplays( accelerator_info *ai )
|
||||
|
||||
// all versions have a standard VGA port
|
||||
if( (displays & dd_crt) == 0 &&
|
||||
(controlled_displays && dd_crt) != 0 &&
|
||||
Radeon_DetectCRT( ai ))
|
||||
displays |= dd_crt;
|
||||
|
||||
// check VGA signal routed to DVI port
|
||||
// (the detection code checks whether there is hardware for that)
|
||||
if( (displays & dd_tv_crt) == 0 &&
|
||||
(controlled_displays && dd_tv_crt) != 0 &&
|
||||
Radeon_DetectTVCRT( ai ))
|
||||
displays |= dd_tv_crt;
|
||||
|
||||
// TV-Out doesn't work, so don't detect that
|
||||
#if 0
|
||||
// check TV-out connector
|
||||
// (this is the only one where we cannot use DDC)
|
||||
displays |= Radeon_DetectTV( ai, (displays & dd_tv_crt) != 0 );
|
||||
#endif
|
||||
if( (controlled_displays && (dd_ctv | dd_stv)) != 0 )
|
||||
displays |= Radeon_DetectTV( ai, (displays & dd_tv_crt) != 0 );
|
||||
|
||||
SHOW_INFO( 0, "Detected monitors: 0x%x", displays );
|
||||
|
||||
displays &= controlled_displays;
|
||||
|
||||
// if no monitor found, we define to have a CRT connected to CRT-DAC
|
||||
if( displays == 0 )
|
||||
displays = dd_crt;
|
||||
|
||||
si->connected_displays = displays;
|
||||
ai->vc->connected_displays = displays;
|
||||
|
||||
RELEASE_BEN( si->cp.lock );
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/*
|
||||
Copyright (c) 2002/03, Thomas Kurschel
|
||||
Copyright (c) 2002-04, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
|
||||
CRTC <-> display routing
|
||||
|
||||
This stuff is highly ASIC dependant and is probably the most ASIC-specific
|
||||
code of the entire project.
|
||||
*/
|
||||
|
||||
#include "radeon_accelerant.h"
|
||||
@@ -13,40 +16,56 @@
|
||||
#include "fp_regs.h"
|
||||
#include "crtc_regs.h"
|
||||
#include "tv_out_regs.h"
|
||||
#include "pll_regs.h"
|
||||
#include "gpiopad_regs.h"
|
||||
#include "pll_access.h"
|
||||
#include "set_mode.h"
|
||||
|
||||
|
||||
// read regs needed for display device routing
|
||||
void Radeon_ReadMonitorRoutingRegs( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values )
|
||||
void Radeon_ReadMonitorRoutingRegs(
|
||||
accelerator_info *ai, routing_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
(void)head;
|
||||
|
||||
values->dac_cntl = INREG( regs, RADEON_DAC_CNTL );
|
||||
values->dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
|
||||
values->crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL );
|
||||
values->crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
|
||||
values->disp_output_cntl = INREG( regs, RADEON_DISP_OUTPUT_CNTL );
|
||||
values->pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL );
|
||||
values->vclk_ecp_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL );
|
||||
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
break;
|
||||
|
||||
case rt_ve:
|
||||
case rt_m6:
|
||||
case rt_rv200:
|
||||
case rt_m7:
|
||||
case rt_rv250:
|
||||
case rt_rv280:
|
||||
case rt_m9:
|
||||
|
||||
default:
|
||||
case rt_rv280:
|
||||
case rt_m9plus:
|
||||
case rt_rs100:
|
||||
case rt_rs200:
|
||||
values->disp_hw_debug = INREG( regs, RADEON_DISP_HW_DEBUG );
|
||||
break;
|
||||
|
||||
case rt_r200:
|
||||
values->disp_tv_out_cntl = INREG( regs, RADEON_DISP_TV_OUT_CNTL );
|
||||
break;
|
||||
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_m10:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
values->gpiopad_a = INREG( regs, RADEON_GPIOPAD_A );
|
||||
break;
|
||||
|
||||
case rt_r100:
|
||||
break;
|
||||
}
|
||||
|
||||
if( ai->si->asic > rt_r100 ) {
|
||||
@@ -54,121 +73,365 @@ void Radeon_ReadMonitorRoutingRegs( accelerator_info *ai, physical_head *head,
|
||||
values->tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
|
||||
}
|
||||
|
||||
if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
|
||||
values->tv_master_cntl = INREG( regs, RADEON_TV_MASTER_CNTL );
|
||||
|
||||
values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL );
|
||||
values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );
|
||||
}
|
||||
|
||||
|
||||
// setup register contents to proper CRTC <-> display device mapping
|
||||
void Radeon_CalcMonitorRouting( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values )
|
||||
void Radeon_CalcMonitorRouting(
|
||||
accelerator_info *ai, const impactv_params *tv_parameters, routing_regs *values )
|
||||
{
|
||||
display_device_e display_devices;
|
||||
display_device_e display_devices[2], total_devices, controlled_devices;
|
||||
|
||||
display_devices = head->chosen_displays;
|
||||
if( ai->vc->used_crtc[0] )
|
||||
display_devices[0] = ai->si->crtc[0].chosen_displays;
|
||||
else
|
||||
display_devices[0] = dd_none;
|
||||
|
||||
if( ai->vc->used_crtc[1] )
|
||||
display_devices[1] = ai->si->crtc[1].chosen_displays;
|
||||
else
|
||||
display_devices[1] = dd_none;
|
||||
|
||||
total_devices = display_devices[0] | display_devices[1];
|
||||
controlled_devices = ai->vc->controlled_displays;
|
||||
|
||||
// enable 8 bit DAC
|
||||
// (could be moved to boot initialization)
|
||||
values->dac_cntl |=
|
||||
RADEON_DAC_MASK_ALL | RADEON_DAC_VGA_ADR_EN | RADEON_DAC_8BIT_EN;
|
||||
|
||||
// enable frame buffer access and extended CRTC counter
|
||||
// (again: something for boot init.)
|
||||
values->crtc_ext_cntl =
|
||||
RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN;
|
||||
|
||||
// set VGA signal style (not sure whether this affects
|
||||
// CRTC1 or CRT-DAC, so we better always set it)
|
||||
values->dac_cntl &= ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_BLANKING);
|
||||
values->dac_cntl |= RADEON_DAC_RANGE_CNTL_PS2;
|
||||
|
||||
// disable all the magic CRTC shadowing
|
||||
values->fp_gen_cntl &=
|
||||
~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
|
||||
RADEON_FP_DFP_SYNC_SEL |
|
||||
RADEON_FP_CRT_SYNC_SEL |
|
||||
RADEON_FP_CRTC_LOCK_8DOT |
|
||||
RADEON_FP_USE_SHADOW_EN |
|
||||
RADEON_FP_CRTC_USE_SHADOW_VEND |
|
||||
RADEON_FP_CRT_SYNC_ALT);
|
||||
values->fp_gen_cntl |=
|
||||
RADEON_FP_CRTC_DONT_SHADOW_VPAR |
|
||||
RADEON_FP_CRTC_DONT_SHADOW_HEND;
|
||||
|
||||
// route VGA-DAC
|
||||
if( (display_devices & dd_crt) != 0 ) {
|
||||
if( (total_devices & dd_crt) != 0 ) {
|
||||
int crtc_idx = (display_devices[1] & dd_crt) != 0;
|
||||
|
||||
// the CRT_ON flag seems to directly affect the CRT-DAC, _not_ the CRTC1 signal
|
||||
values->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
|
||||
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
values->disp_output_cntl =
|
||||
(values->disp_output_cntl & ~RADEON_DISP_DAC_SOURCE_MASK) |
|
||||
(head->is_crtc2 ? RADEON_DISP_DAC_SOURCE_CRTC2 : 0);
|
||||
break;
|
||||
|
||||
case rt_ve:
|
||||
case rt_m6:
|
||||
case rt_rv200:
|
||||
case rt_m7:
|
||||
case rt_rv250:
|
||||
case rt_rv280:
|
||||
case rt_m9:
|
||||
default:
|
||||
case rt_rv280:
|
||||
case rt_m9plus:
|
||||
case rt_rs100:
|
||||
case rt_rs200:
|
||||
values->dac_cntl2 &= ~RADEON_DAC_CLK_SEL_MASK;
|
||||
values->dac_cntl2 |= head->is_crtc2 ? RADEON_DAC_CLK_SEL_CRTC2 : 0;
|
||||
values->dac_cntl2 |= crtc_idx == 0 ? 0 : RADEON_DAC_CLK_SEL_CRTC2;
|
||||
break;
|
||||
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_m10:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK;
|
||||
values->disp_output_cntl |=
|
||||
(crtc_idx == 0 ? 0 : RADEON_DISP_DAC_SOURCE_CRTC2);
|
||||
break;
|
||||
|
||||
case rt_r100:
|
||||
break;
|
||||
}
|
||||
|
||||
} else if( (controlled_devices & dd_crt) != 0 ) {
|
||||
values->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
|
||||
}
|
||||
|
||||
|
||||
if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) {
|
||||
// power down TV-DAC
|
||||
// (but only if TV-Out _and_ TV-CRT is controlled by us)
|
||||
// this will be undone if needed
|
||||
values->tv_dac_cntl |=
|
||||
RADEON_TV_DAC_CNTL_RDACPD |
|
||||
RADEON_TV_DAC_CNTL_GDACPD |
|
||||
RADEON_TV_DAC_CNTL_BDACPD;
|
||||
}
|
||||
|
||||
|
||||
// set CRT mode of TV-DAC if needed
|
||||
if( (display_devices & dd_tv_crt) != 0 ) {
|
||||
// TODO: this register doesn't exist on r200 as TV DAC is on
|
||||
// external Rage Theatre
|
||||
// (doesn't work on r200, but there is no TV-DAC used for CRT anyway)
|
||||
if( (total_devices & dd_tv_crt) != 0 ) {
|
||||
// enable CRT via TV-DAC (ignored if TV-DAC is in TV-Out mode)
|
||||
values->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
|
||||
|
||||
values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK;
|
||||
values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_CRT;
|
||||
|
||||
// enable TV-DAC
|
||||
// enable TV-DAC and set PS2 signal level
|
||||
values->tv_dac_cntl =
|
||||
RADEON_TV_DAC_CNTL_NBLANK |
|
||||
RADEON_TV_DAC_CNTL_NHOLD |
|
||||
RADEON_TV_DAC_CNTL_STD_PS2;
|
||||
RADEON_TV_DAC_CNTL_STD_PS2 |
|
||||
(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
|
||||
(2 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT);
|
||||
|
||||
// at least r300 needs magic bit set to switch between TV-CRT and TV-Out
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_m10:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
values->gpiopad_a |= 1;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
} else if( (controlled_devices & dd_tv_crt) != 0 ) {
|
||||
values->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
|
||||
}
|
||||
|
||||
values->skip_tv_dac = false;
|
||||
|
||||
|
||||
// disable forwarding data to TV-Out unit
|
||||
// (will be enabled on demand later on)
|
||||
if( (controlled_devices & (dd_ctv | dd_stv)) != 0 )
|
||||
values->dac_cntl &= ~RADEON_DAC_TVO_EN;
|
||||
|
||||
|
||||
// set TV mode of TV-DAC if needed
|
||||
if( (display_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
if( (total_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
// see above
|
||||
values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK;
|
||||
values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_TV;
|
||||
}
|
||||
|
||||
// at least r300 needs magic bit set to switch between TV-CRT and TV-Out
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_rv360:
|
||||
case rt_m10:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
values->gpiopad_a &= ~1;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
// the TV-DAC itself is under control of the TV-Out code
|
||||
values->skip_tv_dac = true;
|
||||
|
||||
if( !IS_INTERNAL_TV_OUT( ai->si->tv_chip )) {
|
||||
// tell DAC to forward data to external chip
|
||||
values->dac_cntl |= RADEON_DAC_TVO_EN;
|
||||
|
||||
// set Output Linear Transform Unit as source
|
||||
// (TODO: is this unit initialized properly?)
|
||||
// disable overlay sync (could be a good idea to enable it)
|
||||
// set 8 BPP mode
|
||||
values->disp_output_cntl &=
|
||||
~(RADEON_DISP_TV_SOURCE |
|
||||
RADEON_DISP_TV_MODE_MASK |
|
||||
RADEON_DISP_TV_YG_DITH_EN |
|
||||
RADEON_DISP_TV_CBB_CRR_DITH_EN |
|
||||
RADEON_DISP_TV_BIT_WIDTH |
|
||||
RADEON_DISP_TV_SYNC_MODE_MASK |
|
||||
RADEON_DISP_TV_SYNC_COLOR_MASK);
|
||||
|
||||
// enable dithering
|
||||
values->disp_output_cntl |=
|
||||
RADEON_DISP_TV_YG_DITH_EN |
|
||||
RADEON_DISP_TV_CBB_CRR_DITH_EN;
|
||||
|
||||
// set output data format
|
||||
values->disp_output_cntl |= tv_parameters->mode888 ?
|
||||
RADEON_DISP_TV_MODE_888 : RADEON_DISP_TV_MODE_565;
|
||||
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
// disable downfiltering and scaling, set RGB mode,
|
||||
// don't transmit overlay indicator;
|
||||
// I don't really know whether this is a good choice
|
||||
values->disp_tv_out_cntl &=
|
||||
(RADEON_DISP_TV_OUT_YG_FILTER_MASK |
|
||||
RADEON_DISP_TV_OUT_YG_SAMPLE |
|
||||
RADEON_DISP_TV_OUT_CrR_FILTER_MASK |
|
||||
RADEON_DISP_TV_OUT_CrR_SAMPLE |
|
||||
RADEON_DISP_TV_OUT_CbB_FILTER_MASK |
|
||||
RADEON_DISP_TV_OUT_CbB_SAMPLE |
|
||||
RADEON_DISP_TV_SUBSAMPLE_CNTL_MASK |
|
||||
RADEON_DISP_TV_H_DOWNSCALE |
|
||||
RADEON_DISP_TV_COLOR_SPACE |
|
||||
RADEON_DISP_TV_DITH_MODE |
|
||||
RADEON_DISP_TV_DATA_ZERO_SEL |
|
||||
RADEON_DISP_TV_CLKO_SEL |
|
||||
RADEON_DISP_TV_CLKO_OUT_EN |
|
||||
RADEON_DISP_TV_DOWNSCALE_CNTL);
|
||||
|
||||
// enable TVOCLKO (is this needed?)
|
||||
values->disp_tv_out_cntl |= RADEON_DISP_TV_CLKO_OUT_EN;
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} else if( (controlled_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) {
|
||||
// disable clock of TV-out units
|
||||
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_TVCLK_ALWAYS_ONb;
|
||||
}
|
||||
}
|
||||
|
||||
// choose CRTC for TV-DAC
|
||||
if( (display_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) {
|
||||
if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) {
|
||||
int crtc_idx = (display_devices[1] & (dd_tv_crt | dd_ctv | dd_stv)) != 0;
|
||||
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
// for r200, this register doesn not exist!?
|
||||
// according to r300 spec, this is because TV-DAC is on external chip
|
||||
values->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
values->disp_output_cntl |=
|
||||
head->is_crtc2 ? RADEON_DISP_TVDAC_SOURCE_CRTC2 : 0;
|
||||
break;
|
||||
|
||||
case rt_ve:
|
||||
case rt_m6:
|
||||
case rt_rv200:
|
||||
case rt_m7:
|
||||
case rt_rv250:
|
||||
case rt_rv280:
|
||||
case rt_m9:
|
||||
default:
|
||||
case rt_rv280:
|
||||
case rt_m9plus:
|
||||
case rt_rs100:
|
||||
case rt_rs200:
|
||||
values->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
|
||||
values->disp_hw_debug |= head->is_crtc2 ? RADEON_CRT2_DISP1_SEL : 0;
|
||||
// warning: meaning is wrong way around - 0 means crtc2, 1 means crtc1
|
||||
values->disp_hw_debug |= crtc_idx == 0 ? RADEON_CRT2_DISP1_SEL : 0;
|
||||
break;
|
||||
|
||||
case rt_r200:
|
||||
// TV-Out data comes directly from CRTC (i.e. with Linear Transform Unit)
|
||||
values->disp_output_cntl |= RADEON_DISP_TV_SOURCE;
|
||||
// choose CRTC
|
||||
values->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC;
|
||||
values->disp_tv_out_cntl |= crtc_idx == 0 ? 0 : RADEON_DISP_TV_PATH_SRC;
|
||||
break;
|
||||
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_m10:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
values->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
values->disp_output_cntl |=
|
||||
crtc_idx == 0 ? 0 : RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
break;
|
||||
|
||||
case rt_r100:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// choose CRTC for flat panel
|
||||
if( (display_devices & (dd_lvds | dd_dvi)) != 0 ) {
|
||||
values->fp_gen_cntl |= head->is_crtc2 ? RADEON_FP_SEL_CRTC2 : 0;
|
||||
// choose clock source for (internal) TV-out unit
|
||||
if( (total_devices & (dd_ctv | dd_stv)) != 0 ) {
|
||||
int crtc_idx = (display_devices[1] & (dd_ctv | dd_stv)) != 0;
|
||||
|
||||
values->pixclks_cntl &= ~RADEON_PIXCLK_TV_SRC_SEL_MASK;
|
||||
values->pixclks_cntl |= crtc_idx == 0 ?
|
||||
RADEON_PIXCLK_TV_SRC_SEL_PIXCLK : RADEON_PIXCLK_TV_SRC_SEL_PIX2CLK;
|
||||
}
|
||||
|
||||
// enable/disable RMX for crtc1
|
||||
// choose CRTC clock source;
|
||||
// normally, CRTC1 uses PLL1 and CRTC2 uses PLL2, but if an external TV-Out
|
||||
// chip is used, the clock is retrieved from this chip to stay in perfect sync
|
||||
if( (display_devices[0] & (dd_ctv | dd_stv)) != 0
|
||||
&& !IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
|
||||
{
|
||||
// select BYTCLK input pin as pixel src
|
||||
values->vclk_ecp_cntl &=
|
||||
~(RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_MASK | RADEON_VCLK_SRC_SEL_MASK);
|
||||
|
||||
values->vclk_ecp_cntl |= RADEON_VCLK_SRC_BYTE_CLK;
|
||||
values->vclk_ecp_cntl |= 0 << RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_SHIFT;
|
||||
|
||||
// disable clock if pixel format in CRTC_GEN_CNTL is zero;
|
||||
// disable (DAC?) during blank
|
||||
values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb;
|
||||
|
||||
} else {
|
||||
// select PLL as pixel clock
|
||||
values->vclk_ecp_cntl &= ~RADEON_VCLK_SRC_SEL_MASK;
|
||||
values->vclk_ecp_cntl |= RADEON_VCLK_SRC_PPLL_CLK;
|
||||
|
||||
// disable clock if pixel format in CRTC_GEN_CNTL is zero
|
||||
values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb;
|
||||
}
|
||||
|
||||
values->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
|
||||
if( (display_devices[1] & (dd_ctv | dd_stv)) != 0
|
||||
&& !IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
|
||||
{
|
||||
// r200 spec misses everything regarding second CRTC, so
|
||||
// this is guessing
|
||||
values->pixclks_cntl |= 2;
|
||||
} else
|
||||
values->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLL_CLK;
|
||||
|
||||
// choose CRTC for flat panel
|
||||
if( (total_devices & (dd_lvds | dd_dvi)) != 0 ) {
|
||||
int crtc_idx = (display_devices[1] & (dd_lvds | dd_dvi)) != 0;
|
||||
|
||||
values->fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
|
||||
values->fp_gen_cntl |= crtc_idx == 0 ? 0 : RADEON_FP_SEL_CRTC2;
|
||||
}
|
||||
|
||||
// enable/disable RMX for crtc1 if there is a flat panel
|
||||
// (TODO: this doesn't seem to work)
|
||||
// !!! makes trouble on Radeon 9200 Mobility !??
|
||||
/*
|
||||
if( !head->is_crtc2 ) {
|
||||
// use RMX if there is a flat panel
|
||||
if( (display_devices & (dd_lvds | dd_dvi)) != 0 ) {
|
||||
values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK;
|
||||
values->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_RMX;
|
||||
}
|
||||
}*/
|
||||
if( (display_devices[1] & (dd_lvds | dd_dvi)) != 0 ) {
|
||||
values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK;
|
||||
values->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_RMX;
|
||||
}
|
||||
|
||||
|
||||
// choose CRTC for secondary flat panel
|
||||
if( (display_devices & dd_dvi_ext) != 0 ) {
|
||||
if( (total_devices & dd_dvi_ext) != 0 ) {
|
||||
int crtc_idx = (display_devices[1] & (dd_dvi_ext)) != 0;
|
||||
|
||||
// TODO: this list looks a bit magic/wrong for me; I reckon ATI moved the
|
||||
// bit starting with ASIC xxx, but I have no specs to verify that
|
||||
switch( ai->si->asic ) {
|
||||
@@ -176,126 +439,279 @@ void Radeon_CalcMonitorRouting( accelerator_info *ai, physical_head *head,
|
||||
case rt_r300:
|
||||
case rt_r350:
|
||||
case rt_rv350:
|
||||
case rt_m10:
|
||||
values->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_CRTC2;
|
||||
values->fp2_gen_cntl |=
|
||||
head->is_crtc2 ? RADEON_FP2_SOURCE_SEL_CRTC2 : 0;
|
||||
crtc_idx == 0 ? 0 : RADEON_FP2_SOURCE_SEL_CRTC2;
|
||||
break;
|
||||
|
||||
default:
|
||||
values->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
|
||||
values->fp2_gen_cntl |=
|
||||
head->is_crtc2 ? RADEON_FP2_SRC_SEL_CRTC2 : 0;
|
||||
crtc_idx == 0 ? 0 : RADEON_FP2_SRC_SEL_CRTC2;
|
||||
}
|
||||
}
|
||||
|
||||
// we don't set source of TV-OUT unit - it's done in the tv-out code
|
||||
}
|
||||
|
||||
void Radeon_ProgramMonitorRouting( accelerator_info *ai, physical_head *head, port_regs *values )
|
||||
void Radeon_ProgramMonitorRouting(
|
||||
accelerator_info *ai, routing_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
|
||||
(void)head;
|
||||
|
||||
OUTREG( regs, RADEON_DAC_CNTL, values->dac_cntl );
|
||||
OUTREG( regs, RADEON_DAC_CNTL2, values->dac_cntl2 );
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, values->crtc_ext_cntl,
|
||||
~RADEON_CRTC_CRT_ON );
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, values->crtc2_gen_cntl,
|
||||
~RADEON_CRTC2_CRT2_ON );
|
||||
OUTREG( regs, RADEON_DISP_OUTPUT_CNTL, values->disp_output_cntl );
|
||||
|
||||
switch( ai->si->asic ) {
|
||||
case rt_r200:
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
break;
|
||||
|
||||
case rt_ve:
|
||||
case rt_m6:
|
||||
case rt_rv200:
|
||||
case rt_m7:
|
||||
case rt_rv250:
|
||||
case rt_rv280:
|
||||
case rt_m9:
|
||||
default:
|
||||
case rt_rv280:
|
||||
case rt_m9plus:
|
||||
case rt_rs100:
|
||||
case rt_rs200:
|
||||
OUTREG( regs, RADEON_DISP_HW_DEBUG, values->disp_hw_debug );
|
||||
break;
|
||||
|
||||
case rt_r200:
|
||||
OUTREG( regs, RADEON_DISP_TV_OUT_CNTL, values->disp_tv_out_cntl );
|
||||
break;
|
||||
|
||||
case rt_r300:
|
||||
case rt_r300_4p:
|
||||
case rt_rv350:
|
||||
case rt_m10:
|
||||
case rt_rv360:
|
||||
case rt_r350:
|
||||
case rt_r360:
|
||||
OUTREGP( regs, RADEON_GPIOPAD_A, values->gpiopad_a, ~1 );
|
||||
break;
|
||||
|
||||
case rt_r100:
|
||||
break;
|
||||
}
|
||||
|
||||
if( ai->si->asic > rt_r100 ) {
|
||||
// register introduced after R100
|
||||
OUTREG( regs, RADEON_TV_DAC_CNTL, values->tv_dac_cntl );
|
||||
// register introduced after R100;
|
||||
// only set it when necessary (more precisely: if TV-Out is used,
|
||||
// this register is set by the TV-Out code)
|
||||
if( !values->skip_tv_dac )
|
||||
OUTREG( regs, RADEON_TV_DAC_CNTL, values->tv_dac_cntl );
|
||||
}
|
||||
|
||||
OUTREG( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl );
|
||||
OUTREG( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl );
|
||||
if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
|
||||
OUTREG( regs, RADEON_TV_MASTER_CNTL, values->tv_master_cntl );
|
||||
|
||||
OUTREGP( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl, ~(
|
||||
RADEON_FP_SEL_CRTC2 |
|
||||
RADEON_FP_RMX_HVSYNC_CONTROL_EN |
|
||||
RADEON_FP_DFP_SYNC_SEL |
|
||||
RADEON_FP_CRT_SYNC_SEL |
|
||||
RADEON_FP_CRTC_LOCK_8DOT |
|
||||
RADEON_FP_USE_SHADOW_EN |
|
||||
RADEON_FP_CRTC_USE_SHADOW_VEND |
|
||||
RADEON_FP_CRT_SYNC_ALT |
|
||||
RADEON_FP_CRTC_DONT_SHADOW_VPAR |
|
||||
RADEON_FP_CRTC_DONT_SHADOW_HEND ));
|
||||
|
||||
|
||||
OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
|
||||
~(RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 ));
|
||||
|
||||
if( ai->vc->used_crtc[0] ) {
|
||||
Radeon_OUTPLLP( ai->regs, ai->si->asic,
|
||||
RADEON_VCLK_ECP_CNTL, values->vclk_ecp_cntl,
|
||||
~RADEON_VCLK_SRC_SEL_MASK );
|
||||
}
|
||||
|
||||
if( ai->vc->used_crtc[1] ) {
|
||||
Radeon_OUTPLLP( ai->regs, ai->si->asic,
|
||||
RADEON_PIXCLKS_CNTL, values->pixclks_cntl,
|
||||
~RADEON_PIX2CLK_SRC_SEL_MASK );
|
||||
}
|
||||
|
||||
Radeon_OUTPLLP( ai->regs, ai->si->asic,
|
||||
RADEON_PIXCLKS_CNTL, values->pixclks_cntl,
|
||||
~RADEON_PIXCLK_TV_SRC_SEL_MASK );
|
||||
|
||||
// enable/disable CRTC1
|
||||
if( ai->vc->assigned_crtc[0] ) {
|
||||
uint32 crtc_gen_cntl;
|
||||
|
||||
crtc_gen_cntl = INREG( regs, RADEON_CRTC_GEN_CNTL );
|
||||
|
||||
if( ai->vc->used_crtc[0] ) {
|
||||
crtc_gen_cntl |= RADEON_CRTC_EN;
|
||||
} else {
|
||||
crtc_gen_cntl &= ~RADEON_CRTC_EN;
|
||||
crtc_gen_cntl &= ~RADEON_CRTC_PIX_WIDTH_MASK;
|
||||
}
|
||||
|
||||
OUTREGP( regs, RADEON_CRTC_GEN_CNTL, crtc_gen_cntl,
|
||||
~(RADEON_CRTC_PIX_WIDTH_MASK | RADEON_CRTC_EN) );
|
||||
}
|
||||
|
||||
// enable/disable CRTC2
|
||||
if( ai->vc->assigned_crtc[1] ) {
|
||||
uint32 crtc2_gen_cntl;
|
||||
|
||||
crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
|
||||
|
||||
if( ai->vc->used_crtc[1] ) {
|
||||
crtc2_gen_cntl |= RADEON_CRTC2_EN;
|
||||
} else {
|
||||
crtc2_gen_cntl &= ~RADEON_CRTC2_EN;
|
||||
crtc2_gen_cntl &= ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
}
|
||||
|
||||
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl,
|
||||
~(RADEON_CRTC2_PIX_WIDTH_MASK | RADEON_CRTC2_EN) );
|
||||
}
|
||||
|
||||
// XFree says that crtc_ext_cntl must be restored after CRTC2 in dual-screen mode
|
||||
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, values->crtc_ext_cntl,
|
||||
RADEON_CRTC_VSYNC_DIS |
|
||||
RADEON_CRTC_HSYNC_DIS |
|
||||
RADEON_CRTC_DISPLAY_DIS );
|
||||
}
|
||||
|
||||
|
||||
// Setup sensible default monitor routing
|
||||
// whished_num_heads - number of independant heads current display mode would need
|
||||
void Radeon_SetupDefaultMonitorRouting( accelerator_info *ai, int whished_num_heads )
|
||||
// internal version of SetupDefaultMonitorRouting;
|
||||
// input and output are written to local variables
|
||||
void assignDefaultMonitorRoute(
|
||||
accelerator_info *ai,
|
||||
display_device_e display_devices, int whished_num_heads, bool use_laptop_panel,
|
||||
display_device_e *crtc1, display_device_e *crtc2 )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
display_device_e crtc1_displays = 0, crtc2_displays = 0;
|
||||
display_device_e display_devices = ai->si->connected_displays;
|
||||
|
||||
SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d",
|
||||
display_devices, whished_num_heads );
|
||||
|
||||
// restrict to allowed devices
|
||||
display_devices &= ai->vc->controlled_displays;
|
||||
|
||||
// if CRTC1 is not ours, we cannot use flat panels
|
||||
if( !ai->vc->assigned_crtc[0] ) {
|
||||
display_devices &= ~(dd_lvds | dd_dvi);
|
||||
}
|
||||
|
||||
SHOW_FLOW( 2, "after restriction: %x", display_devices );
|
||||
|
||||
// flat panels get always connected to CRTC1 because its RMX unit
|
||||
if( (display_devices & dd_lvds) != 0 ) {
|
||||
// don't enable Laptop panel if display mode needs one head only
|
||||
// and there is a CRT connected (showing the same on both panel and
|
||||
// CRT doesn't make much sense)
|
||||
if( !(whished_num_heads == 1 && (display_devices & (dd_crt | dd_tv_crt)) != 0 ))
|
||||
// if user requests it, laptop panels are always used
|
||||
if( use_laptop_panel ) {
|
||||
crtc1_displays |= dd_lvds;
|
||||
|
||||
} else {
|
||||
// if he doesn't request it, we try to not use it
|
||||
display_device_e tmp_crtc1, tmp_crtc2;
|
||||
int effective_num_heads;
|
||||
|
||||
// determine routing with laptop panel ignored
|
||||
assignDefaultMonitorRoute( ai, display_devices & ~dd_lvds,
|
||||
whished_num_heads, use_laptop_panel, &tmp_crtc1, &tmp_crtc2 );
|
||||
|
||||
effective_num_heads = (tmp_crtc1 != 0) + (tmp_crtc2 != 0);
|
||||
|
||||
// only use laptop panel if we cannot satisfy the requested
|
||||
// number of heads without it
|
||||
if( effective_num_heads < whished_num_heads )
|
||||
crtc1_displays |= dd_lvds;
|
||||
}
|
||||
|
||||
} else if( (display_devices & dd_dvi) != 0 )
|
||||
crtc1_displays |= dd_dvi;
|
||||
|
||||
// TV-Out gets always connected to crtc2...
|
||||
if( (display_devices & dd_stv) != 0 )
|
||||
crtc2_displays |= dd_stv;
|
||||
else if( (display_devices & dd_stv) != 0 )
|
||||
else if( (display_devices & dd_ctv) != 0 )
|
||||
crtc2_displays |= dd_ctv;
|
||||
|
||||
// ...but if there is no crtc2, they win on crtc1;
|
||||
// if the user connects both a flat panel and a TV, he certainly wants to use the TV
|
||||
if( ai->si->num_heads == 1 && crtc2_displays != 0 )
|
||||
// if the user connects both a flat panel and a TV, he usually
|
||||
// wants to use the TV
|
||||
if( !vc->assigned_crtc[1] && crtc2_displays != 0 ) {
|
||||
crtc1_displays = crtc2_displays;
|
||||
crtc2_displays = dd_none;
|
||||
}
|
||||
|
||||
// if TV-Out is used, the DAC cannot drive a CRT at the same time
|
||||
if( (display_devices & (dd_stv | dd_ctv)) != 0 )
|
||||
// if internal TV-Out is used, the DAC cannot drive a CRT at the same time
|
||||
if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ) && (display_devices & (dd_stv | dd_ctv)) != 0 )
|
||||
display_devices &= ~dd_tv_crt;
|
||||
|
||||
// CRT on CRT-DAC gets any spare CRTC;
|
||||
// if there is none, it can share CRTC with TV-Out
|
||||
// if there is none, it can share CRTC with TV-Out;
|
||||
// this sharing may be dangerous as TV-Out uses strange timings, so
|
||||
// we should perhaps forbid sharing
|
||||
if( (display_devices & dd_crt) != 0 ) {
|
||||
if( crtc1_displays == 0 )
|
||||
if( crtc1_displays == 0 && vc->assigned_crtc[0] )
|
||||
crtc1_displays |= dd_crt;
|
||||
else if( ai->si->num_heads > 1 && crtc2_displays == 0 )
|
||||
else if( ai->si->num_crtc > 1 && crtc2_displays == 0 && vc->assigned_crtc[1] )
|
||||
crtc2_displays |= dd_crt;
|
||||
else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 )
|
||||
else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[0] )
|
||||
crtc1_displays |= dd_crt;
|
||||
else if( ai->si->num_heads > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 )
|
||||
else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] )
|
||||
crtc2_displays |= dd_crt;
|
||||
}
|
||||
|
||||
// same applies to CRT on TV-DAC;
|
||||
// if we cannot find a CRTC, we could clone the content of the CRT-DAC,
|
||||
// but I doubt that you really want two CRTs showing the same
|
||||
if( (display_devices & dd_tv_crt) != 0 &&
|
||||
(display_devices & (dd_ctv | dd_stv)) == 0 )
|
||||
{
|
||||
if( crtc1_displays == 0 )
|
||||
if( (display_devices & dd_tv_crt) != 0 ) {
|
||||
if( crtc1_displays == 0 && vc->assigned_crtc[0] )
|
||||
crtc1_displays |= dd_tv_crt;
|
||||
else if( ai->si->num_heads > 1 && crtc2_displays == 0 )
|
||||
else if( ai->si->num_crtc > 1 && crtc2_displays == 0 && vc->assigned_crtc[1] )
|
||||
crtc2_displays |= dd_tv_crt;
|
||||
else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 )
|
||||
else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[0] )
|
||||
crtc1_displays |= dd_tv_crt;
|
||||
else if( ai->si->num_heads > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 )
|
||||
else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] )
|
||||
crtc2_displays |= dd_tv_crt;
|
||||
}
|
||||
|
||||
//crtc1_displays = dd_stv | dd_crt;
|
||||
//crtc2_displays = 0;
|
||||
SHOW_FLOW( 3, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays );
|
||||
|
||||
SHOW_FLOW( 2, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays );
|
||||
|
||||
ai->si->heads[0].chosen_displays = crtc1_displays;
|
||||
ai->si->heads[1].chosen_displays = crtc2_displays;
|
||||
*crtc1 = crtc1_displays;
|
||||
*crtc2 = crtc2_displays;
|
||||
}
|
||||
|
||||
// Setup sensible default monitor routing
|
||||
// whished_num_heads - number of independant heads current display mode would need
|
||||
// use_laptop_panel - if true, always use laptop panel
|
||||
void Radeon_SetupDefaultMonitorRouting(
|
||||
accelerator_info *ai, int whished_num_heads, bool use_laptop_panel )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
display_device_e display_devices = vc->connected_displays;
|
||||
|
||||
SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d, use_laptop_panel=%d",
|
||||
display_devices, whished_num_heads, use_laptop_panel );
|
||||
|
||||
// ignore TV if standard is set to "off"
|
||||
if( vc->tv_standard == ts_off )
|
||||
display_devices &= ~(dd_ctv | dd_stv);
|
||||
|
||||
assignDefaultMonitorRoute(
|
||||
ai, display_devices, whished_num_heads, use_laptop_panel,
|
||||
&si->crtc[0].chosen_displays, &si->crtc[1].chosen_displays );
|
||||
|
||||
/* si->crtc[0].chosen_displays = dd_none;
|
||||
si->crtc[1].chosen_displays = dd_tv_crt;*/
|
||||
|
||||
/*vc->used_crtc[0] = si->crtc[0].chosen_displays != dd_none;
|
||||
vc->used_crtc[1] = si->crtc[1].chosen_displays != dd_none;*/
|
||||
|
||||
SHOW_FLOW( 2, "num_crtc: %d, CRTC1 (%s): 0x%x, CRTC2 (%s): 0x%x",
|
||||
si->num_crtc,
|
||||
vc->assigned_crtc[0] ? "assigned" : "not assigned", si->crtc[0].chosen_displays,
|
||||
vc->assigned_crtc[0] ? "assigned" : "not assigned", si->crtc[1].chosen_displays );
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -15,33 +15,15 @@
|
||||
// transform official mode to internal, multi-screen mode enhanced mode
|
||||
void Radeon_DetectMultiMode( virtual_card *vc, display_mode *mode )
|
||||
{
|
||||
mode->timing.flags &= ~RADEON_MODE_MASK;
|
||||
(void)vc;
|
||||
|
||||
switch( vc->wanted_multi_mode ) {
|
||||
case mm_mirror:
|
||||
mode->timing.flags |= RADEON_MODE_MIRROR;
|
||||
break;
|
||||
case mm_clone:
|
||||
mode->timing.flags |= RADEON_MODE_CLONE;
|
||||
break;
|
||||
case mm_combine:
|
||||
mode->timing.flags |= RADEON_MODE_COMBINE;
|
||||
break;
|
||||
case mm_none:
|
||||
default:
|
||||
}
|
||||
mode->timing.flags &= ~RADEON_MODE_MASK;
|
||||
|
||||
// combine mode is used if virtual area is twice as visible area
|
||||
// and if scrolling is enabled; if combining is impossible, use
|
||||
// cloning instead
|
||||
if( (mode->flags & B_SCROLL) == 0 ) {
|
||||
if( (mode->timing.flags & RADEON_MODE_MASK) == RADEON_MODE_COMBINE ) {
|
||||
SHOW_FLOW0( 3, "This isn't a combine mode, falling back to clone" );
|
||||
mode->timing.flags &= ~RADEON_MODE_MASK;
|
||||
mode->timing.flags |= RADEON_MODE_CLONE;
|
||||
}
|
||||
if( (mode->flags & B_SCROLL) == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
SHOW_FLOW0( 3, "possibly combine mode" );
|
||||
|
||||
@@ -51,20 +33,19 @@ void Radeon_DetectMultiMode( virtual_card *vc, display_mode *mode )
|
||||
mode->timing.flags &= ~RADEON_MODE_POSITION_MASK;
|
||||
|
||||
if( mode->virtual_width == 2 * mode->timing.h_display ) {
|
||||
SHOW_FLOW0( 3, "horizontal combine mode" );
|
||||
SHOW_FLOW0( 2, "horizontal combine mode" );
|
||||
mode->timing.flags |= RADEON_MODE_POSITION_HORIZONTAL;
|
||||
mode->timing.flags &= ~RADEON_MODE_MASK;
|
||||
mode->timing.flags |= RADEON_MODE_COMBINE;
|
||||
} else if( mode->virtual_height == 2 * mode->timing.v_display ) {
|
||||
SHOW_FLOW0( 3, "vertical combine mode" );
|
||||
SHOW_FLOW0( 2, "vertical combine mode" );
|
||||
mode->timing.flags |= RADEON_MODE_POSITION_VERTICAL;
|
||||
mode->timing.flags &= ~RADEON_MODE_MASK;
|
||||
mode->timing.flags |= RADEON_MODE_COMBINE;
|
||||
} else {
|
||||
// ups, this isn't really a combine mode - restore flags
|
||||
SHOW_FLOW0( 3, "wasn't really a combine mode" );
|
||||
SHOW_FLOW0( 2, "wasn't really a combine mode" );
|
||||
mode->timing.flags &= ~RADEON_MODE_MASK;
|
||||
mode->timing.flags |= RADEON_MODE_CLONE;
|
||||
mode->flags |= B_SCROLL;
|
||||
}
|
||||
}
|
||||
@@ -74,11 +55,13 @@ void Radeon_VerifyMultiMode( virtual_card *vc, shared_info *si, display_mode *mo
|
||||
{
|
||||
// if there is no second port or no second monitor connected,
|
||||
// fall back to standard mode
|
||||
if( vc->num_heads == 1 ||
|
||||
(si->heads[vc->heads[0].physical_head].chosen_displays == dd_none ||
|
||||
si->heads[vc->heads[1].physical_head].chosen_displays == dd_none) )
|
||||
{
|
||||
SHOW_FLOW0( 3, "only one monitor - disabling any multi-mon mode" );
|
||||
int num_usable_crtcs = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none;
|
||||
|
||||
if( si->num_crtc > 1 )
|
||||
num_usable_crtcs += vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none;
|
||||
|
||||
if( num_usable_crtcs < 2 ) {
|
||||
SHOW_FLOW0( 2, "only one monitor - disabling any multi-mon mode" );
|
||||
// restore flags if combine mode is selected
|
||||
if( (mode->timing.flags & RADEON_MODE_MASK) == RADEON_MODE_COMBINE )
|
||||
mode->flags |= B_SCROLL;
|
||||
@@ -101,24 +84,28 @@ void Radeon_HideMultiMode( virtual_card *vc, display_mode *mode )
|
||||
|
||||
|
||||
// initialize multi-screen mode dependant variables
|
||||
void Radeon_InitMultiModeVars( virtual_card *vc, display_mode *mode )
|
||||
void Radeon_InitMultiModeVars(
|
||||
accelerator_info *ai, display_mode *mode )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
uint32 x, y;
|
||||
|
||||
// setup single-screen mode
|
||||
vc->eff_width = mode->timing.h_display;
|
||||
vc->eff_height = mode->timing.v_display;
|
||||
|
||||
vc->heads[0].rel_x = 0;
|
||||
vc->heads[0].rel_y = 0;
|
||||
|
||||
if( vc->used_crtc[0] ) {
|
||||
si->crtc[0].rel_x = 0;
|
||||
si->crtc[0].rel_y = 0;
|
||||
}
|
||||
|
||||
if( vc->used_crtc[1] ) {
|
||||
si->crtc[1].rel_x = 0;
|
||||
si->crtc[1].rel_y = 0;
|
||||
}
|
||||
|
||||
switch( mode->timing.flags & RADEON_MODE_MASK ) {
|
||||
case RADEON_MODE_CLONE:
|
||||
// in clone mode, ports are independant but show the same
|
||||
vc->heads[1].rel_x = 0;
|
||||
vc->heads[1].rel_y = 0;
|
||||
break;
|
||||
|
||||
case RADEON_MODE_COMBINE:
|
||||
// detect where second screen must be located and
|
||||
// adapt total visible area accordingly
|
||||
@@ -134,26 +121,27 @@ void Radeon_InitMultiModeVars( virtual_card *vc, display_mode *mode )
|
||||
|
||||
SHOW_FLOW( 3, "relative position of second screen: %d, %d", x, y );
|
||||
|
||||
vc->heads[1].rel_x = 0;
|
||||
vc->heads[1].rel_y = 0;
|
||||
|
||||
// set relative offset
|
||||
if( !vc->swap_displays ) {
|
||||
vc->heads[1].rel_x = x;
|
||||
vc->heads[1].rel_y = y;
|
||||
si->crtc[1].rel_x = x;
|
||||
si->crtc[1].rel_y = y;
|
||||
} else {
|
||||
vc->heads[0].rel_x = x;
|
||||
vc->heads[0].rel_y = y;
|
||||
si->crtc[0].rel_x = x;
|
||||
si->crtc[0].rel_y = y;
|
||||
}
|
||||
break;
|
||||
|
||||
case RADEON_MODE_STANDARD:
|
||||
case RADEON_MODE_MIRROR:
|
||||
default:
|
||||
// else, ports are independant but show the same
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mapping of internal TV standard code to public TV standard code
|
||||
static const uint32 private2be[] = {
|
||||
0, 1, 3, 4, 103, 3/* PAL SCART - no public id, so I use PAL BDGHI */, 102 };
|
||||
|
||||
// check and execute tunnel settings command
|
||||
status_t Radeon_CheckMultiMonTunnel( virtual_card *vc, display_mode *mode,
|
||||
const display_mode *low, const display_mode *high, bool *isTunneled )
|
||||
@@ -185,29 +173,91 @@ status_t Radeon_CheckMultiMonTunnel( virtual_card *vc, display_mode *mode,
|
||||
|
||||
*isTunneled = true;
|
||||
|
||||
/*SHOW_FLOW( 1, "tunnel access code=%d, command=%d",
|
||||
mode->h_display_start, mode->v_display_start );*/
|
||||
|
||||
switch( mode->h_display_start ) {
|
||||
case ms_swap:
|
||||
if( mode->v_display_start != 0 )
|
||||
vc->swap_displays = mode->timing.flags != 0;
|
||||
else
|
||||
switch( mode->v_display_start ) {
|
||||
case 0:
|
||||
mode->timing.flags = vc->swap_displays;
|
||||
return B_OK;
|
||||
|
||||
// write settings instantly
|
||||
Radeon_WriteSettings( vc );
|
||||
return B_OK;
|
||||
case 1:
|
||||
vc->swap_displays = mode->timing.flags != 0;
|
||||
vc->enforce_mode_change = true;
|
||||
// write settings instantly
|
||||
Radeon_WriteSettings( vc );
|
||||
return B_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
/* case ms_overlay_port:
|
||||
if( mode->v_display_start != 0 )
|
||||
vc->whished_overlay_port = mode->timing.flags;
|
||||
else
|
||||
mode->timing.flags = vc->whished_overlay_port;
|
||||
case ms_use_laptop_panel:
|
||||
// we must refuse this setting if there is no laptop panel;
|
||||
// else, the preferences dialog would show this (useless) option
|
||||
if( (vc->connected_displays & dd_lvds) == 0 )
|
||||
return B_ERROR;
|
||||
|
||||
Radeon_WriteSettings( vc );
|
||||
return B_OK;*/
|
||||
switch( mode->v_display_start ) {
|
||||
case 0:
|
||||
mode->timing.flags = vc->use_laptop_panel;
|
||||
//SHOW_FLOW( 1, "get use_laptop_panel settings (%d)", mode->timing.flags );
|
||||
return B_OK;
|
||||
|
||||
case 1:
|
||||
vc->use_laptop_panel = mode->timing.flags != 0;
|
||||
//SHOW_FLOW( 1, "set use_laptop_panel settings (%d)", vc->use_laptop_panel );
|
||||
vc->enforce_mode_change = true;
|
||||
Radeon_WriteSettings( vc );
|
||||
return B_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_BAD_INDEX;
|
||||
case ms_tv_standard:
|
||||
switch( mode->v_display_start ) {
|
||||
case 0:
|
||||
mode->timing.flags = private2be[vc->tv_standard];
|
||||
/*SHOW_FLOW( 1, "read tv_standard (internal %d, public %d)",
|
||||
vc->tv_standard, mode->timing.flags );*/
|
||||
return B_OK;
|
||||
|
||||
case 1:
|
||||
switch( mode->timing.flags ) {
|
||||
case 0: vc->tv_standard = ts_off; break;
|
||||
case 1: vc->tv_standard = ts_ntsc; break;
|
||||
case 2: break; // ntsc j
|
||||
case 3: vc->tv_standard = ts_pal_bdghi; break;
|
||||
case 4: vc->tv_standard = ts_pal_m; break;
|
||||
case 5: break; // pal n
|
||||
case 6: break; // secam - I reckon not supported by hardware
|
||||
case 101: break; // ntsc 443
|
||||
case 102: vc->tv_standard = ts_pal_60; break;
|
||||
case 103: vc->tv_standard = ts_pal_nc; break;
|
||||
}
|
||||
|
||||
SHOW_FLOW( 1, "set tv_standard (internal %d, public %d)",
|
||||
vc->tv_standard, mode->timing.flags );
|
||||
|
||||
vc->enforce_mode_change = true;
|
||||
Radeon_WriteSettings( vc );
|
||||
return B_OK;
|
||||
|
||||
case 2: {
|
||||
uint32 idx = mode->timing.flags;
|
||||
|
||||
// we limit it explicetely to NTSC and PAL as all other
|
||||
// modes are not fully implemented
|
||||
if( idx < sizeof( private2be ) / sizeof( private2be[0] ) &&
|
||||
idx < 3 ) {
|
||||
mode->timing.flags = private2be[idx];
|
||||
return B_OK;
|
||||
} else
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -216,13 +266,13 @@ bool Radeon_NeedsSecondPort( display_mode *mode )
|
||||
{
|
||||
switch( mode->timing.flags & RADEON_MODE_MASK ) {
|
||||
case RADEON_MODE_COMBINE:
|
||||
case RADEON_MODE_CLONE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// return number of ports showing differents parts of frame buffer
|
||||
bool Radeon_DifferentPorts( display_mode *mode )
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -51,7 +51,8 @@ static struct {
|
||||
|
||||
|
||||
// setup overlay unit before first use
|
||||
void Radeon_InitOverlay( accelerator_info *ai, physical_head *head )
|
||||
void Radeon_InitOverlay(
|
||||
accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
shared_info *si = ai->si;
|
||||
@@ -93,7 +94,7 @@ void Radeon_InitOverlay( accelerator_info *ai, physical_head *head )
|
||||
|
||||
// overlay unit can only handle up to 175 MHz, if pixel clock is higher,
|
||||
// only every second pixel is handled
|
||||
if( head->mode.timing.pixel_clock < 175000 )
|
||||
if( si->crtc[crtc_idx].mode.timing.pixel_clock < 175000 )
|
||||
ecp_div = 0;
|
||||
else
|
||||
ecp_div = 1;
|
||||
@@ -101,7 +102,7 @@ void Radeon_InitOverlay( accelerator_info *ai, physical_head *head )
|
||||
Radeon_OUTPLLP( regs, si->asic, RADEON_VCLK_ECP_CNTL,
|
||||
ecp_div << RADEON_ECP_DIV_SHIFT, ~RADEON_ECP_DIV_MASK );
|
||||
|
||||
si->active_overlay.head = si->pending_overlay.head;
|
||||
si->active_overlay.crtc_idx = si->pending_overlay.crtc_idx;
|
||||
|
||||
// invalidate active colour space
|
||||
si->active_overlay.ob.space = -1;
|
||||
@@ -140,7 +141,8 @@ space_transform trans_rgb =
|
||||
|
||||
|
||||
// set overlay colour space transformation matrix
|
||||
static void Radeon_SetTransform( accelerator_info *ai,
|
||||
static void Radeon_SetTransform(
|
||||
accelerator_info *ai,
|
||||
float bright,
|
||||
float cont,
|
||||
float sat,
|
||||
@@ -263,7 +265,8 @@ static void Radeon_SetTransform( accelerator_info *ai,
|
||||
|
||||
|
||||
// convert Be colour key to rgb value
|
||||
static uint32 colourKey2RGB32( uint32 space, uint8 red, uint8 green, uint8 blue )
|
||||
static uint32 colourKey2RGB32(
|
||||
uint32 space, uint8 red, uint8 green, uint8 blue )
|
||||
{
|
||||
uint32 res;
|
||||
|
||||
@@ -300,7 +303,8 @@ static uint32 colourKey2RGB32( uint32 space, uint8 red, uint8 green, uint8 blue
|
||||
|
||||
|
||||
// set colour key of overlay
|
||||
static void Radeon_SetColourKey( accelerator_info *ai, const overlay_window *ow )
|
||||
static void Radeon_SetColourKey(
|
||||
accelerator_info *ai, const overlay_window *ow )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
vuint8 *regs = ai->regs;
|
||||
@@ -437,7 +441,8 @@ static space_params space_params_table[16] = {
|
||||
};
|
||||
|
||||
// get appropriate scaling/filter parameters
|
||||
static hscale_factor *getHScaleFactor( space_params *params,
|
||||
static hscale_factor *getHScaleFactor(
|
||||
space_params *params,
|
||||
uint32 src_left, uint32 src_right, uint32 *h_inc )
|
||||
{
|
||||
uint words_per_p1_line, words_per_p23_line, max_words_per_line;
|
||||
@@ -511,14 +516,15 @@ static hscale_factor *getHScaleFactor( space_params *params,
|
||||
|
||||
|
||||
// show overlay on screen
|
||||
static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_head )
|
||||
static status_t Radeon_ShowOverlay(
|
||||
accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
vuint8 *regs = ai->regs;
|
||||
overlay_info *overlay = &si->pending_overlay;
|
||||
overlay_buffer_node *node = overlay->on;
|
||||
physical_head *head = &si->heads[virtual_head->physical_head];
|
||||
crtc_info *crtc = &si->crtc[crtc_idx];
|
||||
|
||||
uint32 ecp_div;
|
||||
uint32 v_inc, h_inc;
|
||||
@@ -547,7 +553,7 @@ static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_
|
||||
// only every second pixel is handled
|
||||
// (this devider is gets written into PLL by InitOverlay,
|
||||
// so we don't need to do it ourself)
|
||||
if( head->mode.timing.pixel_clock < 175000 )
|
||||
if( crtc->mode.timing.pixel_clock < 175000 )
|
||||
ecp_div = 0;
|
||||
else
|
||||
ecp_div = 1;
|
||||
@@ -595,10 +601,10 @@ static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_
|
||||
|
||||
|
||||
// apply virtual screen
|
||||
dest_left -= vc->mode.h_display_start + virtual_head->rel_x;
|
||||
dest_top -= vc->mode.v_display_start + virtual_head->rel_y;
|
||||
dest_right -= vc->mode.h_display_start + virtual_head->rel_x;
|
||||
dest_bottom -= vc->mode.v_display_start + virtual_head->rel_y;
|
||||
dest_left -= vc->mode.h_display_start + crtc->rel_x;
|
||||
dest_top -= vc->mode.v_display_start + crtc->rel_y;
|
||||
dest_right -= vc->mode.h_display_start + crtc->rel_x;
|
||||
dest_bottom -= vc->mode.v_display_start + crtc->rel_y;
|
||||
|
||||
|
||||
// clip to visible area
|
||||
@@ -612,12 +618,12 @@ static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_
|
||||
}
|
||||
|
||||
SHOW_FLOW( 3, "mode: w=%d, h=%d",
|
||||
head->mode.timing.h_display, head->mode.timing.v_display );
|
||||
crtc->mode.timing.h_display, crtc->mode.timing.v_display );
|
||||
|
||||
if( dest_right > head->mode.timing.h_display )
|
||||
dest_right = head->mode.timing.h_display;
|
||||
if( dest_bottom > head->mode.timing.v_display )
|
||||
dest_bottom = head->mode.timing.v_display;
|
||||
if( dest_right > crtc->mode.timing.h_display )
|
||||
dest_right = crtc->mode.timing.h_display;
|
||||
if( dest_bottom > crtc->mode.timing.v_display )
|
||||
dest_bottom = crtc->mode.timing.v_display;
|
||||
|
||||
SHOW_FLOW( 3, "src=(%d, %d, %d, %d)",
|
||||
src_left, src_top, src_right, src_bottom );
|
||||
@@ -718,16 +724,13 @@ static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_
|
||||
// TBD: there is no description at all concerning this, so v_accum_init may
|
||||
// need to be initialized based on original value
|
||||
{
|
||||
display_device_e disp_devices;
|
||||
|
||||
disp_devices = head->active_displays;
|
||||
if( (disp_devices & (dd_lvds | dd_dvi)) != 0 ) {
|
||||
if( (crtc->active_displays & (dd_lvds | dd_dvi)) != 0 ) {
|
||||
uint64 v_ratio;
|
||||
|
||||
// convert 32.32 format to 16.16 format; else we
|
||||
// cannot multiply two fixed point values without
|
||||
// overflow
|
||||
v_ratio = si->flatpanels[head->flatpanel_port].v_ratio >> (FIX_SHIFT - 16);
|
||||
v_ratio = si->flatpanels[crtc->flatpanel_port].v_ratio >> (FIX_SHIFT - 16);
|
||||
|
||||
v_inc = (v_inc * v_ratio) >> 16;
|
||||
}
|
||||
@@ -846,10 +849,10 @@ static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_
|
||||
OUTREG( regs, RADEON_OV0_V_INC, v_inc );
|
||||
|
||||
OUTREG( regs,
|
||||
head->is_crtc2 ? RADEON_OV1_Y_X_START : RADEON_OV0_Y_X_START,
|
||||
crtc->crtc_idx == 0 ? RADEON_OV0_Y_X_START : RADEON_OV1_Y_X_START,
|
||||
(dest_left) | (dest_top << 16) );
|
||||
OUTREG( regs,
|
||||
head->is_crtc2 ? RADEON_OV1_Y_X_END : RADEON_OV0_Y_X_END,
|
||||
crtc->crtc_idx == 0 ? RADEON_OV0_Y_X_END : RADEON_OV1_Y_X_END,
|
||||
(dest_right - 1) | ((dest_bottom - 1) << 16) );
|
||||
|
||||
OUTREG( regs, RADEON_OV0_P1_BLANK_LINES_AT_TOP,
|
||||
@@ -873,7 +876,7 @@ static status_t Radeon_ShowOverlay( accelerator_info *ai, virtual_head *virtual_
|
||||
RADEON_SCALER_DOUBLE_BUFFER |
|
||||
(node->ati_space << 8) |
|
||||
/*RADEON_SCALER_ADAPTIVE_DEINT |*/
|
||||
(head->is_crtc2 ? RADEON_SCALER_CRTC_SEL : 0 ));
|
||||
(crtc->crtc_idx == 0 ? 0 : RADEON_SCALER_CRTC_SEL ));
|
||||
|
||||
si->overlay_mgr.auto_flip_reg ^= RADEON_OV0_SOFT_EOF_TOGGLE;
|
||||
|
||||
@@ -895,7 +898,8 @@ done:
|
||||
|
||||
|
||||
// hide overlay, but not permanently
|
||||
void Radeon_TempHideOverlay( accelerator_info *ai )
|
||||
void Radeon_TempHideOverlay(
|
||||
accelerator_info *ai )
|
||||
{
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
@@ -904,7 +908,8 @@ void Radeon_TempHideOverlay( accelerator_info *ai )
|
||||
|
||||
|
||||
// hide overlay (can be called even if there is none visible)
|
||||
void Radeon_HideOverlay( accelerator_info *ai )
|
||||
void Radeon_HideOverlay(
|
||||
accelerator_info *ai )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
|
||||
@@ -917,12 +922,13 @@ void Radeon_HideOverlay( accelerator_info *ai )
|
||||
|
||||
// invalidate active head so it will be setup again once
|
||||
// a new overlay is shown
|
||||
si->active_overlay.head = -1;
|
||||
si->active_overlay.crtc_idx = -1;
|
||||
}
|
||||
|
||||
|
||||
// show new overlay buffer with same parameters as last one
|
||||
static void Radeon_ReplaceOverlayBuffer( accelerator_info *ai )
|
||||
static void Radeon_ReplaceOverlayBuffer(
|
||||
accelerator_info *ai )
|
||||
{
|
||||
#if 0
|
||||
shared_info *si = ai->si;
|
||||
@@ -984,14 +990,14 @@ static void Radeon_ReplaceOverlayBuffer( accelerator_info *ai )
|
||||
|
||||
|
||||
// get number of pixels of overlay shown on virtual port
|
||||
static int getIntersectArea( accelerator_info *ai, overlay_window *ow, virtual_head *virtual_head )
|
||||
static int getIntersectArea(
|
||||
accelerator_info *ai, overlay_window *ow, crtc_info *crtc )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
physical_head *head = &ai->si->heads[virtual_head->physical_head];
|
||||
int left, top, right, bottom;
|
||||
|
||||
left = ow->h_start - (vc->mode.h_display_start + virtual_head->rel_x);
|
||||
top = ow->v_start - (vc->mode.v_display_start + virtual_head->rel_y);
|
||||
left = ow->h_start - (vc->mode.h_display_start + crtc->rel_x);
|
||||
top = ow->v_start - (vc->mode.v_display_start + crtc->rel_y);
|
||||
right = left + ow->width;
|
||||
bottom = top + ow->height;
|
||||
|
||||
@@ -999,10 +1005,10 @@ static int getIntersectArea( accelerator_info *ai, overlay_window *ow, virtual_h
|
||||
left = 0;
|
||||
if( top < 0 )
|
||||
top = 0;
|
||||
if( right > head->mode.timing.h_display )
|
||||
right = head->mode.timing.h_display;
|
||||
if( bottom > head->mode.timing.v_display )
|
||||
bottom = head->mode.timing.v_display;
|
||||
if( right > crtc->mode.timing.h_display )
|
||||
right = crtc->mode.timing.h_display;
|
||||
if( bottom > crtc->mode.timing.v_display )
|
||||
bottom = crtc->mode.timing.v_display;
|
||||
|
||||
if( right < left || bottom < top )
|
||||
return 0;
|
||||
@@ -1013,12 +1019,12 @@ static int getIntersectArea( accelerator_info *ai, overlay_window *ow, virtual_h
|
||||
|
||||
// update overlay, to be called whenever something in terms of
|
||||
// overlay have or can have been changed
|
||||
status_t Radeon_UpdateOverlay( accelerator_info *ai )
|
||||
status_t Radeon_UpdateOverlay(
|
||||
accelerator_info *ai )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
virtual_head *virtual_head;
|
||||
physical_head *physical_head;
|
||||
int crtc_idx;
|
||||
|
||||
float brightness = 0.0f;
|
||||
float contrast = 1.0f;
|
||||
@@ -1040,38 +1046,40 @@ status_t Radeon_UpdateOverlay( accelerator_info *ai )
|
||||
if( (uint32)si->pending_overlay.ot != si->overlay_mgr.token )
|
||||
return B_BAD_VALUE;
|
||||
|
||||
/* SHOW_FLOW( 3, "num_ports=%d, whished_overlay_port=%d",
|
||||
vc->num_ports, vc->whished_overlay_port );*/
|
||||
|
||||
if( vc->different_heads > 1 ) {
|
||||
int area0, area1;
|
||||
|
||||
// determine on which port most of the overlay is shown
|
||||
area0 = getIntersectArea( ai, &si->pending_overlay.ow, &vc->heads[0] );
|
||||
area1 = getIntersectArea( ai, &si->pending_overlay.ow, &vc->heads[1] );
|
||||
area0 = getIntersectArea( ai, &si->pending_overlay.ow, &si->crtc[0] );
|
||||
area1 = getIntersectArea( ai, &si->pending_overlay.ow, &si->crtc[0] );
|
||||
|
||||
SHOW_FLOW( 3, "area0=%d, area1=%d", area0, area1 );
|
||||
|
||||
if( area0 >= area1 )
|
||||
virtual_head = &vc->heads[0];
|
||||
crtc_idx = 0;
|
||||
else
|
||||
virtual_head = &vc->heads[1];
|
||||
} else {
|
||||
crtc_idx = 1;
|
||||
|
||||
} else if( vc->independant_heads > 1 ) {
|
||||
// both ports show the same, use "swap displays" to decide
|
||||
// where to show the overlay (to be improved as this flag isn't
|
||||
// really designed for that)
|
||||
if( vc->independant_heads > 1 && vc->swap_displays )
|
||||
virtual_head = &vc->heads[1];
|
||||
if( vc->swap_displays )
|
||||
crtc_idx = 1;
|
||||
else
|
||||
virtual_head = &vc->heads[0];
|
||||
crtc_idx = 0;
|
||||
|
||||
} else {
|
||||
|
||||
// one crtc used only - pick the one that we use
|
||||
crtc_idx = vc->used_crtc[0] ? 0 : 1;
|
||||
}
|
||||
|
||||
si->pending_overlay.head = virtual_head->physical_head;
|
||||
physical_head = &si->heads[virtual_head->physical_head];
|
||||
si->pending_overlay.crtc_idx = crtc_idx;
|
||||
|
||||
// only update registers that have been changed to minimize work
|
||||
if( si->active_overlay.head != si->pending_overlay.head ) {
|
||||
Radeon_InitOverlay( ai, physical_head );
|
||||
if( si->active_overlay.crtc_idx != si->pending_overlay.crtc_idx ) {
|
||||
Radeon_InitOverlay( ai, crtc_idx );
|
||||
}
|
||||
|
||||
if( si->active_overlay.ob.space != si->pending_overlay.ob.space ) {
|
||||
@@ -1085,7 +1093,7 @@ status_t Radeon_UpdateOverlay( accelerator_info *ai )
|
||||
si->active_overlay.ob.width != si->pending_overlay.ob.width ||
|
||||
si->active_overlay.ob.height != si->pending_overlay.ob.height ||
|
||||
si->active_overlay.ob.bytes_per_row != si->pending_overlay.ob.bytes_per_row )
|
||||
Radeon_ShowOverlay( ai, virtual_head );
|
||||
Radeon_ShowOverlay( ai, crtc_idx );
|
||||
|
||||
else if( si->active_overlay.on != si->pending_overlay.on )
|
||||
Radeon_ReplaceOverlayBuffer( ai );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002/03, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -18,20 +18,21 @@
|
||||
|
||||
// Radeon's DACs share same public registers, this function
|
||||
// selects the DAC you'll talk to
|
||||
#define selectPalette( head ) \
|
||||
#define selectPalette( crtc_idx ) \
|
||||
WRITE_IB_REG( RADEON_DAC_CNTL2, \
|
||||
((head)->is_crtc2 ? RADEON_DAC2_PALETTE_ACC_CTL : 0) | \
|
||||
(crtc_idx == 0 ? 0 : RADEON_DAC2_PALETTE_ACC_CTL) | \
|
||||
(ai->si->dac_cntl2 & ~RADEON_DAC2_PALETTE_ACC_CTL) );
|
||||
|
||||
|
||||
// set standard colour palette (needed for non-palette modes)
|
||||
void Radeon_InitPalette( accelerator_info *ai, physical_head *head )
|
||||
void Radeon_InitPalette(
|
||||
accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
int i;
|
||||
|
||||
START_IB();
|
||||
|
||||
selectPalette( head );
|
||||
selectPalette( crtc_idx );
|
||||
|
||||
WRITE_IB_REG( RADEON_PALETTE_INDEX, 0 );
|
||||
|
||||
@@ -41,14 +42,15 @@ void Radeon_InitPalette( accelerator_info *ai, physical_head *head )
|
||||
SUBMIT_IB();
|
||||
}
|
||||
|
||||
static void setPalette( accelerator_info *ai, physical_head *head,
|
||||
static void setPalette(
|
||||
accelerator_info *ai, int crtc_idx,
|
||||
uint count, uint8 first, uint8 *color_data );
|
||||
|
||||
// public function: set colour palette
|
||||
void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags)
|
||||
void SET_INDEXED_COLORS(
|
||||
uint count, uint8 first, uint8 *color_data, uint32 flags )
|
||||
{
|
||||
virtual_card *vc = ai->vc;
|
||||
shared_info *si = ai->si;
|
||||
|
||||
(void)flags;
|
||||
|
||||
@@ -58,23 +60,24 @@ void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags
|
||||
SHOW_ERROR0( 2, "Tried to set palette in non-palette mode" );
|
||||
return;
|
||||
}
|
||||
|
||||
setPalette( ai, &si->heads[vc->heads[0].physical_head], count, first, color_data );
|
||||
|
||||
if( vc->independant_heads > 1 )
|
||||
setPalette( ai, &si->heads[vc->heads[1].physical_head], count, first, color_data );
|
||||
|
||||
if( vc->used_crtc[0] )
|
||||
setPalette( ai, 0, count, first, color_data );
|
||||
if( vc->used_crtc[1] )
|
||||
setPalette( ai, 1, count, first, color_data );
|
||||
}
|
||||
|
||||
|
||||
// set palette of one DAC
|
||||
static void setPalette( accelerator_info *ai, physical_head *head,
|
||||
static void setPalette(
|
||||
accelerator_info *ai, int crtc_idx,
|
||||
uint count, uint8 first, uint8 *color_data )
|
||||
{
|
||||
uint i;
|
||||
|
||||
START_IB();
|
||||
|
||||
selectPalette( head );
|
||||
selectPalette( crtc_idx );
|
||||
|
||||
WRITE_IB_REG( RADEON_PALETTE_INDEX, first );
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002/03, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -14,9 +14,11 @@
|
||||
#include "pll_access.h"
|
||||
#include "utils.h"
|
||||
#include <stdlib.h>
|
||||
#include "set_mode.h"
|
||||
|
||||
|
||||
static void Radeon_PLLWaitForReadUpdateComplete( accelerator_info *ai, physical_head *head )
|
||||
static void Radeon_PLLWaitForReadUpdateComplete(
|
||||
accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -24,18 +26,19 @@ static void Radeon_PLLWaitForReadUpdateComplete( accelerator_info *ai, physical_
|
||||
// 1. this is unsafe
|
||||
// 2. some r300 loop forever (reported by XFree86)
|
||||
for( i = 0; i < 10000; ++i ) {
|
||||
if( (Radeon_INPLL( ai->regs, ai->si->asic, head->is_crtc2 ? RADEON_P2PLL_REF_DIV : RADEON_PPLL_REF_DIV )
|
||||
if( (Radeon_INPLL( ai->regs, ai->si->asic, crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV )
|
||||
& RADEON_PPLL_ATOMIC_UPDATE_R) == 0 )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void Radeon_PLLWriteUpdate( accelerator_info *ai, physical_head *head )
|
||||
static void Radeon_PLLWriteUpdate(
|
||||
accelerator_info *ai, int crtc_idx )
|
||||
{
|
||||
Radeon_PLLWaitForReadUpdateComplete( ai, head );
|
||||
Radeon_PLLWaitForReadUpdateComplete( ai, crtc_idx );
|
||||
|
||||
Radeon_OUTPLLP( ai->regs, ai->si->asic,
|
||||
head->is_crtc2 ? RADEON_P2PLL_REF_DIV : RADEON_PPLL_REF_DIV,
|
||||
crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV,
|
||||
RADEON_PPLL_ATOMIC_UPDATE_W,
|
||||
~RADEON_PPLL_ATOMIC_UPDATE_W );
|
||||
}
|
||||
@@ -45,7 +48,8 @@ static void Radeon_PLLWriteUpdate( accelerator_info *ai, physical_head *head )
|
||||
// freq - whished frequency in Hz
|
||||
// fixed_post_div - if != 0, fixed divider to be used
|
||||
// dividers - filled with proper dividers
|
||||
void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_div, pll_dividers *dividers )
|
||||
void Radeon_CalcPLLDividers(
|
||||
const pll_info *pll, uint32 freq, uint fixed_post_div, pll_dividers *dividers )
|
||||
{
|
||||
// the PLL gets the reference
|
||||
// pll_in = ref_freq / ref_div
|
||||
@@ -71,8 +75,9 @@ void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_d
|
||||
best_post_div_idx, best_extra_post_div_idx;
|
||||
|
||||
uint32
|
||||
best_ref_div, best_feedback_div,
|
||||
best_freq, best_error, best_vco_dev;
|
||||
best_ref_div, best_feedback_div, best_freq;
|
||||
int32
|
||||
best_error, best_vco_dev;
|
||||
|
||||
best_error = 999999999;
|
||||
|
||||
@@ -127,7 +132,8 @@ void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_d
|
||||
// we can either iterate through feedback or reference dividers;
|
||||
// usually, there are fewer possible reference dividers, so I picked them
|
||||
for( ref_div = pll->min_ref_div; ref_div <= pll->max_ref_div; ++ref_div ) {
|
||||
uint32 feedback_div, cur_freq, error, vco_dev;
|
||||
uint32 feedback_div, cur_freq;
|
||||
int32 error, vco_dev;
|
||||
|
||||
// this implies the frequency of the lock unit
|
||||
uint32 pll_in = pll->ref_freq / ref_div;
|
||||
@@ -144,17 +150,17 @@ void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_d
|
||||
if( feedback_div < pll->min_feedback_div ||
|
||||
feedback_div > pll->max_feedback_div )
|
||||
continue;
|
||||
|
||||
|
||||
// let's see what we've got
|
||||
cur_freq = RoundDiv64(
|
||||
(int64)pll->ref_freq * 10000 * feedback_div * pll->extra_feedback_div,
|
||||
ref_div * post_div );
|
||||
|
||||
|
||||
// absolute error in terms of output clock
|
||||
error = abs( cur_freq - freq );
|
||||
// deviation from perfect VCO clock
|
||||
vco_dev = abs( vco - pll->best_vco );
|
||||
|
||||
|
||||
// if there is no optimal VCO frequency, choose setting with less error;
|
||||
// if there is an optimal VCO frequency, choose new settings if
|
||||
// - error is reduced significantly (100 Hz or more), or
|
||||
@@ -165,6 +171,7 @@ void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_d
|
||||
(error < best_error - 100 ||
|
||||
(abs( error - best_error ) < 100 && vco_dev < best_vco_dev ))))
|
||||
{
|
||||
//SHOW_FLOW( 2, "got freq=%d, best_freq=%d", freq, cur_freq );
|
||||
best_post_div_idx = post_div_idx;
|
||||
best_extra_post_div_idx = extra_post_div_idx;
|
||||
best_ref_div = ref_div;
|
||||
@@ -184,6 +191,10 @@ void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_d
|
||||
dividers->ref = best_ref_div;
|
||||
dividers->feedback = best_feedback_div;
|
||||
dividers->freq = best_freq;
|
||||
|
||||
/*SHOW_FLOW( 2, "post_code=%d, post=%d, extra_post_code=%d, extra_post=%d, ref=%d, feedback=%d, freq=%d",
|
||||
dividers->post_code, dividers->post, dividers->extra_post_code,
|
||||
dividers->extra_post, dividers->ref, dividers->feedback, dividers->freq );*/
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +204,7 @@ void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_d
|
||||
// with precisely the same frame rate; the solution is to tweak the CRT
|
||||
// image a bit by making it wider/taller/smaller until the frame rate
|
||||
// drift is under a given threshold;
|
||||
// we follows two aims:
|
||||
// we follow two aims:
|
||||
// - primary, keep frame rate in sync
|
||||
// - secondary, only tweak as much as unavoidable
|
||||
void Radeon_MatchCRTPLL(
|
||||
@@ -267,7 +278,7 @@ void Radeon_MatchCRTPLL(
|
||||
// if drift is within threshold, we take this setting and stop
|
||||
// searching (later iteration will increasingly tweak screen size,
|
||||
// and we don't really want that)
|
||||
if( frame_rate_drift < max_frame_rate_drift ) {
|
||||
if( frame_rate_drift <= max_frame_rate_drift ) {
|
||||
SHOW_INFO( 2, "frame_rate_drift=%d, crt_freq=%d, v_total=%d, h_total=%d",
|
||||
frame_rate_drift, crt_freq, v_total, h_total );
|
||||
|
||||
@@ -348,7 +359,7 @@ void Radeon_GetTVPLLConfiguration( const general_pll_info *general_pll, pll_info
|
||||
// in the original code, they set it to 330kHz if PAL is requested and
|
||||
// quartz is 27 MHz, but I don't see how these circumstances can effect the
|
||||
// mimimal PLL input frequency
|
||||
pll->pll_in_min = 40;
|
||||
pll->pll_in_min = 20;//40;
|
||||
// in the original code, they don't define an upper limit
|
||||
pll->pll_in_max = 100;
|
||||
pll->extra_feedback_div = 1;
|
||||
@@ -391,47 +402,46 @@ void Radeon_GetTVCRTPLLConfiguration( const general_pll_info *general_pll, pll_i
|
||||
}
|
||||
|
||||
|
||||
// calc PLL dividers for CRT
|
||||
// mode->timing.pixel_clock must be in Hz because required accuracy in TV-Out mode
|
||||
void Radeon_CalcCRTPLLDividers(
|
||||
const general_pll_info *general_pll, const display_mode *mode, pll_dividers *dividers )
|
||||
{
|
||||
pll_info pll;
|
||||
|
||||
pll.post_divs = post_divs;
|
||||
pll.extra_post_divs = extra_post_divs;
|
||||
pll.ref_freq = general_pll->ref_freq;
|
||||
pll.vco_min = general_pll->min_pll_freq;
|
||||
pll.vco_max = general_pll->max_pll_freq;
|
||||
pll.min_ref_div = 2;
|
||||
pll.max_ref_div = 0x3ff;
|
||||
pll.pll_in_min = 40;
|
||||
pll.pll_in_max = 100;
|
||||
pll.extra_feedback_div = 1;
|
||||
pll.min_feedback_div = 4;
|
||||
pll.max_feedback_div = 0x7ff;
|
||||
pll.best_vco = 0;
|
||||
|
||||
SHOW_FLOW( 2, "freq=%ld", mode->timing.pixel_clock );
|
||||
|
||||
Radeon_CalcPLLDividers( &pll, mode->timing.pixel_clock, 0, dividers );
|
||||
}
|
||||
|
||||
|
||||
// calculate PLL registers
|
||||
// mode->timing.pixel_clock must be in Hz because required accuracy in TV-Out mode
|
||||
// (old: freq is in 10kHz)
|
||||
// fixed_dividers - if non-NULL, you can force a pre-calculated divider (used for TV-Out)
|
||||
void Radeon_CalcPLLRegisters( general_pll_info *general_pll,
|
||||
const display_mode *mode, pll_dividers *fixed_dividers, port_regs *values )
|
||||
void Radeon_CalcPLLRegisters(
|
||||
const display_mode *mode, const pll_dividers *dividers, pll_regs *values )
|
||||
{
|
||||
pll_dividers dividers;
|
||||
values->dot_clock_freq = dividers->freq;
|
||||
values->feedback_div = dividers->feedback;
|
||||
values->post_div = dividers->post;
|
||||
values->pll_output_freq = dividers->freq * dividers->post;
|
||||
|
||||
if( fixed_dividers == NULL ) {
|
||||
pll_info pll;
|
||||
|
||||
pll.post_divs = post_divs;
|
||||
pll.extra_post_divs = extra_post_divs;
|
||||
pll.ref_freq = general_pll->ref_freq;
|
||||
pll.vco_min = general_pll->min_pll_freq;
|
||||
pll.vco_max = general_pll->max_pll_freq;
|
||||
pll.min_ref_div = 2;
|
||||
pll.max_ref_div = 0x3ff;
|
||||
pll.pll_in_min = 40;
|
||||
pll.pll_in_max = 100;
|
||||
pll.extra_feedback_div = 1;
|
||||
pll.min_feedback_div = 4;
|
||||
pll.max_feedback_div = 0x7ff;
|
||||
pll.best_vco = 0;
|
||||
|
||||
SHOW_FLOW( 2, "freq=%ld", mode->timing.pixel_clock/*freq * 10000*/ );
|
||||
|
||||
Radeon_CalcPLLDividers( &pll, mode->timing.pixel_clock /*freq * 10000*/, 0, ÷rs );
|
||||
} else {
|
||||
// dividers are precalculated, so use them
|
||||
dividers = *fixed_dividers;
|
||||
}
|
||||
|
||||
values->dot_clock_freq = dividers.freq;
|
||||
values->feedback_div = dividers.feedback;
|
||||
values->post_div = dividers.post;
|
||||
values->pll_output_freq = dividers.freq * dividers.post;
|
||||
|
||||
values->ppll_ref_div = dividers.ref;
|
||||
values->ppll_div_3 = (dividers.feedback | (dividers.post_code << 16));
|
||||
values->ppll_ref_div = dividers->ref;
|
||||
values->ppll_div_3 = (dividers->feedback | (dividers->post_code << 16));
|
||||
// this is mad: the PLL controls the horizontal length in sub-byte precision!
|
||||
values->htotal_cntl = mode->timing.h_total & 7;
|
||||
|
||||
@@ -441,7 +451,8 @@ void Radeon_CalcPLLRegisters( general_pll_info *general_pll,
|
||||
}
|
||||
|
||||
// write values into PLL registers
|
||||
void Radeon_ProgramPLL( accelerator_info *ai, physical_head *head, port_regs *values )
|
||||
void Radeon_ProgramPLL(
|
||||
accelerator_info *ai, int crtc_idx, pll_regs *values )
|
||||
{
|
||||
vuint8 *regs = ai->regs;
|
||||
radeon_type asic = ai->si->asic;
|
||||
@@ -450,11 +461,11 @@ void Radeon_ProgramPLL( accelerator_info *ai, physical_head *head, port_regs *va
|
||||
|
||||
// use some other PLL for pixel clock source to not fiddling with PLL
|
||||
// while somebody is using it
|
||||
Radeon_OUTPLLP( regs, asic, head->is_crtc2 ? RADEON_PIXCLKS_CNTL : RADEON_VCLK_ECP_CNTL,
|
||||
Radeon_OUTPLLP( regs, asic, crtc_idx == 0 ? RADEON_VCLK_ECP_CNTL : RADEON_PIXCLKS_CNTL,
|
||||
RADEON_VCLK_SRC_CPU_CLK, ~RADEON_VCLK_SRC_SEL_MASK );
|
||||
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
head->is_crtc2 ? RADEON_P2PLL_CNTL : RADEON_PPLL_CNTL,
|
||||
crtc_idx == 0 ? RADEON_PPLL_CNTL : RADEON_P2PLL_CNTL,
|
||||
RADEON_PPLL_RESET
|
||||
| RADEON_PPLL_ATOMIC_UPDATE_EN
|
||||
| RADEON_PPLL_VGA_ATOMIC_UPDATE_EN,
|
||||
@@ -467,40 +478,40 @@ void Radeon_ProgramPLL( accelerator_info *ai, physical_head *head, port_regs *va
|
||||
RADEON_PLL_DIV_SEL_DIV3,
|
||||
~RADEON_PLL_DIV_SEL_MASK );
|
||||
|
||||
if( ai->si->asic >= rt_r300 && !head->is_crtc2 ) {
|
||||
// with r300, the reference divider of the first PLL was moved
|
||||
// to another bit position; at the old location, you only find
|
||||
// the "BIOS suggested divider"; no clue why they did that
|
||||
if( ai->si->new_pll && crtc_idx == 0 ) {
|
||||
// starting with r300, the reference divider of the first PLL was
|
||||
// moved to another bit position; at the old location, you only
|
||||
// find the "BIOS suggested divider"; no clue why they did that
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
RADEON_PPLL_REF_DIV,
|
||||
values->ppll_ref_div << RADEON_PPLL_REF_DIV_ACC_SHIFT,
|
||||
~RADEON_PPLL_REF_DIV_ACC_MASK );
|
||||
} else {
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
head->is_crtc2 ? RADEON_P2PLL_REF_DIV : RADEON_PPLL_REF_DIV,
|
||||
crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV,
|
||||
values->ppll_ref_div,
|
||||
~RADEON_PPLL_REF_DIV_MASK );
|
||||
}
|
||||
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
head->is_crtc2 ? RADEON_P2PLL_DIV_0 : RADEON_PPLL_DIV_3,
|
||||
crtc_idx == 0 ? RADEON_PPLL_DIV_3 : RADEON_P2PLL_DIV_0,
|
||||
values->ppll_div_3,
|
||||
~RADEON_PPLL_FB3_DIV_MASK );
|
||||
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
head->is_crtc2 ? RADEON_P2PLL_DIV_0 : RADEON_PPLL_DIV_3,
|
||||
crtc_idx == 0 ? RADEON_PPLL_DIV_3 : RADEON_P2PLL_DIV_0,
|
||||
values->ppll_div_3,
|
||||
~RADEON_PPLL_POST3_DIV_MASK );
|
||||
|
||||
Radeon_PLLWriteUpdate( ai, head );
|
||||
Radeon_PLLWaitForReadUpdateComplete( ai, head );
|
||||
Radeon_PLLWriteUpdate( ai, crtc_idx );
|
||||
Radeon_PLLWaitForReadUpdateComplete( ai, crtc_idx );
|
||||
|
||||
Radeon_OUTPLL( regs, asic,
|
||||
head->is_crtc2 ? RADEON_HTOTAL2_CNTL : RADEON_HTOTAL_CNTL,
|
||||
crtc_idx == 0 ? RADEON_HTOTAL_CNTL : RADEON_HTOTAL2_CNTL,
|
||||
values->htotal_cntl );
|
||||
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
head->is_crtc2 ? RADEON_P2PLL_CNTL : RADEON_PPLL_CNTL, 0,
|
||||
crtc_idx == 0 ? RADEON_PPLL_CNTL : RADEON_P2PLL_CNTL, 0,
|
||||
~(RADEON_PPLL_RESET
|
||||
| RADEON_PPLL_SLEEP
|
||||
| RADEON_PPLL_ATOMIC_UPDATE_EN
|
||||
@@ -511,6 +522,6 @@ void Radeon_ProgramPLL( accelerator_info *ai, physical_head *head, port_regs *va
|
||||
|
||||
// use PLL for pixel clock again
|
||||
Radeon_OUTPLLP( regs, asic,
|
||||
head->is_crtc2 ? RADEON_PIXCLKS_CNTL : RADEON_VCLK_ECP_CNTL,
|
||||
crtc_idx == 0 ? RADEON_VCLK_ECP_CNTL : RADEON_PIXCLKS_CNTL,
|
||||
RADEON_VCLK_SRC_PPLL_CLK, ~RADEON_VCLK_SRC_SEL_MASK );
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002/03, Thomas Kurschel
|
||||
Copyright (c) 2002-2005, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -18,12 +18,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef __HAIKU__
|
||||
void _kdprintf_(const char *format, ...);
|
||||
#define dprintf _kdprintf_
|
||||
#else
|
||||
#define dprintf _sPrintf
|
||||
#endif
|
||||
void _sPrintf(const char *format, ...);
|
||||
//bool set_dprintf_enabled(bool); /* returns old enable flag */
|
||||
|
||||
#define dprintf _sPrintf
|
||||
|
||||
extern int debug_level_flow;
|
||||
extern int debug_level_info;
|
||||
@@ -32,7 +30,7 @@ extern int debug_level_error;
|
||||
/*#define DEBUG_WAIT_ON_MSG 1000000
|
||||
#define DEBUG_WAIT_ON_ERROR 1000000*/
|
||||
|
||||
#define DEBUG_MSG_PREFIX "Radeon Acc - "
|
||||
#define DEBUG_MSG_PREFIX "Radeon - "
|
||||
|
||||
#define DEBUG_MAX_LEVEL_FLOW 2
|
||||
|
||||
@@ -41,9 +39,11 @@ extern int debug_level_error;
|
||||
|
||||
// info about this accelerant
|
||||
typedef struct accelerator_info {
|
||||
shared_info *si; // info shared between accelerants
|
||||
virtual_card *vc; // associated virtual card
|
||||
vuint8 *regs; // pointer to mapped registers
|
||||
// !! dont't make it vuint32, access macros rely on 8 bits !!
|
||||
|
||||
area_id shared_info_area; // info shared between accelerants
|
||||
area_id regs_area; // MM I/O registers
|
||||
area_id virtual_card_area; // info about virtual card
|
||||
@@ -64,30 +64,27 @@ typedef struct accelerator_info {
|
||||
|
||||
area_id mode_list_area; // cloned list of standard display modes
|
||||
display_mode *mode_list; // list of standard display modes
|
||||
shared_info *si; // info shared between accelerants
|
||||
} accelerator_info;
|
||||
|
||||
|
||||
#define IS_INTERNAL_TV_OUT( tv_chip ) \
|
||||
( (tv_chip) == tc_internal_rt1 || (tv_chip) == tc_internal_rt2 )
|
||||
|
||||
|
||||
// vesa_modes.c
|
||||
extern const display_timing vesa_mode_list[];
|
||||
extern const size_t vesa_mode_list_count;
|
||||
|
||||
// SetDisplayMode.c
|
||||
uint32 Radeon_RoundVWidth( int virtual_width, int bpp );
|
||||
status_t Radeon_MoveDisplay( accelerator_info *ai, uint16 h_display_start, uint16 v_display_start );
|
||||
|
||||
|
||||
// crtc.c
|
||||
void Radeon_ReadCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values );
|
||||
uint16 Radeon_GetHSyncFudge( physical_head *head, int datatype );
|
||||
void Radeon_CalcCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
display_mode *mode, port_regs *values );
|
||||
void Radeon_ProgramCRTCRegisters( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values );
|
||||
|
||||
|
||||
// multimon.c
|
||||
void Radeon_HideMultiMode( virtual_card *vc, display_mode *mode );
|
||||
void Radeon_DetectMultiMode( virtual_card *vc, display_mode *mode );
|
||||
void Radeon_VerifyMultiMode( virtual_card *vc, shared_info *si, display_mode *mode );
|
||||
void Radeon_InitMultiModeVars( virtual_card *vc, display_mode *mode );
|
||||
void Radeon_InitMultiModeVars( accelerator_info *ai, display_mode *mode );
|
||||
status_t Radeon_CheckMultiMonTunnel( virtual_card *vc, display_mode *mode,
|
||||
const display_mode *low, const display_mode *high, bool *isTunnel );
|
||||
bool Radeon_NeedsSecondPort( display_mode *mode );
|
||||
@@ -99,42 +96,14 @@ bool Radeon_GetFormat( int space, int *format, int *bpp );
|
||||
status_t Radeon_CreateModeList( shared_info *si );
|
||||
|
||||
|
||||
// pll.c
|
||||
void Radeon_CalcPLLRegisters( general_pll_info *pll, const display_mode *mode, pll_dividers *fixed_dividers, port_regs *values );
|
||||
void Radeon_ProgramPLL( accelerator_info *ai, physical_head *head, port_regs *values );
|
||||
void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_div, pll_dividers *dividers );
|
||||
void Radeon_MatchCRTPLL(
|
||||
const pll_info *pll,
|
||||
uint32 tv_v_total, uint32 tv_h_total, uint32 tv_frame_size_adjust, uint32 freq,
|
||||
const display_mode *mode, uint32 max_v_tweak, uint32 max_h_tweak,
|
||||
uint32 max_frame_rate_drift, uint32 fixed_post_div,
|
||||
pll_dividers *dividers,
|
||||
display_mode *tweaked_mode );
|
||||
void Radeon_GetTVPLLConfiguration( const general_pll_info *general_pll, pll_info *pll,
|
||||
bool internal_encoder );
|
||||
void Radeon_GetTVCRTPLLConfiguration( const general_pll_info *general_pll, pll_info *pll,
|
||||
bool internal_tv_encoder );
|
||||
|
||||
|
||||
// flat_panel.c
|
||||
void Radeon_ReadRMXRegisters( accelerator_info *ai, port_regs *values );
|
||||
void Radeon_CalcRMXRegisters( fp_info *flatpanel, display_mode *mode, bool use_rmx, port_regs *values );
|
||||
void Radeon_ProgramRMXRegisters( accelerator_info *ai, port_regs *values );
|
||||
|
||||
void Radeon_ReadFPRegisters( accelerator_info *ai, port_regs *values );
|
||||
void Radeon_CalcFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
fp_info *fp_port, port_regs *values );
|
||||
void Radeon_ProgramFPRegisters( accelerator_info *ai, physical_head *head,
|
||||
fp_info *fp_port, port_regs *values );
|
||||
|
||||
|
||||
// dpms.c
|
||||
status_t Radeon_SetDPMS( accelerator_info *ai, physical_head *head, int mode );
|
||||
uint32 Radeon_GetDPMS( accelerator_info *ai, physical_head *head );
|
||||
status_t Radeon_SetDPMS( accelerator_info *ai, int crtc_idx, int mode );
|
||||
uint32 Radeon_GetDPMS( accelerator_info *ai, int crtc_idx );
|
||||
|
||||
|
||||
// Cursor.c
|
||||
void Radeon_SetCursorColors( accelerator_info *ai, physical_head *head );
|
||||
void Radeon_SetCursorColors( accelerator_info *ai, int crtc_idx );
|
||||
void Radeon_ShowCursor( accelerator_info *ai, int crtc_idx );
|
||||
|
||||
|
||||
// Acceleration.c
|
||||
@@ -171,32 +140,13 @@ void Radeon_Spin( uint32 delay );
|
||||
void Radeon_DetectDisplays( accelerator_info *ai );
|
||||
|
||||
|
||||
// tv_out.c
|
||||
void Radeon_DetectTVOut( accelerator_info *ai );
|
||||
void Radeon_CalcTVParams( const general_pll_info *general_pll, tv_params *params,
|
||||
const tv_timing *tv_timing, bool internal_encoder,
|
||||
const display_mode *mode, display_mode *tweaked_mode );
|
||||
void Radeon_CalcTVRegisters( accelerator_info *ai, display_mode *mode, tv_timing *timing,
|
||||
tv_params *params, port_regs *values, physical_head *head,
|
||||
bool internal_encoder, tv_standard tv_format );
|
||||
void Radeon_ProgramTVRegisters( accelerator_info *ai, port_regs *values, bool internal_encoder );
|
||||
void Radeon_ReadTVRegisters( accelerator_info *ai, port_regs *values, bool internal_encoder );
|
||||
|
||||
extern tv_timing Radeon_std_tv_timing[6];
|
||||
|
||||
|
||||
// palette.c
|
||||
void Radeon_InitPalette( accelerator_info *ai, physical_head *head );
|
||||
void Radeon_InitPalette( accelerator_info *ai, int crtc_idx );
|
||||
|
||||
|
||||
// monitor_routing.h
|
||||
void Radeon_ReadMonitorRoutingRegs( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values );
|
||||
void Radeon_CalcMonitorRouting( accelerator_info *ai, physical_head *head,
|
||||
port_regs *values );
|
||||
void Radeon_ProgramMonitorRouting( accelerator_info *ai, physical_head *head, port_regs *values );
|
||||
void Radeon_SetupDefaultMonitorRouting( accelerator_info *ai, int whished_num_heads );
|
||||
|
||||
// theatre_out.c
|
||||
void Radeon_DetectTVOut( accelerator_info *ai );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
Copyright (c) 2002-04, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
|
||||
Header file explicitely for display mode changes
|
||||
*/
|
||||
|
||||
#ifndef _SET_MODE_H
|
||||
#define _SET_MODE_H
|
||||
|
||||
// PLL divider values
|
||||
typedef struct {
|
||||
uint32 post_code; // code for post divider
|
||||
uint32 post; // value of post divider
|
||||
uint32 extra_post_code; // code for extra post divider
|
||||
uint32 extra_post; // value of extra post divider
|
||||
uint32 ref; // reference divider
|
||||
uint32 feedback; // feedback divider
|
||||
uint32 freq; // resulting frequency
|
||||
} pll_dividers;
|
||||
|
||||
|
||||
// TV-timing
|
||||
typedef struct {
|
||||
uint32 freq; // TV sub carrier frequency x12
|
||||
uint16 h_total;
|
||||
uint16 h_sync_len;
|
||||
uint16 h_genclk_delay;
|
||||
uint16 h_setup_delay;
|
||||
uint16 h_active_delay;
|
||||
uint16 h_active_len;
|
||||
uint16 v_total;
|
||||
uint16 v_active_lines;
|
||||
uint16 v_field_total;
|
||||
uint16 v_fields;
|
||||
uint16 f_total;
|
||||
uint16 frame_size_adjust;
|
||||
uint32 scale;
|
||||
} tv_timing;
|
||||
|
||||
|
||||
// TV-Out parameters
|
||||
typedef struct {
|
||||
uint16 y_accum_init;
|
||||
uint16 uv_accum_init;
|
||||
uint16 uv_inc;
|
||||
uint16 h_inc;
|
||||
uint32 tv_clocks_to_active;
|
||||
|
||||
uint16 f_restart;
|
||||
uint16 v_restart;
|
||||
uint16 h_restart;
|
||||
bool mode888;
|
||||
|
||||
uint16 y_saw_tooth_slope;
|
||||
uint16 y_saw_tooth_amp;
|
||||
uint16 y_rise_accum_init;
|
||||
uint16 y_fall_accum_init;
|
||||
bool y_coeff_enable;
|
||||
uint8 y_coeff_value;
|
||||
|
||||
pll_dividers tv_dividers;
|
||||
pll_dividers crt_dividers;
|
||||
|
||||
tv_timing timing;
|
||||
} impactv_params;
|
||||
|
||||
|
||||
// CRTC register content (for mode change)
|
||||
typedef struct {
|
||||
uint32 crtc_h_total_disp;
|
||||
uint32 crtc_h_sync_strt_wid;
|
||||
uint32 crtc_v_total_disp;
|
||||
uint32 crtc_v_sync_strt_wid;
|
||||
uint32 crtc_pitch;
|
||||
uint32 crtc_gen_cntl;
|
||||
uint32 crtc_offset_cntl;
|
||||
} crtc_regs;
|
||||
|
||||
|
||||
// PLL register content (for mode change)
|
||||
typedef struct {
|
||||
uint32 ppll_div_3;
|
||||
uint32 ppll_ref_div;
|
||||
uint32 htotal_cntl;
|
||||
|
||||
// pure information
|
||||
uint32 dot_clock_freq; // in 10 kHz
|
||||
uint32 pll_output_freq;// in 10 kHz
|
||||
int feedback_div;
|
||||
int post_div;
|
||||
} pll_regs;
|
||||
|
||||
|
||||
// Flat Panel register content (for mode change)
|
||||
typedef struct {
|
||||
uint32 fp_gen_cntl;
|
||||
uint32 fp_panel_cntl;
|
||||
uint32 lvds_gen_cntl;
|
||||
uint32 fp_h_sync_strt_wid;
|
||||
uint32 fp_v_sync_strt_wid;
|
||||
uint32 fp2_gen_cntl;
|
||||
|
||||
uint32 fp2_h_sync_strt_wid;
|
||||
uint32 fp2_v_sync_strt_wid;
|
||||
|
||||
// RMX registers
|
||||
uint32 fp_horz_stretch;
|
||||
uint32 fp_vert_stretch;
|
||||
} fp_regs;
|
||||
|
||||
|
||||
#define RADEON_TV_TIMING_SIZE 32
|
||||
#define RADEON_TV_UPSAMP_COEFF_NUM (5*3)
|
||||
|
||||
|
||||
// ImpacTV-Out regs (for mode change)
|
||||
typedef struct {
|
||||
uint32 tv_ftotal;
|
||||
uint32 tv_vscaler_cntl1;
|
||||
uint32 tv_y_saw_tooth_cntl;
|
||||
uint32 tv_y_fall_cntl;
|
||||
uint32 tv_y_rise_cntl;
|
||||
uint32 tv_vscaler_cntl2;
|
||||
uint32 tv_hrestart;
|
||||
uint32 tv_vrestart;
|
||||
uint32 tv_frestart;
|
||||
uint32 tv_tv_pll_cntl;
|
||||
uint32 tv_crt_pll_cntl;
|
||||
uint32 tv_clock_sel_cntl;
|
||||
uint32 tv_clkout_cntl;
|
||||
uint32 tv_htotal;
|
||||
uint32 tv_hsize;
|
||||
uint32 tv_hdisp;
|
||||
uint32 tv_hstart;
|
||||
uint32 tv_vtotal;
|
||||
uint32 tv_vdisp;
|
||||
uint32 tv_sync_size;
|
||||
uint32 tv_timing_cntl;
|
||||
uint32 tv_modulator_cntl1;
|
||||
uint32 tv_modulator_cntl2;
|
||||
uint32 tv_data_delay_a;
|
||||
uint32 tv_data_delay_b;
|
||||
uint32 tv_frame_lock_cntl;
|
||||
uint32 tv_pll_cntl1;
|
||||
uint32 tv_rgb_cntl;
|
||||
uint32 tv_pre_dac_mux_cntl;
|
||||
uint32 tv_master_cntl;
|
||||
uint32 tv_dac_cntl;
|
||||
uint32 tv_uv_adr;
|
||||
uint32 tv_pll_fine_cntl;
|
||||
uint32 tv_gain_limit_settings;
|
||||
uint32 tv_linear_gain_settings;
|
||||
uint32 tv_upsamp_and_gain_cntl;
|
||||
uint32 tv_crc_cntl;
|
||||
|
||||
uint16 tv_hor_timing[RADEON_TV_TIMING_SIZE];
|
||||
uint16 tv_vert_timing[RADEON_TV_TIMING_SIZE];
|
||||
|
||||
uint32 tv_upsample_filter_coeff[RADEON_TV_UPSAMP_COEFF_NUM];
|
||||
} impactv_regs;
|
||||
|
||||
|
||||
// Monitor Signal Routing regs (for mode change)
|
||||
// (they collide with many other *_regs, so take
|
||||
// care to set only the bits really used for routing)
|
||||
typedef struct {
|
||||
// DAC registers
|
||||
uint32 dac_cntl2;
|
||||
uint32 dac_cntl;
|
||||
uint32 tv_master_cntl;
|
||||
uint32 tv_dac_cntl;
|
||||
bool skip_tv_dac; // if true, don't write tv_dac_cntl
|
||||
|
||||
// Display path registers
|
||||
uint32 disp_hw_debug;
|
||||
uint32 disp_output_cntl;
|
||||
uint32 disp_tv_out_cntl;
|
||||
|
||||
// CRTC registers
|
||||
uint32 crtc_ext_cntl;
|
||||
uint32 crtc2_gen_cntl;
|
||||
|
||||
// PLL regs
|
||||
uint32 vclk_ecp_cntl;
|
||||
uint32 pixclks_cntl;
|
||||
|
||||
// GP IO-pad
|
||||
uint32 gpiopad_a;
|
||||
|
||||
// flat panel registers
|
||||
uint32 fp_gen_cntl;
|
||||
uint32 fp2_gen_cntl;
|
||||
} routing_regs;
|
||||
|
||||
|
||||
// crtc.c
|
||||
uint16 Radeon_GetHSyncFudge( crtc_info *crtc, int datatype );
|
||||
void Radeon_CalcCRTCRegisters( accelerator_info *ai, crtc_info *crtc,
|
||||
display_mode *mode, crtc_regs *values );
|
||||
void Radeon_ProgramCRTCRegisters( accelerator_info *ai, int crtc_idx,
|
||||
crtc_regs *values );
|
||||
|
||||
|
||||
// pll.c
|
||||
void Radeon_CalcCRTPLLDividers( const general_pll_info *general_pll, const display_mode *mode, pll_dividers *dividers );
|
||||
void Radeon_CalcPLLRegisters( const display_mode *mode, const pll_dividers *dividers, pll_regs *values );
|
||||
void Radeon_ProgramPLL( accelerator_info *ai, int crtc_idx, pll_regs *values );
|
||||
void Radeon_CalcPLLDividers( const pll_info *pll, uint32 freq, uint fixed_post_div, pll_dividers *dividers );
|
||||
void Radeon_MatchCRTPLL(
|
||||
const pll_info *pll,
|
||||
uint32 tv_v_total, uint32 tv_h_total, uint32 tv_frame_size_adjust, uint32 freq,
|
||||
const display_mode *mode, uint32 max_v_tweak, uint32 max_h_tweak,
|
||||
uint32 max_frame_rate_drift, uint32 fixed_post_div,
|
||||
pll_dividers *dividers,
|
||||
display_mode *tweaked_mode );
|
||||
void Radeon_GetTVPLLConfiguration( const general_pll_info *general_pll, pll_info *pll,
|
||||
bool internal_encoder );
|
||||
void Radeon_GetTVCRTPLLConfiguration( const general_pll_info *general_pll, pll_info *pll,
|
||||
bool internal_tv_encoder );
|
||||
|
||||
|
||||
// flat_panel.c
|
||||
void Radeon_ReadRMXRegisters( accelerator_info *ai, fp_regs *values );
|
||||
void Radeon_CalcRMXRegisters( fp_info *flatpanel, display_mode *mode, bool use_rmx, fp_regs *values );
|
||||
void Radeon_ProgramRMXRegisters( accelerator_info *ai, fp_regs *values );
|
||||
|
||||
void Radeon_ReadFPRegisters( accelerator_info *ai, fp_regs *values );
|
||||
void Radeon_CalcFPRegisters( accelerator_info *ai, crtc_info *crtc,
|
||||
fp_info *fp_port, crtc_regs *crtc_values, fp_regs *values );
|
||||
void Radeon_ProgramFPRegisters( accelerator_info *ai, crtc_info *crtc,
|
||||
fp_info *fp_port, fp_regs *values );
|
||||
|
||||
|
||||
// monitor_routing.h
|
||||
void Radeon_ReadMonitorRoutingRegs(
|
||||
accelerator_info *ai, routing_regs *values );
|
||||
void Radeon_CalcMonitorRouting(
|
||||
accelerator_info *ai, const impactv_params *tv_parameters, routing_regs *values );
|
||||
void Radeon_ProgramMonitorRouting(
|
||||
accelerator_info *ai, routing_regs *values );
|
||||
void Radeon_SetupDefaultMonitorRouting(
|
||||
accelerator_info *ai, int whished_num_heads, bool use_laptop_panel );
|
||||
|
||||
|
||||
// impactv.c
|
||||
|
||||
typedef void (*impactv_write_FIFO) (
|
||||
accelerator_info *ai, uint16 addr, uint32 value );
|
||||
typedef uint32 (*impactv_read_FIFO) (
|
||||
accelerator_info *ai, uint16 addr );
|
||||
|
||||
void Radeon_CalcImpacTVParams(
|
||||
const general_pll_info *general_pll, impactv_params *params,
|
||||
tv_standard_e tv_format, bool internal_encoder,
|
||||
const display_mode *mode, display_mode *tweaked_mode );
|
||||
void Radeon_CalcImpacTVRegisters(
|
||||
accelerator_info *ai, display_mode *mode,
|
||||
impactv_params *params, impactv_regs *values, int crtc_idx,
|
||||
bool internal_encoder, tv_standard_e tv_format, display_device_e display_device );
|
||||
void Radeon_ImpacTVwriteHorTimingTable(
|
||||
accelerator_info *ai, impactv_write_FIFO write, impactv_regs *values, bool internal_encoder );
|
||||
void Radeon_ImpacTVwriteVertTimingTable(
|
||||
accelerator_info *ai, impactv_write_FIFO write, impactv_regs *values );
|
||||
|
||||
|
||||
// theatre_out.c
|
||||
void Radeon_TheatreProgramTVRegisters( accelerator_info *ai, impactv_regs *values );
|
||||
void Radeon_TheatreReadTVRegisters( accelerator_info *ai, impactv_regs *values );
|
||||
uint32 Radeon_TheatreReadFIFO( accelerator_info *ai, uint16 addr );
|
||||
void Radeon_TheatreWriteFIFO( accelerator_info *ai, uint16 addr, uint32 value );
|
||||
|
||||
// internal_tv_out.c
|
||||
void Radeon_InternalTVOutProgramRegisters( accelerator_info *ai, impactv_regs *values );
|
||||
void Radeon_InternalTVOutReadRegisters( accelerator_info *ai, impactv_regs *values );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -30,13 +30,9 @@ void Radeon_ReadSettings( virtual_card *vc )
|
||||
BPath path;
|
||||
int32 tmp;
|
||||
|
||||
// per default we enable combine mode;
|
||||
// if actual mode isn't combine mode, we fall back to clone mode
|
||||
vc->wanted_multi_mode = mm_combine;
|
||||
vc->swap_displays = false;
|
||||
|
||||
// per default, show overlay on first port
|
||||
//vc->whished_overlay_port = 0;
|
||||
vc->use_laptop_panel = false;
|
||||
vc->tv_standard = ts_ntsc;
|
||||
|
||||
// this is problematic during boot: if there is multi-user support,
|
||||
// you don't have a user when app_server gets launched;
|
||||
@@ -56,27 +52,12 @@ void Radeon_ReadSettings( virtual_card *vc )
|
||||
if( settings.Unflatten( &file ) != B_OK )
|
||||
return;
|
||||
|
||||
if( settings.FindBool( "SwapDisplays", &vc->swap_displays ) != B_OK )
|
||||
vc->swap_displays = false;
|
||||
|
||||
if( settings.FindInt32( "MultiMonitorMode", &tmp ) != B_OK )
|
||||
tmp = mm_combine;
|
||||
|
||||
switch( tmp ) {
|
||||
case mm_none:
|
||||
case mm_mirror:
|
||||
case mm_combine:
|
||||
case mm_clone:
|
||||
vc->wanted_multi_mode = (multi_mode_e) tmp;
|
||||
break;
|
||||
default:
|
||||
vc->wanted_multi_mode = mm_combine;
|
||||
}
|
||||
settings.FindBool( "SwapDisplays", &vc->swap_displays );
|
||||
settings.FindBool( "UseLaptopPanel", &vc->use_laptop_panel );
|
||||
settings.FindInt32( "TVStandard", &tmp );
|
||||
|
||||
if( settings.FindInt32( "OverlayPort", &tmp ) != B_OK )
|
||||
tmp = 0;
|
||||
|
||||
//vc->whished_overlay_port = tmp;
|
||||
if( tmp >= 0 && tmp <= ts_max )
|
||||
vc->tv_standard = (tv_standard_e)tmp;
|
||||
}
|
||||
|
||||
void Radeon_WriteSettings( virtual_card *vc )
|
||||
@@ -100,10 +81,9 @@ void Radeon_WriteSettings( virtual_card *vc )
|
||||
BMessage settings;
|
||||
|
||||
settings.AddBool( "SwapDisplays", vc->swap_displays );
|
||||
tmp = vc->wanted_multi_mode;
|
||||
settings.AddInt32( "MultiMonitorMode", tmp );
|
||||
/*tmp = vc->whished_overlay_port;
|
||||
settings.AddInt32( "OverlayPort", tmp );*/
|
||||
settings.AddBool( "UseLaptopPanel", vc->use_laptop_panel );
|
||||
tmp = vc->tv_standard;
|
||||
settings.AddInt32( "TVStandard", tmp );
|
||||
|
||||
settings.Flatten( &file );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
Copyright (c) 2002/03, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
|
||||
Programming of TV-out via Rage Theatre
|
||||
*/
|
||||
|
||||
|
||||
#include "radeon_interface.h"
|
||||
#include "radeon_accelerant.h"
|
||||
|
||||
#include "theatre_regs.h"
|
||||
#include "tv_out_regs.h"
|
||||
#include "set_mode.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
// mapping of offset in impactv_regs to register address
|
||||
typedef struct register_mapping {
|
||||
uint16 address; // register address
|
||||
uint16 offset; // offset in impactv_regs
|
||||
} register_mapping;
|
||||
|
||||
|
||||
// Rage Theatre TV-Out:
|
||||
|
||||
// registers to write at first
|
||||
static const register_mapping theatre_reg_mapping_start[] = {
|
||||
{ THEATRE_VIP_MASTER_CNTL, offsetof( impactv_regs, tv_master_cntl ) },
|
||||
{ THEATRE_VIP_TVO_DATA_DELAY_A, offsetof( impactv_regs, tv_data_delay_a ) },
|
||||
{ THEATRE_VIP_TVO_DATA_DELAY_B, offsetof( impactv_regs, tv_data_delay_b ) },
|
||||
|
||||
{ THEATRE_VIP_CLKOUT_CNTL, offsetof( impactv_regs, tv_clkout_cntl ) },
|
||||
{ THEATRE_VIP_PLL_CNTL0, offsetof( impactv_regs, tv_pll_cntl1 ) },
|
||||
|
||||
{ THEATRE_VIP_HRESTART, offsetof( impactv_regs, tv_hrestart ) },
|
||||
{ THEATRE_VIP_VRESTART, offsetof( impactv_regs, tv_vrestart ) },
|
||||
{ THEATRE_VIP_FRESTART, offsetof( impactv_regs, tv_frestart ) },
|
||||
{ THEATRE_VIP_FTOTAL, offsetof( impactv_regs, tv_ftotal ) },
|
||||
|
||||
{ THEATRE_VIP_CLOCK_SEL_CNTL, offsetof( impactv_regs, tv_clock_sel_cntl ) },
|
||||
{ THEATRE_VIP_TV_PLL_CNTL, offsetof( impactv_regs, tv_tv_pll_cntl ) },
|
||||
{ THEATRE_VIP_CRT_PLL_CNTL, offsetof( impactv_regs, tv_crt_pll_cntl ) },
|
||||
|
||||
{ THEATRE_VIP_HTOTAL, offsetof( impactv_regs, tv_htotal ) },
|
||||
{ THEATRE_VIP_HSIZE, offsetof( impactv_regs, tv_hsize ) },
|
||||
{ THEATRE_VIP_HDISP, offsetof( impactv_regs, tv_hdisp ) },
|
||||
{ THEATRE_VIP_HSTART, offsetof( impactv_regs, tv_hstart ) },
|
||||
{ THEATRE_VIP_VTOTAL, offsetof( impactv_regs, tv_vtotal ) },
|
||||
{ THEATRE_VIP_VDISP, offsetof( impactv_regs, tv_vdisp ) },
|
||||
|
||||
{ THEATRE_VIP_TIMING_CNTL, offsetof( impactv_regs, tv_timing_cntl ) },
|
||||
|
||||
{ THEATRE_VIP_VSCALER_CNTL, offsetof( impactv_regs, tv_vscaler_cntl1 ) },
|
||||
{ THEATRE_VIP_VSCALER_CNTL2, offsetof( impactv_regs, tv_vscaler_cntl2 ) },
|
||||
{ THEATRE_VIP_SYNC_SIZE, offsetof( impactv_regs, tv_sync_size ) },
|
||||
{ THEATRE_VIP_Y_SAW_TOOTH_CNTL, offsetof( impactv_regs, tv_y_saw_tooth_cntl ) },
|
||||
{ THEATRE_VIP_Y_RISE_CNTL, offsetof( impactv_regs, tv_y_rise_cntl ) },
|
||||
{ THEATRE_VIP_Y_FALL_CNTL, offsetof( impactv_regs, tv_y_fall_cntl ) },
|
||||
|
||||
{ THEATRE_VIP_MODULATOR_CNTL1, offsetof( impactv_regs, tv_modulator_cntl1 ) },
|
||||
{ THEATRE_VIP_MODULATOR_CNTL2, offsetof( impactv_regs, tv_modulator_cntl2 ) },
|
||||
|
||||
{ THEATRE_VIP_RGB_CNTL, offsetof( impactv_regs, tv_rgb_cntl ) },
|
||||
|
||||
{ THEATRE_VIP_UV_ADR, offsetof( impactv_regs, tv_uv_adr ) },
|
||||
|
||||
{ THEATRE_VIP_PRE_DAC_MUX_CNTL, offsetof( impactv_regs, tv_pre_dac_mux_cntl ) },
|
||||
{ THEATRE_VIP_FRAME_LOCK_CNTL, offsetof( impactv_regs, tv_frame_lock_cntl ) },
|
||||
{ THEATRE_VIP_CRC_CNTL, offsetof( impactv_regs, tv_crc_cntl ) },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
// registers to write when things settled down
|
||||
static const register_mapping theatre_reg_mapping_finish[] = {
|
||||
{ THEATRE_VIP_UPSAMP_COEFF0_0, offsetof( impactv_regs, tv_upsample_filter_coeff[0*3+0] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF0_1, offsetof( impactv_regs, tv_upsample_filter_coeff[0*3+1] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF0_2, offsetof( impactv_regs, tv_upsample_filter_coeff[0*3+2] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF1_0, offsetof( impactv_regs, tv_upsample_filter_coeff[1*3+0] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF1_1, offsetof( impactv_regs, tv_upsample_filter_coeff[1*3+1] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF1_2, offsetof( impactv_regs, tv_upsample_filter_coeff[1*3+2] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF2_0, offsetof( impactv_regs, tv_upsample_filter_coeff[2*3+0] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF2_1, offsetof( impactv_regs, tv_upsample_filter_coeff[2*3+1] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF2_2, offsetof( impactv_regs, tv_upsample_filter_coeff[2*3+2] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF3_0, offsetof( impactv_regs, tv_upsample_filter_coeff[3*3+0] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF3_1, offsetof( impactv_regs, tv_upsample_filter_coeff[3*3+1] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF3_2, offsetof( impactv_regs, tv_upsample_filter_coeff[3*3+2] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF4_0, offsetof( impactv_regs, tv_upsample_filter_coeff[4*3+0] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF4_1, offsetof( impactv_regs, tv_upsample_filter_coeff[4*3+1] ) },
|
||||
{ THEATRE_VIP_UPSAMP_COEFF4_2, offsetof( impactv_regs, tv_upsample_filter_coeff[4*3+2] ) },
|
||||
|
||||
{ THEATRE_VIP_GAIN_LIMIT_SETTINGS, offsetof( impactv_regs, tv_gain_limit_settings ) },
|
||||
{ THEATRE_VIP_LINEAR_GAIN_SETTINGS, offsetof( impactv_regs, tv_linear_gain_settings ) },
|
||||
{ THEATRE_VIP_UPSAMP_AND_GAIN_CNTL, offsetof( impactv_regs, tv_upsamp_and_gain_cntl ) },
|
||||
|
||||
{ THEATRE_VIP_TV_DAC_CNTL, offsetof( impactv_regs, tv_dac_cntl ) },
|
||||
{ THEATRE_VIP_MASTER_CNTL, offsetof( impactv_regs, tv_master_cntl ) },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
// write list of Rage Theatre registers
|
||||
static void writeTheatreRegList(
|
||||
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
|
||||
{
|
||||
for( ; mapping->address != 0 || mapping->offset != 0; ++mapping ) {
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );
|
||||
|
||||
/* SHOW_FLOW( 2, "%x=%x", mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read timing FIFO
|
||||
uint32 Radeon_TheatreReadFIFO(
|
||||
accelerator_info *ai, uint16 addr )
|
||||
{
|
||||
bigtime_t start_time;
|
||||
uint32 res = ~0;
|
||||
|
||||
//SHOW_FLOW( 2, "addr=%d", addr );
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel,
|
||||
THEATRE_VIP_HOST_RD_WT_CNTL, addr | RADEON_TV_HOST_RD_WT_CNTL_RD );
|
||||
|
||||
start_time = system_time();
|
||||
|
||||
do {
|
||||
uint32 status;
|
||||
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_HOST_RD_WT_CNTL, &status );
|
||||
|
||||
if( (status & RADEON_TV_HOST_RD_WT_CNTL_RD_ACK) != 0 )
|
||||
break;
|
||||
} while( system_time() - start_time < 2000000 );
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_HOST_RD_WT_CNTL, 0);
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_HOST_READ_DATA, &res );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// write to timing FIFO
|
||||
void Radeon_TheatreWriteFIFO(
|
||||
accelerator_info *ai, uint16 addr, uint32 value )
|
||||
{
|
||||
bigtime_t start_time;
|
||||
|
||||
//readFIFO( ai, addr, internal_encoder );
|
||||
|
||||
//SHOW_FLOW( 2, "addr=%d, value=%x %x", addr, value >> 14, value & 0x3fff );
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_HOST_WRITE_DATA, value);
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel,
|
||||
THEATRE_VIP_HOST_RD_WT_CNTL, addr | RADEON_TV_HOST_RD_WT_CNTL_WT);
|
||||
|
||||
start_time = system_time();
|
||||
|
||||
do {
|
||||
uint32 status;
|
||||
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_HOST_RD_WT_CNTL, &status );
|
||||
|
||||
if( (status & RADEON_TV_HOST_RD_WT_CNTL_WT_ACK) != 0 )
|
||||
break;
|
||||
} while( system_time() - start_time < 2000000 );
|
||||
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_HOST_RD_WT_CNTL, 0 );
|
||||
}
|
||||
|
||||
|
||||
// program TV-Out registers
|
||||
void Radeon_TheatreProgramTVRegisters(
|
||||
accelerator_info *ai, impactv_regs *values )
|
||||
{
|
||||
uint32 orig_tv_master_cntl = values->tv_master_cntl;
|
||||
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
// disable TV-out when registers are setup
|
||||
// it gets enabled again when things have settled down
|
||||
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;
|
||||
|
||||
writeTheatreRegList( ai, values, theatre_reg_mapping_start );
|
||||
|
||||
// un-reset FIFO to access timing table
|
||||
Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_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_TheatreWriteFIFO, values, false );
|
||||
Radeon_ImpacTVwriteVertTimingTable( ai, Radeon_TheatreWriteFIFO, values );
|
||||
|
||||
snooze( 50000 );
|
||||
|
||||
values->tv_master_cntl = orig_tv_master_cntl;
|
||||
writeTheatreRegList( ai, values, theatre_reg_mapping_finish );
|
||||
}
|
||||
|
||||
|
||||
// read list of Rage Theatre registers
|
||||
static void readTheatreRegList(
|
||||
accelerator_info *ai, impactv_regs *values, const register_mapping *mapping )
|
||||
{
|
||||
for( ; mapping->address != 0 || mapping->offset != 0; ++mapping ) {
|
||||
Radeon_VIPRead( ai, ai->si->theatre_channel, mapping->address,
|
||||
(uint32 *)((char *)(values) + mapping->offset) );
|
||||
|
||||
/*SHOW_FLOW( 2, "%x=%x", mapping->address,
|
||||
*(uint32 *)((char *)(values) + mapping->offset) );*/
|
||||
}
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
|
||||
|
||||
// read TV-Out registers
|
||||
void Radeon_TheatreReadTVRegisters(
|
||||
accelerator_info *ai, impactv_regs *values )
|
||||
{
|
||||
readTheatreRegList( ai, values, theatre_reg_mapping_start );
|
||||
readTheatreRegList( ai, values, theatre_reg_mapping_finish );
|
||||
|
||||
//snooze( 1000000 );
|
||||
}
|
||||
|
||||
|
||||
// detect TV-Out encoder
|
||||
void Radeon_DetectTVOut(
|
||||
accelerator_info *ai )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
|
||||
SHOW_FLOW0( 0, "" );
|
||||
|
||||
switch( si->tv_chip ) {
|
||||
case tc_external_rt1: {
|
||||
// for external encoder, we need the VIP channel
|
||||
int channel = Radeon_FindVIPDevice( ai, THEATRE_ID );
|
||||
|
||||
if( channel < 0 ) {
|
||||
SHOW_ERROR0( 2, "This card needs a Rage Theatre for TV-Out, but there is none." );
|
||||
si->tv_chip = tc_none;
|
||||
} else {
|
||||
SHOW_INFO( 2, "Rage Theatre found on VIP channel %d", channel );
|
||||
si->theatre_channel = channel;
|
||||
}
|
||||
break; }
|
||||
default:
|
||||
// for internal encoder, we don't have to look farther - it must be there
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "radeon_accelerant.h"
|
||||
|
||||
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
|
||||
|
||||
// these are the official VESA modes
|
||||
// interestingly, they completely differ from the modes generated via GMTF
|
||||
const display_timing vesa_mode_list[] = {
|
||||
{ 31500, 640, 672, 736, 832, 350, 382, 385, 445, B_POSITIVE_HSYNC}, /* Vesa_Monitor_@85Hz_(640X350X8.Z1) */
|
||||
|
||||
{ 31500, 640, 672, 736, 832, 400, 401, 404, 445, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@85Hz_(640X400X8.Z1) */
|
||||
|
||||
{ 35500, 720, 756, 828, 936, 400, 401, 404, 446, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@85Hz_(720X400X8.Z1) */
|
||||
|
||||
{ 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
|
||||
{ 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, /* Vesa_Monitor_@72Hz_(640X480X8.Z1) */
|
||||
{ 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
|
||||
{ 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
|
||||
|
||||
{ 36000, 800, 824, 896, 1024, 600, 601, 603, 625, T_POSITIVE_SYNC}, /* Vesa_Monitor_800X600X56Hz - this is different to Be's mode! */
|
||||
{ 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */
|
||||
{ 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, /* Vesa_Monitor_@72Hz_(800X600X8.Z1) */
|
||||
{ 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */
|
||||
{ 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */
|
||||
|
||||
{ 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */
|
||||
{ 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, /* Vesa_Monitor_@70_(1024X768X8.Z1) */
|
||||
{ 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */
|
||||
{ 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */
|
||||
|
||||
{ 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) - is this really Vesa? */
|
||||
{ 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */
|
||||
{ 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) - is this really Vesa?*/
|
||||
|
||||
{ 108000, 1280, 1376, 1488, 1800, 960, 961, 964, 1000, T_POSITIVE_SYNC}, /* Vesa_Monitor_@60Hz_(1280X960X8.Z1) - not in Be's list */
|
||||
{ 148500, 1280, 1344, 1504, 1728, 960, 961, 964, 1011, T_POSITIVE_SYNC}, /* Vesa_Monitor_@85Hz_(1280X960X8.Z1) - not in Be's list */
|
||||
|
||||
{ 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */
|
||||
{ 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */
|
||||
{ 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */
|
||||
|
||||
{ 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */
|
||||
{ 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */
|
||||
{ 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */
|
||||
{ 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */
|
||||
{ 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) - is this really Vesa? */
|
||||
{ 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */
|
||||
|
||||
// the following modes weren't defined in Be's code (they are strange anyway - perhaps HDTV?)
|
||||
{ 204800, 1792, 1920, 2120, 2448, 1344, 1345, 1348, 1394, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@60Hz_(1792X1344X8.Z1) */
|
||||
{ 261000, 1792, 1888, 2104, 2456, 1344, 1345, 1348, 1417, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@75Hz_(1792X1344X8.Z1) */
|
||||
|
||||
{ 218300, 1856, 1952, 2176, 2528, 1392, 1393, 1396, 1439, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@60Hz_(1856X1392X8.Z1) */
|
||||
{ 288000, 1856, 1984, 2208, 2560, 1392, 1393, 1396, 1500, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@75Hz_(1856X1392X8.Z1) */
|
||||
|
||||
{ 234000, 1920, 2048, 2256, 2600, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@60Hz_(1920X1440X8.Z1) */
|
||||
{ 297000, 1920, 2064, 2288, 2640, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC}, /* Vesa_Monitor_@75Hz_(1920X1440X8.Z1) */
|
||||
};
|
||||
|
||||
|
||||
// number of VESA modes
|
||||
const size_t vesa_mode_list_count = sizeof( vesa_mode_list ) / sizeof( vesa_mode_list[0] );
|
||||
@@ -217,7 +217,7 @@ void Radeon_ResetEngine( device_info *di )
|
||||
// cannot be read out)
|
||||
// -> this is a very bad idea, especially when it comes to laptops
|
||||
// I comment it out for now, let's hope noone takes notice
|
||||
if( di->num_heads > 1 ) {
|
||||
if( di->num_crtc > 1 ) {
|
||||
Radeon_OUTPLLP( regs, di->asic, RADEON_SCLK_CNTL,
|
||||
RADEON_CP_MAX_DYN_STOP_LAT |
|
||||
RADEON_SCLK_FORCEON_MASK,
|
||||
@@ -342,6 +342,16 @@ static void loadMicroEngineRAMData( device_info *di )
|
||||
|
||||
Radeon_WaitForIdle( di, false, false );
|
||||
|
||||
/*
|
||||
// HACK start
|
||||
Radeon_ResetEngine( di );
|
||||
OUTREG( di->regs, 0x30, 0x5133a3a0 ); // bus_cntl
|
||||
OUTREGP( di->regs, 0xf0c, 0xff00, ~0xff ); // latency
|
||||
Radeon_WaitForIdle( di, false, false );
|
||||
Radeon_ResetEngine( di );
|
||||
// HACK end
|
||||
*/
|
||||
|
||||
OUTREG( di->regs, RADEON_CP_ME_RAM_ADDR, 0 );
|
||||
|
||||
for ( i = 0 ; i < 256 ; i++ ) {
|
||||
@@ -401,7 +411,7 @@ static status_t initRingBuffer( device_info *di, int aring_size )
|
||||
OUTREG( regs, RADEON_CP_RB_WPTR, 0 );
|
||||
//*cp->ring.head = 0;
|
||||
cp->ring.tail = 0;
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -457,7 +467,7 @@ static status_t initCPFeedback( device_info *di )
|
||||
*(uint32 *)MEM2CPU( cp->feedback.mem_type, cp->feedback.head_mem_offset) = 0;
|
||||
memset( MEM2CPU( cp->feedback.mem_type, cp->feedback.scratch_mem_offset), 0, 0x40 );
|
||||
//*cp->ring.head = 0;
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ static status_t Radeon_PrepareDMA(
|
||||
|
||||
cur_size = min( contig_size, RADEON_DMA_DESC_MAX_SIZE );
|
||||
|
||||
if( ++num_desc > di->dma_desc_max_num ) {
|
||||
if( ++num_desc > (int)di->dma_desc_max_num ) {
|
||||
SHOW_ERROR( 2, "Overflow of DMA descriptors, %ld bytes left", size );
|
||||
res = B_BAD_VALUE;
|
||||
goto err;
|
||||
|
||||
@@ -167,7 +167,7 @@ static status_t initGATT( GART_info *gart )
|
||||
|
||||
// temporary area where we fill in the memory map (deleted below)
|
||||
map_area = create_area("pci_gart_map_area", (void **)&map, B_ANY_ADDRESS, map_area_size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
dprintf("pci_gart_map_area: %d\n", map_area);
|
||||
dprintf("pci_gart_map_area: %ld\n", map_area);
|
||||
|
||||
get_memory_map( gart->buffer.ptr, gart->buffer.size, map, map_count );
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#define PCI_agp_status 4 /* Status register */
|
||||
#define PCI_agp_status_rq_mask 0xff000000 /* Maximum number of requests - 1 */
|
||||
#define PCI_agp_status_rq_shift 24
|
||||
#define PCI_agp_status_sba 0x0200 /* Sideband addressing supported */
|
||||
#define PCI_agp_status_64bit 0x0020 /* 64-bit addressing supported */
|
||||
#define PCI_agp_status_fw 0x0010 /* FW transfers supported */
|
||||
@@ -46,6 +47,7 @@
|
||||
|
||||
#define PCI_agp_command 8 /* Control register */
|
||||
#define PCI_agp_command_rq_mask 0xff000000 /* Master: Maximum number of requests */
|
||||
#define PCI_agp_command_rq_shift 24
|
||||
#define PCI_agp_command_sba 0x0200 /* Sideband addressing enabled */
|
||||
#define PCI_agp_command_agp 0x0100 /* Allow processing of AGP transactions */
|
||||
#define PCI_agp_command_64bit 0x0020 /* Allow processing of 64-bit addresses */
|
||||
@@ -64,7 +66,8 @@
|
||||
// show AGP capabilities
|
||||
static void show_agp_status( uint32 status )
|
||||
{
|
||||
SHOW_FLOW( 3, "Status (%08lx): %s%s%s%s%s%s", status,
|
||||
SHOW_FLOW( 3, "Status (%08lx): Max Queue Depth=%ld %s%s%s%s%s%s", status,
|
||||
(status & PCI_agp_status_rq_mask) >> PCI_agp_status_rq_shift,
|
||||
(status & PCI_agp_status_sba) != 0 ? "Sideband addressing " : "",
|
||||
(status & PCI_agp_status_64bit) != 0 ? "64-bit " : "",
|
||||
(status & PCI_agp_status_fw) != 0 ? "FastWrite " : "",
|
||||
@@ -77,7 +80,8 @@ static void show_agp_status( uint32 status )
|
||||
// show AGP settings
|
||||
static void show_agp_command( uint32 command )
|
||||
{
|
||||
SHOW_FLOW( 3, "Command (%08lx): %s%s%s%s%s%s%s", command,
|
||||
SHOW_FLOW( 3, "Command (%08lx): Queue Depth=%ld %s%s%s%s%s%s%s", command,
|
||||
(command & PCI_agp_command_rq_mask) >> PCI_agp_command_rq_shift,
|
||||
(command & PCI_agp_command_sba) != 0 ? "Sideband addressing " : "",
|
||||
(command & PCI_agp_command_agp) != 0 ? "AGP-Enabled " : "AGP-Disabled ",
|
||||
(command & PCI_agp_command_64bit) != 0 ? "64-bit " : "",
|
||||
@@ -142,11 +146,12 @@ int find_capability( pci_info *pcii, uint8 capability )
|
||||
|
||||
|
||||
// fix invalid AGP settings
|
||||
void Radeon_Fix_AGP()
|
||||
void Radeon_Fix_AGP(void)
|
||||
{
|
||||
long pci_index;
|
||||
pci_info pci_data, *pcii;
|
||||
|
||||
// start with all features enabled, queue depth bits must be 0
|
||||
uint32 common_caps =
|
||||
PCI_agp_status_sba | PCI_agp_status_64bit | PCI_agp_status_fw |
|
||||
PCI_agp_status_rate4 | PCI_agp_status_rate2 | PCI_agp_status_rate1;
|
||||
@@ -164,9 +169,9 @@ void Radeon_Fix_AGP()
|
||||
{
|
||||
int offset;
|
||||
|
||||
SHOW_FLOW( 3, "Checking bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
|
||||
/*SHOW_FLOW( 3, "Checking bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
|
||||
pcii->bus, pcii->device, pcii->function,
|
||||
pcii->vendor_id, pcii->device_id );
|
||||
pcii->vendor_id, pcii->device_id );*/
|
||||
|
||||
offset = find_capability( pcii, PCI_cap_id_agp );
|
||||
|
||||
@@ -186,6 +191,20 @@ void Radeon_Fix_AGP()
|
||||
read_queue_depth = min( read_queue_depth, agp_status & PCI_agp_status_rq_mask );
|
||||
}
|
||||
}
|
||||
|
||||
// explicitely enable AGP - it's not part of status register
|
||||
common_caps |= PCI_agp_command_agp;
|
||||
|
||||
// choose fastest transmission speed and disable lower ones
|
||||
if( (common_caps & PCI_agp_status_rate4) != 0 )
|
||||
common_caps &= ~(PCI_agp_status_rate2 | PCI_agp_status_rate1);
|
||||
else if( (common_caps & PCI_agp_status_rate2) != 0 )
|
||||
common_caps &= ~PCI_agp_status_rate1;
|
||||
else if( (common_caps & PCI_agp_status_rate1) == 0 )
|
||||
// no speed found - disable AGP
|
||||
common_caps &= ~PCI_agp_command_agp;
|
||||
|
||||
common_caps |= read_queue_depth;
|
||||
|
||||
SHOW_FLOW0( 3, "Combined:" );
|
||||
show_agp_command( common_caps );
|
||||
@@ -204,7 +223,7 @@ void Radeon_Fix_AGP()
|
||||
pcii->bus, pcii->device, pcii->function,
|
||||
pcii->vendor_id, pcii->device_id );
|
||||
|
||||
set_pci( offset + PCI_agp_command, 4, common_caps | read_queue_depth );
|
||||
set_pci( offset + PCI_agp_command, 4, common_caps );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,7 +466,7 @@ static void Radeon_GetFPData( device_info *di )
|
||||
}
|
||||
|
||||
// detect amount of graphics memory
|
||||
void Radeon_DetectRAM( device_info *di )
|
||||
static void Radeon_DetectRAM( device_info *di )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
|
||||
|
||||
@@ -66,10 +66,13 @@
|
||||
#define DEVICE_ID_RADEON_Lf 0x4c66
|
||||
#define DEVICE_ID_RADEON_Lg 0x4c67
|
||||
|
||||
// M9+
|
||||
#define DEVICE_ID_RADEON_5c61 0x5c61
|
||||
|
||||
// RV280
|
||||
#define DEVICE_ID_RADEON_Ya_ 0x5960
|
||||
#define DEVICE_ID_RADEON_Ya 0x5961
|
||||
#define DEVICE_ID_RADEON_Yd 0x5964
|
||||
#define DEVICE_ID_RADEON_Zprea 0x5960
|
||||
#define DEVICE_ID_RADEON_Za 0x5961
|
||||
#define DEVICE_ID_RADEON_Zd 0x5964
|
||||
|
||||
// r300
|
||||
#define DEVICE_ID_RADEON_ND 0x4e44
|
||||
@@ -86,8 +89,11 @@
|
||||
// rv350
|
||||
#define DEVICE_ID_RADEON_AP 0x4150
|
||||
#define DEVICE_ID_RADEON_AQ 0x4151
|
||||
#define DEVICE_ID_RADEON_NO 0x4e50
|
||||
#define DEVICE_ID_RADEON_NS 0x4e54
|
||||
|
||||
// m10
|
||||
#define DEVICE_ID_RADEON_NP 0x4e50
|
||||
// Mobility Fire GL T2 - any idea about the chip?
|
||||
#define DEVICE_ID_RADEON_NT 0x4e54
|
||||
|
||||
// rv360
|
||||
#define DEVICE_ID_RADEON_AR 0x4152
|
||||
@@ -97,9 +103,6 @@
|
||||
#define DEVICE_ID_RADEON_NH 0x4e48
|
||||
#define DEVICE_ID_RADEON_NI 0x4e49
|
||||
|
||||
// Mobility Fire GL T2 - any idea about the chip?
|
||||
#define DEVICE_ID_RADEON_NT 0x4e54
|
||||
|
||||
// r360
|
||||
#define DEVICE_ID_RADEON_NJ 0x4e4a
|
||||
|
||||
@@ -131,8 +134,6 @@ RadeonDevice radeon_device_list[] = {
|
||||
// mobility version of original Radeon (based on VE), now called M6
|
||||
{ DEVICE_ID_RADEON_LY, rt_m6, "Radeon Mobility" },
|
||||
{ DEVICE_ID_RADEON_LZ, rt_m6, "Radeon Mobility M6 LZ" },
|
||||
// not sure about that: ROM signature is "RADEON" which means r100
|
||||
{ DEVICE_ID_RADEON_NT, rt_m6, "Radeon Mobility FireGL T2" },
|
||||
|
||||
// rs100 (integrated Radeon, seems to be a Radeon VE)
|
||||
{ DEVICE_ID_IGP320M, rt_rs100, "IGP320M" },
|
||||
@@ -159,7 +160,7 @@ RadeonDevice radeon_device_list[] = {
|
||||
{ DEVICE_ID_RADEON_Qk, rt_r200, "Radeon 8500 Qk" },
|
||||
{ DEVICE_ID_RADEON_BB, rt_r200, "ALL-IN-Wonder Radeon 8500 DV" },
|
||||
|
||||
// RV250 (cut-down R200)
|
||||
// RV250 (cut-down R200 with integrated TV-Out)
|
||||
{ DEVICE_ID_RADEON_Id, rt_rv250, "Radeon 9000 Id" },
|
||||
{ DEVICE_ID_RADEON_Ie, rt_rv250, "Radeon 9000 Ie" },
|
||||
{ DEVICE_ID_RADEON_If, rt_rv250, "Radeon 9000" },
|
||||
@@ -171,11 +172,14 @@ RadeonDevice radeon_device_list[] = {
|
||||
{ DEVICE_ID_RADEON_Lf, rt_m9, "Radeon Mobility 9000 Lf" },
|
||||
{ DEVICE_ID_RADEON_Lg, rt_m9, "Radeon Mobility 9000 Lg" },
|
||||
|
||||
// RV280
|
||||
// the naming scheme can't properly handle this id
|
||||
{ DEVICE_ID_RADEON_Ya_, rt_rv280, "Radeon 9200" },
|
||||
{ DEVICE_ID_RADEON_Ya, rt_rv280, "Radeon 9200" },
|
||||
{ DEVICE_ID_RADEON_Yd, rt_rv280, "Radeon 9200 SE" },
|
||||
// RV280 (rv250 with higher frequency)
|
||||
// this entry violates naming scheme, so it's probably wrong
|
||||
{ DEVICE_ID_RADEON_Zprea, rt_rv280, "Radeon 9200" },
|
||||
{ DEVICE_ID_RADEON_Za, rt_rv280, "Radeon 9200" },
|
||||
{ DEVICE_ID_RADEON_Zd, rt_rv280, "Radeon 9200 SE" },
|
||||
|
||||
// M9+ (based on rv280)
|
||||
{ DEVICE_ID_RADEON_5c61,rt_m9plus, "Radeon Mobility 9200" },
|
||||
|
||||
// R300
|
||||
{ DEVICE_ID_RADEON_ND, rt_r300, "Radeon 9700 ND" },
|
||||
@@ -187,13 +191,16 @@ RadeonDevice radeon_device_list[] = {
|
||||
{ DEVICE_ID_RADEON_AE, rt_r300, "Radeon 9700 AE" },
|
||||
{ DEVICE_ID_RADEON_AF, rt_r300, "Radeon 9700 AF" },
|
||||
{ DEVICE_ID_RADEON_AG, rt_r300, "Radeon 9700 AG" },
|
||||
|
||||
|
||||
// RV350
|
||||
{ DEVICE_ID_RADEON_AP, rt_rv350, "Radeon 9600 AP" },
|
||||
{ DEVICE_ID_RADEON_AQ, rt_rv350, "Radeon 9600 AQ" },
|
||||
{ DEVICE_ID_RADEON_NO, rt_rv350, "Radeon 9600 Pro" },
|
||||
{ DEVICE_ID_RADEON_NS, rt_rv350, "Mobility FireGL T2" },
|
||||
|
||||
// M10 (based on rv350)
|
||||
{ DEVICE_ID_RADEON_NP, rt_m10, "Radeon Mobility 9600 NP" },
|
||||
// not sure about that: ROM signature is "RADEON" which means r100
|
||||
{ DEVICE_ID_RADEON_NT, rt_m10, "Radeon Mobility FireGL T2" },
|
||||
|
||||
// RV360 (probably minor revision of rv350)
|
||||
{ DEVICE_ID_RADEON_AR, rt_rv360, "Radeon 9600 AR" },
|
||||
|
||||
@@ -205,10 +212,10 @@ RadeonDevice radeon_device_list[] = {
|
||||
// R360 (probably minor revision of r350)
|
||||
{ DEVICE_ID_RADEON_NJ, rt_r360, "Radeon 9800 XT" },
|
||||
|
||||
// rs100 (aka IGP)
|
||||
// rs100 (aka IGP 320)
|
||||
{ DEVICE_ID_IGP320M, rt_rs100, "Radeon IGP 320M" },
|
||||
|
||||
// rs200 (aka IGP)
|
||||
// rs200 (aka IGP 340)
|
||||
{ DEVICE_ID_RADEON_C7, rt_rs200, "IGP330M/340M/350M (U2) 4337" },
|
||||
{ DEVICE_ID_RADEON_A7, rt_rs200, "IGP 340" },
|
||||
|
||||
@@ -278,26 +285,29 @@ static struct {
|
||||
bool has_crtc2; // has second CRTC
|
||||
bool is_mobility; // mobility chip
|
||||
bool has_vip; // has VIP/I2C
|
||||
bool new_pll; // reference divider of PPLL moved to other location
|
||||
bool is_igp; // integrated graphics
|
||||
} asic_properties[] =
|
||||
{
|
||||
{ "r100", tc_external_rt1, false, false, true, false }, // only original Radeons have one crtc only
|
||||
{ "ve", tc_internal_rt1, true, false, true, false },
|
||||
{ "m6", tc_internal_rt1, true, true, false, false },
|
||||
{ "rs100", tc_internal_rt1, true, true, false, true },
|
||||
{ "rv200", tc_internal_rt2, true, false, true, false },
|
||||
{ "m7", tc_internal_rt1, true, true, false, false },
|
||||
{ "rs200", tc_internal_rt1, true, true, false, true },
|
||||
{ "r200", tc_external_rt1, true, false, true, false }, // r200 has external TV-Out encoder
|
||||
{ "rv250", tc_internal_rt2, true, false, true, false },
|
||||
{ "rv280", tc_internal_rt2, true, false, true, false },
|
||||
{ "m9", tc_internal_rt2, true, true, true, false },
|
||||
{ "r300", tc_internal_rt2, true, false, true, false },
|
||||
{ "r300_4p",tc_internal_rt2, true, false, true, false },
|
||||
{ "rv350", tc_internal_rt2, true, false, true, false },
|
||||
{ "rv360", tc_internal_rt2, true, false, true, false },
|
||||
{ "r350", tc_internal_rt2, true, false, true, false },
|
||||
{ "r360", tc_internal_rt2, true, false, true, false }
|
||||
{ "r100", tc_external_rt1, false, false, true, false, false }, // only original Radeons have one crtc only
|
||||
{ "ve", tc_internal_rt1, true, false, true, false, false },
|
||||
{ "m6", tc_internal_rt1, true, true, false, false, false },
|
||||
{ "rs100", tc_internal_rt1, true, true, false, false, true },
|
||||
{ "rv200", tc_internal_rt2, true, false, true, false, false },
|
||||
{ "m7", tc_internal_rt1, true, true, false, false, false },
|
||||
{ "rs200", tc_internal_rt1, true, true, false, false, true },
|
||||
{ "r200", tc_external_rt1, true, false, true, false, false }, // r200 has external TV-Out encoder
|
||||
{ "rv250", tc_internal_rt2, true, false, true, false, false },
|
||||
{ "m9", tc_internal_rt2, true, true, false, false, false },
|
||||
{ "rv280", tc_internal_rt2, true, false, true, false, false },
|
||||
{ "m9plus", tc_internal_rt2, true, true, false, false, false },
|
||||
{ "r300", tc_internal_rt2, true, false, true, true, false },
|
||||
{ "r300_4p",tc_internal_rt2, true, false, true, true, false },
|
||||
{ "rv350", tc_internal_rt2, true, false, true, true, false },
|
||||
{ "m10", tc_internal_rt2, true, true, false, true, false },
|
||||
{ "rv360", tc_internal_rt2, true, false, true, true, false },
|
||||
{ "r350", tc_internal_rt2, true, false, true, true, false },
|
||||
{ "r360", tc_internal_rt2, true, false, true, true, false }
|
||||
};
|
||||
|
||||
|
||||
@@ -318,11 +328,12 @@ static bool probeDevice( device_info *di )
|
||||
if (device->device_id != di->pcii.device_id )
|
||||
continue;
|
||||
|
||||
di->num_heads = asic_properties[device->asic].has_crtc2 ? 2 : 1;
|
||||
di->num_crtc = asic_properties[device->asic].has_crtc2 ? 2 : 1;
|
||||
di->tv_chip = asic_properties[device->asic].tv_chip;
|
||||
di->asic = device->asic;
|
||||
di->is_mobility = asic_properties[device->asic].is_mobility;
|
||||
di->has_vip = asic_properties[device->asic].has_vip;
|
||||
di->new_pll = asic_properties[device->asic].new_pll;
|
||||
di->is_igp = asic_properties[device->asic].is_igp;
|
||||
|
||||
if( Radeon_MapBIOS( &di->pcii, &di->rom ) != B_OK )
|
||||
|
||||
@@ -289,8 +289,8 @@ static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len )
|
||||
if( vr->magic != RADEON_PRIVATE_DATA_MAGIC )
|
||||
break;
|
||||
|
||||
result = Radeon_VIPRead( di, vr->channel, vr->address, &vr->data ) ?
|
||||
B_OK : B_ERROR;
|
||||
result = Radeon_VIPRead( di, vr->channel, vr->address, &vr->data,
|
||||
vr->lock ) ? B_OK : B_ERROR;
|
||||
} break;
|
||||
|
||||
case RADEON_VIPWRITE: {
|
||||
@@ -299,8 +299,8 @@ static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len )
|
||||
if( vw->magic != RADEON_PRIVATE_DATA_MAGIC )
|
||||
break;
|
||||
|
||||
result = Radeon_VIPWrite( di, vw->channel, vw->address, vw->data ) ?
|
||||
B_OK : B_ERROR;
|
||||
result = Radeon_VIPWrite( di, vw->channel, vw->address, vw->data,
|
||||
vw->lock ) ? B_OK : B_ERROR;
|
||||
} break;
|
||||
|
||||
case RADEON_FINDVIPDEVICE: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon kernel driver
|
||||
@@ -213,9 +213,9 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
memset( di->si, 0, sizeof( *di->si ));
|
||||
|
||||
si = di->si;
|
||||
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
#ifdef LOG_INCLUDE_STARTUP
|
||||
#ifdef LOG_INCLUDE_STARTUP
|
||||
si->log = log_init( 1000000 );
|
||||
#endif
|
||||
#endif
|
||||
@@ -228,6 +228,7 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
si->asic = di->asic;
|
||||
si->is_mobility = di->is_mobility;
|
||||
si->tv_chip = di->tv_chip;
|
||||
si->new_pll = di->new_pll;
|
||||
|
||||
// detecting theatre channel in kernel would lead to code duplication,
|
||||
// so we let the first accelerant take care of it
|
||||
@@ -235,11 +236,11 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
|
||||
/* si->ports[0].disp_type = di->disp_type[0];
|
||||
si->ports[1].disp_type = di->disp_type[1];*/
|
||||
si->heads[0].is_crtc2 = false;
|
||||
si->heads[0].flatpanel_port = 0;
|
||||
si->heads[1].is_crtc2 = true;
|
||||
si->heads[1].flatpanel_port = 1;
|
||||
si->num_heads = di->num_heads;
|
||||
si->crtc[0].crtc_idx = 0;
|
||||
si->crtc[0].flatpanel_port = 0;
|
||||
si->crtc[1].crtc_idx = 1;
|
||||
si->crtc[1].flatpanel_port = 1;
|
||||
si->num_crtc = di->num_crtc;
|
||||
|
||||
si->flatpanels[0] = di->fp_info;
|
||||
si->pll = di->pll;
|
||||
@@ -264,10 +265,11 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
}
|
||||
|
||||
// currently, we assign fixed ports to this virtual card
|
||||
di->vc->num_heads = si->num_heads;
|
||||
di->vc->heads[0].physical_head = 0;
|
||||
di->vc->heads[1].physical_head = 1;
|
||||
|
||||
di->vc->assigned_crtc[0] = true;
|
||||
di->vc->assigned_crtc[1] = si->num_crtc > 1;
|
||||
di->vc->controlled_displays =
|
||||
dd_tv_crt | dd_crt | dd_lvds | dd_dvi | dd_ctv | dd_stv;
|
||||
|
||||
di->vc->fb_mem_handle = 0;
|
||||
di->vc->cursor.mem_handle = 0;
|
||||
|
||||
@@ -324,6 +326,10 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
|
||||
// no AGP support
|
||||
di->memmgr[mt_AGP] = NULL;
|
||||
|
||||
// fix AGP settings for IGP chipset
|
||||
if( di->asic == rt_rs100 || di->asic == rt_rs200 )
|
||||
Radeon_Fix_AGP();
|
||||
|
||||
// time to init Command Processor
|
||||
result = Radeon_InitCP( di );
|
||||
@@ -334,8 +340,6 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
if( result != B_OK )
|
||||
goto err0;
|
||||
|
||||
//Radeon_Fix_AGP();
|
||||
|
||||
// mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset );
|
||||
/* dma_offset = 15 * 1024 * 1024;
|
||||
|
||||
@@ -391,7 +395,7 @@ void Radeon_LastClose( device_info *di )
|
||||
Radeon_UnmapDevice(di);
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
#ifdef LOG_INCLUDE_STARTUP
|
||||
#ifdef LOG_INCLUDE_STARTUP
|
||||
log_exit( di->si->log );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon kernel driver
|
||||
@@ -32,27 +32,27 @@ Radeon_ThreadInterruptWork( vuint8 *regs, device_info *di, uint32 int_status )
|
||||
uint32 handled = B_HANDLED_INTERRUPT;
|
||||
|
||||
if( (int_status & RADEON_CRTC_VBLANK_STAT) != 0 &&
|
||||
si->heads[0].vblank >= 0 )
|
||||
si->crtc[0].vblank >= 0 )
|
||||
{
|
||||
int32 blocked;
|
||||
|
||||
++di->vbi_count[0];
|
||||
|
||||
if( (get_sem_count( si->heads[0].vblank, &blocked ) == B_OK) && (blocked < 0) ) {
|
||||
release_sem_etc( si->heads[0].vblank, -blocked, B_DO_NOT_RESCHEDULE );
|
||||
if( (get_sem_count( si->crtc[0].vblank, &blocked ) == B_OK) && (blocked < 0) ) {
|
||||
release_sem_etc( si->crtc[0].vblank, -blocked, B_DO_NOT_RESCHEDULE );
|
||||
handled = B_INVOKE_SCHEDULER;
|
||||
}
|
||||
}
|
||||
|
||||
if( (int_status & RADEON_CRTC2_VBLANK_STAT) != 0 &&
|
||||
si->heads[1].vblank >= 0 )
|
||||
si->crtc[1].vblank >= 0 )
|
||||
{
|
||||
int32 blocked;
|
||||
|
||||
++di->vbi_count[1];
|
||||
|
||||
if( (get_sem_count( si->heads[1].vblank, &blocked ) == B_OK) && (blocked < 0) ) {
|
||||
release_sem_etc( si->heads[1].vblank, -blocked, B_DO_NOT_RESCHEDULE );
|
||||
if( (get_sem_count( si->crtc[1].vblank, &blocked ) == B_OK) && (blocked < 0) ) {
|
||||
release_sem_etc( si->crtc[1].vblank, -blocked, B_DO_NOT_RESCHEDULE );
|
||||
handled = B_INVOKE_SCHEDULER;
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ static int32 timer_interrupt_func( timer *te )
|
||||
/* do the things we do when we notice a vertical retrace */
|
||||
result = Radeon_ThreadInterruptWork( regs, di,
|
||||
RADEON_CRTC_VBLANK_STAT |
|
||||
(di->num_heads > 1 ? RADEON_CRTC2_VBLANK_STAT : 0 ));
|
||||
(di->num_crtc > 1 ? RADEON_CRTC2_VBLANK_STAT : 0 ));
|
||||
}
|
||||
|
||||
/* pick the "other" timer */
|
||||
@@ -198,21 +198,21 @@ Radeon_SetupIRQ( device_info *di, char *buffer )
|
||||
sprintf( buffer, "%04X_%04X_%02X%02X%02X VBI 1",
|
||||
di->pcii.vendor_id, di->pcii.device_id,
|
||||
di->pcii.bus, di->pcii.device, di->pcii.function );
|
||||
si->heads[0].vblank = create_sem( 0, buffer );
|
||||
if( si->heads[0].vblank < 0 ) {
|
||||
result = si->heads[0].vblank;
|
||||
si->crtc[0].vblank = create_sem( 0, buffer );
|
||||
if( si->crtc[0].vblank < 0 ) {
|
||||
result = si->crtc[0].vblank;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
si->heads[1].vblank = 0;
|
||||
si->crtc[1].vblank = 0;
|
||||
|
||||
if( di->num_heads > 1 ) {
|
||||
if( di->num_crtc > 1 ) {
|
||||
sprintf( buffer, "%04X_%04X_%02X%02X%02X VBI 2",
|
||||
di->pcii.vendor_id, di->pcii.device_id,
|
||||
di->pcii.bus, di->pcii.device, di->pcii.function );
|
||||
si->heads[1].vblank = create_sem( 0, buffer );
|
||||
if( si->heads[1].vblank < 0 ) {
|
||||
result = si->heads[1].vblank;
|
||||
si->crtc[1].vblank = create_sem( 0, buffer );
|
||||
if( si->crtc[1].vblank < 0 ) {
|
||||
result = si->crtc[1].vblank;
|
||||
goto err2;
|
||||
}
|
||||
}
|
||||
@@ -241,9 +241,9 @@ Radeon_SetupIRQ( device_info *di, char *buffer )
|
||||
/* this is required because apps can't aquire kernel semaphores */
|
||||
thid = find_thread(NULL);
|
||||
get_thread_info(thid, &thinfo);
|
||||
set_sem_owner(si->heads[0].vblank, thinfo.team);
|
||||
if( di->num_heads > 1 )
|
||||
set_sem_owner(si->heads[1].vblank, thinfo.team);
|
||||
set_sem_owner(si->crtc[0].vblank, thinfo.team);
|
||||
if( di->num_crtc > 1 )
|
||||
set_sem_owner(si->crtc[1].vblank, thinfo.team);
|
||||
//set_sem_owner(di->cap_sem, thinfo.team);
|
||||
|
||||
/* disable all interrupts */
|
||||
@@ -283,10 +283,10 @@ err5:
|
||||
err4:
|
||||
delete_sem( di->cap_sem );
|
||||
err3:
|
||||
if( di->num_heads > 1 )
|
||||
delete_sem( si->heads[1].vblank );
|
||||
if( di->num_crtc > 1 )
|
||||
delete_sem( si->crtc[1].vblank );
|
||||
err2:
|
||||
delete_sem( si->heads[0].vblank );
|
||||
delete_sem( si->crtc[0].vblank );
|
||||
err1:
|
||||
return result;
|
||||
}
|
||||
@@ -313,13 +313,13 @@ Radeon_CleanupIRQ( device_info *di )
|
||||
remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, Radeon_Interrupt, di);
|
||||
}
|
||||
|
||||
delete_sem( si->heads[0].vblank );
|
||||
delete_sem( si->crtc[0].vblank );
|
||||
|
||||
if( di->num_heads > 1 )
|
||||
delete_sem( si->heads[1].vblank );
|
||||
if( di->num_crtc > 1 )
|
||||
delete_sem( si->crtc[1].vblank );
|
||||
|
||||
delete_sem( di->cap_sem );
|
||||
delete_sem( di->dma_sem );
|
||||
|
||||
di->cap_sem = si->heads[1].vblank = si->heads[0].vblank = 0;
|
||||
di->cap_sem = si->crtc[1].vblank = si->crtc[0].vblank = 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
Copyright (c) 2002-2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon kernel driver
|
||||
@@ -106,11 +106,12 @@ typedef struct device_info {
|
||||
vuint8 *regs;
|
||||
|
||||
radeon_type asic;
|
||||
uint8 num_heads;
|
||||
uint8 num_crtc;
|
||||
tv_chip_type tv_chip;
|
||||
bool is_mobility;
|
||||
bool is_igp;
|
||||
bool new_pll;
|
||||
bool has_vip;
|
||||
bool is_igp;
|
||||
//display_type_e disp_type[2];
|
||||
fp_info fp_info;
|
||||
|
||||
@@ -202,7 +203,7 @@ void Radeon_CleanupIRQ( device_info *di );
|
||||
|
||||
|
||||
// agp.c
|
||||
void Radeon_Fix_AGP();
|
||||
void Radeon_Fix_AGP(void);
|
||||
|
||||
|
||||
// mem_controller.c
|
||||
@@ -218,8 +219,8 @@ void Radeon_UninitCP( device_info *di );
|
||||
|
||||
|
||||
// vip.c
|
||||
bool Radeon_VIPRead( device_info *di, uint channel, uint address, uint32 *data );
|
||||
bool Radeon_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data );
|
||||
bool Radeon_VIPRead( device_info *di, uint channel, uint address, uint32 *data, bool lock );
|
||||
bool Radeon_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data, bool lock );
|
||||
int Radeon_FindVIPDevice( device_info *di, uint32 device_id );
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2002-04, Thomas Kurschel
|
||||
Copyright (c) 2002-05, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon accelerant
|
||||
@@ -25,7 +25,8 @@ static bool Radeon_VIPWaitForIdle( device_info *di );
|
||||
|
||||
// read data from VIP
|
||||
// CP lock must be hold
|
||||
static bool do_VIPRead( device_info *di, uint channel, uint address, uint32 *data )
|
||||
static bool do_VIPRead(
|
||||
device_info *di, uint channel, uint address, uint32 *data )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
|
||||
@@ -74,21 +75,28 @@ static bool do_VIPRead( device_info *di, uint channel, uint address, uint32 *dat
|
||||
}
|
||||
|
||||
// public function: read data from VIP
|
||||
bool Radeon_VIPRead( device_info *di, uint channel, uint address, uint32 *data )
|
||||
bool Radeon_VIPRead(
|
||||
device_info *di, uint channel, uint address, uint32 *data, bool lock )
|
||||
{
|
||||
bool res;
|
||||
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
if( lock )
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
res = do_VIPRead( di, channel, address, data );
|
||||
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
if( lock )
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
|
||||
//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// write data to VIP
|
||||
// not must be hold
|
||||
static bool do_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data )
|
||||
// CP must be hold
|
||||
static bool do_VIPWrite(
|
||||
device_info *di, uint8 channel, uint address, uint32 data )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
bool res;
|
||||
@@ -110,25 +118,33 @@ static bool do_VIPWrite( device_info *di, uint8 channel, uint address, uint32 da
|
||||
}
|
||||
|
||||
// public function: write data to VIP
|
||||
bool Radeon_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data )
|
||||
bool Radeon_VIPWrite(
|
||||
device_info *di, uint8 channel, uint address, uint32 data, bool lock )
|
||||
{
|
||||
bool res;
|
||||
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
|
||||
|
||||
if( lock )
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
res = do_VIPWrite( di, channel, address, data );
|
||||
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
if( lock )
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// reset VIP
|
||||
static void VIPReset( device_info *di )
|
||||
static void VIPReset(
|
||||
device_info *di, bool lock )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
if( lock )
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
Radeon_WaitForFifo( di, 5 );
|
||||
OUTREG( regs, RADEON_VIPH_CONTROL,
|
||||
@@ -151,44 +167,15 @@ static void VIPReset( device_info *di )
|
||||
(1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH3_CHUNK_SHIFT));
|
||||
OUTREGP( regs, RADEON_TEST_DEBUG_CNTL, 0, ~RADEON_TEST_DEBUG_CNTL_OUT_EN );
|
||||
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
}
|
||||
|
||||
|
||||
// find VIP channel of a device
|
||||
// return: >= 0 channel of device
|
||||
// < 0 no device found
|
||||
int Radeon_FindVIPDevice( device_info *di, uint32 device_id )
|
||||
{
|
||||
uint channel;
|
||||
uint32 cur_device_id;
|
||||
|
||||
// if card has no VIP port, let hardware detection fail;
|
||||
// in this case, noone will bother us again
|
||||
if( !di->has_vip )
|
||||
return -1;
|
||||
|
||||
VIPReset( di );
|
||||
|
||||
// there are up to 4 devices, connected to one of 4 channels
|
||||
for( channel = 0; channel < 4; ++channel ) {
|
||||
// read device id
|
||||
if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id ))
|
||||
continue;
|
||||
|
||||
// compare device id directly
|
||||
if( cur_device_id == device_id )
|
||||
return channel;
|
||||
}
|
||||
|
||||
// couldn't find device
|
||||
return -1;
|
||||
if( lock )
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
}
|
||||
|
||||
|
||||
// check whether VIP host is idle
|
||||
// lock must be hold
|
||||
static status_t Radeon_VIPIdle( device_info *di )
|
||||
static status_t Radeon_VIPIdle(
|
||||
device_info *di )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
uint32 timeout;
|
||||
@@ -218,7 +205,8 @@ static status_t Radeon_VIPIdle( device_info *di )
|
||||
|
||||
// wait until VIP host is idle
|
||||
// lock must be hold
|
||||
static bool Radeon_VIPWaitForIdle( device_info *di )
|
||||
static bool Radeon_VIPWaitForIdle(
|
||||
device_info *di )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -239,3 +227,42 @@ static bool Radeon_VIPWaitForIdle( device_info *di )
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// find VIP channel of a device
|
||||
// return: >= 0 channel of device
|
||||
// < 0 no device found
|
||||
int Radeon_FindVIPDevice(
|
||||
device_info *di, uint32 device_id )
|
||||
{
|
||||
uint channel;
|
||||
uint32 cur_device_id;
|
||||
|
||||
// if card has no VIP port, let hardware detection fail;
|
||||
// in this case, noone will bother us again
|
||||
if( !di->has_vip )
|
||||
return -1;
|
||||
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
VIPReset( di, false );
|
||||
|
||||
// there are up to 4 devices, connected to one of 4 channels
|
||||
for( channel = 0; channel < 4; ++channel ) {
|
||||
// read device id
|
||||
if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false ))
|
||||
continue;
|
||||
|
||||
// compare device id directly
|
||||
if( cur_device_id == device_id ) {
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
|
||||
// couldn't find device
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user