162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2017 Samsung Electronics Co., Ltd. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef _EXYNOS_DRM_IPP_H_ 762306a36Sopenharmony_ci#define _EXYNOS_DRM_IPP_H_ 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistruct exynos_drm_ipp; 1062306a36Sopenharmony_cistruct exynos_drm_ipp_task; 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/** 1362306a36Sopenharmony_ci * struct exynos_drm_ipp_funcs - exynos_drm_ipp control functions 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_cistruct exynos_drm_ipp_funcs { 1662306a36Sopenharmony_ci /** 1762306a36Sopenharmony_ci * @commit: 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * This is the main entry point to start framebuffer processing 2062306a36Sopenharmony_ci * in the hardware. The exynos_drm_ipp_task has been already validated. 2162306a36Sopenharmony_ci * This function must not wait until the device finishes processing. 2262306a36Sopenharmony_ci * When the driver finishes processing, it has to call 2362306a36Sopenharmony_ci * exynos_exynos_drm_ipp_task_done() function. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * RETURNS: 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * 0 on success or negative error codes in case of failure. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci int (*commit)(struct exynos_drm_ipp *ipp, 3062306a36Sopenharmony_ci struct exynos_drm_ipp_task *task); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci /** 3362306a36Sopenharmony_ci * @abort: 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * Informs the driver that it has to abort the currently running 3662306a36Sopenharmony_ci * task as soon as possible (i.e. as soon as it can stop the device 3762306a36Sopenharmony_ci * safely), even if the task would not have been finished by then. 3862306a36Sopenharmony_ci * After the driver performs the necessary steps, it has to call 3962306a36Sopenharmony_ci * exynos_drm_ipp_task_done() (as if the task ended normally). 4062306a36Sopenharmony_ci * This function does not have to (and will usually not) wait 4162306a36Sopenharmony_ci * until the device enters a state when it can be stopped. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci void (*abort)(struct exynos_drm_ipp *ipp, 4462306a36Sopenharmony_ci struct exynos_drm_ipp_task *task); 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/** 4862306a36Sopenharmony_ci * struct exynos_drm_ipp - central picture processor module structure 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistruct exynos_drm_ipp { 5162306a36Sopenharmony_ci struct drm_device *drm_dev; 5262306a36Sopenharmony_ci struct device *dev; 5362306a36Sopenharmony_ci struct list_head head; 5462306a36Sopenharmony_ci unsigned int id; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci const char *name; 5762306a36Sopenharmony_ci const struct exynos_drm_ipp_funcs *funcs; 5862306a36Sopenharmony_ci unsigned int capabilities; 5962306a36Sopenharmony_ci const struct exynos_drm_ipp_formats *formats; 6062306a36Sopenharmony_ci unsigned int num_formats; 6162306a36Sopenharmony_ci atomic_t sequence; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci spinlock_t lock; 6462306a36Sopenharmony_ci struct exynos_drm_ipp_task *task; 6562306a36Sopenharmony_ci struct list_head todo_list; 6662306a36Sopenharmony_ci wait_queue_head_t done_wq; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct exynos_drm_ipp_buffer { 7062306a36Sopenharmony_ci struct drm_exynos_ipp_task_buffer buf; 7162306a36Sopenharmony_ci struct drm_exynos_ipp_task_rect rect; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; 7462306a36Sopenharmony_ci const struct drm_format_info *format; 7562306a36Sopenharmony_ci dma_addr_t dma_addr[MAX_FB_BUFFER]; 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/** 7962306a36Sopenharmony_ci * struct exynos_drm_ipp_task - a structure describing transformation that 8062306a36Sopenharmony_ci * has to be performed by the picture processor hardware module 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_cistruct exynos_drm_ipp_task { 8362306a36Sopenharmony_ci struct device *dev; 8462306a36Sopenharmony_ci struct exynos_drm_ipp *ipp; 8562306a36Sopenharmony_ci struct list_head head; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci struct exynos_drm_ipp_buffer src; 8862306a36Sopenharmony_ci struct exynos_drm_ipp_buffer dst; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci struct drm_exynos_ipp_task_transform transform; 9162306a36Sopenharmony_ci struct drm_exynos_ipp_task_alpha alpha; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci struct work_struct cleanup_work; 9462306a36Sopenharmony_ci unsigned int flags; 9562306a36Sopenharmony_ci int ret; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci struct drm_pending_exynos_ipp_event *event; 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define DRM_EXYNOS_IPP_TASK_DONE (1 << 0) 10162306a36Sopenharmony_ci#define DRM_EXYNOS_IPP_TASK_ASYNC (1 << 1) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistruct exynos_drm_ipp_formats { 10462306a36Sopenharmony_ci uint32_t fourcc; 10562306a36Sopenharmony_ci uint32_t type; 10662306a36Sopenharmony_ci uint64_t modifier; 10762306a36Sopenharmony_ci const struct drm_exynos_ipp_limit *limits; 10862306a36Sopenharmony_ci unsigned int num_limits; 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* helper macros to set exynos_drm_ipp_formats structure and limits*/ 11262306a36Sopenharmony_ci#define IPP_SRCDST_MFORMAT(f, m, l) \ 11362306a36Sopenharmony_ci .fourcc = DRM_FORMAT_##f, .modifier = m, .limits = l, \ 11462306a36Sopenharmony_ci .num_limits = ARRAY_SIZE(l), \ 11562306a36Sopenharmony_ci .type = (DRM_EXYNOS_IPP_FORMAT_SOURCE | \ 11662306a36Sopenharmony_ci DRM_EXYNOS_IPP_FORMAT_DESTINATION) 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define IPP_SRCDST_FORMAT(f, l) IPP_SRCDST_MFORMAT(f, 0, l) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define IPP_SIZE_LIMIT(l, val...) \ 12162306a36Sopenharmony_ci .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE | \ 12262306a36Sopenharmony_ci DRM_EXYNOS_IPP_LIMIT_SIZE_##l), val 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define IPP_SCALE_LIMIT(val...) \ 12562306a36Sopenharmony_ci .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE), val 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciint exynos_drm_ipp_register(struct device *dev, struct exynos_drm_ipp *ipp, 12862306a36Sopenharmony_ci const struct exynos_drm_ipp_funcs *funcs, unsigned int caps, 12962306a36Sopenharmony_ci const struct exynos_drm_ipp_formats *formats, 13062306a36Sopenharmony_ci unsigned int num_formats, const char *name); 13162306a36Sopenharmony_civoid exynos_drm_ipp_unregister(struct device *dev, 13262306a36Sopenharmony_ci struct exynos_drm_ipp *ipp); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_civoid exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#ifdef CONFIG_DRM_EXYNOS_IPP 13762306a36Sopenharmony_ciint exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data, 13862306a36Sopenharmony_ci struct drm_file *file_priv); 13962306a36Sopenharmony_ciint exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data, 14062306a36Sopenharmony_ci struct drm_file *file_priv); 14162306a36Sopenharmony_ciint exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data, 14262306a36Sopenharmony_ci struct drm_file *file_priv); 14362306a36Sopenharmony_ciint exynos_drm_ipp_commit_ioctl(struct drm_device *dev, 14462306a36Sopenharmony_ci void *data, struct drm_file *file_priv); 14562306a36Sopenharmony_ci#else 14662306a36Sopenharmony_cistatic inline int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, 14762306a36Sopenharmony_ci void *data, struct drm_file *file_priv) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct drm_exynos_ioctl_ipp_get_res *resp = data; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci resp->count_ipps = 0; 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_cistatic inline int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, 15562306a36Sopenharmony_ci void *data, struct drm_file *file_priv) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci return -ENODEV; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_cistatic inline int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, 16062306a36Sopenharmony_ci void *data, struct drm_file *file_priv) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci return -ENODEV; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_cistatic inline int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, 16562306a36Sopenharmony_ci void *data, struct drm_file *file_priv) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci return -ENODEV; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci#endif 17062306a36Sopenharmony_ci#endif 171