xref: /linux/drivers/gpu/drm/tiny/gm12u320.c (revision d8a46257c22906db38590eb7986c07770bee002c)
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_modeset_helper_vtables.h>
23 #include <drm/drm_probe_helper.h>
24 #include <drm/drm_simple_kms_helper.h>
25 #include <drm/drm_vblank.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 #define DRIVER_PATCHLEVEL	1
37 
38 /*
39  * The DLP has an actual width of 854 pixels, but that is not a multiple
40  * of 8, breaking things left and right, so we export a width of 848.
41  */
42 #define GM12U320_USER_WIDTH		848
43 #define GM12U320_REAL_WIDTH		854
44 #define GM12U320_HEIGHT			480
45 
46 #define GM12U320_BLOCK_COUNT		20
47 
48 #define MISC_RCV_EPT			1
49 #define DATA_RCV_EPT			2
50 #define DATA_SND_EPT			3
51 #define MISC_SND_EPT			4
52 
53 #define DATA_BLOCK_HEADER_SIZE		84
54 #define DATA_BLOCK_CONTENT_SIZE		64512
55 #define DATA_BLOCK_FOOTER_SIZE		20
56 #define DATA_BLOCK_SIZE			(DATA_BLOCK_HEADER_SIZE + \
57 					 DATA_BLOCK_CONTENT_SIZE + \
58 					 DATA_BLOCK_FOOTER_SIZE)
59 #define DATA_LAST_BLOCK_CONTENT_SIZE	4032
60 #define DATA_LAST_BLOCK_SIZE		(DATA_BLOCK_HEADER_SIZE + \
61 					 DATA_LAST_BLOCK_CONTENT_SIZE + \
62 					 DATA_BLOCK_FOOTER_SIZE)
63 
64 #define CMD_SIZE			31
65 #define READ_STATUS_SIZE		13
66 #define MISC_VALUE_SIZE			4
67 
68 #define CMD_TIMEOUT			msecs_to_jiffies(200)
69 #define DATA_TIMEOUT			msecs_to_jiffies(1000)
70 #define IDLE_TIMEOUT			msecs_to_jiffies(2000)
71 #define FIRST_FRAME_TIMEOUT		msecs_to_jiffies(2000)
72 
73 #define MISC_REQ_GET_SET_ECO_A		0xff
74 #define MISC_REQ_GET_SET_ECO_B		0x35
75 /* Windows driver does once every second, with arg d = 1, other args 0 */
76 #define MISC_REQ_UNKNOWN1_A		0xff
77 #define MISC_REQ_UNKNOWN1_B		0x38
78 /* Windows driver does this on init, with arg a, b = 0, c = 0xa0, d = 4 */
79 #define MISC_REQ_UNKNOWN2_A		0xa5
80 #define MISC_REQ_UNKNOWN2_B		0x00
81 
82 struct gm12u320_device {
83 	struct drm_device	         dev;
84 	struct drm_simple_display_pipe   pipe;
85 	struct drm_connector	         conn;
86 	struct usb_device               *udev;
87 	unsigned char                   *cmd_buf;
88 	unsigned char                   *data_buf[GM12U320_BLOCK_COUNT];
89 	bool                             pipe_enabled;
90 	struct {
91 		bool                     run;
92 		struct workqueue_struct *workq;
93 		struct work_struct       work;
94 		wait_queue_head_t        waitq;
95 		struct mutex             lock;
96 		struct drm_framebuffer  *fb;
97 		struct drm_rect          rect;
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 = kmalloc(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] = kzalloc(block_size, GFP_KERNEL);
175 		if (!gm12u320->data_buf[i])
176 			return -ENOMEM;
177 
178 		memcpy(gm12u320->data_buf[i], hdr, DATA_BLOCK_HEADER_SIZE);
179 		memcpy(gm12u320->data_buf[i] +
180 				(block_size - DATA_BLOCK_FOOTER_SIZE),
181 		       data_block_footer, DATA_BLOCK_FOOTER_SIZE);
182 	}
183 
184 	gm12u320->fb_update.workq = create_singlethread_workqueue(DRIVER_NAME);
185 	if (!gm12u320->fb_update.workq)
186 		return -ENOMEM;
187 
188 	return 0;
189 }
190 
191 static void gm12u320_usb_free(struct gm12u320_device *gm12u320)
192 {
193 	int i;
194 
195 	if (gm12u320->fb_update.workq)
196 		destroy_workqueue(gm12u320->fb_update.workq);
197 
198 	for (i = 0; i < GM12U320_BLOCK_COUNT; i++)
199 		kfree(gm12u320->data_buf[i]);
200 
201 	kfree(gm12u320->cmd_buf);
202 }
203 
204 static int gm12u320_misc_request(struct gm12u320_device *gm12u320,
205 				 u8 req_a, u8 req_b,
206 				 u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d)
207 {
208 	int ret, len;
209 
210 	memcpy(gm12u320->cmd_buf, &cmd_misc, CMD_SIZE);
211 	gm12u320->cmd_buf[20] = req_a;
212 	gm12u320->cmd_buf[21] = req_b;
213 	gm12u320->cmd_buf[22] = arg_a;
214 	gm12u320->cmd_buf[23] = arg_b;
215 	gm12u320->cmd_buf[24] = arg_c;
216 	gm12u320->cmd_buf[25] = arg_d;
217 
218 	/* Send request */
219 	ret = usb_bulk_msg(gm12u320->udev,
220 			   usb_sndbulkpipe(gm12u320->udev, MISC_SND_EPT),
221 			   gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
222 	if (ret || len != CMD_SIZE) {
223 		dev_err(&gm12u320->udev->dev, "Misc. req. error %d\n", ret);
224 		return -EIO;
225 	}
226 
227 	/* Read value */
228 	ret = usb_bulk_msg(gm12u320->udev,
229 			   usb_rcvbulkpipe(gm12u320->udev, MISC_RCV_EPT),
230 			   gm12u320->cmd_buf, MISC_VALUE_SIZE, &len,
231 			   DATA_TIMEOUT);
232 	if (ret || len != MISC_VALUE_SIZE) {
233 		dev_err(&gm12u320->udev->dev, "Misc. value error %d\n", ret);
234 		return -EIO;
235 	}
236 	/* cmd_buf[0] now contains the read value, which we don't use */
237 
238 	/* Read status */
239 	ret = usb_bulk_msg(gm12u320->udev,
240 			   usb_rcvbulkpipe(gm12u320->udev, MISC_RCV_EPT),
241 			   gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
242 			   CMD_TIMEOUT);
243 	if (ret || len != READ_STATUS_SIZE) {
244 		dev_err(&gm12u320->udev->dev, "Misc. status error %d\n", ret);
245 		return -EIO;
246 	}
247 
248 	return 0;
249 }
250 
251 static void gm12u320_32bpp_to_24bpp_packed(u8 *dst, u8 *src, int len)
252 {
253 	while (len--) {
254 		*dst++ = *src++;
255 		*dst++ = *src++;
256 		*dst++ = *src++;
257 		src++;
258 	}
259 }
260 
261 static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
262 {
263 	int block, dst_offset, len, remain, ret, x1, x2, y1, y2;
264 	struct drm_framebuffer *fb;
265 	void *vaddr;
266 	u8 *src;
267 
268 	mutex_lock(&gm12u320->fb_update.lock);
269 
270 	if (!gm12u320->fb_update.fb)
271 		goto unlock;
272 
273 	fb = gm12u320->fb_update.fb;
274 	x1 = gm12u320->fb_update.rect.x1;
275 	x2 = gm12u320->fb_update.rect.x2;
276 	y1 = gm12u320->fb_update.rect.y1;
277 	y2 = gm12u320->fb_update.rect.y2;
278 
279 	vaddr = drm_gem_shmem_vmap(fb->obj[0]);
280 	if (IS_ERR(vaddr)) {
281 		DRM_ERROR("failed to vmap fb: %ld\n", PTR_ERR(vaddr));
282 		goto put_fb;
283 	}
284 
285 	if (fb->obj[0]->import_attach) {
286 		ret = dma_buf_begin_cpu_access(
287 			fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE);
288 		if (ret) {
289 			DRM_ERROR("dma_buf_begin_cpu_access err: %d\n", ret);
290 			goto vunmap;
291 		}
292 	}
293 
294 	src = vaddr + y1 * fb->pitches[0] + x1 * 4;
295 
296 	x1 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
297 	x2 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
298 
299 	for (; y1 < y2; y1++) {
300 		remain = 0;
301 		len = (x2 - x1) * 3;
302 		dst_offset = (y1 * GM12U320_REAL_WIDTH + x1) * 3;
303 		block = dst_offset / DATA_BLOCK_CONTENT_SIZE;
304 		dst_offset %= DATA_BLOCK_CONTENT_SIZE;
305 
306 		if ((dst_offset + len) > DATA_BLOCK_CONTENT_SIZE) {
307 			remain = dst_offset + len - DATA_BLOCK_CONTENT_SIZE;
308 			len = DATA_BLOCK_CONTENT_SIZE - dst_offset;
309 		}
310 
311 		dst_offset += DATA_BLOCK_HEADER_SIZE;
312 		len /= 3;
313 
314 		gm12u320_32bpp_to_24bpp_packed(
315 			gm12u320->data_buf[block] + dst_offset,
316 			src, len);
317 
318 		if (remain) {
319 			block++;
320 			dst_offset = DATA_BLOCK_HEADER_SIZE;
321 			gm12u320_32bpp_to_24bpp_packed(
322 				gm12u320->data_buf[block] + dst_offset,
323 				src + len * 4, remain / 3);
324 		}
325 		src += fb->pitches[0];
326 	}
327 
328 	if (fb->obj[0]->import_attach) {
329 		ret = dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf,
330 					     DMA_FROM_DEVICE);
331 		if (ret)
332 			DRM_ERROR("dma_buf_end_cpu_access err: %d\n", ret);
333 	}
334 vunmap:
335 	drm_gem_shmem_vunmap(fb->obj[0], vaddr);
336 put_fb:
337 	drm_framebuffer_put(fb);
338 	gm12u320->fb_update.fb = NULL;
339 unlock:
340 	mutex_unlock(&gm12u320->fb_update.lock);
341 }
342 
343 static int gm12u320_fb_update_ready(struct gm12u320_device *gm12u320)
344 {
345 	int ret;
346 
347 	mutex_lock(&gm12u320->fb_update.lock);
348 	ret = !gm12u320->fb_update.run || gm12u320->fb_update.fb != NULL;
349 	mutex_unlock(&gm12u320->fb_update.lock);
350 
351 	return ret;
352 }
353 
354 static void gm12u320_fb_update_work(struct work_struct *work)
355 {
356 	struct gm12u320_device *gm12u320 =
357 		container_of(work, struct gm12u320_device, fb_update.work);
358 	int draw_status_timeout = FIRST_FRAME_TIMEOUT;
359 	int block, block_size, len;
360 	int frame = 0;
361 	int ret = 0;
362 
363 	while (gm12u320->fb_update.run) {
364 		gm12u320_copy_fb_to_blocks(gm12u320);
365 
366 		for (block = 0; block < GM12U320_BLOCK_COUNT; block++) {
367 			if (block == GM12U320_BLOCK_COUNT - 1)
368 				block_size = DATA_LAST_BLOCK_SIZE;
369 			else
370 				block_size = DATA_BLOCK_SIZE;
371 
372 			/* Send data command to device */
373 			memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE);
374 			gm12u320->cmd_buf[8] = block_size & 0xff;
375 			gm12u320->cmd_buf[9] = block_size >> 8;
376 			gm12u320->cmd_buf[20] = 0xfc - block * 4;
377 			gm12u320->cmd_buf[21] = block | (frame << 7);
378 
379 			ret = usb_bulk_msg(gm12u320->udev,
380 				usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT),
381 				gm12u320->cmd_buf, CMD_SIZE, &len,
382 				CMD_TIMEOUT);
383 			if (ret || len != CMD_SIZE)
384 				goto err;
385 
386 			/* Send data block to device */
387 			ret = usb_bulk_msg(gm12u320->udev,
388 				usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT),
389 				gm12u320->data_buf[block], block_size,
390 				&len, DATA_TIMEOUT);
391 			if (ret || len != block_size)
392 				goto err;
393 
394 			/* Read status */
395 			ret = usb_bulk_msg(gm12u320->udev,
396 				usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT),
397 				gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
398 				CMD_TIMEOUT);
399 			if (ret || len != READ_STATUS_SIZE)
400 				goto err;
401 		}
402 
403 		/* Send draw command to device */
404 		memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE);
405 		ret = usb_bulk_msg(gm12u320->udev,
406 			usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT),
407 			gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
408 		if (ret || len != CMD_SIZE)
409 			goto err;
410 
411 		/* Read status */
412 		ret = usb_bulk_msg(gm12u320->udev,
413 			usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT),
414 			gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
415 			draw_status_timeout);
416 		if (ret || len != READ_STATUS_SIZE)
417 			goto err;
418 
419 		draw_status_timeout = CMD_TIMEOUT;
420 		frame = !frame;
421 
422 		/*
423 		 * We must draw a frame every 2s otherwise the projector
424 		 * switches back to showing its logo.
425 		 */
426 		wait_event_timeout(gm12u320->fb_update.waitq,
427 				   gm12u320_fb_update_ready(gm12u320),
428 				   IDLE_TIMEOUT);
429 	}
430 	return;
431 err:
432 	/* Do not log errors caused by module unload or device unplug */
433 	if (ret != -ECONNRESET && ret != -ESHUTDOWN)
434 		dev_err(&gm12u320->udev->dev, "Frame update error: %d\n", ret);
435 }
436 
437 static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb,
438 				   struct drm_rect *dirty)
439 {
440 	struct gm12u320_device *gm12u320 = fb->dev->dev_private;
441 	struct drm_framebuffer *old_fb = NULL;
442 	bool wakeup = false;
443 
444 	mutex_lock(&gm12u320->fb_update.lock);
445 
446 	if (gm12u320->fb_update.fb != fb) {
447 		old_fb = gm12u320->fb_update.fb;
448 		drm_framebuffer_get(fb);
449 		gm12u320->fb_update.fb = fb;
450 		gm12u320->fb_update.rect = *dirty;
451 		wakeup = true;
452 	} else {
453 		struct drm_rect *rect = &gm12u320->fb_update.rect;
454 
455 		rect->x1 = min(rect->x1, dirty->x1);
456 		rect->y1 = min(rect->y1, dirty->y1);
457 		rect->x2 = max(rect->x2, dirty->x2);
458 		rect->y2 = max(rect->y2, dirty->y2);
459 	}
460 
461 	mutex_unlock(&gm12u320->fb_update.lock);
462 
463 	if (wakeup)
464 		wake_up(&gm12u320->fb_update.waitq);
465 
466 	if (old_fb)
467 		drm_framebuffer_put(old_fb);
468 }
469 
470 static void gm12u320_start_fb_update(struct gm12u320_device *gm12u320)
471 {
472 	mutex_lock(&gm12u320->fb_update.lock);
473 	gm12u320->fb_update.run = true;
474 	mutex_unlock(&gm12u320->fb_update.lock);
475 
476 	queue_work(gm12u320->fb_update.workq, &gm12u320->fb_update.work);
477 }
478 
479 static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320)
480 {
481 	mutex_lock(&gm12u320->fb_update.lock);
482 	gm12u320->fb_update.run = false;
483 	mutex_unlock(&gm12u320->fb_update.lock);
484 
485 	wake_up(&gm12u320->fb_update.waitq);
486 	cancel_work_sync(&gm12u320->fb_update.work);
487 
488 	mutex_lock(&gm12u320->fb_update.lock);
489 	if (gm12u320->fb_update.fb) {
490 		drm_framebuffer_put(gm12u320->fb_update.fb);
491 		gm12u320->fb_update.fb = NULL;
492 	}
493 	mutex_unlock(&gm12u320->fb_update.lock);
494 }
495 
496 static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320)
497 {
498 	return gm12u320_misc_request(gm12u320, MISC_REQ_GET_SET_ECO_A,
499 				     MISC_REQ_GET_SET_ECO_B, 0x01 /* set */,
500 				     eco_mode ? 0x01 : 0x00, 0x00, 0x01);
501 }
502 
503 /* ------------------------------------------------------------------ */
504 /* gm12u320 connector						      */
505 
506 /*
507  * We use fake EDID info so that userspace know that it is dealing with
508  * an Acer projector, rather then listing this as an "unknown" monitor.
509  * Note this assumes this driver is only ever used with the Acer C120, if we
510  * add support for other devices the vendor and model should be parameterized.
511  */
512 static struct edid gm12u320_edid = {
513 	.header		= { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 },
514 	.mfg_id		= { 0x04, 0x72 },	/* "ACR" */
515 	.prod_code	= { 0x20, 0xc1 },	/* C120h */
516 	.serial		= 0xaa55aa55,
517 	.mfg_week	= 1,
518 	.mfg_year	= 16,
519 	.version	= 1,			/* EDID 1.3 */
520 	.revision	= 3,			/* EDID 1.3 */
521 	.input		= 0x08,			/* Analog input */
522 	.features	= 0x0a,			/* Pref timing in DTD 1 */
523 	.standard_timings = { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
524 			      { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } },
525 	.detailed_timings = { {
526 		.pixel_clock = 3383,
527 		/* hactive = 848, hblank = 256 */
528 		.data.pixel_data.hactive_lo = 0x50,
529 		.data.pixel_data.hblank_lo = 0x00,
530 		.data.pixel_data.hactive_hblank_hi = 0x31,
531 		/* vactive = 480, vblank = 28 */
532 		.data.pixel_data.vactive_lo = 0xe0,
533 		.data.pixel_data.vblank_lo = 0x1c,
534 		.data.pixel_data.vactive_vblank_hi = 0x10,
535 		/* hsync offset 40 pw 128, vsync offset 1 pw 4 */
536 		.data.pixel_data.hsync_offset_lo = 0x28,
537 		.data.pixel_data.hsync_pulse_width_lo = 0x80,
538 		.data.pixel_data.vsync_offset_pulse_width_lo = 0x14,
539 		.data.pixel_data.hsync_vsync_offset_pulse_width_hi = 0x00,
540 		/* Digital separate syncs, hsync+, vsync+ */
541 		.data.pixel_data.misc = 0x1e,
542 	}, {
543 		.pixel_clock = 0,
544 		.data.other_data.type = 0xfd, /* Monitor ranges */
545 		.data.other_data.data.range.min_vfreq = 59,
546 		.data.other_data.data.range.max_vfreq = 61,
547 		.data.other_data.data.range.min_hfreq_khz = 29,
548 		.data.other_data.data.range.max_hfreq_khz = 32,
549 		.data.other_data.data.range.pixel_clock_mhz = 4, /* 40 MHz */
550 		.data.other_data.data.range.flags = 0,
551 		.data.other_data.data.range.formula.cvt = {
552 			0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
553 	}, {
554 		.pixel_clock = 0,
555 		.data.other_data.type = 0xfc, /* Model string */
556 		.data.other_data.data.str.str = {
557 			'P', 'r', 'o', 'j', 'e', 'c', 't', 'o', 'r', '\n',
558 			' ', ' ',  ' ' },
559 	}, {
560 		.pixel_clock = 0,
561 		.data.other_data.type = 0xfe, /* Unspecified text / padding */
562 		.data.other_data.data.str.str = {
563 			'\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
564 			' ', ' ',  ' ' },
565 	} },
566 	.checksum = 0x13,
567 };
568 
569 static int gm12u320_conn_get_modes(struct drm_connector *connector)
570 {
571 	drm_connector_update_edid_property(connector, &gm12u320_edid);
572 	return drm_add_edid_modes(connector, &gm12u320_edid);
573 }
574 
575 static const struct drm_connector_helper_funcs gm12u320_conn_helper_funcs = {
576 	.get_modes = gm12u320_conn_get_modes,
577 };
578 
579 static const struct drm_connector_funcs gm12u320_conn_funcs = {
580 	.fill_modes = drm_helper_probe_single_connector_modes,
581 	.destroy = drm_connector_cleanup,
582 	.reset = drm_atomic_helper_connector_reset,
583 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
584 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
585 };
586 
587 static int gm12u320_conn_init(struct gm12u320_device *gm12u320)
588 {
589 	drm_connector_helper_add(&gm12u320->conn, &gm12u320_conn_helper_funcs);
590 	return drm_connector_init(&gm12u320->dev, &gm12u320->conn,
591 				  &gm12u320_conn_funcs, DRM_MODE_CONNECTOR_VGA);
592 }
593 
594 /* ------------------------------------------------------------------ */
595 /* gm12u320 (simple) display pipe				      */
596 
597 static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
598 				 struct drm_crtc_state *crtc_state,
599 				 struct drm_plane_state *plane_state)
600 {
601 	struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private;
602 	struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT };
603 
604 	gm12u320_fb_mark_dirty(plane_state->fb, &rect);
605 	gm12u320_start_fb_update(gm12u320);
606 	gm12u320->pipe_enabled = true;
607 }
608 
609 static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
610 {
611 	struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private;
612 
613 	gm12u320_stop_fb_update(gm12u320);
614 	gm12u320->pipe_enabled = false;
615 }
616 
617 static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
618 				 struct drm_plane_state *old_state)
619 {
620 	struct drm_plane_state *state = pipe->plane.state;
621 	struct drm_crtc *crtc = &pipe->crtc;
622 	struct drm_rect rect;
623 
624 	if (drm_atomic_helper_damage_merged(old_state, state, &rect))
625 		gm12u320_fb_mark_dirty(pipe->plane.state->fb, &rect);
626 
627 	if (crtc->state->event) {
628 		spin_lock_irq(&crtc->dev->event_lock);
629 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
630 		crtc->state->event = NULL;
631 		spin_unlock_irq(&crtc->dev->event_lock);
632 	}
633 }
634 
635 static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
636 	.enable	    = gm12u320_pipe_enable,
637 	.disable    = gm12u320_pipe_disable,
638 	.update	    = gm12u320_pipe_update,
639 };
640 
641 static const uint32_t gm12u320_pipe_formats[] = {
642 	DRM_FORMAT_XRGB8888,
643 };
644 
645 static const uint64_t gm12u320_pipe_modifiers[] = {
646 	DRM_FORMAT_MOD_LINEAR,
647 	DRM_FORMAT_MOD_INVALID
648 };
649 
650 static void gm12u320_driver_release(struct drm_device *dev)
651 {
652 	struct gm12u320_device *gm12u320 = dev->dev_private;
653 
654 	gm12u320_usb_free(gm12u320);
655 	drm_mode_config_cleanup(dev);
656 	drm_dev_fini(dev);
657 	kfree(gm12u320);
658 }
659 
660 DEFINE_DRM_GEM_SHMEM_FOPS(gm12u320_fops);
661 
662 static struct drm_driver gm12u320_drm_driver = {
663 	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
664 
665 	.name		 = DRIVER_NAME,
666 	.desc		 = DRIVER_DESC,
667 	.date		 = DRIVER_DATE,
668 	.major		 = DRIVER_MAJOR,
669 	.minor		 = DRIVER_MINOR,
670 
671 	.release	 = gm12u320_driver_release,
672 	.fops		 = &gm12u320_fops,
673 	DRM_GEM_SHMEM_DRIVER_OPS,
674 };
675 
676 static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
677 	.fb_create = drm_gem_fb_create_with_dirty,
678 	.atomic_check = drm_atomic_helper_check,
679 	.atomic_commit = drm_atomic_helper_commit,
680 };
681 
682 static int gm12u320_usb_probe(struct usb_interface *interface,
683 			      const struct usb_device_id *id)
684 {
685 	struct gm12u320_device *gm12u320;
686 	struct drm_device *dev;
687 	int ret;
688 
689 	/*
690 	 * The gm12u320 presents itself to the system as 2 usb mass-storage
691 	 * interfaces, we only care about / need the first one.
692 	 */
693 	if (interface->cur_altsetting->desc.bInterfaceNumber != 0)
694 		return -ENODEV;
695 
696 	gm12u320 = kzalloc(sizeof(*gm12u320), GFP_KERNEL);
697 	if (gm12u320 == NULL)
698 		return -ENOMEM;
699 
700 	gm12u320->udev = interface_to_usbdev(interface);
701 	INIT_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
702 	mutex_init(&gm12u320->fb_update.lock);
703 	init_waitqueue_head(&gm12u320->fb_update.waitq);
704 
705 	dev = &gm12u320->dev;
706 	ret = drm_dev_init(dev, &gm12u320_drm_driver, &interface->dev);
707 	if (ret) {
708 		kfree(gm12u320);
709 		return ret;
710 	}
711 	dev->dev_private = gm12u320;
712 
713 	drm_mode_config_init(dev);
714 	dev->mode_config.min_width = GM12U320_USER_WIDTH;
715 	dev->mode_config.max_width = GM12U320_USER_WIDTH;
716 	dev->mode_config.min_height = GM12U320_HEIGHT;
717 	dev->mode_config.max_height = GM12U320_HEIGHT;
718 	dev->mode_config.funcs = &gm12u320_mode_config_funcs;
719 
720 	ret = gm12u320_usb_alloc(gm12u320);
721 	if (ret)
722 		goto err_put;
723 
724 	ret = gm12u320_set_ecomode(gm12u320);
725 	if (ret)
726 		goto err_put;
727 
728 	ret = gm12u320_conn_init(gm12u320);
729 	if (ret)
730 		goto err_put;
731 
732 	ret = drm_simple_display_pipe_init(&gm12u320->dev,
733 					   &gm12u320->pipe,
734 					   &gm12u320_pipe_funcs,
735 					   gm12u320_pipe_formats,
736 					   ARRAY_SIZE(gm12u320_pipe_formats),
737 					   gm12u320_pipe_modifiers,
738 					   &gm12u320->conn);
739 	if (ret)
740 		goto err_put;
741 
742 	drm_mode_config_reset(dev);
743 
744 	usb_set_intfdata(interface, dev);
745 	ret = drm_dev_register(dev, 0);
746 	if (ret)
747 		goto err_put;
748 
749 	drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
750 
751 	return 0;
752 
753 err_put:
754 	drm_dev_put(dev);
755 	return ret;
756 }
757 
758 static void gm12u320_usb_disconnect(struct usb_interface *interface)
759 {
760 	struct drm_device *dev = usb_get_intfdata(interface);
761 	struct gm12u320_device *gm12u320 = dev->dev_private;
762 
763 	gm12u320_stop_fb_update(gm12u320);
764 	drm_dev_unplug(dev);
765 	drm_dev_put(dev);
766 }
767 
768 #ifdef CONFIG_PM
769 static int gm12u320_suspend(struct usb_interface *interface,
770 			    pm_message_t message)
771 {
772 	struct drm_device *dev = usb_get_intfdata(interface);
773 	struct gm12u320_device *gm12u320 = dev->dev_private;
774 
775 	if (gm12u320->pipe_enabled)
776 		gm12u320_stop_fb_update(gm12u320);
777 
778 	return 0;
779 }
780 
781 static int gm12u320_resume(struct usb_interface *interface)
782 {
783 	struct drm_device *dev = usb_get_intfdata(interface);
784 	struct gm12u320_device *gm12u320 = dev->dev_private;
785 
786 	gm12u320_set_ecomode(gm12u320);
787 	if (gm12u320->pipe_enabled)
788 		gm12u320_start_fb_update(gm12u320);
789 
790 	return 0;
791 }
792 #endif
793 
794 static const struct usb_device_id id_table[] = {
795 	{ USB_DEVICE(0x1de1, 0xc102) },
796 	{},
797 };
798 MODULE_DEVICE_TABLE(usb, id_table);
799 
800 static struct usb_driver gm12u320_usb_driver = {
801 	.name = "gm12u320",
802 	.probe = gm12u320_usb_probe,
803 	.disconnect = gm12u320_usb_disconnect,
804 	.id_table = id_table,
805 #ifdef CONFIG_PM
806 	.suspend = gm12u320_suspend,
807 	.resume = gm12u320_resume,
808 	.reset_resume = gm12u320_resume,
809 #endif
810 };
811 
812 module_usb_driver(gm12u320_usb_driver);
813 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
814 MODULE_LICENSE("GPL");
815