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

Commit 031b4154 authored by Dhaval Patel's avatar Dhaval Patel Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm: add event support in sde rsc



Add core_powercollapse, core_restore, solver_enabled,
solver_disabled, etc. events support in sde rsc
driver. Client can request for multiple events
with single call.

Change-Id: Ic0ece204d7b44eb3357fadd7b4071f554658042c
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent fcd9e913
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -142,6 +142,69 @@ void sde_rsc_client_destroy(struct sde_rsc_client *client)
	return;
}

struct sde_rsc_event *sde_rsc_register_event(int rsc_index, uint32_t event_type,
		void (*cb_func)(uint32_t event_type, void *usr), void *usr)
{
	struct sde_rsc_event *evt;
	struct sde_rsc_priv *rsc;

	if (rsc_index >= MAX_RSC_COUNT) {
		pr_err("invalid rsc index:%d\n", rsc_index);
		return ERR_PTR(-EINVAL);
	} else if (!rsc_prv_list[rsc_index]) {
		pr_err("rsc idx:%d not probed yet or not available\n",
								rsc_index);
		return ERR_PTR(-EINVAL);
	} else if (!cb_func || !event_type) {
		pr_err("no event or cb func\n");
		return ERR_PTR(-EINVAL);
	}

	rsc = rsc_prv_list[rsc_index];
	evt = kzalloc(sizeof(struct sde_rsc_event), GFP_KERNEL);
	if (!evt)
		return ERR_PTR(-ENOMEM);

	evt->event_type = event_type;
	evt->rsc_index = rsc_index;
	evt->usr = usr;
	evt->cb_func = cb_func;
	pr_debug("event register type:%d rsc index:%d\n",
						event_type, rsc_index);

	mutex_lock(&rsc->client_lock);
	list_add(&evt->list, &rsc->event_list);
	mutex_unlock(&rsc->client_lock);

	return evt;
}

void sde_rsc_unregister_event(struct sde_rsc_event *event)
{
	struct sde_rsc_priv *rsc;

	if (!event) {
		pr_debug("invalid event client\n");
		goto end;
	} else if (event->rsc_index >= MAX_RSC_COUNT) {
		pr_err("invalid rsc index\n");
		goto end;
	}

	pr_debug("event client destroyed\n");
	rsc = rsc_prv_list[event->rsc_index];
	if (!rsc)
		goto end;

	mutex_lock(&rsc->client_lock);
	list_del_init(&event->list);
	mutex_unlock(&rsc->client_lock);

	kfree(event);
end:
	return;
}

