changeset 20079:f0e4c56a3bb7

13152 loader: add flat panel info query Reviewed by: Robert Mustacchi <rm@fingolfin.org> Approved by: Dan McDonald <danmcd@joyent.com>
author Toomas Soome <tsoome@me.com>
date Sun, 13 Jan 2019 19:10:19 +0200
parents 3b587ddb3287
children 3988d4e53378
files usr/src/boot/sys/boot/common/gfx_fb.h usr/src/boot/sys/boot/i386/libi386/vbe.c usr/src/boot/sys/boot/i386/libi386/vbe.h
diffstat 3 files changed, 98 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/boot/sys/boot/common/gfx_fb.h	Mon Sep 14 20:37:35 2020 +0300
+++ b/usr/src/boot/sys/boot/common/gfx_fb.h	Sun Jan 13 19:10:19 2019 +0200
@@ -93,15 +93,21 @@
 	uint8_t checksum;
 } __packed;
 
+/*
+ * Number of pixels and lines is 12-bit int, valid values 0-4095.
+ */
+#define	EDID_MAX_PIXELS	4095
+#define	EDID_MAX_LINES	4095
+
 #define	GET_EDID_INFO_WIDTH(edid_info, timings_num) \
-    ((edid_info)->detailed_timings[(timings_num)].horizontal_active_lo | \
-    (((uint_t)(edid_info)->detailed_timings[(timings_num)].horizontal_hi & \
-    0xf0) << 4))
+	((edid_info)->detailed_timings[(timings_num)].horizontal_active_lo | \
+	(((uint_t)(edid_info)->detailed_timings[(timings_num)].horizontal_hi & \
+	0xf0) << 4))
 
 #define	GET_EDID_INFO_HEIGHT(edid_info, timings_num) \
-    ((edid_info)->detailed_timings[(timings_num)].vertical_active_lo | \
-    (((uint_t)(edid_info)->detailed_timings[(timings_num)].vertical_hi & \
-    0xf0) << 4))
+	((edid_info)->detailed_timings[(timings_num)].vertical_active_lo | \
+	(((uint_t)(edid_info)->detailed_timings[(timings_num)].vertical_hi & \
+	0xf0) << 4))
 
 extern multiboot_tag_framebuffer_t gfx_fb;
 
--- a/usr/src/boot/sys/boot/i386/libi386/vbe.c	Mon Sep 14 20:37:35 2020 +0300
+++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c	Sun Jan 13 19:10:19 2019 +0200
@@ -180,6 +180,20 @@
 	return (v86.ebx & 0xffff);
 }
 
+/* Function 11h BL=01h - Flat Panel status */
+static int
+biosvbe_ddc_read_flat_panel_info(void *buf)
+{
+	v86.ctl = V86_FLAGS;
+	v86.addr = 0x10;
+	v86.eax = 0x4f11;	/* Flat Panel Interface extensions */
+	v86.ebx = 1;		/* Return Flat Panel Information */
+	v86.es = VTOPSEG(buf);
+	v86.edi = VTOPOFF(buf);
+	v86int();
+	return (v86.eax & 0xffff);
+}
+
 /* Function 15h BL=01h - Read EDID */
 static int
 biosvbe_ddc_read_edid(int blockno, void *buf)
@@ -495,6 +509,7 @@
 	edid_info = bio_alloc(sizeof (*edid_info));
 	if (edid_info == NULL)
 		return (ret);
+	memset(edid_info, 0, sizeof (*edid_info));
 
 	if (VBE_ERROR(biosvbe_ddc_read_edid(0, edid_info)))
 		goto done;
@@ -511,12 +526,37 @@
 	*pwidth = GET_EDID_INFO_WIDTH(edid_info, 0);
 	*pheight = GET_EDID_INFO_HEIGHT(edid_info, 0);
 
-	ret = true;
+	if (*pwidth > 0 && *pwidth <= EDID_MAX_PIXELS &&
+	    *pheight > 0 && *pheight <= EDID_MAX_LINES)
+		ret = true;
 done:
 	bio_free(edid_info, sizeof (*edid_info));
 	return (ret);
 }
 
+static bool
+vbe_get_flatpanel(uint_t *pwidth, uint_t *pheight)
+{
+	struct flatpanelinfo *fp_info;
+	bool ret = false;
+
+	fp_info = bio_alloc(sizeof (*fp_info));
+	if (fp_info == NULL)
+		return (ret);
+	memset(fp_info, 0, sizeof (*fp_info));
+
+	if (VBE_ERROR(biosvbe_ddc_read_flat_panel_info(fp_info)))
+		goto done;
+
+	*pwidth = fp_info->HorizontalSize;
+	*pheight = fp_info->VerticalSize;
+	ret = true;
+
+done:
+	bio_free(fp_info, sizeof (*fp_info));
+	return (ret);
+}
+
 static void
 vbe_print_vbe_info(struct vbeinfoblock *vbep)
 {
@@ -554,7 +594,8 @@
 	uint16_t mode;
 	int nmodes = 0, safety = 0;
 	int ddc_caps;
-	uint_t edid_width, edid_height;
+	uint_t width, height;
+	bool edid = false;
 
 	if (!vbe_check())
 		return;
@@ -567,11 +608,15 @@
 		if (ddc_caps & 2)
 			printf(" [DDC2]");
 
-		if (vbe_get_edid(&edid_width, &edid_height))
-			printf(": EDID %dx%d\n", edid_width, edid_height);
+		edid = vbe_get_edid(&width, &height);
+		if (edid)
+			printf(": EDID %dx%d\n", width, height);
 		else
 			printf(": no EDID information\n");
 	}
