Subversion Repositories Kolibri OS

Rev

Rev 4560 | Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4560 Rev 5060
Line 43... Line 43...
43
 
43
 
44
/**
44
/**
45
 * DOC: fbdev helpers
45
 * DOC: fbdev helpers
46
 *
46
 *
47
 * The fb helper functions are useful to provide an fbdev on top of a drm kernel
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 independantely from the crtc
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
49
 * helper functions used by many drivers to implement the kernel mode setting
50
 * interfaces.
50
 * interfaces.
51
 *
51
 *
52
 * Initialization is done as a three-step process with drm_fb_helper_init(),
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
53
 * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config().
54
 * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
54
 * Drivers with fancier requirements than the default beheviour can override the
55
 * default behaviour can override the third step with their own code.
55
 * second step with their own code.  Teardown is done with drm_fb_helper_fini().
56
 * Teardown is done with drm_fb_helper_fini().
56
 *
57
 *
57
 * At runtime drivers should restore the fbdev console by calling
58
 * At runtime drivers should restore the fbdev console by calling
58
 * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
59
 * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
59
 * should also notify the fb helper code from updates to the output
60
 * should also notify the fb helper code from updates to the output
60
 * configuration by calling drm_fb_helper_hotplug_event(). For easier
61
 * configuration by calling drm_fb_helper_hotplug_event(). For easier
61
 * integration with the output polling code in drm_crtc_helper.c the modeset
62
 * integration with the output polling code in drm_crtc_helper.c the modeset
62
 * code proves a ->output_poll_changed callback.
63
 * code provides a ->output_poll_changed callback.
63
 *
64
 *
64
 * All other functions exported by the fb helper library can be used to
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
65
 * implement the fbdev driver interface by the driver.
79
 * drm_fb_helper_initial_config().
Line 66... Line 80...
66
 */
80
 */
67
 
81
 
68
/**
82
/**
Line 103... Line 117...
103
	fb_helper->connector_count = 0;
117
	fb_helper->connector_count = 0;
104
    return -ENOMEM;
118
    return -ENOMEM;
105
}
119
}
106
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
120
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
Line -... Line 121...
-
 
121
 
-
 
122
int 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
}
-
 
146
EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
-
 
147
 
-
 
148
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
-
 
149
				       struct drm_connector *connector)
-
 
150
{
-
 
151
	struct drm_fb_helper_connector *fb_helper_connector;
-
 
152
	int i, j;
-
 
153
 
-
 
154
	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
-
 
155
 
-
 
156
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
157
		if (fb_helper->connector_info[i]->connector == connector)
-
 
158
			break;
-
 
159
	}
-
 
160
 
-
 
161
	if (i == fb_helper->connector_count)
-
 
162
		return -EINVAL;
-
 
163
	fb_helper_connector = fb_helper->connector_info[i];
-
 
164
 
-
 
165
	for (j = i + 1; j < fb_helper->connector_count; j++) {
-
 
166
		fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
-
 
167
	}
-
 
168
	fb_helper->connector_count--;
-
 
169
	kfree(fb_helper_connector);
-
 
170
	return 0;
-
 
171
}
107
 
172
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
108
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
173
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
109
{
174
{
110
	uint16_t *r_base, *g_base, *b_base;
175
	uint16_t *r_base, *g_base, *b_base;
Line 134... Line 199...
134
 
199
 
135
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
200
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
Line -... Line 201...
-
 
201
}
-
 
202
 
-
 
203
 
-
 
204
static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
-
 
205
{
-
 
206
	struct drm_device *dev = fb_helper->dev;
-
 
207
	struct drm_plane *plane;
-
 
208
	bool error = false;
-
 
209
	int i;
-
 
210
 
-
 
211
	drm_warn_on_modeset_not_all_locked(dev);
-
 
212
 
-
 
213
	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
-
 
214
		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
-
 
215
			drm_plane_force_disable(plane);
-
 
216
 
-
 
217
	for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
218
		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
-
 
219
		struct drm_crtc *crtc = mode_set->crtc;
-
 
220
		int ret;
-
 
221
 
-
 
222
		if (crtc->funcs->cursor_set) {
-
 
223
			ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
-
 
224
			if (ret)
-
 
225
				error = true;
-
 
226
		}
-
 
227
 
-
 
228
		ret = drm_mode_set_config_internal(mode_set);
-
 
229
		if (ret)
-
 
230
			error = true;
-
 
231
	}
-
 
232
	return error;
-
 
233
}
-
 
234
/**
-
 
235
 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
-
 
236
 * @fb_helper: fbcon to restore
-
 
237
 *
-
 
238
 * This should be called from driver's drm ->lastclose callback
-
 
239
 * when implementing an fbcon on top of kms using this helper. This ensures that
-
 
240
 * the user isn't greeted with a black screen when e.g. X dies.
-
 
241
 */
