From 2ee0f0e4707330ce3279696d73c22dec88d7a462 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 20 Oct 2025 20:32:41 +0200 Subject: [PATCH] RAMDAC/Clock fixes to the S3 and ET4000AX cards 1. The S3 968-based Diamond Stealth 64 Video VRAM, using a 14mhz reference clock, now has its RGB528 fixed Pixel PLL reference divider set to its default value (0x07) per manual and reference clock. Fixes wrong refresh rates on said cards and others. 2. Added the ICS2494-324 clock generator to the ET4000AX. Fixes wrong refresh rates on this one too. --- src/video/ramdac/vid_ramdac_ibm_rgb528.c | 186 ++++++++++++++--------- src/video/vid_et4000.c | 25 ++- src/video/vid_s3.c | 52 +++++-- 3 files changed, 160 insertions(+), 103 deletions(-) diff --git a/src/video/ramdac/vid_ramdac_ibm_rgb528.c b/src/video/ramdac/vid_ramdac_ibm_rgb528.c index bded466d1..09cabeb0a 100644 --- a/src/video/ramdac/vid_ramdac_ibm_rgb528.c +++ b/src/video/ramdac/vid_ramdac_ibm_rgb528.c @@ -60,6 +60,7 @@ typedef union ibm_rgb528_pixel32_t { } ibm_rgb528_pixel32_t; typedef struct ibm_rgb528_ramdac_t { + int type; PALETTE extpal; uint32_t extpallook[256]; uint8_t indexed_data[2048]; @@ -627,19 +628,21 @@ ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *s case 0x02a: case 0x02c: case 0x02e: - if (ramdac->indexed_data[0x0002] & 0x01) { - switch (ramdac->indexed_data[0x0010] & 0x07) { - case 0x00: - case 0x02: - ramdac->pix_f[ramdac->index - 0x0020] = val; - break; - case 0x01: - case 0x03: - ramdac->pix_m[(ramdac->index - 0x0020) >> 1] = val; - break; - default: - break; - } + switch (ramdac->indexed_data[0x0010] & 0x03) { + case 0x00: + ramdac->pix_f[(ramdac->index - 0x0020)] = val; + break; + case 0x01: + ramdac->pix_m[(ramdac->index - 0x0020) >> 1] = val; + break; + case 0x02: + ramdac->pix_f[(ramdac->index - 0x0020)] = val; + break; + case 0x03: + ramdac->pix_m[(ramdac->index - 0x0020) >> 1] = val; + break; + default: + break; } break; case 0x021: @@ -650,19 +653,21 @@ ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *s case 0x02b: case 0x02d: case 0x02f: - if (ramdac->indexed_data[0x0002] & 0x01) { - switch (ramdac->indexed_data[0x010] & 0x07) { - case 0x00: - case 0x02: - ramdac->pix_f[ramdac->index - 0x0020] = val; - break; - case 0x01: - case 0x03: - ramdac->pix_n[(ramdac->index - 0x0020) >> 1] = val; - break; - default: - break; - } + switch (ramdac->indexed_data[0x0010] & 0x03) { + case 0x00: + ramdac->pix_f[(ramdac->index - 0x0020)] = val; + break; + case 0x01: + ramdac->pix_n[(ramdac->index - 0x0020) >> 1] = val; + break; + case 0x02: + ramdac->pix_f[(ramdac->index - 0x0020)] = val; + break; + case 0x03: + ramdac->pix_n[(ramdac->index - 0x0020) >> 1] = val; + break; + default: + break; } break; @@ -868,7 +873,52 @@ ibm_rgb528_recalctimings(void *priv, svga_t *svga) { const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; - svga->interlace = ramdac->indexed_data[0x071] & 0x20; + svga->interlace = !!(ramdac->indexed_data[0x071] & 0x20); + //pclog("MiscClockControl idx002=%02x, SystemClockControl idx008=%02x, Misc2 idx071=%02x, Misc1 idx070=%02x, Misc4 idx073=%02x.\n", + // ramdac->indexed_data[0x002], ramdac->indexed_data[0x008], ramdac->indexed_data[0x071], ramdac->indexed_data[0x070], ramdac->indexed_data[0x073]); + + if (ramdac->indexed_data[0x071] & 0x01) { + if ((ramdac->indexed_data[0x070] & 0x03) == 0x03) { + switch ((ramdac->indexed_data[0x002] & 0x0e) >> 1) { + case 0x00: + default: + svga->clock_multiplier = 0; + break; + case 0x01: + svga->clock_multiplier = 1; + break; + case 0x02: + svga->clock_multiplier = 2; + break; + case 0x03: + svga->clock_multiplier = 3; + break; + case 0x04: + svga->clock_multiplier = 4; + break; + } + } else if ((ramdac->indexed_data[0x070] & 0x03) == 0x01) { + switch ((ramdac->indexed_data[0x002] & 0x0e) >> 1) { + case 0x00: + default: + svga->clock_multiplier = 1; + svga->clock *= 2.0; + break; + case 0x01: + svga->clock_multiplier = 1; + break; + case 0x02: + svga->clock_multiplier = 2; + break; + case 0x03: + svga->clock_multiplier = 3; + break; + case 0x04: + svga->clock_multiplier = 4; + break; + } + } + } if (svga->scrblank || !svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { @@ -904,49 +954,47 @@ ibm_rgb528_recalctimings(void *priv, svga_t *svga) float ibm_rgb528_getclock(int clock, void *priv) { - const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; - int pll_vco_div_cnt; - int pll_df; - int pll_ref_div_cnt; - int ddot_divs[8] = { 1, 2, 4, 8, 16, 1, 1, 1 }; - int ddot_div = ddot_divs[(ramdac->indexed_data[0x0002] >> 1) & 0x07]; - float f_pll; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; + int pll_vco_div_cnt; + int pll_df; + int pll_ref_div_cnt; + int ddot_divs[8] = { 1, 2, 4, 8, 16, 1, 1, 1 }; + int ddot_div = ddot_divs[(ramdac->indexed_data[0x0002] >> 1) & 0x07]; + float f_pll; - clock &= 0x03; + if (clock == 0) + return 25175000.0f; + if (clock == 1) + return 28322000.0f; - if (ramdac->indexed_data[0x0002] & 0x01) { - switch (ramdac->indexed_data[0x0010] & 0x07) { - case 0x00: - default: - pll_vco_div_cnt = ramdac->pix_f[clock] & 0x3f; - pll_df = 8 >> (ramdac->pix_f[clock] >> 6); - pll_ref_div_cnt = ramdac->pix_f_ref_div & 0x1f; - break; - case 0x01: - pll_vco_div_cnt = ramdac->pix_m[clock] & 0x3f; - pll_df = 8 >> (ramdac->pix_m[clock] >> 6); - pll_ref_div_cnt = ramdac->pix_n[clock] & 0x1f; - break; - case 0x02: - pll_vco_div_cnt = ramdac->pix_f[ramdac->indexed_data[0x0011] & 0x0f] & 0x3f; - pll_df = 8 >> (ramdac->pix_f[ramdac->indexed_data[0x0011] & 0x0f] >> 6); - pll_ref_div_cnt = ramdac->pix_f_ref_div & 0x1f; - break; - case 0x03: - pll_vco_div_cnt = ramdac->pix_m[ramdac->indexed_data[0x0011] & 0x07] & 0x3f; - pll_df = 8 >> (ramdac->pix_m[ramdac->indexed_data[0x0011] & 0x07] >> 6); - pll_ref_div_cnt = ramdac->pix_n[ramdac->indexed_data[0x0011] & 0x07] & 0x1f; - break; - } - } else { - pll_vco_div_cnt = ramdac->indexed_data[0x0016] & 0x3f; - pll_df = 8 >> (ramdac->indexed_data[0x0016] >> 6); - pll_ref_div_cnt = ramdac->indexed_data[0x0015] & 0x1f; + switch (ramdac->indexed_data[0x0010] & 0x03) { + case 0x00: + default: + pll_vco_div_cnt = ramdac->pix_f[clock & 0x03] & 0x3f; + pll_df = 8 >> (ramdac->pix_f[clock & 0x03] >> 6); + pll_ref_div_cnt = ramdac->pix_f_ref_div & 0x1f; + break; + case 0x01: + pll_vco_div_cnt = ramdac->pix_m[clock & 0x03] & 0x3f; + pll_df = 8 >> (ramdac->pix_m[clock & 0x03] >> 6); + pll_ref_div_cnt = ramdac->pix_n[clock & 0x03] & 0x1f; + break; + case 0x02: + pll_vco_div_cnt = ramdac->pix_f[ramdac->indexed_data[0x0011] & 0x0f] & 0x3f; + pll_df = 8 >> (ramdac->pix_f[ramdac->indexed_data[0x0011] & 0x0f] >> 6); + pll_ref_div_cnt = ramdac->pix_f_ref_div & 0x1f; + break; + case 0x03: + pll_vco_div_cnt = ramdac->pix_m[ramdac->indexed_data[0x0011] & 0x0f] & 0x3f; + pll_df = 8 >> (ramdac->pix_m[ramdac->indexed_data[0x0011] & 0x0f] >> 6); + pll_ref_div_cnt = ramdac->pix_n[ramdac->indexed_data[0x0011] & 0x0f] & 0x1f; + break; } - f_pll = ramdac->ref_clock * (float) (pll_vco_div_cnt + 65) / (float) (pll_ref_div_cnt * pll_df); f_pll /= (float) ddot_div; + //pclog("PIXCTRL1=%02x, clock=%d, m=%d, df=%d, n=%d, ctrl2=%02x, miscclock=%02x, sysclock=%02x, f_pll=%f.\n", + // ramdac->indexed_data[0x010], clock, pll_vco_div_cnt, pll_df, pll_ref_div_cnt, ramdac->indexed_data[0x011], ramdac->indexed_data[0x002], ramdac->indexed_data[0x008], f_pll); return f_pll; } @@ -1073,19 +1121,11 @@ ibm_rgb528_ramdac_init(UNUSED(const device_t *info)) ramdac->smlc_part = 0x0100; ramdac->ref_clock = 14318184.0f; + ramdac->pix_f_ref_div = 0x07; /*Per datasheet regarding the reference clock value.*/ ramdac->indexed_data[0x0008] = 0x0001; - ramdac->indexed_data[0x0014] = 0x0005; ramdac->indexed_data[0x0015] = 0x0008; ramdac->indexed_data[0x0016] = 0x0041; - ramdac->indexed_data[0x0020] = 0x0005; - ramdac->indexed_data[0x0021] = 0x000e; - - ramdac->pix_f_ref_div = 0x0005; - ramdac->pix_f[0] = 0x0005; - ramdac->pix_f[1] = 0x000e; - ramdac->pix_m[0] = 0x0005; - ramdac->pix_n[0] = 0x000e; return ramdac; } diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 1a8a767e2..80f27833a 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -639,6 +639,7 @@ static void et4000_recalctimings(svga_t *svga) { const et4000_t *dev = (et4000_t *) svga->priv; + int clk_sel = ((svga->miscout >> 2) & 0x03) | ((svga->crtc[0x34] << 1) & 0x04)| ((svga->crtc[0x31] >> 3) & 0x08); svga->memaddr_latch |= (svga->crtc[0x33] & 3) << 16; @@ -665,26 +666,15 @@ et4000_recalctimings(svga_t *svga) svga->dots_per_clock <<= 1; } - switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { - case 0: - case 1: - break; - case 3: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 40000000.0; - break; - case 5: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0; - break; - default: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; - break; - } + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); + if (clk_sel < 2) + svga->clock *= 2.0; switch (svga->bpp) { case 15: case 16: - svga->hdisp /= 2; - svga->dots_per_clock /= 2; + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; break; case 24: @@ -901,6 +891,9 @@ et4000_init(const device_t *info) if (dev->type >= ET4000_TYPE_ISA) dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + dev->svga.clock_gen = device_add(&ics2494an_324_device); + dev->svga.getclock = ics2494_getclock; + if (dev->type == ET4000_TYPE_TC6058AF) dev->svga.adv_flags |= FLAG_PRECISETIME; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 210a9f625..74b57370e 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3758,6 +3758,7 @@ s3_recalctimings(svga_t *svga) if ((((svga->miscout >> 2) & 3) == 3) && (s3->chip < S3_TRIO32)) clk_sel = svga->crtc[0x42] & 0x0f; + s3_log("MiscOut=%02x, cr42=%02x.\n", (svga->miscout >> 2) & 3, svga->crtc[0x42] & 0x0f); svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); switch (s3->ramdac_type) { @@ -3968,6 +3969,10 @@ s3_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->dots_per_clock <<= 1; svga->clock *= 2.0; + } else if ((clk_sel == 3) && (s3->width >= 1024)) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4160,6 +4165,10 @@ s3_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->dots_per_clock <<= 1; svga->clock *= 2.0; + } else if ((clk_sel == 3) && (s3->width >= 1024)) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4357,6 +4366,10 @@ s3_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->dots_per_clock <<= 1; svga->clock *= 2.0; + } else if ((clk_sel == 3) && (s3->width >= 1024)) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } s3_log("TVP3026 968 16bpp: MiscOut=%x, clksel=%x.\n", (svga->miscout >> 2) & 3, clk_sel); if (svga->hdisp == 832) @@ -4443,9 +4456,20 @@ s3_recalctimings(svga_t *svga) case S3_VISION968: switch (s3->ramdac_type) { + case IBM_RGB: /*IBM RGB528 RAMDAC and clock chip*/ + svga->hdisp = (svga->hdisp << 2) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 2) / 3; + svga->clock = (svga->clock * 4.0) / 3.0; + svga->clock /= 2.0; + if (!s3->elsa_eeprom) { + if (svga->hdisp == 832) + svga->hdisp -= 32; + } + break; + case TVP3026: /*TVP3026 RAMDAC and clock chip*/ svga->hdisp = (svga->hdisp << 1) / 3; - if (clk_sel == 2) { + if (clk_sel >= 2) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; svga->clock = (svga->clock * 4.0) / 3.0; @@ -4594,6 +4618,10 @@ s3_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->dots_per_clock <<= 1; svga->clock *= 2.0; + } else if ((clk_sel == 3) && (s3->width >= 1024)) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } if (svga->hdisp == 832) svga->hdisp -= 32; @@ -8197,7 +8225,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->bpp == 1) || s3->color_16bit) { srcbase >>= 1; dstbase >>= 1; - } else if (s3->bpp == 3) { + } else if (s3->bpp >= 2) { srcbase >>= 2; dstbase >>= 2; } @@ -8222,7 +8250,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } if ((s3->bpp == 1) || s3->color_16bit) count >>= 1; - else if (s3->bpp == 3) + else if (s3->bpp >= 2) count >>= 2; } } @@ -8930,6 +8958,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy = s3->accel.cur_y & 0xfff; if (s3->bpp == 2) { + s3_log("24bpp x68 rectfill: cmd=%04x CX=%d, CY=%d.\n", s3->accel.cmd, s3->accel.cx, s3->accel.cy); s3->accel.cx *= 3; s3->accel.cy *= 3; } else if ((s3->bpp == 0) && (svga->bpp == 24)) @@ -9091,16 +9120,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (wrt_mask == 0x0000ffff) wrt_mask = 0xffffffff; - if ((rd_mask == 0x0000ffff) || (rd_mask == 0x000000ff)) + if ((rd_mask == 0x00ffffff) || (rd_mask == 0x0000ffff) || (rd_mask == 0x000000ff)) rd_mask = 0xffffffff; } while (count-- && (s3->accel.sy >= 0)) { - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) { - mix_dat >>= 16; - s3->accel.temp_cnt = 16; - } - if ((((s3->accel.cx >= (clip_l * multiplier)) && (s3->accel.cx <= (clip_r * multiplier)) && (s3->accel.cy >= (clip_t * multiplier)) && (s3->accel.cy <= (clip_b * multiplier))) && !(s3->accel.multifunc[0xe] & 0x20)) || (((s3->accel.cx < (clip_l * multiplier)) && (s3->accel.cx > (clip_r * multiplier)) && (s3->accel.cy < (clip_t * multiplier)) && (s3->accel.cy > (clip_b * multiplier))) && (s3->accel.multifunc[0xe] & 0x20)) ) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -9138,7 +9162,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if (update) { if (s3->bpp == 2) - dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.cx - (s3->accel.minus * 3)) & s3->vram_mask]) & 0xffffff; + dest_dat = (*(uint32_t *) &vram_b[(s3->accel.dest + s3->accel.cx) & s3->vram_mask]) & 0xffffff; else { READ(s3->accel.dest + s3->accel.cx, dest_dat); } @@ -11515,8 +11539,8 @@ s3_init(const device_t *info) case S3_VISION968: switch (info->local) { - case S3_ELSAWIN2KPROX: case S3_DIAMOND_STEALTH64_968: + case S3_ELSAWIN2KPROX: case S3_PHOENIX_VISION968: case S3_NUMBER9_9FX_771: svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; @@ -11887,10 +11911,10 @@ s3_init(const device_t *info) if (info->local == S3_ELSAWIN2KPROX) { s3->elsa_eeprom = 1; ibm_rgb528_ramdac_set_ref_clock(svga->ramdac, svga, 28322000.0f); - } else if (info->local != S3_DIAMOND_STEALTH64_968) - ibm_rgb528_ramdac_set_ref_clock(svga->ramdac, svga, 16000000.0f); - else + } else if (info->local == S3_DIAMOND_STEALTH64_968) ibm_rgb528_ramdac_set_ref_clock(svga->ramdac, svga, 14318184.0f); + else + ibm_rgb528_ramdac_set_ref_clock(svga->ramdac, svga, 16000000.0f); break; default: svga->ramdac = device_add(&tvp3026_ramdac_device);