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