vt: export RGB offsets with FBIO_GETRGBOFFS

Add a new ioctl to vt to make it possible to export RGB offsets
set by vt drivers. This is needed to fix colors on X and Mesa
on some machines, especially on modern PowerPC64 BE ones.

With the appropriate changes in SCFB, to use this ioctl to find
out the correct RGB offsets, this fixes wrong colors on Talos II
and Blackbird, when used with their built-in video cards.

Reviewed by:		alfredo
Sponsored by:		Instituto de Pesquisas Eldorado (eldorado.org.br)
Differential Revision:	https://reviews.freebsd.org/D29000
This commit is contained in:
Leandro Lupori 2021-11-25 15:54:11 -03:00
parent b19740f4ce
commit b9f3b63ab2
12 changed files with 76 additions and 37 deletions

View File

@ -137,12 +137,12 @@ bcm_fb_setup_fbd(struct bcmsc_softc *sc)
if (sc->fbswap) {
switch (sc->info.fb_bpp) {
case 24:
vt_generate_cons_palette(sc->info.fb_cmap,
vt_config_cons_colors(&sc->info,
COLOR_FORMAT_RGB, 0xff, 0, 0xff, 8, 0xff, 16);
sc->info.fb_cmsize = 16;
break;
case 32:
vt_generate_cons_palette(sc->info.fb_cmap,
vt_config_cons_colors(&sc->info,
COLOR_FORMAT_RGB, 0xff, 16, 0xff, 8, 0xff, 0);
sc->info.fb_cmsize = 16;
break;

View File

@ -156,22 +156,22 @@ ipu3_fb_init(struct ipu3sc_softc *sc)
/* Use own color map, because of different RGB offset. */
static int
ipu3_fb_init_cmap(uint32_t *cmap, int bytespp)
ipu3_fb_init_colors(struct fb_info *info)
{
switch (bytespp) {
switch (info->fb_depth) {
case 8:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x7, 5, 0x7, 2, 0x3, 0));
case 15:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x1f, 10, 0x1f, 5, 0x1f, 0));
case 16:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x1f, 11, 0x3f, 5, 0x1f, 0));
case 24:
case 32: /* Ignore alpha. */
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0xff, 0, 0xff, 8, 0xff, 16));
default:
return (1);
@ -303,7 +303,7 @@ ipu3_fb_attach(device_t dev)
sc->sc_info.fb_name = device_get_nameunit(dev);
ipu3_fb_init_cmap(sc->sc_info.fb_cmap, sc->sc_info.fb_depth);
ipu3_fb_init_colors(&sc->sc_info);
sc->sc_info.fb_cmsize = 16;
/* Ask newbus to attach framebuffer device to me. */

View File

@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/fbio.h>
#include <dev/vt/colors/vt_termcolors.h>
@ -152,7 +153,7 @@ vt_palette_init(void)
}
}
int
static int
vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
@ -176,3 +177,18 @@ vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
return (0);
}
int
vt_config_cons_colors(struct fb_info *info, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
if (format == COLOR_FORMAT_RGB) {
info->fb_rgboffs.red = roffset;
info->fb_rgboffs.green = goffset;
info->fb_rgboffs.blue = boffset;
} else
memset(&info->fb_rgboffs, 0, sizeof(info->fb_rgboffs));
return (vt_generate_cons_palette(info->fb_cmap, format, rmax,
roffset, gmax, goffset, bmax, boffset));
}

View File

@ -30,6 +30,8 @@
* $FreeBSD$
*/
struct fb_info;
enum vt_color_format {
COLOR_FORMAT_BW = 0,
COLOR_FORMAT_GRAY,
@ -57,6 +59,6 @@ static const int cons_to_vga_colors[NCOLORS] = {
8, 12, 10, 14, 9, 13, 11, 15
};
/* Helper to fill color map used by driver */
int vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
/* Helper to fill color map and set RGB offsets used by driver */
int vt_config_cons_colors(struct fb_info *info, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset);

View File

@ -131,7 +131,7 @@ vt_efifb_init(struct vt_device *vd)
roff = ffs(efifb->fb_mask_red) - 1;
goff = ffs(efifb->fb_mask_green) - 1;
boff = ffs(efifb->fb_mask_blue) - 1;
vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
vt_config_cons_colors(info, COLOR_FORMAT_RGB,
efifb->fb_mask_red >> roff, roff,
efifb->fb_mask_green >> goff, goff,
efifb->fb_mask_blue >> boff, boff);

View File

@ -93,24 +93,24 @@ vt_efb_initialize(struct fb_info *info)
*/
switch (info->fb_depth) {
case 8:
vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x7, 5, 0x7, 2, 0x3, 0);
break;
case 15:
vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x1f, 10, 0x1f, 5, 0x1f, 0);
break;
case 16:
vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x1f, 11, 0x3f, 5, 0x1f, 0);
break;
case 24:
case 32:
#if BYTE_ORDER == BIG_ENDIAN
vt_generate_cons_palette(info->fb_cmap,
vt_config_cons_colors(info,
COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
#else
vt_generate_cons_palette(info->fb_cmap,
vt_config_cons_colors(info,
COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
#endif
#ifdef FDT

View File

@ -120,6 +120,14 @@ vt_fb_ioctl(struct vt_device *vd, u_long cmd, caddr_t data, struct thread *td)
vd->vd_driver->vd_blank(vd, TC_BLACK);
break;
case FBIO_GETRGBOFFS: /* get RGB offsets */
if (info->fb_rgboffs.red == 0 && info->fb_rgboffs.green == 0 &&
info->fb_rgboffs.blue == 0)
return (ENOTTY);
memcpy((struct fb_rgboffs *)data, &info->fb_rgboffs,
sizeof(struct fb_rgboffs));
break;
default:
error = ENOIOCTL;
break;
@ -432,22 +440,22 @@ vt_fb_postswitch(struct vt_device *vd)
}
static int
vt_fb_init_cmap(uint32_t *cmap, int depth)
vt_fb_init_colors(struct fb_info *info)
{
switch (depth) {
switch (FBTYPE_GET_BPP(info)) {
case 8:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x7, 5, 0x7, 2, 0x3, 0));
case 15:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x1f, 10, 0x1f, 5, 0x1f, 0));
case 16:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0x1f, 11, 0x3f, 5, 0x1f, 0));
case 24:
case 32: /* Ignore alpha. */
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
return (vt_config_cons_colors(info, COLOR_FORMAT_RGB,
0xff, 16, 0xff, 8, 0xff, 0));
default:
return (1);
@ -478,7 +486,7 @@ vt_fb_init(struct vt_device *vd)
info->fb_flags |= FB_FLAG_NOMMAP;
if (info->fb_cmsize <= 0) {
err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info));
err = vt_fb_init_colors(info);
if (err)
return (CN_DEAD);
info->fb_cmsize = 16;

