1/*
2 * Copyright (c) 2006-2009 Red Hat Inc.
3 * Copyright (c) 2006-2008 Intel Corporation
4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
5 *
6 * DRM framebuffer helper functions
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that copyright
11 * notice and this permission notice appear in supporting documentation, and
12 * that the name of the copyright holders not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission.  The copyright holders make no representations
15 * about the suitability of this software for any purpose.  It is provided "as
16 * is" without express or implied warranty.
17 *
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 *
26 * Authors:
27 *      Dave Airlie <airlied@linux.ie>
28 *      Jesse Barnes <jesse.barnes@intel.com>
29 */
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#include <linux/kernel.h>
33#include <linux/sysrq.h>
34#include <linux/slab.h>
35#include <linux/fb.h>
36#include <linux/module.h>
37#include <drm/drmP.h>
38#include <drm/drm_crtc.h>
39#include <drm/drm_fb_helper.h>
40#include <drm/drm_crtc_helper.h>
41
42static LIST_HEAD(kernel_fb_helper_list);
43
44/**
45 * DOC: fbdev helpers
46 *
47 * The fb helper functions are useful to provide an fbdev on top of a drm kernel
48 * mode setting driver. They can be used mostly independently from the crtc
49 * helper functions used by many drivers to implement the kernel mode setting
50 * interfaces.
51 *
52 * Initialization is done as a four-step process with drm_fb_helper_prepare(),
53 * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
54 * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
55 * default behaviour can override the third step with their own code.
56 * Teardown is done with drm_fb_helper_fini().
57 *
58 * At runtime drivers should restore the fbdev console by calling
59 * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
60 * should also notify the fb helper code from updates to the output
61 * configuration by calling drm_fb_helper_hotplug_event(). For easier
62 * integration with the output polling code in drm_crtc_helper.c the modeset
63 * code provides a ->output_poll_changed callback.
64 *
65 * All other functions exported by the fb helper library can be used to
66 * implement the fbdev driver interface by the driver.
67 *
68 * It is possible, though perhaps somewhat tricky, to implement race-free
69 * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
70 * helper must be called first to initialize the minimum required to make
71 * hotplug detection work. Drivers also need to make sure to properly set up
72 * the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init()
73 * it is safe to enable interrupts and start processing hotplug events. At the
74 * same time, drivers should initialize all modeset objects such as CRTCs,
75 * encoders and connectors. To finish up the fbdev helper initialization, the
76 * drm_fb_helper_init() function is called. To probe for all attached displays
77 * and set up an initial configuration using the detected hardware, drivers
78 * should call drm_fb_helper_single_add_all_connectors() followed by
79 * drm_fb_helper_initial_config().
80 */
81
82/**
83 * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
84 * 					       emulation helper
85 * @fb_helper: fbdev initialized with drm_fb_helper_init
86 *
87 * This functions adds all the available connectors for use with the given
88 * fb_helper. This is a separate step to allow drivers to freely assign
89 * connectors to the fbdev, e.g. if some are reserved for special purposes or
90 * not adequate to be used for the fbcon.
91 *
92 * Since this is part of the initial setup before the fbdev is published, no
93 * locking is required.
94 */
95int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
96{
97	struct drm_device *dev = fb_helper->dev;
98	struct drm_connector *connector;
99	int i;
100
101	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
102		struct drm_fb_helper_connector *fb_helper_connector;
103
104		fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
105		if (!fb_helper_connector)
106			goto fail;
107
108		fb_helper_connector->connector = connector;
109		fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
110	}
111	return 0;
112fail:
113	for (i = 0; i < fb_helper->connector_count; i++) {
114		kfree(fb_helper->connector_info[i]);
115		fb_helper->connector_info[i] = NULL;
116	}
117	fb_helper->connector_count = 0;
118	return -ENOMEM;
119}
120EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
121
122int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector)
123{
124	struct drm_fb_helper_connector **temp;
125	struct drm_fb_helper_connector *fb_helper_connector;
126
127	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
128	if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
129		temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
130		if (!temp)
131			return -ENOMEM;
132
133		fb_helper->connector_info_alloc_count = fb_helper->connector_count + 1;
134		fb_helper->connector_info = temp;
135	}
136
137
138	fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
139	if (!fb_helper_connector)
140		return -ENOMEM;
141
142	fb_helper_connector->connector = connector;
143	fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
144	return 0;
145}
146EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
147
148static void remove_from_modeset(struct drm_mode_set *set,
149		struct drm_connector *connector)
150{
151	int i, j;
152
153	for (i = 0; i < set->num_connectors; i++) {
154		if (set->connectors[i] == connector)
155			break;
156	}
157
158	if (i == set->num_connectors)
159		return;
160
161	for (j = i + 1; j < set->num_connectors; j++) {
162		set->connectors[j - 1] = set->connectors[j];
163	}
164	set->num_connectors--;
165
166	/* because i915 is pissy about this..
167	 * TODO maybe need to makes sure we set it back to !=NULL somewhere?
168	 */
169	if (set->num_connectors == 0)
170		set->fb = NULL;
171}
172
173int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
174				       struct drm_connector *connector)
175{
176	struct drm_fb_helper_connector *fb_helper_connector;
177	int i, j;
178
179	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
180
181	for (i = 0; i < fb_helper->connector_count; i++) {
182		if (fb_helper->connector_info[i]->connector == connector)
183			break;
184	}
185
186	if (i == fb_helper->connector_count)
187		return -EINVAL;
188	fb_helper_connector = fb_helper->connector_info[i];
189
190	for (j = i + 1; j < fb_helper->connector_count; j++) {
191		fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
192	}
193	fb_helper->connector_count--;
194	kfree(fb_helper_connector);
195
196	/* also cleanup dangling references to the connector: */
197	for (i = 0; i < fb_helper->crtc_count; i++)
198		remove_from_modeset(&fb_helper->crtc_info[i].mode_set, connector);
199
200	return 0;
201}
202EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
203
204static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
205{
206	uint16_t *r_base, *g_base, *b_base;
207	int i;
208
209	if (helper->funcs->gamma_get == NULL)
210		return;
211
212	r_base = crtc->gamma_store;
213	g_base = r_base + crtc->gamma_size;
214	b_base = g_base + crtc->gamma_size;
215
216	for (i = 0; i < crtc->gamma_size; i++)
217		helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i);
218}
219
220static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
221{
222	uint16_t *r_base, *g_base, *b_base;
223
224	if (crtc->funcs->gamma_set == NULL)
225		return;
226
227	r_base = crtc->gamma_store;
228	g_base = r_base + crtc->gamma_size;
229	b_base = g_base + crtc->gamma_size;
230
231	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
232}
233
234/**
235 * drm_fb_helper_debug_enter - implementation for ->fb_debug_enter
236 * @info: fbdev registered by the helper
237 */
238int drm_fb_helper_debug_enter(struct fb_info *info)
239{
240	struct drm_fb_helper *helper = info->par;
241	const struct drm_crtc_helper_funcs *funcs;
242	int i;
243
244	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
245		for (i = 0; i < helper->crtc_count; i++) {
246			struct drm_mode_set *mode_set =
247				&helper->crtc_info[i].mode_set;
248
249			if (!mode_set->crtc->enabled)
250				continue;
251
252			funcs =	mode_set->crtc->helper_private;
253			drm_fb_helper_save_lut_atomic(mode_set->crtc, helper);
254			funcs->mode_set_base_atomic(mode_set->crtc,
255						    mode_set->fb,
256						    mode_set->x,
257						    mode_set->y,
258						    ENTER_ATOMIC_MODE_SET);
259		}
260	}
261
262	return 0;
263}
264EXPORT_SYMBOL(drm_fb_helper_debug_enter);
265
266/* Find the real fb for a given fb helper CRTC */
267static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
268{
269	struct drm_device *dev = crtc->dev;
270	struct drm_crtc *c;
271
272	list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
273		if (crtc->base.id == c->base.id)
274			return c->primary->fb;
275	}
276
277	return NULL;
278}
279
280/**
281 * drm_fb_helper_debug_leave - implementation for ->fb_debug_leave
282 * @info: fbdev registered by the helper
283 */
284int drm_fb_helper_debug_leave(struct fb_info *info)
285{
286	struct drm_fb_helper *helper = info->par;
287	struct drm_crtc *crtc;
288	const struct drm_crtc_helper_funcs *funcs;
289	struct drm_framebuffer *fb;
290	int i;
291
292	for (i = 0; i < helper->crtc_count; i++) {
293		struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
294		crtc = mode_set->crtc;
295		funcs = crtc->helper_private;
296		fb = drm_mode_config_fb(crtc);
297
298		if (!crtc->enabled)
299			continue;
300
301		if (!fb) {
302			DRM_ERROR("no fb to restore??\n");
303			continue;
304		}
305
306		drm_fb_helper_restore_lut_atomic(mode_set->crtc);
307		funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
308					    crtc->y, LEAVE_ATOMIC_MODE_SET);
309	}
310
311	return 0;
312}
313EXPORT_SYMBOL(drm_fb_helper_debug_leave);
314
315static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
316{
317	struct drm_device *dev = fb_helper->dev;
318	struct drm_plane *plane;
319	bool error = false;
320	int i;
321
322	drm_warn_on_modeset_not_all_locked(dev);
323
324	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
325		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
326			drm_plane_force_disable(plane);
327
328		if (dev->mode_config.rotation_property) {
329			drm_mode_plane_set_obj_prop(plane,
330						    dev->mode_config.rotation_property,
331						    BIT(DRM_ROTATE_0));
332		}
333	}
334
335	for (i = 0; i < fb_helper->crtc_count; i++) {
336		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
337		struct drm_crtc *crtc = mode_set->crtc;
338		int ret;
339
340		if (crtc->funcs->cursor_set) {
341			ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
342			if (ret)
343				error = true;
344		}
345
346		ret = drm_mode_set_config_internal(mode_set);
347		if (ret)
348			error = true;
349	}
350	return error;
351}
352/**
353 * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
354 * @fb_helper: fbcon to restore
355 *
356 * This should be called from driver's drm ->lastclose callback
357 * when implementing an fbcon on top of kms using this helper. This ensures that
358 * the user isn't greeted with a black screen when e.g. X dies.
359 *
360 * Use this variant if you need to bypass locking (panic), or already
361 * hold all modeset locks.  Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
362 */
363static bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
364{
365	return restore_fbdev_mode(fb_helper);
366}
367
368/**
369 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
370 * @fb_helper: fbcon to restore
371 *
372 * This should be called from driver's drm ->lastclose callback
373 * when implementing an fbcon on top of kms using this helper. This ensures that
374 * the user isn't greeted with a black screen when e.g. X dies.
375 */
376bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
377{
378	struct drm_device *dev = fb_helper->dev;
379	bool ret;
380	bool do_delayed = false;
381
382	drm_modeset_lock_all(dev);
383	ret = restore_fbdev_mode(fb_helper);
384
385	do_delayed = fb_helper->delayed_hotplug;
386	if (do_delayed)
387		fb_helper->delayed_hotplug = false;
388	drm_modeset_unlock_all(dev);
389
390	if (do_delayed)
391		drm_fb_helper_hotplug_event(fb_helper);
392	return ret;
393}
394EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
395
396/*
397 * restore fbcon display for all kms driver's using this helper, used for sysrq
398 * and panic handling.
399 */
400static bool drm_fb_helper_force_kernel_mode(void)
401{
402	bool ret, error = false;
403	struct drm_fb_helper *helper;
404
405	if (list_empty(&kernel_fb_helper_list))
406		return false;
407
408	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
409		struct drm_device *dev = helper->dev;
410
411		if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
412			continue;
413
414		/*
415		 * NOTE: Use trylock mode to avoid deadlocks and sleeping in
416		 * panic context.
417		 */
418		if (__drm_modeset_lock_all(dev, true) != 0) {
419			error = true;
420			continue;
421		}
422
423		ret = drm_fb_helper_restore_fbdev_mode(helper);
424		if (ret)
425			error = true;
426
427		drm_modeset_unlock_all(dev);
428	}
429	return error;
430}
431
432static int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
433			void *panic_str)
434{
435	/*
436	 * It's a waste of time and effort to switch back to text console
437	 * if the kernel should reboot before panic messages can be seen.
438	 */
439	if (panic_timeout < 0)
440		return 0;
441
442	pr_err("panic occurred, switching back to text console\n");
443	return drm_fb_helper_force_kernel_mode();
444}
445
446static struct notifier_block paniced = {
447	.notifier_call = drm_fb_helper_panic,
448};
449
450static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
451{
452	struct drm_device *dev = fb_helper->dev;
453	struct drm_crtc *crtc;
454	int bound = 0, crtcs_bound = 0;
455
456	/* Sometimes user space wants everything disabled, so don't steal the
457	 * display if there's a master. */
458	if (dev->primary->master)
459		return false;
460
461	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
462		if (crtc->primary->fb)
463			crtcs_bound++;
464		if (crtc->primary->fb == fb_helper->fb)
465			bound++;
466	}
467
468	if (bound < crtcs_bound)
469		return false;
470
471	return true;
472}
473
474#ifdef CONFIG_MAGIC_SYSRQ
475static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
476{
477	bool ret;
478	ret = drm_fb_helper_force_kernel_mode();
479	if (ret == true)
480		DRM_ERROR("Failed to restore crtc configuration\n");
481}
482static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
483
484static void drm_fb_helper_sysrq(int dummy1)
485{
486	schedule_work(&drm_fb_helper_restore_work);
487}
488
489static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
490	.handler = drm_fb_helper_sysrq,
491	.help_msg = "force-fb(V)",
492	.action_msg = "Restore framebuffer console",
493};
494#else
495static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
496#endif
497
498static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
499{
500	struct drm_fb_helper *fb_helper = info->par;
501	struct drm_device *dev = fb_helper->dev;
502	struct drm_crtc *crtc;
503	struct drm_connector *connector;
504	int i, j;
505
506	/*
507	 * fbdev->blank can be called from irq context in case of a panic.
508	 * Since we already have our own special panic handler which will
509	 * restore the fbdev console mode completely, just bail out early.
510	 */
511	if (oops_in_progress)
512		return;
513
514	/*
515	 * For each CRTC in this fb, turn the connectors on/off.
516	 */
517	drm_modeset_lock_all(dev);
518	if (!drm_fb_helper_is_bound(fb_helper)) {
519		drm_modeset_unlock_all(dev);
520		return;
521	}
522
523	for (i = 0; i < fb_helper->crtc_count; i++) {
524		crtc = fb_helper->crtc_info[i].mode_set.crtc;
525
526		if (!crtc->enabled)
527			continue;
528
529		/* Walk the connectors & encoders on this fb turning them on/off */
530		for (j = 0; j < fb_helper->connector_count; j++) {
531			connector = fb_helper->connector_info[j]->connector;
532			connector->funcs->dpms(connector, dpms_mode);
533			drm_object_property_set_value(&connector->base,
534				dev->mode_config.dpms_property, dpms_mode);
535		}
536	}
537	drm_modeset_unlock_all(dev);
538}
539
540/**
541 * drm_fb_helper_blank - implementation for ->fb_blank
542 * @blank: desired blanking state
543 * @info: fbdev registered by the helper
544 */
545int drm_fb_helper_blank(int blank, struct fb_info *info)
546{
547	switch (blank) {
548	/* Display: On; HSync: On, VSync: On */
549	case FB_BLANK_UNBLANK:
550		drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON);
551		break;
552	/* Display: Off; HSync: On, VSync: On */
553	case FB_BLANK_NORMAL:
554		drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
555		break;
556	/* Display: Off; HSync: Off, VSync: On */
557	case FB_BLANK_HSYNC_SUSPEND:
558		drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
559		break;
560	/* Display: Off; HSync: On, VSync: Off */
561	case FB_BLANK_VSYNC_SUSPEND:
562		drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND);
563		break;
564	/* Display: Off; HSync: Off, VSync: Off */
565	case FB_BLANK_POWERDOWN:
566		drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF);
567		break;
568	}
569	return 0;
570}
571EXPORT_SYMBOL(drm_fb_helper_blank);
572
573static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
574{
575	int i;
576
577	for (i = 0; i < helper->connector_count; i++)
578		kfree(helper->connector_info[i]);
579	kfree(helper->connector_info);
580	for (i = 0; i < helper->crtc_count; i++) {
581		kfree(helper->crtc_info[i].mode_set.connectors);
582		if (helper->crtc_info[i].mode_set.mode)
583			drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode);
584	}
585	kfree(helper->crtc_info);
586}
587
588/**
589 * drm_fb_helper_prepare - setup a drm_fb_helper structure
590 * @dev: DRM device
591 * @helper: driver-allocated fbdev helper structure to set up
592 * @funcs: pointer to structure of functions associate with this helper
593 *
594 * Sets up the bare minimum to make the framebuffer helper usable. This is
595 * useful to implement race-free initialization of the polling helpers.
596 */
597void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
598			   const struct drm_fb_helper_funcs *funcs)
599{
600	INIT_LIST_HEAD(&helper->kernel_fb_list);
601	helper->funcs = funcs;
602	helper->dev = dev;
603}
604EXPORT_SYMBOL(drm_fb_helper_prepare);
605
606/**
607 * drm_fb_helper_init - initialize a drm_fb_helper structure
608 * @dev: drm device
609 * @fb_helper: driver-allocated fbdev helper structure to initialize
610 * @crtc_count: maximum number of crtcs to support in this fbdev emulation
611 * @max_conn_count: max connector count
612 *
613 * This allocates the structures for the fbdev helper with the given limits.
614 * Note that this won't yet touch the hardware (through the driver interfaces)
615 * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
616 * to allow driver writes more control over the exact init sequence.
617 *
618 * Drivers must call drm_fb_helper_prepare() before calling this function.
619 *
620 * RETURNS:
621 * Zero if everything went ok, nonzero otherwise.
622 */
623int drm_fb_helper_init(struct drm_device *dev,
624		       struct drm_fb_helper *fb_helper,
625		       int crtc_count, int max_conn_count)
626{
627	struct drm_crtc *crtc;
628	int i;
629
630	if (!max_conn_count)
631		return -EINVAL;
632
633	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
634	if (!fb_helper->crtc_info)
635		return -ENOMEM;
636
637	fb_helper->crtc_count = crtc_count;
638	fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
639	if (!fb_helper->connector_info) {
640		kfree(fb_helper->crtc_info);
641		return -ENOMEM;
642	}
643	fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
644	fb_helper->connector_count = 0;
645
646	for (i = 0; i < crtc_count; i++) {
647		fb_helper->crtc_info[i].mode_set.connectors =
648			kcalloc(max_conn_count,
649				sizeof(struct drm_connector *),
650				GFP_KERNEL);
651
652		if (!fb_helper->crtc_info[i].mode_set.connectors)
653			goto out_free;
654		fb_helper->crtc_info[i].mode_set.num_connectors = 0;
655	}
656
657	i = 0;
658	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
659		fb_helper->crtc_info[i].mode_set.crtc = crtc;
660		i++;
661	}
662
663	return 0;
664out_free:
665	drm_fb_helper_crtc_free(fb_helper);
666	return -ENOMEM;
667}
668EXPORT_SYMBOL(drm_fb_helper_init);
669
670void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
671{
672	if (!list_empty(&fb_helper->kernel_fb_list)) {
673		list_del(&fb_helper->kernel_fb_list);
674		if (list_empty(&kernel_fb_helper_list)) {
675			pr_info("drm: unregistered panic notifier\n");
676			atomic_notifier_chain_unregister(&panic_notifier_list,
677							 &paniced);
678			unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
679		}
680	}
681
682	drm_fb_helper_crtc_free(fb_helper);
683
684}
685EXPORT_SYMBOL(drm_fb_helper_fini);
686
687static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
688		     u16 blue, u16 regno, struct fb_info *info)
689{
690	struct drm_fb_helper *fb_helper = info->par;
691	struct drm_framebuffer *fb = fb_helper->fb;
692	int pindex;
693
694	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
695		u32 *palette;
696		u32 value;
697		/* place color in psuedopalette */
698		if (regno > 16)
699			return -EINVAL;
700		palette = (u32 *)info->pseudo_palette;
701		red >>= (16 - info->var.red.length);
702		green >>= (16 - info->var.green.length);
703		blue >>= (16 - info->var.blue.length);
704		value = (red << info->var.red.offset) |
705			(green << info->var.green.offset) |
706			(blue << info->var.blue.offset);
707		if (info->var.transp.length > 0) {
708			u32 mask = (1 << info->var.transp.length) - 1;
709			mask <<= info->var.transp.offset;
710			value |= mask;
711		}
712		palette[regno] = value;
713		return 0;
714	}
715
716	/*
717	 * The driver really shouldn't advertise pseudo/directcolor
718	 * visuals if it can't deal with the palette.
719	 */
720	if (WARN_ON(!fb_helper->funcs->gamma_set ||
721		    !fb_helper->funcs->gamma_get))
722		return -EINVAL;
723
724	pindex = regno;
725
726	if (fb->bits_per_pixel == 16) {
727		pindex = regno << 3;
728
729		if (fb->depth == 16 && regno > 63)
730			return -EINVAL;
731		if (fb->depth == 15 && regno > 31)
732			return -EINVAL;
733
734		if (fb->depth == 16) {
735			u16 r, g, b;
736			int i;
737			if (regno < 32) {
738				for (i = 0; i < 8; i++)
739					fb_helper->funcs->gamma_set(crtc, red,
740						green, blue, pindex + i);
741			}
742
743			fb_helper->funcs->gamma_get(crtc, &r,
744						    &g, &b,
745						    pindex >> 1);
746
747			for (i = 0; i < 4; i++)
748				fb_helper->funcs->gamma_set(crtc, r,
749							    green, b,
750							    (pindex >> 1) + i);
751		}
752	}
753
754	if (fb->depth != 16)
755		fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
756	return 0;
757}
758
759/**
760 * drm_fb_helper_setcmap - implementation for ->fb_setcmap
761 * @cmap: cmap to set
762 * @info: fbdev registered by the helper
763 */
764int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
765{
766	struct drm_fb_helper *fb_helper = info->par;
767	struct drm_device *dev = fb_helper->dev;
768	const struct drm_crtc_helper_funcs *crtc_funcs;
769	u16 *red, *green, *blue, *transp;
770	struct drm_crtc *crtc;
771	int i, j, rc = 0;
772	int start;
773
774	if (__drm_modeset_lock_all(dev, !!oops_in_progress)) {
775		return -EBUSY;
776	}
777	if (!drm_fb_helper_is_bound(fb_helper)) {
778		drm_modeset_unlock_all(dev);
779		return -EBUSY;
780	}
781
782	for (i = 0; i < fb_helper->crtc_count; i++) {
783		crtc = fb_helper->crtc_info[i].mode_set.crtc;
784		crtc_funcs = crtc->helper_private;
785
786		red = cmap->red;
787		green = cmap->green;
788		blue = cmap->blue;
789		transp = cmap->transp;
790		start = cmap->start;
791
792		for (j = 0; j < cmap->len; j++) {
793			u16 hred, hgreen, hblue, htransp = 0xffff;
794
795			hred = *red++;
796			hgreen = *green++;
797			hblue = *blue++;
798
799			if (transp)
800				htransp = *transp++;
801
802			rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
803			if (rc)
804				goto out;
805		}
806		if (crtc_funcs->load_lut)
807			crtc_funcs->load_lut(crtc);
808	}
809 out:
810	drm_modeset_unlock_all(dev);
811	return rc;
812}
813EXPORT_SYMBOL(drm_fb_helper_setcmap);
814
815/**
816 * drm_fb_helper_check_var - implementation for ->fb_check_var
817 * @var: screeninfo to check
818 * @info: fbdev registered by the helper
819 */
820int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
821			    struct fb_info *info)
822{
823	struct drm_fb_helper *fb_helper = info->par;
824	struct drm_framebuffer *fb = fb_helper->fb;
825	int depth;
826
827	if (var->pixclock != 0 || in_dbg_master())
828		return -EINVAL;
829
830	/* Need to resize the fb object !!! */
831	if (var->bits_per_pixel > fb->bits_per_pixel ||
832	    var->xres > fb->width || var->yres > fb->height ||
833	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
834		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
835			  "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
836			  var->xres, var->yres, var->bits_per_pixel,
837			  var->xres_virtual, var->yres_virtual,
838			  fb->width, fb->height, fb->bits_per_pixel);
839		return -EINVAL;
840	}
841
842	switch (var->bits_per_pixel) {
843	case 16:
844		depth = (var->green.length == 6) ? 16 : 15;
845		break;
846	case 32:
847		depth = (var->transp.length > 0) ? 32 : 24;
848		break;
849	default:
850		depth = var->bits_per_pixel;
851		break;
852	}
853
854	switch (depth) {
855	case 8:
856		var->red.offset = 0;
857		var->green.offset = 0;
858		var->blue.offset = 0;
859		var->red.length = 8;
860		var->green.length = 8;
861		var->blue.length = 8;
862		var->transp.length = 0;
863		var->transp.offset = 0;
864		break;
865	case 15:
866		var->red.offset = 10;
867		var->green.offset = 5;
868		var->blue.offset = 0;
869		var->red.length = 5;
870		var->green.length = 5;
871		var->blue.length = 5;
872		var->transp.length = 1;
873		var->transp.offset = 15;
874		break;
875	case 16:
876		var->red.offset = 11;
877		var->green.offset = 5;
878		var->blue.offset = 0;
879		var->red.length = 5;
880		var->green.length = 6;
881		var->blue.length = 5;
882		var->transp.length = 0;
883		var->transp.offset = 0;
884		break;
885	case 24:
886		var->red.offset = 16;
887		var->green.offset = 8;
888		var->blue.offset = 0;
889		var->red.length = 8;
890		var->green.length = 8;
891		var->blue.length = 8;
892		var->transp.length = 0;
893		var->transp.offset = 0;
894		break;
895	case 32:
896		var->red.offset = 16;
897		var->green.offset = 8;
898		var->blue.offset = 0;
899		var->red.length = 8;
900		var->green.length = 8;
901		var->blue.length = 8;
902		var->transp.length = 8;
903		var->transp.offset = 24;
904		break;
905	default:
906		return -EINVAL;
907	}
908	return 0;
909}
910EXPORT_SYMBOL(drm_fb_helper_check_var);
911
912/**
913 * drm_fb_helper_set_par - implementation for ->fb_set_par
914 * @info: fbdev registered by the helper
915 *
916 * This will let fbcon do the mode init and is called at initialization time by
917 * the fbdev core when registering the driver, and later on through the hotplug
918 * callback.
919 */
920int drm_fb_helper_set_par(struct fb_info *info)
921{
922	struct drm_fb_helper *fb_helper = info->par;
923	struct fb_var_screeninfo *var = &info->var;
924
925	if (var->pixclock != 0) {
926		DRM_ERROR("PIXEL CLOCK SET\n");
927		return -EINVAL;
928	}
929
930	drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
931
932	return 0;
933}
934EXPORT_SYMBOL(drm_fb_helper_set_par);
935
936/**
937 * drm_fb_helper_pan_display - implementation for ->fb_pan_display
938 * @var: updated screen information
939 * @info: fbdev registered by the helper
940 */
941int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
942			      struct fb_info *info)
943{
944	struct drm_fb_helper *fb_helper = info->par;
945	struct drm_device *dev = fb_helper->dev;
946	struct drm_mode_set *modeset;
947	int ret = 0;
948	int i;
949
950	if (__drm_modeset_lock_all(dev, !!oops_in_progress)) {
951		return -EBUSY;
952	}
953	if (!drm_fb_helper_is_bound(fb_helper)) {
954		drm_modeset_unlock_all(dev);
955		return -EBUSY;
956	}
957
958	for (i = 0; i < fb_helper->crtc_count; i++) {
959		modeset = &fb_helper->crtc_info[i].mode_set;
960
961		modeset->x = var->xoffset;
962		modeset->y = var->yoffset;
963
964		if (modeset->num_connectors) {
965			ret = drm_mode_set_config_internal(modeset);
966			if (!ret) {
967				info->var.xoffset = var->xoffset;
968				info->var.yoffset = var->yoffset;
969			}
970		}
971	}
972	drm_modeset_unlock_all(dev);
973	return ret;
974}
975EXPORT_SYMBOL(drm_fb_helper_pan_display);
976
977/*
978 * Allocates the backing storage and sets up the fbdev info structure through
979 * the ->fb_probe callback and then registers the fbdev and sets up the panic
980 * notifier.
981 */
982static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
983					 int preferred_bpp)
984{
985	int ret = 0;
986	int crtc_count = 0;
987	int i;
988	struct fb_info *info;
989	struct drm_fb_helper_surface_size sizes;
990	int gamma_size = 0;
991
992	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
993	sizes.surface_depth = 24;
994	sizes.surface_bpp = 32;
995	sizes.fb_width = (unsigned)-1;
996	sizes.fb_height = (unsigned)-1;
997
998	/* if driver picks 8 or 16 by default use that
999	   for both depth/bpp */
1000	if (preferred_bpp != sizes.surface_bpp)
1001		sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
1002
1003	/* first up get a count of crtcs now in use and new min/maxes width/heights */
1004	for (i = 0; i < fb_helper->connector_count; i++) {
1005		struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
1006		struct drm_cmdline_mode *cmdline_mode;
1007
1008		cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1009
1010		if (cmdline_mode->bpp_specified) {
1011			switch (cmdline_mode->bpp) {
1012			case 8:
1013				sizes.surface_depth = sizes.surface_bpp = 8;
1014				break;
1015			case 15:
1016				sizes.surface_depth = 15;
1017				sizes.surface_bpp = 16;
1018				break;
1019			case 16:
1020				sizes.surface_depth = sizes.surface_bpp = 16;
1021				break;
1022			case 24:
1023				sizes.surface_depth = sizes.surface_bpp = 24;
1024				break;
1025			case 32:
1026				sizes.surface_depth = 24;
1027				sizes.surface_bpp = 32;
1028				break;
1029			}
1030			break;
1031		}
1032	}
1033
1034	crtc_count = 0;
1035	for (i = 0; i < fb_helper->crtc_count; i++) {
1036		struct drm_display_mode *desired_mode;
1037		struct drm_mode_set *mode_set;
1038		int x, y, j;
1039		/* in case of tile group, are we the last tile vert or horiz?
1040		 * If no tile group you are always the last one both vertically
1041		 * and horizontally
1042		 */
1043		bool lastv = true, lasth = true;
1044
1045		desired_mode = fb_helper->crtc_info[i].desired_mode;
1046		mode_set = &fb_helper->crtc_info[i].mode_set;
1047
1048		if (!desired_mode)
1049			continue;
1050
1051		crtc_count++;
1052
1053		x = fb_helper->crtc_info[i].x;
1054		y = fb_helper->crtc_info[i].y;
1055
1056		if (gamma_size == 0)
1057			gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
1058
1059		sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
1060		sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
1061
1062		for (j = 0; j < mode_set->num_connectors; j++) {
1063			struct drm_connector *connector = mode_set->connectors[j];
1064			if (connector->has_tile) {
1065				lasth = (connector->tile_h_loc == (connector->num_h_tile - 1));
1066				lastv = (connector->tile_v_loc == (connector->num_v_tile - 1));
1067				/* cloning to multiple tiles is just crazy-talk, so: */
1068				break;
1069			}
1070		}
1071
1072		if (lasth)
1073			sizes.fb_width  = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width);
1074		if (lastv)
1075			sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
1076	}
1077
1078	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
1079		/* hmm everyone went away - assume VGA cable just fell out
1080		   and will come back later. */
1081		DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
1082		sizes.fb_width = sizes.surface_width = 1024;
1083		sizes.fb_height = sizes.surface_height = 768;
1084	}
1085
1086	/* push down into drivers */
1087	ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
1088	if (ret < 0)
1089		return ret;
1090
1091	info = fb_helper->fbdev;
1092
1093	/*
1094	 * Set the fb pointer - usually drm_setup_crtcs does this for hotplug
1095	 * events, but at init time drm_setup_crtcs needs to be called before
1096	 * the fb is allocated (since we need to figure out the desired size of
1097	 * the fb before we can allocate it ...). Hence we need to fix things up
1098	 * here again.
1099	 */
1100	for (i = 0; i < fb_helper->crtc_count; i++)
1101		if (fb_helper->crtc_info[i].mode_set.num_connectors)
1102			fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
1103
1104
1105	info->var.pixclock = 0;
1106	if (register_framebuffer(info) < 0)
1107		return -EINVAL;
1108
1109	dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
1110			info->node, info->fix.id);
1111
1112	/* Switch back to kernel console on panic */
1113	/* multi card linked list maybe */
1114	if (list_empty(&kernel_fb_helper_list)) {
1115		dev_info(fb_helper->dev->dev, "registered panic notifier\n");
1116		atomic_notifier_chain_register(&panic_notifier_list,
1117					       &paniced);
1118		register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
1119	}
1120
1121	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
1122
1123	return 0;
1124}
1125
1126/**
1127 * drm_fb_helper_fill_fix - initializes fixed fbdev information
1128 * @info: fbdev registered by the helper
1129 * @pitch: desired pitch
1130 * @depth: desired depth
1131 *
1132 * Helper to fill in the fixed fbdev information useful for a non-accelerated
1133 * fbdev emulations. Drivers which support acceleration methods which impose
1134 * additional constraints need to set up their own limits.
1135 *
1136 * Drivers should call this (or their equivalent setup code) from their
1137 * ->fb_probe callback.
1138 */
1139void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
1140			    uint32_t depth)
1141{
1142	info->fix.type = FB_TYPE_PACKED_PIXELS;
1143	info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
1144		FB_VISUAL_TRUECOLOR;
1145	info->fix.mmio_start = 0;
1146	info->fix.mmio_len = 0;
1147	info->fix.type_aux = 0;
1148	info->fix.xpanstep = 1; /* doing it in hw */
1149	info->fix.ypanstep = 1; /* doing it in hw */
1150	info->fix.ywrapstep = 0;
1151	info->fix.accel = FB_ACCEL_NONE;
1152
1153	info->fix.line_length = pitch;
1154	return;
1155}
1156EXPORT_SYMBOL(drm_fb_helper_fill_fix);
1157
1158/**
1159 * drm_fb_helper_fill_var - initalizes variable fbdev information
1160 * @info: fbdev instance to set up
1161 * @fb_helper: fb helper instance to use as template
1162 * @fb_width: desired fb width
1163 * @fb_height: desired fb height
1164 *
1165 * Sets up the variable fbdev metainformation from the given fb helper instance
1166 * and the drm framebuffer allocated in fb_helper->fb.
1167 *
1168 * Drivers should call this (or their equivalent setup code) from their
1169 * ->fb_probe callback after having allocated the fbdev backing
1170 * storage framebuffer.
1171 */
1172void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
1173			    uint32_t fb_width, uint32_t fb_height)
1174{
1175	struct drm_framebuffer *fb = fb_helper->fb;
1176	info->pseudo_palette = fb_helper->pseudo_palette;
1177	info->var.xres_virtual = fb->width;
1178	info->var.yres_virtual = fb->height;
1179	info->var.bits_per_pixel = fb->bits_per_pixel;
1180	info->var.accel_flags = FB_ACCELF_TEXT;
1181	info->var.xoffset = 0;
1182	info->var.yoffset = 0;
1183	info->var.activate = FB_ACTIVATE_NOW;
1184	info->var.height = -1;
1185	info->var.width = -1;
1186
1187	switch (fb->depth) {
1188	case 8:
1189		info->var.red.offset = 0;
1190		info->var.green.offset = 0;
1191		info->var.blue.offset = 0;
1192		info->var.red.length = 8; /* 8bit DAC */
1193		info->var.green.length = 8;
1194		info->var.blue.length = 8;
1195		info->var.transp.offset = 0;
1196		info->var.transp.length = 0;
1197		break;
1198	case 15:
1199		info->var.red.offset = 10;
1200		info->var.green.offset = 5;
1201		info->var.blue.offset = 0;
1202		info->var.red.length = 5;
1203		info->var.green.length = 5;
1204		info->var.blue.length = 5;
1205		info->var.transp.offset = 15;
1206		info->var.transp.length = 1;
1207		break;
1208	case 16:
1209		info->var.red.offset = 11;
1210		info->var.green.offset = 5;
1211		info->var.blue.offset = 0;
1212		info->var.red.length = 5;
1213		info->var.green.length = 6;
1214		info->var.blue.length = 5;
1215		info->var.transp.offset = 0;
1216		break;
1217	case 24:
1218		info->var.red.offset = 16;
1219		info->var.green.offset = 8;
1220		info->var.blue.offset = 0;
1221		info->var.red.length = 8;
1222		info->var.green.length = 8;
1223		info->var.blue.length = 8;
1224		info->var.transp.offset = 0;
1225		info->var.transp.length = 0;
1226		break;
1227	case 32:
1228		info->var.red.offset = 16;
1229		info->var.green.offset = 8;
1230		info->var.blue.offset = 0;
1231		info->var.red.length = 8;
1232		info->var.green.length = 8;
1233		info->var.blue.length = 8;
1234		info->var.transp.offset = 24;
1235		info->var.transp.length = 8;
1236		break;
1237	default:
1238		break;
1239	}
1240
1241	info->var.xres = fb_width;
1242	info->var.yres = fb_height;
1243}
1244EXPORT_SYMBOL(drm_fb_helper_fill_var);
1245
1246static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
1247					       uint32_t maxX,
1248					       uint32_t maxY)
1249{
1250	struct drm_connector *connector;
1251	int count = 0;
1252	int i;
1253
1254	for (i = 0; i < fb_helper->connector_count; i++) {
1255		connector = fb_helper->connector_info[i]->connector;
1256		count += connector->funcs->fill_modes(connector, maxX, maxY);
1257	}
1258
1259	return count;
1260}
1261
1262struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
1263{
1264	struct drm_display_mode *mode;
1265
1266	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
1267		if (mode->hdisplay > width ||
1268		    mode->vdisplay > height)
1269			continue;
1270		if (mode->type & DRM_MODE_TYPE_PREFERRED)
1271			return mode;
1272	}
1273	return NULL;
1274}
1275EXPORT_SYMBOL(drm_has_preferred_mode);
1276
1277static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1278{
1279	return fb_connector->connector->cmdline_mode.specified;
1280}
1281
1282struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1283						      int width, int height)
1284{
1285	struct drm_cmdline_mode *cmdline_mode;
1286	struct drm_display_mode *mode;
1287	bool prefer_non_interlace;
1288
1289	cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1290	if (cmdline_mode->specified == false)
1291		return NULL;
1292
1293	/* attempt to find a matching mode in the list of modes
1294	 *  we have gotten so far, if not add a CVT mode that conforms
1295	 */
1296	if (cmdline_mode->rb || cmdline_mode->margins)
1297		goto create_mode;
1298
1299	prefer_non_interlace = !cmdline_mode->interlace;
1300again:
1301	list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
1302		/* check width/height */
1303		if (mode->hdisplay != cmdline_mode->xres ||
1304		    mode->vdisplay != cmdline_mode->yres)
1305			continue;
1306
1307		if (cmdline_mode->refresh_specified) {
1308			if (mode->vrefresh != cmdline_mode->refresh)
1309				continue;
1310		}
1311
1312		if (cmdline_mode->interlace) {
1313			if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
1314				continue;
1315		} else if (prefer_non_interlace) {
1316			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1317				continue;
1318		}
1319		return mode;
1320	}
1321
1322	if (prefer_non_interlace) {
1323		prefer_non_interlace = false;
1324		goto again;
1325	}
1326
1327create_mode:
1328	mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
1329						 cmdline_mode);
1330	list_add(&mode->head, &fb_helper_conn->connector->modes);
1331	return mode;
1332}
1333EXPORT_SYMBOL(drm_pick_cmdline_mode);
1334
1335static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
1336{
1337	bool enable;
1338
1339	if (strict)
1340		enable = connector->status == connector_status_connected;
1341	else
1342		enable = connector->status != connector_status_disconnected;
1343
1344	return enable;
1345}
1346
1347static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
1348				  bool *enabled)
1349{
1350	bool any_enabled = false;
1351	struct drm_connector *connector;
1352	int i = 0;
1353
1354	for (i = 0; i < fb_helper->connector_count; i++) {
1355		connector = fb_helper->connector_info[i]->connector;
1356		enabled[i] = drm_connector_enabled(connector, true);
1357		DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
1358			  enabled[i] ? "yes" : "no");
1359		any_enabled |= enabled[i];
1360	}
1361
1362	if (any_enabled)
1363		return;
1364
1365	for (i = 0; i < fb_helper->connector_count; i++) {
1366		connector = fb_helper->connector_info[i]->connector;
1367		enabled[i] = drm_connector_enabled(connector, false);
1368	}
1369}
1370
1371static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
1372			      struct drm_display_mode **modes,
1373			      struct drm_fb_offset *offsets,
1374			      bool *enabled, int width, int height)
1375{
1376	int count, i, j;
1377	bool can_clone = false;
1378	struct drm_fb_helper_connector *fb_helper_conn;
1379	struct drm_display_mode *dmt_mode, *mode;
1380
1381	/* only contemplate cloning in the single crtc case */
1382	if (fb_helper->crtc_count > 1)
1383		return false;
1384
1385	count = 0;
1386	for (i = 0; i < fb_helper->connector_count; i++) {
1387		if (enabled[i])
1388			count++;
1389	}
1390
1391	/* only contemplate cloning if more than one connector is enabled */
1392	if (count <= 1)
1393		return false;
1394
1395	/* check the command line or if nothing common pick 1024x768 */
1396	can_clone = true;
1397	for (i = 0; i < fb_helper->connector_count; i++) {
1398		if (!enabled[i])
1399			continue;
1400		fb_helper_conn = fb_helper->connector_info[i];
1401		modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
1402		if (!modes[i]) {
1403			can_clone = false;
1404			break;
1405		}
1406		for (j = 0; j < i; j++) {
1407			if (!enabled[j])
1408				continue;
1409			if (!drm_mode_equal(modes[j], modes[i]))
1410				can_clone = false;
1411		}
1412	}
1413
1414	if (can_clone) {
1415		DRM_DEBUG_KMS("can clone using command line\n");
1416		return true;
1417	}
1418
1419	/* try and find a 1024x768 mode on each connector */
1420	can_clone = true;
1421	dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false);
1422
1423	for (i = 0; i < fb_helper->connector_count; i++) {
1424
1425		if (!enabled[i])
1426			continue;
1427
1428		fb_helper_conn = fb_helper->connector_info[i];
1429		list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
1430			if (drm_mode_equal(mode, dmt_mode))
1431				modes[i] = mode;
1432		}
1433		if (!modes[i])
1434			can_clone = false;
1435	}
1436
1437	if (can_clone) {
1438		DRM_DEBUG_KMS("can clone using 1024x768\n");
1439		return true;
1440	}
1441	DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
1442	return false;
1443}
1444
1445static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper,
1446				struct drm_display_mode **modes,
1447				struct drm_fb_offset *offsets,
1448				int idx,
1449				int h_idx, int v_idx)
1450{
1451	struct drm_fb_helper_connector *fb_helper_conn;
1452	int i;
1453	int hoffset = 0, voffset = 0;
1454
1455	for (i = 0; i < fb_helper->connector_count; i++) {
1456		fb_helper_conn = fb_helper->connector_info[i];
1457		if (!fb_helper_conn->connector->has_tile)
1458			continue;
1459
1460		if (!modes[i] && (h_idx || v_idx)) {
1461			DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
1462				      fb_helper_conn->connector->base.id);
1463			continue;
1464		}
1465		if (fb_helper_conn->connector->tile_h_loc < h_idx)
1466			hoffset += modes[i]->hdisplay;
1467
1468		if (fb_helper_conn->connector->tile_v_loc < v_idx)
1469			voffset += modes[i]->vdisplay;
1470	}
1471	offsets[idx].x = hoffset;
1472	offsets[idx].y = voffset;
1473	DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx);
1474	return 0;
1475}
1476
1477static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
1478				 struct drm_display_mode **modes,
1479				 struct drm_fb_offset *offsets,
1480				 bool *enabled, int width, int height)
1481{
1482	struct drm_fb_helper_connector *fb_helper_conn;
1483	int i;
1484	uint64_t conn_configured = 0, mask;
1485	int tile_pass = 0;
1486	mask = (1 << fb_helper->connector_count) - 1;
1487retry:
1488	for (i = 0; i < fb_helper->connector_count; i++) {
1489		fb_helper_conn = fb_helper->connector_info[i];
1490
1491		if (conn_configured & (1 << i))
1492			continue;
1493
1494		if (enabled[i] == false) {
1495			conn_configured |= (1 << i);
1496			continue;
1497		}
1498
1499		/* first pass over all the untiled connectors */
1500		if (tile_pass == 0 && fb_helper_conn->connector->has_tile)
1501			continue;
1502
1503		if (tile_pass == 1) {
1504			if (fb_helper_conn->connector->tile_h_loc != 0 ||
1505			    fb_helper_conn->connector->tile_v_loc != 0)
1506				continue;
1507
1508		} else {
1509			if (fb_helper_conn->connector->tile_h_loc != tile_pass -1 &&
1510			    fb_helper_conn->connector->tile_v_loc != tile_pass - 1)
1511			/* if this tile_pass doesn't cover any of the tiles - keep going */
1512				continue;
1513
1514			/* find the tile offsets for this pass - need
1515			   to find all tiles left and above */
1516			drm_get_tile_offsets(fb_helper, modes, offsets,
1517					     i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc);
1518		}
1519		DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
1520			      fb_helper_conn->connector->base.id);
1521
1522		/* got for command line mode first */
1523		modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
1524		if (!modes[i]) {
1525			DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
1526				      fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0);
1527			modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
1528		}
1529		/* No preferred modes, pick one off the list */
1530		if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
1531			list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
1532				break;
1533		}
1534		DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
1535			  "none");
1536		conn_configured |= (1 << i);
1537	}
1538
1539	if ((conn_configured & mask) != mask) {
1540		tile_pass++;
1541		goto retry;
1542	}
1543	return true;
1544}
1545
1546static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
1547			  struct drm_fb_helper_crtc **best_crtcs,
1548			  struct drm_display_mode **modes,
1549			  int n, int width, int height)
1550{
1551	int c, o;
1552	struct drm_connector *connector;
1553	const struct drm_connector_helper_funcs *connector_funcs;
1554	struct drm_encoder *encoder;
1555	int my_score, best_score, score;
1556	struct drm_fb_helper_crtc **crtcs, *crtc;
1557	struct drm_fb_helper_connector *fb_helper_conn;
1558
1559	if (n == fb_helper->connector_count)
1560		return 0;
1561
1562	fb_helper_conn = fb_helper->connector_info[n];
1563	connector = fb_helper_conn->connector;
1564
1565	best_crtcs[n] = NULL;
1566	best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
1567	if (modes[n] == NULL)
1568		return best_score;
1569
1570	crtcs = kzalloc(fb_helper->connector_count *
1571			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
1572	if (!crtcs)
1573		return best_score;
1574
1575	my_score = 1;
1576	if (connector->status == connector_status_connected)
1577		my_score++;
1578	if (drm_has_cmdline_mode(fb_helper_conn))
1579		my_score++;
1580	if (drm_has_preferred_mode(fb_helper_conn, width, height))
1581		my_score++;
1582
1583	connector_funcs = connector->helper_private;
1584	encoder = connector_funcs->best_encoder(connector);
1585	if (!encoder)
1586		goto out;
1587
1588	/* select a crtc for this connector and then attempt to configure
1589	   remaining connectors */
1590	for (c = 0; c < fb_helper->crtc_count; c++) {
1591		crtc = &fb_helper->crtc_info[c];
1592
1593		if ((encoder->possible_crtcs & (1 << c)) == 0)
1594			continue;
1595
1596		for (o = 0; o < n; o++)
1597			if (best_crtcs[o] == crtc)
1598				break;
1599
1600		if (o < n) {
1601			/* ignore cloning unless only a single crtc */
1602			if (fb_helper->crtc_count > 1)
1603				continue;
1604
1605			if (!drm_mode_equal(modes[o], modes[n]))
1606				continue;
1607		}
1608
1609		crtcs[n] = crtc;
1610		memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
1611		score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
1612						  width, height);
1613		if (score > best_score) {
1614			best_score = score;
1615			memcpy(best_crtcs, crtcs,
1616			       fb_helper->connector_count *
1617			       sizeof(struct drm_fb_helper_crtc *));
1618		}
1619	}
1620out:
1621	kfree(crtcs);
1622	return best_score;
1623}
1624
1625static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1626{
1627	struct drm_device *dev = fb_helper->dev;
1628	struct drm_fb_helper_crtc **crtcs;
1629	struct drm_display_mode **modes;
1630	struct drm_fb_offset *offsets;
1631	struct drm_mode_set *modeset;
1632	bool *enabled;
1633	int width, height;
1634	int i;
1635
1636	DRM_DEBUG_KMS("\n");
1637
1638	width = dev->mode_config.max_width;
1639	height = dev->mode_config.max_height;
1640
1641	crtcs = kcalloc(dev->mode_config.num_connector,
1642			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
1643	modes = kcalloc(dev->mode_config.num_connector,
1644			sizeof(struct drm_display_mode *), GFP_KERNEL);
1645	offsets = kcalloc(dev->mode_config.num_connector,
1646			  sizeof(struct drm_fb_offset), GFP_KERNEL);
1647	enabled = kcalloc(dev->mode_config.num_connector,
1648			  sizeof(bool), GFP_KERNEL);
1649	if (!crtcs || !modes || !enabled || !offsets) {
1650		DRM_ERROR("Memory allocation failed\n");
1651		goto out;
1652	}
1653
1654
1655	drm_enable_connectors(fb_helper, enabled);
1656
1657	if (!(fb_helper->funcs->initial_config &&
1658	      fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
1659					       offsets,
1660					       enabled, width, height))) {
1661		memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0]));
1662		memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0]));
1663		memset(offsets, 0, dev->mode_config.num_connector*sizeof(offsets[0]));
1664
1665		if (!drm_target_cloned(fb_helper, modes, offsets,
1666				       enabled, width, height) &&
1667		    !drm_target_preferred(fb_helper, modes, offsets,
1668					  enabled, width, height))
1669			DRM_ERROR("Unable to find initial modes\n");
1670
1671		DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
1672			      width, height);
1673
1674		drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
1675	}
1676
1677	/* need to set the modesets up here for use later */
1678	/* fill out the connector<->crtc mappings into the modesets */
1679	for (i = 0; i < fb_helper->crtc_count; i++) {
1680		modeset = &fb_helper->crtc_info[i].mode_set;
1681		modeset->num_connectors = 0;
1682		modeset->fb = NULL;
1683	}
1684
1685	for (i = 0; i < fb_helper->connector_count; i++) {
1686		struct drm_display_mode *mode = modes[i];
1687		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
1688		struct drm_fb_offset *offset = &offsets[i];
1689		modeset = &fb_crtc->mode_set;
1690
1691		if (mode && fb_crtc) {
1692			DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
1693				      mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
1694			fb_crtc->desired_mode = mode;
1695			fb_crtc->x = offset->x;
1696			fb_crtc->y = offset->y;
1697			if (modeset->mode)
1698				drm_mode_destroy(dev, modeset->mode);
1699			modeset->mode = drm_mode_duplicate(dev,
1700							   fb_crtc->desired_mode);
1701			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
1702			modeset->fb = fb_helper->fb;
1703			modeset->x = offset->x;
1704			modeset->y = offset->y;
1705		}
1706	}
1707
1708	/* Clear out any old modes if there are no more connected outputs. */
1709	for (i = 0; i < fb_helper->crtc_count; i++) {
1710		modeset = &fb_helper->crtc_info[i].mode_set;
1711		if (modeset->num_connectors == 0) {
1712			BUG_ON(modeset->fb);
1713			if (modeset->mode)
1714				drm_mode_destroy(dev, modeset->mode);
1715			modeset->mode = NULL;
1716		}
1717	}
1718out:
1719	kfree(crtcs);
1720	kfree(modes);
1721	kfree(offsets);
1722	kfree(enabled);
1723}
1724
1725/**
1726 * drm_fb_helper_initial_config - setup a sane initial connector configuration
1727 * @fb_helper: fb_helper device struct
1728 * @bpp_sel: bpp value to use for the framebuffer configuration
1729 *
1730 * Scans the CRTCs and connectors and tries to put together an initial setup.
1731 * At the moment, this is a cloned configuration across all heads with
1732 * a new framebuffer object as the backing store.
1733 *
1734 * Note that this also registers the fbdev and so allows userspace to call into
1735 * the driver through the fbdev interfaces.
1736 *
1737 * This function will call down into the ->fb_probe callback to let
1738 * the driver allocate and initialize the fbdev info structure and the drm
1739 * framebuffer used to back the fbdev. drm_fb_helper_fill_var() and
1740 * drm_fb_helper_fill_fix() are provided as helpers to setup simple default
1741 * values for the fbdev info structure.
1742 *
1743 * RETURNS:
1744 * Zero if everything went ok, nonzero otherwise.
1745 */
1746int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1747{
1748	struct drm_device *dev = fb_helper->dev;
1749	int count = 0;
1750
1751	mutex_lock(&dev->mode_config.mutex);
1752	count = drm_fb_helper_probe_connector_modes(fb_helper,
1753						    dev->mode_config.max_width,
1754						    dev->mode_config.max_height);
1755	mutex_unlock(&dev->mode_config.mutex);
1756	/*
1757	 * we shouldn't end up with no modes here.
1758	 */
1759	if (count == 0)
1760		dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n");
1761
1762	drm_setup_crtcs(fb_helper);
1763
1764	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1765}
1766EXPORT_SYMBOL(drm_fb_helper_initial_config);
1767
1768/**
1769 * drm_fb_helper_hotplug_event - respond to a hotplug notification by
1770 *                               probing all the outputs attached to the fb
1771 * @fb_helper: the drm_fb_helper
1772 *
1773 * Scan the connectors attached to the fb_helper and try to put together a
1774 * setup after *notification of a change in output configuration.
1775 *
1776 * Called at runtime, takes the mode config locks to be able to check/change the
1777 * modeset configuration. Must be run from process context (which usually means
1778 * either the output polling work or a work item launched from the driver's
1779 * hotplug interrupt).
1780 *
1781 * Note that drivers may call this even before calling
1782 * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
1783 * for a race-free fbcon setup and will make sure that the fbdev emulation will
1784 * not miss any hotplug events.
1785 *
1786 * RETURNS:
1787 * 0 on success and a non-zero error code otherwise.
1788 */
1789int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1790{
1791	struct drm_device *dev = fb_helper->dev;
1792	u32 max_width, max_height;
1793
1794	mutex_lock(&fb_helper->dev->mode_config.mutex);
1795	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
1796		fb_helper->delayed_hotplug = true;
1797		mutex_unlock(&fb_helper->dev->mode_config.mutex);
1798		return 0;
1799	}
1800	DRM_DEBUG_KMS("\n");
1801
1802	max_width = fb_helper->fb->width;
1803	max_height = fb_helper->fb->height;
1804
1805	drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height);
1806	mutex_unlock(&fb_helper->dev->mode_config.mutex);
1807
1808	drm_modeset_lock_all(dev);
1809	drm_setup_crtcs(fb_helper);
1810	drm_modeset_unlock_all(dev);
1811	drm_fb_helper_set_par(fb_helper->fbdev);
1812
1813	return 0;
1814}
1815EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
1816
1817/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
1818 * but the module doesn't depend on any fb console symbols.  At least
1819 * attempt to load fbcon to avoid leaving the system without a usable console.
1820 */
1821#if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT)
1822static int __init drm_fb_helper_modinit(void)
1823{
1824	const char *name = "fbcon";
1825	struct module *fbcon;
1826
1827	mutex_lock(&module_mutex);
1828	fbcon = find_module(name);
1829	mutex_unlock(&module_mutex);
1830
1831	if (!fbcon)
1832		request_module_nowait(name);
1833	return 0;
1834}
1835
1836module_init(drm_fb_helper_modinit);
1837#endif
1838