Subversion Repositories Kolibri OS

Rev

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

Rev 1430 Rev 1963
Line 26... Line 26...
26
 * Authors:
26
 * Authors:
27
 *      Dave Airlie 
27
 *      Dave Airlie 
28
 *      Jesse Barnes 
28
 *      Jesse Barnes 
29
 */
29
 */
30
#include 
30
#include 
31
//#include 
31
#include 
-
 
32
#include 
32
#include 
33
#include 
33
#include "drmP.h"
34
#include "drmP.h"
34
#include "drm_crtc.h"
35
#include "drm_crtc.h"
35
#include "drm_fb_helper.h"
36
#include "drm_fb_helper.h"
36
#include "drm_crtc_helper.h"
37
#include "drm_crtc_helper.h"
Line 39... Line 40...
39
MODULE_DESCRIPTION("DRM KMS helper");
40
MODULE_DESCRIPTION("DRM KMS helper");
40
MODULE_LICENSE("GPL and additional rights");
41
MODULE_LICENSE("GPL and additional rights");
Line 41... Line 42...
41
 
42
 
Line -... Line 43...
-
 
43
static LIST_HEAD(kernel_fb_helper_list);
42
static LIST_HEAD(kernel_fb_helper_list);
44
 
43
 
45
/* simple single crtc case helper function */
44
int drm_fb_helper_add_connector(struct drm_connector *connector)
46
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
45
{
47
{
46
	connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
48
	struct drm_device *dev = fb_helper->dev;
Line -... Line 49...
-
 
49
	struct drm_connector *connector;
-
 
50
	int i;
-
 
51
 
-
 
52
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-
 
53
		struct drm_fb_helper_connector *fb_helper_connector;
-
 
54
 
-
 
55
		fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
-
 
56
		if (!fb_helper_connector)
-
 
57
			goto fail;
-
 
58
 
47
	if (!connector->fb_helper_private)
59
		fb_helper_connector->connector = connector;
-
 
60
		fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
-
 
61
	}
-
 
62
	return 0;
-
 
63
fail:
-
 
64
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
65
		kfree(fb_helper->connector_info[i]);
-
 
66
		fb_helper->connector_info[i] = NULL;
48
		return -ENOMEM;
67
	}
49
 
68
	fb_helper->connector_count = 0;
Line 50... Line 69...
50
	return 0;
69
    return -ENOMEM;
51
}
70
}
-
 
71
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
52
EXPORT_SYMBOL(drm_fb_helper_add_connector);
72
 
53
 
-
 
54
bool drm_fb_helper_force_kernel_mode(void)
-
 
Line -... Line 73...
-
 
73
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
55
{
74
{
56
	int i = 0;
75
	uint16_t *r_base, *g_base, *b_base;
Line 57... Line -...
57
	bool ret, error = false;
-
 
58
	struct drm_fb_helper *helper;
76
	int i;
59
 
77
 
60
	if (list_empty(&kernel_fb_helper_list))
-
 
61
		return false;
-
 
62
 
-
 
63
	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-
 
64
		for (i = 0; i < helper->crtc_count; i++) {
-
 
65
			struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
-
 
66
			ret = drm_crtc_helper_set_config(mode_set);
78
	r_base = crtc->gamma_store;
Line 67... Line -...
67
			if (ret)
-
 
68
				error = true;
-
 
69
		}
-
 
70
	}
-
 
71
	return error;
-
 
72
}
79
	g_base = r_base + crtc->gamma_size;
73
 
80
	b_base = g_base + crtc->gamma_size;
-
 
81
 
-
 
82
	for (i = 0; i < crtc->gamma_size; i++)
74
/**
83
		helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i);
75
 * drm_fb_helper_restore - restore the framebuffer console (kernel) config
84
}
76
 *
85
 
-
 
86
static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
77
 * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
87
{
78
 */
88
	uint16_t *r_base, *g_base, *b_base;
79
void drm_fb_helper_restore(void)
-
 
Line 80... Line 89...
80
{
89
 
81
	bool ret;
90
	r_base = crtc->gamma_store;
82
	ret = drm_fb_helper_force_kernel_mode();
91
	g_base = r_base + crtc->gamma_size;
83
	if (ret == true)
92
	b_base = g_base + crtc->gamma_size;
84
		DRM_ERROR("Failed to restore crtc configuration\n");
93
 
-
 
94
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
-
 
95
}
85
}
96
 
86
EXPORT_SYMBOL(drm_fb_helper_restore);
97
 
Line 87... Line 98...
87
 
98
static void drm_fb_helper_on(struct fb_info *info)
88
 
