Importing sys/dev/videomode

NetBSD provides an in-kernel EDID parser, validator, and printer
along with other useful functions. This code will be re-used by
the Minix fb driver as it is a complete and well tested
implementation.

Change-Id: I46fe3005d9957cd90d4972030ddcce7bc3bd7924
This commit is contained in:
Thomas Cort 2013-07-29 12:21:48 -04:00 committed by Gerrit Code Review
parent 6405d78182
commit bdf33c702a
19 changed files with 3089 additions and 0 deletions

View file

@ -109,6 +109,7 @@
2013/04/23 12:00:00,sys/dev/Makefile
2013/04/23 12:00:00,sys/dev/i2c/Makefile
2013/04/23 12:00:00,sys/dev/i2c/i2c_io.h
2013/07/22 12:00:00,sys/dev/videomode
2012/01/16 18:47:57,sys/lib/libsa
2012/10/17 12:00:00,sys/lib/libz
2012/10/17 12:00:00,sys/Makefile

View file

@ -0,0 +1,15 @@
# $NetBSD: Makefile.ediddevs,v 1.2 2008/10/19 22:05:23 apb Exp $
#
# As per tron@NetBSD.org, the proper procedure is
#
# 1.) Change "src/sys/dev/videomode/ediddevs".
# 2.) Commit "src/sys/dev/videomode/ediddevs".
# 3.) Execute "make -f Makefile.ediddevs" in "src/sys/dev/videomode".
# 4.) Commit "src/sys/dev/videomode/ediddevs.h" and
# "src/sys/dev/videomode/ediddevs_data.h".
.include <bsd.own.mk>
ediddevs.h ediddevs_data.h: ediddevs devlist2h.awk
/bin/rm -f ediddevs.h ediddevs_data.h
${TOOL_AWK} -f devlist2h.awk ediddevs

View file

@ -0,0 +1,17 @@
# $NetBSD: Makefile.videomode,v 1.2 2008/10/19 22:05:23 apb Exp $
#
# As per tron@NetBSD.org, the proper procedure is
#
# 1.) Change "src/sys/dev/videomode/modelines".
# 2.) Commit "src/sys/dev/videomode/modelines".
# 3.) Execute "make -f Makefile.videomode" in "src/sys/dev/videomode".
# 4.) Commit "src/sys/dev/videomode/videomode.c"
.include <bsd.own.mk>
videomode.c: modelines modelines2c.awk
/bin/rm -f videomode.c
${TOOL_AWK} -f modelines2c.awk modelines > videomode.c
test: videomode.c videomode.h test.c
${CC} -I ../../ -o test test.c videomode.c

View file

@ -0,0 +1,192 @@
#! /usr/bin/awk -f
# $NetBSD: devlist2h.awk,v 1.1 2006/05/11 01:49:53 gdamore Exp $
#
# Copyright (c) 1995, 1996 Christopher G. Demetriou
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Christopher G. Demetriou.
# 4. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
BEGIN {
nproducts = nvendors = blanklines = 0
dfile="ediddevs_data.h"
hfile="ediddevs.h"
}
NR == 1 {
VERSION = $0
gsub("\\$", "", VERSION)
gsub(/ $/, "", VERSION)
printf("/*\t$NetBSD" "$\t*/\n\n") > dfile
printf("/*\n") > dfile
printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
> dfile
printf(" *\n") > dfile
printf(" * generated from:\n") > dfile
printf(" *\t%s\n", VERSION) > dfile
printf(" */\n") > dfile
printf("/*\t$NetBSD" "$\t*/\n\n") > hfile
printf("/*\n") > hfile
printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
> hfile
printf(" *\n") > hfile
printf(" * generated from:\n") > hfile
printf(" *\t%s\n", VERSION) > hfile
printf(" */\n") > hfile
next
}
NF > 0 && $1 == "vendor" {
nvendors++
vendorindex[$2] = nvendors; # record index for this name, for later.
vendors[nvendors, 1] = $2; # name/ID
i = 2; f = 3;
printf("#define\tEDID_VENDOR_%s\t\"", vendors[nvendors, 1]) > hfile
# comments
oparen = 0
while (f <= NF) {
if ($f == "#") {
printf("(") > hfile
oparen = 1
f++
continue
}
if (oparen) {
printf("%s", $f) > hfile
f++
continue
}
vendors[nvendors, i] = $f
printf("%s", vendors[nvendors, i]) > hfile
if (f < NF)
printf(" ") > hfile
i++; f++;
}
if (oparen)
printf(")") > hfile
printf("\"") > hfile
printf("\n") > hfile
next
}
NF > 0 && $1 == "product" {
nproducts++
products[nproducts, 1] = $2; # vendor name
products[nproducts, 2] = $3; # product id
products[nproducts, 3] = $4; # id
printf("#define\tEDID_PRODUCT_%s_%s\t%s", products[nproducts, 1],
products[nproducts, 2], products[nproducts, 3]) > hfile
i = 4; f = 5;
ocomment = oparen = 0
if (f <= NF) {
printf("\t\t/* ") > hfile
ocomment = 1;
}
while (f <= NF) {
if ($f == "#") {
printf("(") > hfile
oparen = 1
f++
continue
}
if (oparen) {
printf("%s", $f) > hfile
if (f < NF)
printf(" ") > hfile
f++
continue
}
products[nproducts, i] = $f
printf("%s", products[nproducts, i]) > hfile
if (f < NF)
printf(" ") > hfile
i++; f++;
}
if (oparen)
printf(")") > hfile
if (ocomment)
printf(" */") > hfile
printf("\n") > hfile
next
}
{
if ($0 == "")
blanklines++
if (blanklines != 2 && blanklines != 3)
print $0 > hfile
if (blanklines < 2)
print $0 > dfile
}
END {
# print out the match tables
printf("\n") > dfile
printf("const struct edid_vendor edid_vendors[] = {\n") > dfile
for (i = 1; i <= nvendors; i++) {
printf("\t{") > dfile
printf(" \"%s\", EDID_VENDOR_%s", vendors[i, 1], \
vendors[i, 1]) > dfile
printf(" },\n") > dfile
}
printf("};\n") > dfile
printf("const int edid_nvendors = %d;\n", nvendors) > dfile
printf("\n") > dfile
printf("const struct edid_product edid_products[] = {\n") > dfile
for (i = 1; i <= nproducts; i++) {
printf("\t{\n") > dfile
printf("\t \"%s\", EDID_PRODUCT_%s_%s,\n", \
products[i, 1], products[i, 1], products[i, 2]) > dfile
printf("\t \"") > dfile
j = 4
needspace = 0
while ((i, j) in products) {
if (needspace)
printf(" ") > dfile
printf("%s", products[i, j]) > dfile
needspace = 1
j++
}
printf("\",\n") > dfile
printf("\t},\n") > dfile
}
printf("};\n") > dfile
printf("const int edid_nproducts = %d;\n", nproducts) >dfile
close(dfile)
close(hfile)
}

651
sys/dev/videomode/edid.c Normal file
View file

