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