-
 
242
bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
-
 
243
{
-
 
244
	struct drm_device *dev = fb_helper->dev;
-
 
245
	bool ret;
-
 
246
	drm_modeset_lock_all(dev);
-
 
247
	ret = restore_fbdev_mode(fb_helper);
-
 
248
	drm_modeset_unlock_all(dev);
-
 
249
	return ret;
136
}
250
}
137
 
251
EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
138
 
252
 
139
static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
253
static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
140
{
254
{
Line 141... Line 255...
141
	struct drm_device *dev = fb_helper->dev;
255
	struct drm_device *dev = fb_helper->dev;
142
	struct drm_crtc *crtc;
256
	struct drm_crtc *crtc;
143
	int bound = 0, crtcs_bound = 0;
257
	int bound = 0, crtcs_bound = 0;
144
 
258
 
145
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
259
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
146
		if (crtc->fb)
260
		if (crtc->primary->fb)
Line 147... Line 261...
147
			crtcs_bound++;
261
			crtcs_bound++;
148
		if (crtc->fb == fb_helper->fb)
262
		if (crtc->primary->fb == fb_helper->fb)
Line 266... Line 380...
266
	}
380
	}
267
	kfree(helper->crtc_info);
381
	kfree(helper->crtc_info);
268
}
382
}
Line 269... Line 383...
269
 
383
 
-
 
384
/**
-
 
385
 * drm_fb_helper_prepare - setup a drm_fb_helper structure
-
 
386
 * @dev: DRM device
-
 
387
 * @helper: driver-allocated fbdev helper structure to set up
-
 
388
 * @funcs: pointer to structure of functions associate with this helper
-
 
389
 *
-
 
390
 * Sets up the bare minimum to make the framebuffer helper usable. This is
-
 
391
 * useful to implement race-free initialization of the polling helpers.
-
 
392
 */
-
 
393
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
-
 
394
			   const struct drm_fb_helper_funcs *funcs)
-
 
395
{
-
 
396
	INIT_LIST_HEAD(&helper->kernel_fb_list);
-
 
397
	helper->funcs = funcs;
-
 
398
	helper->dev = dev;
-
 
399
}
-
 
400
EXPORT_SYMBOL(drm_fb_helper_prepare);
-
 
401
 
270
/**
402
/**
271
 * drm_fb_helper_init - initialize a drm_fb_helper structure
403
 * drm_fb_helper_init - initialize a drm_fb_helper structure
272
 * @dev: drm device
404
 * @dev: drm device
273
 * @fb_helper: driver-allocated fbdev helper structure to initialize
405
 * @fb_helper: driver-allocated fbdev helper structure to initialize
274
 * @crtc_count: maximum number of crtcs to support in this fbdev emulation
406
 * @crtc_count: maximum number of crtcs to support in this fbdev emulation
Line 277... Line 409...
277
 * This allocates the structures for the fbdev helper with the given limits.
409
 * This allocates the structures for the fbdev helper with the given limits.
278
 * Note that this won't yet touch the hardware (through the driver interfaces)
410
 * Note that this won't yet touch the hardware (through the driver interfaces)
279
 * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
411
 * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
280
 * to allow driver writes more control over the exact init sequence.
412
 * to allow driver writes more control over the exact init sequence.
281
 *
413
 *
282
 * Drivers must set fb_helper->funcs before calling
414
 * Drivers must call drm_fb_helper_prepare() before calling this function.
283
 * drm_fb_helper_initial_config().
-
 
284
 *
415
 *
285
 * RETURNS:
416
 * RETURNS:
286
 * Zero if everything went ok, nonzero otherwise.
417
 * Zero if everything went ok, nonzero otherwise.
287
 */
