/*
 * sst_match_apci.c - SST (LPE) match for ACPI enumeration.
 *
 * Copyright (c) 2013-15, Intel Corporation.
 *
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 "sst-acpi.h"

static acpi_status sst_acpi_find_name(acpi_handle handle, u32 level,
				      void *context, void **ret)
{
	struct acpi_device *adev;
	const char *name = NULL;

	if (acpi_bus_get_device(handle, &adev))
		return AE_OK;

	if (adev->status.present && adev->status.functional) {
		name = acpi_dev_name(adev);
		*(const char **)ret = name;
		return AE_CTRL_TERMINATE;
	}

	return AE_OK;
}

const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
{
	const char *name = NULL;
	acpi_status status;

	status = acpi_get_devices(hid, sst_acpi_find_name, NULL,
				  (void **)&name);

	if (ACPI_FAILURE(status) || name[0] == '\0')
		return NULL;

	return name;
}
EXPORT_SYMBOL_GPL(sst_acpi_find_name_from_hid);

static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
				       void *context, void **ret)
{
	unsigned long long sta;
	acpi_status status;

	*(bool *)context = true;
	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
		*(bool *)context = false;

	return AE_OK;
}

bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN])
{
	acpi_status status;
	bool found = false;

	status = acpi_get_devices(hid, sst_acpi_mach_match, &found, NULL);

	if (ACPI_FAILURE(status))
		return false;

	return found;
}
EXPORT_SYMBOL_GPL(sst_acpi_check_hid);

struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
{
	struct sst_acpi_mach *mach;

	for (mach = machines; mach->id[0]; mach++) {
		if (sst_acpi_check_hid(mach->id) == true) {
			if (mach->machine_quirk)
				mach = mach->machine_quirk(mach);
			return mach;
		}
	}
	return NULL;
}
EXPORT_SYMBOL_GPL(sst_acpi_find_machine);

static acpi_status sst_acpi_find_package(acpi_handle handle, u32 level,
					void *context, void **ret)
{
	struct acpi_device *adev;
	acpi_status status = AE_OK;
	struct sst_acpi_package_context *pkg_ctx = context;

	pkg_ctx->data_valid = false;

	if (acpi_bus_get_device(handle, &adev))
		return AE_OK;

	if (adev->status.present && adev->status.functional) {
		struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
		union acpi_object  *myobj = NULL;

		status = acpi_evaluate_object_typed(handle, pkg_ctx->name,
						NULL, &buffer,
						ACPI_TYPE_PACKAGE);
		if (ACPI_FAILURE(status))
			return AE_OK;

		myobj = buffer.pointer;
		if (!myobj || myobj->package.count != pkg_ctx->length) {
			kfree(buffer.pointer);
			return AE_OK;
		}

		status = acpi_extract_package(myobj,
					pkg_ctx->format, pkg_ctx->state);
		if (ACPI_FAILURE(status)) {
			kfree(buffer.pointer);
			return AE_OK;
		}

		kfree(buffer.pointer);
		pkg_ctx->data_valid = true;
		return AE_CTRL_TERMINATE;
	}

	return AE_OK;
}

bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
				struct sst_acpi_package_context *ctx)
{
	acpi_status status;

	status = acpi_get_devices(hid, sst_acpi_find_package, ctx, NULL);

	if (ACPI_FAILURE(status) || !ctx->data_valid)
		return false;

	return true;
}
EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid);

struct sst_acpi_mach *sst_acpi_codec_list(void *arg)
{
	struct sst_acpi_mach *mach = arg;
	struct sst_codecs *codec_list = (struct sst_codecs *) mach->quirk_data;
	int i;

	if (mach->quirk_data == NULL)
		return mach;

	for (i = 0; i < codec_list->num_codecs; i++) {
		if (sst_acpi_check_hid(codec_list->codecs[i]) != true)
			return NULL;
	}

	return mach;
}
EXPORT_SYMBOL_GPL(sst_acpi_codec_list);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel Common ACPI Match module");
