1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 3 #ifndef _VKMS_DRV_H_ 4 #define _VKMS_DRV_H_ 5 6 #include <linux/hrtimer.h> 7 8 #include <drm/drm.h> 9 #include <drm/drm_framebuffer.h> 10 #include <drm/drm_gem.h> 11 #include <drm/drm_gem_atomic_helper.h> 12 #include <drm/drm_encoder.h> 13 #include <drm/drm_writeback.h> 14 15 #define DEFAULT_DEVICE_NAME "vkms" 16 17 #define XRES_MIN 10 18 #define YRES_MIN 10 19 20 #define XRES_DEF 1024 21 #define YRES_DEF 768 22 23 #define XRES_MAX 8192 24 #define YRES_MAX 8192 25 26 #define NUM_OVERLAY_PLANES 8 27 28 #define VKMS_LUT_SIZE 256 29 30 /** 31 * struct vkms_frame_info - Structure to store the state of a frame 32 * 33 * @fb: backing drm framebuffer 34 * @src: source rectangle of this frame in the source framebuffer, stored in 16.16 fixed-point form 35 * @dst: destination rectangle in the crtc buffer, stored in whole pixel units 36 * @map: see @drm_shadow_plane_state.data 37 * @rotation: rotation applied to the source. 38 * 39 * @src and @dst should have the same size modulo the rotation. 40 */ 41 struct vkms_frame_info { 42 struct drm_framebuffer *fb; 43 struct drm_rect src, dst; 44 struct iosys_map map[DRM_FORMAT_MAX_PLANES]; 45 unsigned int rotation; 46 }; 47 48 struct pixel_argb_u16 { 49 u16 a, r, g, b; 50 }; 51 52 struct line_buffer { 53 size_t n_pixels; 54 struct pixel_argb_u16 *pixels; 55 }; 56 57 /** 58 * typedef pixel_write_t - These functions are used to read a pixel from a 59 * &struct pixel_argb_u16, convert it in a specific format and write it in the @out_pixel 60 * buffer. 61 * 62 * @out_pixel: destination address to write the pixel 63 * @in_pixel: pixel to write 64 */ 65 typedef void (*pixel_write_t)(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel); 66 67 struct vkms_writeback_job { 68 struct iosys_map data[DRM_FORMAT_MAX_PLANES]; 69 struct vkms_frame_info wb_frame_info; 70 pixel_write_t pixel_write; 71 }; 72 73 /** 74 * enum pixel_read_direction - Enum used internally by VKMS to represent a reading direction in a 75 * plane. 76 */ 77 enum pixel_read_direction { 78 READ_BOTTOM_TO_TOP, 79 READ_TOP_TO_BOTTOM, 80 READ_RIGHT_TO_LEFT, 81 READ_LEFT_TO_RIGHT 82 }; 83 84 struct vkms_plane_state; 85 86 /** 87 * typedef pixel_read_line_t - These functions are used to read a pixel line in the source frame, 88 * convert it to `struct pixel_argb_u16` and write it to @out_pixel. 89 * 90 * @plane: plane used as source for the pixel value 91 * @x_start: X (width) coordinate of the first pixel to copy. The caller must ensure that x_start 92 * is non-negative and smaller than @plane->frame_info->fb->width. 93 * @y_start: Y (height) coordinate of the first pixel to copy. The caller must ensure that y_start 94 * is non-negative and smaller than @plane->frame_info->fb->height. 95 * @direction: direction to use for the copy, starting at @x_start/@y_start 96 * @count: number of pixels to copy 97 * @out_pixel: pointer where to write the pixel values. They will be written from @out_pixel[0] 98 * (included) to @out_pixel[@count] (excluded). The caller must ensure that out_pixel have a 99 * length of at least @count. 100 */ 101 typedef void (*pixel_read_line_t)(const struct vkms_plane_state *plane, int x_start, 102 int y_start, enum pixel_read_direction direction, int count, 103 struct pixel_argb_u16 out_pixel[]); 104 105 /** 106 * struct vkms_plane_state - Driver specific plane state 107 * @base: base plane state 108 * @frame_info: data required for composing computation 109 * @pixel_read_line: function to read a pixel line in this plane. The creator of a 110 * struct vkms_plane_state must ensure that this pointer is valid 111 */ 112 struct vkms_plane_state { 113 struct drm_shadow_plane_state base; 114 struct vkms_frame_info *frame_info; 115 pixel_read_line_t pixel_read_line; 116 }; 117 118 struct vkms_plane { 119 struct drm_plane base; 120 }; 121 122 struct vkms_color_lut { 123 struct drm_color_lut *base; 124 size_t lut_length; 125 s64 channel_value2index_ratio; 126 }; 127 128 /** 129 * struct vkms_crtc_state - Driver specific CRTC state 130 * 131 * @base: base CRTC state 132 * @composer_work: work struct to compose and add CRC entries 133 * 134 * @num_active_planes: Number of active planes 135 * @active_planes: List containing all the active planes (counted by 136 * @num_active_planes). They should be stored in z-order. 137 * @active_writeback: Current active writeback job 138 * @gamma_lut: Look up table for gamma used in this CRTC 139 * @crc_pending: Protected by @vkms_output.composer_lock, true when the frame CRC is not computed 140 * yet. Used by vblank to detect if the composer is too slow. 141 * @wb_pending: Protected by @vkms_output.composer_lock, true when a writeback frame is requested. 142 * @frame_start: Protected by @vkms_output.composer_lock, saves the frame number before the start 143 * of the composition process. 144 * @frame_end: Protected by @vkms_output.composer_lock, saves the last requested frame number. 145 * This is used to generate enough CRC entries when the composition worker is too slow. 146 */ 147 struct vkms_crtc_state { 148 struct drm_crtc_state base; 149 struct work_struct composer_work; 150 151 int num_active_planes; 152 struct vkms_plane_state **active_planes; 153 struct vkms_writeback_job *active_writeback; 154 struct vkms_color_lut gamma_lut; 155 156 bool crc_pending; 157 bool wb_pending; 158 u64 frame_start; 159 u64 frame_end; 160 }; 161 162 /** 163 * struct vkms_output - Internal representation of all output components in VKMS 164 * 165 * @crtc: Base CRTC in DRM 166 * @encoder: DRM encoder used for this output 167 * @connector: DRM connector used for this output 168 * @wb_connecter: DRM writeback connector used for this output 169 * @vblank_hrtimer: Timer used to trigger the vblank 170 * @period_ns: vblank period, in nanoseconds, used to configure @vblank_hrtimer and to compute 171 * vblank timestamps 172 * @composer_workq: Ordered workqueue for @composer_state.composer_work. 173 * @lock: Lock used to protect concurrent access to the composer 174 * @composer_enabled: Protected by @lock, true when the VKMS composer is active (crc needed or 175 * writeback) 176 * @composer_state: Protected by @lock, current state of this VKMS output 177 * @composer_lock: Lock used internally to protect @composer_state members 178 */ 179 struct vkms_output { 180 struct drm_crtc crtc; 181 struct drm_writeback_connector wb_connector; 182 struct drm_encoder wb_encoder; 183 struct hrtimer vblank_hrtimer; 184 ktime_t period_ns; 185 struct workqueue_struct *composer_workq; 186 spinlock_t lock; 187 188 bool composer_enabled; 189 struct vkms_crtc_state *composer_state; 190 191 spinlock_t composer_lock; 192 }; 193 194 struct vkms_config; 195 196 /** 197 * struct vkms_device - Description of a VKMS device 198 * 199 * @drm - Base device in DRM 200 * @platform - Associated platform device 201 * @output - Configuration and sub-components of the VKMS device 202 * @config: Configuration used in this VKMS device 203 */ 204 struct vkms_device { 205 struct drm_device drm; 206 struct platform_device *platform; 207 const struct vkms_config *config; 208 }; 209 210 /* 211 * The following helpers are used to convert a member of a struct into its parent. 212 */ 213 214 #define drm_crtc_to_vkms_output(target) \ 215 container_of(target, struct vkms_output, crtc) 216 217 #define drm_device_to_vkms_device(target) \ 218 container_of(target, struct vkms_device, drm) 219 220 #define to_vkms_crtc_state(target)\ 221 container_of(target, struct vkms_crtc_state, base) 222 223 #define to_vkms_plane_state(target)\ 224 container_of(target, struct vkms_plane_state, base.base) 225 226 /** 227 * vkms_crtc_init() - Initialize a CRTC for VKMS 228 * @dev: DRM device associated with the VKMS buffer 229 * @crtc: uninitialized CRTC device 230 * @primary: primary plane to attach to the CRTC 231 * @cursor: plane to attach to the CRTC 232 */ 233 struct vkms_output *vkms_crtc_init(struct drm_device *dev, 234 struct drm_plane *primary, 235 struct drm_plane *cursor); 236 237 /** 238 * vkms_output_init() - Initialize all sub-components needed for a VKMS device. 239 * 240 * @vkmsdev: VKMS device to initialize 241 */ 242 int vkms_output_init(struct vkms_device *vkmsdev); 243 244 /** 245 * vkms_plane_init() - Initialize a plane 246 * 247 * @vkmsdev: VKMS device containing the plane 248 * @type: type of plane to initialize 249 */ 250 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, 251 enum drm_plane_type type); 252 253 /* CRC Support */ 254 const char *const *vkms_get_crc_sources(struct drm_crtc *crtc, 255 size_t *count); 256 int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name); 257 int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, 258 size_t *values_cnt); 259 260 /* Composer Support */ 261 void vkms_composer_worker(struct work_struct *work); 262 void vkms_set_composer(struct vkms_output *out, bool enabled); 263 void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y); 264 265 /* Writeback */ 266 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_output *vkms_out); 267 268 #endif /* _VKMS_DRV_H_ */ 269