summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vkms/vkms_drv.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vkms/vkms_drv.h')
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.h335
1 files changed, 261 insertions, 74 deletions
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index e4469cd3d254..0933e4ce0ff0 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -1,14 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
#ifndef _VKMS_DRV_H_
#define _VKMS_DRV_H_
-#include <drm/drmP.h>
+#include <linux/hrtimer.h>
+
#include <drm/drm.h>
+#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_encoder.h>
-#include <linux/hrtimer.h>
+#include <drm/drm_writeback.h>
+
+#define DEFAULT_DEVICE_NAME "vkms"
-#define XRES_MIN 20
-#define YRES_MIN 20
+#define XRES_MIN 10
+#define YRES_MIN 10
#define XRES_DEF 1024
#define YRES_DEF 768
@@ -16,77 +23,231 @@
#define XRES_MAX 8192
#define YRES_MAX 8192
-extern bool enable_cursor;
+#define NUM_OVERLAY_PLANES 8
-static const u32 vkms_formats[] = {
- DRM_FORMAT_XRGB8888,
+#define VKMS_LUT_SIZE 256
+
+/**
+ * struct vkms_frame_info - Structure to store the state of a frame
+ *
+ * @fb: backing drm framebuffer
+ * @src: source rectangle of this frame in the source framebuffer, stored in 16.16 fixed-point form
+ * @dst: destination rectangle in the crtc buffer, stored in whole pixel units
+ * @map: see @drm_shadow_plane_state.data
+ * @rotation: rotation applied to the source.
+ *
+ * @src and @dst should have the same size modulo the rotation.
+ */
+struct vkms_frame_info {
+ struct drm_framebuffer *fb;
+ struct drm_rect src, dst;
+ struct iosys_map map[DRM_FORMAT_MAX_PLANES];
+ unsigned int rotation;
};
-static const u32 vkms_cursor_formats[] = {
- DRM_FORMAT_ARGB8888,
+struct pixel_argb_s32 {
+ s32 a, r, g, b;
};
-struct vkms_crc_data {
- struct drm_framebuffer fb;
- struct drm_rect src, dst;
- unsigned int offset;
- unsigned int pitch;
- unsigned int cpp;
+/**
+ * struct pixel_argb_u16 - Internal representation of a pixel color.
+ * @a: Alpha component value, stored in 16 bits, without padding, using
+ * machine endianness
+ * @r: Red component value, stored in 16 bits, without padding, using
+ * machine endianness
+ * @g: Green component value, stored in 16 bits, without padding, using
+ * machine endianness
+ * @b: Blue component value, stored in 16 bits, without padding, using
+ * machine endianness
+ *
+ * The goal of this structure is to keep enough precision to ensure
+ * correct composition results in VKMS and simplifying color
+ * manipulation by splitting each component into its own field.
+ * Caution: the byte ordering of this structure is machine-dependent,
+ * you can't cast it directly to AR48 or xR48.
+ */
+struct pixel_argb_u16 {
+ u16 a, r, g, b;
+};
+
+struct line_buffer {
+ size_t n_pixels;
+ struct pixel_argb_u16 *pixels;
+};
+
+/**
+ * typedef pixel_write_t - These functions are used to read a pixel from a
+ * &struct pixel_argb_u16, convert it in a specific format and write it in the @out_pixel
+ * buffer.
+ *
+ * @out_pixel: destination address to write the pixel
+ * @in_pixel: pixel to write
+ */
+typedef void (*pixel_write_t)(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel);
+
+struct vkms_writeback_job {
+ struct iosys_map data[DRM_FORMAT_MAX_PLANES];
+ struct vkms_frame_info wb_frame_info;
+ pixel_write_t pixel_write;
};
/**
- * vkms_plane_state - Driver specific plane state
+ * enum pixel_read_direction - Enum used internally by VKMS to represent a reading direction in a
+ * plane.
+ */
+enum pixel_read_direction {
+ READ_BOTTOM_TO_TOP,
+ READ_TOP_TO_BOTTOM,
+ READ_RIGHT_TO_LEFT,
+ READ_LEFT_TO_RIGHT
+};
+
+struct vkms_plane_state;
+
+/**
+ * typedef pixel_read_line_t - These functions are used to read a pixel line in the source frame,
+ * convert it to `struct pixel_argb_u16` and write it to @out_pixel.
+ *
+ * @plane: plane used as source for the pixel value
+ * @x_start: X (width) coordinate of the first pixel to copy. The caller must ensure that x_start
+ * is non-negative and smaller than @plane->frame_info->fb->width.
+ * @y_start: Y (height) coordinate of the first pixel to copy. The caller must ensure that y_start
+ * is non-negative and smaller than @plane->frame_info->fb->height.
+ * @direction: direction to use for the copy, starting at @x_start/@y_start
+ * @count: number of pixels to copy
+ * @out_pixel: pointer where to write the pixel values. They will be written from @out_pixel[0]
+ * (included) to @out_pixel[@count] (excluded). The caller must ensure that out_pixel have a
+ * length of at least @count.
+ */
+typedef void (*pixel_read_line_t)(const struct vkms_plane_state *plane, int x_start,
+ int y_start, enum pixel_read_direction direction, int count,
+ struct pixel_argb_u16 out_pixel[]);
+
+/**
+ * struct conversion_matrix - Matrix to use for a specific encoding and range
+ *
+ * @matrix: Conversion matrix from yuv to rgb. The matrix is stored in a row-major manner and is
+ * used to compute rgb values from yuv values:
+ * [[r],[g],[b]] = @matrix * [[y],[u],[v]]
+ * OR for yvu formats:
+ * [[r],[g],[b]] = @matrix * [[y],[v],[u]]
+ * The values of the matrix are signed fixed-point values with 32 bits fractional part.
+ * @y_offset: Offset to apply on the y value.
+ */
+struct conversion_matrix {
+ s64 matrix[3][3];
+ int y_offset;
+};
+
+/**
+ * struct vkms_plane_state - Driver specific plane state
* @base: base plane state
- * @crc_data: data required for CRC computation
+ * @frame_info: data required for composing computation
+ * @pixel_read_line: function to read a pixel line in this plane. The creator of a
+ * struct vkms_plane_state must ensure that this pointer is valid
+ * @conversion_matrix: matrix used for yuv formats to convert to rgb
*/
struct vkms_plane_state {
- struct drm_plane_state base;
- struct vkms_crc_data *crc_data;
+ struct drm_shadow_plane_state base;
+ struct vkms_frame_info *frame_info;
+ pixel_read_line_t pixel_read_line;
+ struct conversion_matrix conversion_matrix;
+};
+
+struct vkms_plane {
+ struct drm_plane base;
+};
+
+struct vkms_color_lut {
+ struct drm_color_lut *base;
+ size_t lut_length;
+ s64 channel_value2index_ratio;
};
/**
- * vkms_crtc_state - Driver specific CRTC state
+ * struct vkms_crtc_state - Driver specific CRTC state
+ *
* @base: base CRTC state
- * @crc_work: work struct to compute and add CRC entries
- * @n_frame_start: start frame number for computed CRC
- * @n_frame_end: end frame number for computed CRC
+ * @composer_work: work struct to compose and add CRC entries
+ *
+ * @num_active_planes: Number of active planes
+ * @active_planes: List containing all the active planes (counted by
+ * @num_active_planes). They should be stored in z-order.
+ * @active_writeback: Current active writeback job
+ * @gamma_lut: Look up table for gamma used in this CRTC
+ * @crc_pending: Protected by @vkms_output.composer_lock, true when the frame CRC is not computed
+ * yet. Used by vblank to detect if the composer is too slow.
+ * @wb_pending: Protected by @vkms_output.composer_lock, true when a writeback frame is requested.
+ * @frame_start: Protected by @vkms_output.composer_lock, saves the frame number before the start
+ * of the composition process.
+ * @frame_end: Protected by @vkms_output.composer_lock, saves the last requested frame number.
+ * This is used to generate enough CRC entries when the composition worker is too slow.
*/
struct vkms_crtc_state {
struct drm_crtc_state base;
- struct work_struct crc_work;
+ struct work_struct composer_work;
+
+ int num_active_planes;
+ struct vkms_plane_state **active_planes;
+ struct vkms_writeback_job *active_writeback;
+ struct vkms_color_lut gamma_lut;
+
+ bool crc_pending;
+ bool wb_pending;
u64 frame_start;
u64 frame_end;
};
+/**
+ * struct vkms_output - Internal representation of all output components in VKMS
+ *
+ * @crtc: Base CRTC in DRM
+ * @encoder: DRM encoder used for this output
+ * @connector: DRM connector used for this output
+ * @wb_connecter: DRM writeback connector used for this output
+ * @vblank_hrtimer: Timer used to trigger the vblank
+ * @period_ns: vblank period, in nanoseconds, used to configure @vblank_hrtimer and to compute
+ * vblank timestamps
+ * @composer_workq: Ordered workqueue for @composer_state.composer_work.
+ * @lock: Lock used to protect concurrent access to the composer
+ * @composer_enabled: Protected by @lock, true when the VKMS composer is active (crc needed or
+ * writeback)
+ * @composer_state: Protected by @lock, current state of this VKMS output
+ * @composer_lock: Lock used internally to protect @composer_state members
+ */
struct vkms_output {
struct drm_crtc crtc;
- struct drm_encoder encoder;
- struct drm_connector connector;
- struct hrtimer vblank_hrtimer;
- ktime_t period_ns;
- struct drm_pending_vblank_event *event;
- bool crc_enabled;
- /* ordered wq for crc_work */
- struct workqueue_struct *crc_workq;
- /* protects concurrent access to crc_data */
+ struct drm_writeback_connector wb_connector;
+ struct drm_encoder wb_encoder;
+ struct workqueue_struct *composer_workq;
spinlock_t lock;
- /* protects concurrent access to crtc_state */
- spinlock_t state_lock;
+
+ bool composer_enabled;
+ struct vkms_crtc_state *composer_state;
+
+ spinlock_t composer_lock;
};
+struct vkms_config;
+struct vkms_config_plane;
+
+/**
+ * struct vkms_device - Description of a VKMS device
+ *
+ * @drm - Base device in DRM
+ * @faux_dev - Associated faux device
+ * @output - Configuration and sub-components of the VKMS device
+ * @config: Configuration used in this VKMS device
+ */
struct vkms_device {
struct drm_device drm;
- struct platform_device *platform;
- struct vkms_output output;
+ struct faux_device *faux_dev;
+ const struct vkms_config *config;
};
-struct vkms_gem_object {
- struct drm_gem_object gem;
- struct mutex pages_lock; /* Page lock used in page fault handler */
- struct page **pages;
- unsigned int vmap_count;
- void *vaddr;
-};
+/*
+ * The following helpers are used to convert a member of a struct into its parent.
+ */
#define drm_crtc_to_vkms_output(target) \
container_of(target, struct vkms_output, crtc)
@@ -94,49 +255,75 @@ struct vkms_gem_object {
#define drm_device_to_vkms_device(target) \
container_of(target, struct vkms_device, drm)
-#define drm_gem_to_vkms_gem(target)\
- container_of(target, struct vkms_gem_object, gem)
-
#define to_vkms_crtc_state(target)\
container_of(target, struct vkms_crtc_state, base)
#define to_vkms_plane_state(target)\
- container_of(target, struct vkms_plane_state, base)
-
-/* CRTC */
-int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
- struct drm_plane *primary, struct drm_plane *cursor);
-
-bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
- int *max_error, ktime_t *vblank_time,
- bool in_vblank_irq);
-
-int vkms_output_init(struct vkms_device *vkmsdev);
+ container_of(target, struct vkms_plane_state, base.base)
-struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
- enum drm_plane_type type);
-
-/* Gem stuff */
-struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
- struct drm_file *file,
- u32 *handle,
- u64 size);
-
-vm_fault_t vkms_gem_fault(struct vm_fault *vmf);
+/**
+ * vkms_create() - Create a device from a configuration
+ * @config: Config used to configure the new device
+ *
+ * A pointer to the created vkms_device is stored in @config
+ *
+ * Returns:
+ * 0 on success or an error.
+ */
+int vkms_create(struct vkms_config *config);
-int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
- struct drm_mode_create_dumb *args);
+/**
+ * vkms_destroy() - Destroy a device
+ * @config: Config from which the device was created
+ *
+ * The device is completely removed, but the @config is not freed. It can be
+ * reused or destroyed with vkms_config_destroy().
+ */
+void vkms_destroy(struct vkms_config *config);
-void vkms_gem_free_object(struct drm_gem_object *obj);
+/**
+ * vkms_crtc_init() - Initialize a CRTC for VKMS
+ * @dev: DRM device associated with the VKMS buffer
+ * @crtc: uninitialized CRTC device
+ * @primary: primary plane to attach to the CRTC
+ * @cursor: plane to attach to the CRTC
+ */
+struct vkms_output *vkms_crtc_init(struct drm_device *dev,
+ struct drm_plane *primary,
+ struct drm_plane *cursor);
-int vkms_gem_vmap(struct drm_gem_object *obj);
+/**
+ * vkms_output_init() - Initialize all sub-components needed for a VKMS device.
+ *
+ * @vkmsdev: VKMS device to initialize
+ */
+int vkms_output_init(struct vkms_device *vkmsdev);
-void vkms_gem_vunmap(struct drm_gem_object *obj);
+/**
+ * vkms_plane_init() - Initialize a plane
+ *
+ * @vkmsdev: VKMS device containing the plane
+ * @plane_cfg: plane configuration
+ */
+struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
+ struct vkms_config_plane *plane_cfg);
/* CRC Support */
+const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
+ size_t *count);
int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name);
int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
size_t *values_cnt);
-void vkms_crc_work_handle(struct work_struct *work);
+
+/* Composer Support */
+void vkms_composer_worker(struct work_struct *work);
+void vkms_set_composer(struct vkms_output *out, bool enabled);
+void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y);
+
+/* Writeback */
+int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_output *vkms_out);
+
+/* Colorops */
+int vkms_initialize_colorops(struct drm_plane *plane);
#endif /* _VKMS_DRV_H_ */