// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */

#include <linux/acpi.h>
#include "mt792x.h"

static int
mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
{
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
	struct mt76_dev *mdev = &dev->mt76;
	union acpi_object *sar_root;
	acpi_handle root, handle;
	acpi_status status;
	u32 i = 0;
	int ret;

	root = ACPI_HANDLE(mdev->dev);
	if (!root)
		return -EOPNOTSUPP;

	status = acpi_get_handle(root, method, &handle);
	if (ACPI_FAILURE(status))
		return -EIO;

	status = acpi_evaluate_object(handle, NULL, NULL, &buf);
	if (ACPI_FAILURE(status))
		return -EIO;

	sar_root = buf.pointer;
	if (sar_root->type != ACPI_TYPE_PACKAGE ||
	    sar_root->package.count < 4 ||
	    sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
		dev_err(mdev->dev, "sar cnt = %d\n",
			sar_root->package.count);
		ret = -EINVAL;
		goto free;
	}

	if (!*tbl) {
		*tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
				    GFP_KERNEL);
		if (!*tbl) {
			ret = -ENOMEM;
			goto free;
		}
	}

	if (len)
		*len = sar_root->package.count;

	for (i = 0; i < sar_root->package.count; i++) {
		union acpi_object *sar_unit = &sar_root->package.elements[i];

		if (sar_unit->type != ACPI_TYPE_INTEGER)
			break;

		*(*tbl + i) = (u8)sar_unit->integer.value;
	}

	ret = i == sar_root->package.count ? 0 : -EINVAL;
free:
	kfree(sar_root);

	return ret;
}

/* MTCL : Country List Table for 6G band */
static void
mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
{
	if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0)
		*version = 1;
	else
		*version = 2;
}

/* MTDS : Dynamic SAR Power Table */
static int
mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
{
	int len, ret, sarlen, prelen, tblcnt;
	bool enable;

	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
	if (ret)
		return ret;

	/* Table content validation */
	switch (version) {
	case 1:
		enable = ((struct mt792x_asar_dyn *)*table)->enable;
		sarlen = sizeof(struct mt792x_asar_dyn_limit);
		prelen = sizeof(struct mt792x_asar_dyn);
		break;
	case 2:
		enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
		sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
		prelen = sizeof(struct mt792x_asar_dyn_v2);
		break;
	default:
		return -EINVAL;
	}

	tblcnt = (len - prelen) / sarlen;
	if (!enable ||
	    tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
		return -EINVAL;

	return 0;
}

/* MTGS : Geo SAR Power Table */
static int
mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
{
	int len, ret, sarlen, prelen, tblcnt;

	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
	if (ret)
		return ret;

	/* Table content validation */
	switch (version) {
	case 1:
		sarlen = sizeof(struct mt792x_asar_geo_limit);
		prelen = sizeof(struct mt792x_asar_geo);
		break;
	case 2:
		sarlen = sizeof(struct mt792x_asar_geo_limit_v2);
		prelen = sizeof(struct mt792x_asar_geo_v2);
		break;
	default:
		return -EINVAL;
	}

	tblcnt = (len - prelen) / sarlen;
	if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
		return -EINVAL;

	return 0;
}

/* MTFG : Flag Table */
static int
mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table)
{
	int len, ret;

	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len);
	if (ret)
		return ret;

	if (len < MT792x_ASAR_MIN_FG)
		return -EINVAL;

	return 0;
}

int mt792x_init_acpi_sar(struct mt792x_dev *dev)
{
	struct mt792x_acpi_sar *asar;
	int ret;

	asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
	if (!asar)
		return -ENOMEM;

	mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);

	/* MTDS is mandatory. Return error if table is invalid */
	ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
	if (ret) {
		devm_kfree(dev->mt76.dev, asar->dyn);
		devm_kfree(dev->mt76.dev, asar->countrylist);
		devm_kfree(dev->mt76.dev, asar);

		return ret;
	}

	/* MTGS is optional */
	ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
	if (ret) {
		devm_kfree(dev->mt76.dev, asar->geo);
		asar->geo = NULL;
	}

	/* MTFG is optional */
	ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
	if (ret) {
		devm_kfree(dev->mt76.dev, asar->fg);
		asar->fg = NULL;
	}
	dev->phy.acpisar = asar;

	return 0;
}
EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar);