99
{
89
static void drm_fb_helper_on(struct fb_info *info)
100
	struct drm_fb_helper *fb_helper = info->par;
90
{
101
	struct drm_device *dev = fb_helper->dev;
-
 
102
	struct drm_crtc *crtc;
91
	struct drm_fb_helper *fb_helper = info->par;
103
	struct drm_crtc_helper_funcs *crtc_funcs;
92
	struct drm_device *dev = fb_helper->dev;
104
	struct drm_connector *connector;
93
	struct drm_crtc *crtc;
-
 
94
	struct drm_encoder *encoder;
105
	struct drm_encoder *encoder;
Line 95... Line -...
95
	int i;
-
 
96
 
-
 
97
	/*
106
	int i, j;
98
	 * For each CRTC in this fb, turn the crtc on then,
107
 
Line 99... Line -...
99
	 * find all associated encoders and turn them on.
-
 
100
	 */
108
	/*
101
	for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
Line -... Line 109...
-
 
109
	 * For each CRTC in this fb, turn the crtc on then,
-
 
110
	 * find all associated encoders and turn them on.
-
 
111
	 */
-
 
112
	mutex_lock(&dev->mode_config.mutex);
-
 
113
	for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
114
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
-
 
115
		crtc_funcs = crtc->helper_private;
-
 
116
 
102
		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
117
		if (!crtc->enabled)
103
			struct drm_crtc_helper_funcs *crtc_funcs =
118
				continue;
104
				crtc->helper_private;
119
 
105
 
120
			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
Line 106... Line 121...
106
			/* Only mess with CRTCs in this fb */
121
 
107
			if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
-
 
108
			    !crtc->enabled)
122
		/* Walk the connectors & encoders on this fb turning them on */
109
				continue;
-
 
110
 
-
 
111
			mutex_lock(&dev->mode_config.mutex);
123
		for (j = 0; j < fb_helper->connector_count; j++) {
112
			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
124
			connector = fb_helper->connector_info[j]->connector;
113
			mutex_unlock(&dev->mode_config.mutex);
125
			connector->dpms = DRM_MODE_DPMS_ON;
-
 
126
			drm_connector_property_set_value(connector,
114
 
127
							 dev->mode_config.dpms_property,
Line 115... Line 128...
115
			/* Found a CRTC on this fb, now find encoders */
128
							 DRM_MODE_DPMS_ON);
116
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
129
		}
117
				if (encoder->crtc == crtc) {
130
			/* Found a CRTC on this fb, now find encoders */
118
					struct drm_encoder_helper_funcs *encoder_funcs;
131
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
119
 
132
				if (encoder->crtc == crtc) {
-
 
133
					struct drm_encoder_helper_funcs *encoder_funcs;
-
 
134
 
120
					encoder_funcs = encoder->helper_private;
135
					encoder_funcs = encoder->helper_private;
121
					mutex_lock(&dev->mode_config.mutex);
136
					encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
Line 122... Line 137...
122
					encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
137
			}
123
					mutex_unlock(&dev->mode_config.mutex);
138
		}
124
				}
139
	}
125
			}
140
	mutex_unlock(&dev->mode_config.mutex);
-
 
141
}
126
		}
142
 
127
	}
143
static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
128
}
-
 
129
 
144
{
Line 130... Line -...
130
static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
-
 
131
{
-
 
132
	struct drm_fb_helper *fb_helper = info->par;
145
	struct drm_fb_helper *fb_helper = info->par;
133
	struct drm_device *dev = fb_helper->dev;
146
	struct drm_device *dev = fb_helper->dev;
Line -... Line 147...
-
 
147
	struct drm_crtc *crtc;
-
 
148
	struct drm_crtc_helper_funcs *crtc_funcs;
-
 
149
	struct drm_connector *connector;
-
 
150
	struct drm_encoder *encoder;
-
 
151
	int i, j;
-
 
152
 
-
 
153
	/*
-
 
154
	 * For each CRTC in this fb, find all associated encoders
134
	struct drm_crtc *crtc;
155
	 * and turn them off, then turn off the CRTC.
135
	struct drm_encoder *encoder;
156
	 */
136
	int i;
157
	mutex_lock(&dev->mode_config.mutex);
137
 
158
	for (i = 0; i < fb_helper->crtc_count; i++) {
Line 138... Line 159...
138
	/*
159
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
139
	 * For each CRTC in this fb, find all associated encoders
-
 
140
	 * and turn them off, then turn off the CRTC.
160
		crtc_funcs = crtc->helper_private;
141
	 */
-
 
142
	for (i = 0; i < fb_helper->crtc_count; i++) {
161
 
143
		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
162
		if (!crtc->enabled)
144
			struct drm_crtc_helper_funcs *crtc_funcs =
-
 
145
				crtc->helper_private;
163
				continue;
146
 
-
 
147
			/* Only mess with CRTCs in this fb */
-
 
148
			if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
164
 
-
 
165
		/* Walk the connectors on this fb and mark them off */
149
			    !crtc->enabled)
166
		for (j = 0; j < fb_helper->connector_count; j++) {
Line 150... Line 167...
150
				continue;
167
			connector = fb_helper->connector_info[j]->connector;
151
 
168
			connector->dpms = dpms_mode;
152
			/* Found a CRTC on this fb, now find encoders */
169
			drm_connector_property_set_value(connector,
Line 197... Line 214...
197
 
214
 
198
static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
215
static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
199
{
216
{
Line -... Line 217...
-
 
217
	int i;
-
 
218
 
-
 
219
	for (i = 0; i < helper->connector_count; i++)
200
	int i;
220
		kfree(helper->connector_info[i]);
201
 
221
	kfree(helper->connector_info);
202
	for (i = 0; i < helper->crtc_count; i++)
222
	for (i = 0; i < helper->crtc_count; i++)
203
		kfree(helper->crtc_info[i].mode_set.connectors);
223
		kfree(helper->crtc_info[i].mode_set.connectors);
Line 204... Line 224...
204
	kfree(helper->crtc_info);
224
	kfree(helper->crtc_info);
-
 
225
}
-
 
226
 
205
}
227
int drm_fb_helper_init(struct drm_device *dev,
206
 
-
 
207
int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn_count)
228
		       struct drm_fb_helper *fb_helper,
208
{
229
		       int crtc_count, int max_conn_count)
209
	struct drm_device *dev = helper->dev;
230
{
Line -... Line 231...
-
 
231
	struct drm_crtc *crtc;
-
 
232
	int ret = 0;
-
 
233
	int i;
-
 
234
 
210
	struct drm_crtc *crtc;
235
	fb_helper->dev = dev;
211
	int ret = 0;
236
 
212
	int i;
237
	INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
Line 213... Line 238...
213
 
238
 
-
 
239
	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
-
 
240
	if (!fb_helper->crtc_info)
-
 
241
		return -ENOMEM;
-
 
242
 
-
 
243
	fb_helper->crtc_count = crtc_count;
-
 
244
	fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
Line 214... Line 245...
214
	helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
245
	if (!fb_helper->connector_info) {
215
	if (!helper->crtc_info)
246
		kfree(fb_helper->crtc_info);
216
		return -ENOMEM;
247
		return -ENOMEM;
217
 
248
	}
218
	helper->crtc_count = crtc_count;
249
	fb_helper->connector_count = 0;
Line 219... Line 250...
219
 
250
 
220
	for (i = 0; i < crtc_count; i++) {
251
	for (i = 0; i < crtc_count; i++) {
221
		helper->crtc_info[i].mode_set.connectors =
252
		fb_helper->crtc_info[i].mode_set.connectors =
222
			kcalloc(max_conn_count,
253
			kcalloc(max_conn_count,
223
				sizeof(struct drm_connector *),
254
				sizeof(struct drm_connector *),
224
				GFP_KERNEL);
255
				GFP_KERNEL);
Line 225... Line 256...
225
 
256
 
226
		if (!helper->crtc_info[i].mode_set.connectors) {
257
		if (!fb_helper->crtc_info[i].mode_set.connectors) {
227
			ret = -ENOMEM;
258
			ret = -ENOMEM;
228
			goto out_free;
259
			goto out_free;
229
		}
260
		}
230
		helper->crtc_info[i].mode_set.num_connectors = 0;
261
		fb_helper->crtc_info[i].mode_set.num_connectors = 0;
231
	}
262
	}
232
 
263
 
233
	i = 0;
264
	i = 0;
234
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
265
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
235
		helper->crtc_info[i].crtc_id = crtc->base.id;
266
		fb_helper->crtc_info[i].crtc_id = crtc->base.id;
236
		helper->crtc_info[i].mode_set.crtc = crtc;
267
		fb_helper->crtc_info[i].mode_set.crtc = crtc;
237
		i++;
268
		i++;
Line 238... Line 269...
238
	}
269
	}
239
	helper->conn_limit = max_conn_count;
270
	fb_helper->conn_limit = max_conn_count;
240
	return 0;
271
	return 0;
241
out_free:
272
out_free:
Line 262... Line 293...
262
		green >>= (16 - info->var.green.length);
293
		green >>= (16 - info->var.green.length);
263
		blue >>= (16 - info->var.blue.length);
294
		blue >>= (16 - info->var.blue.length);
264
		value = (red << info->var.red.offset) |
295
		value = (red << info->var.red.offset) |
265
			(green << info->var.green.offset) |
296
			(green << info->var.green.offset) |
266
			(blue << info->var.blue.offset);
297
			(blue << info->var.blue.offset);
-
 
298
		if (info->var.transp.length > 0) {
-
 
299
			u32 mask = (1 << info->var.transp.length) - 1;
-
 
300
			mask <<= info->var.transp.offset;
-
 
301
			value |= mask;
-
 
302
		}
267
		palette[regno] = value;
303
		palette[regno] = value;
268
		return 0;
304
		return 0;
269
	}
305
	}
Line 270... Line 306...
270
 
306
 
Line 304... Line 340...
304
}
340
}
Line 305... Line 341...
305
 
