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