FOX_WTM2: First pass at FUI.

This lights up the display. We don't get graphics but we are missing the gttsetup
at this point, so that is no shock. The real shock is that anything works at all.

Change-Id: I03fc470334e96878aeb8465044b3cc9c90378735
Signed-off-by: Ronald G. Minnich <rminnich@google.com>
Signed-off-by: Gabe Black <gabeblack@chromium.org>
Reviewed-on: http://review.coreboot.org/3634
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Ronald G. Minnich 2013-03-28 17:01:43 -07:00 committed by Stefan Reinauer
parent f42b83e958
commit 2a66d6b804
9 changed files with 12365 additions and 1 deletions

View File

@ -16,6 +16,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select EXTERNAL_MRC_BLOB
select CACHE_ROM
select MARK_GRAPHICS_MEM_WRCOMB
select MAINBOARD_HAS_NATIVE_VGA_INIT
config MAINBOARD_DIR
string

View File

@ -19,5 +19,8 @@
romstage-$(CONFIG_CHROMEOS) += chromeos.c
ramstage-$(CONFIG_CHROMEOS) += chromeos.c
ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += i915.c
ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += i915io.c
ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += intel_dp.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c

View File

@ -0,0 +1,239 @@
/*
* Copyright 2013 Google Inc.
* Copyright © 2008 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef _DRM_DP_HELPER_H_
#define _DRM_DP_HELPER_H_
/* From the VESA DisplayPort spec */
#define AUX_NATIVE_WRITE 0x8
#define AUX_NATIVE_READ 0x9
#define AUX_I2C_WRITE 0x0
#define AUX_I2C_READ 0x1
#define AUX_I2C_STATUS 0x2
#define AUX_I2C_MOT 0x4
#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
#define AUX_NATIVE_REPLY_NACK (0x1 << 4)
#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
#define AUX_I2C_REPLY_ACK (0x0 << 6)
#define AUX_I2C_REPLY_NACK (0x1 << 6)
#define AUX_I2C_REPLY_DEFER (0x2 << 6)
#define AUX_I2C_REPLY_MASK (0x3 << 6)
/* AUX CH addresses */
/* DPCD */
#define DP_DPCD_REV 0x000
#define DP_MAX_LINK_RATE 0x001
#define DP_MAX_LANE_COUNT 0x002
# define DP_MAX_LANE_COUNT_MASK 0x1f
# define DP_TPS3_SUPPORTED (1 << 6)
# define DP_ENHANCED_FRAME_CAP (1 << 7)
#define DP_MAX_DOWNSPREAD 0x003
# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6)
#define DP_NORP 0x004
#define DP_DOWNSTREAMPORT_PRESENT 0x005
# define DP_DWN_STRM_PORT_PRESENT (1 << 0)
# define DP_DWN_STRM_PORT_TYPE_MASK 0x06
/* 00b = DisplayPort */
/* 01b = Analog */
/* 10b = TMDS or HDMI */
/* 11b = Other */
# define DP_FORMAT_CONVERSION (1 << 3)
#define DP_MAIN_LINK_CHANNEL_CODING 0x006
#define DP_EDP_CONFIGURATION_CAP 0x00d
#define DP_TRAINING_AUX_RD_INTERVAL 0x00e
#define DP_PSR_SUPPORT 0x070
# define DP_PSR_IS_SUPPORTED 1
#define DP_PSR_CAPS 0x071
# define DP_PSR_NO_TRAIN_ON_EXIT 1
# define DP_PSR_SETUP_TIME_330 (0 << 1)
# define DP_PSR_SETUP_TIME_275 (1 << 1)
# define DP_PSR_SETUP_TIME_220 (2 << 1)
# define DP_PSR_SETUP_TIME_165 (3 << 1)
# define DP_PSR_SETUP_TIME_110 (4 << 1)
# define DP_PSR_SETUP_TIME_55 (5 << 1)
# define DP_PSR_SETUP_TIME_0 (6 << 1)
# define DP_PSR_SETUP_TIME_MASK (7 << 1)
# define DP_PSR_SETUP_TIME_SHIFT 1
/* link configuration */
#define DP_LINK_BW_SET 0x100
# define DP_LINK_BW_1_62 0x06
# define DP_LINK_BW_2_7 0x0a
# define DP_LINK_BW_5_4 0x14
#define DP_LANE_COUNT_SET 0x101
# define DP_LANE_COUNT_MASK 0x0f
# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
#define DP_TRAINING_PATTERN_SET 0x102
# define DP_TRAINING_PATTERN_DISABLE 0
# define DP_TRAINING_PATTERN_1 1
# define DP_TRAINING_PATTERN_2 2
# define DP_TRAINING_PATTERN_3 3
# define DP_TRAINING_PATTERN_MASK 0x3
# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
# define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
# define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
#define DP_TRAINING_LANE0_SET 0x103
#define DP_TRAINING_LANE1_SET 0x104
#define DP_TRAINING_LANE2_SET 0x105
#define DP_TRAINING_LANE3_SET 0x106
# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
# define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
#define DP_DOWNSPREAD_CTRL 0x107
# define DP_SPREAD_AMP_0_5 (1 << 4)
#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
# define DP_SET_ANSI_8B10B (1 << 0)
#define DP_PSR_EN_CFG 0x170
# define DP_PSR_ENABLE (1 << 0)
# define DP_PSR_MAIN_LINK_ACTIVE (1 << 1)
# define DP_PSR_CRC_VERIFICATION (1 << 2)
# define DP_PSR_FRAME_CAPTURE (1 << 3)
#define DP_DEVICE_SERVICE_IRQ_VECTOR 0x201
# define DP_REMOTE_CONTROL_COMMAND_PENDING (1 << 0)
# define DP_AUTOMATED_TEST_REQUEST (1 << 1)
# define DP_CP_IRQ (1 << 2)
# define DP_SINK_SPECIFIC_IRQ (1 << 6)
#define DP_EDP_CONFIGURATION_SET 0x10a
#define DP_LANE0_1_STATUS 0x202
#define DP_LANE2_3_STATUS 0x203
# define DP_LANE_CR_DONE (1 << 0)
# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
# define DP_LANE_SYMBOL_LOCKED (1 << 2)
#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \
DP_LANE_CHANNEL_EQ_DONE | \
DP_LANE_SYMBOL_LOCKED)
#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
#define DP_INTERLANE_ALIGN_DONE (1 << 0)
#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
#define DP_LINK_STATUS_UPDATED (1 << 7)
#define DP_SINK_STATUS 0x205
#define DP_RECEIVE_PORT_0_STATUS (1 << 0)
#define DP_RECEIVE_PORT_1_STATUS (1 << 1)
#define DP_ADJUST_REQUEST_LANE0_1 0x206
#define DP_ADJUST_REQUEST_LANE2_3 0x207
# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
# define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
# define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
# define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
# define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
# define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
#define DP_TEST_REQUEST 0x218
# define DP_TEST_LINK_TRAINING (1 << 0)
# define DP_TEST_LINK_PATTERN (1 << 1)
# define DP_TEST_LINK_EDID_READ (1 << 2)
# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */
#define DP_TEST_LINK_RATE 0x219
# define DP_LINK_RATE_162 (0x6)
# define DP_LINK_RATE_27 (0xa)
#define DP_TEST_LANE_COUNT 0x220
#define DP_TEST_PATTERN 0x221
#define DP_TEST_RESPONSE 0x260
# define DP_TEST_ACK (1 << 0)
# define DP_TEST_NAK (1 << 1)
# define DP_TEST_EDID_CHECKSUM_WRITE (1 << 2)
#define DP_SET_POWER 0x600
# define DP_SET_POWER_D0 0x1
# define DP_SET_POWER_D3 0x2
#define DP_PSR_ERROR_STATUS 0x2006
# define DP_PSR_LINK_CRC_ERROR (1 << 0)
# define DP_PSR_RFB_STORAGE_ERROR (1 << 1)
#define DP_PSR_ESI 0x2007
# define DP_PSR_CAPS_CHANGE (1 << 0)
#define DP_PSR_STATUS 0x2008
# define DP_PSR_SINK_INACTIVE 0
# define DP_PSR_SINK_ACTIVE_SRC_SYNCED 1
# define DP_PSR_SINK_ACTIVE_RFB 2
# define DP_PSR_SINK_ACTIVE_SINK_SYNCED 3
# define DP_PSR_SINK_ACTIVE_RESYNC 4
# define DP_PSR_SINK_INTERNAL_ERROR 7
# define DP_PSR_SINK_STATE_MASK 0x07
#define MODE_I2C_START 1
#define MODE_I2C_WRITE 2
#define MODE_I2C_READ 4
#define MODE_I2C_STOP 8
#endif /* _DRM_DP_HELPER_H_ */

