/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef __SDE_VM_H__ #define __SDE_VM_H__ #include "msm_drv.h" #define TRUSTED_VM_MAX_ENCODER_PER_CRTC 1 struct sde_kms; /* sde_vm_msg_type - msg_type for dispaly custom messages */ enum sde_vm_msg_type { SDE_VM_MSG_MAX, }; /** * sde_vm_msg_work - sde msgq work definition * @work - base kthread work object * @msg_buf - payload buffer * @msg_size - payload buffer size * @sde_vm - handle to vm structure */ struct sde_vm_msg_work { struct kthread_work work; void *msg_buf; size_t msg_size; struct sde_vm *sde_vm; }; /** * sde_vm_msg_header - header definition for custom messages. Must * be placed at the beginning of each custom * message definition. * @msg_type - type of the message */ struct sde_vm_msg_header { enum sde_vm_msg_type msg_type; }; /** * sde_vm_irq_entry - VM irq specification * @label - VM_IRQ_LABEL assigned by Hyp RM * @irq - linux mapped irq number */ struct sde_vm_irq_entry { u32 label; u32 irq; }; /** * sde_vm_irq_desc - list of IRQ's to be handled * @n_irq - irq count * @irq_entries - list of sde_vm_irq_entry */ struct sde_vm_irq_desc { u32 n_irq; struct sde_vm_irq_entry *irq_entries; }; enum sde_crtc_vm_req; /** * sde_vm_ops - VM specific function hooks */ struct sde_vm_ops { /** * vm_acquire - hook to handle HW accept * @kms - handle to sde_kms * @return - return 0 on success */ int (*vm_acquire)(struct sde_kms *kms); /** * vm_release - hook to handle HW release * @kms - handle to sde_kms * @return - return 0 on success */ int (*vm_release)(struct sde_kms *kms); /** * vm_owns_hw - hook to query the HW status of the VM * @kms - handle to sde_kms * @return - return true when vm owns the hw */ bool (*vm_owns_hw)(struct sde_kms *kms); /** * vm_prepare_commit - hook to handle operations before the first commit after acquiring the HW * @sde_kms - handle to sde_kms * @state - global atomic state to be parsed * @return - return 0 on success */ int (*vm_prepare_commit)(struct sde_kms *sde_kms, struct drm_atomic_state *state); /** * vm_post_commit - hook to handle operations after last commit before release * @sde_kms - handle to sde_kms * @state - global atomic state to be parsed * @return - return 0 on success */ int (*vm_post_commit)(struct sde_kms *sde_kms, struct drm_atomic_state *state); /** * vm_deinit - deinitialize VM layer * @kms - pointer to sde_kms * @ops - primary VM specific ops functions */ void (*vm_deinit)(struct sde_kms *kms, struct sde_vm_ops *ops); /** * vm_check - hook to check with vm_clients for its readiness to release the HW reasources */ int (*vm_check)(void); /** * vm_client_pre_release - hook to invoke vm_client list for pre_release handling * @kms - handle to sde_kms */ int (*vm_client_pre_release)(struct sde_kms *kms); /** * vm_client_post_acquire - hook to invoke vm_client list for * post_acquire resource handling * @kms - handle to sde_kms */ int (*vm_client_post_acquire)(struct sde_kms *kms); /** * vm_request_valid - hook to validate the RM_REQ state change * @sde_kms - handle to sde_kms * @old_state - current vm_req state * @new_state - new vm_req state */ int (*vm_request_valid)(struct sde_kms *sde_kms, enum sde_crtc_vm_req old_state, enum sde_crtc_vm_req new_state); /** * vm_acquire_fail_handler - hook to the handler when resource * accept/reclaim fails. * @sde_kms - handle to sde_kms */ int (*vm_acquire_fail_handler)(struct sde_kms *sde_kms); /** vm_msg_recv_cb - sde kms callback hook for msgq data * @sde_vm - handle to sde_vm struct * @data - paylod data * @size - size of payload data */ void (*vm_msg_recv_cb)(struct sde_vm *sde_vm, void *data, size_t size); /** vm_msg_send - hook to send custom data to VM * @sde_vm - handle to sde_vm struct * @msg - payload data * @msg_size - payload data size * @return - 0 on success, errorcode otherwise */ int (*vm_msg_send)(struct sde_vm *sde_vm, void *msg, size_t msg_size); /** * vm_resource_init - hook to the handler when resource * accept/reclaim fails. * @sde_kms - handle to sde_kms * @state: current update atomic commit state */ int (*vm_resource_init)(struct sde_kms *sde_kms, struct drm_atomic_state *state); }; /** * sde_vm - VM layer descriptor. Abstract for all the VM's * @vm_res_lock - mutex to protect resource updates * @mem_notificaiton_cookie - Hyp RM notification identifier * @n_irq_lent - irq count * @io_mem_handle - RM identifier for the IO range * @sde_kms - handle to sde_kms * @vm_ops - VM operation hooks for respective VM type * @msgq_listener_thread - handle to msgq receiver thread * @vm_work - kthread work obj for msgq * @msgq_handle - handle to display msgq * @lastclose_in_progress - boolean entry to check if * lastclose is in progress */ struct sde_vm { struct mutex vm_res_lock; void *mem_notification_cookie; atomic_t n_irq_lent; int io_mem_handle; struct sde_kms *sde_kms; struct sde_vm_ops vm_ops; struct task_struct *msgq_listener_thread; struct sde_vm_msg_work vm_work; void *msgq_handle; bool lastclose_in_progress; }; /** * sde_vm_primary - VM layer descriptor for Primary VM * @base - parent struct object * @irq_desc - cache copy of irq list for validating reclaim */ struct sde_vm_primary { struct sde_vm base; struct sde_vm_irq_desc *irq_desc; }; /** * sde_vm_trusted - VM layer descriptor for Trusted VM * @base - parent struct object * @sgl_desc - hyp RM sgl list descriptor for IO ranges * @irq_desc - irq list */ struct sde_vm_trusted { struct sde_vm base; struct sde_vm_irq_desc *irq_desc; struct gh_sgl_desc *sgl_desc; }; #if IS_ENABLED(CONFIG_DRM_SDE_VM) /** * sde_vm_primary_init - Initialize primary VM layer * @kms - pointer to sde_kms * @return - 0 on success */ int sde_vm_primary_init(struct sde_kms *kms); /** * sde_vm_trusted_init - Initialize Trusted VM layer * @kms - pointer to sde_kms * @ops - primary VM specific ops functions * @return - 0 on success */ int sde_vm_trusted_init(struct sde_kms *kms); /** * sde_vm_is_enabled - check whether TUI feature is enabled * @sde_kms - pointer to sde_kms * @return - true if enabled, false otherwise */ static inline bool sde_vm_is_enabled(struct sde_kms *sde_kms) { return !!sde_kms->vm; } /** * sde_vm_lock - lock vm variables * @sde_kms - pointer to sde_kms */ static inline void sde_vm_lock(struct sde_kms *sde_kms) { if (!sde_kms->vm) return; mutex_lock(&sde_kms->vm->vm_res_lock); } /** * sde_vm_unlock - unlock vm variables * @sde_kms - pointer to sde_kms */ static inline void sde_vm_unlock(struct sde_kms *sde_kms) { if (!sde_kms->vm) return; mutex_unlock(&sde_kms->vm->vm_res_lock); } /** * sde_vm_get_ops - helper API to retrieve sde_vm_ops * @sde_kms - pointer to sde_kms * @return - pointer to sde_vm_ops */ static inline struct sde_vm_ops *sde_vm_get_ops(struct sde_kms *sde_kms) { if (!sde_kms->vm) return NULL; return &sde_kms->vm->vm_ops; } /** * sde_vm_owns_hw - checks if the executing VM currently has HW ownership (caller must be holding * the sde_vm_lock) * @sde_kms - pointer to sde_kms * @return - true if this VM currently owns the HW */ static inline bool sde_vm_owns_hw(struct sde_kms *sde_kms) { struct sde_vm_ops *vm_ops = sde_kms ? sde_vm_get_ops(sde_kms) : NULL; if (vm_ops && vm_ops->vm_owns_hw) return vm_ops->vm_owns_hw(sde_kms); return true; } #else static inline int sde_vm_primary_init(struct sde_kms *kms) { return 0; } static inline int sde_vm_trusted_init(struct sde_kms *kms) { return 0; } static inline bool sde_vm_is_enabled(struct sde_kms *sde_kms) { return false; } static inline void sde_vm_lock(struct sde_kms *sde_kms) { } static inline void sde_vm_unlock(struct sde_kms *sde_kms) { } static inline struct sde_vm_ops *sde_vm_get_ops(struct sde_kms *sde_kms) { return NULL; } static inline bool sde_vm_owns_hw(struct sde_kms *sde_kms) { return true; } #endif /* IS_ENABLED(CONFIG_DRM_SDE_VM) */ #endif /* __SDE_VM_H__ */