forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/gpu/drm/bochs/bochs_hw.c
....@@ -1,9 +1,11 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
2
- * This program is free software; you can redistribute it and/or modify
3
- * it under the terms of the GNU General Public License as published by
4
- * the Free Software Foundation; either version 2 of the License, or
5
- * (at your option) any later version.
63 */
4
+
5
+#include <linux/pci.h>
6
+
7
+#include <drm/drm_drv.h>
8
+#include <drm/drm_fourcc.h>
79
810 #include "bochs.h"
911
....@@ -47,11 +49,69 @@
4749 }
4850 }
4951
50
-int bochs_hw_init(struct drm_device *dev, uint32_t flags)
52
+static void bochs_hw_set_big_endian(struct bochs_device *bochs)
53
+{
54
+ if (bochs->qext_size < 8)
55
+ return;
56
+
57
+ writel(0xbebebebe, bochs->mmio + 0x604);
58
+}
59
+
60
+static void bochs_hw_set_little_endian(struct bochs_device *bochs)
61
+{
62
+ if (bochs->qext_size < 8)
63
+ return;
64
+
65
+ writel(0x1e1e1e1e, bochs->mmio + 0x604);
66
+}
67
+
68
+#ifdef __BIG_ENDIAN
69
+#define bochs_hw_set_native_endian(_b) bochs_hw_set_big_endian(_b)
70
+#else
71
+#define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b)
72
+#endif
73
+
74
+static int bochs_get_edid_block(void *data, u8 *buf,
75
+ unsigned int block, size_t len)
76
+{
77
+ struct bochs_device *bochs = data;
78
+ size_t i, start = block * EDID_LENGTH;
79
+
80
+ if (start + len > 0x400 /* vga register offset */)
81
+ return -1;
82
+
83
+ for (i = 0; i < len; i++) {
84
+ buf[i] = readb(bochs->mmio + start + i);
85
+ }
86
+ return 0;
87
+}
88
+
89
+int bochs_hw_load_edid(struct bochs_device *bochs)
90
+{
91
+ u8 header[8];
92
+
93
+ if (!bochs->mmio)
94
+ return -1;
95
+
96
+ /* check header to detect whenever edid support is enabled in qemu */
97
+ bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header));
98
+ if (drm_edid_header_is_valid(header) != 8)
99
+ return -1;
100
+
101
+ kfree(bochs->edid);
102
+ bochs->edid = drm_do_get_edid(&bochs->connector,
103
+ bochs_get_edid_block, bochs);
104
+ if (bochs->edid == NULL)
105
+ return -1;
106
+
107
+ return 0;
108
+}
109
+
110
+int bochs_hw_init(struct drm_device *dev)
51111 {
52112 struct bochs_device *bochs = dev->dev_private;
53113 struct pci_dev *pdev = dev->pdev;
54
- unsigned long addr, size, mem, ioaddr, iosize, qext_size;
114
+ unsigned long addr, size, mem, ioaddr, iosize;
55115 u16 id;
56116
57117 if (pdev->resource[2].flags & IORESOURCE_MEM) {
....@@ -115,19 +175,14 @@
115175 ioaddr);
116176
117177 if (bochs->mmio && pdev->revision >= 2) {
118
- qext_size = readl(bochs->mmio + 0x600);
119
- if (qext_size < 4 || qext_size > iosize)
178
+ bochs->qext_size = readl(bochs->mmio + 0x600);
179
+ if (bochs->qext_size < 4 || bochs->qext_size > iosize) {
180
+ bochs->qext_size = 0;
120181 goto noext;
121
- DRM_DEBUG("Found qemu ext regs, size %ld\n", qext_size);
122
- if (qext_size >= 8) {
123
-#ifdef __BIG_ENDIAN
124
- writel(0xbebebebe, bochs->mmio + 0x604);
125
-#else
126
- writel(0x1e1e1e1e, bochs->mmio + 0x604);
127
-#endif
128
- DRM_DEBUG(" qext endian: 0x%x\n",
129
- readl(bochs->mmio + 0x604));
130182 }
183
+ DRM_DEBUG("Found qemu ext regs, size %ld\n",
184
+ bochs->qext_size);
185
+ bochs_hw_set_native_endian(bochs);
131186 }
132187
133188 noext:
....@@ -138,6 +193,8 @@
138193 {
139194 struct bochs_device *bochs = dev->dev_private;
140195
196
+ /* TODO: shot down existing vram mappings */
197
+
141198 if (bochs->mmio)
142199 iounmap(bochs->mmio);
143200 if (bochs->ioports)
....@@ -145,11 +202,17 @@
145202 if (bochs->fb_map)
146203 iounmap(bochs->fb_map);
147204 pci_release_regions(dev->pdev);
205
+ kfree(bochs->edid);
148206 }
149207
150208 void bochs_hw_setmode(struct bochs_device *bochs,
151209 struct drm_display_mode *mode)
152210 {
211
+ int idx;
212
+
213
+ if (!drm_dev_enter(bochs->dev, &idx))
214
+ return;
215
+
153216 bochs->xres = mode->hdisplay;
154217 bochs->yres = mode->vdisplay;
155218 bochs->bpp = 32;
....@@ -175,19 +238,63 @@
175238
176239 bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
177240 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
241
+
242
+ drm_dev_exit(idx);
243
+}
244
+
245
+void bochs_hw_setformat(struct bochs_device *bochs,
246
+ const struct drm_format_info *format)
247
+{
248
+ int idx;
249
+
250
+ if (!drm_dev_enter(bochs->dev, &idx))
251
+ return;
252
+
253
+ DRM_DEBUG_DRIVER("format %c%c%c%c\n",
254
+ (format->format >> 0) & 0xff,
255
+ (format->format >> 8) & 0xff,
256
+ (format->format >> 16) & 0xff,
257
+ (format->format >> 24) & 0xff);
258
+
259
+ switch (format->format) {
260
+ case DRM_FORMAT_XRGB8888:
261
+ bochs_hw_set_little_endian(bochs);
262
+ break;
263
+ case DRM_FORMAT_BGRX8888:
264
+ bochs_hw_set_big_endian(bochs);
265
+ break;
266
+ default:
267
+ /* should not happen */
268
+ DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
269
+ __func__, format->format);
270
+ break;
271
+ }
272
+
273
+ drm_dev_exit(idx);
178274 }
179275
180276 void bochs_hw_setbase(struct bochs_device *bochs,
181
- int x, int y, u64 addr)
277
+ int x, int y, int stride, u64 addr)
182278 {
183
- unsigned long offset = (unsigned long)addr +
279
+ unsigned long offset;
280
+ unsigned int vx, vy, vwidth, idx;
281
+
282
+ if (!drm_dev_enter(bochs->dev, &idx))
283
+ return;
284
+
285
+ bochs->stride = stride;
286
+ offset = (unsigned long)addr +
184287 y * bochs->stride +
185288 x * (bochs->bpp / 8);
186
- int vy = offset / bochs->stride;
187
- int vx = (offset % bochs->stride) * 8 / bochs->bpp;
289
+ vy = offset / bochs->stride;
290
+ vx = (offset % bochs->stride) * 8 / bochs->bpp;
291
+ vwidth = stride * 8 / bochs->bpp;
188292
189293 DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n",
190294 x, y, addr, offset, vx, vy);
295
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, vwidth);
191296 bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx);
192297 bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy);
298
+
299
+ drm_dev_exit(idx);
193300 }