Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2019 Hans de Goede <hdegoede@redhat.com>
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/usb.h>
0008 
0009 #include <drm/drm_atomic_helper.h>
0010 #include <drm/drm_atomic_state_helper.h>
0011 #include <drm/drm_connector.h>
0012 #include <drm/drm_damage_helper.h>
0013 #include <drm/drm_drv.h>
0014 #include <drm/drm_edid.h>
0015 #include <drm/drm_fb_helper.h>
0016 #include <drm/drm_file.h>
0017 #include <drm/drm_format_helper.h>
0018 #include <drm/drm_fourcc.h>
0019 #include <drm/drm_framebuffer.h>
0020 #include <drm/drm_gem_atomic_helper.h>
0021 #include <drm/drm_gem_framebuffer_helper.h>
0022 #include <drm/drm_gem_shmem_helper.h>
0023 #include <drm/drm_ioctl.h>
0024 #include <drm/drm_managed.h>
0025 #include <drm/drm_modeset_helper_vtables.h>
0026 #include <drm/drm_probe_helper.h>
0027 #include <drm/drm_simple_kms_helper.h>
0028 
0029 static bool eco_mode;
0030 module_param(eco_mode, bool, 0644);
0031 MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
0032 
0033 #define DRIVER_NAME     "gm12u320"
0034 #define DRIVER_DESC     "Grain Media GM12U320 USB projector display"
0035 #define DRIVER_DATE     "2019"
0036 #define DRIVER_MAJOR        1
0037 #define DRIVER_MINOR        0
0038 
0039 /*
0040  * The DLP has an actual width of 854 pixels, but that is not a multiple
0041  * of 8, breaking things left and right, so we export a width of 848.
0042  */
0043 #define GM12U320_USER_WIDTH     848
0044 #define GM12U320_REAL_WIDTH     854
0045 #define GM12U320_HEIGHT         480
0046 
0047 #define GM12U320_BLOCK_COUNT        20
0048 
0049 #define GM12U320_ERR(fmt, ...) \
0050     DRM_DEV_ERROR(gm12u320->dev.dev, fmt, ##__VA_ARGS__)
0051 
0052 #define MISC_RCV_EPT            1
0053 #define DATA_RCV_EPT            2
0054 #define DATA_SND_EPT            3
0055 #define MISC_SND_EPT            4
0056 
0057 #define DATA_BLOCK_HEADER_SIZE      84
0058 #define DATA_BLOCK_CONTENT_SIZE     64512
0059 #define DATA_BLOCK_FOOTER_SIZE      20
0060 #define DATA_BLOCK_SIZE         (DATA_BLOCK_HEADER_SIZE + \
0061                      DATA_BLOCK_CONTENT_SIZE + \
0062                      DATA_BLOCK_FOOTER_SIZE)
0063 #define DATA_LAST_BLOCK_CONTENT_SIZE    4032
0064 #define DATA_LAST_BLOCK_SIZE        (DATA_BLOCK_HEADER_SIZE + \
0065                      DATA_LAST_BLOCK_CONTENT_SIZE + \
0066                      DATA_BLOCK_FOOTER_SIZE)
0067 
0068 #define CMD_SIZE            31
0069 #define READ_STATUS_SIZE        13
0070 #define MISC_VALUE_SIZE         4
0071 
0072 #define CMD_TIMEOUT         msecs_to_jiffies(200)
0073 #define DATA_TIMEOUT            msecs_to_jiffies(1000)
0074 #define IDLE_TIMEOUT            msecs_to_jiffies(2000)
0075 #define FIRST_FRAME_TIMEOUT     msecs_to_jiffies(2000)
0076 
0077 #define MISC_REQ_GET_SET_ECO_A      0xff
0078 #define MISC_REQ_GET_SET_ECO_B      0x35
0079 /* Windows driver does once every second, with arg d = 1, other args 0 */
0080 #define MISC_REQ_UNKNOWN1_A     0xff
0081 #define MISC_REQ_UNKNOWN1_B     0x38
0082 /* Windows driver does this on init, with arg a, b = 0, c = 0xa0, d = 4 */
0083 #define MISC_REQ_UNKNOWN2_A     0xa5
0084 #define MISC_REQ_UNKNOWN2_B     0x00
0085 
0086 struct gm12u320_device {
0087     struct drm_device            dev;
0088     struct device                   *dmadev;
0089     struct drm_simple_display_pipe   pipe;
0090     struct drm_connector             conn;
0091     unsigned char                   *cmd_buf;
0092     unsigned char                   *data_buf[GM12U320_BLOCK_COUNT];
0093     struct {
0094         struct delayed_work       work;
0095         struct mutex             lock;
0096         struct drm_framebuffer  *fb;
0097         struct drm_rect          rect;
0098         int frame;
0099         int draw_status_timeout;
0100         struct iosys_map src_map;
0101     } fb_update;
0102 };
0103 
0104 #define to_gm12u320(__dev) container_of(__dev, struct gm12u320_device, dev)
0105 
0106 static const char cmd_data[CMD_SIZE] = {
0107     0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
0108     0x68, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff,
0109     0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x80, 0x00,
0110     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0111 };
0112 
0113 static const char cmd_draw[CMD_SIZE] = {
0114     0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
0115     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe,
0116     0x00, 0x00, 0x00, 0xc0, 0xd1, 0x05, 0x00, 0x40,
0117     0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
0118 };
0119 
0120 static const char cmd_misc[CMD_SIZE] = {
0121     0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
0122     0x04, 0x00, 0x00, 0x00, 0x80, 0x01, 0x10, 0xfd,
0123     0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
0124     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0125 };
0126 
0127 static const char data_block_header[DATA_BLOCK_HEADER_SIZE] = {
0128     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0129     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0130     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0131     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0132     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0133     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0134     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0135     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0136     0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0137     0x00, 0x04, 0x15, 0x00, 0x00, 0xfc, 0x00, 0x00,
0138     0x01, 0x00, 0x00, 0xdb
0139 };
0140 
0141 static const char data_last_block_header[DATA_BLOCK_HEADER_SIZE] = {
0142     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0143     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0144     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0145     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0146     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0147     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0148     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0149     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0150     0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0151     0x2a, 0x00, 0x20, 0x00, 0xc0, 0x0f, 0x00, 0x00,
0152     0x01, 0x00, 0x00, 0xd7
0153 };
0154 
0155 static const char data_block_footer[DATA_BLOCK_FOOTER_SIZE] = {
0156     0xfb, 0x14, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
0157     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0158     0x80, 0x00, 0x00, 0x4f
0159 };
0160 
0161 static inline struct usb_device *gm12u320_to_usb_device(struct gm12u320_device *gm12u320)
0162 {
0163     return interface_to_usbdev(to_usb_interface(gm12u320->dev.dev));
0164 }
0165 
0166 static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320)
0167 {
0168     int i, block_size;
0169     const char *hdr;
0170 
0171     gm12u320->cmd_buf = drmm_kmalloc(&gm12u320->dev, CMD_SIZE, GFP_KERNEL);
0172     if (!gm12u320->cmd_buf)
0173         return -ENOMEM;
0174 
0175     for (i = 0; i < GM12U320_BLOCK_COUNT; i++) {
0176         if (i == GM12U320_BLOCK_COUNT - 1) {
0177             block_size = DATA_LAST_BLOCK_SIZE;
0178             hdr = data_last_block_header;
0179         } else {
0180             block_size = DATA_BLOCK_SIZE;
0181             hdr = data_block_header;
0182         }
0183 
0184         gm12u320->data_buf[i] = drmm_kzalloc(&gm12u320->dev,
0185                              block_size, GFP_KERNEL);
0186         if (!gm12u320->data_buf[i])
0187             return -ENOMEM;
0188 
0189         memcpy(gm12u320->data_buf[i], hdr, DATA_BLOCK_HEADER_SIZE);
0190         memcpy(gm12u320->data_buf[i] +
0191                 (block_size - DATA_BLOCK_FOOTER_SIZE),
0192                data_block_footer, DATA_BLOCK_FOOTER_SIZE);
0193     }
0194 
0195     return 0;
0196 }
0197 
0198 static int gm12u320_misc_request(struct gm12u320_device *gm12u320,
0199                  u8 req_a, u8 req_b,
0200                  u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d)
0201 {
0202     struct usb_device *udev = gm12u320_to_usb_device(gm12u320);
0203     int ret, len;
0204 
0205     memcpy(gm12u320->cmd_buf, &cmd_misc, CMD_SIZE);
0206     gm12u320->cmd_buf[20] = req_a;
0207     gm12u320->cmd_buf[21] = req_b;
0208     gm12u320->cmd_buf[22] = arg_a;
0209     gm12u320->cmd_buf[23] = arg_b;
0210     gm12u320->cmd_buf[24] = arg_c;
0211     gm12u320->cmd_buf[25] = arg_d;
0212 
0213     /* Send request */
0214     ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, MISC_SND_EPT),
0215                gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
0216     if (ret || len != CMD_SIZE) {
0217         GM12U320_ERR("Misc. req. error %d\n", ret);
0218         return -EIO;
0219     }
0220 
0221     /* Read value */
0222     ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, MISC_RCV_EPT),
0223                gm12u320->cmd_buf, MISC_VALUE_SIZE, &len,
0224                DATA_TIMEOUT);
0225     if (ret || len != MISC_VALUE_SIZE) {
0226         GM12U320_ERR("Misc. value error %d\n", ret);
0227         return -EIO;
0228     }
0229     /* cmd_buf[0] now contains the read value, which we don't use */
0230 
0231     /* Read status */
0232     ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, MISC_RCV_EPT),
0233                gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
0234                CMD_TIMEOUT);
0235     if (ret || len != READ_STATUS_SIZE) {
0236         GM12U320_ERR("Misc. status error %d\n", ret);
0237         return -EIO;
0238     }
0239 
0240     return 0;
0241 }
0242 
0243 static void gm12u320_32bpp_to_24bpp_packed(u8 *dst, u8 *src, int len)
0244 {
0245     while (len--) {
0246         *dst++ = *src++;
0247         *dst++ = *src++;
0248         *dst++ = *src++;
0249         src++;
0250     }
0251 }
0252 
0253 static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
0254 {
0255     int block, dst_offset, len, remain, ret, x1, x2, y1, y2;
0256     struct drm_framebuffer *fb;
0257     void *vaddr;
0258     u8 *src;
0259 
0260     mutex_lock(&gm12u320->fb_update.lock);
0261 
0262     if (!gm12u320->fb_update.fb)
0263         goto unlock;
0264 
0265     fb = gm12u320->fb_update.fb;
0266     x1 = gm12u320->fb_update.rect.x1;
0267     x2 = gm12u320->fb_update.rect.x2;
0268     y1 = gm12u320->fb_update.rect.y1;
0269     y2 = gm12u320->fb_update.rect.y2;
0270     vaddr = gm12u320->fb_update.src_map.vaddr; /* TODO: Use mapping abstraction properly */
0271 
0272     ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
0273     if (ret) {
0274         GM12U320_ERR("drm_gem_fb_begin_cpu_access err: %d\n", ret);
0275         goto put_fb;
0276     }
0277 
0278     src = vaddr + y1 * fb->pitches[0] + x1 * 4;
0279 
0280     x1 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
0281     x2 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
0282 
0283     for (; y1 < y2; y1++) {
0284         remain = 0;
0285         len = (x2 - x1) * 3;
0286         dst_offset = (y1 * GM12U320_REAL_WIDTH + x1) * 3;
0287         block = dst_offset / DATA_BLOCK_CONTENT_SIZE;
0288         dst_offset %= DATA_BLOCK_CONTENT_SIZE;
0289 
0290         if ((dst_offset + len) > DATA_BLOCK_CONTENT_SIZE) {
0291             remain = dst_offset + len - DATA_BLOCK_CONTENT_SIZE;
0292             len = DATA_BLOCK_CONTENT_SIZE - dst_offset;
0293         }
0294 
0295         dst_offset += DATA_BLOCK_HEADER_SIZE;
0296         len /= 3;
0297 
0298         gm12u320_32bpp_to_24bpp_packed(
0299             gm12u320->data_buf[block] + dst_offset,
0300             src, len);
0301 
0302         if (remain) {
0303             block++;
0304             dst_offset = DATA_BLOCK_HEADER_SIZE;
0305             gm12u320_32bpp_to_24bpp_packed(
0306                 gm12u320->data_buf[block] + dst_offset,
0307                 src + len * 4, remain / 3);
0308         }
0309         src += fb->pitches[0];
0310     }
0311 
0312     drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
0313 put_fb:
0314     drm_framebuffer_put(fb);
0315     gm12u320->fb_update.fb = NULL;
0316 unlock:
0317     mutex_unlock(&gm12u320->fb_update.lock);
0318 }
0319 
0320 static void gm12u320_fb_update_work(struct work_struct *work)
0321 {
0322     struct gm12u320_device *gm12u320 =
0323         container_of(to_delayed_work(work), struct gm12u320_device,
0324                  fb_update.work);
0325     struct usb_device *udev = gm12u320_to_usb_device(gm12u320);
0326     int block, block_size, len;
0327     int ret = 0;
0328 
0329     gm12u320_copy_fb_to_blocks(gm12u320);
0330 
0331     for (block = 0; block < GM12U320_BLOCK_COUNT; block++) {
0332         if (block == GM12U320_BLOCK_COUNT - 1)
0333             block_size = DATA_LAST_BLOCK_SIZE;
0334         else
0335             block_size = DATA_BLOCK_SIZE;
0336 
0337         /* Send data command to device */
0338         memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE);
0339         gm12u320->cmd_buf[8] = block_size & 0xff;
0340         gm12u320->cmd_buf[9] = block_size >> 8;
0341         gm12u320->cmd_buf[20] = 0xfc - block * 4;
0342         gm12u320->cmd_buf[21] =
0343             block | (gm12u320->fb_update.frame << 7);
0344 
0345         ret = usb_bulk_msg(udev,
0346                    usb_sndbulkpipe(udev, DATA_SND_EPT),
0347                    gm12u320->cmd_buf, CMD_SIZE, &len,
0348                    CMD_TIMEOUT);
0349         if (ret || len != CMD_SIZE)
0350             goto err;
0351 
0352         /* Send data block to device */
0353         ret = usb_bulk_msg(udev,
0354                    usb_sndbulkpipe(udev, DATA_SND_EPT),
0355                    gm12u320->data_buf[block], block_size,
0356                    &len, DATA_TIMEOUT);
0357         if (ret || len != block_size)
0358             goto err;
0359 
0360         /* Read status */
0361         ret = usb_bulk_msg(udev,
0362                    usb_rcvbulkpipe(udev, DATA_RCV_EPT),
0363                    gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
0364                    CMD_TIMEOUT);
0365         if (ret || len != READ_STATUS_SIZE)
0366             goto err;
0367     }
0368 
0369     /* Send draw command to device */
0370     memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE);
0371     ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, DATA_SND_EPT),
0372                gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
0373     if (ret || len != CMD_SIZE)
0374         goto err;
0375 
0376     /* Read status */
0377     ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, DATA_RCV_EPT),
0378                gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
0379                gm12u320->fb_update.draw_status_timeout);
0380     if (ret || len != READ_STATUS_SIZE)
0381         goto err;
0382 
0383     gm12u320->fb_update.draw_status_timeout = CMD_TIMEOUT;
0384     gm12u320->fb_update.frame = !gm12u320->fb_update.frame;
0385 
0386     /*
0387      * We must draw a frame every 2s otherwise the projector
0388      * switches back to showing its logo.
0389      */
0390     queue_delayed_work(system_long_wq, &gm12u320->fb_update.work,
0391                IDLE_TIMEOUT);
0392 
0393     return;
0394 err:
0395     /* Do not log errors caused by module unload or device unplug */
0396     if (ret != -ENODEV && ret != -ECONNRESET && ret != -ESHUTDOWN)
0397         GM12U320_ERR("Frame update error: %d\n", ret);
0398 }
0399 
0400 static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb,
0401                    const struct iosys_map *map,
0402                    struct drm_rect *dirty)
0403 {
0404     struct gm12u320_device *gm12u320 = to_gm12u320(fb->dev);
0405     struct drm_framebuffer *old_fb = NULL;
0406     bool wakeup = false;
0407 
0408     mutex_lock(&gm12u320->fb_update.lock);
0409 
0410     if (gm12u320->fb_update.fb != fb) {
0411         old_fb = gm12u320->fb_update.fb;
0412         drm_framebuffer_get(fb);
0413         gm12u320->fb_update.fb = fb;
0414         gm12u320->fb_update.rect = *dirty;
0415         gm12u320->fb_update.src_map = *map;
0416         wakeup = true;
0417     } else {
0418         struct drm_rect *rect = &gm12u320->fb_update.rect;
0419 
0420         rect->x1 = min(rect->x1, dirty->x1);
0421         rect->y1 = min(rect->y1, dirty->y1);
0422         rect->x2 = max(rect->x2, dirty->x2);
0423         rect->y2 = max(rect->y2, dirty->y2);
0424     }
0425 
0426     mutex_unlock(&gm12u320->fb_update.lock);
0427 
0428     if (wakeup)
0429         mod_delayed_work(system_long_wq, &gm12u320->fb_update.work, 0);
0430 
0431     if (old_fb)
0432         drm_framebuffer_put(old_fb);
0433 }
0434 
0435 static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320)
0436 {
0437     struct drm_framebuffer *old_fb;
0438 
0439     cancel_delayed_work_sync(&gm12u320->fb_update.work);
0440 
0441     mutex_lock(&gm12u320->fb_update.lock);
0442     old_fb = gm12u320->fb_update.fb;
0443     gm12u320->fb_update.fb = NULL;
0444     iosys_map_clear(&gm12u320->fb_update.src_map);
0445     mutex_unlock(&gm12u320->fb_update.lock);
0446 
0447     drm_framebuffer_put(old_fb);
0448 }
0449 
0450 static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320)
0451 {
0452     return gm12u320_misc_request(gm12u320, MISC_REQ_GET_SET_ECO_A,
0453                      MISC_REQ_GET_SET_ECO_B, 0x01 /* set */,
0454                      eco_mode ? 0x01 : 0x00, 0x00, 0x01);
0455 }
0456 
0457 /* ------------------------------------------------------------------ */
0458 /* gm12u320 connector                             */
0459 
0460 /*
0461  * We use fake EDID info so that userspace know that it is dealing with
0462  * an Acer projector, rather then listing this as an "unknown" monitor.
0463  * Note this assumes this driver is only ever used with the Acer C120, if we
0464  * add support for other devices the vendor and model should be parameterized.
0465  */
0466 static struct edid gm12u320_edid = {
0467     .header     = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 },
0468     .mfg_id     = { 0x04, 0x72 },   /* "ACR" */
0469     .prod_code  = { 0x20, 0xc1 },   /* C120h */
0470     .serial     = 0xaa55aa55,
0471     .mfg_week   = 1,
0472     .mfg_year   = 16,
0473     .version    = 1,            /* EDID 1.3 */
0474     .revision   = 3,            /* EDID 1.3 */
0475     .input      = 0x08,         /* Analog input */
0476     .features   = 0x0a,         /* Pref timing in DTD 1 */
0477     .standard_timings = { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
0478                   { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } },
0479     .detailed_timings = { {
0480         .pixel_clock = 3383,
0481         /* hactive = 848, hblank = 256 */
0482         .data.pixel_data.hactive_lo = 0x50,
0483         .data.pixel_data.hblank_lo = 0x00,
0484         .data.pixel_data.hactive_hblank_hi = 0x31,
0485         /* vactive = 480, vblank = 28 */
0486         .data.pixel_data.vactive_lo = 0xe0,
0487         .data.pixel_data.vblank_lo = 0x1c,
0488         .data.pixel_data.vactive_vblank_hi = 0x10,
0489         /* hsync offset 40 pw 128, vsync offset 1 pw 4 */
0490         .data.pixel_data.hsync_offset_lo = 0x28,
0491         .data.pixel_data.hsync_pulse_width_lo = 0x80,
0492         .data.pixel_data.vsync_offset_pulse_width_lo = 0x14,
0493         .data.pixel_data.hsync_vsync_offset_pulse_width_hi = 0x00,
0494         /* Digital separate syncs, hsync+, vsync+ */
0495         .data.pixel_data.misc = 0x1e,
0496     }, {
0497         .pixel_clock = 0,
0498         .data.other_data.type = 0xfd, /* Monitor ranges */
0499         .data.other_data.data.range.min_vfreq = 59,
0500         .data.other_data.data.range.max_vfreq = 61,
0501         .data.other_data.data.range.min_hfreq_khz = 29,
0502         .data.other_data.data.range.max_hfreq_khz = 32,
0503         .data.other_data.data.range.pixel_clock_mhz = 4, /* 40 MHz */
0504         .data.other_data.data.range.flags = 0,
0505         .data.other_data.data.range.formula.cvt = {
0506             0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
0507     }, {
0508         .pixel_clock = 0,
0509         .data.other_data.type = 0xfc, /* Model string */
0510         .data.other_data.data.str.str = {
0511             'P', 'r', 'o', 'j', 'e', 'c', 't', 'o', 'r', '\n',
0512             ' ', ' ',  ' ' },
0513     }, {
0514         .pixel_clock = 0,
0515         .data.other_data.type = 0xfe, /* Unspecified text / padding */
0516         .data.other_data.data.str.str = {
0517             '\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
0518             ' ', ' ',  ' ' },
0519     } },
0520     .checksum = 0x13,
0521 };
0522 
0523 static int gm12u320_conn_get_modes(struct drm_connector *connector)
0524 {
0525     drm_connector_update_edid_property(connector, &gm12u320_edid);
0526     return drm_add_edid_modes(connector, &gm12u320_edid);
0527 }
0528 
0529 static const struct drm_connector_helper_funcs gm12u320_conn_helper_funcs = {
0530     .get_modes = gm12u320_conn_get_modes,
0531 };
0532 
0533 static const struct drm_connector_funcs gm12u320_conn_funcs = {
0534     .fill_modes = drm_helper_probe_single_connector_modes,
0535     .destroy = drm_connector_cleanup,
0536     .reset = drm_atomic_helper_connector_reset,
0537     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0538     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0539 };
0540 
0541 static int gm12u320_conn_init(struct gm12u320_device *gm12u320)
0542 {
0543     drm_connector_helper_add(&gm12u320->conn, &gm12u320_conn_helper_funcs);
0544     return drm_connector_init(&gm12u320->dev, &gm12u320->conn,
0545                   &gm12u320_conn_funcs, DRM_MODE_CONNECTOR_VGA);
0546 }
0547 
0548 /* ------------------------------------------------------------------ */
0549 /* gm12u320 (simple) display pipe                     */
0550 
0551 static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
0552                  struct drm_crtc_state *crtc_state,
0553                  struct drm_plane_state *plane_state)
0554 {
0555     struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT };
0556     struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev);
0557     struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
0558 
0559     gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT;
0560     gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect);
0561 }
0562 
0563 static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
0564 {
0565     struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev);
0566 
0567     gm12u320_stop_fb_update(gm12u320);
0568 }
0569 
0570 static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
0571                  struct drm_plane_state *old_state)
0572 {
0573     struct drm_plane_state *state = pipe->plane.state;
0574     struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
0575     struct drm_rect rect;
0576 
0577     if (drm_atomic_helper_damage_merged(old_state, state, &rect))
0578         gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
0579 }
0580 
0581 static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
0582     .enable     = gm12u320_pipe_enable,
0583     .disable    = gm12u320_pipe_disable,
0584     .update     = gm12u320_pipe_update,
0585     DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
0586 };
0587 
0588 static const uint32_t gm12u320_pipe_formats[] = {
0589     DRM_FORMAT_XRGB8888,
0590 };
0591 
0592 static const uint64_t gm12u320_pipe_modifiers[] = {
0593     DRM_FORMAT_MOD_LINEAR,
0594     DRM_FORMAT_MOD_INVALID
0595 };
0596 
0597 /*
0598  * FIXME: Dma-buf sharing requires DMA support by the importing device.
0599  *        This function is a workaround to make USB devices work as well.
0600  *        See todo.rst for how to fix the issue in the dma-buf framework.
0601  */
0602 static struct drm_gem_object *gm12u320_gem_prime_import(struct drm_device *dev,
0603                             struct dma_buf *dma_buf)
0604 {
0605     struct gm12u320_device *gm12u320 = to_gm12u320(dev);
0606 
0607     if (!gm12u320->dmadev)
0608         return ERR_PTR(-ENODEV);
0609 
0610     return drm_gem_prime_import_dev(dev, dma_buf, gm12u320->dmadev);
0611 }
0612 
0613 DEFINE_DRM_GEM_FOPS(gm12u320_fops);
0614 
0615 static const struct drm_driver gm12u320_drm_driver = {
0616     .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
0617 
0618     .name        = DRIVER_NAME,
0619     .desc        = DRIVER_DESC,
0620     .date        = DRIVER_DATE,
0621     .major       = DRIVER_MAJOR,
0622     .minor       = DRIVER_MINOR,
0623 
0624     .fops        = &gm12u320_fops,
0625     DRM_GEM_SHMEM_DRIVER_OPS,
0626     .gem_prime_import = gm12u320_gem_prime_import,
0627 };
0628 
0629 static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
0630     .fb_create = drm_gem_fb_create_with_dirty,
0631     .atomic_check = drm_atomic_helper_check,
0632     .atomic_commit = drm_atomic_helper_commit,
0633 };
0634 
0635 static int gm12u320_usb_probe(struct usb_interface *interface,
0636                   const struct usb_device_id *id)
0637 {
0638     struct gm12u320_device *gm12u320;
0639     struct drm_device *dev;
0640     int ret;
0641 
0642     /*
0643      * The gm12u320 presents itself to the system as 2 usb mass-storage
0644      * interfaces, we only care about / need the first one.
0645      */
0646     if (interface->cur_altsetting->desc.bInterfaceNumber != 0)
0647         return -ENODEV;
0648 
0649     gm12u320 = devm_drm_dev_alloc(&interface->dev, &gm12u320_drm_driver,
0650                       struct gm12u320_device, dev);
0651     if (IS_ERR(gm12u320))
0652         return PTR_ERR(gm12u320);
0653     dev = &gm12u320->dev;
0654 
0655     gm12u320->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
0656     if (!gm12u320->dmadev)
0657         drm_warn(dev, "buffer sharing not supported"); /* not an error */
0658 
0659     INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
0660     mutex_init(&gm12u320->fb_update.lock);
0661 
0662     ret = drmm_mode_config_init(dev);
0663     if (ret)
0664         goto err_put_device;
0665 
0666     dev->mode_config.min_width = GM12U320_USER_WIDTH;
0667     dev->mode_config.max_width = GM12U320_USER_WIDTH;
0668     dev->mode_config.min_height = GM12U320_HEIGHT;
0669     dev->mode_config.max_height = GM12U320_HEIGHT;
0670     dev->mode_config.funcs = &gm12u320_mode_config_funcs;
0671 
0672     ret = gm12u320_usb_alloc(gm12u320);
0673     if (ret)
0674         goto err_put_device;
0675 
0676     ret = gm12u320_set_ecomode(gm12u320);
0677     if (ret)
0678         goto err_put_device;
0679 
0680     ret = gm12u320_conn_init(gm12u320);
0681     if (ret)
0682         goto err_put_device;
0683 
0684     ret = drm_simple_display_pipe_init(&gm12u320->dev,
0685                        &gm12u320->pipe,
0686                        &gm12u320_pipe_funcs,
0687                        gm12u320_pipe_formats,
0688                        ARRAY_SIZE(gm12u320_pipe_formats),
0689                        gm12u320_pipe_modifiers,
0690                        &gm12u320->conn);
0691     if (ret)
0692         goto err_put_device;
0693 
0694     drm_mode_config_reset(dev);
0695 
0696     usb_set_intfdata(interface, dev);
0697     ret = drm_dev_register(dev, 0);
0698     if (ret)
0699         goto err_put_device;
0700 
0701     drm_fbdev_generic_setup(dev, 0);
0702 
0703     return 0;
0704 
0705 err_put_device:
0706     put_device(gm12u320->dmadev);
0707     return ret;
0708 }
0709 
0710 static void gm12u320_usb_disconnect(struct usb_interface *interface)
0711 {
0712     struct drm_device *dev = usb_get_intfdata(interface);
0713     struct gm12u320_device *gm12u320 = to_gm12u320(dev);
0714 
0715     put_device(gm12u320->dmadev);
0716     gm12u320->dmadev = NULL;
0717     drm_dev_unplug(dev);
0718     drm_atomic_helper_shutdown(dev);
0719 }
0720 
0721 static __maybe_unused int gm12u320_suspend(struct usb_interface *interface,
0722                        pm_message_t message)
0723 {
0724     struct drm_device *dev = usb_get_intfdata(interface);
0725 
0726     return drm_mode_config_helper_suspend(dev);
0727 }
0728 
0729 static __maybe_unused int gm12u320_resume(struct usb_interface *interface)
0730 {
0731     struct drm_device *dev = usb_get_intfdata(interface);
0732     struct gm12u320_device *gm12u320 = to_gm12u320(dev);
0733 
0734     gm12u320_set_ecomode(gm12u320);
0735 
0736     return drm_mode_config_helper_resume(dev);
0737 }
0738 
0739 static const struct usb_device_id id_table[] = {
0740     { USB_DEVICE(0x1de1, 0xc102) },
0741     {},
0742 };
0743 MODULE_DEVICE_TABLE(usb, id_table);
0744 
0745 static struct usb_driver gm12u320_usb_driver = {
0746     .name = "gm12u320",
0747     .probe = gm12u320_usb_probe,
0748     .disconnect = gm12u320_usb_disconnect,
0749     .id_table = id_table,
0750 #ifdef CONFIG_PM
0751     .suspend = gm12u320_suspend,
0752     .resume = gm12u320_resume,
0753     .reset_resume = gm12u320_resume,
0754 #endif
0755 };
0756 
0757 module_usb_driver(gm12u320_usb_driver);
0758 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0759 MODULE_LICENSE("GPL");