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 *drm_dev; 58 struct device *dev; 59 struct list_head head; 60 unsigned int id; 61 62 const char *name; 63 const struct exynos_drm_ipp_funcs *funcs; 64 unsigned int capabilities; 65 const struct exynos_drm_ipp_formats *formats; 66 unsigned int num_formats; 67 atomic_t sequence; 68 69 spinlock_t lock; 70 struct exynos_drm_ipp_task *task; 71 struct list_head todo_list; 72 wait_queue_head_t done_wq; 73 }; 74 75 struct exynos_drm_ipp_buffer { 76 struct drm_exynos_ipp_task_buffer buf; 77 struct drm_exynos_ipp_task_rect rect; 78 79 struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; 80 const struct drm_format_info *format; 81 dma_addr_t dma_addr[MAX_FB_BUFFER]; 82 }; 83 84 /** 85 * struct exynos_drm_ipp_task - a structure describing transformation that 86 * has to be performed by the picture processor hardware module 87 */ 88 struct exynos_drm_ipp_task { 89 struct device *dev; 90 struct exynos_drm_ipp *ipp; 91 struct list_head head; 92 93 struct exynos_drm_ipp_buffer src; 94 struct exynos_drm_ipp_buffer dst; 95 96 struct drm_exynos_ipp_task_transform transform; 97 struct drm_exynos_ipp_task_alpha alpha; 98 99 struct work_struct cleanup_work; 100 unsigned int flags; 101 int ret; 102 103 struct drm_pending_exynos_ipp_event *event; 104 }; 105 106 #define DRM_EXYNOS_IPP_TASK_DONE (1 << 0) 107 #define DRM_EXYNOS_IPP_TASK_ASYNC (1 << 1) 108 109 struct exynos_drm_ipp_formats { 110 uint32_t fourcc; 111 uint32_t type; 112 uint64_t modifier; 113 const struct drm_exynos_ipp_limit *limits; 114 unsigned int num_limits; 115 }; 116 117 /* helper macros to set exynos_drm_ipp_formats structure and limits*/ 118 #define IPP_SRCDST_MFORMAT(f, m, l) \ 119 .fourcc = DRM_FORMAT_##f, .modifier = m, .limits = l, \ 120 .num_limits = ARRAY_SIZE(l), \ 121 .type = (DRM_EXYNOS_IPP_FORMAT_SOURCE | \ 122 DRM_EXYNOS_IPP_FORMAT_DESTINATION) 123 124 #define IPP_SRCDST_FORMAT(f, l) IPP_SRCDST_MFORMAT(f, 0, l) 125 126 #define IPP_SIZE_LIMIT(l, val...) \ 127 .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE | \ 128 DRM_EXYNOS_IPP_LIMIT_SIZE_##l), val 129 130 #define IPP_SCALE_LIMIT(val...) \ 131 .type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE), val 132 133 int exynos_drm_ipp_register(struct device *dev, struct exynos_drm_ipp *ipp, 134 const struct exynos_drm_ipp_funcs *funcs, unsigned int caps, 135 const struct exynos_drm_ipp_formats *formats, 136 unsigned int num_formats, const char *name); 137 void exynos_drm_ipp_unregister(struct device *dev, 138 struct exynos_drm_ipp *ipp); 139 140 void exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret); 141 142 #ifdef CONFIG_DRM_EXYNOS_IPP 143 int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data, 144 struct drm_file *file_priv); 145 int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data, 146 struct drm_file *file_priv); 147 int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data, 148 struct drm_file *file_priv); 149 int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, 150 void *data, struct drm_file *file_priv); 151 #else 152 static inline int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, 153 void *data, struct drm_file *file_priv) 154 { 155 struct drm_exynos_ioctl_ipp_get_res *resp = data; 156 157 resp->count_ipps = 0; 158 return 0; 159 } 160 static inline int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, 161 void *data, struct drm_file *file_priv) 162 { 163 return -ENODEV; 164 } 165 static inline int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, 166 void *data, struct drm_file *file_priv) 167 { 168 return -ENODEV; 169 } 170 static inline int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, 171 void *data, struct drm_file *file_priv) 172 { 173 return -ENODEV; 174 } 175 #endif 176 #endif 177