static int sde_rsc_clk_enable(struct sde_power_handle *phandle,
	struct sde_power_client *pclient, bool enable)
{
+68 −1
Original line number Diff line number Diff line
@@ -32,6 +32,37 @@

struct sde_rsc_priv;

/**
 * event will be triggered before sde core power collapse,
 * mdss gdsc is still on
 */
#define SDE_RSC_EVENT_PRE_CORE_PC 0x1
/**
 * event will be triggered after sde core collapse complete,
 * mdss gdsc is off now
 */
#define SDE_RSC_EVENT_POST_CORE_PC 0x2
/**
 * event will be triggered before restoring the sde core from power collapse,
 * mdss gdsc is still off
 */
#define SDE_RSC_EVENT_PRE_CORE_RESTORE 0x4
/**
 * event will be triggered after restoring the sde core from power collapse,
 * mdss gdsc is on now
 */
#define SDE_RSC_EVENT_POST_CORE_RESTORE 0x8
/**
 * event attached with solver state enabled
 * all clients in clk_state or cmd_state
 */
#define SDE_RSC_EVENT_SOLVER_ENABLED 0x10
/**
 * event attached with solver state disabled
 * one of the client requested for vid state
 */
#define SDE_RSC_EVENT_SOLVER_DISABLED 0x20

/**
 * rsc_mode_req: sde rsc mode request information
 * MODE_READ: read vsync status
@@ -85,7 +116,7 @@ enum sde_rsc_state {
 * @current_state:   current client state
 * @crtc_id:		crtc_id associated with this rsc client.
 * @rsc_index:	rsc index of a client - only index "0" valid.
 * @list:	list to attach power handle master list
 * @list:	list to attach client master list
 */
struct sde_rsc_client {
	char name[MAX_RSC_CLIENT_NAME_LEN];
@@ -95,6 +126,22 @@ struct sde_rsc_client {
	struct list_head list;
};

/**
 * struct sde_rsc_event: local event registration entry structure
 * @cb_func:	Pointer to desired callback function
 * @usr:	User pointer to pass to callback on event trigger
 * @rsc_index:	rsc index of a client - only index "0" valid.
 * @event_type:	refer comments in event_register
 * @list:	list to attach event master list
 */
struct sde_rsc_event {
	void (*cb_func)(uint32_t event_type, void *usr);
	void *usr;
	u32 rsc_index;
	uint32_t event_type;
	struct list_head list;
};

/**
 * struct sde_rsc_hw_ops - sde resource state coordinator hardware ops
 * @init:			Initialize the sequencer, solver, qtimer,
@@ -182,6 +229,7 @@ struct sde_rsc_timer_config {
 * @wrapper_io:		wrapper io data mapping
 *
 * @client_list:	current rsc client list handle
 * @event_list:		current rsc event list handle
 * @client_lock:	current rsc client synchronization lock
 *
 * timer_config:	current rsc timer configuration
@@ -211,6 +259,7 @@ struct sde_rsc_priv {
	struct dss_io_data wrapper_io;

	struct list_head client_list;
	struct list_head event_list;
	struct mutex client_lock;

	struct sde_rsc_timer_config timer_config;
@@ -297,5 +346,23 @@ int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
 */
int sde_rsc_hw_register(struct sde_rsc_priv *rsc);

/**
 * sde_rsc_register_event - register a callback function for an event
 * @rsc_index:   A client will be created on this RSC. As of now only
 *               SDE_RSC_INDEX is valid rsc index.
 * @event_type:  event type to register; client sets 0x3 if it wants
 *               to register for CORE_PC and CORE_RESTORE - both events.
 * @cb_func:     Pointer to desired callback function
 * @usr:         User pointer to pass to callback on event trigger
 * Returns: sde_rsc_event pointer on success
 */
struct sde_rsc_event *sde_rsc_register_event(int rsc_index, uint32_t event_type,
		void (*cb_func)(uint32_t event_type, void *usr), void *usr);

/**
 * sde_rsc_unregister_event - unregister callback for an event
 * @sde_rsc_event: event returned by sde_rsc_register_event
 */
void sde_rsc_unregister_event(struct sde_rsc_event *event);

#endif /* _SDE_RSC_H_ */
+32 −2
Original line number Diff line number Diff line
@@ -102,6 +102,15 @@

#define MAX_CHECK_LOOPS			500

static void rsc_event_trigger(struct sde_rsc_priv *rsc, uint32_t event_type)
{
	struct sde_rsc_event *event;

	list_for_each_entry(event, &rsc->event_list, list)
		if (event->event_type & event_type)
			event->cb_func(event_type, event->usr);
}

static int rsc_hw_qtimer_init(struct sde_rsc_priv *rsc)
{
	pr_debug("rsc hardware qtimer init\n");
@@ -297,10 +306,13 @@ int sde_rsc_mode2_entry(struct sde_rsc_priv *rsc)
	rc = regulator_set_mode(rsc->fs, REGULATOR_MODE_FAST);
	if (rc) {
		pr_err("vdd reg fast mode set failed rc:%d\n", rc);
		goto end;
		return rc;
	}

	rc = -EBUSY;

	rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_PC);

	wrapper_status = dss_reg_r(&rsc->wrapper_io, SDE_RSCC_WRAPPER_CTRL,
				rsc->debug_mode);
	wrapper_status |= BIT(3);
@@ -319,10 +331,20 @@ int sde_rsc_mode2_entry(struct sde_rsc_priv *rsc)
		usleep_range(1, 2);
	}

	if (rc)
	if (rc) {
		pr_err("vdd fs is still enabled\n");
		goto end;
	}

	rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_PC);

	return 0;

end:
	regulator_set_mode(rsc->fs, REGULATOR_MODE_NORMAL);

	rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);

	return rc;
}

@@ -331,6 +353,8 @@ int sde_rsc_mode2_exit(struct sde_rsc_priv *rsc)
	int rc = -EBUSY;
	int count, reg;

	rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_RESTORE);

	// needs review with HPG sequence
	dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
					0x0, rsc->debug_mode);
@@ -374,6 +398,8 @@ int sde_rsc_mode2_exit(struct sde_rsc_priv *rsc)
	if (rc)
		pr_err("vdd reg normal mode set failed rc:%d\n", rc);

	rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);

	return rc;
}

@@ -407,6 +433,8 @@ static int sde_rsc_state_update(struct sde_rsc_priv *rsc,
							reg, rsc->debug_mode);
		/* make sure that solver is enabled */
		wmb();

		rsc_event_trigger(rsc, SDE_RSC_EVENT_SOLVER_ENABLED);
		break;

	case SDE_RSC_VID_STATE:
@@ -424,6 +452,8 @@ static int sde_rsc_state_update(struct sde_rsc_priv *rsc,
							0x1, rsc->debug_mode);
		/* make sure that solver mode is override */
		wmb();

		rsc_event_trigger(rsc, SDE_RSC_EVENT_SOLVER_DISABLED);
		break;

	case SDE_RSC_IDLE_STATE: