Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Also set the bits for horizontal sync start dela...



details:   https://anonhg.NetBSD.org/src/rev/a792b2423146
branches:  trunk
changeset: 937050:a792b2423146
user:      jdc <jdc%NetBSD.org@localhost>
date:      Fri Aug 07 18:26:33 2020 +0000

description:
Also set the bits for horizontal sync start delay.  This makes machfb work
correctly for some modes (e.g. 1152x720).
Modify mach64_get_mode() to get the mode from the chip registers (only used
with debug on).
Whilst here tidy up some other debug output.

diffstat:

 sys/dev/pci/machfb.c |  169 ++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 126 insertions(+), 43 deletions(-)

diffs (263 lines):

diff -r c57c9f7c0a08 -r a792b2423146 sys/dev/pci/machfb.c
--- a/sys/dev/pci/machfb.c      Fri Aug 07 18:14:21 2020 +0000
+++ b/sys/dev/pci/machfb.c      Fri Aug 07 18:26:33 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machfb.c,v 1.100 2020/07/30 21:29:20 macallan Exp $    */
+/*     $NetBSD: machfb.c,v 1.101 2020/08/07 18:26:33 jdc Exp $ */
 
 /*
  * Copyright (c) 2002 Bang Jun-Young
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0,
-       "$NetBSD: machfb.c,v 1.100 2020/07/30 21:29:20 macallan Exp $");
+       "$NetBSD: machfb.c,v 1.101 2020/08/07 18:26:33 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -228,8 +228,9 @@
 static void    mach64_init(struct mach64_softc *);
 static int     mach64_get_memsize(struct mach64_softc *);
 static int     mach64_get_max_ramdac(struct mach64_softc *);
+static int     mach64_ref_freq(void);
 
-#if 0
+#ifdef MACHFB_DEBUG
 static void    mach64_get_mode(struct mach64_softc *, struct videomode *);
 #endif
 
@@ -505,6 +506,9 @@
 
        printf("%s: %d KB ROM at 0x%08x\n", device_xname(sc->sc_dev),
            (int)sc->sc_rom.vb_size >> 10, (uint32_t)sc->sc_rom.vb_base);
+#ifdef MACHFB_DEBUG
+       mach64_get_mode(sc, NULL);
+#endif
 
        prop_dictionary_get_uint32(device_properties(self), "width", &width);
        prop_dictionary_get_uint32(device_properties(self), "height", &height);
@@ -556,23 +560,13 @@
        else
                sc->memtype = regr(sc, CONFIG_STAT0) & 0x07;
 
-       /*
-        * XXX is there any way to calculate reference frequency from
-        * known values?
-        */
-       if ((mach64_chip_id == PCI_PRODUCT_ATI_RAGE_XL_PCI) ||
-           ((mach64_chip_id >= PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI) &&
-           (mach64_chip_id <= PCI_PRODUCT_ATI_RAGE_LT_PRO))) {
-               aprint_normal_dev(sc->sc_dev, "ref_freq=29.498MHz\n");
-               sc->ref_freq = 29498;
-       } else
-               sc->ref_freq = 14318;
+       sc->ref_freq = mach64_ref_freq();
 
        reg = regr(sc, CLOCK_CNTL);
-       aprint_debug("CLOCK_CNTL: %08x\n", reg);
        sc->sc_clock = reg & 3;
-       aprint_debug("using clock %d\n", sc->sc_clock);
+       DPRINTF("using clock %d\n", sc->sc_clock);
 
+       DPRINTF("ref_freq: %d\n", sc->ref_freq);
        sc->ref_div = regrb_pll(sc, PLL_REF_DIV);
        DPRINTF("ref_div: %d\n", sc->ref_div);
        sc->mclk_fb_div = regrb_pll(sc, MCLK_FB_DIV);
