/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 */

#ifndef WCD_CPE_CORE_H
#define WCD_CPE_CORE_H

#include <soc/qcom/ramdump.h>
#include <linux/dma-mapping.h>
#include "wcd_cpe_services.h"

#define WCD_CPE_LAB_MAX_LATENCY 250
#define WCD_CPE_MAD_SLIM_CHANNEL 140

/* Indicates CPE block is ready for image re-download */
#define WCD_CPE_BLK_READY  (1 << 0)
/* Indicates the underlying bus is ready */
#define WCD_CPE_BUS_READY (1 << 1)

/*
 * only when the underlying bus and CPE block both are ready,
 * the state will be ready to download
 */
#define WCD_CPE_READY_TO_DLOAD	\
	(WCD_CPE_BLK_READY | WCD_CPE_BUS_READY)

#define WCD_CPE_LOAD_IMEM (1 << 0)
#define WCD_CPE_LOAD_DATA (1 << 1)
#define WCD_CPE_LOAD_ALL \
	(WCD_CPE_LOAD_IMEM | WCD_CPE_LOAD_DATA)

#define WCD_CPE_IMAGE_FNAME_MAX 64

#define WCD_CPE_AFE_OUT_PORT_2 2
#define WCD_CPE_AFE_OUT_PORT_4 4

enum {
	WCD_CPE_LSM_CAL_AFE = 0,
	WCD_CPE_LSM_CAL_LSM,
	WCD_CPE_LSM_CAL_TOPOLOGY_ID,
	WCD_CPE_LSM_CAL_MAX,
};

enum cpe_err_irq_cntl_type {
	CPE_ERR_IRQ_MASK = 0,
	CPE_ERR_IRQ_UNMASK,
	CPE_ERR_IRQ_CLEAR,
	CPE_ERR_IRQ_STATUS,
};

struct wcd_cpe_cdc_cb {
	/* codec provided callback to enable RCO */
	int (*cdc_clk_en)(struct snd_soc_component *cpmponent, bool enable);

	/* callback for FLL setup for codec */
	int (*cpe_clk_en)(struct snd_soc_component *component, bool enable);
	int (*cdc_ext_clk)(struct snd_soc_component *component, int enable,
			   bool dapm);
	int (*lab_cdc_ch_ctl)(struct snd_soc_component *component, u8 event);
	int (*get_afe_out_port_id)(struct snd_soc_component *component,
				   u16 *port_id);
	int (*bus_vote_bw)(struct snd_soc_component *component,
			   bool vote);

	/* Callback to control the cpe error interrupt mask/status/clear */
	int (*cpe_err_irq_control)(struct snd_soc_component *component,
				    enum cpe_err_irq_cntl_type cntl_type,
				    u8 *status);
};

enum wcd_cpe_ssr_state_event {
	/* Indicates CPE is initialized */
	WCD_CPE_INITIALIZED = 0,
	/* Indicates that IMEM is downloaded to CPE */
	WCD_CPE_IMEM_DOWNLOADED,
	/* Indicates CPE is enabled */
	WCD_CPE_ENABLED,
	/* Indicates that CPE is currently active */
	WCD_CPE_ACTIVE,
	/* Event from underlying bus notifying bus is down */
	WCD_CPE_BUS_DOWN_EVENT,
	/* Event from CPE block, notifying CPE is down */
	WCD_CPE_SSR_EVENT,
	/* Event from underlying bus notifying bus is up */
	WCD_CPE_BUS_UP_EVENT,
};

struct wcd_cpe_ssr_entry {
	int offline;
	u32 offline_change;
	wait_queue_head_t offline_poll_wait;
	struct snd_info_entry *entry;
};

struct wcd_cpe_irq_info {
	int cpe_engine_irq;
	int cpe_err_irq;
	u8 cpe_fatal_irqs;
};

struct wcd_cpe_hw_info {
	u32 dram_offset;
	size_t dram_size;
	u32 iram_offset;
	size_t iram_size;
};