341
 
306
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
342
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
307
{
343
{
308
	struct drm_fb_helper *fb_helper = info->par;
344
	struct drm_fb_helper *fb_helper = info->par;
309
	struct drm_device *dev = fb_helper->dev;
345
	struct drm_crtc_helper_funcs *crtc_funcs;
310
	u16 *red, *green, *blue, *transp;
346
	u16 *red, *green, *blue, *transp;
311
	struct drm_crtc *crtc;
347
	struct drm_crtc *crtc;
312
	int i, rc = 0;
348
	int i, j, rc = 0;
Line 313... Line -...
313
	int start;
-
 
314
 
-
 
315
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
349
	int start;
316
		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
350
 
317
		for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
318
			if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
-
 
319
				break;
351
		for (i = 0; i < fb_helper->crtc_count; i++) {
320
		}
-
 
Line 321... Line 352...
321
		if (i == fb_helper->crtc_count)
352
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
322
			continue;
353
		crtc_funcs = crtc->helper_private;
323
 
354
 
324
		red = cmap->red;
355
		red = cmap->red;
325
		green = cmap->green;
356
		green = cmap->green;
Line 326... Line 357...
326
		blue = cmap->blue;
357
		blue = cmap->blue;
327
		transp = cmap->transp;
358
		transp = cmap->transp;
Line 328... Line 359...
328
		start = cmap->start;
359
		start = cmap->start;
329
 
360
 
330
		for (i = 0; i < cmap->len; i++) {
361
		for (j = 0; j < cmap->len; j++) {
Line 345... Line 376...
345
	}
376
	}
346
	return rc;
377
	return rc;
347
}
378
}
348
EXPORT_SYMBOL(drm_fb_helper_setcmap);
379
EXPORT_SYMBOL(drm_fb_helper_setcmap);
Line 349... Line -...
349
 
-
 
350
int drm_fb_helper_setcolreg(unsigned regno,
-
 
351
			    unsigned red,
-
 
352
			    unsigned green,
-
 
353
			    unsigned blue,
-
 
354
			    unsigned transp,
-
 
355
			    struct fb_info *info)
-
 
356
{
-
 
357
	struct drm_fb_helper *fb_helper = info->par;
-
 
358
	struct drm_device *dev = fb_helper->dev;
-
 
359
	struct drm_crtc *crtc;
-
 
360
	int i;
-
 
361
	int ret;
-
 
362
 
-
 
363
	if (regno > 255)
-
 
364
		return 1;
-
 
365
 
-
 
366
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-
 
367
		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
 
368
		for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
369
			if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
-
 
370
				break;
-
 
371
		}
-
 
372
		if (i == fb_helper->crtc_count)
-
 
373
			continue;
-
 
374
 
-
 
