/*
 * This file is part of the coreboot project.
 *
 * Copyright 2018 Intel Corp.
 *
 * 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.
 */

#include <arch/acpi.h>
#include <baseboard/cbi_ssfc.h>
#include <baseboard/variants.h>
#include <boardid.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <device/pci_ops.h>
#include <drivers/i2c/generic/chip.h>
#include <ec/google/chromeec/ec.h>
#include <ec/ec.h>
#include <nhlt.h>
#include <smbios.h>
#include <soc/cpu.h>
#include <soc/gpio.h>
#include <soc/nhlt.h>
#include <soc/pci_devs.h>
#include <stdint.h>
#include <string.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <variant/ec.h>
#include <variant/gpio.h>

extern struct chip_operations drivers_i2c_generic_ops;
extern struct chip_operations drivers_i2c_da7219_ops;

static bool is_cnvi_held_in_reset(void)
{
	struct device *dev = dev_find_slot(0, PCH_DEVFN_CNVI);
	uint32_t reg = pci_read_config32(dev, PCI_VENDOR_ID);

	/*
	 * If vendor/device ID for CNVi reads as 0xffffffff, then it is safe to
	 * assume that it is being held in reset.
	 */
	if (reg == 0xffffffff)
		return true;

	return false;
}

static void disable_wifi_wake(void)
{
	static const struct pad_config wifi_wake_gpio[] = {
		PAD_NC(GPIO_119, UP_20K),
	};

	gpio_configure_pads(wifi_wake_gpio, ARRAY_SIZE(wifi_wake_gpio));
}

/*
 * GPIO_137 for two audio codecs right now has the different configuration so
 * if SSFC indicates that codec is different than default one then GPIO_137
 * needs to be overridden for the corresponding second source.
 */
static void gpio_modification_by_ssfc(struct pad_config *table, size_t num)
{
	/* For RT5682, GPIO 137 should be set as EDGE_BOTH. */
	const struct pad_config rt5682_gpio_137 = PAD_CFG_GPI_APIC_IOS(GPIO_137,
			NONE, DEEP, EDGE_BOTH, INVERT, HIZCRx1, DISPUPD);

	if (table == NULL || num == 0)
		return;

	/*
	 * Currently we only have the case of RT5682 as the second source. And
	 * in case of Ampton which used RT5682 as the default source, it didn't
	 * provide override_table right now so it will be returned ealier since
	 * table above is NULL.
	 */
	if (ssfc_get_audio_codec() != SSFC_AUDIO_CODEC_RT5682)
		return;

	while (num--) {
		if (table->pad == GPIO_137) {
			*table = rt5682_gpio_137;
			printk(BIOS_INFO,
				"Configure GPIO 137 based on SSFC.\n");
			return;
		}

		table++;
	}
}

static void mainboard_init(void *chip_info)
{
	int boardid;
	const struct pad_config *base_pads;
	const struct pad_config *override_pads;
	size_t base_num, override_num;

	boardid = board_id();
	printk(BIOS_INFO, "Board ID: %d\n", boardid);

	base_pads = variant_base_gpio_table(&base_num);
	override_pads = variant_override_gpio_table(&override_num);
	gpio_modification_by_ssfc((struct pad_config *)override_pads,
			override_num);

	gpio_configure_pads_with_override(base_pads, base_num,
			override_pads, override_num);

	if (!is_cnvi_held_in_reset())
		disable_wifi_wake();

	mainboard_ec_init();
}

static unsigned long mainboard_write_acpi_tables(
	struct device *device, unsigned long current, acpi_rsdp_t *rsdp)
{
	uintptr_t start_addr;
	uintptr_t end_addr;
	struct nhlt *nhlt;

	start_addr = current;

	nhlt = nhlt_init();

	if (nhlt == NULL)
		return start_addr;

	variant_nhlt_init(nhlt);

	end_addr = nhlt_soc_serialize(nhlt, start_addr);

	if (end_addr != start_addr)
		acpi_add_table(rsdp, (void *)start_addr);

	return end_addr;
}

static void mainboard_enable(struct device *dev)
{
	dev->ops->write_acpi_tables = mainboard_write_acpi_tables;
	dev->ops->acpi_inject_dsdt_generator = chromeos_dsdt_generator;
}

struct chip_operations mainboard_ops = {
	.init = mainboard_init,
	.enable_dev = mainboard_enable,
};

void __weak variant_update_devtree(struct device *dev)
{
	/* Place holder for common updates. */
}

/*
 * Check if CNVi PCI device is released from reset. If yes, then the system is
 * booting with CNVi module. In this case, the PCIe device for WiFi needs to
 * be disabled. If CNVi device is held in reset, then disable it.
 */
static void wifi_device_update(void)
{
	struct device *dev;
	unsigned int devfn;

	if (is_cnvi_held_in_reset())
		devfn = PCH_DEVFN_CNVI;
	else
		devfn = PCH_DEVFN_PCIE1;

	dev = dev_find_slot(0, devfn);
	if (dev)
		dev->enabled = 0;
}

/*
 * Base on SSFC value in the CBI from EC to enable one of audio codec sources in
 * the device tree.
 */
static void audio_codec_device_update(void)
{
	struct device *audio_dev = NULL;
	struct bus *audio_i2c_bus = dev_find_slot(0, PCH_DEVFN_I2C5)->link_list;
	enum ssfc_audio_codec codec = ssfc_get_audio_codec();

	while ((audio_dev = dev_bus_each_child(audio_i2c_bus, audio_dev))) {
		if (audio_dev->chip_info == NULL)
			continue;

		if ((audio_dev->chip_ops == &drivers_i2c_da7219_ops) &&
			(codec == SSFC_AUDIO_CODEC_DA7219)) {
			printk(BIOS_INFO, "enable DA7219.\n");
			continue;
		}

		if ((audio_dev->chip_ops == &drivers_i2c_generic_ops) &&
			(codec == SSFC_AUDIO_CODEC_RT5682)) {
			struct drivers_i2c_generic_config *cfg =
				audio_dev->chip_info;

			if (cfg != NULL && !strcmp(cfg->hid, "10EC5682")) {
				printk(BIOS_INFO, "enable RT5682.\n");
				continue;
			}
		}
		printk(BIOS_INFO, "%s has been disabled\n", audio_dev->chip_ops->name);
		audio_dev->enabled = 0;
	}
}

void mainboard_devtree_update(struct device *dev)
{
	/* Apply common devtree updates. */
	wifi_device_update();
	audio_codec_device_update();

	/* Defer to variant for board-specific updates. */
	variant_update_devtree(dev);
}

const char *smbios_mainboard_manufacturer(void)
{
	static char oem_name[32];
	static const char *manuf;

	if (manuf)
		return manuf;

	if (google_chromeec_cbi_get_oem_name(&oem_name[0],
			ARRAY_SIZE(oem_name)) < 0) {
		printk(BIOS_ERR, "Couldn't obtain OEM name from CBI\n");
		manuf = CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
	} else {
		manuf = &oem_name[0];
	}

	return manuf;
}
