1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2019 Hans de Goede <hdegoede@redhat.com> 4 */ 5 6 #include <linux/dma-buf.h> 7 #include <linux/module.h> 8 #include <linux/usb.h> 9 10 #include <drm/drm_atomic_helper.h> 11 #include <drm/drm_atomic_state_helper.h> 12 #include <drm/drm_connector.h> 13 #include <drm/drm_damage_helper.h> 14 #include <drm/drm_drv.h> 15 #include <drm/drm_fb_helper.h> 16 #include <drm/drm_file.h> 17 #include <drm/drm_format_helper.h> 18 #include <drm/drm_fourcc.h> 19 #include <drm/drm_gem_shmem_helper.h> 20 #include <drm/drm_gem_framebuffer_helper.h> 21 #include <drm/drm_ioctl.h> 22 #include <drm/drm_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 <hdegoede@redhat.com>"); 795 MODULE_LICENSE("GPL"); 796