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