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