@@ -636,8 +630,9 @@
                                    sizeof(struct videomode));
                                sc->sc_setmode = 1;
                        } else {
-                               aprint_error_dev(sc->sc_dev,
-                                   "unable to use preferred mode\n");
+                               aprint_normal_dev(sc->sc_dev,
+                                   "unable to use EDID preferred mode "
+                                   "(%d x %d)\n", m->hdisplay, m->vdisplay);
                        }
                }
                /*
@@ -905,32 +900,118 @@
                return 80000;
 }
 
-#if 0
+static int
+mach64_ref_freq(void)
+{
+       /*
+        * There doesn't seem to be any way to calculate the reference
+        * frequency from known values
+        */
+       if ((mach64_chip_id == PCI_PRODUCT_ATI_RAGE_XL_PCI) ||
+           ((mach64_chip_id >= PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI) &&
+           (mach64_chip_id <= PCI_PRODUCT_ATI_RAGE_L_MOB_M1_PCI)))
+               return 29498;
+       else
+               return 14318;
+}
+
+#ifdef MACHFB_DEBUG
 static void
 mach64_get_mode(struct mach64_softc *sc, struct videomode *mode)
 {
-       struct mach64_crtcregs crtc;
+       int htotal, hdisplay, hsync_start, hsync_end;
+       int vtotal, vdisplay, vsync_start, vsync_end;
+       int gen_ctl, clk_ctl, clock;
+       int ref_freq, ref_div, mclk_fb_div, vclk_post_div, vclk_fb_div;
+       int nhsync, nvsync;
+       int post_div, dot_clock, vrefresh, vrefresh2;
+
+       hdisplay = regr(sc, CRTC_H_TOTAL_DISP);
+       hsync_end = regr(sc, CRTC_H_SYNC_STRT_WID);
+       vdisplay = regr(sc, CRTC_V_TOTAL_DISP);
+       vsync_end = regr(sc, CRTC_V_SYNC_STRT_WID);
+       gen_ctl = regr(sc, CRTC_GEN_CNTL);
+       clk_ctl = regr(sc, CLOCK_CNTL);
+       clock = clk_ctl & 3;
+       ref_div = regrb_pll(sc, PLL_REF_DIV);
+       mclk_fb_div = regrb_pll(sc, MCLK_FB_DIV);
+       vclk_post_div = regrb_pll(sc, VCLK_POST_DIV);
+       vclk_fb_div = regrb_pll(sc, VCLK0_FB_DIV + clock);
+       ref_freq = mach64_ref_freq();
 
-       crtc.h_total_disp = regr(sc, CRTC_H_TOTAL_DISP);
-       crtc.h_sync_strt_wid = regr(sc, CRTC_H_SYNC_STRT_WID);
-       crtc.v_total_disp = regr(sc, CRTC_V_TOTAL_DISP);
-       crtc.v_sync_strt_wid = regr(sc, CRTC_V_SYNC_STRT_WID);
+       aprint_normal_dev(sc->sc_dev, "CRTC registers:\n");
+       aprint_normal("\th total: 0x%08x  h sync: 0x%08x\n",
+           hdisplay, hsync_end);
+       aprint_normal("\tv total: 0x%08x  v sync: 0x%08x\n",
+           vdisplay, vsync_end);
+       aprint_normal("\t g cntl: 0x%08x  c cntl: 0x%08x\n",
+           gen_ctl, clk_ctl);
+       aprint_normal("\t rfreq %d  rdiv: %d\n", ref_freq, ref_div);
+       aprint_normal_dev(sc->sc_dev, "PLL registers:\n");
+       aprint_normal("\t m div: 0x%02x  p div: 0x%02x  v%d div: 0x%02x\n",
+           mclk_fb_div, vclk_post_div, clock, vclk_fb_div);
+
+       htotal = ((hdisplay & 0x01ff) + 1) << 3;
+       hdisplay = (((hdisplay & 0x1ff0000) >> 16) + 1) << 3;
+       if (hsync_end & CRTC_HSYNC_NEG)
+               nhsync = 1;
+       else
+               nhsync = 0;
+       hsync_start = (((hsync_end & 0xff) + 1) << 3) +
+           ((hsync_end & 0x700) >> 8);
+       hsync_end = (((hsync_end & 0x1f0000) >> 16) << 3) + hsync_start;
 
-       mode->htotal = ((crtc.h_total_disp & 0xffff) + 1) << 3;
-       mode->hdisplay = ((crtc.h_total_disp >> 16) + 1) << 3;
-       mode->hsync_start = ((crtc.h_sync_strt_wid & 0xffff) + 1) << 3;
-       mode->hsync_end = ((crtc.h_sync_strt_wid >> 16) << 3) +
-           mode->hsync_start;
-       mode->vtotal = (crtc.v_total_disp & 0xffff) + 1;
-       mode->vdisplay = (crtc.v_total_disp >> 16) + 1;
-       mode->vsync_start = (crtc.v_sync_strt_wid & 0xffff) + 1;
-       mode->vsync_end = (crtc.v_sync_strt_wid >> 16) + mode->vsync_start;
+       vtotal = (vdisplay & 0x07ff) + 1;
+       vdisplay = ((vdisplay & 0x7ff0000) >> 16) + 1;
+       if (vsync_end & CRTC_VSYNC_NEG)
+               nvsync = 1;
+       else
+               nvsync = 0;
+       vsync_start = (vsync_end & 0x07ff) + 1;
+       vsync_end = ((vsync_end & 0x1f0000) >> 16) + vsync_start;
 
-#ifdef MACHFB_DEBUG
-       printf("mach64_get_mode: %d %d %d %d %d %d %d %d\n",
-           mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal,
-           mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal);
-#endif
+       switch ((vclk_post_div >> (clock * 2)) & 3) {
+               case 3:
+                       post_div = 8;
+                       break;
+               case 2:
+                       post_div = 4;
+                       break;
+               case 1:
+                       post_div = 2;
+                       break;
+               default:
+                       post_div = 1;
+                       break;
+       }
+       dot_clock = (2 * ref_freq * vclk_fb_div) / (ref_div * post_div);
+       vrefresh = (dot_clock * 1000) / (htotal * vtotal);
+       vrefresh2 = ((dot_clock * 1000) - (vrefresh * htotal * vtotal)) * 100 /
+           (htotal * vtotal);
+
+       aprint_normal_dev(sc->sc_dev, "Video mode:\n");
+       aprint_normal("\t%d" "x%d @ %d.%02dHz "
+           "(%d %d %d %d %d %d %d %cH %cV)\n",
+           hdisplay, vdisplay, vrefresh, vrefresh2, dot_clock,
+           hsync_start, hsync_end, htotal, vsync_start, vsync_end, vtotal,
+           nhsync == 1 ? '-' : '+', nvsync == 1 ? '-' : '+');
+
+       if (mode != NULL) {
+               mode->dot_clock = dot_clock;
+               mode->htotal = htotal;
+               mode->hdisplay = hdisplay;
+               mode->hsync_start = hsync_start;
+               mode->hsync_end = hsync_end;
+               mode->vtotal = vtotal;
+               mode->vdisplay = vdisplay;
+               mode->vsync_start = vsync_start;
+               mode->vsync_end = vsync_end;
+               mode->flags = 0;
+               if (nhsync)
+                       mode->flags |= VID_NHSYNC;
+               if (nvsync)
+                       mode->flags |= VID_NVSYNC;
+       }
 }
 #endif
 