static s8
mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
			enum nl80211_band band, s8 dyn_power)
{
	struct mt792x_acpi_sar *asar = phy->acpisar;
	struct mt792x_asar_geo_band *band_pwr;
	s8 geo_power;
	u8 idx, max;

	if (!asar->geo)
		return dyn_power;

	switch (phy->mt76->dev->region) {
	case NL80211_DFS_FCC:
		idx = 0;
		break;
	case NL80211_DFS_ETSI:
		idx = 1;
		break;
	default: /* WW */
		idx = 2;
		break;
	}

	if (asar->ver == 1) {
		band_pwr = &asar->geo->tbl[idx].band[0];
		max = ARRAY_SIZE(asar->geo->tbl[idx].band);
	} else {
		band_pwr = &asar->geo_v2->tbl[idx].band[0];
		max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
	}

	switch (band) {
	case NL80211_BAND_2GHZ:
		idx = 0;
		break;
	case NL80211_BAND_5GHZ:
		idx = 1;
		break;
	case NL80211_BAND_6GHZ:
		idx = 2;
		break;
	default:
		return dyn_power;
	}

	if (idx >= max)
		return dyn_power;

	geo_power = (band_pwr + idx)->pwr;
	dyn_power += (band_pwr + idx)->offset;

	return min(geo_power, dyn_power);
}

static s8
mt792x_asar_range_pwr(struct mt792x_phy *phy,
		      const struct cfg80211_sar_freq_ranges *range,
		      u8 idx)
{
	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
	struct mt792x_acpi_sar *asar = phy->acpisar;
	u8 *limit, band, max;

	if (!capa)
		return 127;

	if (asar->ver == 1) {
		limit = &asar->dyn->tbl[0].frp[0];
		max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
	} else {
		limit = &asar->dyn_v2->tbl[0].frp[0];
		max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
	}

	if (idx >= max)
		return 127;

	if (range->start_freq >= 5945)
		band = NL80211_BAND_6GHZ;
	else if (range->start_freq >= 5150)
		band = NL80211_BAND_5GHZ;
	else
		band = NL80211_BAND_2GHZ;

	return mt792x_asar_get_geo_pwr(phy, band, limit[idx]);
}

int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
{
	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
	int i;

	if (!phy->acpisar)
		return 0;

	/* When ACPI SAR enabled in HW, we should apply rules for .frp
	 * 1. w/o .sar_specs : set ACPI SAR power as the defatul value
	 * 2. w/  .sar_specs : set power with min(.sar_specs, ACPI_SAR)
	 */
	for (i = 0; i < capa->num_freq_ranges; i++) {
		struct mt76_freq_range_power *frp = &phy->mt76->frp[i];

		frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
		if (!frp->range)
			continue;

		frp->power = min_t(s8, set_default ? 127 : frp->power,
				   mt792x_asar_range_pwr(phy, frp->range, i));
	}

	return 0;
}
EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power);

u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
{
	struct mt792x_acpi_sar *acpisar = phy->acpisar;
	struct mt792x_asar_fg *fg;
	struct {
		u8 acpi_idx;
		u8 chip_idx;
	} map[] = {
		{ 1, 1 },
		{ 4, 2 },
	};
	u8 flags = BIT(0);
	int i, j;

	if (!acpisar)
		return 0;

	fg = acpisar->fg;
	if (!fg)
		return flags;

	/* pickup necessary settings per device and
	 * translate the index of bitmap for chip command.
	 */
	for (i = 0; i < fg->nr_flag; i++) {
		for (j = 0; j < ARRAY_SIZE(map); j++) {
			if (fg->flag[i] == map[j].acpi_idx) {
				flags |= BIT(map[j].chip_idx);
				break;
			}
		}
	}

	return flags;
}
EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
