The branch main has been updated by alfredo:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=50b7c1f530f174be720b83f7e1d13e0fd42c5974

commit 50b7c1f530f174be720b83f7e1d13e0fd42c5974
Author:     Alfredo Dal'Ava Junior <[email protected]>
AuthorDate: 2021-02-19 06:22:25 +0000
Commit:     Alfredo Dal'Ava Junior <[email protected]>
CommitDate: 2021-02-19 22:50:36 +0000

    ofwfb: fix incorrect colors on powerpc* and add new tunable parameters
    
    - Implements little-endian support (powerpc64le)
    - Adds 'hw.ofwfb.physaddr' kernel parameter so user can manually
      provide correct address if it's not detected correctly
    - Adds 'hw.ofwfb.argb32_pixel' so user can set it manually if
      colors are inverted due to incorrect pixel format (default = 1)
    - Automatically selects RGBA32 pixel format if NVidia graphic adapter
      is detected (sets hw.ofwfb.argb32_pixel=0)
    
    Machines equipped with NVidia graphic adapters tend to use RGBA32
    pixel format. By default ARGB32 pixel format is used, proved to work
    on machines equipped with ATI graphic adapter and the onboard adapter
    used on Talos II and Blackbird machines from Raptor Computing Systems.
    
    Original patch developed by bdragon
    
    Reviewed by:    bdragon, luporl
    MFC after:      3 days
    Relnotes:       yes
    Differential Revision:  https://reviews.freebsd.org/D28604
---
 sys/dev/vt/hw/ofwfb/ofwfb.c | 165 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 123 insertions(+), 42 deletions(-)