View File

@ -0,0 +1,405 @@
/*
* 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
*/
#include <types.h>
#include <string.h>
#include <stdlib.h>
#include <device/device.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <device/pci_ops.h>
#include <console/console.h>
#include <delay.h>
#include <pc80/mc146818rtc.h>
#include <arch/acpi.h>
#include <arch/io.h>
#include <arch/interrupt.h>
#include <arch/coreboot_tables.h>
#include "hda_verb.h"
#include <smbios.h>
#include <device/pci.h>
#include <ec/google/chromeec/ec.h>
#include <cbfs_core.h>
#include <cpu/x86/tsc.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/mtrr.h>
#include <cpu/amd/mtrr.h>
#include <cpu/x86/msr.h>
#include <edid.h>
#include "i915io.h"
enum {
vmsg = 1, vio = 2, vspin = 4,
};
static int verbose = 0;
static unsigned int *mmio;
static unsigned int graphics;
static unsigned short addrport;
static unsigned short dataport;
static unsigned int physbase;
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 WRITE32(val, addr) io_i915_WRITE32(val, addr)
static char *regname(unsigned long addr)
{
static char name[16];
sprintf(name, "0x%lx", addr);
return name;
}
unsigned long io_i915_READ32(unsigned long addr)
{
unsigned long val;
outl(addr, addrport);
val = inl(dataport);
if (verbose & vio)printk(BIOS_SPEW, "%s: Got %08lx\n", regname(addr), val);
return val;
}
void io_i915_WRITE32(unsigned long val, unsigned long addr)
{
if (verbose & vio)printk(BIOS_SPEW, "%s: outl %08lx\n", regname(addr), val);
outl(addr, addrport);
outl(val, dataport);
}
/*
2560
4 words per
4 *p
10240
4k bytes per page
4096/p
2.50
1700 lines
1700 * p
4250.00
PTEs
*/
static void
setgtt(int start, int end, unsigned long base, int inc)
{
int i;
for(i = start; i < end; i++){
u32 word = base + i*inc;
WRITE32(word|1,(i*4)|1);
}
}
static unsigned long tickspermicrosecond = 1795;
static unsigned long long globalstart;
static unsigned long
microseconds(unsigned long long start, unsigned long long end)
{
unsigned long ret;
ret = ((end - start)/tickspermicrosecond);
return ret;
}
static unsigned long globalmicroseconds(void)
{
return microseconds(globalstart, rdtscll());
}
extern struct iodef iodefs[];
extern int niodefs;
static int i915_init_done = 0;
/* fill the palette. This runs when the P opcode is hit. */
static void palette(void)
{
int i;
unsigned long color = 0;
for(i = 0; i < 256; i++, color += 0x010101){
io_i915_WRITE32(color, _LGC_PALETTE_A + (i<<2));
}
}
int vbe_mode_info_valid(void);
int vbe_mode_info_valid(void)
{
return i915_init_done;
}
void fill_lb_framebuffer(struct lb_framebuffer *framebuffer);
void fill_lb_framebuffer(struct lb_framebuffer *framebuffer)
{
printk(BIOS_SPEW, "fill_lb_framebuffer: graphics is %p\n", (void *)graphics);
framebuffer->physical_address = graphics;
framebuffer->x_resolution = 2560;
framebuffer->y_resolution = 1700;
framebuffer->bytes_per_line = 10240;
framebuffer->bits_per_pixel = 32;
framebuffer->red_mask_pos = 16;
framebuffer->red_mask_size = 8;
framebuffer->green_mask_pos = 8;
framebuffer->green_mask_size = 8;
framebuffer->blue_mask_pos = 0;
framebuffer->blue_mask_size = 8;
framebuffer->reserved_mask_pos = 0;
framebuffer->reserved_mask_size = 0;
}
static unsigned long times[4096];
static int run(int index)
{
int i, prev = 0;
struct iodef *id, *lastidread = 0;
unsigned long u, t;
if (index >= niodefs)
return index;
/* state machine! */
for(i = index, id = &iodefs[i]; id->op; i++, id++){
switch(id->op){
case M:
if (verbose & vmsg) printk(BIOS_SPEW, "%ld: %s\n",
globalmicroseconds(), id->msg);
break;
case P:
palette();
break;
case R:
u = READ32(id->addr);
if (verbose & vio)
printk(BIOS_SPEW, "\texpect %08lx\n", id->data);
/* we're looking for something. */
if (lastidread->addr == id->addr){
/* they're going to be polling.
* just do it 1000 times
*/
for(t = 0; t < 1000 && id->data != u; t++){
u = READ32(id->addr);
}
if (verbose & vspin) printk(BIOS_SPEW,
"%s: # loops %ld got %08lx want %08lx\n",
regname(id->addr),
t, u, id->data);
}
lastidread = id;
break;
case W:
WRITE32(id->data, id->addr);
if (id->addr == PCH_PP_CONTROL){
if (verbose & vio)
printk(BIOS_SPEW, "PCH_PP_CONTROL\n");
switch(id->data & 0xf){
case 8: break;
case 7: break;
default: udelay(100000);
if (verbose & vio)
printk(BIOS_SPEW, "U %d\n", 100000);
}
}
break;
case V:
if (id->count < 8){
prev = verbose;
verbose = id->count;
} else {
verbose = prev;
}
printk(BIOS_SPEW, "Change verbosity to %d\n", verbose);
break;
case I:
printk(BIOS_SPEW, "run: return %d\n", i+1);
return i+1;
break;
default:
printk(BIOS_SPEW, "BAD TABLE, opcode %d @ %d\n", id->op, i);
return -1;
}
if (id->udelay)
udelay(id->udelay);
if (i < ARRAY_SIZE(times))
times[i] = globalmicroseconds();
}
printk(BIOS_SPEW, "run: return %d\n", i);
return i+1;
}
int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio,
unsigned int gfx);
int i915lightup(unsigned int pphysbase, unsigned int piobase,
unsigned int pmmio, unsigned int pgfx)
{
static struct edid edid;
int index;
u32 auxin[16], auxout[16];
mmio = (void *)pmmio;
addrport = piobase;
dataport = addrport + 4;
physbase = pphysbase;
graphics = pgfx;
printk(BIOS_SPEW,
"i915lightup: graphics %p mmio %p"
"addrport %04x physbase %08x\n",
(void *)graphics, mmio, addrport, physbase);
globalstart = rdtscll();
index = run(0);
if (0){
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);
index = run(0);
printk(BIOS_SPEW, "Run returns %d\n", index);
auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_DPCD_REV<<8|0xe;
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 14);
auxout[0] = 0<<31 /* i2c */|1<<30|0x0<<28/*W*/|0x0<<8|0x0;
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0);
index = run(index);
printk(BIOS_SPEW, "Run returns %d\n", index);
auxout[0] = 0<<31 /* i2c */|0<<30|0x0<<28/*W*/|0x0<<8|0x0;
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0);
index = run(index);
printk(BIOS_SPEW, "Run returns %d\n", index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_SET_POWER<<8|0x0;
auxout[1] = 0x01000000;
/* DP_SET_POWER_D0 | DP_PSR_SINK_INACTIVE |
* (0x0<<13602104)|0x00000001*/ /* broken, fix. */
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_LINK_BW_SET<<8|0x8;
auxout[1] = 0x0a840000;
/*( DP_LINK_BW_2_7 &0xa)|0x0000840a*/
auxout[2] = 0x00000000;
auxout[3] = 0x01000000;
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 13, auxin, 0);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
auxout[1] = 0x21000000;
/* DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE |
* DP_SYMBOL_ERROR_COUNT_BOTH |0x00000021*/
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3;
auxout[1] = 0x00000000;
/* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5;
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
auxout[1] = 0x22000000;
/* DP_TRAINING_PATTERN_2 | DP_LINK_SCRAMBLING_DISABLE |
* DP_SYMBOL_ERROR_COUNT_BOTH |0x00000022*/
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3;
auxout[1] = 0x00000000;
/* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5;
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5);
index = run(index);
auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
auxout[1] = 0x00000000;
/* DP_TRAINING_PATTERN_DISABLE | DP_LINK_QUAL_PATTERN_DISABLE |
* DP_SYMBOL_ERROR_COUNT_BOTH |0x00000000*/
intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
index = run(index);
}
if (index != niodefs)
printk(BIOS_ERR, "Left over IO work in i915_lightup"
" -- this is likely a table error. "
"Only %d of %d were done.\n", index, niodefs);
printk(BIOS_SPEW, "DONE startup\n");
verbose = 0;
/* GTT is the Global Translation Table for the graphics pipeline.
* It is used to translate graphics addresses to physical
* memory addresses. As in the CPU, GTTs map 4K pages.
* There are 32 bits per pixel, or 4 bytes,
* which means 1024 pixels per page.
* There are 4250 GTTs on Link:
* 2650 (X) * 1700 (Y) pixels / 1024 pixels per page.
* The setgtt function adds a further bit of flexibility:
* it allows you to set a range (the first two parameters) to point
* to a physical address (third parameter);the physical address is
* incremented by a count (fourth parameter) for each GTT in the
* range.
* Why do it this way? For ultrafast startup,
* we can point all the GTT entries to point to one page,
* and set that page to 0s:
* memset(physbase, 0, 4096);
* setgtt(0, 4250, physbase, 0);
* this takes about 2 ms, and is a win because zeroing
* the page takes a up to 200 ms. We will be exploiting this
* trick in a later rev of this code.
* This call sets the GTT to point to a linear range of pages
* starting at physbase.
*/
setgtt(0, FRAME_BUFFER_PAGES, physbase, 4096);
printk(BIOS_SPEW, "memset %p to 0 for %d bytes\n",
(void *)graphics, FRAME_BUFFER_BYTES);
memset((void *)graphics, 0, FRAME_BUFFER_BYTES);
printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds());
i915_init_done = 1;
oprom_is_loaded = 1;
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2012 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
*/
#include "i915_reg.h"
#include "drm_dp_helper.h"
/* things that are, strangely, not defined anywhere? */
#define PCH_PP_UNLOCK 0xabcd0000
#define WMx_LP_SR_EN (1<<31)
/* Google Link-specific defines */
/* how many 4096-byte pages do we need for the framebuffer?
* There are 32 bits per pixel, or 4 bytes,
* which means 1024 pixels per page.
* HencetThere are 4250 GTTs on Link:
* 2650 (X) * 1700 (Y) pixels / 1024 pixels per page.
*/
#define FRAME_BUFFER_PAGES ((2560*1700)/1024)
#define FRAME_BUFFER_BYTES (FRAME_BUFFER_PAGES*4096)
/* One-letter commands for code not mean to be ready for humans.
* The code was generated by a set of programs/scripts.
* M print out a kernel message
* R read a register. We do these mainly to ensure that if hardware wanted
* the register read, it was read; also, in debug, we can see what was expected
* and what was found. This has proven *very* useful to get this debugged.
* The udelay, if non-zero, will make sure there is a
* udelay() call with the value.
* The count is from the kernel and tells us how many times this read was done.
* Also useful for debugging and the state
* machine uses the info to drive a poll.
* W Write a register
* V set verbosity. It's a bit mask.
* 0 -> nothing
* 1 -> print kernel messages
* 2 -> print IO ops
* 4 -> print the number of times we spin on a register in a poll
* 8 -> restore whatever the previous verbosity level was
* (only one deep stack)
*
* Again, this is not really meant for human consumption. There is not a poll
* operator as such because, sometimes, there is a read/write/read where the
* second read is a poll, and this chipset is so touchy I'm reluctant to move
* things around and/or delete too many reads.
*/
#define M 1
#define R 2
#define W 4
#define V 8
#define I 16
#define P 32
struct iodef {
unsigned char op;
unsigned int count;
const char *msg;
unsigned long addr;
unsigned long data;
unsigned long udelay;
};
/* i915.c */
unsigned long io_i915_READ32(unsigned long addr);
void io_i915_WRITE32(unsigned long val, unsigned long addr);
/* intel_dp.c */
u32 pack_aux(u32 *src, int src_bytes);
void unpack_aux(u32 src, u32 *dst, int dst_bytes);
int intel_dp_aux_ch(u32 ch_ctl, u32 ch_data, u32 *send, int send_bytes,
u32 *recv, int recv_size);

