Merge tag 'for-linus-6.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / gpu / drm / gud / gud_connector.c
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 }