summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/intel/gma/Kconfig4
-rw-r--r--src/drivers/intel/gma/Makefile.inc1
-rw-r--r--src/drivers/intel/gma/acpi.c135
-rw-r--r--src/drivers/intel/gma/i915.h7
-rw-r--r--src/drivers/intel/gma/igd.asl113
5 files changed, 260 insertions, 0 deletions
diff --git a/src/drivers/intel/gma/Kconfig b/src/drivers/intel/gma/Kconfig
index f4c7e45690..f726e6f1e7 100644
--- a/src/drivers/intel/gma/Kconfig
+++ b/src/drivers/intel/gma/Kconfig
@@ -36,3 +36,7 @@ config INTEL_EDID
config INTEL_INT15
bool
default n
+
+config INTEL_GMA_ACPI
+ bool
+ default n
diff --git a/src/drivers/intel/gma/Makefile.inc b/src/drivers/intel/gma/Makefile.inc
index 24599973b2..6bd9b71804 100644
--- a/src/drivers/intel/gma/Makefile.inc
+++ b/src/drivers/intel/gma/Makefile.inc
@@ -23,3 +23,4 @@ ramstage-$(CONFIG_INTEL_EDID) += edid.c vbt.c
ifeq ($(CONFIG_VGA_ROM_RUN),y)
ramstage-$(CONFIG_INTEL_INT15) += int15.c
endif
+ramstage-$(CONFIG_INTEL_GMA_ACPI) += acpi.c \ No newline at end of file
diff --git a/src/drivers/intel/gma/acpi.c b/src/drivers/intel/gma/acpi.c
new file mode 100644
index 0000000000..c3a9b8a266
--- /dev/null
+++ b/src/drivers/intel/gma/acpi.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2014 Vladimir Serbinenko
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <string.h>
+#include "i915.h"
+
+void
+drivers_intel_gma_displays_ssdt_generate(const struct i915_gpu_controller_info *conf)
+{
+ size_t i;
+ const char *names[] = { "UNK", "VGA", "TV", "DVI", "LCD" };
+ int counters[ARRAY_SIZE(names)];
+
+ memset(counters, 0, sizeof(counters));
+
+ acpigen_write_scope("\\_SB.PCI0.GFX0");
+
+ /*
+ Method (_DOD, 0)
+ {
+ Return (Package() {
+ 0x5a5a5a5a,
+ 0x5a5a5a5a,
+ 0x5a5a5a5a
+ })
+ }
+ */
+ acpigen_write_method("_DOD", 0);
+ acpigen_emit_byte(0xa4); /* ReturnOp. */
+ acpigen_write_package(conf->ndid);
+
+ for (i = 0; i < conf->ndid; i++) {
+ acpigen_write_dword (conf->did[i] | 0x80010000);
+ }
+ acpigen_pop_len(); /* End Package. */
+ acpigen_pop_len(); /* End Method. */
+
+ for (i = 0; i < conf->ndid; i++) {
+ char name[10];
+ char *ptr;
+ int kind;
+ kind = (conf->did[i] >> 8) & 0xf;
+ if (kind >= ARRAY_SIZE(names)) {
+ kind = 0;
+ }
+ strcpy(name, names[kind]);
+ for (ptr = name; *ptr; ptr++);
+ *ptr++ = counters[kind] + '0';
+ *ptr++ = '\0';
+ counters[kind]++;
+ acpigen_write_device(name);
+ /* Name (_ADR, 0x0410) */
+ acpigen_write_name_dword("_ADR", conf->did[i] & 0xffff);
+
+ /* ACPI brightness for LCD. */
+ if (kind == 4) {
+ /*
+ Method (_BCL, 0, NotSerialized)
+ {
+ Return (^^XBCL())
+ }
+ */
+ acpigen_write_method("_BCL", 0);
+ acpigen_emit_byte(0xa4); /* ReturnOp. */
+ acpigen_emit_namestring("^^XBCL");
+ acpigen_pop_len();
+
+ /*
+ Method (_BCM, 1, NotSerialized)
+ {
+ ^^XBCM(Arg0)
+ }
+ */
+ acpigen_write_method("_BCM", 1);
+ acpigen_emit_namestring("^^XBCM");
+ acpigen_emit_byte(0x68); /* Arg0Op. */
+ acpigen_pop_len();
+
+ /*
+ Method (_BQC, 0, NotSerialized)
+ {
+ Return (^^XBQC())
+ }
+ */
+ acpigen_write_method("_BQC", 0);
+ acpigen_emit_byte(0xa4); /* ReturnOp. */
+ acpigen_emit_namestring("^^XBQC");
+ acpigen_pop_len();
+ }
+
+ /*
+ Method(_DCS, 0)
+ {
+ Return (^^XDCS(<device number>))
+ }
+ */
+ acpigen_write_method("_DCS", 0);
+ acpigen_emit_byte(0xa4); /* ReturnOp. */
+ acpigen_emit_namestring("^^XDCS");
+ acpigen_write_byte(i);
+ acpigen_pop_len();
+
+ /*
+ Method(_DGS, 0)
+ {
+ Return (^^XDGS(<device number>))
+ }
+ */
+ acpigen_write_method("_DGS", 0);
+ acpigen_emit_byte(0xa4); /* ReturnOp. */
+ acpigen_emit_namestring("^^XDGS");
+ acpigen_write_byte(i);
+ acpigen_pop_len();
+
+ /*
+ Method(_DSS, 1)
+ {
+ ^^XDSS(0x5a, Arg0)
+ }
+ */
+ acpigen_write_method("_DSS", 0);
+ acpigen_emit_namestring("^^XDSS");
+ acpigen_write_byte(i);
+ acpigen_emit_byte(0x68); /* Arg0Op. */
+ acpigen_pop_len();
+
+ acpigen_pop_len();
+ }
+
+ acpigen_pop_len();
+}
diff --git a/src/drivers/intel/gma/i915.h b/src/drivers/intel/gma/i915.h
index ef9e68ee05..37e2e4910c 100644
--- a/src/drivers/intel/gma/i915.h
+++ b/src/drivers/intel/gma/i915.h
@@ -292,8 +292,15 @@ struct i915_gpu_controller_info
int link_frequency_270_mhz;
int lvds_num_lanes;
u32 backlight;
+ int ndid;
+ u32 did[5];
};
+void
+drivers_intel_gma_displays_ssdt_generate(const struct i915_gpu_controller_info *conf);
+const struct i915_gpu_controller_info *
+intel_gma_get_controller_info(void);
+
int i915lightup(unsigned int physbase, unsigned int mmio,
unsigned int gfx, unsigned int init_fb);
int panel_lightup(struct intel_dp *dp, unsigned int init_fb);
diff --git a/src/drivers/intel/gma/igd.asl b/src/drivers/intel/gma/igd.asl
new file mode 100644
index 0000000000..31e8fecbd0
--- /dev/null
+++ b/src/drivers/intel/gma/igd.asl
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * 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
+ */
+
+ External(LCD0, DeviceObj)
+
+ Name (BRCT, 0)
+
+ Method(BRID, 1, NotSerialized)
+ {
+ Store (Match (BRIG, MEQ, Arg0, MTR, Zero, 2), Local0)
+ If (LEqual (Local0, Ones))
+ {
+ Return (Subtract(SizeOf(BRIG), One))
+ }
+ Return (Local0)
+ }
+
+ Method (XBCL, 0, NotSerialized)
+ {
+ Store (1, BRCT)
+ Return (BRIG)
+ }
+
+ /* Display Output Switching */
+ Method (_DOS, 1)
+ {
+ /* Windows 2000 and Windows XP call _DOS to enable/disable
+ * Display Output Switching during init and while a switch
+ * is already active
+ */
+ Store (And(Arg0, 7), DSEN)
+ }
+
+ /* Using Notify is the right way. But Windows doesn't handle
+ it well. So use both method in a way to avoid double action.
+ */
+ Method (DECB, 0, NotSerialized)
+ {
+ If (BRCT)
+ {
+ Notify (LCD0, 0x87)
+ } Else {
+ Store (BRID (XBQC ()), Local0)
+ If (LNotEqual (Local0, 2))
+ {
+ Decrement (Local0)
+ }
+ XBCM (DerefOf (Index (BRIG, Local0)))
+ }
+ }
+
+ Method (INCB, 0, NotSerialized)
+ {
+ If (BRCT)
+ {
+ Notify (LCD0, 0x86)
+ } Else {
+ Store (BRID (XBQC ()), Local0)
+ If (LNotEqual (Local0, Subtract(SizeOf(BRIG), One)))
+ {
+ Increment (Local0)
+ }
+ XBCM (DerefOf (Index (BRIG, Local0)))
+ }
+ }
+
+ /* Device Current Status */
+ Method(XDCS, 1)
+ {
+ TRAP(1)
+ If (And(CSTE, ShiftLeft (1, Arg0))) {
+ Return (0x1f)
+ }
+ Return(0x1d)
+ }
+
+ /* Query Device Graphics State */
+ Method(XDGS, 1)
+ {
+ If (And(NSTE, ShiftLeft (1, Arg0))) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ /* Device Set State */
+ Method(XDSS, 2)
+ {
+ /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+ * display switch was completed
+ */
+ If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+ Store (NSTE, CSTE)
+ }
+ }