View File

@ -0,0 +1,168 @@
/*
* Copyright 2013 Google Inc.
* Copyright © 2008 Intel Corporation
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Keith Packard <keithp@keithp.com>
*
*/
#include <console/console.h>
#include <stdint.h>
#include <delay.h>
#include "i915io.h"
u32
pack_aux(u32 *src32, int src_bytes)
{
u8 *src = (u8 *)src32;
int i;
u32 v = 0;
if (src_bytes > 4)
src_bytes = 4;
for (i = 0; i < src_bytes; i++)
v |= ((u32) src[i]) << ((3-i) * 8);
return v;
}
void
unpack_aux(u32 src, u32 *dst32, int dst_bytes)
{
u8 *dst = (u8 *)dst32;
int i;
if (dst_bytes > 4)
dst_bytes = 4;
for (i = 0; i < dst_bytes; i++)
dst[i] = src >> ((3-i) * 8);
}
int
intel_dp_aux_ch(u32 ch_ctl, u32 ch_data, u32 *send, int send_bytes,
u32 *recv, int recv_size)
{
int i;
int recv_bytes;
u32 status;
u32 aux_clock_divider;
int try, precharge = 5;
/* The clock divider is based off the hrawclk,
* and would like to run at 2MHz. So, take the
* hrawclk value and divide by 2 and use that
*
* Note that PCH attached eDP panels should use a 125MHz input
* clock divider.
*/
/* 200 on link */
aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
/* Try to wait for any previous AUX channel activity */
for (try = 0; try < 3; try++) {
status = io_i915_READ32(ch_ctl);
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break;
udelay(1000);
}
if (try == 3) {
printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__);
printk(BIOS_SPEW, "dp_aux_ch not started status 0x%08lx\n",
io_i915_READ32(ch_ctl));
return -1;
}
/* Must try at least 3 times according to DP spec */
for (try = 0; try < 5; try++) {
/* Load the send data into the aux channel data registers */
for (i = 0; i < send_bytes; i += 4)
io_i915_WRITE32(send[i], ch_data + i);
/* Send the command and wait for it to complete */
io_i915_WRITE32(
DP_AUX_CH_CTL_SEND_BUSY |
DP_AUX_CH_CTL_TIME_OUT_400us |
(send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
(precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
(aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR, ch_ctl);
for (;;) {
status = io_i915_READ32(ch_ctl);
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break;
udelay(100);
}
/* Clear done status and any errors */
io_i915_WRITE32(
status |
DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR, ch_ctl);
if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR))
continue;
if (status & DP_AUX_CH_CTL_DONE)
break;
}
if ((status & DP_AUX_CH_CTL_DONE) == 0) {
printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__);
printk(BIOS_SPEW, "dp_aux_ch not done status 0x%08x\n", status);
return -1;
}
/* Check for timeout or receive error.
* Timeouts occur when the sink is not connected
*/
if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__);
printk(BIOS_SPEW, "dp_aux_ch receive error status 0x%08x\n", status);
return -1;
}
/* Timeouts occur when the device isn't connected, so they're
* "normal" -- don't fill the kernel log with these */
if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__);
printk(BIOS_SPEW, "dp_aux_ch timeout status 0x%08x\n", status);
return -1;
}
/* Unload any bytes sent back from the other side */
recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
if (recv_bytes > recv_size)
recv_bytes = recv_size;
for (i = 0; i < recv_bytes; i += 4)
unpack_aux(io_i915_READ32(ch_data + i),
recv + i, recv_bytes - i);
return recv_bytes;
}