@ -0,0 +1,651 @@
/* $NetBSD: edid.c,v 1.12 2013/02/08 16:35:10 skrll Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: edid.c,v 1.12 2013/02/08 16:35:10 skrll Exp $");
#include <sys/param.h>
#ifdef __minix
#include <errno.h>
#include <stdio.h>
#include <string.h>
#ifndef aprint_debug
#define aprint_debug if (0) printf
#endif /* !aprint_debug */
#else /* !__minix */
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#endif /* !__minix */
#include <dev/videomode/videomode.h>
#include <dev/videomode/ediddevs.h>
#include <dev/videomode/edidreg.h>
#include <dev/videomode/edidvar.h>
#include <dev/videomode/vesagtf.h>
#define EDIDVERBOSE 1
#define DIVIDE(x,y) (((x) + ((y) / 2)) / (y))
/* These are reversed established timing order */
static const char *_edid_modes[] = {
"1280x1024x75",
"1024x768x75",
"1024x768x70",
"1024x768x60",
"1024x768x87i",
"832x624x74", /* rounding error, 74.55 Hz aka "832x624x75" */
"800x600x75",
"800x600x72",
"800x600x60",
"800x600x56",
"640x480x75",
"640x480x72",
"640x480x67",
"640x480x60",
"720x400x87", /* rounding error, 87.85 Hz aka "720x400x88" */
"720x400x70",
};
#ifdef EDIDVERBOSE
struct edid_vendor {
const char *vendor;
const char *name;
};
struct edid_product {
const char *vendor;
uint16_t product;
const char *name;
};
#include <dev/videomode/ediddevs_data.h>
#endif /* EDIDVERBOSE */
static const char *
edid_findvendor(const char *vendor)
{
#ifdef EDIDVERBOSE
int n;
for (n = 0; n < edid_nvendors; n++)
if (memcmp(edid_vendors[n].vendor, vendor, 3) == 0)
return edid_vendors[n].name;
#endif
return NULL;
}
static const char *
edid_findproduct(const char *vendor, uint16_t product)
{
#ifdef EDIDVERBOSE
int n;
for (n = 0; n < edid_nproducts; n++)
if (edid_products[n].product == product &&
memcmp(edid_products[n].vendor, vendor, 3) == 0)
return edid_products[n].name;
#endif /* EDIDVERBOSE */
return NULL;
}
static void
edid_strchomp(char *ptr)
{
for (;;) {
switch (*ptr) {
case '\0':
return;
case '\r':
case '\n':
*ptr = '\0';
return;
}
ptr++;
}
}
int
edid_is_valid(uint8_t *d)
{
int sum = 0, i;
uint8_t sig[8] = EDID_SIGNATURE;
if (memcmp(d, sig, 8) != 0)
return EINVAL;
for (i = 0; i < 128; i++)
sum += d[i];
if ((sum & 0xff) != 0)
return EINVAL;
return 0;
}
void
edid_print(struct edid_info *edid)
{
int i;
if (edid == NULL)
return;
printf("Vendor: [%s] %s\n", edid->edid_vendor, edid->edid_vendorname);
printf("Product: [%04X] %s\n", edid->edid_product,
edid->edid_productname);
printf("Serial number: %s\n", edid->edid_serial);
printf("Manufactured %d Week %d\n",
edid->edid_year, edid->edid_week);
printf("EDID Version %d.%d\n", edid->edid_version,
edid->edid_revision);
printf("EDID Comment: %s\n", edid->edid_comment);
printf("Video Input: %x\n", edid->edid_video_input);
if (edid->edid_video_input & EDID_VIDEO_INPUT_DIGITAL) {
printf("\tDigital");
if (edid->edid_video_input & EDID_VIDEO_INPUT_DFP1_COMPAT)
printf(" (DFP 1.x compatible)");
printf("\n");
} else {
printf("\tAnalog\n");
switch (EDID_VIDEO_INPUT_LEVEL(edid->edid_video_input)) {
case 0:
printf("\t-0.7, 0.3V\n");
break;
case 1:
printf("\t-0.714, 0.286V\n");
break;
case 2:
printf("\t-1.0, 0.4V\n");
break;
case 3:
printf("\t-0.7, 0.0V\n");
break;
}
if (edid->edid_video_input & EDID_VIDEO_INPUT_BLANK_TO_BLACK)
printf("\tBlank-to-black setup\n");
if (edid->edid_video_input & EDID_VIDEO_INPUT_SEPARATE_SYNCS)
printf("\tSeperate syncs\n");
if (edid->edid_video_input & EDID_VIDEO_INPUT_COMPOSITE_SYNC)
printf("\tComposite sync\n");
if (edid->edid_video_input & EDID_VIDEO_INPUT_SYNC_ON_GRN)
printf("\tSync on green\n");
if (edid->edid_video_input & EDID_VIDEO_INPUT_SERRATION)
printf("\tSerration vsync\n");
}
printf("Gamma: %d.%02d\n",
edid->edid_gamma / 100, edid->edid_gamma % 100);
printf("Max Size: %d cm x %d cm\n",
edid->edid_max_hsize, edid->edid_max_vsize);
printf("Features: %x\n", edid->edid_features);
if (edid->edid_features & EDID_FEATURES_STANDBY)
printf("\tDPMS standby\n");
if (edid->edid_features & EDID_FEATURES_SUSPEND)
printf("\tDPMS suspend\n");
if (edid->edid_features & EDID_FEATURES_ACTIVE_OFF)
printf("\tDPMS active-off\n");
switch (EDID_FEATURES_DISP_TYPE(edid->edid_features)) {
case EDID_FEATURES_DISP_TYPE_MONO:
printf("\tMonochrome\n");
break;
case EDID_FEATURES_DISP_TYPE_RGB:
printf("\tRGB\n");
break;
case EDID_FEATURES_DISP_TYPE_NON_RGB:
printf("\tMulticolor\n");
break;
case EDID_FEATURES_DISP_TYPE_UNDEFINED:
printf("\tUndefined monitor type\n");
break;
}
if (edid->edid_features & EDID_FEATURES_STD_COLOR)
printf("\tStandard color space\n");
if (edid->edid_features & EDID_FEATURES_PREFERRED_TIMING)
printf("\tPreferred timing\n");
if (edid->edid_features & EDID_FEATURES_DEFAULT_GTF)
printf("\tDefault GTF supported\n");
printf("Chroma Info:\n");
printf("\tRed X: 0.%03d\n", edid->edid_chroma.ec_redx);
printf("\tRed Y: 0.%03d\n", edid->edid_chroma.ec_redy);
printf("\tGrn X: 0.%03d\n", edid->edid_chroma.ec_greenx);
printf("\tGrn Y: 0.%03d\n", edid->edid_chroma.ec_greeny);
printf("\tBlu X: 0.%03d\n", edid->edid_chroma.ec_bluex);
printf("\tBlu Y: 0.%03d\n", edid->edid_chroma.ec_bluey);
printf("\tWht X: 0.%03d\n", edid->edid_chroma.ec_whitex);
printf("\tWht Y: 0.%03d\n", edid->edid_chroma.ec_whitey);
if (edid->edid_have_range) {
printf("Range:\n");
printf("\tHorizontal: %d - %d kHz\n",
edid->edid_range.er_min_hfreq,
edid->edid_range.er_max_hfreq);
printf("\tVertical: %d - %d Hz\n",
edid->edid_range.er_min_vfreq,
edid->edid_range.er_max_vfreq);
printf("\tMax Dot Clock: %d MHz\n",
edid->edid_range.er_max_clock);
if (edid->edid_range.er_have_gtf2) {
printf("\tGTF2 hfreq: %d\n",
edid->edid_range.er_gtf2_hfreq);
printf("\tGTF2 C: %d\n", edid->edid_range.er_gtf2_c);
printf("\tGTF2 M: %d\n", edid->edid_range.er_gtf2_m);
printf("\tGTF2 J: %d\n", edid->edid_range.er_gtf2_j);
printf("\tGTF2 K: %d\n", edid->edid_range.er_gtf2_k);
}
}
printf("Video modes:\n");
for (i = 0; i < edid->edid_nmodes; i++) {
printf("\t%dx%d @ %dHz",
edid->edid_modes[i].hdisplay,
edid->edid_modes[i].vdisplay,
DIVIDE(DIVIDE(edid->edid_modes[i].dot_clock * 1000,
edid->edid_modes[i].htotal), edid->edid_modes[i].vtotal));
printf(" (%d %d %d %d %d %d %d",
edid->edid_modes[i].dot_clock,
edid->edid_modes[i].hsync_start,
edid->edid_modes[i].hsync_end,
edid->edid_modes[i].htotal,
edid->edid_modes[i].vsync_start,
edid->edid_modes[i].vsync_end,
edid->edid_modes[i].vtotal);
printf(" %s%sH %s%sV)\n",
edid->edid_modes[i].flags & VID_PHSYNC ? "+" : "",
edid->edid_modes[i].flags & VID_NHSYNC ? "-" : "",
edid->edid_modes[i].flags & VID_PVSYNC ? "+" : "",
edid->edid_modes[i].flags & VID_NVSYNC ? "-" : "");
}
if (edid->edid_preferred_mode)
printf("Preferred mode: %dx%d @ %dHz\n",
edid->edid_preferred_mode->hdisplay,
edid->edid_preferred_mode->vdisplay,
DIVIDE(DIVIDE(edid->edid_preferred_mode->dot_clock * 1000,
edid->edid_preferred_mode->htotal),
edid->edid_preferred_mode->vtotal));
}
static const struct videomode *
edid_mode_lookup_list(const char *name)
{
int i;
for (i = 0; i < videomode_count; i++)
if (strcmp(name, videomode_list[i].name) == 0)
return &videomode_list[i];
return NULL;
}
static struct videomode *
edid_search_mode(struct edid_info *edid, const struct videomode *mode)
{
int refresh, i;
refresh = DIVIDE(DIVIDE(mode->dot_clock * 1000,
mode->htotal), mode->vtotal);
for (i = 0; i < edid->edid_nmodes; i++) {
if (mode->hdisplay == edid->edid_modes[i].hdisplay &&
mode->vdisplay == edid->edid_modes[i].vdisplay &&
refresh == DIVIDE(DIVIDE(
edid->edid_modes[i].dot_clock * 1000,
edid->edid_modes[i].htotal), edid->edid_modes[i].vtotal)) {
return &edid->edid_modes[i];
}
}
return NULL;
}
static int
edid_std_timing(uint8_t *data, struct videomode *vmp)
{
unsigned x, y, f;
const struct videomode *lookup;
char name[80];
if ((data[0] == 1 && data[1] == 1) ||
(data[0] == 0 && data[1] == 0) ||
(data[0] == 0x20 && data[1] == 0x20))
return 0;
x = EDID_STD_TIMING_HRES(data);
switch (EDID_STD_TIMING_RATIO(data)) {
case EDID_STD_TIMING_RATIO_16_10:
y = x * 10 / 16;
break;
case EDID_STD_TIMING_RATIO_4_3:
y = x * 3 / 4;
break;
case EDID_STD_TIMING_RATIO_5_4:
y = x * 4 / 5;
break;
case EDID_STD_TIMING_RATIO_16_9:
default:
y = x * 9 / 16;
break;
}
f = EDID_STD_TIMING_VFREQ(data);
/* first try to lookup the mode as a DMT timing */
snprintf(name, sizeof(name), "%dx%dx%d", x, y, f);
if ((lookup = edid_mode_lookup_list(name)) != NULL) {
*vmp = *lookup;
} else {
/* failing that, calculate it using gtf */
/*
* Hmm. I'm not using alternate GTF timings, which
* could, in theory, be present.
*/
vesagtf_mode(x, y, f, vmp);
}
return 1;
}
static int
edid_det_timing(uint8_t *data, struct videomode *vmp)
{
unsigned hactive, hblank, hsyncwid, hsyncoff;
unsigned vactive, vblank, vsyncwid, vsyncoff;
uint8_t flags;
flags = EDID_DET_TIMING_FLAGS(data);
/* we don't support stereo modes (for now) */
if (flags & (EDID_DET_TIMING_FLAG_STEREO |
EDID_DET_TIMING_FLAG_STEREO_MODE))
return 0;
vmp->dot_clock = EDID_DET_TIMING_DOT_CLOCK(data) / 1000;
hactive = EDID_DET_TIMING_HACTIVE(data);
hblank = EDID_DET_TIMING_HBLANK(data);
hsyncwid = EDID_DET_TIMING_HSYNC_WIDTH(data);
hsyncoff = EDID_DET_TIMING_HSYNC_OFFSET(data);
vactive = EDID_DET_TIMING_VACTIVE(data);
vblank = EDID_DET_TIMING_VBLANK(data);
vsyncwid = EDID_DET_TIMING_VSYNC_WIDTH(data);
vsyncoff = EDID_DET_TIMING_VSYNC_OFFSET(data);
/* Borders are contained within the blank areas. */
vmp->hdisplay = hactive;
vmp->htotal = hactive + hblank;
vmp->hsync_start = hactive + hsyncoff;
vmp->hsync_end = vmp->hsync_start + hsyncwid;
vmp->vdisplay = vactive;
vmp->vtotal = vactive + vblank;
vmp->vsync_start = vactive + vsyncoff;
vmp->vsync_end = vmp->vsync_start + vsyncwid;
vmp->flags = 0;
if (flags & EDID_DET_TIMING_FLAG_INTERLACE)
vmp->flags |= VID_INTERLACE;
if (flags & EDID_DET_TIMING_FLAG_HSYNC_POSITIVE)
vmp->flags |= VID_PHSYNC;
else
vmp->flags |= VID_NHSYNC;
if (flags & EDID_DET_TIMING_FLAG_VSYNC_POSITIVE)
vmp->flags |= VID_PVSYNC;
else
vmp->flags |= VID_NVSYNC;
return 1;
}
static void
edid_block(struct edid_info *edid, uint8_t *data)
{
int i;
struct videomode mode, *exist_mode;
if (EDID_BLOCK_IS_DET_TIMING(data)) {
if (!edid_det_timing(data, &mode))
return;
/* Does this mode already exist? */
exist_mode = edid_search_mode(edid, &mode);
if (exist_mode != NULL) {
*exist_mode = mode;
if (edid->edid_preferred_mode == NULL)
edid->edid_preferred_mode = exist_mode;
} else {
edid->edid_modes[edid->edid_nmodes] = mode;
if (edid->edid_preferred_mode == NULL)
edid->edid_preferred_mode =
&edid->edid_modes[edid->edid_nmodes];
edid->edid_nmodes++;
}
return;
}
switch (EDID_BLOCK_TYPE(data)) {
case EDID_DESC_BLOCK_TYPE_SERIAL:
memcpy(edid->edid_serial, data + EDID_DESC_ASCII_DATA_OFFSET,
EDID_DESC_ASCII_DATA_LEN);
edid->edid_serial[sizeof(edid->edid_serial) - 1] = 0;
break;
case EDID_DESC_BLOCK_TYPE_ASCII:
memcpy(edid->edid_comment, data + EDID_DESC_ASCII_DATA_OFFSET,
EDID_DESC_ASCII_DATA_LEN);
edid->edid_comment[sizeof(edid->edid_comment) - 1] = 0;
break;
case EDID_DESC_BLOCK_TYPE_RANGE:
edid->edid_have_range = 1;
edid->edid_range.er_min_vfreq = EDID_DESC_RANGE_MIN_VFREQ(data);
edid->edid_range.er_max_vfreq = EDID_DESC_RANGE_MAX_VFREQ(data);
edid->edid_range.er_min_hfreq = EDID_DESC_RANGE_MIN_HFREQ(data);
edid->edid_range.er_max_hfreq = EDID_DESC_RANGE_MAX_HFREQ(data);
edid->edid_range.er_max_clock = EDID_DESC_RANGE_MAX_CLOCK(data);
if (!EDID_DESC_RANGE_HAVE_GTF2(data))
break;
edid->edid_range.er_have_gtf2 = 1;
edid->edid_range.er_gtf2_hfreq =
EDID_DESC_RANGE_GTF2_HFREQ(data);
edid->edid_range.er_gtf2_c = EDID_DESC_RANGE_GTF2_C(data);
edid->edid_range.er_gtf2_m = EDID_DESC_RANGE_GTF2_M(data);
edid->edid_range.er_gtf2_j = EDID_DESC_RANGE_GTF2_J(data);
edid->edid_range.er_gtf2_k = EDID_DESC_RANGE_GTF2_K(data);
break;
case EDID_DESC_BLOCK_TYPE_NAME:
/* copy the product name into place */
memcpy(edid->edid_productname,
data + EDID_DESC_ASCII_DATA_OFFSET,
EDID_DESC_ASCII_DATA_LEN);
break;
case EDID_DESC_BLOCK_TYPE_STD_TIMING:
data += EDID_DESC_STD_TIMING_START;
for (i = 0; i < EDID_DESC_STD_TIMING_COUNT; i++) {
if (edid_std_timing(data, &mode)) {
/* Does this mode already exist? */
exist_mode = edid_search_mode(edid, &mode);
if (exist_mode == NULL) {
edid->edid_modes[edid->edid_nmodes] =
mode;
edid->edid_nmodes++;
}
}
data += 2;
}
break;
case EDID_DESC_BLOCK_TYPE_COLOR_POINT:
/* XXX: not implemented yet */
break;
}
}
/*
* Gets EDID version in BCD, e.g. EDID v1.3 returned as 0x0103
*/
int
edid_parse(uint8_t *data, struct edid_info *edid)
{
uint16_t manfid, estmodes;
const struct videomode *vmp;
int i;
const char *name;
int max_dotclock = 0;
int mhz;
if (edid_is_valid(data) != 0)
return -1;
/* get product identification */
manfid = EDID_VENDOR_ID(data);
edid->edid_vendor[0] = EDID_MANFID_0(manfid);
edid->edid_vendor[1] = EDID_MANFID_1(manfid);
edid->edid_vendor[2] = EDID_MANFID_2(manfid);
edid->edid_vendor[3] = 0; /* null terminate for convenience */
edid->edid_product = data[EDID_OFFSET_PRODUCT_ID] +
(data[EDID_OFFSET_PRODUCT_ID + 1] << 8);
name = edid_findvendor(edid->edid_vendor);
if (name != NULL)
strlcpy(edid->edid_vendorname, name,
sizeof(edid->edid_vendorname));
else
edid->edid_vendorname[0] = '\0';
name = edid_findproduct(edid->edid_vendor, edid->edid_product);
if (name != NULL)
strlcpy(edid->edid_productname, name,
sizeof(edid->edid_productname));
else
edid->edid_productname[0] = '\0';
snprintf(edid->edid_serial, sizeof(edid->edid_serial), "%08x",
EDID_SERIAL_NUMBER(data));
edid->edid_week = EDID_WEEK(data);
edid->edid_year = EDID_YEAR(data);
/* get edid revision */
edid->edid_version = EDID_VERSION(data);
edid->edid_revision = EDID_REVISION(data);
edid->edid_video_input = EDID_VIDEO_INPUT(data);
edid->edid_max_hsize = EDID_MAX_HSIZE(data);
edid->edid_max_vsize = EDID_MAX_VSIZE(data);
edid->edid_gamma = EDID_GAMMA(data);
edid->edid_features = EDID_FEATURES(data);
edid->edid_chroma.ec_redx = EDID_CHROMA_REDX(data);
edid->edid_chroma.ec_redy = EDID_CHROMA_REDX(data);
edid->edid_chroma.ec_greenx = EDID_CHROMA_GREENX(data);
edid->edid_chroma.ec_greeny = EDID_CHROMA_GREENY(data);
edid->edid_chroma.ec_bluex = EDID_CHROMA_BLUEX(data);
edid->edid_chroma.ec_bluey = EDID_CHROMA_BLUEY(data);
edid->edid_chroma.ec_whitex = EDID_CHROMA_WHITEX(data);
edid->edid_chroma.ec_whitey = EDID_CHROMA_WHITEY(data);
/* lookup established modes */
edid->edid_nmodes = 0;
edid->edid_preferred_mode = NULL;
estmodes = EDID_EST_TIMING(data);
/* Iterate in esztablished timing order */
for (i = 15; i >= 0; i--) {
if (estmodes & (1 << i)) {
vmp = edid_mode_lookup_list(_edid_modes[i]);
if (vmp != NULL) {
edid->edid_modes[edid->edid_nmodes] = *vmp;
edid->edid_nmodes++;
}
#ifdef DIAGNOSTIC
else
printf("no data for est. mode %s\n",
_edid_modes[i]);
#endif
}
}
/* do standard timing section */
for (i = 0; i < EDID_STD_TIMING_COUNT; i++) {
struct videomode mode, *exist_mode;
if (edid_std_timing(data + EDID_OFFSET_STD_TIMING + i * 2,
&mode)) {
/* Does this mode already exist? */
exist_mode = edid_search_mode(edid, &mode);
if (exist_mode == NULL) {
edid->edid_modes[edid->edid_nmodes] = mode;
edid->edid_nmodes++;
}
}
}
/* do detailed timings and descriptors */
for (i = 0; i < EDID_BLOCK_COUNT; i++) {
edid_block(edid, data + EDID_OFFSET_DESC_BLOCK +
i * EDID_BLOCK_SIZE);
}
edid_strchomp(edid->edid_vendorname);
edid_strchomp(edid->edid_productname);
edid_strchomp(edid->edid_serial);
edid_strchomp(edid->edid_comment);
/*
* XXX
* some monitors lie about their maximum supported dot clock
* by claiming to support modes which need a higher dot clock
* than the stated maximum.
* For sanity's sake we bump it to the highest dot clock we find
* in the list of supported modes
*/
for (i = 0; i < edid->edid_nmodes; i++)
if (edid->edid_modes[i].dot_clock > max_dotclock)
max_dotclock = edid->edid_modes[i].dot_clock;
aprint_debug("max_dotclock according to supported modes: %d\n",
max_dotclock);
mhz = (max_dotclock + 999) / 1000;
if (edid->edid_have_range) {
if (mhz > edid->edid_range.er_max_clock)
edid->edid_range.er_max_clock = mhz;
} else
edid->edid_range.er_max_clock = mhz;
return 0;
}