375
		ret = setcolreg(crtc, red, green, blue, regno, info);
-
 
376
		if (ret)
-
 
377
			return ret;
-
 
378
 
-
 
379
		crtc_funcs->load_lut(crtc);
-
 
380
	}
-
 
381
	return 0;
-
 
382
}
-
 
383
EXPORT_SYMBOL(drm_fb_helper_setcolreg);
-
 
384
 
380
 
385
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
381
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
386
			    struct fb_info *info)
382
			    struct fb_info *info)
387
{
383
{
388
	struct drm_fb_helper *fb_helper = info->par;
384
	struct drm_fb_helper *fb_helper = info->par;
389
	struct drm_framebuffer *fb = fb_helper->fb;
385
	struct drm_framebuffer *fb = fb_helper->fb;
Line 390... Line 386...
390
	int depth;
386
	int depth;
391
 
387
 
Line 392... Line 388...
392
	if (var->pixclock != 0)
388
	if (var->pixclock != 0 || in_dbg_master())
393
		return -EINVAL;
389
		return -EINVAL;
394
 
390
 
Line 483... Line 479...
483
	if (var->pixclock != 0) {
479
	if (var->pixclock != 0) {
484
		DRM_ERROR("PIXEL CLOCK SET\n");
480
		DRM_ERROR("PIXEL CLOCK SET\n");
485
		return -EINVAL;
481
		return -EINVAL;
486
	}
482
	}
Line 487... Line -...
487
 
-
 
488
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-
 
489
 
-
 
490
		for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
491
			if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
-
 
492
				break;
-
 
493
		}
-
 
494
		if (i == fb_helper->crtc_count)
-
 
495
			continue;
-
 
496
 
-
 
497
		if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) {
483
 
-
 
484
	mutex_lock(&dev->mode_config.mutex);
-
 
485
		for (i = 0; i < fb_helper->crtc_count; i++) {
498
			mutex_lock(&dev->mode_config.mutex);
486
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
-
 
487
			ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
499
			ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
488
		if (ret) {
500
			mutex_unlock(&dev->mode_config.mutex);
-
 
501
			if (ret)
489
			mutex_unlock(&dev->mode_config.mutex);
502
				return ret;
490
				return ret;
503
		}
491
		}
-
 
492
	}
-
 
493
	mutex_unlock(&dev->mode_config.mutex);
-
 
494
 
-
 
495
	if (fb_helper->delayed_hotplug) {
-
 
496
		fb_helper->delayed_hotplug = false;
-
 
497
//       drm_fb_helper_hotplug_event(fb_helper);
504
	}
498
	}
505
	return 0;
499
	return 0;
506
}
500
}
Line 507... Line 501...
507
EXPORT_SYMBOL(drm_fb_helper_set_par);
501
EXPORT_SYMBOL(drm_fb_helper_set_par);
Line 514... Line 508...
514
	struct drm_mode_set *modeset;
508
	struct drm_mode_set *modeset;
515
	struct drm_crtc *crtc;
509
	struct drm_crtc *crtc;
516
	int ret = 0;
510
	int ret = 0;
517
	int i;
511
	int i;
Line 518... Line 512...
518
 
512
 
519
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
513
	mutex_lock(&dev->mode_config.mutex);
520
		for (i = 0; i < fb_helper->crtc_count; i++) {
514
		for (i = 0; i < fb_helper->crtc_count; i++) {
521
			if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
-
 
522
				break;
-
 
523
		}
-
 
524
 
-
 
525
		if (i == fb_helper->crtc_count)
-
 
Line 526... Line 515...
526
			continue;
515
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
Line 527... Line 516...
527
 
516
 
528
		modeset = &fb_helper->crtc_info[i].mode_set;
517
		modeset = &fb_helper->crtc_info[i].mode_set;
Line 529... Line 518...
529
 
518
 
530
		modeset->x = var->xoffset;
-
 
531
		modeset->y = var->yoffset;
519
		modeset->x = var->xoffset;
532
 
-
 
533
		if (modeset->num_connectors) {
520
		modeset->y = var->yoffset;
534
			mutex_lock(&dev->mode_config.mutex);
521
 
535
			ret = crtc->funcs->set_config(modeset);
522
		if (modeset->num_connectors) {
536
			mutex_unlock(&dev->mode_config.mutex);
523
			ret = crtc->funcs->set_config(modeset);
537
			if (!ret) {
524
			if (!ret) {
538
				info->var.xoffset = var->xoffset;
525
				info->var.xoffset = var->xoffset;
-
 
526
				info->var.yoffset = var->yoffset;
539
				info->var.yoffset = var->yoffset;
527
			}
540
			}
528
		}
541
		}
529
	}
Line 542... Line 530...
542
	}
530
	mutex_unlock(&dev->mode_config.mutex);
543
	return ret;
531
	return ret;
544
}
-
 
545
EXPORT_SYMBOL(drm_fb_helper_pan_display);
-
 
546
 
-
 
547
int drm_fb_helper_single_fb_probe(struct drm_device *dev,
-
 
548
				  int preferred_bpp,
-
 
549
				  int (*fb_create)(struct drm_device *dev,
-
 
550
						   uint32_t fb_width,
-
 
551
						   uint32_t fb_height,
-
 
552
						   uint32_t surface_width,
532
}
553
						   uint32_t surface_height,
-
 
554
						   uint32_t surface_depth,
-
 
555
						   uint32_t surface_bpp,
-
 
556
						   struct drm_framebuffer **fb_ptr))
-
 
557
{
533
EXPORT_SYMBOL(drm_fb_helper_pan_display);
558
	struct drm_crtc *crtc;
534
 
559
	struct drm_connector *connector;
535
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
560
	unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
536
				  int preferred_bpp)
561
	unsigned int surface_width = 0, surface_height = 0;
