1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * Copyright (c) 2017 Samsung Electronics Co., Ltd. |
4 | */ |
5 | |
6 | #ifndef _EXYNOS_DRM_IPP_H_ |
7 | #define _EXYNOS_DRM_IPP_H_ |
8 | |
9 | struct exynos_drm_ipp; |
10 | struct exynos_drm_ipp_task; |
11 | |
12 | /** |
13 | * struct exynos_drm_ipp_funcs - exynos_drm_ipp control functions |
14 | */ |
15 | struct exynos_drm_ipp_funcs { |
16 | /** |
17 | * @commit: |
18 | * |
19 | * This is the main entry point to start framebuffer processing |
20 | * in the hardware. The exynos_drm_ipp_task has been already validated. |
21 | * This function must not wait until the device finishes processing. |
22 | * When the driver finishes processing, it has to call |
23 | * exynos_exynos_drm_ipp_task_done() function. |
24 | * |
25 | * RETURNS: |
26 | * |
27 | * 0 on success or negative error codes in case of failure. |
28 | */ |
29 | int (*commit)(struct exynos_drm_ipp *ipp, |
30 | struct exynos_drm_ipp_task *task); |
31 | |
32 | /** |
33 | * @abort: |
34 | * |
35 | * Informs the driver that it has to abort the currently running |
36 | * task as soon as possible (i.e. as soon as it can stop the device |
37 | * safely), even if the task would not have been finished by then. |
38 | * After the driver performs the necessary steps, it has to call |
39 | * exynos_drm_ipp_task_done() (as if the task ended normally). |
40 | * This function does not have to (and will usually not) wait |
41 | * until the device enters a state when it can be stopped. |
42 | */ |
43 | void (*abort)(struct exynos_drm_ipp *ipp, |
44 | struct exynos_drm_ipp_task *task); |
45 | }; |
46 | |
47 | /** |
48 | * struct exynos_drm_ipp - central picture processor module structure |
49 | */ |
50 | struct exynos_drm_ipp { |
51 | struct drm_device *drm_dev; |
52 | struct device *dev; |
53 | struct list_head head; |
54 | unsigned int id; |
55 | |
56 | const char *name; |
57 | const struct exynos_drm_ipp_funcs *funcs; |
58 | unsigned int capabilities; |
59 | const struct exynos_drm_ipp_formats *formats; |
60 | unsigned int num_formats; |
61 | atomic_t sequence; |
62 | |
63 | spinlock_t lock; |
64 | struct exynos_drm_ipp_task *task; |
65 | struct list_head todo_list; |
66 | wait_queue_head_t done_wq; |
67 | }; |
68 | |
69 | struct exynos_drm_ipp_buffer { |
70 | struct drm_exynos_ipp_task_buffer buf; |
71 | struct drm_exynos_ipp_task_rect rect; |
72 | |
73 | struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; |
74 | const struct drm_format_info *format; |
75 | dma_addr_t dma_addr[MAX_FB_BUFFER]; |
76 | }; |
77 | |
78 | /** |
79 | * struct exynos_drm_ipp_task - a structure describing transformation that |
80 | * has to be performed by the picture processor hardware module |
81 | */ |
82 | struct exynos_drm_ipp_task { |
83 | struct device *dev; |
84 | struct exynos_drm_ipp *ipp; |
85 | struct list_head head; |
86 | |
87 | struct exynos_drm_ipp_buffer src; |
88 | struct exynos_drm_ipp_buffer dst; |
89 | |
90 | struct drm_exynos_ipp_task_transform transform; |
91 | struct drm_exynos_ipp_task_alpha alpha; |
92 | |
93 | struct work_struct cleanup_work; |
94 | unsigned int flags; |
95 | int ret; |
96 | |
97 | struct drm_pending_exynos_ipp_event *event; |
98 | }; |
99 | |
100 | #define DRM_EXYNOS_IPP_TASK_DONE (1 << 0) |
101 | #define DRM_EXYNOS_IPP_TASK_ASYNC (1 << 1) |
102 | |
103 | struct exynos_drm_ipp_formats { |
104 | uint32_t fourcc; |
105 | uint32_t type; |
106 | uint64_t modifier; |
107 | const struct drm_exynos_ipp_limit *limits; |
108 | unsigned int num_limits; |
109 | }; |
110 | |
111 | /* helper macros to set exynos_drm_ipp_formats structure and limits*/ |
112 | #define IPP_SRCDST_MFORMAT(f, m, l) \ |
113 | .fourcc = DRM_FORMAT_##f, .modifier = m, .limits = l, \ |
114 | .num_limits = ARRAY_SIZE(l), \ |
115 | .type = (DRM_EXYNOS_IPP_FORMAT_SOURCE | \ |
116 | DRM_EXYNOS_IPP_FORMAT_DESTINATION) |
117 | |
118 | #define IPP_SRCDST_FORMAT(f, l) IPP_SRCDST_MFORMAT(f, 0, l) |
119 | |
120 | #define IPP_SIZE_LIMIT(l, val...) \ |
121 | .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE | \ |
122 | DRM_EXYNOS_IPP_LIMIT_SIZE_##l), val |
123 | |
124 | #define IPP_SCALE_LIMIT(val...) \ |
125 | .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE), val |
126 | |
127 | int exynos_drm_ipp_register(struct device *dev, struct exynos_drm_ipp *ipp, |
128 | const struct exynos_drm_ipp_funcs *funcs, unsigned int caps, |
129 | const struct exynos_drm_ipp_formats *formats, |
130 | unsigned int num_formats, const char *name); |
131 | void exynos_drm_ipp_unregister(struct device *dev, |
132 | struct exynos_drm_ipp *ipp); |
133 | |
134 | void exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret); |
135 | |
136 | #ifdef CONFIG_DRM_EXYNOS_IPP |
137 | int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data, |
138 | struct drm_file *file_priv); |
139 | int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data, |
140 | struct drm_file *file_priv); |
141 | int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data, |
142 | struct drm_file *file_priv); |
143 | int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, |
144 | void *data, struct drm_file *file_priv); |
145 | #else |
146 | static inline int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, |
147 | void *data, struct drm_file *file_priv) |
148 | { |
149 | struct drm_exynos_ioctl_ipp_get_res *resp = data; |
150 | |
151 | resp->count_ipps = 0; |
152 | return 0; |
153 | } |
154 | static inline int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, |
155 | void *data, struct drm_file *file_priv) |
156 | { |
157 | return -ENODEV; |
158 | } |
159 | static inline int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, |
160 | void *data, struct drm_file *file_priv) |
161 | { |
162 | return -ENODEV; |
163 | } |
164 | static inline int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, |
165 | void *data, struct drm_file *file_priv) |
166 | { |
167 | return -ENODEV; |
168 | } |
169 | #endif |
170 | #endif |
171 | |