105
sys/dev/videomode/ediddevs Normal file
View file

@ -0,0 +1,105 @@
$NetBSD: ediddevs,v 1.3 2009/01/21 14:40:02 jnemeth Exp $
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Use "make -f Makefile.ediddevs" to regenerate ediddevs.h and ediddevs_data.h
*/
/*
* List of known EDID monitor vendors
*
* These are standard PNP ids, managed (apparently) by Microsoft.
* It is likely that this list is grossly incomplete.
*/
vendor AAC AcerView
vendor AOC AOC
vendor APP Apple Computer
vendor AST AST Research
vendor CPL Compal
vendor CPQ Compaq
vendor CTX CTX
vendor DEC DEC
vendor DEL Dell
vendor DPC Delta
vendor DWE Daewoo
vendor EIZ EIZO
vendor ELS ELSA
vendor EPI Envision
vendor FCM Funai
vendor FUJ Fujitsu
vendor GSM LG Electronics
vendor GWY Gateway 2000
vendor HEI Hyundai
vendor HIT Hitachi
vendor HSL Hansol
vendor HTC Hitachi/Nissei
vendor HWP HP
vendor IBM IBM
vendor ICL Fujitsu ICL
vendor IVM Iiyama
vendor KDS Korea Data Systems
vendor MEI Panasonic
vendor MEL Mitsubishi Electronics
vendor NAN Nanao
vendor NEC NEC
vendor NOK Nokia Data
vendor PHL Philips
vendor REL Relisys
vendor SAM Samsung
vendor SGI SGI
vendor SNY Sony
vendor SRC Shamrock
vendor SUN Sun Microsystems
vendor TAT Tatung
vendor TOS Toshiba
vendor TSB Toshiba
vendor VSC ViewSonic
vendor ZCM Zenith
/*
* List of known products, grouped and sorted by vendor.
*
* EDID version 1.3 requires that monitors expose the monitor name with
* the ASCII descriptor type 0xFC, so for monitors using that block, this
* information is redundant, and there is not point in listing them here,
* unless it is desired to have a symbolic macro to detect the monitor in
* special handling code or somesuch.
*/
/* Dell - this exists for now as a sample. I don't have one of these. */
product DEL ULTRASCAN14XE_REVA 0x139A Ultrascan 14XE
product DEL ULTRASCAN14XE_REVB 0x139B Ultrascan 14XE
/* ViewSonic */
product VSC 17GS 0x0c00 17GS
product VSC 17PS 0x0c0f 17PS

View file

@ -0,0 +1,91 @@
/* $NetBSD: ediddevs.h,v 1.2 2007/03/07 18:47:55 macallan Exp $ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* generated from:
* NetBSD: ediddevs,v 1.1 2006/05/11 01:49:53 gdamore Exp
*/
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define EDID_VENDOR_AAC "AcerView"
#define EDID_VENDOR_AOC "AOC"
#define EDID_VENDOR_APP "Apple Computer"
#define EDID_VENDOR_AST "AST Research"
#define EDID_VENDOR_CPL "Compal"
#define EDID_VENDOR_CPQ "Compaq"
#define EDID_VENDOR_CTX "CTX"
#define EDID_VENDOR_DEC "DEC"
#define EDID_VENDOR_DEL "Dell"
#define EDID_VENDOR_DPC "Delta"
#define EDID_VENDOR_DWE "Daewoo"
#define EDID_VENDOR_EIZ "EIZO"
#define EDID_VENDOR_ELS "ELSA"
#define EDID_VENDOR_EPI "Envision"
#define EDID_VENDOR_FCM "Funai"
#define EDID_VENDOR_FUJ "Fujitsu"
#define EDID_VENDOR_GSM "LG Electronics"
#define EDID_VENDOR_GWY "Gateway 2000"
#define EDID_VENDOR_HEI "Hyundai"
#define EDID_VENDOR_HIT "Hitachi"
#define EDID_VENDOR_HSL "Hansol"
#define EDID_VENDOR_HTC "Hitachi/Nissei"
#define EDID_VENDOR_HWP "HP"
#define EDID_VENDOR_IBM "IBM"
#define EDID_VENDOR_ICL "Fujitsu ICL"
#define EDID_VENDOR_IVM "Iiyama"
#define EDID_VENDOR_KDS "Korea Data Systems"
#define EDID_VENDOR_MEI "Panasonic"
#define EDID_VENDOR_MEL "Mitsubishi Electronics"
#define EDID_VENDOR_NAN "Nanao"
#define EDID_VENDOR_NEC "NEC"
#define EDID_VENDOR_NOK "Nokia Data"
#define EDID_VENDOR_PHL "Philips"
#define EDID_VENDOR_REL "Relisys"
#define EDID_VENDOR_SAM "Samsung"
#define EDID_VENDOR_SGI "SGI"
#define EDID_VENDOR_SNY "Sony"
#define EDID_VENDOR_SRC "Shamrock"
#define EDID_VENDOR_SUN "Sun Microsystems"
#define EDID_VENDOR_TAT "Tatung"
#define EDID_VENDOR_TOS "Toshiba"
#define EDID_VENDOR_TSB "Toshiba"
#define EDID_VENDOR_VSC "ViewSonic"
#define EDID_VENDOR_ZCM "Zenith"
/* Dell - this exists for now as a sample. I don't have one of these. */
#define EDID_PRODUCT_DEL_ULTRASCAN14XE_REVA 0x139A /* Ultrascan 14XE */
#define EDID_PRODUCT_DEL_ULTRASCAN14XE_REVB 0x139B /* Ultrascan 14XE */
/* ViewSonic */
#define EDID_PRODUCT_VSC_17GS 0x0c00 /* 17GS */
#define EDID_PRODUCT_VSC_17PS 0x0c0f /* 17PS */

View file

@ -0,0 +1,107 @@
/* $NetBSD: ediddevs_data.h,v 1.2 2007/03/07 18:47:13 macallan Exp $ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* generated from:
* NetBSD: ediddevs,v 1.1 2006/05/11 01:49:53 gdamore Exp
*/
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const struct edid_vendor edid_vendors[] = {
{ "AAC", EDID_VENDOR_AAC },
{ "AOC", EDID_VENDOR_AOC },
{ "APP", EDID_VENDOR_APP },
{ "AST", EDID_VENDOR_AST },
{ "CPL", EDID_VENDOR_CPL },
{ "CPQ", EDID_VENDOR_CPQ },
{ "CTX", EDID_VENDOR_CTX },
{ "DEC", EDID_VENDOR_DEC },
{ "DEL", EDID_VENDOR_DEL },
{ "DPC", EDID_VENDOR_DPC },
{ "DWE", EDID_VENDOR_DWE },
{ "EIZ", EDID_VENDOR_EIZ },
{ "ELS", EDID_VENDOR_ELS },
{ "EPI", EDID_VENDOR_EPI },
{ "FCM", EDID_VENDOR_FCM },
{ "FUJ", EDID_VENDOR_FUJ },
{ "GSM", EDID_VENDOR_GSM },
{ "GWY", EDID_VENDOR_GWY },
{ "HEI", EDID_VENDOR_HEI },
{ "HIT", EDID_VENDOR_HIT },
{ "HSL", EDID_VENDOR_HSL },
{ "HTC", EDID_VENDOR_HTC },
{ "HWP", EDID_VENDOR_HWP },
{ "IBM", EDID_VENDOR_IBM },
{ "ICL", EDID_VENDOR_ICL },
{ "IVM", EDID_VENDOR_IVM },
{ "KDS", EDID_VENDOR_KDS },
{ "MEI", EDID_VENDOR_MEI },
{ "MEL", EDID_VENDOR_MEL },
{ "NAN", EDID_VENDOR_NAN },
{ "NEC", EDID_VENDOR_NEC },
{ "NOK", EDID_VENDOR_NOK },
{ "PHL", EDID_VENDOR_PHL },
{ "REL", EDID_VENDOR_REL },
{ "SAM", EDID_VENDOR_SAM },
{ "SGI", EDID_VENDOR_SGI },
{ "SNY", EDID_VENDOR_SNY },
{ "SRC", EDID_VENDOR_SRC },
{ "SUN", EDID_VENDOR_SUN },
{ "TAT", EDID_VENDOR_TAT },
{ "TOS", EDID_VENDOR_TOS },
{ "TSB", EDID_VENDOR_TSB },
{ "VSC", EDID_VENDOR_VSC },
{ "ZCM", EDID_VENDOR_ZCM },
};
const int edid_nvendors = 44;
const struct edid_product edid_products[] = {
{
"DEL", EDID_PRODUCT_DEL_ULTRASCAN14XE_REVA,
"Ultrascan 14XE",
},
{
"DEL", EDID_PRODUCT_DEL_ULTRASCAN14XE_REVB,
"Ultrascan 14XE",
},
{
"VSC", EDID_PRODUCT_VSC_17GS,
"17GS",
},
{
"VSC", EDID_PRODUCT_VSC_17PS,
"17PS",
},
};
const int edid_nproducts = 4;

253
sys/dev/videomode/edidreg.h Normal file
View file