-
 
562
	int new_fb = 0;
-
 
563
	int crtc_count = 0;
537
{
564
	int ret, i, conn_count = 0;
-
 
565
	struct fb_info *info;
-
 
566
	struct drm_framebuffer *fb;
-
 
567
	struct drm_mode_set *modeset = NULL;
-
 
568
	struct drm_fb_helper *fb_helper;
-
 
569
	uint32_t surface_depth = 24, surface_bpp = 32;
-
 
570
 
-
 
571
	/* if driver picks 8 or 16 by default use that
-
 
572
	   for both depth/bpp */
-
 
573
	if (preferred_bpp != surface_bpp) {
-
 
574
		surface_depth = surface_bpp = preferred_bpp;
-
 
575
	}
-
 
576
	/* first up get a count of crtcs now in use and new min/maxes width/heights */
-
 
577
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
538
	int new_fb = 0;
578
		struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
-
 
579
 
-
 
580
		struct drm_fb_helper_cmdline_mode *cmdline_mode;
-
 
Line 581... Line -...
581
 
-
 
582
		if (!fb_help_conn)
-
 
583
			continue;
-
 
584
		
539
	int crtc_count = 0;
585
		cmdline_mode = &fb_help_conn->cmdline_mode;
-
 
586
 
-
 
587
		if (cmdline_mode->bpp_specified) {
540
	int i;
588
			switch (cmdline_mode->bpp) {
541
	struct fb_info *info;
589
			case 8:
-
 
590
				surface_depth = surface_bpp = 8;
-
 
591
				break;
542
	struct drm_fb_helper_surface_size sizes;
592
			case 15:
-
 
593
				surface_depth = 15;
-
 
594
				surface_bpp = 16;
543
	int gamma_size = 0;
595
				break;
-
 
596
			case 16:
-
 
597
				surface_depth = surface_bpp = 16;
-
 
598
				break;
-
 
599
			case 24:
-
 
600
				surface_depth = surface_bpp = 24;
-
 
601
				break;
-
 
602
			case 32:
-
 
603
				surface_depth = 24;
-
 
604
				surface_bpp = 32;
-
 
605
				break;
-
 
606
			}
-
 
607
			break;
-
 
608
		}
-
 
609
	}
-
 
Line 610... Line 544...
610
 
544
 
611
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
545
	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
Line -... Line 546...
-
 
546
	sizes.surface_depth = 24;
-
 
547
	sizes.surface_bpp = 32;
612
		if (drm_helper_crtc_in_use(crtc)) {
548
	sizes.fb_width = (unsigned)-1;
613
			if (crtc->desired_mode) {
549
	sizes.fb_height = (unsigned)-1;
Line -... Line 550...
-
 
550
 
-
 
551
    sizes.surface_depth = 24;
-
 
552
    sizes.surface_bpp = 32;
-
 
553
 
-
 
554
	crtc_count = 0;
-
 
555
	for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
556
		struct drm_display_mode *desired_mode;
-
 
557
		desired_mode = fb_helper->crtc_info[i].desired_mode;
-
 
558
 
614
				if (crtc->desired_mode->hdisplay < fb_width)
559
		if (desired_mode) {
615
					fb_width = crtc->desired_mode->hdisplay;
560
			if (gamma_size == 0)
616
 
-
 
617
				if (crtc->desired_mode->vdisplay < fb_height)
561
				gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
618
					fb_height = crtc->desired_mode->vdisplay;
562
			if (desired_mode->hdisplay < sizes.fb_width)
619
 
563
				sizes.fb_width = desired_mode->hdisplay;
Line 620... Line 564...
620
				if (crtc->desired_mode->hdisplay > surface_width)
564
			if (desired_mode->vdisplay < sizes.fb_height)
621
					surface_width = crtc->desired_mode->hdisplay;
565
				sizes.fb_height = desired_mode->vdisplay;
622
 
566
			if (desired_mode->hdisplay > sizes.surface_width)
-
 
567
				sizes.surface_width = desired_mode->hdisplay;
623
				if (crtc->desired_mode->vdisplay > surface_height)
568
			if (desired_mode->vdisplay > sizes.surface_height)
-
 
569
				sizes.surface_height = desired_mode->vdisplay;
624
					surface_height = crtc->desired_mode->vdisplay;
570
			crtc_count++;
Line 625... Line 571...
625
			}
571
		}
626
			crtc_count++;
-
 
627
		}
-
 
628
	}
-
 
629
 
-
 
630
	if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
-
 
631
		/* hmm everyone went away - assume VGA cable just fell out
-
 
632
		   and will come back later. */
-
 
633
		return 0;
-
 
634
	}
-
 
635
 
-
 
Line 636... Line -...
636
	/* do we have an fb already? */
-
 
637
	if (list_empty(&dev->mode_config.fb_kernel_list)) {
-
 
638
		ret = (*fb_create)(dev, fb_width, fb_height, surface_width,
-
 
639
				   surface_height, surface_depth, surface_bpp,
-
 
640
				   &fb);
-
 
641
		if (ret)
572
	}
642
			return -EINVAL;
-
 
643
		new_fb = 1;
-
 
