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