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