@ -0,0 +1,253 @@
/* $NetBSD: edidreg.h,v 1.3 2011/03/30 18:49:56 jdc Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_VIDEOMODE_EDIDREG_H
#define _DEV_VIDEOMODE_EDIDREG_H
#define EDID_OFFSET_SIGNATURE 0x00
#define EDID_OFFSET_MANUFACTURER_ID 0x08
#define EDID_OFFSET_PRODUCT_ID 0x0a
#define EDID_OFFSET_SERIAL_NUMBER 0x0c
#define EDID_OFFSET_MANUFACTURE_WEEK 0x10
#define EDID_OFFSET_MANUFACTURE_YEAR 0x11
#define EDID_OFFSET_VERSION 0x12
#define EDID_OFFSET_REVISION 0x13
#define EDID_OFFSET_VIDEO_INPUT 0x14
#define EDID_OFFSET_MAX_HSIZE 0x15 /* in cm */
#define EDID_OFFSET_MAX_VSIZE 0x16
#define EDID_OFFSET_GAMMA 0x17
#define EDID_OFFSET_FEATURE 0x18
#define EDID_OFFSET_CHROMA 0x19
#define EDID_OFFSET_EST_TIMING_1 0x23
#define EDID_OFFSET_EST_TIMING_2 0x24
#define EDID_OFFSET_MFG_TIMING 0x25
#define EDID_OFFSET_STD_TIMING 0x26
#define EDID_OFFSET_DESC_BLOCK 0x36
#define EDID_SIGNATURE { 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0 }
/* assume x is 16-bit value */
#define EDID_VENDOR_ID(ptr) ((((ptr)[8]) << 8) + ptr[9])
#define EDID_MANFID_0(x) ((((x) >> 10) & 0x1f) + '@')
#define EDID_MANFID_1(x) ((((x) >> 5) & 0x1f) + '@')
#define EDID_MANFID_2(x) ((((x) >> 0) & 0x1f) + '@')
/* relative to edid block */
#define EDID_PRODUCT_ID(ptr) (((ptr)[10]) | (((ptr)[11]) << 8))
#define EDID_SERIAL_NUMBER(ptr) (((ptr)[12] << 24) + \
((ptr)[13] << 16) + \
((ptr)[14] << 8) + \
(ptr)[15])
/* relative to edid block */
#define EDID_WEEK(ptr) ((ptr)[16])
#define EDID_YEAR(ptr) (((ptr)[17]) + 1990)
#define EDID_VERSION(ptr) ((ptr)[18])
#define EDID_REVISION(ptr) ((ptr)[19])
#define EDID_VIDEO_INPUT(ptr) ((ptr)[20])
#define EDID_VIDEO_INPUT_DIGITAL 0x80
/* if INPUT_BIT_DIGITAL set */
#define EDID_VIDEO_INPUT_DFP1_COMPAT 0x01
/* if INPUT_BIT_DIGITAL not set */
#define EDID_VIDEO_INPUT_BLANK_TO_BLACK 0x10
#define EDID_VIDEO_INPUT_SEPARATE_SYNCS 0x08
#define EDID_VIDEO_INPUT_COMPOSITE_SYNC 0x04
#define EDID_VIDEO_INPUT_SYNC_ON_GRN 0x02
#define EDID_VIDEO_INPUT_SERRATION 0x01
#define EDID_VIDEO_INPUT_LEVEL(x) (((x) & 0x60) >> 5)
/* meanings of level bits are as follows, I don't know names */
/* 0 = 0.7,0.3, 1 = 0.714,0.286, 2 = 1.0,0.4, 3 = 0.7,0.0 */
/* relative to edid block */
#define EDID_MAX_HSIZE(ptr) ((ptr)[21]) /* cm */
#define EDID_MAX_VSIZE(ptr) ((ptr)[22]) /* cm */
/* gamma is scaled by 100 (avoid fp), e.g. 213 == 2.13 */
#define _GAMMA(x) ((x) == 0xff ? 100 : ((x) + 100))
#define EDID_GAMMA(ptr) _GAMMA(ptr[23])
#define EDID_FEATURES(ptr) ((ptr)[24])
#define EDID_FEATURES_STANDBY 0x80
#define EDID_FEATURES_SUSPEND 0x40
#define EDID_FEATURES_ACTIVE_OFF 0x20
#define EDID_FEATURES_DISP_TYPE(x) (((x) & 0x18) >> 3)
#define EDID_FEATURES_DISP_TYPE_MONO 0
#define EDID_FEATURES_DISP_TYPE_RGB 1
#define EDID_FEATURES_DISP_TYPE_NON_RGB 2
#define EDID_FEATURES_DISP_TYPE_UNDEFINED 3
#define EDID_FEATURES_STD_COLOR 0x04
#define EDID_FEATURES_PREFERRED_TIMING 0x02
#define EDID_FEATURES_DEFAULT_GTF 0x01
/* chroma values 0.0 - 0.999 scaled as 0-999 */
#define _CHLO(byt, shft) (((byt) >> (shft)) & 0x3)
#define _CHHI(byt) ((byt) << 2)
#define _CHHILO(ptr, l, s, h) (_CHLO((ptr)[l], s) | _CHHI((ptr)[h]))
#define _CHROMA(ptr, l, s, h) ((_CHHILO(ptr, l, s, h) * 1000) / 1024)
#define EDID_CHROMA_REDX(ptr) (_CHROMA(ptr, 25, 6, 27))
#define EDID_CHROMA_REDY(ptr) (_CHROMA(ptr, 25, 4, 28))
#define EDID_CHROMA_GREENX(ptr) (_CHROMA(ptr, 25, 2, 29))
#define EDID_CHROMA_GREENY(ptr) (_CHROMA(ptr, 25, 0, 30))
#define EDID_CHROMA_BLUEX(ptr) (_CHROMA(ptr, 26, 6, 31))
#define EDID_CHROMA_BLUEY(ptr) (_CHROMA(ptr, 26, 4, 32))
#define EDID_CHROMA_WHITEX(ptr) (_CHROMA(ptr, 26, 2, 33))
#define EDID_CHROMA_WHITEY(ptr) (_CHROMA(ptr, 26, 0, 34))
/* relative to edid block */
#define EDID_EST_TIMING(ptr) (((ptr)[35] << 8) | (ptr)[36])
#define EDID_EST_TIMING_720_400_70 0x8000 /* 720x400 @ 70Hz */
#define EDID_EST_TIMING_720_400_88 0x4000 /* 720x400 @ 88Hz */
#define EDID_EST_TIMING_640_480_60 0x2000 /* 640x480 @ 60Hz */
#define EDID_EST_TIMING_640_480_67 0x1000 /* 640x480 @ 67Hz */
#define EDID_EST_TIMING_640_480_72 0x0800 /* 640x480 @ 72Hz */
#define EDID_EST_TIMING_640_480_75 0x0400 /* 640x480 @ 75Hz */
#define EDID_EST_TIMING_800_600_56 0x0200 /* 800x600 @ 56Hz */
#define EDID_EST_TIMING_800_600_60 0x0100 /* 800x600 @ 60Hz */
#define EDID_EST_TIMING_800_600_72 0x0080 /* 800x600 @ 72Hz */
#define EDID_EST_TIMING_800_600_75 0x0040 /* 800x600 @ 75Hz */
#define EDID_EST_TIMING_832_624_75 0x0020 /* 832x624 @ 75Hz */
#define EDID_EST_TIMING_1024_768_87I 0x0010 /* 1024x768i @ 87Hz */
#define EDID_EST_TIMING_1024_768_60 0x0008 /* 1024x768 @ 60Hz */
#define EDID_EST_TIMING_1024_768_70 0x0004 /* 1024x768 @ 70Hz */
#define EDID_EST_TIMING_1024_768_75 0x0002 /* 1024x768 @ 75Hz */
#define EDID_EST_TIMING_1280_1024_75 0x0001 /* 1280x1024 @ 75Hz */
/*
* N.B.: ptr is relative to standard timing block - used for standard timing
* descriptors as well as standard timings section of edid!
*/
#define EDID_STD_TIMING_HRES(ptr) ((((ptr)[0]) * 8) + 248)
#define EDID_STD_TIMING_VFREQ(ptr) ((((ptr)[1]) & 0x3f) + 60)
#define EDID_STD_TIMING_RATIO(ptr) ((ptr)[1] & 0xc0)
#define EDID_STD_TIMING_RATIO_16_10 0x00
#define EDID_STD_TIMING_RATIO_4_3 0x40
#define EDID_STD_TIMING_RATIO_5_4 0x80
#define EDID_STD_TIMING_RATIO_16_9 0xc0
#define EDID_STD_TIMING_SIZE 16
#define EDID_STD_TIMING_COUNT 8
/*
* N.B.: ptr is relative to descriptor block start
*/
#define EDID_BLOCK_SIZE 18
#define EDID_BLOCK_COUNT 4
/* detailed timing block.... what a mess */
#define EDID_BLOCK_IS_DET_TIMING(ptr) ((ptr)[0] | (ptr)[1])
#define EDID_DET_TIMING_DOT_CLOCK(ptr) (((ptr)[0] | ((ptr)[1] << 8)) * 10000)
#define _HACT_LO(ptr) ((ptr)[2])
#define _HBLK_LO(ptr) ((ptr)[3])
#define _HACT_HI(ptr) (((ptr)[4] & 0xf0) << 4)
#define _HBLK_HI(ptr) (((ptr)[4] & 0x0f) << 8)
#define EDID_DET_TIMING_HACTIVE(ptr) (_HACT_LO(ptr) | _HACT_HI(ptr))
#define EDID_DET_TIMING_HBLANK(ptr) (_HBLK_LO(ptr) | _HBLK_HI(ptr))
#define _VACT_LO(ptr) ((ptr)[5])
#define _VBLK_LO(ptr) ((ptr)[6])
#define _VACT_HI(ptr) (((ptr)[7] & 0xf0) << 4)
#define _VBLK_HI(ptr) (((ptr)[7] & 0x0f) << 8)
#define EDID_DET_TIMING_VACTIVE(ptr) (_VACT_LO(ptr) | _VACT_HI(ptr))
#define EDID_DET_TIMING_VBLANK(ptr) (_VBLK_LO(ptr) | _VBLK_HI(ptr))
#define _HOFF_LO(ptr) ((ptr)[8])
#define _HWID_LO(ptr) ((ptr)[9])
#define _VOFF_LO(ptr) ((ptr)[10] >> 4)
#define _VWID_LO(ptr) ((ptr)[10] & 0xf)
#define _HOFF_HI(ptr) (((ptr)[11] & 0xc0) << 2)
#define _HWID_HI(ptr) (((ptr)[11] & 0x30) << 4)
#define _VOFF_HI(ptr) (((ptr)[11] & 0x0c) << 2)
#define _VWID_HI(ptr) (((ptr)[11] & 0x03) << 4)
#define EDID_DET_TIMING_HSYNC_OFFSET(ptr) (_HOFF_LO(ptr) | _HOFF_HI(ptr))
#define EDID_DET_TIMING_HSYNC_WIDTH(ptr) (_HWID_LO(ptr) | _HWID_HI(ptr))
#define EDID_DET_TIMING_VSYNC_OFFSET(ptr) (_VOFF_LO(ptr) | _VOFF_HI(ptr))
#define EDID_DET_TIMING_VSYNC_WIDTH(ptr) (_VWID_LO(ptr) | _VWID_HI(ptr))
#define _HSZ_LO(ptr) ((ptr)[12])
#define _VSZ_LO(ptr) ((ptr)[13])
#define _HSZ_HI(ptr) (((ptr)[14] & 0xf0) << 4)
#define _VSZ_HI(ptr) (((ptr)[14] & 0x0f) << 8)
#define EDID_DET_TIMING_HSIZE(ptr) (_HSZ_LO(ptr) | _HSZ_HI(ptr))
#define EDID_DET_TIMING_VSIZE(ptr) (_VSZ_LO(ptr) | _VSZ_HI(ptr))
#define EDID_DET_TIMING_HBORDER(ptr) ((ptr)[15])
#define EDID_DET_TIMING_VBORDER(ptr) ((ptr)[16])
#define EDID_DET_TIMING_FLAGS(ptr) ((ptr)[17])
#define EDID_DET_TIMING_FLAG_INTERLACE 0x80
#define EDID_DET_TIMING_FLAG_STEREO 0x60 /* stereo or not */
#define EDID_DET_TIMING_FLAG_SYNC_SEPARATE 0x18
#define EDID_DET_TIMING_FLAG_VSYNC_POSITIVE 0x04
#define EDID_DET_TIMING_FLAG_HSYNC_POSITIVE 0x02
#define EDID_DET_TIMING_FLAG_STEREO_MODE 0x01 /* stereo mode */
/* N.B.: these tests assume that we already checked for detailed timing! */
#define EDID_BLOCK_TYPE(ptr) ((ptr)[3])
#define EDID_DESC_BLOCK_SIZE 18
#define EDID_DESC_BLOCK_TYPE_SERIAL 0xFF
#define EDID_DESC_BLOCK_TYPE_ASCII 0xFE
#define EDID_DESC_BLOCK_TYPE_RANGE 0xFD
#define EDID_DESC_BLOCK_TYPE_NAME 0xFC
#define EDID_DESC_BLOCK_TYPE_COLOR_POINT 0xFB
#define EDID_DESC_BLOCK_TYPE_STD_TIMING 0xFA
/* used for descriptors 0xFF, 0xFE, and 0xFC */
#define EDID_DESC_ASCII_DATA_OFFSET 5
#define EDID_DESC_ASCII_DATA_LEN 13
#define EDID_DESC_RANGE_MIN_VFREQ(ptr) ((ptr)[5]) /* Hz */
#define EDID_DESC_RANGE_MAX_VFREQ(ptr) ((ptr)[6]) /* Hz */
#define EDID_DESC_RANGE_MIN_HFREQ(ptr) ((ptr)[7]) /* kHz */
#define EDID_DESC_RANGE_MAX_HFREQ(ptr) ((ptr)[8]) /* kHz */
#define EDID_DESC_RANGE_MAX_CLOCK(ptr) (((ptr)[9]) * 10) /* MHz */
#define EDID_DESC_RANGE_HAVE_GTF2(ptr) (((ptr)[10]) == 0x02)
#define EDID_DESC_RANGE_GTF2_HFREQ(ptr) (((ptr)[12]) * 2)
#define EDID_DESC_RANGE_GTF2_C(ptr) (((ptr)[13]) / 2)
#define EDID_DESC_RANGE_GTF2_M(ptr) ((ptr)[14] + ((ptr)[15] << 8))
#define EDID_DESC_RANGE_GTF2_K(ptr) ((ptr)[16])
#define EDID_DESC_RANGE_GTF2_J(ptr) ((ptr)[17] / 2)
#define EDID_DESC_COLOR_WHITEX(ptr)
#define EDID_DESC_COLOR_WHITE_INDEX_1(ptr) ((ptr)[5])
#define EDID_DESC_COLOR_WHITEX_1(ptr) _CHROMA(ptr, 6, 2, 7)
#define EDID_DESC_COLOR_WHITEY_1(ptr) _CHROMA(ptr, 6, 0, 8)
#define EDID_DESC_COLOR_GAMMA_1(ptr) _GAMMA(ptr[9])
#define EDID_DESC_COLOR_WHITE_INDEX_2(ptr) ((ptr)[10])
#define EDID_DESC_COLOR_WHITEX_2(ptr) _CHROMA(ptr, 11, 2, 12)
#define EDID_DESC_COLOR_WHITEY_2(ptr) _CHROMA(ptr, 11, 0, 13)
#define EDID_DESC_COLOR_GAMMA_2(ptr) _GAMMA(ptr[14])
#define EDID_DESC_STD_TIMING_START 5
#define EDID_DESC_STD_TIMING_COUNT 6
#endif /* _DEV_VIDEOMODE_EDIDREG_H */

