Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70d4aee6 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm: add event support in sde power handle" into msm-4.9

parents 16496105 410d156c
Loading
Loading
Loading
Loading
+105 −2
Original line number Diff line number Diff line
@@ -29,6 +29,17 @@
#include "sde_power_handle.h"
#include "sde_trace.h"

static void sde_power_event_trigger_locked(struct sde_power_handle *phandle,
		u32 event_type)
{
	struct sde_power_event *event;

	list_for_each_entry(event, &phandle->event_list, list) {
		if (event->event_type & event_type)
			event->cb_fnc(event_type, event->usr);
	}
}

struct sde_power_client *sde_power_client_create(
	struct sde_power_handle *phandle, char *client_name)
{
@@ -48,6 +59,7 @@ struct sde_power_client *sde_power_client_create(
	strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
	client->usecase_ndx = VOTE_INDEX_DISABLE;
	client->id = id;
	client->active = true;
	pr_debug("client %s created:%pK id :%d\n", client_name,
		client, id);
	id++;
@@ -62,6 +74,9 @@ void sde_power_client_destroy(struct sde_power_handle *phandle,
{
	if (!client  || !phandle) {
		pr_err("reg bus vote: invalid client handle\n");
	} else if (!client->active) {
		pr_err("sde power deinit already done\n");
		kfree(client);
	} else {
		pr_debug("bus vote client %s destroyed:%pK id:%u\n",
			client->name, client, client->id);
@@ -661,6 +676,8 @@ int sde_power_resource_init(struct platform_device *pdev,
	}

	INIT_LIST_HEAD(&phandle->power_client_clist);
	INIT_LIST_HEAD(&phandle->event_list);

	mutex_init(&phandle->phandle_lock);

	return rc;
@@ -672,9 +689,11 @@ int sde_power_resource_init(struct platform_device *pdev,
clk_err:
	msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0);
vreg_err:
	if (mp->vreg_config)
		devm_kfree(&pdev->dev, mp->vreg_config);
	mp->num_vreg = 0;
parse_vreg_err:
	if (mp->clk_config)
		devm_kfree(&pdev->dev, mp->clk_config);
	mp->num_clk = 0;
end:
@@ -685,6 +704,8 @@ void sde_power_resource_deinit(struct platform_device *pdev,
	struct sde_power_handle *phandle)
{
	struct dss_module_power *mp;
	struct sde_power_client *curr_client, *next_client;
	struct sde_power_event *curr_event, *next_event;

	if (!phandle || !pdev) {
		pr_err("invalid input param\n");
@@ -692,6 +713,26 @@ void sde_power_resource_deinit(struct platform_device *pdev,
	}
	mp = &phandle->mp;

	mutex_lock(&phandle->phandle_lock);
	list_for_each_entry_safe(curr_client, next_client,
			&phandle->power_client_clist, list) {
		pr_err("cliend:%s-%d still registered with refcount:%d\n",
				curr_client->name, curr_client->id,
				curr_client->refcount);
		curr_client->active = false;
		list_del(&curr_client->list);
	}

	list_for_each_entry_safe(curr_event, next_event,
			&phandle->event_list, list) {
		pr_err("event:%d, client:%s still registered\n",
				curr_event->event_type,
				curr_event->client_name);
		curr_event->active = false;
		list_del(&curr_event->list);
	}
	mutex_unlock(&phandle->phandle_lock);

	sde_power_data_bus_unregister(&phandle->data_bus_handle);

	sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
@@ -757,6 +798,9 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
		goto end;

	if (enable) {
		sde_power_event_trigger_locked(phandle,
				SDE_POWER_EVENT_PRE_ENABLE);

		rc = sde_power_data_bus_update(&phandle->data_bus_handle,
									enable);
		if (rc) {
@@ -782,7 +826,14 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
			pr_err("clock enable failed rc:%d\n", rc);
			goto clk_err;
		}

		sde_power_event_trigger_locked(phandle,
				SDE_POWER_EVENT_POST_ENABLE);

	} else {
		sde_power_event_trigger_locked(phandle,
				SDE_POWER_EVENT_PRE_DISABLE);

		msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);

		sde_power_reg_bus_update(phandle->reg_bus_hdl,
@@ -791,6 +842,9 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
		msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);

		sde_power_data_bus_update(&phandle->data_bus_handle, enable);

		sde_power_event_trigger_locked(phandle,
				SDE_POWER_EVENT_POST_DISABLE);
	}

end:
@@ -903,3 +957,52 @@ struct clk *sde_power_clk_get_clk(struct sde_power_handle *phandle,

	return clk;
}

struct sde_power_event *sde_power_handle_register_event(
		struct sde_power_handle *phandle,
		u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
		void *usr, char *client_name)
{
	struct sde_power_event *event;

	if (!phandle) {
		pr_err("invalid power handle\n");
		return ERR_PTR(-EINVAL);
	} else if (!cb_fnc || !event_type) {
		pr_err("no callback fnc or event type\n");
		return ERR_PTR(-EINVAL);
	}

	event = kzalloc(sizeof(struct sde_power_event), GFP_KERNEL);
	if (!event)
		return ERR_PTR(-ENOMEM);

	event->event_type = event_type;
	event->cb_fnc = cb_fnc;
	event->usr = usr;
	strlcpy(event->client_name, client_name, MAX_CLIENT_NAME_LEN);
	event->active = true;

	mutex_lock(&phandle->phandle_lock);
	list_add(&event->list, &phandle->event_list);
	mutex_unlock(&phandle->phandle_lock);

	return event;
}

void sde_power_handle_unregister_event(
		struct sde_power_handle *phandle,
		struct sde_power_event *event)
{
	if (!phandle || !event) {
		pr_err("invalid phandle or event\n");
	} else if (!event->active) {
		pr_err("power handle deinit already done\n");
		kfree(event);
	} else {
		mutex_lock(&phandle->phandle_lock);
		list_del_init(&event->list);
		mutex_unlock(&phandle->phandle_lock);
		kfree(event);
	}
}
+58 −0
Original line number Diff line number Diff line
@@ -23,6 +23,18 @@

#include <linux/sde_io_util.h>

/* event will be triggered before power handler disable */
#define SDE_POWER_EVENT_PRE_DISABLE	0x1

/* event will be triggered after power handler disable */
#define SDE_POWER_EVENT_POST_DISABLE	0x2

/* event will be triggered before power handler enable */
#define SDE_POWER_EVENT_PRE_ENABLE	0x4

/* event will be triggered after power handler enable */
#define SDE_POWER_EVENT_POST_ENABLE	0x8

/**
 * mdss_bus_vote_type: register bus vote type
 * VOTE_INDEX_DISABLE: removes the client vote
@@ -59,6 +71,7 @@ enum sde_power_handle_data_bus_client {
 * @list:	list to attach power handle master list
 * @ab:         arbitrated bandwidth for each bus client
 * @ib:         instantaneous bandwidth for each bus client
 * @active:	inidcates the state of sde power handle
 */
struct sde_power_client {
	char name[MAX_CLIENT_NAME_LEN];
@@ -68,6 +81,7 @@ struct sde_power_client {
	struct list_head list;
	u64 ab[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
	u64 ib[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
	bool active;
};

/**
@@ -90,6 +104,24 @@ struct sde_power_data_bus_handle {
	u32 ao_bw_uc_idx;
};

/*
 * struct sde_power_event - local event registration structure
 * @client_name: name of the client registering
 * @cb_fnc: pointer to desired callback function
 * @usr: user pointer to pass to callback event trigger
 * @event: refer to SDE_POWER_HANDLE_EVENT_*
 * @list: list to attach event master list
 * @active: indicates the state of sde power handle
 */
struct sde_power_event {
	char client_name[MAX_CLIENT_NAME_LEN];
	void (*cb_fnc)(u32 event_type, void *usr);
	void *usr;
	u32 event_type;
	struct list_head list;
	bool active;
};

/**
 * struct sde_power_handle: power handle main struct
 * @mp:		module power for clock and regulator
@@ -99,6 +131,7 @@ struct sde_power_data_bus_handle {
 * @usecase_ndx: current usecase index
 * @reg_bus_hdl: current register bus handle
 * @data_bus_handle: context structure for data bus control
 * @event_list: current power handle event list
 */
struct sde_power_handle {
	struct dss_module_power mp;
@@ -108,6 +141,7 @@ struct sde_power_handle {
	u32 current_usecase_ndx;
	u32 reg_bus_hdl;
	struct sde_power_data_bus_handle data_bus_handle;
	struct list_head event_list;
};

/**
@@ -226,4 +260,28 @@ int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
void sde_power_data_bus_bandwidth_ctrl(struct sde_power_handle *phandle,
		struct sde_power_client *pclient, int enable);

/**
 * sde_power_handle_register_event - register a callback function for an event.
 *	Clients can register for multiple events with a single register.
 *	Any block with access to phandle can register for the event
 *	notification.
 * @phandle:	power handle containing the resources
 * @event_type:	event type to register; refer SDE_POWER_HANDLE_EVENT_*
 * @cb_fnc:	pointer to desired callback function
 * @usr:	user pointer to pass to callback on event trigger
 *
 * Return:	event pointer if success, or error code otherwise
 */
struct sde_power_event *sde_power_handle_register_event(
		struct sde_power_handle *phandle,
		u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
		void *usr, char *client_name);
/**
 * sde_power_handle_unregister_event - unregister callback for event(s)
 * @phandle:	power handle containing the resources
 * @event:	event pointer returned after power handle register
 */
void sde_power_handle_unregister_event(struct sde_power_handle *phandle,
		struct sde_power_event *event);

#endif /* _SDE_POWER_HANDLE_H_ */