644
	} else {
-
 
645
		fb = list_first_entry(&dev->mode_config.fb_kernel_list,
-
 
Line 646... Line -...
646
				      struct drm_framebuffer, filp_head);
-
 
647
 
-
 
Line 648... Line -...
648
		/* if someone hotplugs something bigger than we have already allocated, we are pwned.
-
 
649
		   As really we can't resize an fbdev that is in the wild currently due to fbdev
-
 
650
		   not really being designed for the lower layers moving stuff around under it.
-
 
651
		   - so in the grand style of things - punt. */
573
 
652
		if ((fb->width < surface_width) ||
574
	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
653
		    (fb->height < surface_height)) {
575
		/* hmm everyone went away - assume VGA cable just fell out
654
			DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
-
 
655
			return -EINVAL;
-
 
656
		}
-
 
657
	}
-
 
658
 
-
 
659
	info = fb->fbdev;
-
 
660
	fb_helper = info->par;
-
 
661
 
-
 
662
	crtc_count = 0;
-
 
Line 663... Line 576...
663
	/* okay we need to setup new connector sets in the crtcs */
576
		   and will come back later. */
664
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-
 
Line 665... Line -...
665
		modeset = &fb_helper->crtc_info[crtc_count].mode_set;
-
 
666
		modeset->fb = fb;
577
		DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
Line 667... Line 578...
667
		conn_count = 0;
578
		sizes.fb_width = sizes.surface_width = 1024;
668
		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
579
		sizes.fb_height = sizes.surface_height = 768;
669
			if (connector->encoder)
-
 
670
				if (connector->encoder->crtc == modeset->crtc) {
-
 
671
					modeset->connectors[conn_count] = connector;
580
	}
672
					conn_count++;
-
 
673
					if (conn_count > fb_helper->conn_limit)
-
 
674
						BUG();
581
 
675
				}
-
 
676
		}
-
 
Line 677... Line 582...
677
 
582
	/* push down into drivers */
678
		for (i = conn_count; i < fb_helper->conn_limit; i++)
583
 
-
 
584
    DRM_INFO("enter fb probe\n");
-
 
585
 
-
 
586
 
-
 
587
    new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
679
			modeset->connectors[i] = NULL;
588
	if (new_fb < 0)
680
 
589
		return new_fb;
681
		modeset->crtc = crtc;
590
 
682
		crtc_count++;
-
 
683
 
-
 
Line 684... Line -...
684
		modeset->num_connectors = conn_count;
-
 
-
 
591
	info = fb_helper->fbdev;
685
		if (modeset->crtc->desired_mode) {
592
 
686
			if (modeset->mode)
593
#if 0
-
 
594
 
-
 
595
	/* set the fb pointer */
-
 
596
	for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
597
		fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
-
 
598
		}
687
				drm_mode_destroy(dev, modeset->mode);
599
 
688
			modeset->mode = drm_mode_duplicate(dev,
600
	if (new_fb) {
689
							   modeset->crtc->desired_mode);
601
		info->var.pixclock = 0;
Line 690... Line -...
690
		}
-
 
691
	}
-
 
692
	fb_helper->crtc_count = crtc_count;
-
 
693
	fb_helper->fb = fb;
-
 
694
 
-
 
695
	if (new_fb) {
-
 
696
		info->var.pixclock = 0;
-
 
697
	} else {
602
 
698
		drm_fb_helper_set_par(info);
603
		printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
699
	}
604
		       info->fix.id);
700
	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
605
 
701
	       info->fix.id);
606
	} else {
702
 
607
		drm_fb_helper_set_par(info);
-
 
608
	}
-
 
609
 
703
	/* Switch back to kernel console on panic */
610
 
704
	/* multi card linked list maybe */
611
	if (new_fb)
705
	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
612
        list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
706
	return 0;
613
 
707
}
614
#endif
Line 730... Line 637...
730
	info->fix.line_length = pitch;
637
	info->fix.line_length = pitch;
731
	return;
638
	return;
732
}
639
}
733
EXPORT_SYMBOL(drm_fb_helper_fill_fix);
640
EXPORT_SYMBOL(drm_fb_helper_fill_fix);
Line 734... Line 641...
734
 
641
 
735
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb,
642
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
736
			    uint32_t fb_width, uint32_t fb_height)
643
			    uint32_t fb_width, uint32_t fb_height)
-
 
644
{
737
{
645
	struct drm_framebuffer *fb = fb_helper->fb;
738
	info->pseudo_palette = fb->pseudo_palette;
646
	info->pseudo_palette = fb_helper->pseudo_palette;
739
	info->var.xres_virtual = fb->width;
647
	info->var.xres_virtual = fb->width;
740
	info->var.yres_virtual = fb->height;
648
	info->var.yres_virtual = fb->height;
-
 
649
	info->var.bits_per_pixel = fb->bits_per_pixel;
741
	info->var.bits_per_pixel = fb->bits_per_pixel;
650
	info->var.accel_flags = FB_ACCELF_TEXT;
742
	info->var.xoffset = 0;
651
	info->var.xoffset = 0;
743
	info->var.yoffset = 0;
652
	info->var.yoffset = 0;
744
	info->var.activate = FB_ACTIVATE_NOW;
653
	info->var.activate = FB_ACTIVATE_NOW;
745
	info->var.height = -1;
654
	info->var.height = -1;
Line 801... Line 710...
801
 
710
 
802
	info->var.xres = fb_width;
711
	info->var.xres = fb_width;
803
	info->var.yres = fb_height;
712
	info->var.yres = fb_height;
804
}
713
}
-
 
714
EXPORT_SYMBOL(drm_fb_helper_fill_var);
-
 
715
 
-
 
716
static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
-
 
717
					       uint32_t maxX,
-
 
718
					       uint32_t maxY)
-
 
719
{
-
 
720
	struct drm_connector *connector;
-
 
721
	int count = 0;
-
 
722
	int i;
-
 
723
 
-
 
724
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
725
		connector = fb_helper->connector_info[i]->connector;
-
 
726
		count += connector->funcs->fill_modes(connector, maxX, maxY);
-
 
727
	}
-
 
728
 
-
 
729
	return count;
-
 
730
}
-
 
731
 
-
 
732
static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
-
 
733
{
-
 
734
	struct drm_display_mode *mode;
-
 
735
 
-
 
736
	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
-
 
737
		if (drm_mode_width(mode) > width ||
-
 
738
		    drm_mode_height(mode) > height)
-
 
739
			continue;
-
 
740
		if (mode->type & DRM_MODE_TYPE_PREFERRED)
-
 
741
			return mode;
-
 
742
	}
