Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux into drm...
[linux-2.6-microblaze.git] / drivers / gpu / drm / tiny / gm12u320.c
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");