Loading drivers/gpu/drm/msm/sde_rsc.c +63 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading drivers/gpu/drm/msm/sde_rsc.h +68 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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]; Loading @@ -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, Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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_ */ drivers/gpu/drm/msm/sde_rsc_hw.c +32 −2 Original line number Diff line number Diff line Loading @@ -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"); Loading Loading @@ -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); Loading @@ -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; } Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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: Loading @@ -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: Loading Loading
drivers/gpu/drm/msm/sde_rsc.c +63 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
drivers/gpu/drm/msm/sde_rsc.h +68 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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]; Loading @@ -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, Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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_ */
drivers/gpu/drm/msm/sde_rsc_hw.c +32 −2 Original line number Diff line number Diff line Loading @@ -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"); Loading Loading @@ -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); Loading @@ -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; } Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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: Loading @@ -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: Loading