From owner-dev-commits-src-all@freebsd.org Fri Feb 19 19:53:36 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id B4DFA53A02D; Fri, 19 Feb 2021 19:53:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Dj2M44lwsz3Brj; Fri, 19 Feb 2021 19:53:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 9600F11E28; Fri, 19 Feb 2021 19:53:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 11JJra81092289; Fri, 19 Feb 2021 19:53:36 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 11JJraCs092288; Fri, 19 Feb 2021 19:53:36 GMT (envelope-from git) Date: Fri, 19 Feb 2021 19:53:36 GMT Message-Id: <202102191953.11JJraCs092288@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Alfredo Dal'Ava Junior" Subject: git: 50b7c1f530f1 - main - ofwfb: fix incorrect colors on powerpc* and add new tunable parameters MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: alfredo X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 50b7c1f530f174be720b83f7e1d13e0fd42c5974 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Feb 2021 19:53:36 -0000 The branch main has been updated by alfredo: URL: https://cgit.FreeBSD.org/src/commit/?id=50b7c1f530f174be720b83f7e1d13e0fd42c5974 commit 50b7c1f530f174be720b83f7e1d13e0fd42c5974 Author: Alfredo Dal'Ava Junior AuthorDate: 2021-02-19 06:22:25 +0000 Commit: Alfredo Dal'Ava Junior 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 #include #include +#include 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