-
 
743
	return NULL;
-
 
744
}
-
 
745
 
-
 
746
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
-
 
747
{
-
 
748
	struct drm_cmdline_mode *cmdline_mode;
-
 
749
	cmdline_mode = &fb_connector->cmdline_mode;
-
 
750
	return cmdline_mode->specified;
-
 
751
}
-
 
752
 
-
 
753
 
-
 
754
static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
-
 
755
{
-
 
756
	bool enable;
-
 
757
 
-
 
758
	if (strict) {
-
 
759
		enable = connector->status == connector_status_connected;
-
 
760
	} else {
-
 
761
		enable = connector->status != connector_status_disconnected;
-
 
762
	}
-
 
763
	return enable;
-
 
764
}
-
 
765
 
-
 
766
static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
-
 
767
				  bool *enabled)
-
 
768
{
-
 
769
	bool any_enabled = false;
-
 
770
	struct drm_connector *connector;
-
 
771
	int i = 0;
-
 
772
 
-
 
773
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
774
		connector = fb_helper->connector_info[i]->connector;
-
 
775
		enabled[i] = drm_connector_enabled(connector, true);
-
 
776
		DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
-
 
777
			  enabled[i] ? "yes" : "no");
-
 
778
		any_enabled |= enabled[i];
-
 
779
	}
-
 
780
 
-
 
781
	if (any_enabled)
-
 
782
		return;
-
 
783
 
-
 
784
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
785
		connector = fb_helper->connector_info[i]->connector;
-
 
786
		enabled[i] = drm_connector_enabled(connector, false);
-
 
787
	}
-
 
788
}
-
 
789
 
-
 
790
 
-
 
791
static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
-
 
792
				 struct drm_display_mode **modes,
-
 
793
				 bool *enabled, int width, int height)
-
 
794
{
-
 
795
	struct drm_fb_helper_connector *fb_helper_conn;
-
 
796
	int i;
-
 
797
 
-
 
798
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
799
		fb_helper_conn = fb_helper->connector_info[i];
-
 
800
 
-
 
801
		if (enabled[i] == false)
-
 
802
			continue;
-
 
803
 
-
 
804
		DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
-
 
805
			      fb_helper_conn->connector->base.id);
-
 
806
 
-
 
807
		/* got for command line mode first */
-
 
808
//       modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
-
 
809
 
-
 
810
        modes[i] = NULL;
-
 
811
 
-
 
812
		if (!modes[i]) {
-
 
813
			DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
-
 
814
				      fb_helper_conn->connector->base.id);
-
 
815
			modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
-
 
816
		}
-
 
817
		/* No preferred modes, pick one off the list */
-
 
818
		if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
-
 
819
			list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
-
 
820
				break;
-
 
821
		}
-
 
822
		DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
-
 
823
			  "none");
-
 
824
	}
-
 
825
	return true;
-
 
826
}
-
 
827
 
-
 
828
static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
-
 
829
			  struct drm_fb_helper_crtc **best_crtcs,
-
 
830
			  struct drm_display_mode **modes,
-
 
831
			  int n, int width, int height)
-
 
832
{
-
 
833
	int c, o;
-
 
834
	struct drm_device *dev = fb_helper->dev;
-
 
835
	struct drm_connector *connector;
-
 
836
	struct drm_connector_helper_funcs *connector_funcs;
-
 
837
	struct drm_encoder *encoder;
-
 
838
	struct drm_fb_helper_crtc *best_crtc;
-
 
839
	int my_score, best_score, score;
-
 
840
	struct drm_fb_helper_crtc **crtcs, *crtc;
-
 
841
	struct drm_fb_helper_connector *fb_helper_conn;
-
 
842
 
-
 
843
	if (n == fb_helper->connector_count)
-
 
844
		return 0;
-
 
845
 
-
 
846
	fb_helper_conn = fb_helper->connector_info[n];
-
 
847
	connector = fb_helper_conn->connector;
-
 
848
 
-
 
849
	best_crtcs[n] = NULL;
-
 
850
	best_crtc = NULL;
-
 
851
	best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
-
 
852
	if (modes[n] == NULL)
-
 
853
		return best_score;
-
 
854
 
-
 
855
	crtcs = kzalloc(dev->mode_config.num_connector *
-
 
856
			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
-
 
857
	if (!crtcs)
-
 
858
		return best_score;
-
 
859
 
-
 
860
	my_score = 1;
-
 
861
	if (connector->status == connector_status_connected)
-
 
862
		my_score++;
-
 
863
	if (drm_has_cmdline_mode(fb_helper_conn))
-
 
864
		my_score++;
-
 
865
	if (drm_has_preferred_mode(fb_helper_conn, width, height))
-
 
866
		my_score++;
-
 
867
 
-
 
868
	connector_funcs = connector->helper_private;
-
 
869
	encoder = connector_funcs->best_encoder(connector);
-
 
870
	if (!encoder)
-
 
871
		goto out;
-
 
872
 
-
 
873
	/* select a crtc for this connector and then attempt to configure
-
 
874
	   remaining connectors */
-
 
875
	for (c = 0; c < fb_helper->crtc_count; c++) {
-
 
876
		crtc = &fb_helper->crtc_info[c];
-
 
877
 
-
 
878
		if ((encoder->possible_crtcs & (1 << c)) == 0) {
-
 
879
			continue;
-
 
880
		}
-
 
881
 
-
 
882
		for (o = 0; o < n; o++)
-
 
883
			if (best_crtcs[o] == crtc)
-
 
884
				break;
-
 
885
 
-
 
886
		if (o < n) {
-
 
887
			/* ignore cloning unless only a single crtc */
-
 
888
			if (fb_helper->crtc_count > 1)
-
 
889
				continue;
-
 
890
 
-
 
891
			if (!drm_mode_equal(modes[o], modes[n]))
-
 
892
				continue;
-
 
893
		}
-
 
894
 
-
 
895
		crtcs[n] = crtc;
-
 
896
		memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
-
 
897
		score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
-
 
898
						  width, height);
-
 
899
		if (score > best_score) {
-
 
900
			best_crtc = crtc;
-
 
901
			best_score = score;
-
 
902
			memcpy(best_crtcs, crtcs,
-
 
903
			       dev->mode_config.num_connector *
-
 
904
			       sizeof(struct drm_fb_helper_crtc *));
-
 
905
		}
-
 
906
	}
-
 
907
out:
-
 
908
	kfree(crtcs);
-
 
909
	return best_score;
-
 
910
}
-
 