View file

@ -0,0 +1,94 @@
/* $NetBSD: edidvar.h,v 1.2 2006/05/11 19:05:41 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_VIDEOMODE_EDIDVAR_H
#define _DEV_VIDEOMODE_EDIDVAR_H
struct edid_chroma {
uint16_t ec_redx;
uint16_t ec_redy;
uint16_t ec_greenx;
uint16_t ec_greeny;
uint16_t ec_bluex;
uint16_t ec_bluey;
uint16_t ec_whitex;
uint16_t ec_whitey;
};
struct edid_range {
uint16_t er_min_vfreq; /* Hz */
uint16_t er_max_vfreq; /* Hz */
uint16_t er_min_hfreq; /* kHz */
uint16_t er_max_hfreq; /* kHz */
uint16_t er_max_clock; /* MHz */
int er_have_gtf2;
uint16_t er_gtf2_hfreq;
uint16_t er_gtf2_c;
uint16_t er_gtf2_m;
uint16_t er_gtf2_k;
uint16_t er_gtf2_j;
};
struct edid_info {
uint8_t edid_vendor[4];
char edid_vendorname[16];
char edid_productname[16];
char edid_comment[16];
char edid_serial[16];
uint16_t edid_product;
uint8_t edid_version;
uint8_t edid_revision;
int edid_year;
int edid_week;
uint8_t edid_video_input; /* see edidregs.h */
uint8_t edid_max_hsize; /* in cm */
uint8_t edid_max_vsize; /* in cm */
uint8_t edid_gamma;
uint8_t edid_features;
int edid_have_range;
struct edid_range edid_range;
struct edid_chroma edid_chroma;
/* parsed modes */
struct videomode *edid_preferred_mode;
int edid_nmodes;
struct videomode edid_modes[64];
};
int edid_is_valid(uint8_t *);
int edid_parse(uint8_t *, struct edid_info *);
void edid_print(struct edid_info *);
#endif /* _DEV_VIDEOMODE_EDIDVAR_H */

View file

@ -0,0 +1,13 @@
# $NetBSD: files.videomode,v 1.4 2010/05/04 21:17:10 macallan Exp $
define videomode
define edid
define vesagtf
file dev/videomode/videomode.c videomode | edid
file dev/videomode/edid.c edid
file dev/videomode/pickmode.c videomode
defflag opt_videomode.h PICKMODE_DEBUG
file dev/videomode/vesagtf.c vesagtf | edid

180
sys/dev/videomode/modelines Normal file
View file

@ -0,0 +1,180 @@
// $NetBSD: modelines,v 1.9 2011/03/30 18:45:04 jdc Exp $
//
// This file was imported from XFree86, and is made of the contents of both
// the vesamodes and extramodes files. As a result these should correspond
// to the same default modes compiled into XFree86.
//
// Default modes distilled from
// "VESA and Industry Standards and Guide for Computer Display Monitor
// Timing", version 1.0, revision 0.8, adopted September 17, 1998.
//
// $XFree86: xc/programs/Xserver/hw/xfree86/etc/vesamodes,v 1.3 1999/11/16 03:28:03 tsi Exp $
// $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.5 2002/06/05 19:43:05 dawes Exp $
//
//
// Use "make -f Makefile.videomode" to regenerate videomode.c
//
# 640x350 @ 85Hz (VESA) hsync: 37.9kHz
ModeLine "640x350" 31.5 640 672 736 832 350 382 385 445 +hsync -vsync
# 640x400 @ 85Hz (VESA) hsync: 37.9kHz
ModeLine "640x400" 31.5 640 672 736 832 400 401 404 445 -hsync +vsync
# 720x400 @ 70Hz (EDID established timing) hsync: 31.47kHz
ModeLine "720x400" 28.32 720 738 846 900 400 412 414 449 -hsync +vsync
# 720x400 @ 85Hz (VESA) hsync: 37.9kHz
ModeLine "720x400" 35.5 720 756 828 936 400 401 404 446 -hsync +vsync
# 720x400 @ 88Hz (EDID established timing) hsync: 39.44kHz
ModeLine "720x400" 35.5 720 738 846 900 400 421 423 449 -hsync -vsync
# 640x480 @ 60Hz (Industry standard) hsync: 31.5kHz
ModeLine "640x480" 25.175 640 656 752 800 480 490 492 525 -hsync -vsync
# 640x480 @ 72Hz (VESA) hsync: 37.9kHz
ModeLine "640x480" 31.5 640 664 704 832 480 489 492 520 -hsync -vsync
# 640x480 @ 75Hz (VESA) hsync: 37.5kHz
ModeLine "640x480" 31.5 640 656 720 840 480 481 484 500 -hsync -vsync
# 640x480 @ 85Hz (VESA) hsync: 43.3kHz
ModeLine "640x480" 36.0 640 696 752 832 480 481 484 509 -hsync -vsync
# 800x600 @ 56Hz (VESA) hsync: 35.2kHz
ModeLine "800x600" 36.0 800 824 896 1024 600 601 603 625 +hsync +vsync
# 800x600 @ 60Hz (VESA) hsync: 37.9kHz
ModeLine "800x600" 40.0 800 840 968 1056 600 601 605 628 +hsync +vsync
# 800x600 @ 72Hz (VESA) hsync: 48.1kHz
ModeLine "800x600" 50.0 800 856 976 1040 600 637 643 666 +hsync +vsync
# 800x600 @ 75Hz (VESA) hsync: 46.9kHz
ModeLine "800x600" 49.5 800 816 896 1056 600 601 604 625 +hsync +vsync
# 800x600 @ 85Hz (VESA) hsync: 53.7kHz
ModeLine "800x600" 56.25 800 832 896 1048 600 601 604 631 +hsync +vsync
# 1024x768i @ 43Hz (industry standard) hsync: 35.5kHz
ModeLine "1024x768" 44.9 1024 1032 1208 1264 768 768 776 817 +hsync +vsync Interlace
# 1024x768 @ 60Hz (VESA) hsync: 48.4kHz
ModeLine "1024x768" 65.0 1024 1048 1184 1344 768 771 777 806 -hsync -vsync
# 1024x768 @ 70Hz (VESA) hsync: 56.5kHz
ModeLine "1024x768" 75.0 1024 1048 1184 1328 768 771 777 806 -hsync -vsync
# 1024x768 @ 75Hz (VESA) hsync: 60.0kHz
ModeLine "1024x768" 78.75 1024 1040 1136 1312 768 769 772 800 +hsync +vsync
# 1024x768 @ 85Hz (VESA) hsync: 68.7kHz
ModeLine "1024x768" 94.5 1024 1072 1168 1376 768 769 772 808 +hsync +vsync
# 1024x768 @ 89Hz (non-standard) hsync: 72.0kHz
ModeLine "1024x768" 100 1024 1108 1280 1408 768 768 780 796 +hsync +vsync
# 1152x864 @ 75Hz (VESA) hsync: 67.5kHz
ModeLine "1152x864" 108.0 1152 1216 1344 1600 864 865 868 900 +hsync +vsync
# 1280x768 @ 75Hz (non-standard) hsync: 60.6kHz
ModeLine "1280x768" 105.64 1280 1312 1712 1744 768 782 792 807 -hsync +vsync
# 1280x960 @ 60Hz (VESA) hsync: 60.0kHz
ModeLine "1280x960" 108.0 1280 1376 1488 1800 960 961 964 1000 +hsync +vsync
# 1280x960 @ 85Hz (VESA) hsync: 85.9kHz
ModeLine "1280x960" 148.5 1280 1344 1504 1728 960 961 964 1011 +hsync +vsync
# 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz
ModeLine "1280x1024" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync
# 1280x1024 @ 70Hz (non-standard) hsync: 74.0kHz
ModeLine "1280x1024" 126.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync
# 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz
ModeLine "1280x1024" 135.0 1280 1296 1440 1688 1024 1025 1028 1066 +hsync +vsync
# 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz
ModeLine "1280x1024" 157.5 1280 1344 1504 1728 1024 1025 1028 1072 +hsync +vsync
# 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz
ModeLine "1600x1200" 162.0 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
# 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz
ModeLine "1600x1200" 175.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
# 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz
ModeLine "1600x1200" 189.0 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
# 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz
ModeLine "1600x1200" 202.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
# 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz
ModeLine "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
# 1680x1050 @ 60.00Hz (GTF) hsync: 65.22 kHz; pclk: 147.14 MHz
ModeLine "1680x1050" 147.14 1680 1784 1968 2256 1050 1051 1054 1087 +hsync +vsync
# 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz
ModeLine "1792x1344" 204.8 1792 1920 2120 2448 1344 1345 1348 1394 -hsync +vsync
# 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz
ModeLine "1792x1344" 261.0 1792 1888 2104 2456 1344 1345 1348 1417 -hsync +vsync
# 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz
ModeLine "1856x1392" 218.3 1856 1952 2176 2528 1392 1393 1396 1439 -hsync +vsync
# 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz
ModeLine "1856x1392" 288.0 1856 1984 2208 2560 1392 1393 1396 1500 -hsync +vsync
# 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz
ModeLine "1920x1440" 234.0 1920 2048 2256 2600 1440 1441 1444 1500 -hsync +vsync
# 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz
ModeLine "1920x1440" 297.0 1920 2064 2288 2640 1440 1441 1444 1500 -hsync +vsync
//
// Extra modes to include as default modes in the X server.
//
// $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.5 2002/06/05 19:43:05 dawes Exp $
//
# 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz
ModeLine "832x624" 57.284 832 864 928 1152 624 625 628 667 -Hsync -Vsync
# 1152x768 @ 54.8Hz (Titanium PowerBook) hsync: 44.2kHz
ModeLine "1152x768" 64.995 1152 1178 1314 1472 768 771 777 806 +hsync +vsync
# 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz
ModeLine "1400x1050" 122.0 1400 1488 1640 1880 1050 1052 1064 1082 +hsync +vsync
# 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz
ModeLine "1400x1050" 155.8 1400 1464 1784 1912 1050 1052 1064 1090 +hsync +vsync
# 1600x1024 @ 60Hz (SGI 1600SW) hsync: 64.0kHz
Modeline "1600x1024" 106.910 1600 1620 1640 1670 1024 1027 1030 1067 -hsync -vsync
# 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz
Modeline "1920x1440" 341.35 1920 2072 2288 2656 1440 1441 1444 1512 -hsync +vsync
# 2048x1536 @ 60Hz (VESA GTF) hsync: 95.3kHz
Modeline "2048x1536" 266.95 2048 2200 2424 2800 1536 1537 1540 1589 -hsync +vsync
# 2048x1536 @ 75Hz (VESA GTF) hsync: 120.2kHz
Modeline "2048x1536" 340.48 2048 2216 2440 2832 1536 1537 1540 1603 -hsync +vsync
# 2048x1536 @ 85Hz (VESA GTF) hsync: 137.0kHz
Modeline "2048x1536" 388.04 2048 2216 2440 2832 1536 1537 1540 1612 -hsync +vsync
//
// some Sun-specific modes
//
# 1152x900 @ 66Hz - default on most SBus graphics devices
ModeLine "1152x900" 94.50 1152 1192 1320 1528 900 902 906 937 -hsync -vsync
# 1152x900 @ 76Hz
ModeLine "1152x900" 105.56 1152 1168 1280 1472 900 902 906 943 -hsync -vsync

View file

