Implemented more accurate screen update timing calculation using the RAMDAC
video clock. Removed dependencies to the cpu / memory clock.
This commit is contained in:
parent
ed163dd846
commit
fc5c22d78f
@ -204,10 +204,8 @@ void bx_voodoo_c::init(void)
|
||||
if (model == VOODOO_2) {
|
||||
init_pci_conf(0x121a, 0x0002, 0x02, 0x038000, 0x00);
|
||||
BX_VOODOO_THIS pci_conf[0x10] = 0x08;
|
||||
BX_VOODOO_THIS s.clock = STD_VOODOO_2_CLOCK;
|
||||
} else {
|
||||
init_pci_conf(0x121a, 0x0001, 0x02, 0x000000, 0x00);
|
||||
BX_VOODOO_THIS s.clock = STD_VOODOO_1_CLOCK;
|
||||
}
|
||||
BX_VOODOO_THIS pci_conf[0x3d] = BX_PCI_INTA;
|
||||
BX_VOODOO_THIS pci_base_address[0] = 0;
|
||||
@ -442,34 +440,47 @@ void bx_voodoo_c::mode_change_timer_handler(void *this_ptr)
|
||||
bx_virt_timer.deactivate_timer(BX_VOODOO_THIS s.update_timer_id);
|
||||
DEV_vga_set_override(0, NULL);
|
||||
BX_VOODOO_THIS s.vdraw.override_on = 0;
|
||||
BX_VOODOO_THIS s.vdraw.width = 0;
|
||||
BX_VOODOO_THIS s.vdraw.height = 0;
|
||||
}
|
||||
|
||||
if ((BX_VOODOO_THIS s.vdraw.clock_enabled && BX_VOODOO_THIS s.vdraw.output_on) && !BX_VOODOO_THIS s.vdraw.override_on) {
|
||||
if ((v->reg[hSync].u == 0) || (v->reg[vSync].u == 0))
|
||||
return;
|
||||
// switching on
|
||||
int htotal = ((v->reg[hSync].u >> 16) & 0x3ff) + 1 + (v->reg[hSync].u & 0xff) + 1;
|
||||
int vtotal = ((v->reg[vSync].u >> 16) & 0xfff) + (v->reg[vSync].u & 0xfff);
|
||||
int vsync = ((v->reg[vSync].u >> 16) & 0xfff);
|
||||
double hfreq = BX_VOODOO_THIS s.clock / htotal; // Voodoo1 50 MHz / Voodoo2 90 MHz
|
||||
if (((v->reg[fbiInit1].u >> 20) & 3) == 1) { // VCLK div 2
|
||||
hfreq /= 2;
|
||||
}
|
||||
unsigned vfreq = (unsigned)(hfreq / vtotal);
|
||||
BX_VOODOO_THIS s.vdraw.vtotal_usec = 1000000 / vfreq;
|
||||
BX_VOODOO_THIS s.vdraw.vsync_usec = vsync * (unsigned)(1000000 / hfreq);
|
||||
if (!BX_VOODOO_THIS update_timing())
|
||||
return;
|
||||
DEV_vga_set_override(1, BX_VOODOO_THIS_PTR);
|
||||
BX_VOODOO_THIS s.vdraw.override_on = 1;
|
||||
|
||||
BX_VOODOO_THIS s.vdraw.width = v->fbi.width+1;
|
||||
BX_VOODOO_THIS s.vdraw.height = v->fbi.height;
|
||||
BX_INFO(("Voodoo output %dx%d@%uHz", v->fbi.width, v->fbi.height, vfreq));
|
||||
bx_gui->dimension_update(v->fbi.width+1, v->fbi.height, 0, 0, 16);
|
||||
update_timer_handler(NULL);
|
||||
bx_virt_timer.activate_timer(BX_VOODOO_THIS s.update_timer_id, (Bit32u)BX_VOODOO_THIS s.vdraw.vtotal_usec, 1);
|
||||
}
|
||||
}
|
||||
|
||||
bx_bool bx_voodoo_c::update_timing(void)
|
||||
{
|
||||
if (!BX_VOODOO_THIS s.vdraw.clock_enabled || !BX_VOODOO_THIS s.vdraw.output_on)
|
||||
return 0;
|
||||
if ((v->reg[hSync].u == 0) || (v->reg[vSync].u == 0))
|
||||
return 0;
|
||||
int htotal = ((v->reg[hSync].u >> 16) & 0x3ff) + 1 + (v->reg[hSync].u & 0xff) + 1;
|
||||
int vtotal = ((v->reg[vSync].u >> 16) & 0xfff) + (v->reg[vSync].u & 0xfff);
|
||||
int vsync = ((v->reg[vSync].u >> 16) & 0xfff);
|
||||
double hfreq = (double)(v->dac.clk0_freq * 1000) / htotal;
|
||||
if (((v->reg[fbiInit1].u >> 20) & 3) == 1) { // VCLK div 2
|
||||
hfreq /= 2;
|
||||
}
|
||||
double vfreq = hfreq / (double)vtotal;
|
||||
BX_VOODOO_THIS s.vdraw.vtotal_usec = (unsigned)(1000000.0 / vfreq);
|
||||
BX_VOODOO_THIS s.vdraw.vsync_usec = vsync * (unsigned)(1000000.0 / hfreq);
|
||||
if ((BX_VOODOO_THIS s.vdraw.width != v->fbi.width) ||
|
||||
(BX_VOODOO_THIS s.vdraw.height != v->fbi.height)) {
|
||||
BX_VOODOO_THIS s.vdraw.width = v->fbi.width;
|
||||
BX_VOODOO_THIS s.vdraw.height = v->fbi.height;
|
||||
bx_gui->dimension_update(v->fbi.width, v->fbi.height, 0, 0, 16);
|
||||
update_timer_handler(NULL);
|
||||
}
|
||||
BX_INFO(("Voodoo output %dx%d@%uHz", v->fbi.width, v->fbi.height, (unsigned)vfreq));
|
||||
bx_virt_timer.activate_timer(BX_VOODOO_THIS s.update_timer_id, (Bit32u)BX_VOODOO_THIS s.vdraw.vtotal_usec, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bx_voodoo_c::refresh_display(void *this_ptr, bx_bool redraw)
|
||||
{
|
||||
if (redraw) {
|
||||
|
@ -36,7 +36,6 @@ typedef struct {
|
||||
bx_bool override_on;
|
||||
bx_bool screen_update_pending;
|
||||
} vdraw;
|
||||
double clock;
|
||||
int mode_change_timer_id;
|
||||
int update_timer_id;
|
||||
Bit8u devfunc;
|
||||
@ -62,6 +61,7 @@ public:
|
||||
static bx_bool get_retrace(void);
|
||||
static void output_enable(bx_bool enabled);
|
||||
static void update_screen_start(void);
|
||||
static bx_bool update_timing(void);
|
||||
|
||||
private:
|
||||
bx_voodoo_t s;
|
||||
|
@ -1635,6 +1635,11 @@ struct _dac_state
|
||||
{
|
||||
Bit8u reg[8]; /* 8 registers */
|
||||
Bit8u read_result; /* pending read result */
|
||||
Bit8u data_size;
|
||||
Bit8u clk0_m;
|
||||
Bit8u clk0_n;
|
||||
Bit8u clk0_p;
|
||||
Bit32u clk0_freq;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1397,6 +1397,37 @@ void recompute_video_memory(voodoo_state *v)
|
||||
void dacdata_w(dac_state *d, Bit8u regnum, Bit8u data)
|
||||
{
|
||||
d->reg[regnum] = data;
|
||||
|
||||
/* switch off the DAC register requested */
|
||||
switch (regnum) {
|
||||
case 4: // PLLWMA
|
||||
case 7: // PLLRMA
|
||||
if (data == 0x0e) {
|
||||
d->data_size = 1;
|
||||
} else {
|
||||
d->data_size = 2;
|
||||
}
|
||||
break;
|
||||
case 5: // PLLDATA
|
||||
switch (d->reg[4]) { // PLLWMA
|
||||
case 0x00:
|
||||
if (d->data_size == 2) {
|
||||
d->clk0_m = data;
|
||||
} else if (d->data_size == 1) {
|
||||
d->clk0_n = data & 0x1f;
|
||||
d->clk0_p = data >> 5;
|
||||
}
|
||||
break;
|
||||
case 0x0e:
|
||||
if ((d->data_size == 1) && ((data & 0x21) == 0x21)) {
|
||||
d->clk0_freq = (Bit32u)((14318.0 * (d->clk0_m + 2)) / ((1 << d->clk0_p) * (d->clk0_n + 2)));
|
||||
Voodoo_update_timing();
|
||||
}
|
||||
break;
|
||||
}
|
||||
d->data_size--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1405,16 +1436,22 @@ void dacdata_r(dac_state *d, Bit8u regnum)
|
||||
Bit8u result = 0xff;
|
||||
|
||||
/* switch off the DAC register requested */
|
||||
switch (regnum)
|
||||
{
|
||||
case 5:
|
||||
/* this is just to make startup happy */
|
||||
switch (d->reg[7])
|
||||
{
|
||||
switch (regnum) {
|
||||
case 5: // PLLDATA
|
||||
switch (d->reg[7]) { // PLLRMA
|
||||
case 0x00:
|
||||
if (d->data_size == 2) {
|
||||
result = d->clk0_m;
|
||||
} else if (d->data_size == 1) {
|
||||
result = d->clk0_n | (d->clk0_p << 5);
|
||||
}
|
||||
break;
|
||||
/* this is just to make startup happy */
|
||||
case 0x01: result = 0x55; break;
|
||||
case 0x07: result = 0x71; break;
|
||||
case 0x0b: result = 0x79; break;
|
||||
}
|
||||
d->data_size--;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1846,7 +1883,7 @@ void register_w(Bit32u offset, Bit32u data)
|
||||
#endif
|
||||
|
||||
/* configure the new framebuffer info */
|
||||
v->fbi.width = hvis;
|
||||
v->fbi.width = hvis + 1;
|
||||
v->fbi.height = vvis;
|
||||
v->fbi.xoffs = hbp;
|
||||
v->fbi.yoffs = vbp;
|
||||
@ -2840,6 +2877,9 @@ void voodoo_init(Bit8u _type)
|
||||
v->chipmask = 0x01 | 0x02 | 0x04 | 0x08;
|
||||
memset(v->dac.reg, 0, sizeof(v->dac.reg));
|
||||
v->dac.read_result = 0;
|
||||
v->dac.clk0_m = 0x37;
|
||||
v->dac.clk0_n = 0x02;
|
||||
v->dac.clk0_p = 0x03;
|
||||
|
||||
/* create a table of precomputed 1/n and log2(n) values */
|
||||
/* n ranges from 1.0000 to 2.0000 */
|
||||
|
@ -150,5 +150,6 @@ READ32_DEVICE_HANDLER( banshee_rom_r );
|
||||
#define Voodoo_UpdateScreenStart() theVoodooDevice->update_screen_start()
|
||||
#define Voodoo_Output_Enable(x) theVoodooDevice->output_enable(x)
|
||||
#define Voodoo_get_retrace() theVoodooDevice->get_retrace()
|
||||
#define Voodoo_update_timing() theVoodooDevice->update_timing()
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user