/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2008-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
 */

#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include "southbridge/intel/i82801gx/i82801gx.h"
#include "southbridge/intel/i82801gx/nvs.h"
#include <ec/acpi/ec.h>
#include "ec_oem.c"

#define MAX_LCD_BRIGHTNESS 0xd8

/* The southbridge SMI handler checks whether gnvs has a
 * valid pointer before calling the trap handler
 */
extern global_nvs_t *gnvs;

int mainboard_io_trap_handler(int smif)
{
	u8 reg8;
	u32 reg32;

	switch (smif) {
	case 0x2b:
		printk(BIOS_DEBUG, "CPU power state switch\n");
		// TODO, move to CPU handler?
		break;
	case 0x3d:
		printk(BIOS_DEBUG, "Enable C-State SMM coordination\n");
		// TODO, move to CPU handler?
		break;
	case 0x46:
		printk(BIOS_DEBUG, "S3 DTS SMI (completely re-enable DTS)\n");
		// TODO, move to CPU handler?
		break;
	case 0x47:
		printk(BIOS_DEBUG, "S4 DTS SMI (Update NVS DTS temperature)\n");
		// TODO, move to CPU handler?
		break;
	case 0xc0:
		printk(BIOS_DEBUG, "Disable RF\n");
		// TODO
		break;
	case 0xd0:
		printk(BIOS_DEBUG, "ACBS LAN Power on\n");
		// TODO
		break;
	case 0xd1:
		printk(BIOS_DEBUG, "ACBS LAN Power off\n");
		// TODO
		break;
	case 0xd2:
		printk(BIOS_DEBUG, "Check AC status\n");
		// TODO
		break;
	case 0xd3:
		printk(BIOS_DEBUG, "Enable Bluetooth\n");
		// TODO
		break;
	case 0xd4:
		printk(BIOS_DEBUG, "Disable Bluetooth\n");
		// TODO
		break;
	case 0xd5:
		printk(BIOS_DEBUG, "Set Brightness\n");
		reg8 = gnvs->brtl;
		printk(BIOS_DEBUG, "brtl: %x\n", reg8);
		ec_write(0x17, reg8);
		break;
	case 0xd6:
		printk(BIOS_DEBUG, "Get Brightness\n");
		reg8 = ec_read(0x17);
		printk(BIOS_DEBUG, "brtl: %x\n", reg8);
		gnvs->brtl = reg8;
		break;
	case 0xd7:
		printk(BIOS_DEBUG, "Get ECO mode status\n");
		// TODO
		break;
	case 0xd8:
		printk(BIOS_DEBUG, "Get sunlight readable status\n");
		// TODO
		break;
	case 0xd9:
		printk(BIOS_DEBUG, "Get docking connection\n");
		// TODO
		break;
	case 0xda:
		printk(BIOS_DEBUG, "Power off docking\n");
		// TODO
		break;
	case 0xdc:
		printk(BIOS_DEBUG, "EC: Turn on LED on ECO enable\n");
		// TODO
		break;
	case 0xdd:
		printk(BIOS_DEBUG, "EC: Turn off LED on ECO disable\n");
		// TODO
		break;
	case 0xde:
		printk(BIOS_DEBUG, "LAN power off\n");
		reg32 = inl(DEFAULT_GPIOBASE + GP_LVL);
		reg32 |= (1 << 24);			// Disable LAN Power
		outl(reg32, DEFAULT_GPIOBASE + GP_LVL);
		break;
	case 0xdf:
		printk(BIOS_DEBUG, "RF enable\n");
		// TODO
		break;
	case 0xe0:
		printk(BIOS_DEBUG, "Get RTC wake flag\n");
		// TODO
		break;
	case 0xe1:
		printk(BIOS_DEBUG, "Hotkey function\n");
		// TODO
		break;
	case 0xe3:
		printk(BIOS_DEBUG, "ECO disable\n");
		// TODO
		break;
	default:
		return 0;
	}

	/* gnvs->smif:
	 *   On success, the IO Trap Handler returns 0
	 *   On failure, the IO Trap Handler returns a value != 0
	 */
	gnvs->smif = 0;
	return 1;
}

static void mainboard_smi_hotkey(u8 hotkey)
{
	u8 reg8;

	switch (hotkey) {
	case 0x3b: break; // Fn+F1
	case 0x3c: break; // Fn+F2
	case 0x3d: break; // Fn+F3
	case 0x3e: break; // Fn+F4
	case 0x3f: break; // Fn+F5
	case 0x40:        // Fn+F6 (Decrease Display Brightness)
		   reg8 = ec_read(0x17);
		   reg8 = (reg8 > 8) ? (reg8 - 8) : 0;
		   ec_write(0x17, reg8);
		   return;
	case 0x41:        // Fn+F7 (Increase Display Brightness)
		   reg8 = ec_read(0x17);
		   reg8 += 8;
		   reg8 = (reg8 >= MAX_LCD_BRIGHTNESS) ? MAX_LCD_BRIGHTNESS : reg8;
		   ec_write(0x17, reg8);
		   return;
	case 0x42: break; // Fn+F8
	case 0x43: break; // Fn+F9
	case 0x44: break; // Fn+F10
	case 0x57: break; // Fn+F11
	case 0x58: break; // Fn+F12
	}
	printk(BIOS_DEBUG, "EC hotkey: %02x\n", hotkey);
}

void mainboard_smi_gpi(u32 gpi_sts)
{
	u8 source, hotkey;
	send_ec_oem_command(0x5c);
	source = recv_ec_oem_data();

	switch (source) {
	case 0:
		// Some kind of ACK?
		break;
	case 1:
		send_ec_oem_command(0x59);
		hotkey = recv_ec_oem_data();
		mainboard_smi_hotkey(hotkey);
		break;
	default:
		printk(BIOS_DEBUG, "EC SMI source: %02x\n", source);
	}
}

