dma-buf-map: Rename to iosys-map
[linux-block.git] / drivers / gpu / drm / tiny / gm12u320.c
CommitLineData
e4f86e43
HG
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2019 Hans de Goede <hdegoede@redhat.com>
4 */
5
e4f86e43
HG
6#include <linux/module.h>
7#include <linux/usb.h>
8
9#include <drm/drm_atomic_helper.h>
10#include <drm/drm_atomic_state_helper.h>
11#include <drm/drm_connector.h>
12#include <drm/drm_damage_helper.h>
13#include <drm/drm_drv.h>
14#include <drm/drm_fb_helper.h>
15#include <drm/drm_file.h>
16#include <drm/drm_format_helper.h>
17#include <drm/drm_fourcc.h>
4ac0868d 18#include <drm/drm_gem_atomic_helper.h>
e4f86e43 19#include <drm/drm_gem_framebuffer_helper.h>
4ac0868d 20#include <drm/drm_gem_shmem_helper.h>
e4f86e43 21#include <drm/drm_ioctl.h>
b6731025 22#include <drm/drm_managed.h>
e4f86e43
HG
23#include <drm/drm_modeset_helper_vtables.h>
24#include <drm/drm_probe_helper.h>
25#include <drm/drm_simple_kms_helper.h>
e4f86e43
HG
26
27static bool eco_mode;
28module_param(eco_mode, bool, 0644);
29MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
30
31#define DRIVER_NAME "gm12u320"
32#define DRIVER_DESC "Grain Media GM12U320 USB projector display"
33#define DRIVER_DATE "2019"
34#define DRIVER_MAJOR 1
35#define DRIVER_MINOR 0
e4f86e43
HG
36
37/*
38 * The DLP has an actual width of 854 pixels, but that is not a multiple
39 * of 8, breaking things left and right, so we export a width of 848.
40 */
41#define GM12U320_USER_WIDTH 848
42#define GM12U320_REAL_WIDTH 854
43#define GM12U320_HEIGHT 480
44
45#define GM12U320_BLOCK_COUNT 20
46
4abfa2e4 47#define GM12U320_ERR(fmt, ...) \
0454bc59 48 DRM_DEV_ERROR(gm12u320->dev.dev, fmt, ##__VA_ARGS__)
4abfa2e4 49
e4f86e43
HG
50#define MISC_RCV_EPT 1
51#define DATA_RCV_EPT 2
52#define DATA_SND_EPT 3
53#define MISC_SND_EPT 4
54
55#define DATA_BLOCK_HEADER_SIZE 84
56#define DATA_BLOCK_CONTENT_SIZE 64512
57#define DATA_BLOCK_FOOTER_SIZE 20
58#define DATA_BLOCK_SIZE (DATA_BLOCK_HEADER_SIZE + \
59 DATA_BLOCK_CONTENT_SIZE + \
60 DATA_BLOCK_FOOTER_SIZE)
61#define DATA_LAST_BLOCK_CONTENT_SIZE 4032
62#define DATA_LAST_BLOCK_SIZE (DATA_BLOCK_HEADER_SIZE + \
63 DATA_LAST_BLOCK_CONTENT_SIZE + \
64 DATA_BLOCK_FOOTER_SIZE)
65
66#define CMD_SIZE 31
67#define READ_STATUS_SIZE 13
68#define MISC_VALUE_SIZE 4
69
70#define CMD_TIMEOUT msecs_to_jiffies(200)
71#define DATA_TIMEOUT msecs_to_jiffies(1000)
72#define IDLE_TIMEOUT msecs_to_jiffies(2000)
73#define FIRST_FRAME_TIMEOUT msecs_to_jiffies(2000)
74
75#define MISC_REQ_GET_SET_ECO_A 0xff
76#define MISC_REQ_GET_SET_ECO_B 0x35
77/* Windows driver does once every second, with arg d = 1, other args 0 */
78#define MISC_REQ_UNKNOWN1_A 0xff
79#define MISC_REQ_UNKNOWN1_B 0x38
80/* Windows driver does this on init, with arg a, b = 0, c = 0xa0, d = 4 */
81#define MISC_REQ_UNKNOWN2_A 0xa5
82#define MISC_REQ_UNKNOWN2_B 0x00
83
84struct gm12u320_device {
85 struct drm_device dev;
659ab7a4 86 struct device *dmadev;
e4f86e43
HG
87 struct drm_simple_display_pipe pipe;
88 struct drm_connector conn;
e4f86e43
HG
89 unsigned char *cmd_buf;
90 unsigned char *data_buf[GM12U320_BLOCK_COUNT];
e4f86e43 91 struct {
8f2cb937 92 struct delayed_work work;
e4f86e43
HG
93 struct mutex lock;
94 struct drm_framebuffer *fb;
95 struct drm_rect rect;
8f2cb937
DV
96 int frame;
97 int draw_status_timeout;
7938f421 98 struct iosys_map src_map;
e4f86e43
HG
99 } fb_update;
100};
101
7ced4801
DV
102#define to_gm12u320(__dev) container_of(__dev, struct gm12u320_device, dev)
103
e4f86e43
HG
104static const char cmd_data[CMD_SIZE] = {
105 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
106 0x68, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff,
107 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x80, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
109};
110
111static const char cmd_draw[CMD_SIZE] = {
112 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe,
114 0x00, 0x00, 0x00, 0xc0, 0xd1, 0x05, 0x00, 0x40,
115 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
116};
117
118static const char cmd_misc[CMD_SIZE] = {
119 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
120 0x04, 0x00, 0x00, 0x00, 0x80, 0x01, 0x10, 0xfd,
121 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
123};
124
125static const char data_block_header[DATA_BLOCK_HEADER_SIZE] = {
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x04, 0x15, 0x00, 0x00, 0xfc, 0x00, 0x00,
136 0x01, 0x00, 0x00, 0xdb
137};
138
139static const char data_last_block_header[DATA_BLOCK_HEADER_SIZE] = {
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x2a, 0x00, 0x20, 0x00, 0xc0, 0x0f, 0x00, 0x00,
150 0x01, 0x00, 0x00, 0xd7
151};
152
153static const char data_block_footer[DATA_BLOCK_FOOTER_SIZE] = {
154 0xfb, 0x14, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x80, 0x00, 0x00, 0x4f
157};
158
0454bc59
TZ
159static inline struct usb_device *gm12u320_to_usb_device(struct gm12u320_device *gm12u320)
160{
161 return interface_to_usbdev(to_usb_interface(gm12u320->dev.dev));
162}
163
e4f86e43
HG
164static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320)
165{
166 int i, block_size;
167 const char *hdr;
168
08373edc 169 gm12u320->cmd_buf = drmm_kmalloc(&gm12u320->dev, CMD_SIZE, GFP_KERNEL);
e4f86e43
HG
170 if (!gm12u320->cmd_buf)
171 return -ENOMEM;
172
173 for (i = 0; i < GM12U320_BLOCK_COUNT; i++) {
174 if (i == GM12U320_BLOCK_COUNT - 1) {
175 block_size = DATA_LAST_BLOCK_SIZE;
176 hdr = data_last_block_header;
177 } else {
178 block_size = DATA_BLOCK_SIZE;
179 hdr = data_block_header;
180 }
181
08373edc
DV
182 gm12u320->data_buf[i] = drmm_kzalloc(&gm12u320->dev,
183 block_size, GFP_KERNEL);
e4f86e43
HG
184 if (!gm12u320->data_buf[i])
185 return -ENOMEM;
186
187 memcpy(gm12u320->data_buf[i], hdr, DATA_BLOCK_HEADER_SIZE);
188 memcpy(gm12u320->data_buf[i] +
189 (block_size - DATA_BLOCK_FOOTER_SIZE),
190 data_block_footer, DATA_BLOCK_FOOTER_SIZE);
191 }
192
e4f86e43
HG
193 return 0;
194}
195
e4f86e43
HG
196static int gm12u320_misc_request(struct gm12u320_device *gm12u320,
197 u8 req_a, u8 req_b,
198 u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d)
199{
0454bc59 200 struct usb_device *udev = gm12u320_to_usb_device(gm12u320);
e4f86e43
HG
201 int ret, len;
202
203 memcpy(gm12u320->cmd_buf, &cmd_misc, CMD_SIZE);
204 gm12u320->cmd_buf[20] = req_a;
205 gm12u320->cmd_buf[21] = req_b;
206 gm12u320->cmd_buf[22] = arg_a;
207 gm12u320->cmd_buf[23] = arg_b;
208 gm12u320->cmd_buf[24] = arg_c;
209 gm12u320->cmd_buf[25] = arg_d;
210
211 /* Send request */
0454bc59 212 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, MISC_SND_EPT),
e4f86e43
HG
213 gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
214 if (ret || len != CMD_SIZE) {
4abfa2e4 215 GM12U320_ERR("Misc. req. error %d\n", ret);
e4f86e43
HG
216 return -EIO;
217 }
218
219 /* Read value */
0454bc59 220 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, MISC_RCV_EPT),
e4f86e43
HG
221 gm12u320->cmd_buf, MISC_VALUE_SIZE, &len,
222 DATA_TIMEOUT);
223 if (ret || len != MISC_VALUE_SIZE) {
4abfa2e4 224 GM12U320_ERR("Misc. value error %d\n", ret);
e4f86e43
HG
225 return -EIO;
226 }
227 /* cmd_buf[0] now contains the read value, which we don't use */
228
229 /* Read status */
0454bc59 230 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, MISC_RCV_EPT),
e4f86e43
HG
231 gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
232 CMD_TIMEOUT);
233 if (ret || len != READ_STATUS_SIZE) {
4abfa2e4 234 GM12U320_ERR("Misc. status error %d\n", ret);
e4f86e43
HG
235 return -EIO;
236 }
237
238 return 0;
239}
240
241static void gm12u320_32bpp_to_24bpp_packed(u8 *dst, u8 *src, int len)
242{
243 while (len--) {
244 *dst++ = *src++;
245 *dst++ = *src++;
246 *dst++ = *src++;
247 src++;
248 }
249}
250
251static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
252{
253 int block, dst_offset, len, remain, ret, x1, x2, y1, y2;
254 struct drm_framebuffer *fb;
255 void *vaddr;
256 u8 *src;
257
258 mutex_lock(&gm12u320->fb_update.lock);
259
260 if (!gm12u320->fb_update.fb)
261 goto unlock;
262
263 fb = gm12u320->fb_update.fb;
264 x1 = gm12u320->fb_update.rect.x1;
265 x2 = gm12u320->fb_update.rect.x2;
266 y1 = gm12u320->fb_update.rect.y1;
267 y2 = gm12u320->fb_update.rect.y2;
4ac0868d 268 vaddr = gm12u320->fb_update.src_map.vaddr; /* TODO: Use mapping abstraction properly */
e4f86e43 269
329e2c42
TZ
270 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
271 if (ret) {
272 GM12U320_ERR("drm_gem_fb_begin_cpu_access err: %d\n", ret);
273 goto put_fb;
e4f86e43
HG
274 }
275
276 src = vaddr + y1 * fb->pitches[0] + x1 * 4;
277
278 x1 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
279 x2 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
280
281 for (; y1 < y2; y1++) {
282 remain = 0;
283 len = (x2 - x1) * 3;
284 dst_offset = (y1 * GM12U320_REAL_WIDTH + x1) * 3;
285 block = dst_offset / DATA_BLOCK_CONTENT_SIZE;
286 dst_offset %= DATA_BLOCK_CONTENT_SIZE;
287
288 if ((dst_offset + len) > DATA_BLOCK_CONTENT_SIZE) {
289 remain = dst_offset + len - DATA_BLOCK_CONTENT_SIZE;
290 len = DATA_BLOCK_CONTENT_SIZE - dst_offset;
291 }
292
293 dst_offset += DATA_BLOCK_HEADER_SIZE;
294 len /= 3;
295
296 gm12u320_32bpp_to_24bpp_packed(
297 gm12u320->data_buf[block] + dst_offset,
298 src, len);
299
300 if (remain) {
301 block++;
302 dst_offset = DATA_BLOCK_HEADER_SIZE;
303 gm12u320_32bpp_to_24bpp_packed(
304 gm12u320->data_buf[block] + dst_offset,
305 src + len * 4, remain / 3);
306 }
307 src += fb->pitches[0];
308 }
309
329e2c42 310 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
e4f86e43
HG
311put_fb:
312 drm_framebuffer_put(fb);
313 gm12u320->fb_update.fb = NULL;
314unlock:
315 mutex_unlock(&gm12u320->fb_update.lock);
316}
317
e4f86e43
HG
318static void gm12u320_fb_update_work(struct work_struct *work)
319{
320 struct gm12u320_device *gm12u320 =
8f2cb937
DV
321 container_of(to_delayed_work(work), struct gm12u320_device,
322 fb_update.work);
0454bc59 323 struct usb_device *udev = gm12u320_to_usb_device(gm12u320);
e4f86e43 324 int block, block_size, len;
e4f86e43
HG
325 int ret = 0;
326
8f2cb937
DV
327 gm12u320_copy_fb_to_blocks(gm12u320);
328
329 for (block = 0; block < GM12U320_BLOCK_COUNT; block++) {
330 if (block == GM12U320_BLOCK_COUNT - 1)
331 block_size = DATA_LAST_BLOCK_SIZE;
332 else
333 block_size = DATA_BLOCK_SIZE;
334
335 /* Send data command to device */
336 memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE);
337 gm12u320->cmd_buf[8] = block_size & 0xff;
338 gm12u320->cmd_buf[9] = block_size >> 8;
339 gm12u320->cmd_buf[20] = 0xfc - block * 4;
340 gm12u320->cmd_buf[21] =
341 block | (gm12u320->fb_update.frame << 7);
e4f86e43 342
0454bc59
TZ
343 ret = usb_bulk_msg(udev,
344 usb_sndbulkpipe(udev, DATA_SND_EPT),
345 gm12u320->cmd_buf, CMD_SIZE, &len,
346 CMD_TIMEOUT);
e4f86e43
HG
347 if (ret || len != CMD_SIZE)
348 goto err;
349
8f2cb937 350 /* Send data block to device */
0454bc59
TZ
351 ret = usb_bulk_msg(udev,
352 usb_sndbulkpipe(udev, DATA_SND_EPT),
353 gm12u320->data_buf[block], block_size,
354 &len, DATA_TIMEOUT);
8f2cb937
DV
355 if (ret || len != block_size)
356 goto err;
357
e4f86e43 358 /* Read status */
0454bc59
TZ
359 ret = usb_bulk_msg(udev,
360 usb_rcvbulkpipe(udev, DATA_RCV_EPT),
361 gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
362 CMD_TIMEOUT);
e4f86e43
HG
363 if (ret || len != READ_STATUS_SIZE)
364 goto err;
e4f86e43 365 }
8f2cb937
DV
366
367 /* Send draw command to device */
368 memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE);
0454bc59
TZ
369 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, DATA_SND_EPT),
370 gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
8f2cb937
DV
371 if (ret || len != CMD_SIZE)
372 goto err;
373
374 /* Read status */
0454bc59
TZ
375 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, DATA_RCV_EPT),
376 gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
377 gm12u320->fb_update.draw_status_timeout);
8f2cb937
DV
378 if (ret || len != READ_STATUS_SIZE)
379 goto err;
380
381 gm12u320->fb_update.draw_status_timeout = CMD_TIMEOUT;
382 gm12u320->fb_update.frame = !gm12u320->fb_update.frame;
383
384 /*
385 * We must draw a frame every 2s otherwise the projector
386 * switches back to showing its logo.
387 */
388 queue_delayed_work(system_long_wq, &gm12u320->fb_update.work,
389 IDLE_TIMEOUT);
390
e4f86e43
HG
391 return;
392err:
393 /* Do not log errors caused by module unload or device unplug */
ac9fd659 394 if (ret != -ENODEV && ret != -ECONNRESET && ret != -ESHUTDOWN)
4abfa2e4 395 GM12U320_ERR("Frame update error: %d\n", ret);
e4f86e43
HG
396}
397
7938f421
LDM
398static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb,
399 const struct iosys_map *map,
e4f86e43
HG
400 struct drm_rect *dirty)
401{
7ced4801 402 struct gm12u320_device *gm12u320 = to_gm12u320(fb->dev);
e4f86e43
HG
403 struct drm_framebuffer *old_fb = NULL;
404 bool wakeup = false;
405
406 mutex_lock(&gm12u320->fb_update.lock);
407
408 if (gm12u320->fb_update.fb != fb) {
409 old_fb = gm12u320->fb_update.fb;
410 drm_framebuffer_get(fb);
411 gm12u320->fb_update.fb = fb;
412 gm12u320->fb_update.rect = *dirty;
4ac0868d 413 gm12u320->fb_update.src_map = *map;
e4f86e43
HG
414 wakeup = true;
415 } else {
416 struct drm_rect *rect = &gm12u320->fb_update.rect;
417
418 rect->x1 = min(rect->x1, dirty->x1);
419 rect->y1 = min(rect->y1, dirty->y1);
420 rect->x2 = max(rect->x2, dirty->x2);
421 rect->y2 = max(rect->y2, dirty->y2);
422 }
423
424 mutex_unlock(&gm12u320->fb_update.lock);
425
426 if (wakeup)
8f2cb937 427 mod_delayed_work(system_long_wq, &gm12u320->fb_update.work, 0);
e4f86e43
HG
428
429 if (old_fb)
430 drm_framebuffer_put(old_fb);
431}
432
e4f86e43
HG
433static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320)
434{
8f2cb937 435 struct drm_framebuffer *old_fb;
e4f86e43 436
8f2cb937 437 cancel_delayed_work_sync(&gm12u320->fb_update.work);
e4f86e43
HG
438
439 mutex_lock(&gm12u320->fb_update.lock);
8f2cb937
DV
440 old_fb = gm12u320->fb_update.fb;
441 gm12u320->fb_update.fb = NULL;
7938f421 442 iosys_map_clear(&gm12u320->fb_update.src_map);
e4f86e43 443 mutex_unlock(&gm12u320->fb_update.lock);
8f2cb937
DV
444
445 drm_framebuffer_put(old_fb);
e4f86e43
HG
446}
447
448static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320)
449{
450 return gm12u320_misc_request(gm12u320, MISC_REQ_GET_SET_ECO_A,
451 MISC_REQ_GET_SET_ECO_B, 0x01 /* set */,
452 eco_mode ? 0x01 : 0x00, 0x00, 0x01);
453}
454
455/* ------------------------------------------------------------------ */
456/* gm12u320 connector */
457
458/*
459 * We use fake EDID info so that userspace know that it is dealing with
460 * an Acer projector, rather then listing this as an "unknown" monitor.
461 * Note this assumes this driver is only ever used with the Acer C120, if we
462 * add support for other devices the vendor and model should be parameterized.
463 */
464static struct edid gm12u320_edid = {
465 .header = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 },
466 .mfg_id = { 0x04, 0x72 }, /* "ACR" */
467 .prod_code = { 0x20, 0xc1 }, /* C120h */
468 .serial = 0xaa55aa55,
469 .mfg_week = 1,
470 .mfg_year = 16,
471 .version = 1, /* EDID 1.3 */
472 .revision = 3, /* EDID 1.3 */
473 .input = 0x08, /* Analog input */
474 .features = 0x0a, /* Pref timing in DTD 1 */
475 .standard_timings = { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
476 { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } },
477 .detailed_timings = { {
478 .pixel_clock = 3383,
479 /* hactive = 848, hblank = 256 */
480 .data.pixel_data.hactive_lo = 0x50,
481 .data.pixel_data.hblank_lo = 0x00,
482 .data.pixel_data.hactive_hblank_hi = 0x31,
483 /* vactive = 480, vblank = 28 */
484 .data.pixel_data.vactive_lo = 0xe0,
485 .data.pixel_data.vblank_lo = 0x1c,
486 .data.pixel_data.vactive_vblank_hi = 0x10,
487 /* hsync offset 40 pw 128, vsync offset 1 pw 4 */
488 .data.pixel_data.hsync_offset_lo = 0x28,
489 .data.pixel_data.hsync_pulse_width_lo = 0x80,
490 .data.pixel_data.vsync_offset_pulse_width_lo = 0x14,
491 .data.pixel_data.hsync_vsync_offset_pulse_width_hi = 0x00,
492 /* Digital separate syncs, hsync+, vsync+ */
493 .data.pixel_data.misc = 0x1e,
494 }, {
495 .pixel_clock = 0,
496 .data.other_data.type = 0xfd, /* Monitor ranges */
497 .data.other_data.data.range.min_vfreq = 59,
498 .data.other_data.data.range.max_vfreq = 61,
499 .data.other_data.data.range.min_hfreq_khz = 29,
500 .data.other_data.data.range.max_hfreq_khz = 32,
501 .data.other_data.data.range.pixel_clock_mhz = 4, /* 40 MHz */
502 .data.other_data.data.range.flags = 0,
503 .data.other_data.data.range.formula.cvt = {
504 0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
505 }, {
506 .pixel_clock = 0,
507 .data.other_data.type = 0xfc, /* Model string */
508 .data.other_data.data.str.str = {
509 'P', 'r', 'o', 'j', 'e', 'c', 't', 'o', 'r', '\n',
510 ' ', ' ', ' ' },
511 }, {
512 .pixel_clock = 0,
513 .data.other_data.type = 0xfe, /* Unspecified text / padding */
514 .data.other_data.data.str.str = {
515 '\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
516 ' ', ' ', ' ' },
517 } },
518 .checksum = 0x13,
519};
520
521static int gm12u320_conn_get_modes(struct drm_connector *connector)
522{
523 drm_connector_update_edid_property(connector, &gm12u320_edid);
524 return drm_add_edid_modes(connector, &gm12u320_edid);
525}
526
527static const struct drm_connector_helper_funcs gm12u320_conn_helper_funcs = {
528 .get_modes = gm12u320_conn_get_modes,
529};
530
531static const struct drm_connector_funcs gm12u320_conn_funcs = {
532 .fill_modes = drm_helper_probe_single_connector_modes,
533 .destroy = drm_connector_cleanup,
534 .reset = drm_atomic_helper_connector_reset,
535 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
536 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
537};
538
539static int gm12u320_conn_init(struct gm12u320_device *gm12u320)
540{
541 drm_connector_helper_add(&gm12u320->conn, &gm12u320_conn_helper_funcs);
542 return drm_connector_init(&gm12u320->dev, &gm12u320->conn,
543 &gm12u320_conn_funcs, DRM_MODE_CONNECTOR_VGA);
544}
545
546/* ------------------------------------------------------------------ */
547/* gm12u320 (simple) display pipe */
548
549static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
550 struct drm_crtc_state *crtc_state,
551 struct drm_plane_state *plane_state)
552{
e4f86e43 553 struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT };
7ced4801 554 struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev);
4ac0868d 555 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
e4f86e43 556
8f2cb937 557 gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT;
229d9468 558 gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect);
e4f86e43
HG
559}
560
561static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
562{
7ced4801 563 struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev);
e4f86e43
HG
564
565 gm12u320_stop_fb_update(gm12u320);
e4f86e43
HG
566}
567
568static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
569 struct drm_plane_state *old_state)
570{
571 struct drm_plane_state *state = pipe->plane.state;
4ac0868d 572 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
e4f86e43
HG
573 struct drm_rect rect;
574
575 if (drm_atomic_helper_damage_merged(old_state, state, &rect))
229d9468 576 gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
e4f86e43
HG
577}
578
579static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
580 .enable = gm12u320_pipe_enable,
581 .disable = gm12u320_pipe_disable,
582 .update = gm12u320_pipe_update,
4ac0868d 583 DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
e4f86e43
HG
584};
585
586static const uint32_t gm12u320_pipe_formats[] = {
587 DRM_FORMAT_XRGB8888,
588};
589
590static const uint64_t gm12u320_pipe_modifiers[] = {
591 DRM_FORMAT_MOD_LINEAR,
592 DRM_FORMAT_MOD_INVALID
593};
594
659ab7a4
TZ
595/*
596 * FIXME: Dma-buf sharing requires DMA support by the importing device.
597 * This function is a workaround to make USB devices work as well.
598 * See todo.rst for how to fix the issue in the dma-buf framework.
599 */
600static struct drm_gem_object *gm12u320_gem_prime_import(struct drm_device *dev,
601 struct dma_buf *dma_buf)
602{
603 struct gm12u320_device *gm12u320 = to_gm12u320(dev);
604
605 if (!gm12u320->dmadev)
606 return ERR_PTR(-ENODEV);
607
608 return drm_gem_prime_import_dev(dev, dma_buf, gm12u320->dmadev);
609}
610
eee9a2e0 611DEFINE_DRM_GEM_FOPS(gm12u320_fops);
e4f86e43 612
70a59dd8 613static const struct drm_driver gm12u320_drm_driver = {
e4f86e43
HG
614 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
615
616 .name = DRIVER_NAME,
617 .desc = DRIVER_DESC,
618 .date = DRIVER_DATE,
619 .major = DRIVER_MAJOR,
620 .minor = DRIVER_MINOR,
621
e4f86e43
HG
622 .fops = &gm12u320_fops,
623 DRM_GEM_SHMEM_DRIVER_OPS,
659ab7a4 624 .gem_prime_import = gm12u320_gem_prime_import,
e4f86e43
HG
625};
626
627static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
628 .fb_create = drm_gem_fb_create_with_dirty,
629 .atomic_check = drm_atomic_helper_check,
630 .atomic_commit = drm_atomic_helper_commit,
631};
632
633static int gm12u320_usb_probe(struct usb_interface *interface,
634 const struct usb_device_id *id)
635{
636 struct gm12u320_device *gm12u320;
637 struct drm_device *dev;
638 int ret;
639
640 /*
641 * The gm12u320 presents itself to the system as 2 usb mass-storage
642 * interfaces, we only care about / need the first one.
643 */
644 if (interface->cur_altsetting->desc.bInterfaceNumber != 0)
645 return -ENODEV;
646
9213142d
DV
647 gm12u320 = devm_drm_dev_alloc(&interface->dev, &gm12u320_drm_driver,
648 struct gm12u320_device, dev);
649 if (IS_ERR(gm12u320))
650 return PTR_ERR(gm12u320);
659ab7a4
TZ
651 dev = &gm12u320->dev;
652
653 gm12u320->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
654 if (!gm12u320->dmadev)
655 drm_warn(dev, "buffer sharing not supported"); /* not an error */
e4f86e43 656
8f2cb937 657 INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
e4f86e43 658 mutex_init(&gm12u320->fb_update.lock);
e4f86e43 659
08373edc
DV
660 ret = drmm_mode_config_init(dev);
661 if (ret)
659ab7a4 662 goto err_put_device;
08373edc 663
e4f86e43
HG
664 dev->mode_config.min_width = GM12U320_USER_WIDTH;
665 dev->mode_config.max_width = GM12U320_USER_WIDTH;
666 dev->mode_config.min_height = GM12U320_HEIGHT;
667 dev->mode_config.max_height = GM12U320_HEIGHT;
668 dev->mode_config.funcs = &gm12u320_mode_config_funcs;
669
670 ret = gm12u320_usb_alloc(gm12u320);
671 if (ret)
659ab7a4 672 goto err_put_device;
e4f86e43
HG
673
674 ret = gm12u320_set_ecomode(gm12u320);
675 if (ret)
659ab7a4 676 goto err_put_device;
e4f86e43
HG
677
678 ret = gm12u320_conn_init(gm12u320);
679 if (ret)
659ab7a4 680 goto err_put_device;
e4f86e43
HG
681
682 ret = drm_simple_display_pipe_init(&gm12u320->dev,
683 &gm12u320->pipe,
684 &gm12u320_pipe_funcs,
685 gm12u320_pipe_formats,
686 ARRAY_SIZE(gm12u320_pipe_formats),
687 gm12u320_pipe_modifiers,
688 &gm12u320->conn);
689 if (ret)
659ab7a4 690 goto err_put_device;
e4f86e43
HG
691
692 drm_mode_config_reset(dev);
693
694 usb_set_intfdata(interface, dev);
695 ret = drm_dev_register(dev, 0);
696 if (ret)
659ab7a4 697 goto err_put_device;
e4f86e43 698
8515090c 699 drm_fbdev_generic_setup(dev, 0);
e4f86e43
HG
700
701 return 0;
659ab7a4
TZ
702
703err_put_device:
704 put_device(gm12u320->dmadev);
705 return ret;
e4f86e43
HG
706}
707
708static void gm12u320_usb_disconnect(struct usb_interface *interface)
709{
710 struct drm_device *dev = usb_get_intfdata(interface);
659ab7a4 711 struct gm12u320_device *gm12u320 = to_gm12u320(dev);
e4f86e43 712
659ab7a4
TZ
713 put_device(gm12u320->dmadev);
714 gm12u320->dmadev = NULL;
e4f86e43 715 drm_dev_unplug(dev);
7ef64ed1 716 drm_atomic_helper_shutdown(dev);
e4f86e43
HG
717}
718
8515090c
HG
719static __maybe_unused int gm12u320_suspend(struct usb_interface *interface,
720 pm_message_t message)
e4f86e43
HG
721{
722 struct drm_device *dev = usb_get_intfdata(interface);
e4f86e43 723
7ef64ed1 724 return drm_mode_config_helper_suspend(dev);
e4f86e43
HG
725}
726
8515090c 727static __maybe_unused int gm12u320_resume(struct usb_interface *interface)
e4f86e43
HG
728{
729 struct drm_device *dev = usb_get_intfdata(interface);
7ced4801 730 struct gm12u320_device *gm12u320 = to_gm12u320(dev);
e4f86e43
HG
731
732 gm12u320_set_ecomode(gm12u320);
e4f86e43 733
7ef64ed1 734 return drm_mode_config_helper_resume(dev);
e4f86e43 735}
e4f86e43
HG
736
737static const struct usb_device_id id_table[] = {
738 { USB_DEVICE(0x1de1, 0xc102) },
739 {},
740};
741MODULE_DEVICE_TABLE(usb, id_table);
742
743static struct usb_driver gm12u320_usb_driver = {
744 .name = "gm12u320",
745 .probe = gm12u320_usb_probe,
746 .disconnect = gm12u320_usb_disconnect,
747 .id_table = id_table,
748#ifdef CONFIG_PM
749 .suspend = gm12u320_suspend,
750 .resume = gm12u320_resume,
751 .reset_resume = gm12u320_resume,
752#endif
753};
754
755module_usb_driver(gm12u320_usb_driver);
756MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
757MODULE_LICENSE("GPL");