418
 */
288
int drm_fb_helper_init(struct drm_device *dev,
419
int drm_fb_helper_init(struct drm_device *dev,
Line 290... Line 421...
290
		       int crtc_count, int max_conn_count)
421
		       int crtc_count, int max_conn_count)
291
{
422
{
292
	struct drm_crtc *crtc;
423
	struct drm_crtc *crtc;
293
	int i;
424
	int i;
Line 294... Line 425...
294
 
425
 
295
	fb_helper->dev = dev;
-
 
296
 
426
	if (!max_conn_count)
Line 297... Line 427...
297
	INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
427
		return -EINVAL;
298
 
428
 
299
	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
429
	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
Line 304... Line 434...
304
	fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
434
	fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
305
	if (!fb_helper->connector_info) {
435
	if (!fb_helper->connector_info) {
306
		kfree(fb_helper->crtc_info);
436
		kfree(fb_helper->crtc_info);
307
		return -ENOMEM;
437
		return -ENOMEM;
308
	}
438
	}
-
 
439
	fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
309
	fb_helper->connector_count = 0;
440
	fb_helper->connector_count = 0;
Line 310... Line 441...
310
 
441
 
311
	for (i = 0; i < crtc_count; i++) {
442
	for (i = 0; i < crtc_count; i++) {
312
		fb_helper->crtc_info[i].mode_set.connectors =
443
		fb_helper->crtc_info[i].mode_set.connectors =
Line 564... Line 695...
564
 * callback.
695
 * callback.
565
 */
696
 */
566
int drm_fb_helper_set_par(struct fb_info *info)
697
int drm_fb_helper_set_par(struct fb_info *info)
567
{
698
{
568
	struct drm_fb_helper *fb_helper = info->par;
699
	struct drm_fb_helper *fb_helper = info->par;
569
	struct drm_device *dev = fb_helper->dev;
-
 
570
	struct fb_var_screeninfo *var = &info->var;
700
	struct fb_var_screeninfo *var = &info->var;
571
	int ret;
-
 
572
	int i;
-
 
Line 573... Line 701...
573
 
701
 
574
	if (var->pixclock != 0) {
702
	if (var->pixclock != 0) {
575
		DRM_ERROR("PIXEL CLOCK SET\n");
703
		DRM_ERROR("PIXEL CLOCK SET\n");
576
		return -EINVAL;
704
		return -EINVAL;
Line 577... Line -...
577
	}
-
 
578
 
-
 
579
	drm_modeset_lock_all(dev);
-
 
580
		for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
581
		ret = drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set);
-
 
582
		if (ret) {
-
 
583
			drm_modeset_unlock_all(dev);
-
 
584
				return ret;
-
 
585
		}
705
	}
Line 586... Line 706...
586
	}
706
 
587
	drm_modeset_unlock_all(dev);
707
	drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
588
 
708
 
589
	if (fb_helper->delayed_hotplug) {
709
	if (fb_helper->delayed_hotplug) {
Line 768... Line 888...
768
	info->fix.type_aux = 0;
888
	info->fix.type_aux = 0;
769
	info->fix.xpanstep = 1; /* doing it in hw */
889
	info->fix.xpanstep = 1; /* doing it in hw */
770
	info->fix.ypanstep = 1; /* doing it in hw */
890
	info->fix.ypanstep = 1; /* doing it in hw */
771
	info->fix.ywrapstep = 0;
891
	info->fix.ywrapstep = 0;
772
	info->fix.accel = FB_ACCEL_NONE;
892
	info->fix.accel = FB_ACCEL_NONE;
773
	info->fix.type_aux = 0;
-
 
Line 774... Line 893...
774
 
893
 
775
	info->fix.line_length = pitch;
894
	info->fix.line_length = pitch;
776
	return;
895
	return;
777
}
896
}
Line 879... Line 998...
879
	}
998
	}
Line 880... Line 999...
880
 
999
 
881
	return count;
1000
	return count;
Line 882... Line 1001...
882
}
1001
}
883
 
