0001
0002
0003
0004
0005
0006 #include <linux/backlight.h>
0007 #include <linux/workqueue.h>
0008
0009 #include <drm/drm_atomic.h>
0010 #include <drm/drm_atomic_state_helper.h>
0011 #include <drm/drm_connector.h>
0012 #include <drm/drm_drv.h>
0013 #include <drm/drm_edid.h>
0014 #include <drm/drm_encoder.h>
0015 #include <drm/drm_file.h>
0016 #include <drm/drm_modeset_helper_vtables.h>
0017 #include <drm/drm_print.h>
0018 #include <drm/drm_probe_helper.h>
0019 #include <drm/drm_simple_kms_helper.h>
0020 #include <drm/gud.h>
0021
0022 #include "gud_internal.h"
0023
0024 struct gud_connector {
0025 struct drm_connector connector;
0026 struct drm_encoder encoder;
0027 struct backlight_device *backlight;
0028 struct work_struct backlight_work;
0029
0030
0031 u16 *properties;
0032 unsigned int num_properties;
0033
0034
0035 struct drm_tv_connector_state initial_tv_state;
0036
0037
0038
0039
0040
0041 int initial_brightness;
0042 };
0043
0044 static inline struct gud_connector *to_gud_connector(struct drm_connector *connector)
0045 {
0046 return container_of(connector, struct gud_connector, connector);
0047 }
0048
0049 static void gud_conn_err(struct drm_connector *connector, const char *msg, int ret)
0050 {
0051 dev_err(connector->dev->dev, "%s: %s (ret=%d)\n", connector->name, msg, ret);
0052 }
0053
0054
0055
0056
0057
0058
0059 static void gud_connector_backlight_update_status_work(struct work_struct *work)
0060 {
0061 struct gud_connector *gconn = container_of(work, struct gud_connector, backlight_work);
0062 struct drm_connector *connector = &gconn->connector;
0063 struct drm_connector_state *connector_state;
0064 struct drm_device *drm = connector->dev;
0065 struct drm_modeset_acquire_ctx ctx;
0066 struct drm_atomic_state *state;
0067 int idx, ret;
0068
0069 if (!drm_dev_enter(drm, &idx))
0070 return;
0071
0072 state = drm_atomic_state_alloc(drm);
0073 if (!state) {
0074 ret = -ENOMEM;
0075 goto exit;
0076 }
0077
0078 drm_modeset_acquire_init(&ctx, 0);
0079 state->acquire_ctx = &ctx;
0080 retry:
0081 connector_state = drm_atomic_get_connector_state(state, connector);
0082 if (IS_ERR(connector_state)) {
0083 ret = PTR_ERR(connector_state);
0084 goto out;
0085 }
0086
0087
0088 connector_state->tv.brightness = gconn->backlight->props.brightness;
0089
0090 ret = drm_atomic_commit(state);
0091 out:
0092 if (ret == -EDEADLK) {
0093 drm_atomic_state_clear(state);
0094 drm_modeset_backoff(&ctx);
0095 goto retry;
0096 }
0097
0098 drm_atomic_state_put(state);
0099
0100 drm_modeset_drop_locks(&ctx);
0101 drm_modeset_acquire_fini(&ctx);
0102 exit:
0103 drm_dev_exit(idx);
0104
0105 if (ret)
0106 dev_err(drm->dev, "Failed to update backlight, err=%d\n", ret);
0107 }
0108
0109 static int gud_connector_backlight_update_status(struct backlight_device *bd)
0110 {
0111 struct drm_connector *connector = bl_get_data(bd);
0112 struct gud_connector *gconn = to_gud_connector(connector);
0113
0114
0115 queue_work(system_long_wq, &gconn->backlight_work);
0116
0117 return 0;
0118 }
0119
0120 static const struct backlight_ops gud_connector_backlight_ops = {
0121 .update_status = gud_connector_backlight_update_status,
0122 };
0123
0124 static int gud_connector_backlight_register(struct gud_connector *gconn)
0125 {
0126 struct drm_connector *connector = &gconn->connector;
0127 struct backlight_device *bd;
0128 const char *name;
0129 const struct backlight_properties props = {
0130 .type = BACKLIGHT_RAW,
0131 .scale = BACKLIGHT_SCALE_NON_LINEAR,
0132 .max_brightness = 100,
0133 .brightness = gconn->initial_brightness,
0134 };
0135
0136 name = kasprintf(GFP_KERNEL, "card%d-%s-backlight",
0137 connector->dev->primary->index, connector->name);
0138 if (!name)
0139 return -ENOMEM;
0140
0141 bd = backlight_device_register(name, connector->kdev, connector,
0142 &gud_connector_backlight_ops, &props);
0143 kfree(name);
0144 if (IS_ERR(bd))
0145 return PTR_ERR(bd);
0146
0147 gconn->backlight = bd;
0148
0149 return 0;
0150 }
0151
0152 static int gud_connector_detect(struct drm_connector *connector,
0153 struct drm_modeset_acquire_ctx *ctx, bool force)
0154 {
0155 struct gud_device *gdrm = to_gud_device(connector->dev);
0156 int idx, ret;
0157 u8 status;
0158
0159 if (!drm_dev_enter(connector->dev, &idx))
0160 return connector_status_disconnected;
0161
0162 if (force) {
0163 ret = gud_usb_set(gdrm, GUD_REQ_SET_CONNECTOR_FORCE_DETECT,
0164 connector->index, NULL, 0);
0165 if (ret) {
0166 ret = connector_status_unknown;
0167 goto exit;
0168 }
0169 }
0170
0171 ret = gud_usb_get_u8(gdrm, GUD_REQ_GET_CONNECTOR_STATUS, connector->index, &status);
0172 if (ret) {
0173 ret = connector_status_unknown;
0174 goto exit;
0175 }
0176
0177 switch (status & GUD_CONNECTOR_STATUS_CONNECTED_MASK) {
0178 case GUD_CONNECTOR_STATUS_DISCONNECTED:
0179 ret = connector_status_disconnected;
0180 break;
0181 case GUD_CONNECTOR_STATUS_CONNECTED:
0182 ret = connector_status_connected;
0183 break;
0184 default:
0185 ret = connector_status_unknown;
0186 break;
0187 }
0188
0189 if (status & GUD_CONNECTOR_STATUS_CHANGED)
0190 connector->epoch_counter += 1;
0191 exit:
0192 drm_dev_exit(idx);
0193
0194 return ret;
0195 }
0196
0197 struct gud_connector_get_edid_ctx {
0198 void *buf;
0199 size_t len;
0200 bool edid_override;
0201 };
0202
0203 static int gud_connector_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
0204 {
0205 struct gud_connector_get_edid_ctx *ctx = data;
0206 size_t start = block * EDID_LENGTH;
0207
0208 ctx->edid_override = false;
0209
0210 if (start + len > ctx->len)
0211 return -1;
0212
0213 memcpy(buf, ctx->buf + start, len);
0214
0215 return 0;
0216 }
0217
0218 static int gud_connector_get_modes(struct drm_connector *connector)
0219 {
0220 struct gud_device *gdrm = to_gud_device(connector->dev);
0221 struct gud_display_mode_req *reqmodes = NULL;
0222 struct gud_connector_get_edid_ctx edid_ctx;
0223 unsigned int i, num_modes = 0;
0224 struct edid *edid = NULL;
0225 int idx, ret;
0226
0227 if (!drm_dev_enter(connector->dev, &idx))
0228 return 0;
0229
0230 edid_ctx.edid_override = true;
0231 edid_ctx.buf = kmalloc(GUD_CONNECTOR_MAX_EDID_LEN, GFP_KERNEL);
0232 if (!edid_ctx.buf)
0233 goto out;
0234
0235 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_EDID, connector->index,
0236 edid_ctx.buf, GUD_CONNECTOR_MAX_EDID_LEN);
0237 if (ret > 0 && ret % EDID_LENGTH) {
0238 gud_conn_err(connector, "Invalid EDID size", ret);
0239 } else if (ret > 0) {
0240 edid_ctx.len = ret;
0241 edid = drm_do_get_edid(connector, gud_connector_get_edid_block, &edid_ctx);
0242 }
0243
0244 kfree(edid_ctx.buf);
0245 drm_connector_update_edid_property(connector, edid);
0246
0247 if (edid && edid_ctx.edid_override)
0248 goto out;
0249
0250 reqmodes = kmalloc_array(GUD_CONNECTOR_MAX_NUM_MODES, sizeof(*reqmodes), GFP_KERNEL);
0251 if (!reqmodes)
0252 goto out;
0253
0254 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_MODES, connector->index,
0255 reqmodes, GUD_CONNECTOR_MAX_NUM_MODES * sizeof(*reqmodes));
0256 if (ret <= 0)
0257 goto out;
0258 if (ret % sizeof(*reqmodes)) {
0259 gud_conn_err(connector, "Invalid display mode array size", ret);
0260 goto out;
0261 }
0262
0263 num_modes = ret / sizeof(*reqmodes);
0264
0265 for (i = 0; i < num_modes; i++) {
0266 struct drm_display_mode *mode;
0267
0268 mode = drm_mode_create(connector->dev);
0269 if (!mode) {
0270 num_modes = i;
0271 goto out;
0272 }
0273
0274 gud_to_display_mode(mode, &reqmodes[i]);
0275 drm_mode_probed_add(connector, mode);
0276 }
0277 out:
0278 if (!num_modes)
0279 num_modes = drm_add_edid_modes(connector, edid);
0280
0281 kfree(reqmodes);
0282 kfree(edid);
0283 drm_dev_exit(idx);
0284
0285 return num_modes;
0286 }
0287
0288 static int gud_connector_atomic_check(struct drm_connector *connector,
0289 struct drm_atomic_state *state)
0290 {
0291 struct drm_connector_state *new_state;
0292 struct drm_crtc_state *new_crtc_state;
0293 struct drm_connector_state *old_state;
0294
0295 new_state = drm_atomic_get_new_connector_state(state, connector);
0296 if (!new_state->crtc)
0297 return 0;
0298
0299 old_state = drm_atomic_get_old_connector_state(state, connector);
0300 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
0301
0302 if (old_state->tv.margins.left != new_state->tv.margins.left ||
0303 old_state->tv.margins.right != new_state->tv.margins.right ||
0304 old_state->tv.margins.top != new_state->tv.margins.top ||
0305 old_state->tv.margins.bottom != new_state->tv.margins.bottom ||
0306 old_state->tv.mode != new_state->tv.mode ||
0307 old_state->tv.brightness != new_state->tv.brightness ||
0308 old_state->tv.contrast != new_state->tv.contrast ||
0309 old_state->tv.flicker_reduction != new_state->tv.flicker_reduction ||
0310 old_state->tv.overscan != new_state->tv.overscan ||
0311 old_state->tv.saturation != new_state->tv.saturation ||
0312 old_state->tv.hue != new_state->tv.hue)
0313 new_crtc_state->connectors_changed = true;
0314
0315 return 0;
0316 }
0317
0318 static const struct drm_connector_helper_funcs gud_connector_helper_funcs = {
0319 .detect_ctx = gud_connector_detect,
0320 .get_modes = gud_connector_get_modes,
0321 .atomic_check = gud_connector_atomic_check,
0322 };
0323
0324 static int gud_connector_late_register(struct drm_connector *connector)
0325 {
0326 struct gud_connector *gconn = to_gud_connector(connector);
0327
0328 if (gconn->initial_brightness < 0)
0329 return 0;
0330
0331 return gud_connector_backlight_register(gconn);
0332 }
0333
0334 static void gud_connector_early_unregister(struct drm_connector *connector)
0335 {
0336 struct gud_connector *gconn = to_gud_connector(connector);
0337
0338 backlight_device_unregister(gconn->backlight);
0339 cancel_work_sync(&gconn->backlight_work);
0340 }
0341
0342 static void gud_connector_destroy(struct drm_connector *connector)
0343 {
0344 struct gud_connector *gconn = to_gud_connector(connector);
0345
0346 drm_connector_cleanup(connector);
0347 kfree(gconn->properties);
0348 kfree(gconn);
0349 }
0350
0351 static void gud_connector_reset(struct drm_connector *connector)
0352 {
0353 struct gud_connector *gconn = to_gud_connector(connector);
0354
0355 drm_atomic_helper_connector_reset(connector);
0356 connector->state->tv = gconn->initial_tv_state;
0357
0358 drm_atomic_helper_connector_tv_reset(connector);
0359 if (gconn->initial_brightness >= 0)
0360 connector->state->tv.brightness = gconn->initial_brightness;
0361 }
0362
0363 static const struct drm_connector_funcs gud_connector_funcs = {
0364 .fill_modes = drm_helper_probe_single_connector_modes,
0365 .late_register = gud_connector_late_register,
0366 .early_unregister = gud_connector_early_unregister,
0367 .destroy = gud_connector_destroy,
0368 .reset = gud_connector_reset,
0369 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0370 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0371 };
0372
0373
0374
0375
0376
0377
0378 static int gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connector *connector)
0379 {
0380 size_t buf_len = GUD_CONNECTOR_TV_MODE_MAX_NUM * GUD_CONNECTOR_TV_MODE_NAME_LEN;
0381 const char *modes[GUD_CONNECTOR_TV_MODE_MAX_NUM];
0382 unsigned int i, num_modes;
0383 char *buf;
0384 int ret;
0385
0386 buf = kmalloc(buf_len, GFP_KERNEL);
0387 if (!buf)
0388 return -ENOMEM;
0389
0390 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_TV_MODE_VALUES,
0391 connector->index, buf, buf_len);
0392 if (ret < 0)
0393 goto free;
0394 if (!ret || ret % GUD_CONNECTOR_TV_MODE_NAME_LEN) {
0395 ret = -EIO;
0396 goto free;
0397 }
0398
0399 num_modes = ret / GUD_CONNECTOR_TV_MODE_NAME_LEN;
0400 for (i = 0; i < num_modes; i++)
0401 modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN];
0402
0403 ret = drm_mode_create_tv_properties(connector->dev, num_modes, modes);
0404 free:
0405 kfree(buf);
0406 if (ret < 0)
0407 gud_conn_err(connector, "Failed to add TV modes", ret);
0408
0409 return ret;
0410 }
0411
0412 static struct drm_property *
0413 gud_connector_property_lookup(struct drm_connector *connector, u16 prop)
0414 {
0415 struct drm_mode_config *config = &connector->dev->mode_config;
0416
0417 switch (prop) {
0418 case GUD_PROPERTY_TV_LEFT_MARGIN:
0419 return config->tv_left_margin_property;
0420 case GUD_PROPERTY_TV_RIGHT_MARGIN:
0421 return config->tv_right_margin_property;
0422 case GUD_PROPERTY_TV_TOP_MARGIN:
0423 return config->tv_top_margin_property;
0424 case GUD_PROPERTY_TV_BOTTOM_MARGIN:
0425 return config->tv_bottom_margin_property;
0426 case GUD_PROPERTY_TV_MODE:
0427 return config->tv_mode_property;
0428 case GUD_PROPERTY_TV_BRIGHTNESS:
0429 return config->tv_brightness_property;
0430 case GUD_PROPERTY_TV_CONTRAST:
0431 return config->tv_contrast_property;
0432 case GUD_PROPERTY_TV_FLICKER_REDUCTION:
0433 return config->tv_flicker_reduction_property;
0434 case GUD_PROPERTY_TV_OVERSCAN:
0435 return config->tv_overscan_property;
0436 case GUD_PROPERTY_TV_SATURATION:
0437 return config->tv_saturation_property;
0438 case GUD_PROPERTY_TV_HUE:
0439 return config->tv_hue_property;
0440 default:
0441 return ERR_PTR(-EINVAL);
0442 }
0443 }
0444
0445 static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connector_state *state)
0446 {
0447 switch (prop) {
0448 case GUD_PROPERTY_TV_LEFT_MARGIN:
0449 return &state->margins.left;
0450 case GUD_PROPERTY_TV_RIGHT_MARGIN:
0451 return &state->margins.right;
0452 case GUD_PROPERTY_TV_TOP_MARGIN:
0453 return &state->margins.top;
0454 case GUD_PROPERTY_TV_BOTTOM_MARGIN:
0455 return &state->margins.bottom;
0456 case GUD_PROPERTY_TV_MODE:
0457 return &state->mode;
0458 case GUD_PROPERTY_TV_BRIGHTNESS:
0459 return &state->brightness;
0460 case GUD_PROPERTY_TV_CONTRAST:
0461 return &state->contrast;
0462 case GUD_PROPERTY_TV_FLICKER_REDUCTION:
0463 return &state->flicker_reduction;
0464 case GUD_PROPERTY_TV_OVERSCAN:
0465 return &state->overscan;
0466 case GUD_PROPERTY_TV_SATURATION:
0467 return &state->saturation;
0468 case GUD_PROPERTY_TV_HUE:
0469 return &state->hue;
0470 default:
0471 return ERR_PTR(-EINVAL);
0472 }
0473 }
0474
0475 static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_connector *gconn)
0476 {
0477 struct drm_connector *connector = &gconn->connector;
0478 struct drm_device *drm = &gdrm->drm;
0479 struct gud_property_req *properties;
0480 unsigned int i, num_properties;
0481 int ret;
0482
0483 properties = kcalloc(GUD_CONNECTOR_PROPERTIES_MAX_NUM, sizeof(*properties), GFP_KERNEL);
0484 if (!properties)
0485 return -ENOMEM;
0486
0487 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_PROPERTIES, connector->index,
0488 properties, GUD_CONNECTOR_PROPERTIES_MAX_NUM * sizeof(*properties));
0489 if (ret <= 0)
0490 goto out;
0491 if (ret % sizeof(*properties)) {
0492 ret = -EIO;
0493 goto out;
0494 }
0495
0496 num_properties = ret / sizeof(*properties);
0497 ret = 0;
0498
0499 gconn->properties = kcalloc(num_properties, sizeof(*gconn->properties), GFP_KERNEL);
0500 if (!gconn->properties) {
0501 ret = -ENOMEM;
0502 goto out;
0503 }
0504
0505 for (i = 0; i < num_properties; i++) {
0506 u16 prop = le16_to_cpu(properties[i].prop);
0507 u64 val = le64_to_cpu(properties[i].val);
0508 struct drm_property *property;
0509 unsigned int *state_val;
0510
0511 drm_dbg(drm, "property: %u = %llu(0x%llx)\n", prop, val, val);
0512
0513 switch (prop) {
0514 case GUD_PROPERTY_TV_LEFT_MARGIN:
0515 fallthrough;
0516 case GUD_PROPERTY_TV_RIGHT_MARGIN:
0517 fallthrough;
0518 case GUD_PROPERTY_TV_TOP_MARGIN:
0519 fallthrough;
0520 case GUD_PROPERTY_TV_BOTTOM_MARGIN:
0521 ret = drm_mode_create_tv_margin_properties(drm);
0522 if (ret)
0523 goto out;
0524 break;
0525 case GUD_PROPERTY_TV_MODE:
0526 ret = gud_connector_add_tv_mode(gdrm, connector);
0527 if (ret)
0528 goto out;
0529 break;
0530 case GUD_PROPERTY_TV_BRIGHTNESS:
0531 fallthrough;
0532 case GUD_PROPERTY_TV_CONTRAST:
0533 fallthrough;
0534 case GUD_PROPERTY_TV_FLICKER_REDUCTION:
0535 fallthrough;
0536 case GUD_PROPERTY_TV_OVERSCAN:
0537 fallthrough;
0538 case GUD_PROPERTY_TV_SATURATION:
0539 fallthrough;
0540 case GUD_PROPERTY_TV_HUE:
0541
0542 ret = drm_mode_create_tv_properties(drm, 0, NULL);
0543 if (ret)
0544 goto out;
0545 break;
0546 case GUD_PROPERTY_BACKLIGHT_BRIGHTNESS:
0547 if (val > 100) {
0548 ret = -EINVAL;
0549 goto out;
0550 }
0551 gconn->initial_brightness = val;
0552 break;
0553 default:
0554
0555 drm_dbg(drm, "Ignoring unknown property: %u\n", prop);
0556 continue;
0557 }
0558
0559 gconn->properties[gconn->num_properties++] = prop;
0560
0561 if (prop == GUD_PROPERTY_BACKLIGHT_BRIGHTNESS)
0562 continue;
0563
0564 property = gud_connector_property_lookup(connector, prop);
0565 if (WARN_ON(IS_ERR(property)))
0566 continue;
0567
0568 state_val = gud_connector_tv_state_val(prop, &gconn->initial_tv_state);
0569 if (WARN_ON(IS_ERR(state_val)))
0570 continue;
0571
0572 *state_val = val;
0573 drm_object_attach_property(&connector->base, property, 0);
0574 }
0575 out:
0576 kfree(properties);
0577
0578 return ret;
0579 }
0580
0581 int gud_connector_fill_properties(struct drm_connector_state *connector_state,
0582 struct gud_property_req *properties)
0583 {
0584 struct gud_connector *gconn = to_gud_connector(connector_state->connector);
0585 unsigned int i;
0586
0587 for (i = 0; i < gconn->num_properties; i++) {
0588 u16 prop = gconn->properties[i];
0589 u64 val;
0590
0591 if (prop == GUD_PROPERTY_BACKLIGHT_BRIGHTNESS) {
0592 val = connector_state->tv.brightness;
0593 } else {
0594 unsigned int *state_val;
0595
0596 state_val = gud_connector_tv_state_val(prop, &connector_state->tv);
0597 if (WARN_ON_ONCE(IS_ERR(state_val)))
0598 return PTR_ERR(state_val);
0599
0600 val = *state_val;
0601 }
0602
0603 properties[i].prop = cpu_to_le16(prop);
0604 properties[i].val = cpu_to_le64(val);
0605 }
0606
0607 return gconn->num_properties;
0608 }
0609
0610 static int gud_connector_create(struct gud_device *gdrm, unsigned int index,
0611 struct gud_connector_descriptor_req *desc)
0612 {
0613 struct drm_device *drm = &gdrm->drm;
0614 struct gud_connector *gconn;
0615 struct drm_connector *connector;
0616 struct drm_encoder *encoder;
0617 int ret, connector_type;
0618 u32 flags;
0619
0620 gconn = kzalloc(sizeof(*gconn), GFP_KERNEL);
0621 if (!gconn)
0622 return -ENOMEM;
0623
0624 INIT_WORK(&gconn->backlight_work, gud_connector_backlight_update_status_work);
0625 gconn->initial_brightness = -ENODEV;
0626 flags = le32_to_cpu(desc->flags);
0627 connector = &gconn->connector;
0628
0629 drm_dbg(drm, "Connector: index=%u type=%u flags=0x%x\n", index, desc->connector_type, flags);
0630
0631 switch (desc->connector_type) {
0632 case GUD_CONNECTOR_TYPE_PANEL:
0633 connector_type = DRM_MODE_CONNECTOR_USB;
0634 break;
0635 case GUD_CONNECTOR_TYPE_VGA:
0636 connector_type = DRM_MODE_CONNECTOR_VGA;
0637 break;
0638 case GUD_CONNECTOR_TYPE_DVI:
0639 connector_type = DRM_MODE_CONNECTOR_DVID;
0640 break;
0641 case GUD_CONNECTOR_TYPE_COMPOSITE:
0642 connector_type = DRM_MODE_CONNECTOR_Composite;
0643 break;
0644 case GUD_CONNECTOR_TYPE_SVIDEO:
0645 connector_type = DRM_MODE_CONNECTOR_SVIDEO;
0646 break;
0647 case GUD_CONNECTOR_TYPE_COMPONENT:
0648 connector_type = DRM_MODE_CONNECTOR_Component;
0649 break;
0650 case GUD_CONNECTOR_TYPE_DISPLAYPORT:
0651 connector_type = DRM_MODE_CONNECTOR_DisplayPort;
0652 break;
0653 case GUD_CONNECTOR_TYPE_HDMI:
0654 connector_type = DRM_MODE_CONNECTOR_HDMIA;
0655 break;
0656 default:
0657 connector_type = DRM_MODE_CONNECTOR_USB;
0658 break;
0659 }
0660
0661 drm_connector_helper_add(connector, &gud_connector_helper_funcs);
0662 ret = drm_connector_init(drm, connector, &gud_connector_funcs, connector_type);
0663 if (ret) {
0664 kfree(connector);
0665 return ret;
0666 }
0667
0668 if (WARN_ON(connector->index != index))
0669 return -EINVAL;
0670
0671 if (flags & GUD_CONNECTOR_FLAGS_POLL_STATUS)
0672 connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT);
0673 if (flags & GUD_CONNECTOR_FLAGS_INTERLACE)
0674 connector->interlace_allowed = true;
0675 if (flags & GUD_CONNECTOR_FLAGS_DOUBLESCAN)
0676 connector->doublescan_allowed = true;
0677
0678 ret = gud_connector_add_properties(gdrm, gconn);
0679 if (ret) {
0680 gud_conn_err(connector, "Failed to add properties", ret);
0681 return ret;
0682 }
0683
0684
0685 if (!connector->index) {
0686 encoder = &gdrm->pipe.encoder;
0687 } else {
0688 encoder = &gconn->encoder;
0689
0690 ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
0691 if (ret)
0692 return ret;
0693
0694 encoder->possible_crtcs = 1;
0695 }
0696
0697 return drm_connector_attach_encoder(connector, encoder);
0698 }
0699
0700 int gud_get_connectors(struct gud_device *gdrm)
0701 {
0702 struct gud_connector_descriptor_req *descs;
0703 unsigned int i, num_connectors;
0704 int ret;
0705
0706 descs = kmalloc_array(GUD_CONNECTORS_MAX_NUM, sizeof(*descs), GFP_KERNEL);
0707 if (!descs)
0708 return -ENOMEM;
0709
0710 ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTORS, 0,
0711 descs, GUD_CONNECTORS_MAX_NUM * sizeof(*descs));
0712 if (ret < 0)
0713 goto free;
0714 if (!ret || ret % sizeof(*descs)) {
0715 ret = -EIO;
0716 goto free;
0717 }
0718
0719 num_connectors = ret / sizeof(*descs);
0720
0721 for (i = 0; i < num_connectors; i++) {
0722 ret = gud_connector_create(gdrm, i, &descs[i]);
0723 if (ret)
0724 goto free;
0725 }
0726 free:
0727 kfree(descs);
0728
0729 return ret;
0730 }