|  | /* SPDX-License-Identifier: GPL-2.0-or-later */ | 
|  | /* | 
|  | * Copyright (c) 2017 Samsung Electronics Co., Ltd. | 
|  | */ | 
|  |  | 
|  | #ifndef _EXYNOS_DRM_IPP_H_ | 
|  | #define _EXYNOS_DRM_IPP_H_ | 
|  |  | 
|  | struct exynos_drm_ipp; | 
|  | struct exynos_drm_ipp_task; | 
|  |  | 
|  | /** | 
|  | * struct exynos_drm_ipp_funcs - exynos_drm_ipp control functions | 
|  | */ | 
|  | struct exynos_drm_ipp_funcs { | 
|  | /** | 
|  | * @commit: | 
|  | * | 
|  | * This is the main entry point to start framebuffer processing | 
|  | * in the hardware. The exynos_drm_ipp_task has been already validated. | 
|  | * This function must not wait until the device finishes processing. | 
|  | * When the driver finishes processing, it has to call | 
|  | * exynos_exynos_drm_ipp_task_done() function. | 
|  | * | 
|  | * RETURNS: | 
|  | * | 
|  | * 0 on success or negative error codes in case of failure. | 
|  | */ | 
|  | int (*commit)(struct exynos_drm_ipp *ipp, | 
|  | struct exynos_drm_ipp_task *task); | 
|  |  | 
|  | /** | 
|  | * @abort: | 
|  | * | 
|  | * Informs the driver that it has to abort the currently running | 
|  | * task as soon as possible (i.e. as soon as it can stop the device | 
|  | * safely), even if the task would not have been finished by then. | 
|  | * After the driver performs the necessary steps, it has to call | 
|  | * exynos_drm_ipp_task_done() (as if the task ended normally). | 
|  | * This function does not have to (and will usually not) wait | 
|  | * until the device enters a state when it can be stopped. | 
|  | */ | 
|  | void (*abort)(struct exynos_drm_ipp *ipp, | 
|  | struct exynos_drm_ipp_task *task); | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct exynos_drm_ipp - central picture processor module structure | 
|  | */ | 
|  | struct exynos_drm_ipp { | 
|  | struct drm_device *drm_dev; | 
|  | struct device *dev; | 
|  | struct list_head head; | 
|  | unsigned int id; | 
|  |  | 
|  | const char *name; | 
|  | const struct exynos_drm_ipp_funcs *funcs; | 
|  | unsigned int capabilities; | 
|  | const struct exynos_drm_ipp_formats *formats; | 
|  | unsigned int num_formats; | 
|  | atomic_t sequence; | 
|  |  | 
|  | spinlock_t lock; | 
|  | struct exynos_drm_ipp_task *task; | 
|  | struct list_head todo_list; | 
|  | wait_queue_head_t done_wq; | 
|  | }; | 
|  |  | 
|  | struct exynos_drm_ipp_buffer { | 
|  | struct drm_exynos_ipp_task_buffer buf; | 
|  | struct drm_exynos_ipp_task_rect rect; | 
|  |  | 
|  | struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; | 
|  | const struct drm_format_info *format; | 
|  | dma_addr_t dma_addr[MAX_FB_BUFFER]; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct exynos_drm_ipp_task - a structure describing transformation that | 
|  | * has to be performed by the picture processor hardware module | 
|  | */ | 
|  | struct exynos_drm_ipp_task { | 
|  | struct device *dev; | 
|  | struct exynos_drm_ipp *ipp; | 
|  | struct list_head head; | 
|  |  | 
|  | struct exynos_drm_ipp_buffer src; | 
|  | struct exynos_drm_ipp_buffer dst; | 
|  |  | 
|  | struct drm_exynos_ipp_task_transform transform; | 
|  | struct drm_exynos_ipp_task_alpha alpha; | 
|  |  | 
|  | struct work_struct cleanup_work; | 
|  | unsigned int flags; | 
|  | int ret; | 
|  |  | 
|  | struct drm_pending_exynos_ipp_event *event; | 
|  | }; | 
|  |  | 
|  | #define DRM_EXYNOS_IPP_TASK_DONE	(1 << 0) | 
|  | #define DRM_EXYNOS_IPP_TASK_ASYNC	(1 << 1) | 
|  |  | 
|  | struct exynos_drm_ipp_formats { | 
|  | uint32_t fourcc; | 
|  | uint32_t type; | 
|  | uint64_t modifier; | 
|  | const struct drm_exynos_ipp_limit *limits; | 
|  | unsigned int num_limits; | 
|  | }; | 
|  |  | 
|  | /* helper macros to set exynos_drm_ipp_formats structure and limits*/ | 
|  | #define IPP_SRCDST_MFORMAT(f, m, l) \ | 
|  | .fourcc = DRM_FORMAT_##f, .modifier = m, .limits = l, \ | 
|  | .num_limits = ARRAY_SIZE(l), \ | 
|  | .type = (DRM_EXYNOS_IPP_FORMAT_SOURCE | \ | 
|  | DRM_EXYNOS_IPP_FORMAT_DESTINATION) | 
|  |  | 
|  | #define IPP_SRCDST_FORMAT(f, l) IPP_SRCDST_MFORMAT(f, 0, l) | 
|  |  | 
|  | #define IPP_SIZE_LIMIT(l, val...)	\ | 
|  | .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE | \ | 
|  | DRM_EXYNOS_IPP_LIMIT_SIZE_##l), val | 
|  |  | 
|  | #define IPP_SCALE_LIMIT(val...)		\ | 
|  | .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE), val | 
|  |  | 
|  | int exynos_drm_ipp_register(struct device *dev, struct exynos_drm_ipp *ipp, | 
|  | const struct exynos_drm_ipp_funcs *funcs, unsigned int caps, | 
|  | const struct exynos_drm_ipp_formats *formats, | 
|  | unsigned int num_formats, const char *name); | 
|  | void exynos_drm_ipp_unregister(struct device *dev, | 
|  | struct exynos_drm_ipp *ipp); | 
|  |  | 
|  | void exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret); | 
|  |  | 
|  | #ifdef CONFIG_DRM_EXYNOS_IPP | 
|  | int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data, | 
|  | struct drm_file *file_priv); | 
|  | int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data, | 
|  | struct drm_file *file_priv); | 
|  | int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data, | 
|  | struct drm_file *file_priv); | 
|  | int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, | 
|  | void *data, struct drm_file *file_priv); | 
|  | #else | 
|  | static inline int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, | 
|  | void *data, struct drm_file *file_priv) | 
|  | { | 
|  | struct drm_exynos_ioctl_ipp_get_res *resp = data; | 
|  |  | 
|  | resp->count_ipps = 0; | 
|  | return 0; | 
|  | } | 
|  | static inline int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, | 
|  | void *data, struct drm_file *file_priv) | 
|  | { | 
|  | return -ENODEV; | 
|  | } | 
|  | static inline int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, | 
|  | void *data, struct drm_file *file_priv) | 
|  | { | 
|  | return -ENODEV; | 
|  | } | 
|  | static inline int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, | 
|  | void *data, struct drm_file *file_priv) | 
|  | { | 
|  | return -ENODEV; | 
|  | } | 
|  | #endif | 
|  | #endif |