1002
 
884
static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
1003
struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
Line 885... Line 1004...
885
{
1004
{
886
	struct drm_display_mode *mode;
1005
	struct drm_display_mode *mode;
887
 
1006
 
888
	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
1007
	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
889
		if (drm_mode_width(mode) > width ||
1008
		if (mode->hdisplay > width ||
890
		    drm_mode_height(mode) > height)
1009
		    mode->vdisplay > height)
891
			continue;
1010
			continue;
892
		if (mode->type & DRM_MODE_TYPE_PREFERRED)
1011
		if (mode->type & DRM_MODE_TYPE_PREFERRED)
893
			return mode;
1012
			return mode;
-
 
1013
	}
Line 894... Line 1014...
894
	}
1014
	return NULL;
895
	return NULL;
1015
}
896
}
1016
EXPORT_SYMBOL(drm_has_preferred_mode);
897
 
1017
 
898
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1018
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
899
{
1019
{
Line 900... Line 1020...
900
	struct drm_cmdline_mode *cmdline_mode;
1020
	struct drm_cmdline_mode *cmdline_mode;
901
	cmdline_mode = &fb_connector->cmdline_mode;
1021
	cmdline_mode = &fb_connector->cmdline_mode;
902
	return cmdline_mode->specified;
1022
	return cmdline_mode->specified;
903
}
1023
}
904
 
1024
 
-
 
1025
struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
Line 905... Line 1026...
905
static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1026
						      int width, int height)
Line 906... Line 1027...
906
						      int width, int height)
1027
{
907
{
1028
	struct drm_cmdline_mode *cmdline_mode;
Line 918... Line 1039...
918
	 *  we have gotten so far, if not add a CVT mode that conforms
1039
	 *  we have gotten so far, if not add a CVT mode that conforms
919
	 */
1040
	 */
920
	if (cmdline_mode->rb || cmdline_mode->margins)
1041
	if (cmdline_mode->rb || cmdline_mode->margins)
921
		goto create_mode;
1042
		goto create_mode;
Line -... Line 1043...
-
 
1043
 
-
 
1044
	prefer_non_interlace = !cmdline_mode->interlace;
922
 
1045
 again:
923
	list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
1046
	list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
924
		/* check width/height */
1047
		/* check width/height */
925
		if (mode->hdisplay != cmdline_mode->xres ||
1048
		if (mode->hdisplay != cmdline_mode->xres ||
926
		    mode->vdisplay != cmdline_mode->yres)
1049
		    mode->vdisplay != cmdline_mode->yres)
Line 932... Line 1055...
932
		}
1055
		}
Line 933... Line 1056...
933
 
1056
 
934
		if (cmdline_mode->interlace) {
1057
		if (cmdline_mode->interlace) {
935
			if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
1058
			if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
-
 
1059
				continue;
-
 
1060
		} else if (prefer_non_interlace) {
-
 
1061
			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
936
				continue;
1062
				continue;
937
		}
1063
		}
938
		return mode;
1064
		return mode;
Line -... Line 1065...
-
 
1065
	}
-
 
1066
 
-
 
