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