1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2020 Noralf Trønnes 4 */ 5 6 #include <linux/backlight.h> 7 #include <linux/workqueue.h> 8 9 #include <drm/drm_atomic.h> 10 #include <drm/drm_atomic_state_helper.h> 11 #include <drm/drm_connector.h> 12 #include <drm/drm_drv.h> 13 #include <drm/drm_edid.h> 14 #include <drm/drm_encoder.h> 15 #include <drm/drm_file.h> 16 #include <drm/drm_modeset_helper_vtables.h> 17 #include <drm/drm_print.h> 18 #include <drm/drm_probe_helper.h> 19 #include <drm/gud.h> 20 21 #include "gud_internal.h" 22 23 struct gud_connector { 24 struct drm_connector connector; 25 struct drm_encoder encoder; 26 struct backlight_device *backlight; 27 struct work_struct backlight_work; 28 29 /* Supported properties */ 30 u16 *properties; 31 unsigned int num_properties; 32 33 /* Initial gadget tv state if applicable, applied on state reset */ 34 struct drm_tv_connector_state initial_tv_state; 35 36 /* 37 * Initial gadget backlight brightness if applicable, applied on state reset. 38 * The value -ENODEV is used to signal no backlight. 39 */ 40 int initial_brightness; 41 }; 42 43 static inline struct gud_connector *to_gud_connector(struct drm_connector *connector) 44 { 45 return container_of(connector, struct gud_connector, connector); 46 } 47 48 static void gud_conn_err(struct drm_connector *connector, const char *msg, int ret) 49 { 50 dev_err(connector->dev->dev, "%s: %s (ret=%d)\n", connector->name, msg, ret); 51 } 52 53 /* 54 * Use a worker to avoid taking kms locks inside the backlight lock. 55 * Other display drivers use backlight within their kms locks. 56 * This avoids inconsistent locking rules, which would upset lockdep. 57 */ 58 static void gud_connector_backlight_update_status_work(struct work_struct *work) 59 { 60 struct gud_connector *gconn = container_of(work, struct gud_connector, backlight_work); 61 struct drm_connector *connector = &gconn->connector; 62 struct drm_connector_state *connector_state; 63 struct drm_device *drm = connector->dev; 64 struct drm_modeset_acquire_ctx ctx; 65 struct drm_atomic_commit *state; 66 int idx, ret; 67 68 if (!drm_dev_enter(drm, &idx)) 69 return; 70 71 state = drm_atomic_commit_alloc(drm); 72 if (!state) { 73 ret = -ENOMEM; 74 goto exit; 75 } 76 77 drm_modeset_acquire_init(&ctx, 0); 78 state->acquire_ctx = &ctx; 79 retry: 80 connector_state = drm_atomic_get_connector_state(state, connector); 81 if (IS_ERR(connector_state)) { 82 ret = PTR_ERR(connector_state); 83 goto out; 84 } 85 86 /* Reuse tv.brightness to avoid having to subclass */ 87 connector_state->tv.brightness = gconn->backlight->props.brightness; 88 89 ret = drm_atomic_commit(state); 90 out: 91 if (ret == -EDEADLK) { 92 drm_atomic_commit_clear(state); 93 drm_modeset_backoff(&ctx); 94 goto retry; 95 } 96 97 drm_atomic_commit_put(state); 98 99 drm_modeset_drop_locks(&ctx); 100 drm_modeset_acquire_fini(&ctx); 101 exit: 102 drm_dev_exit(idx); 103 104 if (ret) 105 dev_err(drm->dev, "Failed to update backlight, err=%d\n", ret); 106 } 107 108 static int gud_connector_backlight_update_status(struct backlight_device *bd) 109 { 110 struct drm_connector *connector = bl_get_data(bd); 111 struct gud_connector *gconn = to_gud_connector(connector); 112 113 /* The USB timeout is 5 seconds so use system_long_wq for worst case scenario */ 114 queue_work(system_long_wq, &gconn->backlight_work); 115 116 return 0; 117 } 118 119 static const struct backlight_ops gud_connector_backlight_ops = { 120 .update_status = gud_connector_backlight_update_status, 121 }; 122 123 static int gud_connector_backlight_register(struct gud_connector *gconn) 124 { 125 struct drm_connector *connector = &gconn->connector; 126 struct backlight_device *bd; 127 const char *name; 128 const struct backlight_properties props = { 129 .type = BACKLIGHT_RAW, 130 .scale = BACKLIGHT_SCALE_NON_LINEAR, 131 .max_brightness = 100, 132 .brightness = gconn->initial_brightness, 133 }; 134 135 name = kasprintf(GFP_KERNEL, "card%d-%s-backlight", 136 connector->dev->primary->index, connector->name); 137 if (!name) 138 return -ENOMEM; 139 140 bd = backlight_device_register(name, connector->kdev, connector, 141 &gud_connector_backlight_ops, &props); 142 kfree(name); 143 if (IS_ERR(bd)) 144 return PTR_ERR(bd); 145 146 gconn->backlight = bd; 147 148 return 0; 149 } 150 151 static int gud_connector_detect(struct drm_connector *connector, 152 struct drm_modeset_acquire_ctx *ctx, bool force) 153 { 154 struct gud_device *gdrm = to_gud_device(connector->dev); 155 int idx, ret; 156 u8 status; 157 158 if (!drm_dev_enter(connector->dev, &idx)) 159 return connector_status_disconnected; 160 161 if (force) { 162 ret = gud_usb_set(gdrm, GUD_REQ_SET_CONNECTOR_FORCE_DETECT, 163 connector->index, NULL, 0); 164 if (ret) { 165 ret = connector_status_unknown; 166 goto exit; 167 } 168 } 169 170 ret = gud_usb_get_u8(gdrm, GUD_REQ_GET_CONNECTOR_STATUS, connector->index, &status); 171 if (ret) { 172 ret = connector_status_unknown; 173 goto exit; 174 } 175 176 switch (status & GUD_CONNECTOR_STATUS_CONNECTED_MASK) { 177 case GUD_CONNECTOR_STATUS_DISCONNECTED: 178 ret = connector_status_disconnected; 179 break; 180 case GUD_CONNECTOR_STATUS_CONNECTED: 181 ret = connector_status_connected; 182 break; 183 default: 184 ret = connector_status_unknown; 185 break; 186 } 187 188 if (status & GUD_CONNECTOR_STATUS_CHANGED) 189 connector->epoch_counter += 1; 190 exit: 191 drm_dev_exit(idx); 192 193 return ret; 194 } 195 196 struct gud_connector_get_edid_ctx { 197 void *buf; 198 size_t len; 199 bool edid_override; 200 }; 201 202 static int gud_connector_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) 203 { 204 struct gud_connector_get_edid_ctx *ctx = data; 205 size_t start = block * EDID_LENGTH; 206 207 ctx->edid_override = false; 208 209 if (start + len > ctx->len) 210 return -1; 211 212 memcpy(buf, ctx->buf + start, len); 213 214 return 0; 215 } 216 217 static int gud_connector_get_modes(struct drm_connector *connector) 218 { 219 struct gud_device *gdrm = to_gud_device(connector->dev); 220 struct gud_display_mode_req *reqmodes = NULL; 221 struct gud_connector_get_edid_ctx edid_ctx; 222 unsigned int i, num_modes = 0; 223 const struct drm_edid *drm_edid = NULL; 224 int idx, ret; 225 226 if (!drm_dev_enter(connector->dev, &idx)) 227 return 0; 228 229 edid_ctx.edid_override = true; 230 edid_ctx.buf = kmalloc(GUD_CONNECTOR_MAX_EDID_LEN, GFP_KERNEL); 231 if (!edid_ctx.buf) 232 goto out; 233 234 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_EDID, connector->index, 235 edid_ctx.buf, GUD_CONNECTOR_MAX_EDID_LEN); 236 if (ret > 0 && ret % EDID_LENGTH) { 237 gud_conn_err(connector, "Invalid EDID size", ret); 238 } else if (ret > 0) { 239 edid_ctx.len = ret; 240 drm_edid = drm_edid_read_custom(connector, gud_connector_get_edid_block, &edid_ctx); 241 } 242 243 kfree(edid_ctx.buf); 244 drm_edid_connector_update(connector, drm_edid); 245 246 if (drm_edid && edid_ctx.edid_override) 247 goto out; 248 249 reqmodes = kmalloc_objs(*reqmodes, GUD_CONNECTOR_MAX_NUM_MODES); 250 if (!reqmodes) 251 goto out; 252 253 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_MODES, connector->index, 254 reqmodes, GUD_CONNECTOR_MAX_NUM_MODES * sizeof(*reqmodes)); 255 if (ret <= 0) 256 goto out; 257 if (ret % sizeof(*reqmodes)) { 258 gud_conn_err(connector, "Invalid display mode array size", ret); 259 goto out; 260 } 261 262 num_modes = ret / sizeof(*reqmodes); 263 264 for (i = 0; i < num_modes; i++) { 265 struct drm_display_mode *mode; 266 267 mode = drm_mode_create(connector->dev); 268 if (!mode) { 269 num_modes = i; 270 goto out; 271 } 272 273 gud_to_display_mode(mode, &reqmodes[i]); 274 drm_mode_probed_add(connector, mode); 275 } 276 out: 277 if (!num_modes) 278 num_modes = drm_edid_connector_add_modes(connector); 279 280 kfree(reqmodes); 281 drm_edid_free(drm_edid); 282 drm_dev_exit(idx); 283 284 return num_modes; 285 } 286 287 static int gud_connector_atomic_check(struct drm_connector *connector, 288 struct drm_atomic_commit *state) 289 { 290 struct drm_connector_state *new_state; 291 struct drm_crtc_state *new_crtc_state; 292 struct drm_connector_state *old_state; 293 294 new_state = drm_atomic_get_new_connector_state(state, connector); 295 if (!new_state->crtc) 296 return 0; 297 298 old_state = drm_atomic_get_old_connector_state(state, connector); 299 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc); 300 301 if (old_state->tv.margins.left != new_state->tv.margins.left || 302 old_state->tv.margins.right != new_state->tv.margins.right || 303 old_state->tv.margins.top != new_state->tv.margins.top || 304 old_state->tv.margins.bottom != new_state->tv.margins.bottom || 305 old_state->tv.legacy_mode != new_state->tv.legacy_mode || 306 old_state->tv.brightness != new_state->tv.brightness || 307 old_state->tv.contrast != new_state->tv.contrast || 308 old_state->tv.flicker_reduction != new_state->tv.flicker_reduction || 309 old_state->tv.overscan != new_state->tv.overscan || 310 old_state->tv.saturation != new_state->tv.saturation || 311 old_state->tv.hue != new_state->tv.hue) 312 new_crtc_state->connectors_changed = true; 313 314 return 0; 315 } 316 317 static const struct drm_connector_helper_funcs gud_connector_helper_funcs = { 318 .detect_ctx = gud_connector_detect, 319 .get_modes = gud_connector_get_modes, 320 .atomic_check = gud_connector_atomic_check, 321 }; 322 323 static int gud_connector_late_register(struct drm_connector *connector) 324 { 325 struct gud_connector *gconn = to_gud_connector(connector); 326 327 if (gconn->initial_brightness < 0) 328 return 0; 329 330 return gud_connector_backlight_register(gconn); 331 } 332 333 static void gud_connector_early_unregister(struct drm_connector *connector) 334 { 335 struct gud_connector *gconn = to_gud_connector(connector); 336 337 backlight_device_unregister(gconn->backlight); 338 cancel_work_sync(&gconn->backlight_work); 339 } 340 341 static void gud_connector_destroy(struct drm_connector *connector) 342 { 343 struct gud_connector *gconn = to_gud_connector(connector); 344 345 drm_connector_cleanup(connector); 346 kfree(gconn->properties); 347 kfree(gconn); 348 } 349 350 static void gud_connector_reset(struct drm_connector *connector) 351 { 352 struct gud_connector *gconn = to_gud_connector(connector); 353 354 drm_atomic_helper_connector_reset(connector); 355 connector->state->tv = gconn->initial_tv_state; 356 /* Set margins from command line */ 357 drm_atomic_helper_connector_tv_margins_reset(connector); 358 if (gconn->initial_brightness >= 0) 359 connector->state->tv.brightness = gconn->initial_brightness; 360 } 361 362 static const struct drm_connector_funcs gud_connector_funcs = { 363 .fill_modes = drm_helper_probe_single_connector_modes, 364 .late_register = gud_connector_late_register, 365 .early_unregister = gud_connector_early_unregister, 366 .destroy = gud_connector_destroy, 367 .reset = gud_connector_reset, 368 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 369 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 370 }; 371 372 /* 373 * The tv.mode property is shared among the connectors and its enum names are 374 * driver specific. This means that if more than one connector uses tv.mode, 375 * the enum names has to be the same. 376 */ 377 static int gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connector *connector) 378 { 379 size_t buf_len = GUD_CONNECTOR_TV_MODE_MAX_NUM * GUD_CONNECTOR_TV_MODE_NAME_LEN; 380 const char *modes[GUD_CONNECTOR_TV_MODE_MAX_NUM]; 381 unsigned int i, num_modes; 382 char *buf; 383 int ret; 384 385 buf = kmalloc(buf_len, GFP_KERNEL); 386 if (!buf) 387 return -ENOMEM; 388 389 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_TV_MODE_VALUES, 390 connector->index, buf, buf_len); 391 if (ret < 0) 392 goto free; 393 if (!ret || ret % GUD_CONNECTOR_TV_MODE_NAME_LEN) { 394 ret = -EIO; 395 goto free; 396 } 397 398 num_modes = ret / GUD_CONNECTOR_TV_MODE_NAME_LEN; 399 for (i = 0; i < num_modes; i++) { 400 char *mode = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN]; 401 402 if (!memchr(mode, '\0', GUD_CONNECTOR_TV_MODE_NAME_LEN)) { 403 ret = -EIO; 404 goto free; 405 } 406 407 modes[i] = mode; 408 } 409 410 ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, modes); 411 free: 412 kfree(buf); 413 if (ret < 0) 414 gud_conn_err(connector, "Failed to add TV modes", ret); 415 416 return ret; 417 } 418 419 static struct drm_property * 420 gud_connector_property_lookup(struct drm_connector *connector, u16 prop) 421 { 422 struct drm_mode_config *config = &connector->dev->mode_config; 423 424 switch (prop) { 425 case GUD_PROPERTY_TV_LEFT_MARGIN: 426 return config->tv_left_margin_property; 427 case GUD_PROPERTY_TV_RIGHT_MARGIN: 428 return config->tv_right_margin_property; 429 case GUD_PROPERTY_TV_TOP_MARGIN: 430 return config->tv_top_margin_property; 431 case GUD_PROPERTY_TV_BOTTOM_MARGIN: 432 return config->tv_bottom_margin_property; 433 case GUD_PROPERTY_TV_MODE: 434 return config->legacy_tv_mode_property; 435 case GUD_PROPERTY_TV_BRIGHTNESS: 436 return config->tv_brightness_property; 437 case GUD_PROPERTY_TV_CONTRAST: 438 return config->tv_contrast_property; 439 case GUD_PROPERTY_TV_FLICKER_REDUCTION: 440 return config->tv_flicker_reduction_property; 441 case GUD_PROPERTY_TV_OVERSCAN: 442 return config->tv_overscan_property; 443 case GUD_PROPERTY_TV_SATURATION: 444 return config->tv_saturation_property; 445 case GUD_PROPERTY_TV_HUE: 446 return config->tv_hue_property; 447 default: 448 return ERR_PTR(-EINVAL); 449 } 450 } 451 452 static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connector_state *state) 453 { 454 switch (prop) { 455 case GUD_PROPERTY_TV_LEFT_MARGIN: 456 return &state->margins.left; 457 case GUD_PROPERTY_TV_RIGHT_MARGIN: 458 return &state->margins.right; 459 case GUD_PROPERTY_TV_TOP_MARGIN: 460 return &state->margins.top; 461 case GUD_PROPERTY_TV_BOTTOM_MARGIN: 462 return &state->margins.bottom; 463 case GUD_PROPERTY_TV_MODE: 464 return &state->legacy_mode; 465 case GUD_PROPERTY_TV_BRIGHTNESS: 466 return &state->brightness; 467 case GUD_PROPERTY_TV_CONTRAST: 468 return &state->contrast; 469 case GUD_PROPERTY_TV_FLICKER_REDUCTION: 470 return &state->flicker_reduction; 471 case GUD_PROPERTY_TV_OVERSCAN: 472 return &state->overscan; 473 case GUD_PROPERTY_TV_SATURATION: 474 return &state->saturation; 475 case GUD_PROPERTY_TV_HUE: 476 return &state->hue; 477 default: 478 return ERR_PTR(-EINVAL); 479 } 480 } 481 482 static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_connector *gconn) 483 { 484 struct drm_connector *connector = &gconn->connector; 485 struct drm_device *drm = &gdrm->drm; 486 struct gud_property_req *properties; 487 unsigned int i, num_properties; 488 int ret; 489 490 properties = kzalloc_objs(*properties, GUD_CONNECTOR_PROPERTIES_MAX_NUM); 491 if (!properties) 492 return -ENOMEM; 493 494 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_PROPERTIES, connector->index, 495 properties, GUD_CONNECTOR_PROPERTIES_MAX_NUM * sizeof(*properties)); 496 if (ret <= 0) 497 goto out; 498 if (ret % sizeof(*properties)) { 499 ret = -EIO; 500 goto out; 501 } 502 503 num_properties = ret / sizeof(*properties); 504 ret = 0; 505 506 gconn->properties = kcalloc(num_properties, sizeof(*gconn->properties), GFP_KERNEL); 507 if (!gconn->properties) { 508 ret = -ENOMEM; 509 goto out; 510 } 511 512 for (i = 0; i < num_properties; i++) { 513 u16 prop = le16_to_cpu(properties[i].prop); 514 u64 val = le64_to_cpu(properties[i].val); 515 struct drm_property *property; 516 unsigned int *state_val; 517 518 drm_dbg(drm, "property: %u = %llu(0x%llx)\n", prop, val, val); 519 520 switch (prop) { 521 case GUD_PROPERTY_TV_LEFT_MARGIN: 522 fallthrough; 523 case GUD_PROPERTY_TV_RIGHT_MARGIN: 524 fallthrough; 525 case GUD_PROPERTY_TV_TOP_MARGIN: 526 fallthrough; 527 case GUD_PROPERTY_TV_BOTTOM_MARGIN: 528 ret = drm_mode_create_tv_margin_properties(drm); 529 if (ret) 530 goto out; 531 break; 532 case GUD_PROPERTY_TV_MODE: 533 ret = gud_connector_add_tv_mode(gdrm, connector); 534 if (ret) 535 goto out; 536 break; 537 case GUD_PROPERTY_TV_BRIGHTNESS: 538 fallthrough; 539 case GUD_PROPERTY_TV_CONTRAST: 540 fallthrough; 541 case GUD_PROPERTY_TV_FLICKER_REDUCTION: 542 fallthrough; 543 case GUD_PROPERTY_TV_OVERSCAN: 544 fallthrough; 545 case GUD_PROPERTY_TV_SATURATION: 546 fallthrough; 547 case GUD_PROPERTY_TV_HUE: 548 /* This is a no-op if already added. */ 549 ret = drm_mode_create_tv_properties_legacy(drm, 0, NULL); 550 if (ret) 551 goto out; 552 break; 553 case GUD_PROPERTY_BACKLIGHT_BRIGHTNESS: 554 if (val > 100) { 555 ret = -EINVAL; 556 goto out; 557 } 558 gconn->initial_brightness = val; 559 break; 560 default: 561 /* New ones might show up in future devices, skip those we don't know. */ 562 drm_dbg(drm, "Ignoring unknown property: %u\n", prop); 563 continue; 564 } 565 566 gconn->properties[gconn->num_properties++] = prop; 567 568 if (prop == GUD_PROPERTY_BACKLIGHT_BRIGHTNESS) 569 continue; /* not a DRM property */ 570 571 property = gud_connector_property_lookup(connector, prop); 572 if (drm_WARN_ON(drm, IS_ERR(property))) 573 continue; 574 575 state_val = gud_connector_tv_state_val(prop, &gconn->initial_tv_state); 576 if (drm_WARN_ON(drm, IS_ERR(state_val))) 577 continue; 578 579 *state_val = val; 580 drm_object_attach_property(&connector->base, property, 0); 581 } 582 out: 583 kfree(properties); 584 585 return ret; 586 } 587 588 int gud_connector_fill_properties(struct drm_connector_state *connector_state, 589 struct gud_property_req *properties) 590 { 591 struct gud_connector *gconn = to_gud_connector(connector_state->connector); 592 unsigned int i; 593 594 for (i = 0; i < gconn->num_properties; i++) { 595 u16 prop = gconn->properties[i]; 596 u64 val; 597 598 if (prop == GUD_PROPERTY_BACKLIGHT_BRIGHTNESS) { 599 val = connector_state->tv.brightness; 600 } else { 601 unsigned int *state_val; 602 603 state_val = gud_connector_tv_state_val(prop, &connector_state->tv); 604 if (drm_WARN_ON_ONCE(connector_state->connector->dev, IS_ERR(state_val))) 605 return PTR_ERR(state_val); 606 607 val = *state_val; 608 } 609 610 properties[i].prop = cpu_to_le16(prop); 611 properties[i].val = cpu_to_le64(val); 612 } 613 614 return gconn->num_properties; 615 } 616 617 static const struct drm_encoder_funcs gud_drm_simple_encoder_funcs_cleanup = { 618 .destroy = drm_encoder_cleanup, 619 }; 620 621 static int gud_connector_create(struct gud_device *gdrm, unsigned int index, 622 struct gud_connector_descriptor_req *desc) 623 { 624 struct drm_device *drm = &gdrm->drm; 625 struct gud_connector *gconn; 626 struct drm_connector *connector; 627 int ret, connector_type; 628 u32 flags; 629 630 gconn = kzalloc_obj(*gconn); 631 if (!gconn) 632 return -ENOMEM; 633 634 INIT_WORK(&gconn->backlight_work, gud_connector_backlight_update_status_work); 635 gconn->initial_brightness = -ENODEV; 636 flags = le32_to_cpu(desc->flags); 637 connector = &gconn->connector; 638 639 drm_dbg(drm, "Connector: index=%u type=%u flags=0x%x\n", index, desc->connector_type, flags); 640 641 switch (desc->connector_type) { 642 case GUD_CONNECTOR_TYPE_PANEL: 643 connector_type = DRM_MODE_CONNECTOR_USB; 644 break; 645 case GUD_CONNECTOR_TYPE_VGA: 646 connector_type = DRM_MODE_CONNECTOR_VGA; 647 break; 648 case GUD_CONNECTOR_TYPE_DVI: 649 connector_type = DRM_MODE_CONNECTOR_DVID; 650 break; 651 case GUD_CONNECTOR_TYPE_COMPOSITE: 652 connector_type = DRM_MODE_CONNECTOR_Composite; 653 break; 654 case GUD_CONNECTOR_TYPE_SVIDEO: 655 connector_type = DRM_MODE_CONNECTOR_SVIDEO; 656 break; 657 case GUD_CONNECTOR_TYPE_COMPONENT: 658 connector_type = DRM_MODE_CONNECTOR_Component; 659 break; 660 case GUD_CONNECTOR_TYPE_DISPLAYPORT: 661 connector_type = DRM_MODE_CONNECTOR_DisplayPort; 662 break; 663 case GUD_CONNECTOR_TYPE_HDMI: 664 connector_type = DRM_MODE_CONNECTOR_HDMIA; 665 break; 666 default: /* future types */ 667 connector_type = DRM_MODE_CONNECTOR_USB; 668 break; 669 } 670 671 drm_connector_helper_add(connector, &gud_connector_helper_funcs); 672 ret = drm_connector_init(drm, connector, &gud_connector_funcs, connector_type); 673 if (ret) { 674 kfree(connector); 675 return ret; 676 } 677 678 if (drm_WARN_ON(drm, connector->index != index)) 679 return -EINVAL; 680 681 if (flags & GUD_CONNECTOR_FLAGS_POLL_STATUS) 682 connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT); 683 if (flags & GUD_CONNECTOR_FLAGS_INTERLACE) 684 connector->interlace_allowed = true; 685 if (flags & GUD_CONNECTOR_FLAGS_DOUBLESCAN) 686 connector->doublescan_allowed = true; 687 688 ret = gud_connector_add_properties(gdrm, gconn); 689 if (ret) { 690 gud_conn_err(connector, "Failed to add properties", ret); 691 return ret; 692 } 693 694 gconn->encoder.possible_crtcs = drm_crtc_mask(&gdrm->crtc); 695 ret = drm_encoder_init(drm, &gconn->encoder, &gud_drm_simple_encoder_funcs_cleanup, 696 DRM_MODE_ENCODER_NONE, NULL); 697 if (ret) 698 return ret; 699 700 return drm_connector_attach_encoder(connector, &gconn->encoder); 701 } 702 703 int gud_get_connectors(struct gud_device *gdrm) 704 { 705 struct gud_connector_descriptor_req *descs; 706 unsigned int i, num_connectors; 707 int ret; 708 709 descs = kmalloc_objs(*descs, GUD_CONNECTORS_MAX_NUM); 710 if (!descs) 711 return -ENOMEM; 712 713 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTORS, 0, 714 descs, GUD_CONNECTORS_MAX_NUM * sizeof(*descs)); 715 if (ret < 0) 716 goto free; 717 if (!ret || ret % sizeof(*descs)) { 718 ret = -EIO; 719 goto free; 720 } 721 722 num_connectors = ret / sizeof(*descs); 723 724 for (i = 0; i < num_connectors; i++) { 725 ret = gud_connector_create(gdrm, i, &descs[i]); 726 if (ret) 727 goto free; 728 } 729 free: 730 kfree(descs); 731 732 return ret; 733 } 734