link/graphics: Add support for EDID

This code is taken from an EDID reader written at Red Hat.

The key function is
int decode_edid(unsigned char *edid, int size, struct edid *out)

Which takes a pointer to an EDID blob, and a size, and decodes it into
a machine-independent format in out, which may be used for driving
chipsets. The EDID blob might come for IO, or a compiled-in EDID
BLOB, or CBFS.

Also included are the changes needed to use the EDID code on Link.

Change-Id: I66b275b8ed28fd77cfa5978bdec1eeef9e9425f1
Signed-off-by: Ronald G. Minnich <rminnich@google.com>
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-on: http://review.coreboot.org/2837
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Ronald G. Minnich 2013-03-13 14:35:01 -07:00 committed by Stefan Reinauer
parent a95a13bd47
commit b3b72f350e
5 changed files with 1857 additions and 362 deletions

66
src/include/edid.h Normal file
View File

@ -0,0 +1,66 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef EDID_H
#define EDID_H
/* structure for communicating EDID information from a raw EDID block to
* higher level functions.
* The size of the data types is not critical, so we leave them as
* unsigned int. We can move more into into this struct as needed.
*/
struct edid {
char manuf_name[4];
unsigned int model;
unsigned int serial;
unsigned int year;
unsigned int week;
unsigned int version[2];
unsigned int nonconformant;
unsigned int type;
unsigned int bpp;
unsigned int voltage;
unsigned int sync;
unsigned int xsize_cm;
unsigned int ysize_cm;
/* used to compute timing for graphics chips. */
unsigned char phsync;
unsigned char pvsync;
unsigned int ha;
unsigned int hbl;
unsigned int hso;
unsigned int hspw;
unsigned int hborder;
unsigned int va;
unsigned int vbl;
unsigned int vso;
unsigned int vspw;
unsigned int vborder;
/* it is unlikely we need these things. */
/* if one of these is non-zero, use that one. */
unsigned int aspect_landscape;
unsigned int aspect_portrait;
const char *range_class;
const char *syncmethod;
const char *stereo;
};
int decode_edid(unsigned char *edid, int size, struct edid *out);
#endif /* EDID_H */

View File

@ -82,6 +82,7 @@ ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c
ramstage-$(CONFIG_TRACE) += trace.c ramstage-$(CONFIG_TRACE) += trace.c
ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_COVERAGE) += libgcov.c
ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += edid.c
ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c