View File

@ -190,20 +190,39 @@ static void gma_pm_init_post_vbios(struct device *dev)
static void gma_func0_init(struct device *dev)
{
u32 reg32;
u32 graphics_base; //, graphics_size;
/* IGD needs to be Bus Master */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
pci_write_config32(dev, PCI_COMMAND, reg32);
/* the BAR for graphics space is a well known number for
* sandy and ivy. And the resource code renumbers it.
* So it's almost like having two hardcodes.
*/
graphics_base = dev->resource_list[1].base;
/* Init graphics power management */
gma_pm_init_pre_vbios(dev);
/* PCI Init, will run VBIOS */
#if !CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT
printk(BIOS_SPEW, "Run the VBIOS init\n");
pci_dev_init(dev);
#endif
/* Post VBIOS init */
gma_pm_init_post_vbios(dev);
#if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT
printk(BIOS_SPEW, "NATIVE graphics, run native enable\n");
u32 iobase, mmiobase, physbase;
iobase = dev->resource_list[2].base;
mmiobase = dev->resource_list[0].base;
physbase = pci_read_config32(dev, 0x5c) & ~0xf;
int i915lightup(u32 physbase, u32 iobase, u32 mmiobase, u32 gfx);
i915lightup(physbase, iobase, mmiobase, graphics_base);
#endif
}
static void gma_set_subsystem(device_t dev, unsigned vendor, unsigned device)