+	if (!edid)
+		if (vbe_get_flatpanel(&width, &height))
+			printf(": Panel %dx%d\n", width, height);
 
 	memset(vbe, 0, sizeof (vbe));
 	memcpy(vbe->VbeSignature, "VBE2", 4);
@@ -691,19 +736,29 @@
 	}
 }
 
+/*
+ * Try EDID preferred mode, if EDID or the suggested mode is not available,
+ * then try flat panel information.
+ * Fall back to VBE_DEFAULT_MODE.
+ */
 int
 vbe_default_mode(void)
 {
 	int modenum;
-	uint_t edid_width, edid_height;
+	uint_t width, height;
+
+	modenum = 0;
+	if (vbe_get_edid(&width, &height))
+		modenum = vbe_find_mode_xydm(width, height, -1, -1);
 
-	if (vbe_get_edid(&edid_width, &edid_height)) {
-		modenum = vbe_find_mode_xydm(edid_width, edid_height, -1, -1);
-		if (modenum == 0)
-			modenum = vbe_find_mode(VBE_DEFAULT_MODE);
-	} else {
+	if (modenum == 0 &&
+	    vbe_get_flatpanel(&width, &height)) {
+		modenum = vbe_find_mode_xydm(width, height, -1, -1);
+	}
+
+	/* Still no mode? Fall back to default. */
+	if (modenum == 0)
 		modenum = vbe_find_mode(VBE_DEFAULT_MODE);
-	}
 	return (modenum);
 }
 
--- a/usr/src/boot/sys/boot/i386/libi386/vbe.h	Mon Sep 14 20:37:35 2020 +0300
+++ b/usr/src/boot/sys/boot/i386/libi386/vbe.h	Sun Jan 13 19:10:19 2019 +0200
@@ -33,7 +33,10 @@
  * VESA disabled.
  */
 
-#define VBE_DEFAULT_MODE	"800x600"
+#ifndef _VBE_H
+#define	_VBE_H
+
+#define	VBE_DEFAULT_MODE	"800x600"
 
 struct vbeinfoblock {
 	char VbeSignature[4];
@@ -61,8 +64,10 @@
 	uint8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
 	uint8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
 	uint8_t Reserved1;
-	/* Direct Color fields
-	   (required for direct/6 and YUV/7 memory models) */
+	/*
+	 * Direct Color fields
+	 * (required for direct/6 and YUV/7 memory models)
+	 */
 	uint8_t RedMaskSize, RedFieldPosition;
 	uint8_t GreenMaskSize, GreenFieldPosition;
 	uint8_t BlueMaskSize, BlueFieldPosition;
@@ -108,17 +113,16 @@
 
 struct flatpanelinfo
 {
-	uint16_t HorizontalSize;
-	uint16_t VerticalSize;
-	uint16_t PanelType;
-	uint8_t RedBPP;
-	uint8_t GreenBPP;
-	uint8_t BlueBPP;
-	uint8_t ReservedBPP;
-	uint32_t ReservedOffScreenMemSize;
-	uint32_t ReservedOffScreenMemPtr;
-
-	uint8_t Reserved[14];
+	uint16_t HorizontalSize;	/* Horizontal Size in Pixels */
+	uint16_t VerticalSize;		/* Vertical Size in Lines */
+	uint16_t PanelType;		/* Flat Panel Type */
+	uint8_t RedBPP;			/* Red Bits Per Primary */
+	uint8_t GreenBPP;		/* Green Bits Per Primary */
+	uint8_t BlueBPP;		/* Blue Bits Per Primary */
+	uint8_t ReservedBPP;		/* Reserved Bits Per Primary */
+	uint32_t RsvdOffScreenMemSize;	/* Size in KB of Offscreen Memory */
+	uint32_t RsvdOffScreenMemPtr; /* Pointer to reserved offscreen memory */
+	uint8_t Reserved[14];		/* remainder of FPInfo */
 } __packed;
 
 #define	VBE_BASE_MODE		(0x100)		/* VBE 3.0 page 18 */
@@ -143,3 +147,5 @@
 int vbe_get_mode(void);
 int vbe_set_palette(const struct paletteentry *, size_t);
 void vbe_modelist(int);
+
+#endif /* _VBE_H */