// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2021-2022 Intel Corporation
//
// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
//

#include <sound/hdaudio_ext.h>
#include "avs.h"
#include "registers.h"
#include "trace.h"

#define AVS_ADSPCS_INTERVAL_US		500
#define AVS_ADSPCS_TIMEOUT_US		50000
#define AVS_ADSPCS_DELAY_US		1000

int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
{
	u32 value, mask, reg;
	int ret;

	value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
	trace_avs_dsp_core_op(value, core_mask, "power", power);

	mask = AVS_ADSPCS_SPA_MASK(core_mask);
	value = power ? mask : 0;

	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
	/* Delay the polling to avoid false positives. */
	usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US);

	mask = AVS_ADSPCS_CPA_MASK(core_mask);
	value = power ? mask : 0;

	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
				       reg, (reg & mask) == value,
				       AVS_ADSPCS_INTERVAL_US,
				       AVS_ADSPCS_TIMEOUT_US);
	if (ret)
		dev_err(adev->dev, "core_mask %d power %s failed: %d\n",
			core_mask, power ? "on" : "off", ret);

	return ret;
}

int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset)
{
	u32 value, mask, reg;
	int ret;

	value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
	trace_avs_dsp_core_op(value, core_mask, "reset", reset);

	mask = AVS_ADSPCS_CRST_MASK(core_mask);
	value = reset ? mask : 0;

	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);

	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
				       reg, (reg & mask) == value,
				       AVS_ADSPCS_INTERVAL_US,
				       AVS_ADSPCS_TIMEOUT_US);
	if (ret)
		dev_err(adev->dev, "core_mask %d %s reset failed: %d\n",
			core_mask, reset ? "enter" : "exit", ret);

	return ret;
}

int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall)
{
	u32 value, mask, reg;
	int ret;

	value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
	trace_avs_dsp_core_op(value, core_mask, "stall", stall);

	mask = AVS_ADSPCS_CSTALL_MASK(core_mask);
	value = stall ? mask : 0;

	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);

	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
				       reg, (reg & mask) == value,
				       AVS_ADSPCS_INTERVAL_US,
				       AVS_ADSPCS_TIMEOUT_US);
	if (ret) {
		dev_err(adev->dev, "core_mask %d %sstall failed: %d\n",
			core_mask, stall ? "" : "un", ret);
		return ret;
	}

	/* Give HW time to propagate the change. */
	usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US);
	return 0;
}

int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask)
{
	int ret;

	ret = avs_dsp_op(adev, power, core_mask, true);
	if (ret)
		return ret;

	ret = avs_dsp_op(adev, reset, core_mask, false);
	if (ret)
		return ret;

	return avs_dsp_op(adev, stall, core_mask, false);
}

int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask)
{
	/* No error checks to allow for complete DSP shutdown. */
	avs_dsp_op(adev, stall, core_mask, true);
	avs_dsp_op(adev, reset, core_mask, true);

	return avs_dsp_op(adev, power, core_mask, false);
}

static int avs_dsp_enable(struct avs_dev *adev, u32 core_mask)
{
	u32 mask;
	int ret;

	ret = avs_dsp_core_enable(adev, core_mask);
	if (ret < 0)
		return ret;

	mask = core_mask & ~AVS_MAIN_CORE_MASK;
	if (!mask)
		/*
		 * without main core, fw is dead anyway
		 * so setting D0 for it is futile.
		 */
		return 0;

	ret = avs_ipc_set_dx(adev, mask, true);
	return AVS_IPC_RET(ret);
}

static int avs_dsp_disable(struct avs_dev *adev, u32 core_mask)
{
	int ret;

	ret = avs_ipc_set_dx(adev, core_mask, false);
	if (ret)
		return AVS_IPC_RET(ret);

	return avs_dsp_core_disable(adev, core_mask);
}

static int avs_dsp_get_core(struct avs_dev *adev, u32 core_id)
{
	u32 mask;
	int ret;

	mask = BIT_MASK(core_id);
	if (mask == AVS_MAIN_CORE_MASK)
		/* nothing to do for main core */
		return 0;
	if (core_id >= adev->hw_cfg.dsp_cores) {
		ret = -EINVAL;
		goto err;
	}

	adev->core_refs[core_id]++;
	if (adev->core_refs[core_id] == 1) {
		/*
		 * No cores other than main-core can be running for DSP
		 * to achieve d0ix. Conscious SET_D0IX IPC failure is permitted,
		 * simply d0ix power state will no longer be attempted.
		 */
		ret = avs_dsp_disable_d0ix(adev);
		if (ret && ret != -AVS_EIPC)
			goto err_disable_d0ix;

		ret = avs_dsp_enable(adev, mask);
		if (ret)
			goto err_enable_dsp;
	}

	return 0;

err_enable_dsp:
	avs_dsp_enable_d0ix(adev);
err_disable_d0ix:
	adev->core_refs[core_id]--;
err:
	dev_err(adev->dev, "get core %d failed: %d\n", core_id, ret);
	return ret;
}

