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
24struct 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
44static inline struct gud_connector *to_gud_connector(struct drm_connector *connector)
45{
46	return container_of(connector, struct gud_connector, connector);
47}
48
49static 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 */
59static 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;
80retry:
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);
91out:
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);
102exit:
103	drm_dev_exit(idx);
104
105	if (ret)
106		dev_err(drm->dev, "Failed to update backlight, err=%d\n", ret);
107}
108
109static 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
120static const struct backlight_ops gud_connector_backlight_ops = {
121	.update_status	= gud_connector_backlight_update_status,
122};
123
124static 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
152static 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;
191exit:
192	drm_dev_exit(idx);
193
194	return ret;
195}
196
197struct gud_connector_get_edid_ctx {
198	void *buf;
199	size_t len;
200	bool edid_override;
201};
202
203static 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
218static 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	}
277out:
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
288static 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
318static 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
324static 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
334static 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
342static 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
351static 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
363static 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 */
378static 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);
404free:
405	kfree(buf);
406	if (ret < 0)
407		gud_conn_err(connector, "Failed to add TV modes", ret);
408
409	return ret;
410}
411
412static struct drm_property *
413gud_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
445static 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
475static 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	}
575out:
576	kfree(properties);
577
578	return ret;
579}
580
581int 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
610static 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
700int 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	}
726free:
727	kfree(descs);
728
729	return ret;
730}
731