View File

@ -400,7 +400,7 @@ static void
ofwfb_initialize(struct vt_device *vd)
{
struct ofwfb_softc *sc = vd->vd_softc;
int i, err;
int i, err, r, g, b;
cell_t retval;
sc->fb.fb_cmsize = 16;
@ -419,7 +419,7 @@ ofwfb_initialize(struct vt_device *vd)
* 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,
vt_config_cons_colors(&sc->fb, COLOR_FORMAT_RGB, 255,
16, 255, 8, 255, 0);
for (i = 0; i < 16; i++) {
@ -457,19 +457,17 @@ ofwfb_initialize(struct vt_device *vd)
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);
r = 8, g = 16, b = 24;
else
vt_generate_cons_palette(sc->fb.fb_cmap,
COLOR_FORMAT_RGB, 255, 24, 255, 16, 255, 8);
r = 24, g = 16, b = 8;
} else {
if (sc->argb)
vt_generate_cons_palette(sc->fb.fb_cmap,
COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
r = 16, g = 8, b = 0;
else
vt_generate_cons_palette(sc->fb.fb_cmap,
COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
r = 0, g = 8, b = 16;
}
vt_config_cons_colors(&sc->fb,
COLOR_FORMAT_RGB, 255, r, 255, g, 255, b);
break;
default:

View File

@ -135,7 +135,7 @@ vt_vbefb_init(struct vt_device *vd)
roff = ffs(vbefb->fb_mask_red) - 1;
goff = ffs(vbefb->fb_mask_green) - 1;
boff = ffs(vbefb->fb_mask_blue) - 1;
vt_generate_cons_palette(info->fb_cmap, format,
vt_config_cons_colors(info, format,
vbefb->fb_mask_red >> roff, roff,
vbefb->fb_mask_green >> goff, goff,
vbefb->fb_mask_blue >> boff, boff);

View File

@ -2559,6 +2559,7 @@ vtterm_ioctl(struct terminal *tm, u_long cmd, caddr_t data,
case FBIO_GETDISPSTART: /* get display start address */
case FBIO_GETLINEWIDTH: /* get scan line width in bytes */
case FBIO_BLANK: /* blank display */
case FBIO_GETRGBOFFS: /* get RGB offsets */
if (vd->vd_driver->vd_fb_ioctl)
return (vd->vd_driver->vd_fb_ioctl(vd, cmd, data, td));
break;

View File

@ -228,7 +228,7 @@ ps3fb_init(struct vt_device *vd)
sc->fb_info.fb_cmsize = 16;
/* 32-bit VGA palette */
vt_generate_cons_palette(sc->fb_info.fb_cmap, COLOR_FORMAT_RGB,
vt_config_cons_colors(&sc->fb_info, COLOR_FORMAT_RGB,
255, 16, 255, 8, 255, 0);
/* Set correct graphics context */

View File

@ -110,6 +110,15 @@ struct fbtype {
#define FBTYPE_GET_BPP(_fb) ((_fb)->fb_bpp)
#define FBTYPE_GET_BYTESPP(_fb) ((_fb)->fb_bpp / 8)
/*
* RGB offsets as returned by FBIO_GETRGBOFFS.
*/
struct fb_rgboffs {
int red;
int green;
int blue;
};
#ifdef _KERNEL
struct fb_info;
@ -148,6 +157,8 @@ struct fb_info {
int fb_stride;
int fb_bpp; /* bits per pixel */
uint32_t fb_cmap[16];
struct fb_rgboffs fb_rgboffs; /* RGB offsets */
};
int fbd_list(void);
@ -619,4 +630,7 @@ typedef struct video_color_palette video_color_palette_t;
#define FBIO_BLANK _IOW('F', 115, int)
/* get RGB offsets */
#define FBIO_GETRGBOFFS _IOR('F', 116, struct fb_rgboffs)
#endif /* !_SYS_FBIO_H_ */