xref: /linux/drivers/gpu/drm/vkms/vkms_drv.h (revision 746680ec6696585e30db3e18c93a63df9cbec39c)
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