struct wcd_cpe_core {
	/* handle to cpe services */
	void *cpe_handle;

	/* registration handle to cpe services */
	void *cpe_reg_handle;

	/* cmi registration handle for afe service */
	void *cmi_afe_handle;

	/* handle to codec */
	struct snd_soc_component *component;

	/* codec device */
	struct device *dev;

	/* firmware image file name */
	char fname[WCD_CPE_IMAGE_FNAME_MAX];

	/* firmware image file name from sysfs */
	char dyn_fname[WCD_CPE_IMAGE_FNAME_MAX];

	/* codec information needed by cpe services */
	struct cpe_svc_codec_info_v1 cdc_info;

	/* work to perform image download */
	struct work_struct load_fw_work;

	/* flag to indicate mode in which cpe needs to be booted */
	int cpe_debug_mode;

	/* callbacks for codec specific implementation */
	const struct wcd_cpe_cdc_cb *cpe_cdc_cb;

	/* work to handle CPE SSR*/
	struct work_struct ssr_work;

	/* PM handle for suspend mode during SSR */
	struct pm_qos_request pm_qos_req;

	/* completion event indicating CPE OFFLINE */
	struct completion offline_compl;

	/* entry into snd card procfs indicating cpe status */
	struct wcd_cpe_ssr_entry ssr_entry;

	/*
	 * completion event to signal CPE is
	 * ready for image re-download
	 */
	struct completion ready_compl;

	/* maintains the status for cpe ssr */
	u8 ready_status;

	/* Indicate SSR type */
	enum wcd_cpe_ssr_state_event ssr_type;

	/* mutex to protect cpe ssr status variables */
	struct mutex ssr_lock;

	/* mutex to protect cpe session status variables */
	struct mutex session_lock;

	/* Store the calibration data needed for cpe */
	struct cal_type_data *cal_data[WCD_CPE_LSM_CAL_MAX];

	/* completion event to signal CPE is online */
	struct completion online_compl;

	/* reference counter for cpe usage */
	u8 cpe_users;

	/* Ramdump support */
	void *cpe_ramdump_dev;
	struct ramdump_segment cpe_ramdump_seg;
	dma_addr_t cpe_dump_addr;
	void *cpe_dump_v_addr;

	/* SFR support */
	u32 sfr_buf_addr;
	size_t sfr_buf_size;

	/* IRQ information for CPE interrupts */
	struct wcd_cpe_irq_info irq_info;

	/* Kobject for sysfs entry */
	struct kobject cpe_kobj;

	/* Reference count for cpe clk*/
	int cpe_clk_ref;

	/* codec based hardware info */
	struct wcd_cpe_hw_info hw_info;
};

struct wcd_cpe_params {
	struct snd_soc_component *component;
	struct wcd_cpe_core * (*get_cpe_core)(
				struct snd_soc_component *component);
	const struct wcd_cpe_cdc_cb *cdc_cb;
	int dbg_mode;
	u16 cdc_major_ver;
	u16 cdc_minor_ver;
	u32 cdc_id;

	struct wcd_cpe_irq_info cdc_irq_info;

	struct cpe_svc_init_param *cpe_svc_params;
};

#if IS_ENABLED(CONFIG_SND_SOC_WCD_CPE)
int wcd_cpe_ssr_event(void *core_handle,
		      enum wcd_cpe_ssr_state_event event);
struct wcd_cpe_core *wcd_cpe_init(const char *img_fname,
struct snd_soc_component *component, struct wcd_cpe_params *params);
#else /* CONFIG_SND_SOC_WCD_CPE */
static inline int wcd_cpe_ssr_event(void *core_handle,
		      enum wcd_cpe_ssr_state_event event)
{
	return 0;
}
static inline struct wcd_cpe_core *wcd_cpe_init(const char *img_fname,
					struct snd_soc_component *component,
					struct wcd_cpe_params *params)
{
	return NULL;
}
#endif /* CONFIG_SND_SOC_WCD_CPE */
#endif