@ -0,0 +1,149 @@
#! /usr/bin/awk -f
# $NetBSD: modelines2c.awk,v 1.5 2011/03/21 19:32:26 jdc Exp $
#
# Copyright (c) 2006 Itronix Inc.
# All rights reserved.
#
# Written by Garrett D'Amore for Itronix Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of Itronix Inc. may not be used to endorse
# or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
BEGIN {
nmodes = 0;
}
NR == 1 {
split($0,v,"$");
VERSION=v[2];
printf("/*\t$NetBSD" "$\t*/\n\n");
printf("/*\n") ;
printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n");
printf(" *\n");
printf(" * generated from:\n");
printf(" *\t%s\n", VERSION);
printf(" */\n\n");
printf("#include <sys/cdefs.h>\n");
printf("__KERNEL_RCSID(0, \"$NetBSD" "$\");\n\n");
printf("#include <dev/videomode/videomode.h>\n\n");
printf("/*\n");
printf(" * These macros help the modelines below fit on one line.\n");
printf(" */\n");
printf("#define HP VID_PHSYNC\n");
printf("#define HN VID_NHSYNC\n");
printf("#define VP VID_PVSYNC\n");
printf("#define VN VID_NVSYNC\n");
printf("#define I VID_INTERLACE\n");
printf("#define DS VID_DBLSCAN\n");
printf("\n");
printf("#define M(nm,hr,vr,clk,hs,he,ht,vs,ve,vt,f) \\\n");
printf("\t{ clk, hr, hs, he, ht, vr, vs, ve, vt, f, nm } \n\n");
printf("const struct videomode videomode_list[] = {\n");
next
}
(/^ModeLine/) {
dotclock = $3;
hdisplay = $4;
hsyncstart = $5;
hsyncend = $6;
htotal = $7;
vdisplay = $8;
vsyncstart = $9;
vsyncend = $10;
vtotal = $11;
macro = "MODE";
iflag = "";
iflags = "";
hflags = "HP";
vflags = "VP";
if ($12 ~ "^-")
hflags = "HN";
if ($13 ~ "^-")
vflags = "VN";
ifactor=1.0;
if ($14 ~ "[Ii][Nn][Tt][Ee][Rr][Ll][Aa][Cc][Ee]") {
iflag = "i";
iflags = "|I";
ifactor = 2.0;
}
# We truncate the vrefresh figure, but some mode descriptions rely
# on rounding, so we can't win here. Adding an additional .1
# compensates to some extent.
hrefresh= (dotclock * 1000000) / htotal;
vrefresh= int(((hrefresh * ifactor) / vtotal) + .1);
modestr = sprintf("%dx%dx%d%s", hdisplay, vdisplay, vrefresh, iflag);
# printf("/* %dx%d%s refresh %d Hz, hsync %d kHz */\n",
# hdisplay, vdisplay, iflag, vrefresh, hrefresh/1000);
printf("M(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%s),\n",
modestr,
hdisplay, vdisplay, dotclock * 1000,
hsyncstart, hsyncend, htotal,
vsyncstart, vsyncend, vtotal, hflags "|" vflags iflags);
modestr = sprintf("%dx%dx%d%s",
hdisplay/2 , vdisplay/2, vrefresh, iflag);
dmodes[nmodes]=sprintf("M(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%s),",
modestr,
hdisplay/2, vdisplay/2, dotclock * 1000 / 2,
hsyncstart/2, hsyncend/2, htotal/2,
vsyncstart/2, vsyncend/2, vtotal/2,
hflags "|" vflags "|DS" iflags);
nmodes = nmodes + 1
}
END {
printf("\n/* Derived Double Scan Modes */\n\n");
for ( i = 0; i < nmodes; i++ )
{
print dmodes[i];
}
printf("};\n\n");
printf("const int videomode_count = %d;\n", nmodes);
}

View file

@ -0,0 +1,208 @@
/* $NetBSD: pickmode.c,v 1.4 2011/04/09 20:53:39 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation
* All rights reserved.
*
* this code was contributed to The NetBSD Foundation by Michael Lorenz
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE NETBSD FOUNDATION BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pickmode.c,v 1.4 2011/04/09 20:53:39 christos Exp $");
#include <sys/param.h>
#include <dev/videomode/videomode.h>
#ifndef __minix
#include "opt_videomode.h"
#endif
#ifndef abs
#define abs(x) (((x) < 0) ? -(x) : (x))
#endif
#ifdef PICKMODE_DEBUG
#define DPRINTF printf
#else
#define DPRINTF while (0) printf
#endif
const struct videomode *
pick_mode_by_dotclock(int width, int height, int dotclock)
{
const struct videomode *this, *best = NULL;
int i;
DPRINTF("%s: looking for %d x %d at up to %d kHz\n", __func__, width,
height, dotclock);
for (i = 0; i < videomode_count; i++) {
this = &videomode_list[i];
if ((this->hdisplay != width) || (this->vdisplay != height) ||
(this->dot_clock > dotclock))
continue;
if (best != NULL) {
if (this->dot_clock > best->dot_clock)
best = this;
} else
best = this;
}
if (best != NULL)
DPRINTF("found %s\n", best->name);
return best;
}
const struct videomode *
pick_mode_by_ref(int width, int height, int refresh)
{
const struct videomode *this, *best = NULL;
int mref, closest = 1000, i, diff;
DPRINTF("%s: looking for %d x %d at up to %d Hz\n", __func__, width,
height, refresh);
for (i = 0; i < videomode_count; i++) {
this = &videomode_list[i];
mref = this->dot_clock * 1000 / (this->htotal * this->vtotal);
diff = abs(mref - refresh);
if ((this->hdisplay != width) || (this->vdisplay != height))
continue;
DPRINTF("%s in %d hz, diff %d\n", this->name, mref, diff);
if (best != NULL) {
if (diff < closest) {
best = this;
closest = diff;
}
} else {
best = this;
closest = diff;
}
}
if (best != NULL)
DPRINTF("found %s %d\n", best->name, best->dot_clock);
return best;
}
static inline void
swap_modes(struct videomode *left, struct videomode *right)
{
struct videomode temp;
temp = *left;
*left = *right;
*right = temp;
}
/*
* Sort modes by refresh rate, aspect ratio (*), then resolution.
* Preferred mode or largest mode is first in the list and other modes
* are sorted on closest match to that mode.
* (*) Note that the aspect ratio calculation treats "close" aspect ratios
* (within 12.5%) as the same for this purpose.
*/
#define DIVIDE(x, y) (((x) + ((y) / 2)) / (y))
void
sort_modes(struct videomode *modes, struct videomode **preferred, int nmodes)
{
int aspect, refresh, hbest, vbest, abest, atemp, rbest, rtemp;
int i, j;
struct videomode *mtemp = NULL;
if (nmodes < 2)
return;
if (*preferred != NULL) {
/* Put the preferred mode first in the list */
aspect = (*preferred)->hdisplay * 100 / (*preferred)->vdisplay;
refresh = DIVIDE(DIVIDE((*preferred)->dot_clock * 1000,
(*preferred)->htotal), (*preferred)->vtotal);
if (*preferred != modes) {
swap_modes(*preferred, modes);
*preferred = modes;
}
} else {
/*
* Find the largest horizontal and vertical mode and put that
* first in the list. Preferred refresh rate is taken from
* the first mode of this size.
*/
hbest = 0;
vbest = 0;
for (i = 0; i < nmodes; i++) {
if (modes[i].hdisplay > hbest) {
hbest = modes[i].hdisplay;
vbest = modes[i].vdisplay;
mtemp = &modes[i];
} else if (modes[i].hdisplay == hbest &&
modes[i].vdisplay > vbest) {
vbest = modes[i].vdisplay;
mtemp = &modes[i];
}
}
aspect = mtemp->hdisplay * 100 / mtemp->vdisplay;
refresh = DIVIDE(DIVIDE(mtemp->dot_clock * 1000,
mtemp->htotal), mtemp->vtotal);
if (mtemp != modes)
swap_modes(mtemp, modes);
}
/* Sort other modes by refresh rate, aspect ratio, then resolution */
for (j = 1; j < nmodes - 1; j++) {
rbest = 1000;
abest = 1000;
hbest = 0;
vbest = 0;
for (i = j; i < nmodes; i++) {
rtemp = abs(refresh -
DIVIDE(DIVIDE(modes[i].dot_clock * 1000,
modes[i].htotal), modes[i].vtotal));
atemp = (modes[i].hdisplay * 100 / modes[i].vdisplay);
if (rtemp < rbest) {
rbest = rtemp;
mtemp = &modes[i];
}
if (rtemp == rbest) {
/* Treat "close" aspect ratios as identical */
if (abs(abest - atemp) > (abest / 8) &&
abs(aspect - atemp) < abs(aspect - abest)) {
abest = atemp;
mtemp = &modes[i];
}
if (atemp == abest ||
abs(abest - atemp) <= (abest / 8)) {
if (modes[i].hdisplay > hbest) {
hbest = modes[i].hdisplay;
mtemp = &modes[i];
}
if (modes[i].hdisplay == hbest &&
modes[i].vdisplay > vbest) {
vbest = modes[i].vdisplay;
mtemp = &modes[i];
}
}
}
}
if (mtemp != &modes[j])
swap_modes(mtemp, &modes[j]);
}
}

25
sys/dev/videomode/test.c Normal file
View file

@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "videomode.h"
int
main(int argc, char **argv)
{
int i, j;
for (i = 1; i < argc ; i++) {
for (j = 0; j < videomode_count; j++) {
if (strcmp(videomode_list[j].name, argv[i]) == 0) {
printf("dotclock for mode %s = %d, flags %x\n",
argv[i],
videomode_list[j].dot_clock,
videomode_list[j].flags);
break;
}
}
if (j == videomode_count) {
printf("dotclock for mode %s not found\n", argv[i]);
}
}
}

704
sys/dev/videomode/vesagtf.c Normal file
View file