1388
src/lib/edid.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
#include <cpu/x86/mtrr.h> #include <cpu/x86/mtrr.h>
#include <cpu/amd/mtrr.h> #include <cpu/amd/mtrr.h>
#include <cpu/x86/msr.h> #include <cpu/x86/msr.h>
#include <edid.h>
#include "i915io.h" #include "i915io.h"
enum { enum {
@ -59,6 +60,18 @@ static unsigned short addrport;
static unsigned short dataport; static unsigned short dataport;
static unsigned int physbase; static unsigned int physbase;
extern int oprom_is_loaded; extern int oprom_is_loaded;
static u32 htotal, hblank, hsync, vtotal, vblank, vsync;
const u32 link_edid_data[] = {
0xffffff00, 0x00ffffff, 0x0379e430, 0x00000000,
0x04011500, 0x96121ba5, 0xa2d54f02, 0x26935259,
0x00545017, 0x01010000, 0x01010101, 0x01010101,
0x01010101, 0x6f6d0101, 0xa4a0a000, 0x20306031,
0xb510003a, 0x19000010, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x4c00fe00,
0x69442047, 0x616c7073, 0x20200a79, 0xfe000000,
0x31504c00, 0x45513932, 0x50532d31, 0x24003141,
};
#define READ32(addr) io_i915_READ32(addr) #define READ32(addr) io_i915_READ32(addr)
#define WRITE32(val, addr) io_i915_WRITE32(val, addr) #define WRITE32(val, addr) io_i915_WRITE32(val, addr)
@ -178,6 +191,8 @@ static int run(int index)
int i, prev = 0; int i, prev = 0;
struct iodef *id, *lastidread = 0; struct iodef *id, *lastidread = 0;
unsigned long u, t; unsigned long u, t;
if (index >= niodefs)
return index;
/* state machine! */ /* state machine! */
for(i = index, id = &iodefs[i]; id->op; i++, id++){ for(i = index, id = &iodefs[i]; id->op; i++, id++){
switch(id->op){ switch(id->op){
@ -253,6 +268,8 @@ int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio,
int i915lightup(unsigned int pphysbase, unsigned int piobase, int i915lightup(unsigned int pphysbase, unsigned int piobase,
unsigned int pmmio, unsigned int pgfx) unsigned int pmmio, unsigned int pgfx)
{ {
static struct edid edid;
int index; int index;
u32 auxin[16], auxout[16]; u32 auxin[16], auxout[16];
mmio = (void *)pmmio; mmio = (void *)pmmio;
@ -260,13 +277,35 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase,
dataport = addrport + 4; dataport = addrport + 4;
physbase = pphysbase; physbase = pphysbase;
graphics = pgfx; graphics = pgfx;
printk(BIOS_SPEW, printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p"
"i915lightup: graphics %p mmio %p"
"addrport %04x physbase %08x\n", "addrport %04x physbase %08x\n",
(void *)graphics, mmio, addrport, physbase); (void *)graphics, mmio, addrport, physbase);
globalstart = rdtscll(); globalstart = rdtscll();
decode_edid((unsigned char *)&link_edid_data, sizeof(link_edid_data), &edid);
htotal = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16);
printk(BIOS_SPEW, "I915_WRITE(HTOTAL(pipe), %08x)\n", htotal);
hblank = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16);
printk(BIOS_SPEW, "I915_WRITE(HBLANK(pipe),0x%08x)\n", hblank);
hsync = (edid.ha + edid.hso - 1) |
((edid.ha + edid.hso + edid.hspw- 1) << 16);
printk(BIOS_SPEW, "I915_WRITE(HSYNC(pipe),0x%08x)\n", hsync);
vtotal = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16);
printk(BIOS_SPEW, "I915_WRITE(VTOTAL(pipe), %08x)\n", vtotal);
vblank = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16);
printk(BIOS_SPEW, "I915_WRITE(VBLANK(pipe),0x%08x)\n", vblank);
vsync = (edid.va + edid.vso - 1) |((edid.va + edid.vso + edid.vspw- 1) << 16);
printk(BIOS_SPEW, "I915_WRITE(VSYNC(pipe),0x%08x)\n", vsync);
printk(BIOS_SPEW, "Table has %d elements\n", niodefs); printk(BIOS_SPEW, "Table has %d elements\n", niodefs);
index = run(0); index = run(0);
printk(BIOS_SPEW, "Run returns %d\n", index); printk(BIOS_SPEW, "Run returns %d\n", index);
auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_DPCD_REV<<8|0xe; auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_DPCD_REV<<8|0xe;

View File

@ -352,6 +352,7 @@ struct iodef iodefs[] = {
{M, 1, "[drm:intel_wait_for_vblank], vblank wait timed out", 0x0, 0xcf8e64, 0}, {M, 1, "[drm:intel_wait_for_vblank], vblank wait timed out", 0x0, 0xcf8e64, 0},
{M, 1, "[drm:intel_dp_mode_fixup], Display port link bw 0a lane count 4clock 270000", 0x0, 0xcf8e64, 0}, {M, 1, "[drm:intel_dp_mode_fixup], Display port link bw 0a lane count 4clock 270000", 0x0, 0xcf8e64, 0},
{M, 1, "[drm:drm_crtc_helper_set_mode], [CRTC:3]", 0x0, 0xcf8e64, 0}, {M, 1, "[drm:drm_crtc_helper_set_mode], [CRTC:3]", 0x0, 0xcf8e64, 0},
{I, 0, "(null)", 0x0, 0xcf8e64, 0}, }; {I,},
};
int niodefs = sizeof (iodefs) / sizeof (iodefs[0]); int niodefs = sizeof (iodefs) / sizeof (iodefs[0]);