diff --git a/sys/dev/vt/hw/ofwfb/ofwfb.c b/sys/dev/vt/hw/ofwfb/ofwfb.c
index 833b98b39f78..8a1b7b3688a7 100644
--- a/sys/dev/vt/hw/ofwfb/ofwfb.c
+++ b/sys/dev/vt/hw/ofwfb/ofwfb.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_subr.h>
 
 struct ofwfb_softc {
        struct fb_info  fb;
@@ -55,8 +56,13 @@ struct ofwfb_softc {
        ihandle_t       sc_handle;
        bus_space_tag_t sc_memt;
        int             iso_palette;
+       int             argb;
+       int             endian_flip;
+       uint32_t        vendor_id;
 };
 
+#define PCI_VENDOR_ID_NVIDIA   0x10de
+
 static void ofwfb_initialize(struct vt_device *vd);
 static vd_probe_t      ofwfb_probe;
 static vd_init_t       ofwfb_init;
@@ -297,7 +303,6 @@ ofwfb_initialize(struct vt_device *vd)
        struct ofwfb_softc *sc = vd->vd_softc;
        int i, err;
        cell_t retval;
-       uint32_t oldpix;
 
        sc->fb.fb_cmsize = 16;
 
@@ -311,6 +316,10 @@ ofwfb_initialize(struct vt_device *vd)
        sc->iso_palette = 0;
        switch (sc->fb.fb_bpp) {
        case 8:
+               /*
+                * No color format issues here, since we are passing the RGB
+                * components separately to Open Firmware.
+                */
                vt_generate_cons_palette(sc->fb.fb_cmap, COLOR_FORMAT_RGB, 255,
                    16, 255, 8, 255, 0);
 
@@ -330,21 +339,38 @@ ofwfb_initialize(struct vt_device *vd)
 
        case 32:
                /*
-                * We bypass the usual bus_space_() accessors here, mostly
-                * for performance reasons. In particular, we don't want
-                * any barrier operations that may be performed and handle
-                * endianness slightly different. Figure out the host-view
-                * endianness of the frame buffer.
+                * There are two main color formats in use.
+                * ARGB32 is used mainly on hardware that was designed for
+                * LE systems, and RGBA32 is used mainly on hardware designed
+                * for BE systems.
+                *
+                * PowerMacs use either, depending on the video card option.
+                * NVidia cards tend to be RGBA32, and ATI cards tend to be 
ARGB32.
+                *
+                * There is no good way to determine the correct option, as this
+                * is independent of endian swapping.
                 */
-               oldpix = bus_space_read_4(sc->sc_memt, sc->fb.fb_vbase, 0);
-               bus_space_write_4(sc->sc_memt, sc->fb.fb_vbase, 0, 0xff000000);
-               if (*(uint8_t *)(sc->fb.fb_vbase) == 0xff)
-                       vt_generate_cons_palette(sc->fb.fb_cmap,
-                           COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
+               if (sc->vendor_id == PCI_VENDOR_ID_NVIDIA)
+                       sc->argb = 0;
                else
-                       vt_generate_cons_palette(sc->fb.fb_cmap,
-                           COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
-               bus_space_write_4(sc->sc_memt, sc->fb.fb_vbase, 0, oldpix);
+                       sc->argb = 1;
+
+               TUNABLE_INT_FETCH("hw.ofwfb.argb32_pixel", &sc->argb);
+               if (sc->endian_flip) {
+                       if (sc->argb)
+                               vt_generate_cons_palette(sc->fb.fb_cmap,
+                                   COLOR_FORMAT_RGB, 255, 8, 255, 16, 255, 24);
+                       else
+                               vt_generate_cons_palette(sc->fb.fb_cmap,
+                                   COLOR_FORMAT_RGB, 255, 24, 255, 16, 255, 8);
+               } else {
+                       if (sc->argb)
+                               vt_generate_cons_palette(sc->fb.fb_cmap,
+                                   COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
+                       else
+                               vt_generate_cons_palette(sc->fb.fb_cmap,
+                                   COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
+               }
                break;
 
        default:
@@ -361,8 +387,12 @@ ofwfb_init(struct vt_device *vd)
        phandle_t chosen;
        phandle_t node;
        uint32_t depth, height, width, stride;
-       uint32_t fb_phys;
-       int i, len;
+       uint32_t vendor_id = 0;
+       cell_t adr[2];
+       uint64_t user_phys;
+       bus_addr_t fb_phys;
+       bus_size_t fb_phys_size;
+       int i, j, len;
 
        /* Initialize softc */
        vd->vd_softc = sc = &ofwfb_conssoftc;
@@ -391,6 +421,16 @@ ofwfb_init(struct vt_device *vd)
        if (strcmp(buf, "display") != 0)
                return (CN_DEAD);
 
+       /*
+        * Retrieve vendor-id from /chosen parent node, usually pointing to
+        * video card device. This is used to select pixel format later on
+        * ofwfb_initialize()
+        */
+       if (OF_getencprop(OF_parent(node), "vendor-id", &vendor_id,
+           sizeof(vendor_id)) == sizeof(vendor_id))
+               sc->vendor_id = vendor_id;
+
+
        /* Keep track of the OF node */
        sc->sc_node = node;
 
@@ -419,35 +459,69 @@ ofwfb_init(struct vt_device *vd)
            sizeof(stride))
                stride = width*depth/8;
 
+
        sc->fb.fb_height = height;
        sc->fb.fb_width = width;
        sc->fb.fb_stride = stride;
        sc->fb.fb_size = sc->fb.fb_height * sc->fb.fb_stride;
+       sc->endian_flip = 0;
+
+#if defined(__powerpc__)
+       if (OF_hasprop(node, "little-endian")) {
+               sc->sc_memt = &bs_le_tag;
+#if BYTE_ORDER == BIG_ENDIAN
+               sc->endian_flip = 1;
+#endif
+        } else if (OF_hasprop(node, "big-endian")) {
+               sc->sc_memt = &bs_be_tag;
+#if BYTE_ORDER == LITTLE_ENDIAN
+               sc->endian_flip = 1;
+#endif
+       }
+       else {
+               /* Assume the framebuffer is in native endian. */
+#if BYTE_ORDER == BIG_ENDIAN
+               sc->sc_memt = &bs_be_tag;
+#else
+               sc->sc_memt = &bs_le_tag;
+#endif
+       }
+#elif defined(__arm__)
+       sc->sc_memt = fdtbus_bs_tag;
+#else
+       #error Unsupported platform!
+#endif
+
 
        /*
         * Grab the physical address of the framebuffer, and then map it
         * into our memory space. If the MMU is not yet up, it will be
         * remapped for us when relocation turns on.
         */
-       if (OF_getproplen(node, "address") == sizeof(fb_phys)) {
-               /* XXX We assume #address-cells is 1 at this point. */
-               OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
-
-       #if defined(__powerpc__)
-               sc->sc_memt = &bs_be_tag;
-               bus_space_map(sc->sc_memt, fb_phys, sc->fb.fb_size,
-                   BUS_SPACE_MAP_PREFETCHABLE, &sc->fb.fb_vbase);
-       #elif defined(__arm__)
-               sc->sc_memt = fdtbus_bs_tag;
-               bus_space_map(sc->sc_memt, sc->fb.fb_pbase, sc->fb.fb_size,
-                   BUS_SPACE_MAP_PREFETCHABLE,
-                   (bus_space_handle_t *)&sc->fb.fb_vbase);
-       #else
-               #error Unsupported platform!
-       #endif
+       user_phys = 0;
+       TUNABLE_UINT64_FETCH("hw.ofwfb.physaddr", &user_phys);
+       fb_phys = (bus_addr_t)user_phys;
+       if (fb_phys)
+               sc->fb.fb_pbase = (vm_paddr_t)fb_phys;
+       else if (OF_hasprop(node, "address")) {
+
+               switch (OF_getproplen(node, "address")) {
+               case 4:
+                       OF_getencprop(node, "address", adr, 4);
+                       fb_phys = adr[0];
+                       break;
+               case 8:
+                       OF_getencprop(node, "address", adr, 8);
+                       fb_phys = ((uint64_t)adr[0] << 32) | adr[1];
+                       break;
+               default:
+                       /* Bad property? */
+                       return (CN_DEAD);
+               }
 
-               sc->fb.fb_pbase = fb_phys;
+               sc->fb.fb_pbase = (vm_paddr_t)fb_phys;
        } else {
+#if defined(__powerpc__)
                /*
                 * Some IBM systems don't have an address property. Try to
                 * guess the framebuffer region from the assigned addresses.
@@ -473,7 +547,7 @@ ofwfb_init(struct vt_device *vd)
                        len = 0;
                num_pciaddrs = len / sizeof(struct ofw_pci_register);
 
-               fb_phys = num_pciaddrs;
+               j = num_pciaddrs;
                for (i = 0; i < num_pciaddrs; i++) {
                        /* If it is too small, not the framebuffer */
                        if (pciaddrs[i].size_lo < sc->fb.fb_stride * height)
@@ -484,26 +558,33 @@ ofwfb_init(struct vt_device *vd)
                                continue;
 
                        /* This could be the framebuffer */
-                       fb_phys = i;
+                       j = i;
 
                        /* If it is prefetchable, it certainly is */
                        if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
                                break;
                }
 
-               if (fb_phys == num_pciaddrs) /* No candidates found */
+               if (j == num_pciaddrs) /* No candidates found */
                        return (CN_DEAD);
 
-       #if defined(__powerpc__)
-               OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->fb.fb_vbase,
-                   NULL);
-               sc->fb.fb_pbase = sc->fb.fb_vbase & ~DMAP_BASE_ADDRESS;
-       #else
+               if (ofw_reg_to_paddr(node, j, &fb_phys, &fb_phys_size, NULL) < 
0)
+                       return (CN_DEAD);
+
+               sc->fb.fb_pbase = (vm_paddr_t)fb_phys;
+#else
                /* No ability to interpret assigned-addresses otherwise */
                return (CN_DEAD);
-       #endif
+#endif
         }
 
+       if (!sc->fb.fb_pbase)
+               return (CN_DEAD);
+
+       bus_space_map(sc->sc_memt, sc->fb.fb_pbase, sc->fb.fb_size,
+           BUS_SPACE_MAP_PREFETCHABLE,
+           (bus_space_handle_t *)&sc->fb.fb_vbase);
+
        #if defined(__powerpc__)
        /*
         * If we are running on PowerPC in real mode (supported only on AIM
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to