static int avs_dsp_put_core(struct avs_dev *adev, u32 core_id)
{
	u32 mask;
	int ret;

	mask = BIT_MASK(core_id);
	if (mask == AVS_MAIN_CORE_MASK)
		/* nothing to do for main core */
		return 0;
	if (core_id >= adev->hw_cfg.dsp_cores) {
		ret = -EINVAL;
		goto err;
	}

	adev->core_refs[core_id]--;
	if (!adev->core_refs[core_id]) {
		ret = avs_dsp_disable(adev, mask);
		if (ret)
			goto err;

		/* Match disable_d0ix in avs_dsp_get_core(). */
		avs_dsp_enable_d0ix(adev);
	}

	return 0;
err:
	dev_err(adev->dev, "put core %d failed: %d\n", core_id, ret);
	return ret;
}

int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
			u8 core_id, u8 domain, void *param, u32 param_size,
			u8 *instance_id)
{
	struct avs_module_entry mentry;
	bool was_loaded = false;
	int ret, id;

	id = avs_module_id_alloc(adev, module_id);
	if (id < 0)
		return id;

	ret = avs_get_module_id_entry(adev, module_id, &mentry);
	if (ret)
		goto err_mod_entry;

	ret = avs_dsp_get_core(adev, core_id);
	if (ret)
		goto err_mod_entry;

	/* Load code into memory if this is the first instance. */
	if (!id && !avs_module_entry_is_loaded(&mentry)) {
		ret = avs_dsp_op(adev, transfer_mods, true, &mentry, 1);
		if (ret) {
			dev_err(adev->dev, "load modules failed: %d\n", ret);
			goto err_mod_entry;
		}
		was_loaded = true;
	}

	ret = avs_ipc_init_instance(adev, module_id, id, ppl_instance_id,
				    core_id, domain, param, param_size);
	if (ret) {
		ret = AVS_IPC_RET(ret);
		goto err_ipc;
	}

	*instance_id = id;
	return 0;

err_ipc:
	if (was_loaded)
		avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
	avs_dsp_put_core(adev, core_id);
err_mod_entry:
	avs_module_id_free(adev, module_id, id);
	return ret;
}

void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
			   u8 ppl_instance_id, u8 core_id)
{
	struct avs_module_entry mentry;
	int ret;

	/* Modules not owned by any pipeline need to be freed explicitly. */
	if (ppl_instance_id == INVALID_PIPELINE_ID)
		avs_ipc_delete_instance(adev, module_id, instance_id);

	avs_module_id_free(adev, module_id, instance_id);

	ret = avs_get_module_id_entry(adev, module_id, &mentry);
	/* Unload occupied memory if this was the last instance. */
	if (!ret && mentry.type.load_type == AVS_MODULE_LOAD_TYPE_LOADABLE) {
		if (avs_is_module_ida_empty(adev, module_id)) {
			ret = avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
			if (ret)
				dev_err(adev->dev, "unload modules failed: %d\n", ret);
		}
	}

	avs_dsp_put_core(adev, core_id);
}

int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
			    bool lp, u16 attributes, u8 *instance_id)
{
	struct avs_fw_cfg *fw_cfg = &adev->fw_cfg;
	int ret, id;

	id = ida_alloc_max(&adev->ppl_ida, fw_cfg->max_ppl_count - 1, GFP_KERNEL);
	if (id < 0)
		return id;

	ret = avs_ipc_create_pipeline(adev, req_size, priority, id, lp, attributes);
	if (ret) {
		ida_free(&adev->ppl_ida, id);
		return AVS_IPC_RET(ret);
	}

	*instance_id = id;
	return 0;
}

int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id)
{
	int ret;

	ret = avs_ipc_delete_pipeline(adev, instance_id);
	if (ret)
		ret = AVS_IPC_RET(ret);

	ida_free(&adev->ppl_ida, instance_id);
	return ret;
}