@@ -947,7 +1028,7 @@
            ((mode->htotal >> 3) - 1);
        crtc->h_sync_strt_wid =
            (((mode->hsync_end - mode->hsync_start) >> 3) << 16) |
-           ((mode->hsync_start >> 3) - 1);
+           ((mode->hsync_start >> 3) - 1) | ((mode->hsync_start & 7) << 8);
 
        crtc->v_total_disp = ((mode->vdisplay - 1) << 16) |
            (mode->vtotal - 1);
@@ -991,6 +1072,10 @@
        if (sc->has_dsp)
                mach64_set_dsp(sc);
 
+       DPRINTF("\th total: 0x%08x  h sync: 0x%08x\n",
+           crtc->h_total_disp, crtc->h_sync_strt_wid);
+       DPRINTF("\tv total: 0x%08x  v sync: 0x%08x\n",
+           crtc->v_total_disp, crtc->v_sync_strt_wid);
        regw(sc, CRTC_H_TOTAL_DISP, crtc->h_total_disp);
        regw(sc, CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
        regw(sc, CRTC_V_TOTAL_DISP, crtc->v_total_disp);
@@ -1170,7 +1255,7 @@
                       (sc->vclk_freq * sc->bits_per_pixel);
 
        DPRINTF("xclks_per_qw %d %d\n", xclks_per_qw >> 7, xclks_per_qw_m);
-               DPRINTF("mem %dkHz v %dkHz\n", sc->mem_freq, sc->vclk_freq);
+       DPRINTF("mem %dkHz v %dkHz\n", sc->mem_freq, sc->vclk_freq);
 
        y = (xclks_per_qw * fifo_depth) >> 11;
                       
@@ -1224,15 +1309,13 @@
        dsp_on = fifo_on >> dsp_precision;
        dsp_off = fifo_off >> dsp_precision;
 
-#ifdef MACHFB_DEBUG
-       printf("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n"
+       DPRINTF("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n"
            "dsp_precision = %d, dsp_loop_latency = %d,\n"
            "mclk_fb_div = %d, vclk_fb_div = %d,\n"
            "mclk_post_div = %d, vclk_post_div = %d\n",
            dsp_xclks_per_qw, dsp_on, dsp_off, dsp_precision, dsp_loop_latency,
            sc->mclk_fb_div, sc->vclk_fb_div,
            sc->mclk_post_div, sc->vclk_post_div);
-#endif
        DPRINTF("DSP_ON_OFF %08x\n", regr(sc, DSP_ON_OFF));
        DPRINTF("DSP_CONFIG %08x\n", regr(sc, DSP_CONFIG));
        regw(sc, DSP_ON_OFF, ((dsp_on << 16) & DSP_ON) | (dsp_off & DSP_OFF));



Home | Main Index | Thread Index | Old Index