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

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

static int
mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
{
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *sar_root, *sar_unit;
	struct mt76_dev *mdev = &dev->mt76;
	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);
		goto free;
	}

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

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

		if (sar_unit->type != ACPI_TYPE_INTEGER)
			break;
		*(*tbl + i) = (u8)sar_unit->integer.value;
	}
free:
	ret = (i == sar_root->package.count) ? 0 : -EINVAL;

	kfree(sar_root);

	return ret;
}

/* MTCL : Country List Table for 6G band */
static int
mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version)
{
	*version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0)
		   ? 1 : 2;
	return 0;
}

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

	ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len);
	if (ret)
		return ret;

	/* Table content validation */
	switch (version) {
	case 1:
		enable = ((struct mt7921_asar_dyn *)*table)->enable;
		sarlen = sizeof(struct mt7921_asar_dyn_limit);
		prelen = sizeof(struct mt7921_asar_dyn);
		break;
	case 2:
		enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable;
		sarlen = sizeof(struct mt7921_asar_dyn_limit_v2);
		prelen = sizeof(struct mt7921_asar_dyn_v2);
		break;
	default:
		return -EINVAL;
	}

	tblcnt = (len - prelen) / sarlen;
	if (!enable ||
	    tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN)
		ret = -EINVAL;

	return ret;
}

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

	ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len);
	if (ret)
		return ret;

	/* Table content validation */
	switch (version) {
	case 1:
		sarlen = sizeof(struct mt7921_asar_geo_limit);
		prelen = sizeof(struct mt7921_asar_geo);
		break;
	case 2:
		sarlen = sizeof(struct mt7921_asar_geo_limit_v2);
		prelen = sizeof(struct mt7921_asar_geo_v2);
		break;
	default:
		return -EINVAL;
	}

	tblcnt = (len - prelen) / sarlen;
	if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO)
		ret = -EINVAL;

	return ret;
}

int mt7921_init_acpi_sar(struct mt7921_dev *dev)
{
	struct mt7921_acpi_sar *asar;
	int ret;

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

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

	/* MTDS is mandatory. Return error if table is invalid */
	ret = mt7921_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 = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
	if (ret) {
		devm_kfree(dev->mt76.dev, asar->geo);
		asar->geo = NULL;
	}

	dev->phy.acpisar = asar;

	return 0;
}

static s8
mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
			enum nl80211_band band, s8 dyn_power)
{
	struct mt7921_acpi_sar *asar = phy->acpisar;
	struct mt7921_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
mt7921_asar_range_pwr(struct mt7921_phy *phy,
		      const struct cfg80211_sar_freq_ranges *range,
		      u8 idx)
{
	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
	struct mt7921_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 mt7921_asar_get_geo_pwr(phy, band, limit[idx]);
}

int mt7921_init_acpi_sar_power(struct mt7921_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,
				   mt7921_asar_range_pwr(phy, frp->range, i));
	}

	return 0;
}