@ -0,0 +1,704 @@
/* $NetBSD: vesagtf.c,v 1.1 2006/05/11 01:49:53 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This was derived from a userland GTF program supplied by NVIDIA.
* NVIDIA's original boilerplate follows.
*
* Note that I have heavily modified the program for use in the EDID
* kernel code for NetBSD, including removing the use of floating
* point operations and making significant adjustments to minimize
* error propogation while operating with integer only math.
*
* This has required the use of 64-bit integers in a few places, but
* the upshot is that for a calculation of 1920x1200x85 (as an
* example), the error deviates by only ~.004% relative to the
* floating point version. This error is *well* within VESA
* tolerances.
*/
/*
* Copyright (c) 2001, Andy Ritger aritger@nvidia.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* o Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* o Neither the name of NVIDIA nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
*
* This program is based on the Generalized Timing Formula(GTF TM)
* Standard Version: 1.0, Revision: 1.0
*
* The GTF Document contains the following Copyright information:
*
* Copyright (c) 1994, 1995, 1996 - Video Electronics Standards
* Association. Duplication of this document within VESA member
* companies for review purposes is permitted. All other rights
* reserved.
*
* While every precaution has been taken in the preparation
* of this standard, the Video Electronics Standards Association and
* its contributors assume no responsibility for errors or omissions,
* and make no warranties, expressed or implied, of functionality
* of suitability for any purpose. The sample code contained within
* this standard may be used without restriction.
*
*
*
* The GTF EXCEL(TM) SPREADSHEET, a sample (and the definitive)
* implementation of the GTF Timing Standard, is available at:
*
* ftp://ftp.vesa.org/pub/GTF/GTF_V1R1.xls
*
*
*
* This program takes a desired resolution and vertical refresh rate,
* and computes mode timings according to the GTF Timing Standard.
* These mode timings can then be formatted as an XFree86 modeline
* or a mode description for use by fbset(8).
*
*
*
* NOTES:
*
* The GTF allows for computation of "margins" (the visible border
* surrounding the addressable video); on most non-overscan type
* systems, the margin period is zero. I've implemented the margin
* computations but not enabled it because 1) I don't really have
* any experience with this, and 2) neither XFree86 modelines nor
* fbset fb.modes provide an obvious way for margin timings to be
* included in their mode descriptions (needs more investigation).
*
* The GTF provides for computation of interlaced mode timings;
* I've implemented the computations but not enabled them, yet.
* I should probably enable and test this at some point.
*
*
*
* TODO:
*
* o Add support for interlaced modes.
*
* o Implement the other portions of the GTF: compute mode timings
* given either the desired pixel clock or the desired horizontal
* frequency.
*
* o It would be nice if this were more general purpose to do things
* outside the scope of the GTF: like generate double scan mode
* timings, for example.
*
* o Printing digits to the right of the decimal point when the
* digits are 0 annoys me.
*
* o Error checking.
*
*/
#ifdef _KERNEL
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vesagtf.c,v 1.1 2006/05/11 01:49:53 gdamore Exp $");
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <dev/videomode/videomode.h>
#include <dev/videomode/vesagtf.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "videomode.h"
#include "vesagtf.h"
void print_xf86_mode(struct videomode *m);
#endif
#define CELL_GRAN 8 /* assumed character cell granularity */
/* C' and M' are part of the Blanking Duty Cycle computation */
/*
* #define C_PRIME (((C - J) * K/256.0) + J)
* #define M_PRIME (K/256.0 * M)
*/
/*
* C' and M' multiplied by 256 to give integer math. Make sure to
* scale results using these back down, appropriately.
*/
#define C_PRIME256(p) (((p->C - p->J) * p->K) + (p->J * 256))
#define M_PRIME256(p) (p->K * p->M)
#define DIVIDE(x,y) (((x) + ((y) / 2)) / (y))
/*
* print_value() - print the result of the named computation; this is
* useful when comparing against the GTF EXCEL spreadsheet.
*/
#ifdef GTFDEBUG
static void
print_value(int n, const char *name, unsigned val)
{
printf("%2d: %-27s: %u\n", n, name, val);
}
#else
#define print_value(n, name, val)
#endif
/*
* vert_refresh() - as defined by the GTF Timing Standard, compute the
* Stage 1 Parameters using the vertical refresh frequency. In other
* words: input a desired resolution and desired refresh rate, and
* output the GTF mode timings.
*
* XXX All the code is in place to compute interlaced modes, but I don't
* feel like testing it right now.
*
* XXX margin computations are implemented but not tested (nor used by
* XFree86 of fbset mode descriptions, from what I can tell).
*/
void
vesagtf_mode_params(unsigned h_pixels, unsigned v_lines, unsigned freq,
struct vesagtf_params *params, int flags, struct videomode *vmp)
{
unsigned v_field_rqd;
unsigned top_margin;
unsigned bottom_margin;
unsigned interlace;
uint64_t h_period_est;
unsigned vsync_plus_bp;
unsigned v_back_porch;
unsigned total_v_lines;
uint64_t v_field_est;
uint64_t h_period;
unsigned v_field_rate;
unsigned v_frame_rate;
unsigned left_margin;
unsigned right_margin;
unsigned total_active_pixels;
uint64_t ideal_duty_cycle;
unsigned h_blank;
unsigned total_pixels;
unsigned pixel_freq;
unsigned h_sync;
unsigned h_front_porch;
unsigned v_odd_front_porch_lines;
#ifdef GTFDEBUG
unsigned h_freq;
#endif
/* 1. In order to give correct results, the number of horizontal
* pixels requested is first processed to ensure that it is divisible
* by the character size, by rounding it to the nearest character
* cell boundary:
*
* [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
*/
h_pixels = DIVIDE(h_pixels, CELL_GRAN) * CELL_GRAN;
print_value(1, "[H PIXELS RND]", h_pixels);
/* 2. If interlace is requested, the number of vertical lines assumed
* by the calculation must be halved, as the computation calculates
* the number of vertical lines per field. In either case, the
* number of lines is rounded to the nearest integer.
*
* [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
* ROUND([V LINES],0))
*/
v_lines = (flags & VESAGTF_FLAG_ILACE) ? DIVIDE(v_lines, 2) : v_lines;
print_value(2, "[V LINES RND]", v_lines);
/* 3. Find the frame rate required:
*
* [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
* [I/P FREQ RQD])
*/
v_field_rqd = (flags & VESAGTF_FLAG_ILACE) ? (freq * 2) : (freq);
print_value(3, "[V FIELD RATE RQD]", v_field_rqd);
/* 4. Find number of lines in Top margin:
* 5. Find number of lines in Bottom margin:
*
* [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
* ROUND(([MARGIN%]/100*[V LINES RND]),0),
* 0)
*
* Ditto for bottom margin. Note that instead of %, we use PPT, which
* is parts per thousand. This helps us with integer math.
*/
top_margin = bottom_margin = (flags & VESAGTF_FLAG_MARGINS) ?
DIVIDE(v_lines * params->margin_ppt, 1000) : 0;
print_value(4, "[TOP MARGIN (LINES)]", top_margin);
print_value(5, "[BOT MARGIN (LINES)]", bottom_margin);
/* 6. If interlace is required, then set variable [INTERLACE]=0.5:
*
* [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
*
* To make this integer friendly, we use some special hacks in step
* 7 below. Please read those comments to understand why I am using
* a whole number of 1.0 instead of 0.5 here.
*/
interlace = (flags & VESAGTF_FLAG_ILACE) ? 1 : 0;
print_value(6, "[2*INTERLACE]", interlace);
/* 7. Estimate the Horizontal period
*
* [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
* ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
* [MIN PORCH RND]+[INTERLACE]) * 1000000
*
* To make it integer friendly, we pre-multiply the 1000000 to get to
* usec. This gives us:
*
* [H PERIOD EST] = ((1000000/[V FIELD RATE RQD]) - [MIN VSYNC+BP]) /
* ([V LINES RND] + (2 * [TOP MARGIN (LINES)]) +
* [MIN PORCH RND]+[INTERLACE])
*
* The other problem is that the interlace value is wrong. To get
* the interlace to a whole number, we multiply both the numerator and
* divisor by 2, so we can use a value of either 1 or 0 for the interlace
* factor.
*
* This gives us:
*
* [H PERIOD EST] = ((2*((1000000/[V FIELD RATE RQD]) - [MIN VSYNC+BP])) /
* (2*([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
* [MIN PORCH RND]) + [2*INTERLACE]))
*
* Finally we multiply by another 1000, to get value in picosec.
* Why picosec? To minimize rounding errors. Gotta love integer
* math and error propogation.
*/
h_period_est = DIVIDE(((DIVIDE(2000000000000ULL, v_field_rqd)) -
(2000000 * params->min_vsbp)),
((2 * (v_lines + (2 * top_margin) + params->min_porch)) + interlace));
print_value(7, "[H PERIOD EST (ps)]", h_period_est);
/* 8. Find the number of lines in V sync + back porch:
*
* [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
*
* But recall that h_period_est is in psec. So multiply by 1000000.
*/
vsync_plus_bp = DIVIDE(params->min_vsbp * 1000000, h_period_est);
print_value(8, "[V SYNC+BP]", vsync_plus_bp);
/* 9. Find the number of lines in V back porch alone:
*
* [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
*
* XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
*/
v_back_porch = vsync_plus_bp - params->vsync_rqd;
print_value(9, "[V BACK PORCH]", v_back_porch);
/* 10. Find the total number of lines in Vertical field period:
*
* [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
* [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
* [MIN PORCH RND]
*/
total_v_lines = v_lines + top_margin + bottom_margin + vsync_plus_bp +
interlace + params->min_porch;
print_value(10, "[TOTAL V LINES]", total_v_lines);
/* 11. Estimate the Vertical field frequency:
*
* [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
*
* Again, we want to pre multiply by 10^9 to convert for nsec, thereby
* making it usable in integer math.
*
* So we get:
*
* [V FIELD RATE EST] = 1000000000 / [H PERIOD EST] / [TOTAL V LINES]
*
* This is all scaled to get the result in uHz. Again, we're trying to
* minimize error propogation.
*/
v_field_est = DIVIDE(DIVIDE(1000000000000000ULL, h_period_est),
total_v_lines);
print_value(11, "[V FIELD RATE EST(uHz)]", v_field_est);
/* 12. Find the actual horizontal period:
*
* [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
*/
h_period = DIVIDE(h_period_est * v_field_est, v_field_rqd * 1000);
print_value(12, "[H PERIOD(ps)]", h_period);
/* 13. Find the actual Vertical field frequency:
*
* [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
*
* And again, we convert to nsec ahead of time, giving us:
*
* [V FIELD RATE] = 1000000 / [H PERIOD] / [TOTAL V LINES]
*
* And another rescaling back to mHz. Gotta love it.
*/
v_field_rate = DIVIDE(1000000000000ULL, h_period * total_v_lines);
print_value(13, "[V FIELD RATE]", v_field_rate);
/* 14. Find the Vertical frame frequency:
*
* [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
*
* N.B. that the result here is in mHz.
*/
v_frame_rate = (flags & VESAGTF_FLAG_ILACE) ?
v_field_rate / 2 : v_field_rate;
print_value(14, "[V FRAME RATE]", v_frame_rate);
/* 15. Find number of pixels in left margin:
* 16. Find number of pixels in right margin:
*
* [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
* (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
* [CELL GRAN RND]),0)) * [CELL GRAN RND],
* 0))
*
* Again, we deal with margin percentages as PPT (parts per thousand).
* And the calculations for left and right are the same.
*/
left_margin = right_margin = (flags & VESAGTF_FLAG_MARGINS) ?
DIVIDE(DIVIDE(h_pixels * params->margin_ppt, 1000),
CELL_GRAN) * CELL_GRAN : 0;
print_value(15, "[LEFT MARGIN (PIXELS)]", left_margin);
print_value(16, "[RIGHT MARGIN (PIXELS)]", right_margin);
/* 17. Find total number of active pixels in image and left and right
* margins:
*
* [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
* [RIGHT MARGIN (PIXELS)]
*/
total_active_pixels = h_pixels + left_margin + right_margin;
print_value(17, "[TOTAL ACTIVE PIXELS]", total_active_pixels);
/* 18. Find the ideal blanking duty cycle from the blanking duty cycle
* equation:
*
* [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
*
* However, we have modified values for [C'] as [256*C'] and
* [M'] as [256*M']. Again the idea here is to get good scaling.
* We use 256 as the factor to make the math fast.
*
* Note that this means that we have to scale it appropriately in
* later calculations.
*
* The ending result is that our ideal_duty_cycle is 256000x larger
* than the duty cycle used by VESA. But again, this reduces error
* propogation.
*/
ideal_duty_cycle =
((C_PRIME256(params) * 1000) -
(M_PRIME256(params) * h_period / 1000000));
print_value(18, "[IDEAL DUTY CYCLE]", ideal_duty_cycle);
/* 19. Find the number of pixels in the blanking time to the nearest
* double character cell:
*
* [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
* [IDEAL DUTY CYCLE] /
* (100-[IDEAL DUTY CYCLE]) /
* (2*[CELL GRAN RND])), 0))
* * (2*[CELL GRAN RND])
*
* Of course, we adjust to make this rounding work in integer math.
*/
h_blank = DIVIDE(DIVIDE(total_active_pixels * ideal_duty_cycle,
(256000 * 100ULL) - ideal_duty_cycle),
2 * CELL_GRAN) * (2 * CELL_GRAN);
print_value(19, "[H BLANK (PIXELS)]", h_blank);
/* 20. Find total number of pixels:
*
* [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
*/
total_pixels = total_active_pixels + h_blank;
print_value(20, "[TOTAL PIXELS]", total_pixels);
/* 21. Find pixel clock frequency:
*
* [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
*
* We calculate this in Hz rather than MHz, to get a value that
* is usable with integer math. Recall that the [H PERIOD] is in
* nsec.
*/
pixel_freq = DIVIDE(total_pixels * 1000000, DIVIDE(h_period, 1000));
print_value(21, "[PIXEL FREQ]", pixel_freq);
/* 22. Find horizontal frequency:
*
* [H FREQ] = 1000 / [H PERIOD]
*
* I've ifdef'd this out, because we don't need it for any of
* our calculations.
* We calculate this in Hz rather than kHz, to avoid rounding
* errors. Recall that the [H PERIOD] is in usec.
*/
#ifdef GTFDEBUG
h_freq = 1000000000 / h_period;
print_value(22, "[H FREQ]", h_freq);
#endif
/* Stage 1 computations are now complete; I should really pass
the results to another function and do the Stage 2
computations, but I only need a few more values so I'll just
append the computations here for now */
/* 17. Find the number of pixels in the horizontal sync period:
*
* [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
* [CELL GRAN RND]),0))*[CELL GRAN RND]
*
* Rewriting for integer math:
*
* [H SYNC (PIXELS)]=(ROUND((H SYNC%] * [TOTAL PIXELS] / 100 /
* [CELL GRAN RND),0))*[CELL GRAN RND]
*/
h_sync = DIVIDE(((params->hsync_pct * total_pixels) / 100), CELL_GRAN) *
CELL_GRAN;
print_value(17, "[H SYNC (PIXELS)]", h_sync);
/* 18. Find the number of pixels in the horizontal front porch period:
*
* [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
*
* Note that h_blank is always an even number of characters (i.e.
* h_blank % (CELL_GRAN * 2) == 0)
*/
h_front_porch = (h_blank / 2) - h_sync;
print_value(18, "[H FRONT PORCH (PIXELS)]", h_front_porch);
/* 36. Find the number of lines in the odd front porch period:
*
* [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
*
* Adjusting for the fact that the interlace is scaled:
*
* [V ODD FRONT PORCH(LINES)]=(([MIN PORCH RND] * 2) + [2*INTERLACE]) / 2
*/
v_odd_front_porch_lines = ((2 * params->min_porch) + interlace) / 2;
print_value(36, "[V ODD FRONT PORCH(LINES)]", v_odd_front_porch_lines);
/* finally, pack the results in the mode struct */
vmp->hsync_start = h_pixels + h_front_porch;
vmp->hsync_end = vmp->hsync_start + h_sync;
vmp->htotal = total_pixels;
vmp->hdisplay = h_pixels;
vmp->vsync_start = v_lines + v_odd_front_porch_lines;
vmp->vsync_end = vmp->vsync_start + params->vsync_rqd;
vmp->vtotal = total_v_lines;
vmp->vdisplay = v_lines;
vmp->dot_clock = pixel_freq;
}
void
vesagtf_mode(unsigned x, unsigned y, unsigned refresh, struct videomode *vmp)
{
struct vesagtf_params params;
params.margin_ppt = VESAGTF_MARGIN_PPT;
params.min_porch = VESAGTF_MIN_PORCH;
params.vsync_rqd = VESAGTF_VSYNC_RQD;
params.hsync_pct = VESAGTF_HSYNC_PCT;
params.min_vsbp = VESAGTF_MIN_VSBP;
params.M = VESAGTF_M;
params.C = VESAGTF_C;
params.K = VESAGTF_K;
params.J = VESAGTF_J;
vesagtf_mode_params(x, y, refresh, &params, 0, vmp);
}
/*
* The tidbit here is so that you can compile this file as a
* standalone user program to generate X11 modelines using VESA GTF.
* This also allows for testing of the code itself, without
* necessitating a full kernel recompile.
*/
/* print_xf86_mode() - print the XFree86 modeline, given mode timings. */
#ifndef __minix
#ifndef _KERNEL
void
print_xf86_mode (struct videomode *vmp)
{
float vf, hf;
hf = 1000.0 * vmp->dot_clock / vmp->htotal;
vf = 1.0 * hf / vmp->vtotal;
printf("\n");
printf(" # %dx%d @ %.2f Hz (GTF) hsync: %.2f kHz; pclk: %.2f MHz\n",
vmp->hdisplay, vmp->vdisplay, vf, hf, vmp->dot_clock / 1000.0);
printf(" Modeline \"%dx%d_%.2f\" %.2f"
" %d %d %d %d"
" %d %d %d %d"
" -HSync +Vsync\n\n",
vmp->hdisplay, vmp->vdisplay, vf, (vmp->dot_clock / 1000.0),
vmp->hdisplay, vmp->hsync_start, vmp->hsync_end, vmp->htotal,
vmp->vdisplay, vmp->vsync_start, vmp->vsync_end, vmp->vtotal);
}
int
main (int argc, char *argv[])
{
struct videomode m;
if (argc != 4) {
printf("usage: %s x y refresh\n", argv[0]);
exit(1);
}
vesagtf_mode(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), &m);
print_xf86_mode(&m);
return 0;
}
#endif
#endif /* !__minix */

