/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #ifndef _SDE_RSC_H_ #define _SDE_RSC_H_ #include /* primary display rsc index */ #define SDE_RSC_INDEX 0 #define MAX_RSC_CLIENT_NAME_LEN 128 /* DRM Object IDs are numbered excluding 0, use 0 to indicate invalid CRTC */ #define SDE_RSC_INVALID_CRTC_ID 0 /** * 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 #define SDE_RSC_REV_1 0x1 #define SDE_RSC_REV_2 0x2 #define SDE_RSC_REV_3 0x3 /** * sde_rsc_client_type: sde rsc client type information * SDE_RSC_PRIMARY_DISP_CLIENT: A primary display client which can request * vid or cmd state switch. * SDE_RSC_EXTERNAL_DISPLAY_CLIENT:An external display client which can * request only clk state switch. * SDE_RSC_CLK_CLIENT: A clk client request for only rsc clocks * enabled and mode_2 exit state. */ enum sde_rsc_client_type { SDE_RSC_PRIMARY_DISP_CLIENT, SDE_RSC_EXTERNAL_DISP_CLIENT, SDE_RSC_CLK_CLIENT, SDE_RSC_INVALID_CLIENT, }; /** * sde_rsc_state: sde rsc state information * SDE_RSC_IDLE_STATE: A client requests for idle state when there is no * pixel or cmd transfer expected. An idle vote from * all clients lead to power collapse state. * SDE_RSC_CLK_STATE: A client requests for clk state when it wants to * only avoid mode-2 entry/exit. For ex: V4L2 driver, * sde power handle, etc. * SDE_RSC_CMD_STATE: A client requests for cmd state when it wants to * enable the solver mode. * SDE_RSC_VID_STATE: A client requests for vid state it wants to avoid * solver enable because client is fetching data from * continuously. */ enum sde_rsc_state { SDE_RSC_IDLE_STATE, SDE_RSC_CLK_STATE, SDE_RSC_CMD_STATE, SDE_RSC_VID_STATE, }; /** * struct sde_rsc_client: stores the rsc client for sde driver * @name: name of the client * @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. * @id: Index of client. It will be assigned during client_create call * @client_type: check sde_rsc_client_type information * @list: list to attach client master list */ struct sde_rsc_client { char name[MAX_RSC_CLIENT_NAME_LEN]; short current_state; int crtc_id; u32 rsc_index; u32 id; enum sde_rsc_client_type client_type; 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_cmd_config: provides panel configuration to rsc * when client is command mode. It is not required to set it during * video mode. * * @fps: panel te interval * @vtotal: current vertical total (height + vbp + vfp) * @jitter_numer: panel jitter numerator value. This config causes rsc/solver * early before te. Default is 0.8% jitter. * @jitter_denom: panel jitter denominator. * @prefill_lines: max prefill lines based on panel */ struct sde_rsc_cmd_config { u32 fps; u32 vtotal; u32 jitter_numer; u32 jitter_denom; u32 prefill_lines; }; #ifdef CONFIG_DRM_SDE_RSC /** * sde_rsc_client_create() - create the client for sde rsc. * Different displays like DSI, HDMI, DP, WB, etc should call this * api to register their vote for rpmh. They still need to vote for * power handle to get the clocks. * @rsc_index: A client will be created on this RSC. As of now only * SDE_RSC_INDEX is valid rsc index. * @name: Caller needs to provide some valid string to identify * the client. "primary", "dp", "hdmi" are suggested name. * @is_primary: Caller needs to provide information if client is primary * or not. Primary client votes will be redirected to * display rsc. * @config: fps, vtotal, porches, etc configuration for command mode * panel * @client_type: check client_type enum for information * @vsync_source: This parameter is only valid for primary display. It provides * vsync source information * * Return: client node pointer. */ struct sde_rsc_client *sde_rsc_client_create(u32 rsc_index, char *name, enum sde_rsc_client_type client_type, u32 vsync_source); /** * sde_rsc_client_destroy() - Destroy the sde rsc client. * * @client: Client pointer provided by sde_rsc_client_create(). * * Return: none */ void sde_rsc_client_destroy(struct sde_rsc_client *client); /** * sde_rsc_client_state_update() - rsc client state update * Video mode, cmd mode and clk state are supported as modes. A client need to * set this property during panel time. A switching client can set the * property to change the state * * @client: Client pointer provided by sde_rsc_client_create(). * @state: Client state - video/cmd * @config: fps, vtotal, porches, etc configuration for command mode * panel * @crtc_id: current client's crtc id * @wait_vblank_crtc_id: Output parameter. If set to non-zero, rsc hw * state update requires a wait for one vblank on * the primary crtc. In that case, this output * param will be set to the crtc on which to wait. * If SDE_RSC_INVALID_CRTC_ID, no wait necessary * * Return: error code. */ int sde_rsc_client_state_update(struct sde_rsc_client *client, enum sde_rsc_state state, struct sde_rsc_cmd_config *config, int crtc_id, int *wait_vblank_crtc_id); /** * sde_rsc_client_get_vsync_refcount() - returns the status of the vsync * refcount, to signal if the client needs to reset the refcounting logic * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client); /** * sde_rsc_client_reset_vsync_refcount() - reduces the refcounting * logic that waits for the vsync. * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client); /** * sde_rsc_client_is_state_update_complete() - check if state update is complete * RSC state transition is not complete until HW receives VBLANK signal. This * function checks RSC HW to determine whether that signal has been received. * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ bool sde_rsc_client_is_state_update_complete( struct sde_rsc_client *caller_client); /** * sde_rsc_client_vote() - stores ab/ib vote for rsc client * * @client: Client pointer provided by sde_rsc_client_create(). * @bus_id: data bus identifier * @ab: aggregated bandwidth vote from client. * @ib: instant bandwidth vote from client. * * Return: error code. */ int sde_rsc_client_vote(struct sde_rsc_client *caller_client, u32 bus_id, u64 ab_vote, u64 ib_vote); /** * 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); /** * is_sde_rsc_available - check if display rsc available. * @rsc_index: A client will be created on this RSC. As of now only * SDE_RSC_INDEX is valid rsc index. * Returns: true if rsc is available; false in all other cases */ bool is_sde_rsc_available(int rsc_index); /** * get_sde_rsc_current_state - gets the current state of sde rsc. * @rsc_index: A client will be created on this RSC. As of now only * SDE_RSC_INDEX is valid rsc index. * Returns: current state if rsc available; SDE_RSC_IDLE_STATE for * all other cases */ enum sde_rsc_state get_sde_rsc_current_state(int rsc_index); /** * get_sde_rsc_primary_crtc - gets the primary crtc for the sde rsc. * @rsc_index: A client will be created on this RSC. As of now only * SDE_RSC_INDEX is valid rsc index. * Returns: crtc id of primary crtc ; 0 for all other cases. */ int get_sde_rsc_primary_crtc(int rsc_index); /** * sde_rsc_client_trigger_vote() - triggers ab/ib vote for rsc client * * @client: Client pointer provided by sde_rsc_client_create(). * @delta_vote: if bw vote is increased or decreased * * Return: error code. */ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client, bool delta_vote); /** * get_sde_rsc_version - get the supported rsc version * * @rsc_index: A client will be created on this RSC. As of now only * SDE_RSC_INDEX is valid rsc index. * Return the rsc version. */ u32 get_sde_rsc_version(int rsc_index); #else static inline struct sde_rsc_client *sde_rsc_client_create(u32 rsc_index, char *name, enum sde_rsc_client_type client_type, u32 vsync_source) { return NULL; } static inline void sde_rsc_client_destroy(struct sde_rsc_client *client) { } static inline int sde_rsc_client_state_update(struct sde_rsc_client *client, enum sde_rsc_state state, struct sde_rsc_cmd_config *config, int crtc_id, int *wait_vblank_crtc_id) { return 0; } static inline int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client) { return 0; } static inline int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client) { return 0; } static inline bool sde_rsc_client_is_state_update_complete( struct sde_rsc_client *caller_client) { return false; } static inline int sde_rsc_client_vote(struct sde_rsc_client *caller_client, u32 bus_id, u64 ab_vote, u64 ib_vote) { return 0; } static inline 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) { return NULL; } static inline void sde_rsc_unregister_event(struct sde_rsc_event *event) { } static inline bool is_sde_rsc_available(int rsc_index) { return false; } static inline enum sde_rsc_state get_sde_rsc_current_state(int rsc_index) { return SDE_RSC_IDLE_STATE; } static inline int get_sde_rsc_primary_crtc(int rsc_index) { return 0; } static inline int sde_rsc_client_trigger_vote( struct sde_rsc_client *caller_client, bool delta_vote) { return 0; } static inline u32 get_sde_rsc_version(int rsc_index) { return 0; } #endif /* CONFIG_DRM_SDE_RSC */ #endif /* _SDE_RSC_H_ */