1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Apple Touch Bar DRM Driver 4 * 5 * Copyright (c) 2023 Kerem Karabay <kekrby@gmail.com> 6 */ 7 8 #include <linux/align.h> 9 #include <linux/array_size.h> 10 #include <linux/bitops.h> 11 #include <linux/bug.h> 12 #include <linux/container_of.h> 13 #include <linux/err.h> 14 #include <linux/module.h> 15 #include <linux/overflow.h> 16 #include <linux/slab.h> 17 #include <linux/types.h> 18 #include <linux/unaligned.h> 19 #include <linux/usb.h> 20 21 #include <drm/drm_atomic.h> 22 #include <drm/drm_atomic_helper.h> 23 #include <drm/drm_crtc.h> 24 #include <drm/drm_damage_helper.h> 25 #include <drm/drm_drv.h> 26 #include <drm/drm_encoder.h> 27 #include <drm/drm_format_helper.h> 28 #include <drm/drm_fourcc.h> 29 #include <drm/drm_framebuffer.h> 30 #include <drm/drm_gem_atomic_helper.h> 31 #include <drm/drm_gem_framebuffer_helper.h> 32 #include <drm/drm_gem_shmem_helper.h> 33 #include <drm/drm_plane.h> 34 #include <drm/drm_print.h> 35 #include <drm/drm_probe_helper.h> 36 37 #define APPLETBDRM_PIXEL_FORMAT cpu_to_le32(0x52474241) /* RGBA, the actual format is BGR888 */ 38 #define APPLETBDRM_BITS_PER_PIXEL 24 39 40 #define APPLETBDRM_MSG_CLEAR_DISPLAY cpu_to_le32(0x434c5244) /* CLRD */ 41 #define APPLETBDRM_MSG_GET_INFORMATION cpu_to_le32(0x47494e46) /* GINF */ 42 #define APPLETBDRM_MSG_UPDATE_COMPLETE cpu_to_le32(0x5544434c) /* UDCL */ 43 #define APPLETBDRM_MSG_SIGNAL_READINESS cpu_to_le32(0x52454459) /* REDY */ 44 45 #define APPLETBDRM_BULK_MSG_TIMEOUT 1000 46 47 #define drm_to_adev(_drm) container_of(_drm, struct appletbdrm_device, drm) 48 #define adev_to_udev(adev) interface_to_usbdev(to_usb_interface(adev->dmadev)) 49 50 struct appletbdrm_msg_request_header { 51 __le16 unk_00; 52 __le16 unk_02; 53 __le32 unk_04; 54 __le32 unk_08; 55 __le32 size; 56 } __packed; 57 58 struct appletbdrm_msg_response_header { 59 u8 unk_00[16]; 60 __le32 msg; 61 } __packed; 62 63 struct appletbdrm_msg_simple_request { 64 struct appletbdrm_msg_request_header header; 65 __le32 msg; 66 u8 unk_14[8]; 67 __le32 size; 68 } __packed; 69 70 struct appletbdrm_msg_information { 71 struct appletbdrm_msg_response_header header; 72 u8 unk_14[12]; 73 __le32 width; 74 __le32 height; 75 u8 bits_per_pixel; 76 __le32 bytes_per_row; 77 __le32 orientation; 78 __le32 bitmap_info; 79 __le32 pixel_format; 80 __le32 width_inches; /* floating point */ 81 __le32 height_inches; /* floating point */ 82 } __packed; 83 84 struct appletbdrm_frame { 85 __le16 begin_x; 86 __le16 begin_y; 87 __le16 width; 88 __le16 height; 89 __le32 buf_size; 90 u8 buf[]; 91 } __packed; 92 93 struct appletbdrm_fb_request_footer { 94 u8 unk_00[12]; 95 __le32 unk_0c; 96 u8 unk_10[12]; 97 __le32 unk_1c; 98 __le64 timestamp; 99 u8 unk_28[12]; 100 __le32 unk_34; 101 u8 unk_38[20]; 102 __le32 unk_4c; 103 } __packed; 104 105 struct appletbdrm_fb_request { 106 struct appletbdrm_msg_request_header header; 107 __le16 unk_10; 108 u8 msg_id; 109 u8 unk_13[29]; 110 /* 111 * Contents of `data`: 112 * - struct appletbdrm_frame frames[]; 113 * - struct appletbdrm_fb_request_footer footer; 114 * - padding to make the total size a multiple of 16 115 */ 116 u8 data[]; 117 } __packed; 118 119 struct appletbdrm_fb_request_response { 120 struct appletbdrm_msg_response_header header; 121 u8 unk_14[12]; 122 __le64 timestamp; 123 } __packed; 124 125 struct appletbdrm_device { 126 struct device *dmadev; 127 128 unsigned int in_ep; 129 unsigned int out_ep; 130 131 unsigned int width; 132 unsigned int height; 133 134 struct drm_device drm; 135 struct drm_display_mode mode; 136 struct drm_connector connector; 137 struct drm_plane primary_plane; 138 struct drm_crtc crtc; 139 struct drm_encoder encoder; 140 }; 141 142 struct appletbdrm_plane_state { 143 struct drm_shadow_plane_state base; 144 struct appletbdrm_fb_request *request; 145 struct appletbdrm_fb_request_response *response; 146 size_t request_size; 147 size_t frames_size; 148 }; 149 150 static inline struct appletbdrm_plane_state *to_appletbdrm_plane_state(struct drm_plane_state *state) 151 { 152 return container_of(state, struct appletbdrm_plane_state, base.base); 153 } 154 155 static int appletbdrm_send_request(struct appletbdrm_device *adev, 156 struct appletbdrm_msg_request_header *request, size_t size) 157 { 158 struct usb_device *udev = adev_to_udev(adev); 159 struct drm_device *drm = &adev->drm; 160 int ret, actual_size; 161 162 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, adev->out_ep), 163 request, size, &actual_size, APPLETBDRM_BULK_MSG_TIMEOUT); 164 if (ret) { 165 drm_err(drm, "Failed to send message (%d)\n", ret); 166 return ret; 167 } 168 169 if (actual_size != size) { 170 drm_err(drm, "Actual size (%d) doesn't match expected size (%zu)\n", 171 actual_size, size); 172 return -EIO; 173 } 174 175 return 0; 176 } 177 178 static int appletbdrm_read_response(struct appletbdrm_device *adev, 179 struct appletbdrm_msg_response_header *response, 180 size_t size, __le32 expected_response) 181 { 182 struct usb_device *udev = adev_to_udev(adev); 183 struct drm_device *drm = &adev->drm; 184 int ret, actual_size; 185 bool readiness_signal_received = false; 186 187 retry: 188 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, adev->in_ep), 189 response, size, &actual_size, APPLETBDRM_BULK_MSG_TIMEOUT); 190 if (ret) { 191 drm_err(drm, "Failed to read response (%d)\n", ret); 192 return ret; 193 } 194 195 /* 196 * The device responds to the first request sent in a particular 197 * timeframe after the USB device configuration is set with a readiness 198 * signal, in which case the response should be read again 199 */ 200 if (response->msg == APPLETBDRM_MSG_SIGNAL_READINESS) { 201 if (!readiness_signal_received) { 202 readiness_signal_received = true; 203 goto retry; 204 } 205 206 drm_err(drm, "Encountered unexpected readiness signal\n"); 207 return -EINTR; 208 } 209 210 if (actual_size != size) { 211 drm_err(drm, "Actual size (%d) doesn't match expected size (%zu)\n", 212 actual_size, size); 213 return -EBADMSG; 214 } 215 216 if (response->msg != expected_response) { 217 drm_err(drm, "Unexpected response from device (expected %p4cc found %p4cc)\n", 218 &expected_response, &response->msg); 219 return -EIO; 220 } 221 222 return 0; 223 } 224 225 static int appletbdrm_send_msg(struct appletbdrm_device *adev, __le32 msg) 226 { 227 struct appletbdrm_msg_simple_request *request; 228 int ret; 229 230 request = kzalloc(sizeof(*request), GFP_KERNEL); 231 if (!request) 232 return -ENOMEM; 233 234 request->header.unk_00 = cpu_to_le16(2); 235 request->header.unk_02 = cpu_to_le16(0x1512); 236 request->header.size = cpu_to_le32(sizeof(*request) - sizeof(request->header)); 237 request->msg = msg; 238 request->size = request->header.size; 239 240 ret = appletbdrm_send_request(adev, &request->header, sizeof(*request)); 241 242 kfree(request); 243 244 return ret; 245 } 246 247 static int appletbdrm_clear_display(struct appletbdrm_device *adev) 248 { 249 return appletbdrm_send_msg(adev, APPLETBDRM_MSG_CLEAR_DISPLAY); 250 } 251 252 static int appletbdrm_signal_readiness(struct appletbdrm_device *adev) 253 { 254 return appletbdrm_send_msg(adev, APPLETBDRM_MSG_SIGNAL_READINESS); 255 } 256 257 static int appletbdrm_get_information(struct appletbdrm_device *adev) 258 { 259 struct appletbdrm_msg_information *info; 260 struct drm_device *drm = &adev->drm; 261 u8 bits_per_pixel; 262 __le32 pixel_format; 263 int ret; 264 265 info = kzalloc(sizeof(*info), GFP_KERNEL); 266 if (!info) 267 return -ENOMEM; 268 269 ret = appletbdrm_send_msg(adev, APPLETBDRM_MSG_GET_INFORMATION); 270 if (ret) 271 return ret; 272 273 ret = appletbdrm_read_response(adev, &info->header, sizeof(*info), 274 APPLETBDRM_MSG_GET_INFORMATION); 275 if (ret) 276 goto free_info; 277 278 bits_per_pixel = info->bits_per_pixel; 279 pixel_format = get_unaligned(&info->pixel_format); 280 281 adev->width = get_unaligned_le32(&info->width); 282 adev->height = get_unaligned_le32(&info->height); 283 284 if (bits_per_pixel != APPLETBDRM_BITS_PER_PIXEL) { 285 drm_err(drm, "Encountered unexpected bits per pixel value (%d)\n", bits_per_pixel); 286 ret = -EINVAL; 287 goto free_info; 288 } 289 290 if (pixel_format != APPLETBDRM_PIXEL_FORMAT) { 291 drm_err(drm, "Encountered unknown pixel format (%p4cc)\n", &pixel_format); 292 ret = -EINVAL; 293 goto free_info; 294 } 295 296 free_info: 297 kfree(info); 298 299 return ret; 300 } 301 302 static u32 rect_size(struct drm_rect *rect) 303 { 304 return drm_rect_width(rect) * drm_rect_height(rect) * 305 (BITS_TO_BYTES(APPLETBDRM_BITS_PER_PIXEL)); 306 } 307 308 static int appletbdrm_connector_helper_get_modes(struct drm_connector *connector) 309 { 310 struct appletbdrm_device *adev = drm_to_adev(connector->dev); 311 312 return drm_connector_helper_get_modes_fixed(connector, &adev->mode); 313 } 314 315 static const u32 appletbdrm_primary_plane_formats[] = { 316 DRM_FORMAT_BGR888, 317 DRM_FORMAT_XRGB8888, /* emulated */ 318 }; 319 320 static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane, 321 struct drm_atomic_state *state) 322 { 323 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 324 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); 325 struct drm_crtc *new_crtc = new_plane_state->crtc; 326 struct drm_crtc_state *new_crtc_state = NULL; 327 struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(new_plane_state); 328 struct drm_atomic_helper_damage_iter iter; 329 struct drm_rect damage; 330 size_t frames_size = 0; 331 size_t request_size; 332 int ret; 333 334 if (new_crtc) 335 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); 336 337 ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, 338 DRM_PLANE_NO_SCALING, 339 DRM_PLANE_NO_SCALING, 340 false, false); 341 if (ret) 342 return ret; 343 else if (!new_plane_state->visible) 344 return 0; 345 346 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, new_plane_state); 347 drm_atomic_for_each_plane_damage(&iter, &damage) { 348 frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage)); 349 } 350 351 if (!frames_size) 352 return 0; 353 354 request_size = ALIGN(sizeof(struct appletbdrm_fb_request) + 355 frames_size + 356 sizeof(struct appletbdrm_fb_request_footer), 16); 357 358 appletbdrm_state->request = kzalloc(request_size, GFP_KERNEL); 359 360 if (!appletbdrm_state->request) 361 return -ENOMEM; 362 363 appletbdrm_state->response = kzalloc(sizeof(*appletbdrm_state->response), GFP_KERNEL); 364 365 if (!appletbdrm_state->response) 366 return -ENOMEM; 367 368 appletbdrm_state->request_size = request_size; 369 appletbdrm_state->frames_size = frames_size; 370 371 return 0; 372 } 373 374 static int appletbdrm_flush_damage(struct appletbdrm_device *adev, 375 struct drm_plane_state *old_state, 376 struct drm_plane_state *state) 377 { 378 struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(state); 379 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); 380 struct appletbdrm_fb_request_response *response = appletbdrm_state->response; 381 struct appletbdrm_fb_request_footer *footer; 382 struct drm_atomic_helper_damage_iter iter; 383 struct drm_framebuffer *fb = state->fb; 384 struct appletbdrm_fb_request *request = appletbdrm_state->request; 385 struct drm_device *drm = &adev->drm; 386 struct appletbdrm_frame *frame; 387 u64 timestamp = ktime_get_ns(); 388 struct drm_rect damage; 389 size_t frames_size = appletbdrm_state->frames_size; 390 size_t request_size = appletbdrm_state->request_size; 391 int ret; 392 393 if (!frames_size) 394 return 0; 395 396 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); 397 if (ret) { 398 drm_err(drm, "Failed to start CPU framebuffer access (%d)\n", ret); 399 goto end_fb_cpu_access; 400 } 401 402 request->header.unk_00 = cpu_to_le16(2); 403 request->header.unk_02 = cpu_to_le16(0x12); 404 request->header.unk_04 = cpu_to_le32(9); 405 request->header.size = cpu_to_le32(request_size - sizeof(request->header)); 406 request->unk_10 = cpu_to_le16(1); 407 request->msg_id = timestamp; 408 409 frame = (struct appletbdrm_frame *)request->data; 410 411 drm_atomic_helper_damage_iter_init(&iter, old_state, state); 412 drm_atomic_for_each_plane_damage(&iter, &damage) { 413 struct drm_rect dst_clip = state->dst; 414 struct iosys_map dst = IOSYS_MAP_INIT_VADDR(frame->buf); 415 u32 buf_size = rect_size(&damage); 416 417 if (!drm_rect_intersect(&dst_clip, &damage)) 418 continue; 419 420 /* 421 * The coordinates need to be translated to the coordinate 422 * system the device expects, see the comment in 423 * appletbdrm_setup_mode_config 424 */ 425 frame->begin_x = cpu_to_le16(damage.y1); 426 frame->begin_y = cpu_to_le16(adev->height - damage.x2); 427 frame->width = cpu_to_le16(drm_rect_height(&damage)); 428 frame->height = cpu_to_le16(drm_rect_width(&damage)); 429 frame->buf_size = cpu_to_le32(buf_size); 430 431 switch (fb->format->format) { 432 case DRM_FORMAT_XRGB8888: 433 drm_fb_xrgb8888_to_bgr888(&dst, NULL, &shadow_plane_state->data[0], fb, &damage, &shadow_plane_state->fmtcnv_state); 434 break; 435 default: 436 drm_fb_memcpy(&dst, NULL, &shadow_plane_state->data[0], fb, &damage); 437 break; 438 } 439 440 frame = (void *)frame + struct_size(frame, buf, buf_size); 441 } 442 443 footer = (struct appletbdrm_fb_request_footer *)&request->data[frames_size]; 444 445 footer->unk_0c = cpu_to_le32(0xfffe); 446 footer->unk_1c = cpu_to_le32(0x80001); 447 footer->unk_34 = cpu_to_le32(0x80002); 448 footer->unk_4c = cpu_to_le32(0xffff); 449 footer->timestamp = cpu_to_le64(timestamp); 450 451 ret = appletbdrm_send_request(adev, &request->header, request_size); 452 if (ret) 453 goto end_fb_cpu_access; 454 455 ret = appletbdrm_read_response(adev, &response->header, sizeof(*response), 456 APPLETBDRM_MSG_UPDATE_COMPLETE); 457 if (ret) 458 goto end_fb_cpu_access; 459 460 if (response->timestamp != footer->timestamp) { 461 drm_err(drm, "Response timestamp (%llu) doesn't match request timestamp (%llu)\n", 462 le64_to_cpu(response->timestamp), timestamp); 463 goto end_fb_cpu_access; 464 } 465 466 end_fb_cpu_access: 467 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); 468 469 return ret; 470 } 471 472 static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plane, 473 struct drm_atomic_state *old_state) 474 { 475 struct appletbdrm_device *adev = drm_to_adev(plane->dev); 476 struct drm_device *drm = plane->dev; 477 struct drm_plane_state *plane_state = plane->state; 478 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane); 479 int idx; 480 481 if (!drm_dev_enter(drm, &idx)) 482 return; 483 484 appletbdrm_flush_damage(adev, old_plane_state, plane_state); 485 486 drm_dev_exit(idx); 487 } 488 489 static void appletbdrm_primary_plane_helper_atomic_disable(struct drm_plane *plane, 490 struct drm_atomic_state *state) 491 { 492 struct drm_device *dev = plane->dev; 493 struct appletbdrm_device *adev = drm_to_adev(dev); 494 int idx; 495 496 if (!drm_dev_enter(dev, &idx)) 497 return; 498 499 appletbdrm_clear_display(adev); 500 501 drm_dev_exit(idx); 502 } 503 504 static void appletbdrm_primary_plane_reset(struct drm_plane *plane) 505 { 506 struct appletbdrm_plane_state *appletbdrm_state; 507 508 WARN_ON(plane->state); 509 510 appletbdrm_state = kzalloc(sizeof(*appletbdrm_state), GFP_KERNEL); 511 if (!appletbdrm_state) 512 return; 513 514 __drm_gem_reset_shadow_plane(plane, &appletbdrm_state->base); 515 } 516 517 static struct drm_plane_state *appletbdrm_primary_plane_duplicate_state(struct drm_plane *plane) 518 { 519 struct drm_shadow_plane_state *new_shadow_plane_state; 520 struct appletbdrm_plane_state *appletbdrm_state; 521 522 if (WARN_ON(!plane->state)) 523 return NULL; 524 525 appletbdrm_state = kzalloc(sizeof(*appletbdrm_state), GFP_KERNEL); 526 if (!appletbdrm_state) 527 return NULL; 528 529 /* Request and response are not duplicated and are allocated in .atomic_check */ 530 appletbdrm_state->request = NULL; 531 appletbdrm_state->response = NULL; 532 533 appletbdrm_state->request_size = 0; 534 appletbdrm_state->frames_size = 0; 535 536 new_shadow_plane_state = &appletbdrm_state->base; 537 538 __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state); 539 540 return &new_shadow_plane_state->base; 541 } 542 543 static void appletbdrm_primary_plane_destroy_state(struct drm_plane *plane, 544 struct drm_plane_state *state) 545 { 546 struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(state); 547 548 kfree(appletbdrm_state->request); 549 kfree(appletbdrm_state->response); 550 551 __drm_gem_destroy_shadow_plane_state(&appletbdrm_state->base); 552 553 kfree(appletbdrm_state); 554 } 555 556 static const struct drm_plane_helper_funcs appletbdrm_primary_plane_helper_funcs = { 557 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 558 .atomic_check = appletbdrm_primary_plane_helper_atomic_check, 559 .atomic_update = appletbdrm_primary_plane_helper_atomic_update, 560 .atomic_disable = appletbdrm_primary_plane_helper_atomic_disable, 561 }; 562 563 static const struct drm_plane_funcs appletbdrm_primary_plane_funcs = { 564 .update_plane = drm_atomic_helper_update_plane, 565 .disable_plane = drm_atomic_helper_disable_plane, 566 .reset = appletbdrm_primary_plane_reset, 567 .atomic_duplicate_state = appletbdrm_primary_plane_duplicate_state, 568 .atomic_destroy_state = appletbdrm_primary_plane_destroy_state, 569 .destroy = drm_plane_cleanup, 570 }; 571 572 static enum drm_mode_status appletbdrm_crtc_helper_mode_valid(struct drm_crtc *crtc, 573 const struct drm_display_mode *mode) 574 { 575 struct appletbdrm_device *adev = drm_to_adev(crtc->dev); 576 577 return drm_crtc_helper_mode_valid_fixed(crtc, mode, &adev->mode); 578 } 579 580 static const struct drm_mode_config_funcs appletbdrm_mode_config_funcs = { 581 .fb_create = drm_gem_fb_create_with_dirty, 582 .atomic_check = drm_atomic_helper_check, 583 .atomic_commit = drm_atomic_helper_commit, 584 }; 585 586 static const struct drm_connector_funcs appletbdrm_connector_funcs = { 587 .reset = drm_atomic_helper_connector_reset, 588 .destroy = drm_connector_cleanup, 589 .fill_modes = drm_helper_probe_single_connector_modes, 590 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 591 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 592 }; 593 594 static const struct drm_connector_helper_funcs appletbdrm_connector_helper_funcs = { 595 .get_modes = appletbdrm_connector_helper_get_modes, 596 }; 597 598 static const struct drm_crtc_helper_funcs appletbdrm_crtc_helper_funcs = { 599 .mode_valid = appletbdrm_crtc_helper_mode_valid, 600 }; 601 602 static const struct drm_crtc_funcs appletbdrm_crtc_funcs = { 603 .reset = drm_atomic_helper_crtc_reset, 604 .destroy = drm_crtc_cleanup, 605 .set_config = drm_atomic_helper_set_config, 606 .page_flip = drm_atomic_helper_page_flip, 607 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 608 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 609 }; 610 611 static const struct drm_encoder_funcs appletbdrm_encoder_funcs = { 612 .destroy = drm_encoder_cleanup, 613 }; 614 615 static struct drm_gem_object *appletbdrm_driver_gem_prime_import(struct drm_device *dev, 616 struct dma_buf *dma_buf) 617 { 618 struct appletbdrm_device *adev = drm_to_adev(dev); 619 620 if (!adev->dmadev) 621 return ERR_PTR(-ENODEV); 622 623 return drm_gem_prime_import_dev(dev, dma_buf, adev->dmadev); 624 } 625 626 DEFINE_DRM_GEM_FOPS(appletbdrm_drm_fops); 627 628 static const struct drm_driver appletbdrm_drm_driver = { 629 DRM_GEM_SHMEM_DRIVER_OPS, 630 .gem_prime_import = appletbdrm_driver_gem_prime_import, 631 .name = "appletbdrm", 632 .desc = "Apple Touch Bar DRM Driver", 633 .major = 1, 634 .minor = 0, 635 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 636 .fops = &appletbdrm_drm_fops, 637 }; 638 639 static int appletbdrm_setup_mode_config(struct appletbdrm_device *adev) 640 { 641 struct drm_connector *connector = &adev->connector; 642 struct drm_plane *primary_plane; 643 struct drm_crtc *crtc; 644 struct drm_encoder *encoder; 645 struct drm_device *drm = &adev->drm; 646 int ret; 647 648 ret = drmm_mode_config_init(drm); 649 if (ret) { 650 drm_err(drm, "Failed to initialize mode configuration\n"); 651 return ret; 652 } 653 654 primary_plane = &adev->primary_plane; 655 ret = drm_universal_plane_init(drm, primary_plane, 0, 656 &appletbdrm_primary_plane_funcs, 657 appletbdrm_primary_plane_formats, 658 ARRAY_SIZE(appletbdrm_primary_plane_formats), 659 NULL, 660 DRM_PLANE_TYPE_PRIMARY, NULL); 661 if (ret) { 662 drm_err(drm, "Failed to initialize universal plane object\n"); 663 return ret; 664 } 665 666 drm_plane_helper_add(primary_plane, &appletbdrm_primary_plane_helper_funcs); 667 drm_plane_enable_fb_damage_clips(primary_plane); 668 669 crtc = &adev->crtc; 670 ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, 671 &appletbdrm_crtc_funcs, NULL); 672 if (ret) { 673 drm_err(drm, "Failed to initialize CRTC object\n"); 674 return ret; 675 } 676 677 drm_crtc_helper_add(crtc, &appletbdrm_crtc_helper_funcs); 678 679 encoder = &adev->encoder; 680 ret = drm_encoder_init(drm, encoder, &appletbdrm_encoder_funcs, 681 DRM_MODE_ENCODER_DAC, NULL); 682 if (ret) { 683 drm_err(drm, "Failed to initialize encoder\n"); 684 return ret; 685 } 686 687 encoder->possible_crtcs = drm_crtc_mask(crtc); 688 689 /* 690 * The coordinate system used by the device is different from the 691 * coordinate system of the framebuffer in that the x and y axes are 692 * swapped, and that the y axis is inverted; so what the device reports 693 * as the height is actually the width of the framebuffer and vice 694 * versa. 695 */ 696 drm->mode_config.max_width = max(adev->height, DRM_SHADOW_PLANE_MAX_WIDTH); 697 drm->mode_config.max_height = max(adev->width, DRM_SHADOW_PLANE_MAX_HEIGHT); 698 drm->mode_config.preferred_depth = APPLETBDRM_BITS_PER_PIXEL; 699 drm->mode_config.funcs = &appletbdrm_mode_config_funcs; 700 701 adev->mode = (struct drm_display_mode) { 702 DRM_MODE_INIT(60, adev->height, adev->width, 703 DRM_MODE_RES_MM(adev->height, 218), 704 DRM_MODE_RES_MM(adev->width, 218)) 705 }; 706 707 ret = drm_connector_init(drm, connector, 708 &appletbdrm_connector_funcs, DRM_MODE_CONNECTOR_USB); 709 if (ret) { 710 drm_err(drm, "Failed to initialize connector\n"); 711 return ret; 712 } 713 714 drm_connector_helper_add(connector, &appletbdrm_connector_helper_funcs); 715 716 ret = drm_connector_set_panel_orientation(connector, 717 DRM_MODE_PANEL_ORIENTATION_RIGHT_UP); 718 if (ret) { 719 drm_err(drm, "Failed to set panel orientation\n"); 720 return ret; 721 } 722 723 connector->display_info.non_desktop = true; 724 ret = drm_object_property_set_value(&connector->base, 725 drm->mode_config.non_desktop_property, true); 726 if (ret) { 727 drm_err(drm, "Failed to set non-desktop property\n"); 728 return ret; 729 } 730 731 ret = drm_connector_attach_encoder(connector, encoder); 732 733 if (ret) { 734 drm_err(drm, "Failed to initialize simple display pipe\n"); 735 return ret; 736 } 737 738 drm_mode_config_reset(drm); 739 740 return 0; 741 } 742 743 static int appletbdrm_probe(struct usb_interface *intf, 744 const struct usb_device_id *id) 745 { 746 struct usb_endpoint_descriptor *bulk_in, *bulk_out; 747 struct device *dev = &intf->dev; 748 struct appletbdrm_device *adev; 749 struct drm_device *drm = NULL; 750 int ret; 751 752 ret = usb_find_common_endpoints(intf->cur_altsetting, &bulk_in, &bulk_out, NULL, NULL); 753 if (ret) { 754 drm_err(drm, "appletbdrm: Failed to find bulk endpoints\n"); 755 return ret; 756 } 757 758 adev = devm_drm_dev_alloc(dev, &appletbdrm_drm_driver, struct appletbdrm_device, drm); 759 if (IS_ERR(adev)) 760 return PTR_ERR(adev); 761 762 adev->in_ep = bulk_in->bEndpointAddress; 763 adev->out_ep = bulk_out->bEndpointAddress; 764 adev->dmadev = dev; 765 766 drm = &adev->drm; 767 768 usb_set_intfdata(intf, adev); 769 770 ret = appletbdrm_get_information(adev); 771 if (ret) { 772 drm_err(drm, "Failed to get display information\n"); 773 return ret; 774 } 775 776 ret = appletbdrm_signal_readiness(adev); 777 if (ret) { 778 drm_err(drm, "Failed to signal readiness\n"); 779 return ret; 780 } 781 782 ret = appletbdrm_setup_mode_config(adev); 783 if (ret) { 784 drm_err(drm, "Failed to setup mode config\n"); 785 return ret; 786 } 787 788 ret = drm_dev_register(drm, 0); 789 if (ret) { 790 drm_err(drm, "Failed to register DRM device\n"); 791 return ret; 792 } 793 794 ret = appletbdrm_clear_display(adev); 795 if (ret) { 796 drm_err(drm, "Failed to clear display\n"); 797 return ret; 798 } 799 800 return 0; 801 } 802 803 static void appletbdrm_disconnect(struct usb_interface *intf) 804 { 805 struct appletbdrm_device *adev = usb_get_intfdata(intf); 806 struct drm_device *drm = &adev->drm; 807 808 drm_dev_unplug(drm); 809 drm_atomic_helper_shutdown(drm); 810 } 811 812 static void appletbdrm_shutdown(struct usb_interface *intf) 813 { 814 struct appletbdrm_device *adev = usb_get_intfdata(intf); 815 816 /* 817 * The framebuffer needs to be cleared on shutdown since its content 818 * persists across boots 819 */ 820 drm_atomic_helper_shutdown(&adev->drm); 821 } 822 823 static const struct usb_device_id appletbdrm_usb_id_table[] = { 824 { USB_DEVICE_INTERFACE_CLASS(0x05ac, 0x8302, USB_CLASS_AUDIO_VIDEO) }, 825 {} 826 }; 827 MODULE_DEVICE_TABLE(usb, appletbdrm_usb_id_table); 828 829 static struct usb_driver appletbdrm_usb_driver = { 830 .name = "appletbdrm", 831 .probe = appletbdrm_probe, 832 .disconnect = appletbdrm_disconnect, 833 .shutdown = appletbdrm_shutdown, 834 .id_table = appletbdrm_usb_id_table, 835 }; 836 module_usb_driver(appletbdrm_usb_driver); 837 838 MODULE_AUTHOR("Kerem Karabay <kekrby@gmail.com>"); 839 MODULE_DESCRIPTION("Apple Touch Bar DRM Driver"); 840 MODULE_LICENSE("GPL"); 841