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 drm_rect rotated; 43 struct iosys_map map[DRM_FORMAT_MAX_PLANES]; 44 unsigned int rotation; 45 unsigned int offset; 46 unsigned int pitch; 47 unsigned int cpp; 48 }; 49 50 struct pixel_argb_u16 { 51 u16 a, r, g, b; 52 }; 53 54 struct line_buffer { 55 size_t n_pixels; 56 struct pixel_argb_u16 *pixels; 57 }; 58 59 struct vkms_writeback_job { 60 struct iosys_map data[DRM_FORMAT_MAX_PLANES]; 61 struct vkms_frame_info wb_frame_info; 62 void (*pixel_write)(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel); 63 }; 64 65 /** 66 * struct vkms_plane_state - Driver specific plane state 67 * @base: base plane state 68 * @frame_info: data required for composing computation 69 * @pixel_read: function to read a pixel in this plane. The creator of a struct vkms_plane_state 70 * must ensure that this pointer is valid 71 */ 72 struct vkms_plane_state { 73 struct drm_shadow_plane_state base; 74 struct vkms_frame_info *frame_info; 75 void (*pixel_read)(u8 *src_buffer, struct pixel_argb_u16 *out_pixel); 76 }; 77 78 struct vkms_plane { 79 struct drm_plane base; 80 }; 81 82 struct vkms_color_lut { 83 struct drm_color_lut *base; 84 size_t lut_length; 85 s64 channel_value2index_ratio; 86 }; 87 88 /** 89 * struct vkms_crtc_state - Driver specific CRTC state 90 * 91 * @base: base CRTC state 92 * @composer_work: work struct to compose and add CRC entries 93 * 94 * @num_active_planes: Number of active planes 95 * @active_planes: List containing all the active planes (counted by 96 * @num_active_planes). They should be stored in z-order. 97 * @active_writeback: Current active writeback job 98 * @gamma_lut: Look up table for gamma used in this CRTC 99 * @crc_pending: Protected by @vkms_output.composer_lock, true when the frame CRC is not computed 100 * yet. Used by vblank to detect if the composer is too slow. 101 * @wb_pending: Protected by @vkms_output.composer_lock, true when a writeback frame is requested. 102 * @frame_start: Protected by @vkms_output.composer_lock, saves the frame number before the start 103 * of the composition process. 104 * @frame_end: Protected by @vkms_output.composer_lock, saves the last requested frame number. 105 * This is used to generate enough CRC entries when the composition worker is too slow. 106 */ 107 struct vkms_crtc_state { 108 struct drm_crtc_state base; 109 struct work_struct composer_work; 110 111 int num_active_planes; 112 struct vkms_plane_state **active_planes; 113 struct vkms_writeback_job *active_writeback; 114 struct vkms_color_lut gamma_lut; 115 116 bool crc_pending; 117 bool wb_pending; 118 u64 frame_start; 119 u64 frame_end; 120 }; 121 122 /** 123 * struct vkms_output - Internal representation of all output components in VKMS 124 * 125 * @crtc: Base CRTC in DRM 126 * @encoder: DRM encoder used for this output 127 * @connector: DRM connector used for this output 128 * @wb_connecter: DRM writeback connector used for this output 129 * @vblank_hrtimer: Timer used to trigger the vblank 130 * @period_ns: vblank period, in nanoseconds, used to configure @vblank_hrtimer and to compute 131 * vblank timestamps 132 * @composer_workq: Ordered workqueue for @composer_state.composer_work. 133 * @lock: Lock used to protect concurrent access to the composer 134 * @composer_enabled: Protected by @lock, true when the VKMS composer is active (crc needed or 135 * writeback) 136 * @composer_state: Protected by @lock, current state of this VKMS output 137 * @composer_lock: Lock used internally to protect @composer_state members 138 */ 139 struct vkms_output { 140 struct drm_crtc crtc; 141 struct drm_encoder encoder; 142 struct drm_connector connector; 143 struct drm_writeback_connector wb_connector; 144 struct hrtimer vblank_hrtimer; 145 ktime_t period_ns; 146 struct workqueue_struct *composer_workq; 147 spinlock_t lock; 148 149 bool composer_enabled; 150 struct vkms_crtc_state *composer_state; 151 152 spinlock_t composer_lock; 153 }; 154 155 /** 156 * struct vkms_config - General configuration for VKMS driver 157 * 158 * @writeback: If true, a writeback buffer can be attached to the CRTC 159 * @cursor: If true, a cursor plane is created in the VKMS device 160 * @overlay: If true, NUM_OVERLAY_PLANES will be created for the VKMS device 161 * @dev: Used to store the current VKMS device. Only set when the device is instantiated. 162 */ 163 struct vkms_config { 164 bool writeback; 165 bool cursor; 166 bool overlay; 167 struct vkms_device *dev; 168 }; 169 170 /** 171 * struct vkms_device - Description of a VKMS device 172 * 173 * @drm - Base device in DRM 174 * @platform - Associated platform device 175 * @output - Configuration and sub-components of the VKMS device 176 * @config: Configuration used in this VKMS device 177 */ 178 struct vkms_device { 179 struct drm_device drm; 180 struct platform_device *platform; 181 struct vkms_output output; 182 const struct vkms_config *config; 183 }; 184 185 /* 186 * The following helpers are used to convert a member of a struct into its parent. 187 */ 188 189 #define drm_crtc_to_vkms_output(target) \ 190 container_of(target, struct vkms_output, crtc) 191 192 #define drm_device_to_vkms_device(target) \ 193 container_of(target, struct vkms_device, drm) 194 195 #define to_vkms_crtc_state(target)\ 196 container_of(target, struct vkms_crtc_state, base) 197 198 #define to_vkms_plane_state(target)\ 199 container_of(target, struct vkms_plane_state, base.base) 200 201 /** 202 * vkms_crtc_init() - Initialize a CRTC for VKMS 203 * @dev: DRM device associated with the VKMS buffer 204 * @crtc: uninitialized CRTC device 205 * @primary: primary plane to attach to the CRTC 206 * @cursor: plane to attach to the CRTC 207 */ 208 int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 209 struct drm_plane *primary, struct drm_plane *cursor); 210 211 /** 212 * vkms_output_init() - Initialize all sub-components needed for a VKMS device. 213 * 214 * @vkmsdev: VKMS device to initialize 215 * @index: CRTC which can be attached to the planes. The caller must ensure that 216 * @index is positive and less or equals to 31. 217 */ 218 int vkms_output_init(struct vkms_device *vkmsdev, int index); 219 220 /** 221 * vkms_plane_init() - Initialize a plane 222 * 223 * @vkmsdev: VKMS device containing the plane 224 * @type: type of plane to initialize 225 * @index: CRTC which can be attached to the plane. The caller must ensure that 226 * @index is positive and less or equals to 31. 227 */ 228 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, 229 enum drm_plane_type type, int index); 230 231 /* CRC Support */ 232 const char *const *vkms_get_crc_sources(struct drm_crtc *crtc, 233 size_t *count); 234 int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name); 235 int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, 236 size_t *values_cnt); 237 238 /* Composer Support */ 239 void vkms_composer_worker(struct work_struct *work); 240 void vkms_set_composer(struct vkms_output *out, bool enabled); 241 void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y); 242 void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y); 243 244 /* Writeback */ 245 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev); 246 247 #endif /* _VKMS_DRV_H_ */ 248