1067
	if (prefer_non_interlace) {
-
 
1068
		prefer_non_interlace = false;
-
 
1069
		goto again;
939
	}
1070
	}
940
 
1071
 
941
create_mode:
1072
create_mode:
942
	mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
1073
	mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
943
						 cmdline_mode);
1074
						 cmdline_mode);
944
	list_add(&mode->head, &fb_helper_conn->connector->modes);
1075
	list_add(&mode->head, &fb_helper_conn->connector->modes);
-
 
1076
	return mode;
Line 945... Line 1077...
945
	return mode;
1077
}
946
}
1078
EXPORT_SYMBOL(drm_pick_cmdline_mode);
947
 
1079
 
Line 1284... Line 1416...
1284
	struct drm_device *dev = fb_helper->dev;
1416
	struct drm_device *dev = fb_helper->dev;
1285
	int count = 0;
1417
	int count = 0;
Line 1286... Line 1418...
1286
 
1418
 
Line -... Line 1419...
-
 
1419
//   drm_fb_helper_parse_command_line(fb_helper);
1287
//   drm_fb_helper_parse_command_line(fb_helper);
1420
 
1288
 
1421
	mutex_lock(&dev->mode_config.mutex);
1289
	count = drm_fb_helper_probe_connector_modes(fb_helper,
1422
	count = drm_fb_helper_probe_connector_modes(fb_helper,
-
 
1423
						    dev->mode_config.max_width,
1290
						    dev->mode_config.max_width,
1424
						    dev->mode_config.max_height);
1291
						    dev->mode_config.max_height);
1425
	mutex_unlock(&dev->mode_config.mutex);
1292
	/*
1426
	/*
1293
	 * we shouldn't end up with no modes here.
1427
	 * we shouldn't end up with no modes here.
1294
	 */
1428
	 */
Line 1312... Line 1446...
1312
 * Called at runtime, takes the mode config locks to be able to check/change the
1446
 * Called at runtime, takes the mode config locks to be able to check/change the
1313
 * modeset configuration. Must be run from process context (which usually means
1447
 * modeset configuration. Must be run from process context (which usually means
1314
 * either the output polling work or a work item launched from the driver's
1448
 * either the output polling work or a work item launched from the driver's
1315
 * hotplug interrupt).
1449
 * hotplug interrupt).
1316
 *
1450
 *
1317
 * Note that the driver must ensure that this is only called _after_ the fb has
1451
 * Note that drivers may call this even before calling
1318
 * been fully set up, i.e. after the call to drm_fb_helper_initial_config.
1452
 * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
-
 
1453
 * for a race-free fbcon setup and will make sure that the fbdev emulation will
-
 
1454
 * not miss any hotplug events.
1319
 *
1455
 *
1320
 * RETURNS:
1456
 * RETURNS:
1321
 * 0 on success and a non-zero error code otherwise.
1457
 * 0 on success and a non-zero error code otherwise.
1322
 */
1458
 */
1323
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1459
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1324
{
1460
{
1325
	struct drm_device *dev = fb_helper->dev;
1461
	struct drm_device *dev = fb_helper->dev;
1326
	u32 max_width, max_height;
1462
	u32 max_width, max_height;
Line 1327... Line -...
1327
 
-
 
1328
	if (!fb_helper->fb)
-
 
1329
		return 0;
-
 
1330
 
1463
 
1331
	mutex_lock(&fb_helper->dev->mode_config.mutex);
1464
	mutex_lock(&fb_helper->dev->mode_config.mutex);
1332
	if (!drm_fb_helper_is_bound(fb_helper)) {
1465
	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
1333
		fb_helper->delayed_hotplug = true;
1466
		fb_helper->delayed_hotplug = true;
1334
		mutex_unlock(&fb_helper->dev->mode_config.mutex);
1467
		mutex_unlock(&fb_helper->dev->mode_config.mutex);
1335
		return 0;
1468
		return 0;
1336
	}
1469
	}