aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gud/gud_internal.h
blob: 2a388e27d5d7bf3589f114bf5fe3fec15fa2b7f0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* SPDX-License-Identifier: MIT */

#ifndef __LINUX_GUD_INTERNAL_H
#define __LINUX_GUD_INTERNAL_H

#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
#include <uapi/drm/drm_fourcc.h>

#include <drm/drm_modes.h>
#include <drm/drm_simple_kms_helper.h>

struct gud_device {
	struct drm_device drm;
	struct drm_simple_display_pipe pipe;
	struct device *dmadev;
	struct work_struct work;
	u32 flags;
	const struct drm_format_info *xrgb8888_emulation_format;

	u16 *properties;
	unsigned int num_properties;

	unsigned int bulk_pipe;
	void *bulk_buf;
	size_t bulk_len;
	struct sg_table bulk_sgt;

	u8 compression;
	void *lz4_comp_mem;
	void *compress_buf;

	u64 stats_length;
	u64 stats_actual_length;
	unsigned int stats_num_errors;

	struct mutex ctrl_lock; /* Serialize get/set and status transfers */

	struct mutex damage_lock; /* Protects the following members: */
	struct drm_framebuffer *fb;
	struct drm_rect damage;
	bool prev_flush_failed;
};

static inline struct gud_device *to_gud_device(struct drm_device *drm)
{
	return container_of(drm, struct gud_device, drm);
}

static inline struct usb_device *gud_to_usb_device(struct gud_device *gdrm)
{
	return interface_to_usbdev(to_usb_interface(gdrm->drm.dev));
}

int gud_usb_get(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len);
int gud_usb_set(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len);
int gud_usb_get_u8(struct gud_device *gdrm, u8 request, u16 index, u8 *val);
int gud_usb_set_u8(struct gud_device *gdrm, u8 request, u8 val);

void gud_clear_damage(struct gud_device *gdrm);
void gud_flush_work(struct work_struct *work);
int gud_pipe_check(struct drm_simple_display_pipe *pipe,
		   struct drm_plane_state *new_plane_state,
		   struct drm_crtc_state *new_crtc_state);
void gud_pipe_update(struct drm_simple_display_pipe *pipe,
		     struct drm_plane_state *old_state);
int gud_connector_fill_properties(struct drm_connector_state *connector_state,
				  struct gud_property_req *properties);
int gud_get_connectors(struct gud_device *gdrm);

/* Driver internal fourcc transfer formats */
#define GUD_DRM_FORMAT_R1		0x00000122
#define GUD_DRM_FORMAT_XRGB1111		0x03121722

static inline u8 gud_from_fourcc(u32 fourcc)
{
	switch (fourcc) {
	case GUD_DRM_FORMAT_R1:
		return GUD_PIXEL_FORMAT_R1;
	case GUD_DRM_FORMAT_XRGB1111:
		return GUD_PIXEL_FORMAT_XRGB1111;
	case DRM_FORMAT_RGB565:
		return GUD_PIXEL_FORMAT_RGB565;
	case DRM_FORMAT_XRGB8888:
		return GUD_PIXEL_FORMAT_XRGB8888;
	case DRM_FORMAT_ARGB8888:
		return GUD_PIXEL_FORMAT_ARGB8888;
	}

	return 0;
}

static inline u32 gud_to_fourcc(u8 format)
{
	switch (format) {
	case GUD_PIXEL_FORMAT_R1:
		return GUD_DRM_FORMAT_R1;
	case GUD_PIXEL_FORMAT_XRGB1111:
		return GUD_DRM_FORMAT_XRGB1111;
	case GUD_PIXEL_FORMAT_RGB565:
		return DRM_FORMAT_RGB565;
	case GUD_PIXEL_FORMAT_XRGB8888:
		return DRM_FORMAT_XRGB8888;
	case GUD_PIXEL_FORMAT_ARGB8888:
		return DRM_FORMAT_ARGB8888;
	}

	return 0;
}

static inline void gud_from_display_mode(struct gud_display_mode_req *dst,
					 const struct drm_display_mode *src)
{
	u32 flags = src->flags & GUD_DISPLAY_MODE_FLAG_USER_MASK;

	if (src->type & DRM_MODE_TYPE_PREFERRED)
		flags |= GUD_DISPLAY_MODE_FLAG_PREFERRED;

	dst->clock = cpu_to_le32(src->clock);
	dst->hdisplay = cpu_to_le16(src->hdisplay);
	dst->hsync_start = cpu_to_le16(src->hsync_start);
	dst->hsync_end = cpu_to_le16(src->hsync_end);
	dst->htotal = cpu_to_le16(src->htotal);
	dst->vdisplay = cpu_to_le16(src->vdisplay);
	dst->vsync_start = cpu_to_le16(src->vsync_start);
	dst->vsync_end = cpu_to_le16(src->vsync_end);
	dst->vtotal = cpu_to_le16(src->vtotal);
	dst->flags = cpu_to_le32(flags);
}

static inline void gud_to_display_mode(struct drm_display_mode *dst,
				       const struct gud_display_mode_req *src)
{
	u32 flags = le32_to_cpu(src->flags);

	memset(dst, 0, sizeof(*dst));
	dst->clock = le32_to_cpu(src->clock);
	dst->hdisplay = le16_to_cpu(src->hdisplay);
	dst->hsync_start = le16_to_cpu(src->hsync_start);
	dst->hsync_end = le16_to_cpu(src->hsync_end);
	dst->htotal = le16_to_cpu(src->htotal);
	dst->vdisplay = le16_to_cpu(src->vdisplay);
	dst->vsync_start = le16_to_cpu(src->vsync_start);
	dst->vsync_end = le16_to_cpu(src->vsync_end);
	dst->vtotal = le16_to_cpu(src->vtotal);
	dst->flags = flags & GUD_DISPLAY_MODE_FLAG_USER_MASK;
	dst->type = DRM_MODE_TYPE_DRIVER;
	if (flags & GUD_DISPLAY_MODE_FLAG_PREFERRED)
		dst->type |= DRM_MODE_TYPE_PREFERRED;
	drm_mode_set_name(dst);
}

#endif