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 /** 49 * struct pixel_argb_u16 - Internal representation of a pixel color. 50 * @a: Alpha component value, stored in 16 bits, without padding, using 51 * machine endianness 52 * @r: Red component value, stored in 16 bits, without padding, using 53 * machine endianness 54 * @g: Green component value, stored in 16 bits, without padding, using 55 * machine endianness 56 * @b: Blue component value, stored in 16 bits, without padding, using 57 * machine endianness 58 * 59 * The goal of this structure is to keep enough precision to ensure 60 * correct composition results in VKMS and simplifying color 61 * manipulation by splitting each component into its own field. 62 * Caution: the byte ordering of this structure is machine-dependent, 63 * you can't cast it directly to AR48 or xR48. 64 */ 65 struct pixel_argb_u16 { 66 u16 a, r, g, b; 67 }; 68 69 struct line_buffer { 70 size_t n_pixels; 71 struct pixel_argb_u16 *pixels; 72 }; 73 74 /** 75 * typedef pixel_write_t - These functions are used to read a pixel from a 76 * &struct pixel_argb_u16, convert it in a specific format and write it in the @out_pixel 77 * buffer. 78 * 79 * @out_pixel: destination address to write the pixel 80 * @in_pixel: pixel to write 81 */ 82 typedef void (*pixel_write_t)(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel); 83 84 struct vkms_writeback_job { 85 struct iosys_map data[DRM_FORMAT_MAX_PLANES]; 86 struct vkms_frame_info wb_frame_info; 87 pixel_write_t pixel_write; 88 }; 89 90 /** 91 * enum pixel_read_direction - Enum used internally by VKMS to represent a reading direction in a 92 * plane. 93 */ 94 enum pixel_read_direction { 95 READ_BOTTOM_TO_TOP, 96 READ_TOP_TO_BOTTOM, 97 READ_RIGHT_TO_LEFT, 98 READ_LEFT_TO_RIGHT 99 }; 100 101 struct vkms_plane_state; 102 103 /** 104 * typedef pixel_read_line_t - These functions are used to read a pixel line in the source frame, 105 * convert it to `struct pixel_argb_u16` and write it to @out_pixel. 106 * 107 * @plane: plane used as source for the pixel value 108 * @x_start: X (width) coordinate of the first pixel to copy. The caller must ensure that x_start 109 * is non-negative and smaller than @plane->frame_info->fb->width. 110 * @y_start: Y (height) coordinate of the first pixel to copy. The caller must ensure that y_start 111 * is non-negative and smaller than @plane->frame_info->fb->height. 112 * @direction: direction to use for the copy, starting at @x_start/@y_start 113 * @count: number of pixels to copy 114 * @out_pixel: pointer where to write the pixel values. They will be written from @out_pixel[0] 115 * (included) to @out_pixel[@count] (excluded). The caller must ensure that out_pixel have a 116 * length of at least @count. 117 */ 118 typedef void (*pixel_read_line_t)(const struct vkms_plane_state *plane, int x_start, 119 int y_start, enum pixel_read_direction direction, int count, 120 struct pixel_argb_u16 out_pixel[]); 121 122 /** 123 * struct conversion_matrix - Matrix to use for a specific encoding and range 124 * 125 * @matrix: Conversion matrix from yuv to rgb. The matrix is stored in a row-major manner and is 126 * used to compute rgb values from yuv values: 127 * [[r],[g],[b]] = @matrix * [[y],[u],[v]] 128 * OR for yvu formats: 129 * [[r],[g],[b]] = @matrix * [[y],[v],[u]] 130 * The values of the matrix are signed fixed-point values with 32 bits fractional part. 131 * @y_offset: Offset to apply on the y value. 132 */ 133 struct conversion_matrix { 134 s64 matrix[3][3]; 135 int y_offset; 136 }; 137 138 /** 139 * struct vkms_plane_state - Driver specific plane state 140 * @base: base plane state 141 * @frame_info: data required for composing computation 142 * @pixel_read_line: function to read a pixel line in this plane. The creator of a 143 * struct vkms_plane_state must ensure that this pointer is valid 144 * @conversion_matrix: matrix used for yuv formats to convert to rgb 145 */ 146 struct vkms_plane_state { 147 struct drm_shadow_plane_state base; 148 struct vkms_frame_info *frame_info; 149 pixel_read_line_t pixel_read_line; 150 struct conversion_matrix conversion_matrix; 151 }; 152 153 struct vkms_plane { 154 struct drm_plane base; 155 }; 156 157 struct vkms_color_lut { 158 struct drm_color_lut *base; 159 size_t lut_length; 160 s64 channel_value2index_ratio; 161 }; 162 163 /** 164 * struct vkms_crtc_state - Driver specific CRTC state 165 * 166 * @base: base CRTC state 167 * @composer_work: work struct to compose and add CRC entries 168 * 169 * @num_active_planes: Number of active planes 170 * @active_planes: List containing all the active planes (counted by 171 * @num_active_planes). They should be stored in z-order. 172 * @active_writeback: Current active writeback job 173 * @gamma_lut: Look up table for gamma used in this CRTC 174 * @crc_pending: Protected by @vkms_output.composer_lock, true when the frame CRC is not computed 175 * yet. Used by vblank to detect if the composer is too slow. 176 * @wb_pending: Protected by @vkms_output.composer_lock, true when a writeback frame is requested. 177 * @frame_start: Protected by @vkms_output.composer_lock, saves the frame number before the start 178 * of the composition process. 179 * @frame_end: Protected by @vkms_output.composer_lock, saves the last requested frame number. 180 * This is used to generate enough CRC entries when the composition worker is too slow. 181 */ 182 struct vkms_crtc_state { 183 struct drm_crtc_state base; 184 struct work_struct composer_work; 185 186 int num_active_planes; 187 struct vkms_plane_state **active_planes; 188 struct vkms_writeback_job *active_writeback; 189 struct vkms_color_lut gamma_lut; 190 191 bool crc_pending; 192 bool wb_pending; 193 u64 frame_start; 194 u64 frame_end; 195 }; 196 197 /** 198 * struct vkms_output - Internal representation of all output components in VKMS 199 * 200 * @crtc: Base CRTC in DRM 201 * @encoder: DRM encoder used for this output 202 * @connector: DRM connector used for this output 203 * @wb_connecter: DRM writeback connector used for this output 204 * @vblank_hrtimer: Timer used to trigger the vblank 205 * @period_ns: vblank period, in nanoseconds, used to configure @vblank_hrtimer and to compute 206 * vblank timestamps 207 * @composer_workq: Ordered workqueue for @composer_state.composer_work. 208 * @lock: Lock used to protect concurrent access to the composer 209 * @composer_enabled: Protected by @lock, true when the VKMS composer is active (crc needed or 210 * writeback) 211 * @composer_state: Protected by @lock, current state of this VKMS output 212 * @composer_lock: Lock used internally to protect @composer_state members 213 */ 214 struct vkms_output { 215 struct drm_crtc crtc; 216 struct drm_writeback_connector wb_connector; 217 struct drm_encoder wb_encoder; 218 struct hrtimer vblank_hrtimer; 219 ktime_t period_ns; 220 struct workqueue_struct *composer_workq; 221 spinlock_t lock; 222 223 bool composer_enabled; 224 struct vkms_crtc_state *composer_state; 225 226 spinlock_t composer_lock; 227 }; 228 229 struct vkms_config; 230 231 /** 232 * struct vkms_device - Description of a VKMS device 233 * 234 * @drm - Base device in DRM 235 * @faux_dev - Associated faux device 236 * @output - Configuration and sub-components of the VKMS device 237 * @config: Configuration used in this VKMS device 238 */ 239 struct vkms_device { 240 struct drm_device drm; 241 struct faux_device *faux_dev; 242 const struct vkms_config *config; 243 }; 244 245 /* 246 * The following helpers are used to convert a member of a struct into its parent. 247 */ 248 249 #define drm_crtc_to_vkms_output(target) \ 250 container_of(target, struct vkms_output, crtc) 251 252 #define drm_device_to_vkms_device(target) \ 253 container_of(target, struct vkms_device, drm) 254 255 #define to_vkms_crtc_state(target)\ 256 container_of(target, struct vkms_crtc_state, base) 257 258 #define to_vkms_plane_state(target)\ 259 container_of(target, struct vkms_plane_state, base.base) 260 261 /** 262 * vkms_crtc_init() - Initialize a CRTC for VKMS 263 * @dev: DRM device associated with the VKMS buffer 264 * @crtc: uninitialized CRTC device 265 * @primary: primary plane to attach to the CRTC 266 * @cursor: plane to attach to the CRTC 267 */ 268 struct vkms_output *vkms_crtc_init(struct drm_device *dev, 269 struct drm_plane *primary, 270 struct drm_plane *cursor); 271 272 /** 273 * vkms_output_init() - Initialize all sub-components needed for a VKMS device. 274 * 275 * @vkmsdev: VKMS device to initialize 276 */ 277 int vkms_output_init(struct vkms_device *vkmsdev); 278 279 /** 280 * vkms_plane_init() - Initialize a plane 281 * 282 * @vkmsdev: VKMS device containing the plane 283 * @type: type of plane to initialize 284 */ 285 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, 286 enum drm_plane_type type); 287 288 /* CRC Support */ 289 const char *const *vkms_get_crc_sources(struct drm_crtc *crtc, 290 size_t *count); 291 int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name); 292 int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, 293 size_t *values_cnt); 294 295 /* Composer Support */ 296 void vkms_composer_worker(struct work_struct *work); 297 void vkms_set_composer(struct vkms_output *out, bool enabled); 298 void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y); 299 300 /* Writeback */ 301 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_output *vkms_out); 302 303 #endif /* _VKMS_DRV_H_ */ 304