18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2017 Samsung Electronics Co., Ltd.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef _EXYNOS_DRM_IPP_H_
78c2ecf20Sopenharmony_ci#define _EXYNOS_DRM_IPP_H_
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistruct exynos_drm_ipp;
108c2ecf20Sopenharmony_cistruct exynos_drm_ipp_task;
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/**
138c2ecf20Sopenharmony_ci * struct exynos_drm_ipp_funcs - exynos_drm_ipp control functions
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_cistruct exynos_drm_ipp_funcs {
168c2ecf20Sopenharmony_ci	/**
178c2ecf20Sopenharmony_ci	 * @commit:
188c2ecf20Sopenharmony_ci	 *
198c2ecf20Sopenharmony_ci	 * This is the main entry point to start framebuffer processing
208c2ecf20Sopenharmony_ci	 * in the hardware. The exynos_drm_ipp_task has been already validated.
218c2ecf20Sopenharmony_ci	 * This function must not wait until the device finishes processing.
228c2ecf20Sopenharmony_ci	 * When the driver finishes processing, it has to call
238c2ecf20Sopenharmony_ci	 * exynos_exynos_drm_ipp_task_done() function.
248c2ecf20Sopenharmony_ci	 *
258c2ecf20Sopenharmony_ci	 * RETURNS:
268c2ecf20Sopenharmony_ci	 *
278c2ecf20Sopenharmony_ci	 * 0 on success or negative error codes in case of failure.
288c2ecf20Sopenharmony_ci	 */
298c2ecf20Sopenharmony_ci	int (*commit)(struct exynos_drm_ipp *ipp,
308c2ecf20Sopenharmony_ci		      struct exynos_drm_ipp_task *task);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	/**
338c2ecf20Sopenharmony_ci	 * @abort:
348c2ecf20Sopenharmony_ci	 *
358c2ecf20Sopenharmony_ci	 * Informs the driver that it has to abort the currently running
368c2ecf20Sopenharmony_ci	 * task as soon as possible (i.e. as soon as it can stop the device
378c2ecf20Sopenharmony_ci	 * safely), even if the task would not have been finished by then.
388c2ecf20Sopenharmony_ci	 * After the driver performs the necessary steps, it has to call
398c2ecf20Sopenharmony_ci	 * exynos_drm_ipp_task_done() (as if the task ended normally).
408c2ecf20Sopenharmony_ci	 * This function does not have to (and will usually not) wait
418c2ecf20Sopenharmony_ci	 * until the device enters a state when it can be stopped.
428c2ecf20Sopenharmony_ci	 */
438c2ecf20Sopenharmony_ci	void (*abort)(struct exynos_drm_ipp *ipp,
448c2ecf20Sopenharmony_ci		      struct exynos_drm_ipp_task *task);
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/**
488c2ecf20Sopenharmony_ci * struct exynos_drm_ipp - central picture processor module structure
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_cistruct exynos_drm_ipp {
518c2ecf20Sopenharmony_ci	struct drm_device *drm_dev;
528c2ecf20Sopenharmony_ci	struct device *dev;
538c2ecf20Sopenharmony_ci	struct list_head head;
548c2ecf20Sopenharmony_ci	unsigned int id;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	const char *name;
578c2ecf20Sopenharmony_ci	const struct exynos_drm_ipp_funcs *funcs;
588c2ecf20Sopenharmony_ci	unsigned int capabilities;
598c2ecf20Sopenharmony_ci	const struct exynos_drm_ipp_formats *formats;
608c2ecf20Sopenharmony_ci	unsigned int num_formats;
618c2ecf20Sopenharmony_ci	atomic_t sequence;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	spinlock_t lock;
648c2ecf20Sopenharmony_ci	struct exynos_drm_ipp_task *task;
658c2ecf20Sopenharmony_ci	struct list_head todo_list;
668c2ecf20Sopenharmony_ci	wait_queue_head_t done_wq;
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistruct exynos_drm_ipp_buffer {
708c2ecf20Sopenharmony_ci	struct drm_exynos_ipp_task_buffer buf;
718c2ecf20Sopenharmony_ci	struct drm_exynos_ipp_task_rect rect;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
748c2ecf20Sopenharmony_ci	const struct drm_format_info *format;
758c2ecf20Sopenharmony_ci	dma_addr_t dma_addr[MAX_FB_BUFFER];
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/**
798c2ecf20Sopenharmony_ci * struct exynos_drm_ipp_task - a structure describing transformation that
808c2ecf20Sopenharmony_ci * has to be performed by the picture processor hardware module
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_cistruct exynos_drm_ipp_task {
838c2ecf20Sopenharmony_ci	struct device *dev;
848c2ecf20Sopenharmony_ci	struct exynos_drm_ipp *ipp;
858c2ecf20Sopenharmony_ci	struct list_head head;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	struct exynos_drm_ipp_buffer src;
888c2ecf20Sopenharmony_ci	struct exynos_drm_ipp_buffer dst;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	struct drm_exynos_ipp_task_transform transform;
918c2ecf20Sopenharmony_ci	struct drm_exynos_ipp_task_alpha alpha;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	struct work_struct cleanup_work;
948c2ecf20Sopenharmony_ci	unsigned int flags;
958c2ecf20Sopenharmony_ci	int ret;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	struct drm_pending_exynos_ipp_event *event;
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#define DRM_EXYNOS_IPP_TASK_DONE	(1 << 0)
1018c2ecf20Sopenharmony_ci#define DRM_EXYNOS_IPP_TASK_ASYNC	(1 << 1)
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistruct exynos_drm_ipp_formats {
1048c2ecf20Sopenharmony_ci	uint32_t fourcc;
1058c2ecf20Sopenharmony_ci	uint32_t type;
1068c2ecf20Sopenharmony_ci	uint64_t modifier;
1078c2ecf20Sopenharmony_ci	const struct drm_exynos_ipp_limit *limits;
1088c2ecf20Sopenharmony_ci	unsigned int num_limits;
1098c2ecf20Sopenharmony_ci};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci/* helper macros to set exynos_drm_ipp_formats structure and limits*/
1128c2ecf20Sopenharmony_ci#define IPP_SRCDST_MFORMAT(f, m, l) \
1138c2ecf20Sopenharmony_ci	.fourcc = DRM_FORMAT_##f, .modifier = m, .limits = l, \
1148c2ecf20Sopenharmony_ci	.num_limits = ARRAY_SIZE(l), \
1158c2ecf20Sopenharmony_ci	.type = (DRM_EXYNOS_IPP_FORMAT_SOURCE | \
1168c2ecf20Sopenharmony_ci		 DRM_EXYNOS_IPP_FORMAT_DESTINATION)
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#define IPP_SRCDST_FORMAT(f, l) IPP_SRCDST_MFORMAT(f, 0, l)
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#define IPP_SIZE_LIMIT(l, val...)	\
1218c2ecf20Sopenharmony_ci	.type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE | \
1228c2ecf20Sopenharmony_ci		 DRM_EXYNOS_IPP_LIMIT_SIZE_##l), val
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci#define IPP_SCALE_LIMIT(val...)		\
1258c2ecf20Sopenharmony_ci	.type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE), val
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ciint exynos_drm_ipp_register(struct device *dev, struct exynos_drm_ipp *ipp,
1288c2ecf20Sopenharmony_ci		const struct exynos_drm_ipp_funcs *funcs, unsigned int caps,
1298c2ecf20Sopenharmony_ci		const struct exynos_drm_ipp_formats *formats,
1308c2ecf20Sopenharmony_ci		unsigned int num_formats, const char *name);
1318c2ecf20Sopenharmony_civoid exynos_drm_ipp_unregister(struct device *dev,
1328c2ecf20Sopenharmony_ci			       struct exynos_drm_ipp *ipp);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_civoid exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#ifdef CONFIG_DRM_EXYNOS_IPP
1378c2ecf20Sopenharmony_ciint exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data,
1388c2ecf20Sopenharmony_ci				 struct drm_file *file_priv);
1398c2ecf20Sopenharmony_ciint exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data,
1408c2ecf20Sopenharmony_ci				  struct drm_file *file_priv);
1418c2ecf20Sopenharmony_ciint exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data,
1428c2ecf20Sopenharmony_ci				    struct drm_file *file_priv);
1438c2ecf20Sopenharmony_ciint exynos_drm_ipp_commit_ioctl(struct drm_device *dev,
1448c2ecf20Sopenharmony_ci				void *data, struct drm_file *file_priv);
1458c2ecf20Sopenharmony_ci#else
1468c2ecf20Sopenharmony_cistatic inline int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev,
1478c2ecf20Sopenharmony_ci	 void *data, struct drm_file *file_priv)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct drm_exynos_ioctl_ipp_get_res *resp = data;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	resp->count_ipps = 0;
1528c2ecf20Sopenharmony_ci	return 0;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_cistatic inline int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev,
1558c2ecf20Sopenharmony_ci	 void *data, struct drm_file *file_priv)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	return -ENODEV;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_cistatic inline int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev,
1608c2ecf20Sopenharmony_ci	 void *data, struct drm_file *file_priv)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	return -ENODEV;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_cistatic inline int exynos_drm_ipp_commit_ioctl(struct drm_device *dev,
1658c2ecf20Sopenharmony_ci	 void *data, struct drm_file *file_priv)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	return -ENODEV;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci#endif
1708c2ecf20Sopenharmony_ci#endif
171