View file

@ -0,0 +1,85 @@
/* $NetBSD: vesagtf.h,v 1.1 2006/05/11 01:49:53 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_VIDEOMODE_VESAGTF_H
#define _DEV_VIDEOMODE_VESAGTF_H
/*
* Use VESA GTF formula to generate a monitor mode, given resolution and
* refresh rates.
*/
struct vesagtf_params {
unsigned margin_ppt; /* vertical margin size, percent * 10
* think parts-per-thousand */
unsigned min_porch; /* minimum front porch */
unsigned vsync_rqd; /* width of vsync in lines */
unsigned hsync_pct; /* hsync as % of total width */
unsigned min_vsbp; /* minimum vsync + back porch (usec) */
unsigned M; /* blanking formula gradient */
unsigned C; /* blanking formula offset */
unsigned K; /* blanking formula scaling factor */
unsigned J; /* blanking formula scaling factor */
};
/*
* Default values to use for params.
*/
#define VESAGTF_MARGIN_PPT 18 /* 1.8% */
#define VESAGTF_MIN_PORCH 1 /* minimum front porch */
#define VESAGTF_VSYNC_RQD 3 /* vsync width in lines */
#define VESAGTF_HSYNC_PCT 8 /* width of hsync % of total line */
#define VESAGTF_MIN_VSBP 550 /* min vsync + back porch (usec) */
#define VESAGTF_M 600 /* blanking formula gradient */
#define VESAGTF_C 40 /* blanking formula offset */
#define VESAGTF_K 128 /* blanking formula scaling factor */
#define VESAGTF_J 20 /* blanking formula scaling factor */
/*
* Use VESA GTF formula to generate monitor timings. Assumes default
* GTF parameters, non-interlaced, and no margins.
*/
void vesagtf_mode(unsigned x, unsigned y, unsigned refresh,
struct videomode *);
/*
* A more complete version, in case we ever want to use alternate GTF
* parameters. EDID 1.3 allows for "secondary GTF parameters".
*/
void vesagtf_mode_params(unsigned x, unsigned y, unsigned refresh,
struct vesagtf_params *, int flags, struct videomode *);
#define VESAGTF_FLAG_ILACE 0x0001 /* use interlace */
#define VESAGTF_FLAG_MARGINS 0x0002 /* use margins */
#endif /* _DEV_VIDEOMODE_VESAGTF_H */

View file

@ -0,0 +1,126 @@
/* $NetBSD: videomode.c,v 1.11 2011/03/30 18:46:32 jdc Exp $ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* generated from:
* NetBSD: modelines,v 1.9 2011/03/30 18:45:04 jdc Exp
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: videomode.c,v 1.11 2011/03/30 18:46:32 jdc Exp $");
#include <dev/videomode/videomode.h>
/*
* These macros help the modelines below fit on one line.
*/
#define HP VID_PHSYNC
#define HN VID_NHSYNC
#define VP VID_PVSYNC
#define VN VID_NVSYNC
#define I VID_INTERLACE
#define DS VID_DBLSCAN
#define M(nm,hr,vr,clk,hs,he,ht,vs,ve,vt,f) \
{ clk, hr, hs, he, ht, vr, vs, ve, vt, f, nm }
const struct videomode videomode_list[] = {
M("640x350x85",640,350,31500,672,736,832,382,385,445,HP|VN),
M("640x400x85",640,400,31500,672,736,832,401,404,445,HN|VP),
M("720x400x70",720,400,28320,738,846,900,412,414,449,HN|VP),
M("720x400x85",720,400,35500,756,828,936,401,404,446,HN|VP),
M("720x400x87",720,400,35500,738,846,900,421,423,449,HN|VN),
M("640x480x60",640,480,25175,656,752,800,490,492,525,HN|VN),
M("640x480x72",640,480,31500,664,704,832,489,492,520,HN|VN),
M("640x480x75",640,480,31500,656,720,840,481,484,500,HN|VN),
M("640x480x85",640,480,36000,696,752,832,481,484,509,HN|VN),
M("800x600x56",800,600,36000,824,896,1024,601,603,625,HP|VP),
M("800x600x60",800,600,40000,840,968,1056,601,605,628,HP|VP),
M("800x600x72",800,600,50000,856,976,1040,637,643,666,HP|VP),
M("800x600x75",800,600,49500,816,896,1056,601,604,625,HP|VP),
M("800x600x85",800,600,56250,832,896,1048,601,604,631,HP|VP),
M("1024x768x87i",1024,768,44900,1032,1208,1264,768,776,817,HP|VP|I),
M("1024x768x60",1024,768,65000,1048,1184,1344,771,777,806,HN|VN),
M("1024x768x70",1024,768,75000,1048,1184,1328,771,777,806,HN|VN),
M("1024x768x75",1024,768,78750,1040,1136,1312,769,772,800,HP|VP),
M("1024x768x85",1024,768,94500,1072,1168,1376,769,772,808,HP|VP),
M("1024x768x89",1024,768,100000,1108,1280,1408,768,780,796,HP|VP),
M("1152x864x75",1152,864,108000,1216,1344,1600,865,868,900,HP|VP),
M("1280x768x75",1280,768,105640,1312,1712,1744,782,792,807,HN|VP),
M("1280x960x60",1280,960,108000,1376,1488,1800,961,964,1000,HP|VP),
M("1280x960x85",1280,960,148500,1344,1504,1728,961,964,1011,HP|VP),
M("1280x1024x60",1280,1024,108000,1328,1440,1688,1025,1028,1066,HP|VP),
M("1280x1024x70",1280,1024,126000,1328,1440,1688,1025,1028,1066,HP|VP),
M("1280x1024x75",1280,1024,135000,1296,1440,1688,1025,1028,1066,HP|VP),
M("1280x1024x85",1280,1024,157500,1344,1504,1728,1025,1028,1072,HP|VP),
M("1600x1200x60",1600,1200,162000,1664,1856,2160,1201,1204,1250,HP|VP),
M("1600x1200x65",1600,1200,175500,1664,1856,2160,1201,1204,1250,HP|VP),
M("1600x1200x70",1600,1200,189000,1664,1856,2160,1201,1204,1250,HP|VP),
M("1600x1200x75",1600,1200,202500,1664,1856,2160,1201,1204,1250,HP|VP),
M("1600x1200x85",1600,1200,229500,1664,1856,2160,1201,1204,1250,HP|VP),
M("1680x1050x60",1680,1050,147140,1784,1968,2256,1051,1054,1087,HP|VP),
M("1792x1344x60",1792,1344,204800,1920,2120,2448,1345,1348,1394,HN|VP),
M("1792x1344x75",1792,1344,261000,1888,2104,2456,1345,1348,1417,HN|VP),
M("1856x1392x60",1856,1392,218300,1952,2176,2528,1393,1396,1439,HN|VP),
M("1856x1392x75",1856,1392,288000,1984,2208,2560,1393,1396,1500,HN|VP),
M("1920x1440x60",1920,1440,234000,2048,2256,2600,1441,1444,1500,HN|VP),
M("1920x1440x75",1920,1440,297000,2064,2288,2640,1441,1444,1500,HN|VP),
M("832x624x74",832,624,57284,864,928,1152,625,628,667,HN|VN),
M("1152x768x54",1152,768,64995,1178,1314,1472,771,777,806,HP|VP),
M("1400x1050x60",1400,1050,122000,1488,1640,1880,1052,1064,1082,HP|VP),
M("1400x1050x74",1400,1050,155800,1464,1784,1912,1052,1064,1090,HP|VP),
M("1152x900x66",1152,900,94500,1192,1320,1528,902,906,937,HN|VN),
M("1152x900x76",1152,900,105560,1168,1280,1472,902,906,943,HN|VN),
/* Derived Double Scan Modes */
M("320x175x85",320,175,15750,336,368,416,191,192,222,HP|VN|DS),
M("320x200x85",320,200,15750,336,368,416,200,202,222,HN|VP|DS),
M("360x200x70",360,200,14160,369,423,450,206,207,224,HN|VP|DS),
M("360x200x85",360,200,17750,378,414,468,200,202,223,HN|VP|DS),
M("360x200x87",360,200,17750,369,423,450,210,211,224,HN|VN|DS),
M("320x240x60",320,240,12587,328,376,400,245,246,262,HN|VN|DS),
M("320x240x72",320,240,15750,332,352,416,244,246,260,HN|VN|DS),
M("320x240x75",320,240,15750,328,360,420,240,242,250,HN|VN|DS),
M("320x240x85",320,240,18000,348,376,416,240,242,254,HN|VN|DS),
M("400x300x56",400,300,18000,412,448,512,300,301,312,HP|VP|DS),
M("400x300x60",400,300,20000,420,484,528,300,302,314,HP|VP|DS),
M("400x300x72",400,300,25000,428,488,520,318,321,333,HP|VP|DS),
M("400x300x75",400,300,24750,408,448,528,300,302,312,HP|VP|DS),
M("400x300x85",400,300,28125,416,448,524,300,302,315,HP|VP|DS),
M("512x384x87i",512,384,22450,516,604,632,384,388,408,HP|VP|DS|I),
M("512x384x60",512,384,32500,524,592,672,385,388,403,HN|VN|DS),
M("512x384x70",512,384,37500,524,592,664,385,388,403,HN|VN|DS),
M("512x384x75",512,384,39375,520,568,656,384,386,400,HP|VP|DS),
M("512x384x85",512,384,47250,536,584,688,384,386,404,HP|VP|DS),
M("512x384x89",512,384,50000,554,640,704,384,390,398,HP|VP|DS),
M("576x432x75",576,432,54000,608,672,800,432,434,450,HP|VP|DS),
M("640x384x75",640,384,52820,656,856,872,391,396,403,HN|VP|DS),
M("640x480x60",640,480,54000,688,744,900,480,482,500,HP|VP|DS),
M("640x480x85",640,480,74250,672,752,864,480,482,505,HP|VP|DS),
M("640x512x60",640,512,54000,664,720,844,512,514,533,HP|VP|DS),
M("640x512x70",640,512,63000,664,720,844,512,514,533,HP|VP|DS),
M("640x512x75",640,512,67500,648,720,844,512,514,533,HP|VP|DS),
M("640x512x85",640,512,78750,672,752,864,512,514,536,HP|VP|DS),
M("800x600x60",800,600,81000,832,928,1080,600,602,625,HP|VP|DS),
M("800x600x65",800,600,87750,832,928,1080,600,602,625,HP|VP|DS),
M("800x600x70",800,600,94500,832,928,1080,600,602,625,HP|VP|DS),
M("800x600x75",800,600,101250,832,928,1080,600,602,625,HP|VP|DS),
M("800x600x85",800,600,114750,832,928,1080,600,602,625,HP|VP|DS),
M("840x525x60",840,525,73570,892,984,1128,525,527,543,HP|VP|DS),
M("896x672x60",896,672,102400,960,1060,1224,672,674,697,HN|VP|DS),
M("896x672x75",896,672,130500,944,1052,1228,672,674,708,HN|VP|DS),
M("928x696x60",928,696,109150,976,1088,1264,696,698,719,HN|VP|DS),
M("928x696x75",928,696,144000,992,1104,1280,696,698,750,HN|VP|DS),
M("960x720x60",960,720,117000,1024,1128,1300,720,722,750,HN|VP|DS),
M("960x720x75",960,720,148500,1032,1144,1320,720,722,750,HN|VP|DS),
M("416x312x74",416,312,28642,432,464,576,312,314,333,HN|VN|DS),
M("576x384x54",576,384,32497,589,657,736,385,388,403,HP|VP|DS),
M("700x525x60",700,525,61000,744,820,940,526,532,541,HP|VP|DS),
M("700x525x74",700,525,77900,732,892,956,526,532,545,HP|VP|DS),
M("576x450x66",576,450,47250,596,660,764,451,453,468,HN|VN|DS),
M("576x450x76",576,450,52780,584,640,736,451,453,471,HN|VN|DS),
};
const int videomode_count = 46;

View file

@ -0,0 +1,73 @@
/* $NetBSD: videomode.h,v 1.3 2011/04/09 18:22:31 jdc Exp $ */
/*
* Copyright (c) 2001, 2002 Bang Jun-Young
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_VIDEOMODE_H
#define _DEV_VIDEOMODE_H
struct videomode {
int dot_clock; /* Dot clock frequency in kHz. */
int hdisplay;
int hsync_start;
int hsync_end;
int htotal;
int vdisplay;
int vsync_start;
int vsync_end;
int vtotal;
int flags; /* Video mode flags; see below. */
const char *name;
};
/*
* Video mode flags.
*/
#define VID_PHSYNC 0x0001
#define VID_NHSYNC 0x0002
#define VID_PVSYNC 0x0004
#define VID_NVSYNC 0x0008
#define VID_INTERLACE 0x0010
#define VID_DBLSCAN 0x0020
#define VID_CSYNC 0x0040
#define VID_PCSYNC 0x0080
#define VID_NCSYNC 0x0100
#define VID_HSKEW 0x0200
#define VID_BCAST 0x0400
#define VID_PIXMUX 0x1000
#define VID_DBLCLK 0x2000
#define VID_CLKDIV2 0x4000
extern const struct videomode videomode_list[];
extern const int videomode_count;
const struct videomode *pick_mode_by_dotclock(int, int, int);
const struct videomode *pick_mode_by_ref(int, int, int);
void sort_modes(struct videomode *, struct videomode **, int);
#endif /* _DEV_VIDEOMODE_H */