1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2012 Red Hat 4 * 5 * based in parts on udlfb.c: 6 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it> 7 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> 8 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> 9 */ 10 11 #include <linux/bitfield.h> 12 13 #include <drm/drm_atomic.h> 14 #include <drm/drm_atomic_helper.h> 15 #include <drm/drm_crtc_helper.h> 16 #include <drm/drm_damage_helper.h> 17 #include <drm/drm_drv.h> 18 #include <drm/drm_edid.h> 19 #include <drm/drm_fourcc.h> 20 #include <drm/drm_gem_atomic_helper.h> 21 #include <drm/drm_gem_framebuffer_helper.h> 22 #include <drm/drm_gem_shmem_helper.h> 23 #include <drm/drm_modeset_helper_vtables.h> 24 #include <drm/drm_probe_helper.h> 25 #include <drm/drm_vblank.h> 26 27 #include "udl_drv.h" 28 #include "udl_proto.h" 29 30 /* 31 * All DisplayLink bulk operations start with 0xaf (UDL_MSG_BULK), followed by 32 * a specific command code. All operations are written to a command buffer, which 33 * the driver sends to the device. 34 */ 35 static char *udl_set_register(char *buf, u8 reg, u8 val) 36 { 37 *buf++ = UDL_MSG_BULK; 38 *buf++ = UDL_CMD_WRITEREG; 39 *buf++ = reg; 40 *buf++ = val; 41 42 return buf; 43 } 44 45 static char *udl_vidreg_lock(char *buf) 46 { 47 return udl_set_register(buf, UDL_REG_VIDREG, UDL_VIDREG_LOCK); 48 } 49 50 static char *udl_vidreg_unlock(char *buf) 51 { 52 return udl_set_register(buf, UDL_REG_VIDREG, UDL_VIDREG_UNLOCK); 53 } 54 55 static char *udl_set_blank_mode(char *buf, u8 mode) 56 { 57 return udl_set_register(buf, UDL_REG_BLANKMODE, mode); 58 } 59 60 static char *udl_set_color_depth(char *buf, u8 selection) 61 { 62 return udl_set_register(buf, UDL_REG_COLORDEPTH, selection); 63 } 64 65 static char *udl_set_base16bpp(char *buf, u32 base) 66 { 67 /* the base pointer is 24 bits wide, 0x20 is hi byte. */ 68 u8 reg20 = FIELD_GET(UDL_BASE_ADDR2_MASK, base); 69 u8 reg21 = FIELD_GET(UDL_BASE_ADDR1_MASK, base); 70 u8 reg22 = FIELD_GET(UDL_BASE_ADDR0_MASK, base); 71 72 buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR2, reg20); 73 buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR1, reg21); 74 buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR0, reg22); 75 76 return buf; 77 } 78 79 /* 80 * DisplayLink HW has separate 16bpp and 8bpp framebuffers. 81 * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer 82 */ 83 static char *udl_set_base8bpp(char *buf, u32 base) 84 { 85 /* the base pointer is 24 bits wide, 0x26 is hi byte. */ 86 u8 reg26 = FIELD_GET(UDL_BASE_ADDR2_MASK, base); 87 u8 reg27 = FIELD_GET(UDL_BASE_ADDR1_MASK, base); 88 u8 reg28 = FIELD_GET(UDL_BASE_ADDR0_MASK, base); 89 90 buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR2, reg26); 91 buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR1, reg27); 92 buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR0, reg28); 93 94 return buf; 95 } 96 97 static char *udl_set_register_16(char *wrptr, u8 reg, u16 value) 98 { 99 wrptr = udl_set_register(wrptr, reg, value >> 8); 100 return udl_set_register(wrptr, reg+1, value); 101 } 102 103 /* 104 * This is kind of weird because the controller takes some 105 * register values in a different byte order than other registers. 106 */ 107 static char *udl_set_register_16be(char *wrptr, u8 reg, u16 value) 108 { 109 wrptr = udl_set_register(wrptr, reg, value); 110 return udl_set_register(wrptr, reg+1, value >> 8); 111 } 112 113 /* 114 * LFSR is linear feedback shift register. The reason we have this is 115 * because the display controller needs to minimize the clock depth of 116 * various counters used in the display path. So this code reverses the 117 * provided value into the lfsr16 value by counting backwards to get 118 * the value that needs to be set in the hardware comparator to get the 119 * same actual count. This makes sense once you read above a couple of 120 * times and think about it from a hardware perspective. 121 */ 122 static u16 udl_lfsr16(u16 actual_count) 123 { 124 u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */ 125 126 while (actual_count--) { 127 lv = ((lv << 1) | 128 (((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1)) 129 & 0xFFFF; 130 } 131 132 return (u16) lv; 133 } 134 135 /* 136 * This does LFSR conversion on the value that is to be written. 137 * See LFSR explanation above for more detail. 138 */ 139 static char *udl_set_register_lfsr16(char *wrptr, u8 reg, u16 value) 140 { 141 return udl_set_register_16(wrptr, reg, udl_lfsr16(value)); 142 } 143 144 /* 145 * Takes a DRM display mode and converts it into the DisplayLink 146 * equivalent register commands. 147 */ 148 static char *udl_set_display_mode(char *buf, struct drm_display_mode *mode) 149 { 150 u16 reg01 = mode->crtc_htotal - mode->crtc_hsync_start; 151 u16 reg03 = reg01 + mode->crtc_hdisplay; 152 u16 reg05 = mode->crtc_vtotal - mode->crtc_vsync_start; 153 u16 reg07 = reg05 + mode->crtc_vdisplay; 154 u16 reg09 = mode->crtc_htotal - 1; 155 u16 reg0b = 1; /* libdlo hardcodes hsync start to 1 */ 156 u16 reg0d = mode->crtc_hsync_end - mode->crtc_hsync_start + 1; 157 u16 reg0f = mode->hdisplay; 158 u16 reg11 = mode->crtc_vtotal; 159 u16 reg13 = 0; /* libdlo hardcodes vsync start to 0 */ 160 u16 reg15 = mode->crtc_vsync_end - mode->crtc_vsync_start; 161 u16 reg17 = mode->crtc_vdisplay; 162 u16 reg1b = mode->clock / 5; 163 164 buf = udl_set_register_lfsr16(buf, UDL_REG_XDISPLAYSTART, reg01); 165 buf = udl_set_register_lfsr16(buf, UDL_REG_XDISPLAYEND, reg03); 166 buf = udl_set_register_lfsr16(buf, UDL_REG_YDISPLAYSTART, reg05); 167 buf = udl_set_register_lfsr16(buf, UDL_REG_YDISPLAYEND, reg07); 168 buf = udl_set_register_lfsr16(buf, UDL_REG_XENDCOUNT, reg09); 169 buf = udl_set_register_lfsr16(buf, UDL_REG_HSYNCSTART, reg0b); 170 buf = udl_set_register_lfsr16(buf, UDL_REG_HSYNCEND, reg0d); 171 buf = udl_set_register_16(buf, UDL_REG_HPIXELS, reg0f); 172 buf = udl_set_register_lfsr16(buf, UDL_REG_YENDCOUNT, reg11); 173 buf = udl_set_register_lfsr16(buf, UDL_REG_VSYNCSTART, reg13); 174 buf = udl_set_register_lfsr16(buf, UDL_REG_VSYNCEND, reg15); 175 buf = udl_set_register_16(buf, UDL_REG_VPIXELS, reg17); 176 buf = udl_set_register_16be(buf, UDL_REG_PIXELCLOCK5KHZ, reg1b); 177 178 return buf; 179 } 180 181 static char *udl_dummy_render(char *wrptr) 182 { 183 *wrptr++ = UDL_MSG_BULK; 184 *wrptr++ = UDL_CMD_WRITECOPY16; 185 *wrptr++ = 0x00; /* from addr */ 186 *wrptr++ = 0x00; 187 *wrptr++ = 0x00; 188 *wrptr++ = 0x01; /* one pixel */ 189 *wrptr++ = 0x00; /* to address */ 190 *wrptr++ = 0x00; 191 *wrptr++ = 0x00; 192 return wrptr; 193 } 194 195 static long udl_log_cpp(unsigned int cpp) 196 { 197 if (WARN_ON(!is_power_of_2(cpp))) 198 return -EINVAL; 199 return __ffs(cpp); 200 } 201 202 static int udl_handle_damage(struct drm_framebuffer *fb, 203 const struct iosys_map *map, 204 const struct drm_rect *clip) 205 { 206 struct drm_device *dev = fb->dev; 207 void *vaddr = map->vaddr; /* TODO: Use mapping abstraction properly */ 208 int i, ret; 209 char *cmd; 210 struct urb *urb; 211 int log_bpp; 212 213 ret = udl_log_cpp(fb->format->cpp[0]); 214 if (ret < 0) 215 return ret; 216 log_bpp = ret; 217 218 urb = udl_get_urb(dev); 219 if (!urb) 220 return -ENOMEM; 221 cmd = urb->transfer_buffer; 222 223 for (i = clip->y1; i < clip->y2; i++) { 224 const int line_offset = fb->pitches[0] * i; 225 const int byte_offset = line_offset + (clip->x1 << log_bpp); 226 const int dev_byte_offset = (fb->width * i + clip->x1) << log_bpp; 227 const int byte_width = drm_rect_width(clip) << log_bpp; 228 ret = udl_render_hline(dev, log_bpp, &urb, (char *)vaddr, 229 &cmd, byte_offset, dev_byte_offset, 230 byte_width); 231 if (ret) 232 return ret; 233 } 234 235 if (cmd > (char *)urb->transfer_buffer) { 236 /* Send partial buffer remaining before exiting */ 237 int len; 238 if (cmd < (char *)urb->transfer_buffer + urb->transfer_buffer_length) 239 *cmd++ = UDL_MSG_BULK; 240 len = cmd - (char *)urb->transfer_buffer; 241 ret = udl_submit_urb(dev, urb, len); 242 } else { 243 udl_urb_completion(urb); 244 } 245 246 return 0; 247 } 248 249 /* 250 * Primary plane 251 */ 252 253 static const uint32_t udl_primary_plane_formats[] = { 254 DRM_FORMAT_RGB565, 255 DRM_FORMAT_XRGB8888, 256 }; 257 258 static const uint64_t udl_primary_plane_fmtmods[] = { 259 DRM_FORMAT_MOD_LINEAR, 260 DRM_FORMAT_MOD_INVALID 261 }; 262 263 static int udl_primary_plane_helper_atomic_check(struct drm_plane *plane, 264 struct drm_atomic_state *state) 265 { 266 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 267 struct drm_crtc *new_crtc = new_plane_state->crtc; 268 struct drm_crtc_state *new_crtc_state = NULL; 269 270 if (new_crtc) 271 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); 272 273 return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, 274 DRM_PLANE_NO_SCALING, 275 DRM_PLANE_NO_SCALING, 276 false, false); 277 } 278 279 static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane, 280 struct drm_atomic_state *state) 281 { 282 struct drm_device *dev = plane->dev; 283 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); 284 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 285 struct drm_framebuffer *fb = plane_state->fb; 286 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); 287 struct drm_atomic_helper_damage_iter iter; 288 struct drm_rect damage; 289 int ret, idx; 290 291 if (!fb) 292 return; /* no framebuffer; plane is disabled */ 293 294 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); 295 if (ret) 296 return; 297 298 if (!drm_dev_enter(dev, &idx)) 299 goto out_drm_gem_fb_end_cpu_access; 300 301 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); 302 drm_atomic_for_each_plane_damage(&iter, &damage) { 303 udl_handle_damage(fb, &shadow_plane_state->data[0], &damage); 304 } 305 306 drm_dev_exit(idx); 307 308 out_drm_gem_fb_end_cpu_access: 309 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); 310 } 311 312 static const struct drm_plane_helper_funcs udl_primary_plane_helper_funcs = { 313 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 314 .atomic_check = udl_primary_plane_helper_atomic_check, 315 .atomic_update = udl_primary_plane_helper_atomic_update, 316 }; 317 318 static const struct drm_plane_funcs udl_primary_plane_funcs = { 319 .update_plane = drm_atomic_helper_update_plane, 320 .disable_plane = drm_atomic_helper_disable_plane, 321 .destroy = drm_plane_cleanup, 322 DRM_GEM_SHADOW_PLANE_FUNCS, 323 }; 324 325 /* 326 * CRTC 327 */ 328 329 static void udl_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) 330 { 331 struct drm_device *dev = crtc->dev; 332 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 333 struct drm_display_mode *mode = &crtc_state->mode; 334 struct urb *urb; 335 char *buf; 336 int idx; 337 338 if (!drm_dev_enter(dev, &idx)) 339 return; 340 341 urb = udl_get_urb(dev); 342 if (!urb) 343 goto out; 344 345 buf = (char *)urb->transfer_buffer; 346 buf = udl_vidreg_lock(buf); 347 buf = udl_set_color_depth(buf, UDL_COLORDEPTH_16BPP); 348 /* set base for 16bpp segment to 0 */ 349 buf = udl_set_base16bpp(buf, 0); 350 /* set base for 8bpp segment to end of fb */ 351 buf = udl_set_base8bpp(buf, 2 * mode->vdisplay * mode->hdisplay); 352 buf = udl_set_display_mode(buf, mode); 353 buf = udl_set_blank_mode(buf, UDL_BLANKMODE_ON); 354 buf = udl_vidreg_unlock(buf); 355 buf = udl_dummy_render(buf); 356 357 udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); 358 359 out: 360 drm_dev_exit(idx); 361 } 362 363 static void udl_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) 364 { 365 struct drm_device *dev = crtc->dev; 366 struct urb *urb; 367 char *buf; 368 int idx; 369 370 if (!drm_dev_enter(dev, &idx)) 371 return; 372 373 urb = udl_get_urb(dev); 374 if (!urb) 375 goto out; 376 377 buf = (char *)urb->transfer_buffer; 378 buf = udl_vidreg_lock(buf); 379 buf = udl_set_blank_mode(buf, UDL_BLANKMODE_POWERDOWN); 380 buf = udl_vidreg_unlock(buf); 381 buf = udl_dummy_render(buf); 382 383 udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); 384 385 out: 386 drm_dev_exit(idx); 387 } 388 389 static const struct drm_crtc_helper_funcs udl_crtc_helper_funcs = { 390 .atomic_check = drm_crtc_helper_atomic_check, 391 .atomic_enable = udl_crtc_helper_atomic_enable, 392 .atomic_disable = udl_crtc_helper_atomic_disable, 393 }; 394 395 static const struct drm_crtc_funcs udl_crtc_funcs = { 396 .reset = drm_atomic_helper_crtc_reset, 397 .destroy = drm_crtc_cleanup, 398 .set_config = drm_atomic_helper_set_config, 399 .page_flip = drm_atomic_helper_page_flip, 400 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 401 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 402 }; 403 404 /* 405 * Encoder 406 */ 407 408 static const struct drm_encoder_funcs udl_encoder_funcs = { 409 .destroy = drm_encoder_cleanup, 410 }; 411 412 /* 413 * Connector 414 */ 415 416 static int udl_connector_helper_get_modes(struct drm_connector *connector) 417 { 418 struct udl_connector *udl_connector = to_udl_connector(connector); 419 420 drm_connector_update_edid_property(connector, udl_connector->edid); 421 if (udl_connector->edid) 422 return drm_add_edid_modes(connector, udl_connector->edid); 423 424 return 0; 425 } 426 427 static const struct drm_connector_helper_funcs udl_connector_helper_funcs = { 428 .get_modes = udl_connector_helper_get_modes, 429 }; 430 431 static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) 432 { 433 struct udl_device *udl = data; 434 struct drm_device *dev = &udl->drm; 435 struct usb_device *udev = udl_to_usb_device(udl); 436 u8 *read_buff; 437 int ret; 438 size_t i; 439 440 read_buff = kmalloc(2, GFP_KERNEL); 441 if (!read_buff) 442 return -ENOMEM; 443 444 for (i = 0; i < len; i++) { 445 int bval = (i + block * EDID_LENGTH) << 8; 446 447 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 448 0x02, (0x80 | (0x02 << 5)), bval, 449 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT); 450 if (ret < 0) { 451 drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret); 452 goto err_kfree; 453 } else if (ret < 1) { 454 ret = -EIO; 455 drm_err(dev, "Read EDID byte %zu failed\n", i); 456 goto err_kfree; 457 } 458 459 buf[i] = read_buff[1]; 460 } 461 462 kfree(read_buff); 463 464 return 0; 465 466 err_kfree: 467 kfree(read_buff); 468 return ret; 469 } 470 471 static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force) 472 { 473 struct drm_device *dev = connector->dev; 474 struct udl_device *udl = to_udl(dev); 475 struct udl_connector *udl_connector = to_udl_connector(connector); 476 enum drm_connector_status status = connector_status_disconnected; 477 int idx; 478 479 /* cleanup previous EDID */ 480 kfree(udl_connector->edid); 481 udl_connector->edid = NULL; 482 483 if (!drm_dev_enter(dev, &idx)) 484 return connector_status_disconnected; 485 486 udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl); 487 if (udl_connector->edid) 488 status = connector_status_connected; 489 490 drm_dev_exit(idx); 491 492 return status; 493 } 494 495 static void udl_connector_destroy(struct drm_connector *connector) 496 { 497 struct udl_connector *udl_connector = to_udl_connector(connector); 498 499 drm_connector_cleanup(connector); 500 kfree(udl_connector->edid); 501 kfree(udl_connector); 502 } 503 504 static const struct drm_connector_funcs udl_connector_funcs = { 505 .reset = drm_atomic_helper_connector_reset, 506 .detect = udl_connector_detect, 507 .fill_modes = drm_helper_probe_single_connector_modes, 508 .destroy = udl_connector_destroy, 509 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 510 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 511 }; 512 513 struct drm_connector *udl_connector_init(struct drm_device *dev) 514 { 515 struct udl_connector *udl_connector; 516 struct drm_connector *connector; 517 int ret; 518 519 udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL); 520 if (!udl_connector) 521 return ERR_PTR(-ENOMEM); 522 523 connector = &udl_connector->connector; 524 ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA); 525 if (ret) 526 goto err_kfree; 527 528 drm_connector_helper_add(connector, &udl_connector_helper_funcs); 529 530 connector->polled = DRM_CONNECTOR_POLL_HPD | 531 DRM_CONNECTOR_POLL_CONNECT | 532 DRM_CONNECTOR_POLL_DISCONNECT; 533 534 return connector; 535 536 err_kfree: 537 kfree(udl_connector); 538 return ERR_PTR(ret); 539 } 540 541 /* 542 * Modesetting 543 */ 544 545 static enum drm_mode_status udl_mode_config_mode_valid(struct drm_device *dev, 546 const struct drm_display_mode *mode) 547 { 548 struct udl_device *udl = to_udl(dev); 549 550 if (udl->sku_pixel_limit) { 551 if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) 552 return MODE_MEM; 553 } 554 555 return MODE_OK; 556 } 557 558 static const struct drm_mode_config_funcs udl_mode_config_funcs = { 559 .fb_create = drm_gem_fb_create_with_dirty, 560 .mode_valid = udl_mode_config_mode_valid, 561 .atomic_check = drm_atomic_helper_check, 562 .atomic_commit = drm_atomic_helper_commit, 563 }; 564 565 int udl_modeset_init(struct drm_device *dev) 566 { 567 struct udl_device *udl = to_udl(dev); 568 struct drm_plane *primary_plane; 569 struct drm_crtc *crtc; 570 struct drm_encoder *encoder; 571 struct drm_connector *connector; 572 int ret; 573 574 ret = drmm_mode_config_init(dev); 575 if (ret) 576 return ret; 577 578 dev->mode_config.min_width = 640; 579 dev->mode_config.min_height = 480; 580 dev->mode_config.max_width = 2048; 581 dev->mode_config.max_height = 2048; 582 dev->mode_config.preferred_depth = 16; 583 dev->mode_config.funcs = &udl_mode_config_funcs; 584 585 primary_plane = &udl->primary_plane; 586 ret = drm_universal_plane_init(dev, primary_plane, 0, 587 &udl_primary_plane_funcs, 588 udl_primary_plane_formats, 589 ARRAY_SIZE(udl_primary_plane_formats), 590 udl_primary_plane_fmtmods, 591 DRM_PLANE_TYPE_PRIMARY, NULL); 592 if (ret) 593 return ret; 594 drm_plane_helper_add(primary_plane, &udl_primary_plane_helper_funcs); 595 drm_plane_enable_fb_damage_clips(primary_plane); 596 597 crtc = &udl->crtc; 598 ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, 599 &udl_crtc_funcs, NULL); 600 if (ret) 601 return ret; 602 drm_crtc_helper_add(crtc, &udl_crtc_helper_funcs); 603 604 encoder = &udl->encoder; 605 ret = drm_encoder_init(dev, encoder, &udl_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL); 606 if (ret) 607 return ret; 608 encoder->possible_crtcs = drm_crtc_mask(crtc); 609 610 connector = udl_connector_init(dev); 611 if (IS_ERR(connector)) 612 return PTR_ERR(connector); 613 ret = drm_connector_attach_encoder(connector, encoder); 614 if (ret) 615 return ret; 616 617 drm_mode_config_reset(dev); 618 619 return 0; 620 } 621