911
 
-
 
912
static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
-
 
913
{
-
 
914
	struct drm_device *dev = fb_helper->dev;
-
 
915
	struct drm_fb_helper_crtc **crtcs;
-
 
916
	struct drm_display_mode **modes;
-
 
917
	struct drm_encoder *encoder;
-
 
918
	struct drm_mode_set *modeset;
-
 
919
	bool *enabled;
-
 
920
	int width, height;
-
 
921
	int i, ret;
-
 
922
 
-
 
923
	DRM_DEBUG_KMS("\n");
-
 
924
 
-
 
925
	width = dev->mode_config.max_width;
-
 
926
	height = dev->mode_config.max_height;
-
 
927
 
-
 
928
	/* clean out all the encoder/crtc combos */
-
 
929
//   list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
 
930
//       encoder->crtc = NULL;
-
 
931
//   }
-
 
932
 
-
 
933
	crtcs = kcalloc(dev->mode_config.num_connector,
-
 
934
			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
-
 
935
	modes = kcalloc(dev->mode_config.num_connector,
-
 
936
			sizeof(struct drm_display_mode *), GFP_KERNEL);
-
 
937
	enabled = kcalloc(dev->mode_config.num_connector,
-
 
938
			  sizeof(bool), GFP_KERNEL);
-
 
939
 
-
 
940
	drm_enable_connectors(fb_helper, enabled);
-
 
941
 
-
 
942
    //ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
-
 
943
 
-
 
944
    ret = 0;
-
 
945
 
-
 
946
	if (!ret) {
-
 
947
		ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
-
 
948
		if (!ret)
-
 
949
			DRM_ERROR("Unable to find initial modes\n");
-
 
950
	}
-
 
951
 
-
 
952
	DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
-
 
953
 
-
 
954
	drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
-
 
955
 
-
 
956
	/* need to set the modesets up here for use later */
-
 
957
	/* fill out the connector<->crtc mappings into the modesets */
-
 
958
	for (i = 0; i < fb_helper->crtc_count; i++) {
-
 
959
		modeset = &fb_helper->crtc_info[i].mode_set;
-
 
960
		modeset->num_connectors = 0;
-
 
961
	}
-
 
962
 
-
 
963
	for (i = 0; i < fb_helper->connector_count; i++) {
-
 
964
		struct drm_display_mode *mode = modes[i];
-
 
965
		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
-
 
966
		modeset = &fb_crtc->mode_set;
-
 
967
 
-
 
968
		if (mode && fb_crtc) {
-
 
969
			DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
-
 
970
				      mode->name, fb_crtc->mode_set.crtc->base.id);
-
 
971
			fb_crtc->desired_mode = mode;
-
 
972
			if (modeset->mode)
-
 
973
				drm_mode_destroy(dev, modeset->mode);
-
 
974
			modeset->mode = drm_mode_duplicate(dev,
-
 
975
							   fb_crtc->desired_mode);
-
 
976
			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
-
 
977
		}
-
 
978
	}
-
 
979
 
-
 
980
	kfree(crtcs);
-
 
981
	kfree(modes);
-
 
982
	kfree(enabled);
-
 
983
}
-
 
984
 
-
 
985
/**
-
 
986
 * drm_helper_initial_config - setup a sane initial connector configuration
-
 
987
 * @dev: DRM device
-
 
988
 *
-
 
989
 * LOCKING:
-
 
990
 * Called at init time, must take mode config lock.
-
 
991
 *
-
 
992
 * Scan the CRTCs and connectors and try to put together an initial setup.
-
 
993
 * At the moment, this is a cloned configuration across all heads with
-
 
994
 * a new framebuffer object as the backing store.
-
 
995
 *
-
 
996
 * RETURNS:
-
 
997
 * Zero if everything went ok, nonzero otherwise.
-
 
998
 */
-
 
999
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
-
 
1000
{
-
 
1001
	struct drm_device *dev = fb_helper->dev;
-
 
1002
	int count = 0;
-
 
1003
 
-
 
1004
	/* disable all the possible outputs/crtcs before entering KMS mode */
-
 
1005
//   drm_helper_disable_unused_functions(fb_helper->dev);
-
 
1006
 
-
 
1007
//   drm_fb_helper_parse_command_line(fb_helper);
-
 
1008
 
-
 
1009
	count = drm_fb_helper_probe_connector_modes(fb_helper,
-
 
1010
						    dev->mode_config.max_width,
-
 
1011
						    dev->mode_config.max_height);
-
 
1012
	/*
-
 
1013
	 * we shouldn't end up with no modes here.
-
 
1014
	 */
-
 
1015
	if (count == 0) {
-
 
1016
		printk(KERN_INFO "No connectors reported connected with modes\n");
-
 
1017
	}
-
 
1018
	drm_setup_crtcs(fb_helper);
-
 
1019
 
-
 
1020
 
-
 
1021
 
-
 
1022
	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
-
 
1023
}