/* SPDX-License-Identifier: GPL-2.0-only */


#ifndef __MSM_MMRM_H__
#define __MSM_MMRM_H__

#include <linux/types.h>

#define MMRM_CLK_CLIENT_NAME_SIZE  128


#define MMRM_CLIENT_DATA_FLAG_RESERVE_ONLY  0x0001


enum mmrm_client_domain {
	MMRM_CLIENT_DOMAIN_CAMERA = 0x1,
	MMRM_CLIENT_DOMAIN_CVP = 0x2,
	MMRM_CLIENT_DOMAIN_DISPLAY = 0x3,
	MMRM_CLIENT_DOMAIN_VIDEO = 0x4,
};


enum mmrm_client_type {
	MMRM_CLIENT_CLOCK,
};


enum mmrm_client_priority {
	MMRM_CLIENT_PRIOR_HIGH = 0x1,
	MMRM_CLIENT_PRIOR_LOW  = 0x2
};


enum mmrm_cb_type {
	MMRM_CLIENT_RESOURCE_VALUE_CHANGE = 0x1,
};


struct mmrm_res_val_chng {
	unsigned long old_val;
	unsigned long new_val;
};


struct mmrm_client_notifier_data {
	enum mmrm_cb_type cb_type;
	union {
		struct mmrm_res_val_chng val_chng;
	} cb_data;
	void *pvt_data;
};


struct mmrm_client_res_value {
	unsigned long min;
	unsigned long cur;
	unsigned long max;
};


struct mmrm_client {
	enum mmrm_client_type client_type;
	u32 client_uid;
};


struct mmrm_clk_client_desc {
	u32 client_domain;
	u32 client_id;
	const char name[MMRM_CLK_CLIENT_NAME_SIZE];
	struct clk *clk;
};


struct mmrm_client_desc {
	enum mmrm_client_type client_type;
	union {
		struct mmrm_clk_client_desc desc;
	} client_info;
	enum mmrm_client_priority priority;
	void *pvt_data;
	int (*notifier_callback_fn)(
		struct mmrm_client_notifier_data *notifier_data);
};


struct mmrm_client_data {
	u32 num_hw_blocks;
	u32 flags;
};

#if IS_ENABLED(CONFIG_MSM_MMRM)

bool mmrm_client_check_scaling_supported(enum mmrm_client_type client_type,
	u32 client_domain);


struct mmrm_client *mmrm_client_register(struct mmrm_client_desc *desc);


int mmrm_client_deregister(struct mmrm_client *client);


int mmrm_client_set_value(struct mmrm_client *client,
	struct mmrm_client_data *client_data, unsigned long val);


int mmrm_client_set_value_in_range(struct mmrm_client *client,
	struct mmrm_client_data *client_data,
	struct mmrm_client_res_value *val);


int mmrm_client_get_value(struct mmrm_client *client,
	struct mmrm_client_res_value *val);

#else
static inline bool mmrm_client_check_scaling_supported(
	enum mmrm_client_type client_type, u32 client_domain)
{
	return false;
}

static inline struct mmrm_client *mmrm_client_register(
	struct mmrm_client_desc *desc)
{
	return NULL;
}

static inline int mmrm_client_deregister(struct mmrm_client *client)
{
	return 0;
}

static inline int mmrm_client_set_value(struct mmrm_client *client,
	struct mmrm_client_data *client_data, unsigned long val)
{
	return -EINVAL;
}

static inline int mmrm_client_set_value_in_range(struct mmrm_client *client,
	struct mmrm_client_data *client_data,
	struct mmrm_client_res_value *val)
{
	return -EINVAL;
}

static inline int mmrm_client_get_value(struct mmrm_client *client,
	struct mmrm_client_res_value *val)
{
	return 0;
}

#endif

#endif
