Subversion Repositories Kolibri OS

Rev

Rev 1963 | Rev 2004 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1963 Rev 1986
1
/*
1
/*
2
 * Copyright (c) 2006-2009 Red Hat Inc.
2
 * Copyright (c) 2006-2009 Red Hat Inc.
3
 * Copyright (c) 2006-2008 Intel Corporation
3
 * Copyright (c) 2006-2008 Intel Corporation
4
 * Copyright (c) 2007 Dave Airlie 
4
 * Copyright (c) 2007 Dave Airlie 
5
 *
5
 *
6
 * DRM framebuffer helper functions
6
 * DRM framebuffer helper functions
7
 *
7
 *
8
 * Permission to use, copy, modify, distribute, and sell this software and its
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
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
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
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
12
 * that the name of the copyright holders not be used in advertising or
13
 * publicity pertaining to distribution of the software without specific,
13
 * publicity pertaining to distribution of the software without specific,
14
 * written prior permission.  The copyright holders make no representations
14
 * written prior permission.  The copyright holders make no representations
15
 * about the suitability of this software for any purpose.  It is provided "as
15
 * about the suitability of this software for any purpose.  It is provided "as
16
 * is" without express or implied warranty.
16
 * is" without express or implied warranty.
17
 *
17
 *
18
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
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,
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
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
23
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24
 * OF THIS SOFTWARE.
24
 * OF THIS SOFTWARE.
25
 *
25
 *
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 
34
#include "drmP.h"
34
#include "drmP.h"
35
#include "drm_crtc.h"
35
#include "drm_crtc.h"
36
#include "drm_fb_helper.h"
36
#include "drm_fb_helper.h"
37
#include "drm_crtc_helper.h"
37
#include "drm_crtc_helper.h"
38
 
38
 
39
MODULE_AUTHOR("David Airlie, Jesse Barnes");
39
MODULE_AUTHOR("David Airlie, Jesse Barnes");
40
MODULE_DESCRIPTION("DRM KMS helper");
40
MODULE_DESCRIPTION("DRM KMS helper");
41
MODULE_LICENSE("GPL and additional rights");
41
MODULE_LICENSE("GPL and additional rights");
42
 
42
 
43
static LIST_HEAD(kernel_fb_helper_list);
43
static LIST_HEAD(kernel_fb_helper_list);
44
 
44
 
45
/* simple single crtc case helper function */
45
/* simple single crtc case helper function */
46
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
46
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
47
{
47
{
48
	struct drm_device *dev = fb_helper->dev;
48
	struct drm_device *dev = fb_helper->dev;
49
	struct drm_connector *connector;
49
	struct drm_connector *connector;
50
	int i;
50
	int i;
51
 
51
 
52
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
52
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
53
		struct drm_fb_helper_connector *fb_helper_connector;
53
		struct drm_fb_helper_connector *fb_helper_connector;
54
 
54
 
55
		fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
55
		fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
56
		if (!fb_helper_connector)
56
		if (!fb_helper_connector)
57
			goto fail;
57
			goto fail;
58
 
58
 
59
		fb_helper_connector->connector = connector;
59
		fb_helper_connector->connector = connector;
60
		fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
60
		fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
61
	}
61
	}
62
	return 0;
62
	return 0;
63
fail:
63
fail:
64
	for (i = 0; i < fb_helper->connector_count; i++) {
64
	for (i = 0; i < fb_helper->connector_count; i++) {
65
		kfree(fb_helper->connector_info[i]);
65
		kfree(fb_helper->connector_info[i]);
66
		fb_helper->connector_info[i] = NULL;
66
		fb_helper->connector_info[i] = NULL;
67
	}
67
	}
68
	fb_helper->connector_count = 0;
68
	fb_helper->connector_count = 0;
69
    return -ENOMEM;
69
    return -ENOMEM;
70
}
70
}
71
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
71
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
72
 
72
 
73
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
73
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
74
{
74
{
75
	uint16_t *r_base, *g_base, *b_base;
75
	uint16_t *r_base, *g_base, *b_base;
76
	int i;
76
	int i;
77
 
77
 
78
	r_base = crtc->gamma_store;
78
	r_base = crtc->gamma_store;
79
	g_base = r_base + crtc->gamma_size;
79
	g_base = r_base + crtc->gamma_size;
80
	b_base = g_base + crtc->gamma_size;
80
	b_base = g_base + crtc->gamma_size;
81
 
81
 
82
	for (i = 0; i < crtc->gamma_size; i++)
82
	for (i = 0; i < crtc->gamma_size; i++)
83
		helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i);
83
		helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i);
84
}
84
}
85
 
85
 
86
static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
86
static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
87
{
87
{
88
	uint16_t *r_base, *g_base, *b_base;
88
	uint16_t *r_base, *g_base, *b_base;
89
 
89
 
90
	r_base = crtc->gamma_store;
90
	r_base = crtc->gamma_store;
91
	g_base = r_base + crtc->gamma_size;
91
	g_base = r_base + crtc->gamma_size;
92
	b_base = g_base + crtc->gamma_size;
92
	b_base = g_base + crtc->gamma_size;
93
 
93
 
94
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
94
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
95
}
95
}
96
 
96
 
97
 
97
 
98
static void drm_fb_helper_on(struct fb_info *info)
98
static void drm_fb_helper_on(struct fb_info *info)
99
{
99
{
100
	struct drm_fb_helper *fb_helper = info->par;
100
	struct drm_fb_helper *fb_helper = info->par;
101
	struct drm_device *dev = fb_helper->dev;
101
	struct drm_device *dev = fb_helper->dev;
102
	struct drm_crtc *crtc;
102
	struct drm_crtc *crtc;
103
	struct drm_crtc_helper_funcs *crtc_funcs;
103
	struct drm_crtc_helper_funcs *crtc_funcs;
104
	struct drm_connector *connector;
104
	struct drm_connector *connector;
105
	struct drm_encoder *encoder;
105
	struct drm_encoder *encoder;
106
	int i, j;
106
	int i, j;
107
 
107
 
108
	/*
108
	/*
109
	 * For each CRTC in this fb, turn the crtc on then,
109
	 * For each CRTC in this fb, turn the crtc on then,
110
	 * find all associated encoders and turn them on.
110
	 * find all associated encoders and turn them on.
111
	 */
111
	 */
112
	mutex_lock(&dev->mode_config.mutex);
112
	mutex_lock(&dev->mode_config.mutex);
113
	for (i = 0; i < fb_helper->crtc_count; i++) {
113
	for (i = 0; i < fb_helper->crtc_count; i++) {
114
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
114
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
115
		crtc_funcs = crtc->helper_private;
115
		crtc_funcs = crtc->helper_private;
116
 
116
 
117
		if (!crtc->enabled)
117
		if (!crtc->enabled)
118
				continue;
118
				continue;
119
 
119
 
120
			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
120
			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
121
 
121
 
122
		/* Walk the connectors & encoders on this fb turning them on */
122
		/* Walk the connectors & encoders on this fb turning them on */
123
		for (j = 0; j < fb_helper->connector_count; j++) {
123
		for (j = 0; j < fb_helper->connector_count; j++) {
124
			connector = fb_helper->connector_info[j]->connector;
124
			connector = fb_helper->connector_info[j]->connector;
125
			connector->dpms = DRM_MODE_DPMS_ON;
125
			connector->dpms = DRM_MODE_DPMS_ON;
126
			drm_connector_property_set_value(connector,
126
			drm_connector_property_set_value(connector,
127
							 dev->mode_config.dpms_property,
127
							 dev->mode_config.dpms_property,
128
							 DRM_MODE_DPMS_ON);
128
							 DRM_MODE_DPMS_ON);
129
		}
129
		}
130
			/* Found a CRTC on this fb, now find encoders */
130
			/* Found a CRTC on this fb, now find encoders */
131
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
131
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
132
				if (encoder->crtc == crtc) {
132
				if (encoder->crtc == crtc) {
133
					struct drm_encoder_helper_funcs *encoder_funcs;
133
					struct drm_encoder_helper_funcs *encoder_funcs;
134
 
134
 
135
					encoder_funcs = encoder->helper_private;
135
					encoder_funcs = encoder->helper_private;
136
					encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
136
					encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
137
			}
137
			}
138
		}
138
		}
139
	}
139
	}
140
	mutex_unlock(&dev->mode_config.mutex);
140
	mutex_unlock(&dev->mode_config.mutex);
141
}
141
}
142
 
142
 
143
static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
143
static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
144
{
144
{
145
	struct drm_fb_helper *fb_helper = info->par;
145
	struct drm_fb_helper *fb_helper = info->par;
146
	struct drm_device *dev = fb_helper->dev;
146
	struct drm_device *dev = fb_helper->dev;
147
	struct drm_crtc *crtc;
147
	struct drm_crtc *crtc;
148
	struct drm_crtc_helper_funcs *crtc_funcs;
148
	struct drm_crtc_helper_funcs *crtc_funcs;
149
	struct drm_connector *connector;
149
	struct drm_connector *connector;
150
	struct drm_encoder *encoder;
150
	struct drm_encoder *encoder;
151
	int i, j;
151
	int i, j;
152
 
152
 
153
	/*
153
	/*
154
	 * For each CRTC in this fb, find all associated encoders
154
	 * For each CRTC in this fb, find all associated encoders
155
	 * and turn them off, then turn off the CRTC.
155
	 * and turn them off, then turn off the CRTC.
156
	 */
156
	 */
157
	mutex_lock(&dev->mode_config.mutex);
157
	mutex_lock(&dev->mode_config.mutex);
158
	for (i = 0; i < fb_helper->crtc_count; i++) {
158
	for (i = 0; i < fb_helper->crtc_count; i++) {
159
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
159
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
160
		crtc_funcs = crtc->helper_private;
160
		crtc_funcs = crtc->helper_private;
161
 
161
 
162
		if (!crtc->enabled)
162
		if (!crtc->enabled)
163
				continue;
163
				continue;
164
 
164
 
165
		/* Walk the connectors on this fb and mark them off */
165
		/* Walk the connectors on this fb and mark them off */
166
		for (j = 0; j < fb_helper->connector_count; j++) {
166
		for (j = 0; j < fb_helper->connector_count; j++) {
167
			connector = fb_helper->connector_info[j]->connector;
167
			connector = fb_helper->connector_info[j]->connector;
168
			connector->dpms = dpms_mode;
168
			connector->dpms = dpms_mode;
169
			drm_connector_property_set_value(connector,
169
			drm_connector_property_set_value(connector,
170
							 dev->mode_config.dpms_property,
170
							 dev->mode_config.dpms_property,
171
							 dpms_mode);
171
							 dpms_mode);
172
		}
172
		}
173
			/* Found a CRTC on this fb, now find encoders */
173
			/* Found a CRTC on this fb, now find encoders */
174
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
174
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
175
				if (encoder->crtc == crtc) {
175
				if (encoder->crtc == crtc) {
176
					struct drm_encoder_helper_funcs *encoder_funcs;
176
					struct drm_encoder_helper_funcs *encoder_funcs;
177
 
177
 
178
					encoder_funcs = encoder->helper_private;
178
					encoder_funcs = encoder->helper_private;
179
					encoder_funcs->dpms(encoder, dpms_mode);
179
					encoder_funcs->dpms(encoder, dpms_mode);
180
				}
180
				}
181
			}
181
			}
182
			    crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
182
			    crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
183
	}
183
	}
184
				mutex_unlock(&dev->mode_config.mutex);
184
				mutex_unlock(&dev->mode_config.mutex);
185
}
185
}
186
 
186
 
187
int drm_fb_helper_blank(int blank, struct fb_info *info)
187
int drm_fb_helper_blank(int blank, struct fb_info *info)
188
{
188
{
189
	switch (blank) {
189
	switch (blank) {
190
	/* Display: On; HSync: On, VSync: On */
190
	/* Display: On; HSync: On, VSync: On */
191
	case FB_BLANK_UNBLANK:
191
	case FB_BLANK_UNBLANK:
192
		drm_fb_helper_on(info);
192
		drm_fb_helper_on(info);
193
		break;
193
		break;
194
	/* Display: Off; HSync: On, VSync: On */
194
	/* Display: Off; HSync: On, VSync: On */
195
	case FB_BLANK_NORMAL:
195
	case FB_BLANK_NORMAL:
196
		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
196
		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
197
		break;
197
		break;
198
	/* Display: Off; HSync: Off, VSync: On */
198
	/* Display: Off; HSync: Off, VSync: On */
199
	case FB_BLANK_HSYNC_SUSPEND:
199
	case FB_BLANK_HSYNC_SUSPEND:
200
		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
200
		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
201
		break;
201
		break;
202
	/* Display: Off; HSync: On, VSync: Off */
202
	/* Display: Off; HSync: On, VSync: Off */
203
	case FB_BLANK_VSYNC_SUSPEND:
203
	case FB_BLANK_VSYNC_SUSPEND:
204
		drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
204
		drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
205
		break;
205
		break;
206
	/* Display: Off; HSync: Off, VSync: Off */
206
	/* Display: Off; HSync: Off, VSync: Off */
207
	case FB_BLANK_POWERDOWN:
207
	case FB_BLANK_POWERDOWN:
208
		drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
208
		drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
209
		break;
209
		break;
210
	}
210
	}
211
	return 0;
211
	return 0;
212
}
212
}
213
EXPORT_SYMBOL(drm_fb_helper_blank);
213
EXPORT_SYMBOL(drm_fb_helper_blank);
214
 
214
 
215
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)
216
{
216
{
217
	int i;
217
	int i;
218
 
218
 
219
	for (i = 0; i < helper->connector_count; i++)
219
	for (i = 0; i < helper->connector_count; i++)
220
		kfree(helper->connector_info[i]);
220
		kfree(helper->connector_info[i]);
221
	kfree(helper->connector_info);
221
	kfree(helper->connector_info);
222
	for (i = 0; i < helper->crtc_count; i++)
222
	for (i = 0; i < helper->crtc_count; i++)
223
		kfree(helper->crtc_info[i].mode_set.connectors);
223
		kfree(helper->crtc_info[i].mode_set.connectors);
224
	kfree(helper->crtc_info);
224
	kfree(helper->crtc_info);
225
}
225
}
226
 
226
 
227
int drm_fb_helper_init(struct drm_device *dev,
227
int drm_fb_helper_init(struct drm_device *dev,
228
		       struct drm_fb_helper *fb_helper,
228
		       struct drm_fb_helper *fb_helper,
229
		       int crtc_count, int max_conn_count)
229
		       int crtc_count, int max_conn_count)
230
{
230
{
231
	struct drm_crtc *crtc;
231
	struct drm_crtc *crtc;
232
	int ret = 0;
232
	int ret = 0;
233
	int i;
233
	int i;
234
 
234
 
235
	fb_helper->dev = dev;
235
	fb_helper->dev = dev;
236
 
236
 
237
	INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
237
	INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
238
 
238
 
239
	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
239
	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
240
	if (!fb_helper->crtc_info)
240
	if (!fb_helper->crtc_info)
241
		return -ENOMEM;
241
		return -ENOMEM;
242
 
242
 
243
	fb_helper->crtc_count = crtc_count;
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);
244
	fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
245
	if (!fb_helper->connector_info) {
245
	if (!fb_helper->connector_info) {
246
		kfree(fb_helper->crtc_info);
246
		kfree(fb_helper->crtc_info);
247
		return -ENOMEM;
247
		return -ENOMEM;
248
	}
248
	}
249
	fb_helper->connector_count = 0;
249
	fb_helper->connector_count = 0;
250
 
250
 
251
	for (i = 0; i < crtc_count; i++) {
251
	for (i = 0; i < crtc_count; i++) {
252
		fb_helper->crtc_info[i].mode_set.connectors =
252
		fb_helper->crtc_info[i].mode_set.connectors =
253
			kcalloc(max_conn_count,
253
			kcalloc(max_conn_count,
254
				sizeof(struct drm_connector *),
254
				sizeof(struct drm_connector *),
255
				GFP_KERNEL);
255
				GFP_KERNEL);
256
 
256
 
257
		if (!fb_helper->crtc_info[i].mode_set.connectors) {
257
		if (!fb_helper->crtc_info[i].mode_set.connectors) {
258
			ret = -ENOMEM;
258
			ret = -ENOMEM;
259
			goto out_free;
259
			goto out_free;
260
		}
260
		}
261
		fb_helper->crtc_info[i].mode_set.num_connectors = 0;
261
		fb_helper->crtc_info[i].mode_set.num_connectors = 0;
262
	}
262
	}
263
 
263
 
264
	i = 0;
264
	i = 0;
265
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
265
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
266
		fb_helper->crtc_info[i].crtc_id = crtc->base.id;
266
		fb_helper->crtc_info[i].crtc_id = crtc->base.id;
267
		fb_helper->crtc_info[i].mode_set.crtc = crtc;
267
		fb_helper->crtc_info[i].mode_set.crtc = crtc;
268
		i++;
268
		i++;
269
	}
269
	}
270
	fb_helper->conn_limit = max_conn_count;
270
	fb_helper->conn_limit = max_conn_count;
271
	return 0;
271
	return 0;
272
out_free:
272
out_free:
273
	drm_fb_helper_crtc_free(fb_helper);
273
	drm_fb_helper_crtc_free(fb_helper);
274
	return -ENOMEM;
274
	return -ENOMEM;
275
}
275
}
276
EXPORT_SYMBOL(drm_fb_helper_init);
276
EXPORT_SYMBOL(drm_fb_helper_init);
277
 
277
 
278
static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
278
static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
279
		     u16 blue, u16 regno, struct fb_info *info)
279
		     u16 blue, u16 regno, struct fb_info *info)
280
{
280
{
281
	struct drm_fb_helper *fb_helper = info->par;
281
	struct drm_fb_helper *fb_helper = info->par;
282
	struct drm_framebuffer *fb = fb_helper->fb;
282
	struct drm_framebuffer *fb = fb_helper->fb;
283
	int pindex;
283
	int pindex;
284
 
284
 
285
	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
285
	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
286
		u32 *palette;
286
		u32 *palette;
287
		u32 value;
287
		u32 value;
288
		/* place color in psuedopalette */
288
		/* place color in psuedopalette */
289
		if (regno > 16)
289
		if (regno > 16)
290
			return -EINVAL;
290
			return -EINVAL;
291
		palette = (u32 *)info->pseudo_palette;
291
		palette = (u32 *)info->pseudo_palette;
292
		red >>= (16 - info->var.red.length);
292
		red >>= (16 - info->var.red.length);
293
		green >>= (16 - info->var.green.length);
293
		green >>= (16 - info->var.green.length);
294
		blue >>= (16 - info->var.blue.length);
294
		blue >>= (16 - info->var.blue.length);
295
		value = (red << info->var.red.offset) |
295
		value = (red << info->var.red.offset) |
296
			(green << info->var.green.offset) |
296
			(green << info->var.green.offset) |
297
			(blue << info->var.blue.offset);
297
			(blue << info->var.blue.offset);
298
		if (info->var.transp.length > 0) {
298
		if (info->var.transp.length > 0) {
299
			u32 mask = (1 << info->var.transp.length) - 1;
299
			u32 mask = (1 << info->var.transp.length) - 1;
300
			mask <<= info->var.transp.offset;
300
			mask <<= info->var.transp.offset;
301
			value |= mask;
301
			value |= mask;
302
		}
302
		}
303
		palette[regno] = value;
303
		palette[regno] = value;
304
		return 0;
304
		return 0;
305
	}
305
	}
306
 
306
 
307
	pindex = regno;
307
	pindex = regno;
308
 
308
 
309
	if (fb->bits_per_pixel == 16) {
309
	if (fb->bits_per_pixel == 16) {
310
		pindex = regno << 3;
310
		pindex = regno << 3;
311
 
311
 
312
		if (fb->depth == 16 && regno > 63)
312
		if (fb->depth == 16 && regno > 63)
313
			return -EINVAL;
313
			return -EINVAL;
314
		if (fb->depth == 15 && regno > 31)
314
		if (fb->depth == 15 && regno > 31)
315
			return -EINVAL;
315
			return -EINVAL;
316
 
316
 
317
		if (fb->depth == 16) {
317
		if (fb->depth == 16) {
318
			u16 r, g, b;
318
			u16 r, g, b;
319
			int i;
319
			int i;
320
			if (regno < 32) {
320
			if (regno < 32) {
321
				for (i = 0; i < 8; i++)
321
				for (i = 0; i < 8; i++)
322
					fb_helper->funcs->gamma_set(crtc, red,
322
					fb_helper->funcs->gamma_set(crtc, red,
323
						green, blue, pindex + i);
323
						green, blue, pindex + i);
324
			}
324
			}
325
 
325
 
326
			fb_helper->funcs->gamma_get(crtc, &r,
326
			fb_helper->funcs->gamma_get(crtc, &r,
327
						    &g, &b,
327
						    &g, &b,
328
						    pindex >> 1);
328
						    pindex >> 1);
329
 
329
 
330
			for (i = 0; i < 4; i++)
330
			for (i = 0; i < 4; i++)
331
				fb_helper->funcs->gamma_set(crtc, r,
331
				fb_helper->funcs->gamma_set(crtc, r,
332
							    green, b,
332
							    green, b,
333
							    (pindex >> 1) + i);
333
							    (pindex >> 1) + i);
334
		}
334
		}
335
	}
335
	}
336
 
336
 
337
	if (fb->depth != 16)
337
	if (fb->depth != 16)
338
		fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
338
		fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
339
	return 0;
339
	return 0;
340
}
340
}
341
 
341
 
342
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)
343
{
343
{
344
	struct drm_fb_helper *fb_helper = info->par;
344
	struct drm_fb_helper *fb_helper = info->par;
345
	struct drm_crtc_helper_funcs *crtc_funcs;
345
	struct drm_crtc_helper_funcs *crtc_funcs;
346
	u16 *red, *green, *blue, *transp;
346
	u16 *red, *green, *blue, *transp;
347
	struct drm_crtc *crtc;
347
	struct drm_crtc *crtc;
348
	int i, j, rc = 0;
348
	int i, j, rc = 0;
349
	int start;
349
	int start;
350
 
350
 
351
		for (i = 0; i < fb_helper->crtc_count; i++) {
351
		for (i = 0; i < fb_helper->crtc_count; i++) {
352
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
352
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
353
		crtc_funcs = crtc->helper_private;
353
		crtc_funcs = crtc->helper_private;
354
 
354
 
355
		red = cmap->red;
355
		red = cmap->red;
356
		green = cmap->green;
356
		green = cmap->green;
357
		blue = cmap->blue;
357
		blue = cmap->blue;
358
		transp = cmap->transp;
358
		transp = cmap->transp;
359
		start = cmap->start;
359
		start = cmap->start;
360
 
360
 
361
		for (j = 0; j < cmap->len; j++) {
361
		for (j = 0; j < cmap->len; j++) {
362
			u16 hred, hgreen, hblue, htransp = 0xffff;
362
			u16 hred, hgreen, hblue, htransp = 0xffff;
363
 
363
 
364
			hred = *red++;
364
			hred = *red++;
365
			hgreen = *green++;
365
			hgreen = *green++;
366
			hblue = *blue++;
366
			hblue = *blue++;
367
 
367
 
368
			if (transp)
368
			if (transp)
369
				htransp = *transp++;
369
				htransp = *transp++;
370
 
370
 
371
			rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
371
			rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
372
			if (rc)
372
			if (rc)
373
				return rc;
373
				return rc;
374
		}
374
		}
375
		crtc_funcs->load_lut(crtc);
375
		crtc_funcs->load_lut(crtc);
376
	}
376
	}
377
	return rc;
377
	return rc;
378
}
378
}
379
EXPORT_SYMBOL(drm_fb_helper_setcmap);
379
EXPORT_SYMBOL(drm_fb_helper_setcmap);
380
 
380
 
381
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
381
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
382
			    struct fb_info *info)
382
			    struct fb_info *info)
383
{
383
{
384
	struct drm_fb_helper *fb_helper = info->par;
384
	struct drm_fb_helper *fb_helper = info->par;
385
	struct drm_framebuffer *fb = fb_helper->fb;
385
	struct drm_framebuffer *fb = fb_helper->fb;
386
	int depth;
386
	int depth;
387
 
387
 
388
	if (var->pixclock != 0 || in_dbg_master())
388
	if (var->pixclock != 0 || in_dbg_master())
389
		return -EINVAL;
389
		return -EINVAL;
390
 
390
 
391
	/* Need to resize the fb object !!! */
391
	/* Need to resize the fb object !!! */
392
	if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
392
	if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
393
		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
393
		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
394
			  "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
394
			  "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
395
			  fb->width, fb->height, fb->bits_per_pixel);
395
			  fb->width, fb->height, fb->bits_per_pixel);
396
		return -EINVAL;
396
		return -EINVAL;
397
	}
397
	}
398
 
398
 
399
	switch (var->bits_per_pixel) {
399
	switch (var->bits_per_pixel) {
400
	case 16:
400
	case 16:
401
		depth = (var->green.length == 6) ? 16 : 15;
401
		depth = (var->green.length == 6) ? 16 : 15;
402
		break;
402
		break;
403
	case 32:
403
	case 32:
404
		depth = (var->transp.length > 0) ? 32 : 24;
404
		depth = (var->transp.length > 0) ? 32 : 24;
405
		break;
405
		break;
406
	default:
406
	default:
407
		depth = var->bits_per_pixel;
407
		depth = var->bits_per_pixel;
408
		break;
408
		break;
409
	}
409
	}
410
 
410
 
411
	switch (depth) {
411
	switch (depth) {
412
	case 8:
412
	case 8:
413
		var->red.offset = 0;
413
		var->red.offset = 0;
414
		var->green.offset = 0;
414
		var->green.offset = 0;
415
		var->blue.offset = 0;
415
		var->blue.offset = 0;
416
		var->red.length = 8;
416
		var->red.length = 8;
417
		var->green.length = 8;
417
		var->green.length = 8;
418
		var->blue.length = 8;
418
		var->blue.length = 8;
419
		var->transp.length = 0;
419
		var->transp.length = 0;
420
		var->transp.offset = 0;
420
		var->transp.offset = 0;
421
		break;
421
		break;
422
	case 15:
422
	case 15:
423
		var->red.offset = 10;
423
		var->red.offset = 10;
424
		var->green.offset = 5;
424
		var->green.offset = 5;
425
		var->blue.offset = 0;
425
		var->blue.offset = 0;
426
		var->red.length = 5;
426
		var->red.length = 5;
427
		var->green.length = 5;
427
		var->green.length = 5;
428
		var->blue.length = 5;
428
		var->blue.length = 5;
429
		var->transp.length = 1;
429
		var->transp.length = 1;
430
		var->transp.offset = 15;
430
		var->transp.offset = 15;
431
		break;
431
		break;
432
	case 16:
432
	case 16:
433
		var->red.offset = 11;
433
		var->red.offset = 11;
434
		var->green.offset = 5;
434
		var->green.offset = 5;
435
		var->blue.offset = 0;
435
		var->blue.offset = 0;
436
		var->red.length = 5;
436
		var->red.length = 5;
437
		var->green.length = 6;
437
		var->green.length = 6;
438
		var->blue.length = 5;
438
		var->blue.length = 5;
439
		var->transp.length = 0;
439
		var->transp.length = 0;
440
		var->transp.offset = 0;
440
		var->transp.offset = 0;
441
		break;
441
		break;
442
	case 24:
442
	case 24:
443
		var->red.offset = 16;
443
		var->red.offset = 16;
444
		var->green.offset = 8;
444
		var->green.offset = 8;
445
		var->blue.offset = 0;
445
		var->blue.offset = 0;
446
		var->red.length = 8;
446
		var->red.length = 8;
447
		var->green.length = 8;
447
		var->green.length = 8;
448
		var->blue.length = 8;
448
		var->blue.length = 8;
449
		var->transp.length = 0;
449
		var->transp.length = 0;
450
		var->transp.offset = 0;
450
		var->transp.offset = 0;
451
		break;
451
		break;
452
	case 32:
452
	case 32:
453
		var->red.offset = 16;
453
		var->red.offset = 16;
454
		var->green.offset = 8;
454
		var->green.offset = 8;
455
		var->blue.offset = 0;
455
		var->blue.offset = 0;
456
		var->red.length = 8;
456
		var->red.length = 8;
457
		var->green.length = 8;
457
		var->green.length = 8;
458
		var->blue.length = 8;
458
		var->blue.length = 8;
459
		var->transp.length = 8;
459
		var->transp.length = 8;
460
		var->transp.offset = 24;
460
		var->transp.offset = 24;
461
		break;
461
		break;
462
	default:
462
	default:
463
		return -EINVAL;
463
		return -EINVAL;
464
	}
464
	}
465
	return 0;
465
	return 0;
466
}
466
}
467
EXPORT_SYMBOL(drm_fb_helper_check_var);
467
EXPORT_SYMBOL(drm_fb_helper_check_var);
468
 
468
 
469
/* this will let fbcon do the mode init */
469
/* this will let fbcon do the mode init */
470
int drm_fb_helper_set_par(struct fb_info *info)
470
int drm_fb_helper_set_par(struct fb_info *info)
471
{
471
{
472
	struct drm_fb_helper *fb_helper = info->par;
472
	struct drm_fb_helper *fb_helper = info->par;
473
	struct drm_device *dev = fb_helper->dev;
473
	struct drm_device *dev = fb_helper->dev;
474
	struct fb_var_screeninfo *var = &info->var;
474
	struct fb_var_screeninfo *var = &info->var;
475
	struct drm_crtc *crtc;
475
	struct drm_crtc *crtc;
476
	int ret;
476
	int ret;
477
	int i;
477
	int i;
478
 
478
 
479
	if (var->pixclock != 0) {
479
	if (var->pixclock != 0) {
480
		DRM_ERROR("PIXEL CLOCK SET\n");
480
		DRM_ERROR("PIXEL CLOCK SET\n");
481
		return -EINVAL;
481
		return -EINVAL;
482
	}
482
	}
483
 
483
 
484
	mutex_lock(&dev->mode_config.mutex);
484
	mutex_lock(&dev->mode_config.mutex);
485
		for (i = 0; i < fb_helper->crtc_count; i++) {
485
		for (i = 0; i < fb_helper->crtc_count; i++) {
486
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
486
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
487
			ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
487
			ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
488
		if (ret) {
488
		if (ret) {
489
			mutex_unlock(&dev->mode_config.mutex);
489
			mutex_unlock(&dev->mode_config.mutex);
490
				return ret;
490
				return ret;
491
		}
491
		}
492
	}
492
	}
493
	mutex_unlock(&dev->mode_config.mutex);
493
	mutex_unlock(&dev->mode_config.mutex);
494
 
494
 
495
	if (fb_helper->delayed_hotplug) {
495
	if (fb_helper->delayed_hotplug) {
496
		fb_helper->delayed_hotplug = false;
496
		fb_helper->delayed_hotplug = false;
497
//       drm_fb_helper_hotplug_event(fb_helper);
497
//       drm_fb_helper_hotplug_event(fb_helper);
498
	}
498
	}
499
	return 0;
499
	return 0;
500
}
500
}
501
EXPORT_SYMBOL(drm_fb_helper_set_par);
501
EXPORT_SYMBOL(drm_fb_helper_set_par);
502
 
502
 
503
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
503
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
504
			      struct fb_info *info)
504
			      struct fb_info *info)
505
{
505
{
506
	struct drm_fb_helper *fb_helper = info->par;
506
	struct drm_fb_helper *fb_helper = info->par;
507
	struct drm_device *dev = fb_helper->dev;
507
	struct drm_device *dev = fb_helper->dev;
508
	struct drm_mode_set *modeset;
508
	struct drm_mode_set *modeset;
509
	struct drm_crtc *crtc;
509
	struct drm_crtc *crtc;
510
	int ret = 0;
510
	int ret = 0;
511
	int i;
511
	int i;
512
 
512
 
513
	mutex_lock(&dev->mode_config.mutex);
513
	mutex_lock(&dev->mode_config.mutex);
514
		for (i = 0; i < fb_helper->crtc_count; i++) {
514
		for (i = 0; i < fb_helper->crtc_count; i++) {
515
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
515
		crtc = fb_helper->crtc_info[i].mode_set.crtc;
516
 
516
 
517
		modeset = &fb_helper->crtc_info[i].mode_set;
517
		modeset = &fb_helper->crtc_info[i].mode_set;
518
 
518
 
519
		modeset->x = var->xoffset;
519
		modeset->x = var->xoffset;
520
		modeset->y = var->yoffset;
520
		modeset->y = var->yoffset;
521
 
521
 
522
		if (modeset->num_connectors) {
522
		if (modeset->num_connectors) {
523
			ret = crtc->funcs->set_config(modeset);
523
			ret = crtc->funcs->set_config(modeset);
524
			if (!ret) {
524
			if (!ret) {
525
				info->var.xoffset = var->xoffset;
525
				info->var.xoffset = var->xoffset;
526
				info->var.yoffset = var->yoffset;
526
				info->var.yoffset = var->yoffset;
527
			}
527
			}
528
		}
528
		}
529
	}
529
	}
530
	mutex_unlock(&dev->mode_config.mutex);
530
	mutex_unlock(&dev->mode_config.mutex);
531
	return ret;
531
	return ret;
532
}
532
}
533
EXPORT_SYMBOL(drm_fb_helper_pan_display);
533
EXPORT_SYMBOL(drm_fb_helper_pan_display);
534
 
534
 
535
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
535
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
536
				  int preferred_bpp)
536
				  int preferred_bpp)
537
{
537
{
538
	int new_fb = 0;
538
	int new_fb = 0;
539
	int crtc_count = 0;
539
	int crtc_count = 0;
540
	int i;
540
	int i;
541
	struct fb_info *info;
541
	struct fb_info *info;
542
	struct drm_fb_helper_surface_size sizes;
542
	struct drm_fb_helper_surface_size sizes;
543
	int gamma_size = 0;
543
	int gamma_size = 0;
544
 
544
 
545
	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
545
	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
546
	sizes.surface_depth = 24;
546
	sizes.surface_depth = 24;
547
	sizes.surface_bpp = 32;
547
	sizes.surface_bpp = 32;
548
	sizes.fb_width = (unsigned)-1;
548
	sizes.fb_width = (unsigned)-1;
549
	sizes.fb_height = (unsigned)-1;
549
	sizes.fb_height = (unsigned)-1;
550
 
550
 
551
    sizes.surface_depth = 24;
551
    sizes.surface_depth = 24;
552
    sizes.surface_bpp = 32;
552
    sizes.surface_bpp = 32;
553
 
553
 
554
	crtc_count = 0;
554
	crtc_count = 0;
555
	for (i = 0; i < fb_helper->crtc_count; i++) {
555
	for (i = 0; i < fb_helper->crtc_count; i++) {
556
		struct drm_display_mode *desired_mode;
556
		struct drm_display_mode *desired_mode;
557
		desired_mode = fb_helper->crtc_info[i].desired_mode;
557
		desired_mode = fb_helper->crtc_info[i].desired_mode;
558
 
558
 
559
		if (desired_mode) {
559
		if (desired_mode) {
560
			if (gamma_size == 0)
560
			if (gamma_size == 0)
561
				gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
561
				gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
562
			if (desired_mode->hdisplay < sizes.fb_width)
562
			if (desired_mode->hdisplay < sizes.fb_width)
563
				sizes.fb_width = desired_mode->hdisplay;
563
				sizes.fb_width = desired_mode->hdisplay;
564
			if (desired_mode->vdisplay < sizes.fb_height)
564
			if (desired_mode->vdisplay < sizes.fb_height)
565
				sizes.fb_height = desired_mode->vdisplay;
565
				sizes.fb_height = desired_mode->vdisplay;
566
			if (desired_mode->hdisplay > sizes.surface_width)
566
			if (desired_mode->hdisplay > sizes.surface_width)
567
				sizes.surface_width = desired_mode->hdisplay;
567
				sizes.surface_width = desired_mode->hdisplay;
568
			if (desired_mode->vdisplay > sizes.surface_height)
568
			if (desired_mode->vdisplay > sizes.surface_height)
569
				sizes.surface_height = desired_mode->vdisplay;
569
				sizes.surface_height = desired_mode->vdisplay;
570
			crtc_count++;
570
			crtc_count++;
571
		}
571
		}
572
	}
572
	}
573
 
573
 
574
	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
574
	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
575
		/* hmm everyone went away - assume VGA cable just fell out
575
		/* hmm everyone went away - assume VGA cable just fell out
576
		   and will come back later. */
576
		   and will come back later. */
577
		DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
577
		DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
578
		sizes.fb_width = sizes.surface_width = 1024;
578
		sizes.fb_width = sizes.surface_width = 1024;
579
		sizes.fb_height = sizes.surface_height = 768;
579
		sizes.fb_height = sizes.surface_height = 768;
580
	}
580
	}
581
 
581
 
582
	/* push down into drivers */
582
	/* push down into drivers */
583
 
583
 
584
    DRM_INFO("enter fb probe\n");
584
    DRM_INFO("enter fb probe\n");
585
 
585
 
586
 
586
 
587
    new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
587
    new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
588
	if (new_fb < 0)
588
	if (new_fb < 0)
589
		return new_fb;
589
		return new_fb;
590
 
590
 
591
	info = fb_helper->fbdev;
591
	info = fb_helper->fbdev;
592
 
-
 
593
#if 0
-
 
594
 
592
 
595
	/* set the fb pointer */
593
	/* set the fb pointer */
596
	for (i = 0; i < fb_helper->crtc_count; i++) {
594
	for (i = 0; i < fb_helper->crtc_count; i++) {
597
		fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
595
		fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
598
		}
596
		}
599
 
597
 
600
	if (new_fb) {
598
	if (new_fb) {
601
		info->var.pixclock = 0;
599
		info->var.pixclock = 0;
602
 
600
 
603
		printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
601
		printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
604
		       info->fix.id);
602
		       info->fix.id);
605
 
603
 
606
	} else {
604
	} else {
607
		drm_fb_helper_set_par(info);
605
		drm_fb_helper_set_par(info);
608
	}
606
	}
609
 
607
 
610
 
608
 
611
	if (new_fb)
609
	if (new_fb)
612
        list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
610
        list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
613
 
-
 
614
#endif
611
 
615
 
612
 
616
    LEAVE();
613
    LEAVE();
617
 
614
 
618
	return 0;
615
	return 0;
619
}
616
}
620
EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
617
EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
621
 
618
 
622
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
619
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
623
			    uint32_t depth)
620
			    uint32_t depth)
624
{
621
{
625
	info->fix.type = FB_TYPE_PACKED_PIXELS;
622
	info->fix.type = FB_TYPE_PACKED_PIXELS;
626
	info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
623
	info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
627
		FB_VISUAL_TRUECOLOR;
624
		FB_VISUAL_TRUECOLOR;
628
	info->fix.mmio_start = 0;
625
	info->fix.mmio_start = 0;
629
	info->fix.mmio_len = 0;
626
	info->fix.mmio_len = 0;
630
	info->fix.type_aux = 0;
627
	info->fix.type_aux = 0;
631
	info->fix.xpanstep = 1; /* doing it in hw */
628
	info->fix.xpanstep = 1; /* doing it in hw */
632
	info->fix.ypanstep = 1; /* doing it in hw */
629
	info->fix.ypanstep = 1; /* doing it in hw */
633
	info->fix.ywrapstep = 0;
630
	info->fix.ywrapstep = 0;
634
	info->fix.accel = FB_ACCEL_NONE;
631
	info->fix.accel = FB_ACCEL_NONE;
635
	info->fix.type_aux = 0;
632
	info->fix.type_aux = 0;
636
 
633
 
637
	info->fix.line_length = pitch;
634
	info->fix.line_length = pitch;
638
	return;
635
	return;
639
}
636
}
640
EXPORT_SYMBOL(drm_fb_helper_fill_fix);
637
EXPORT_SYMBOL(drm_fb_helper_fill_fix);
641
 
638
 
642
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
639
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
643
			    uint32_t fb_width, uint32_t fb_height)
640
			    uint32_t fb_width, uint32_t fb_height)
644
{
641
{
645
	struct drm_framebuffer *fb = fb_helper->fb;
642
	struct drm_framebuffer *fb = fb_helper->fb;
646
	info->pseudo_palette = fb_helper->pseudo_palette;
643
	info->pseudo_palette = fb_helper->pseudo_palette;
647
	info->var.xres_virtual = fb->width;
644
	info->var.xres_virtual = fb->width;
648
	info->var.yres_virtual = fb->height;
645
	info->var.yres_virtual = fb->height;
649
	info->var.bits_per_pixel = fb->bits_per_pixel;
646
	info->var.bits_per_pixel = fb->bits_per_pixel;
650
	info->var.accel_flags = FB_ACCELF_TEXT;
647
	info->var.accel_flags = FB_ACCELF_TEXT;
651
	info->var.xoffset = 0;
648
	info->var.xoffset = 0;
652
	info->var.yoffset = 0;
649
	info->var.yoffset = 0;
653
	info->var.activate = FB_ACTIVATE_NOW;
650
	info->var.activate = FB_ACTIVATE_NOW;
654
	info->var.height = -1;
651
	info->var.height = -1;
655
	info->var.width = -1;
652
	info->var.width = -1;
656
 
653
 
657
	switch (fb->depth) {
654
	switch (fb->depth) {
658
	case 8:
655
	case 8:
659
		info->var.red.offset = 0;
656
		info->var.red.offset = 0;
660
		info->var.green.offset = 0;
657
		info->var.green.offset = 0;
661
		info->var.blue.offset = 0;
658
		info->var.blue.offset = 0;
662
		info->var.red.length = 8; /* 8bit DAC */
659
		info->var.red.length = 8; /* 8bit DAC */
663
		info->var.green.length = 8;
660
		info->var.green.length = 8;
664
		info->var.blue.length = 8;
661
		info->var.blue.length = 8;
665
		info->var.transp.offset = 0;
662
		info->var.transp.offset = 0;
666
		info->var.transp.length = 0;
663
		info->var.transp.length = 0;
667
		break;
664
		break;
668
	case 15:
665
	case 15:
669
		info->var.red.offset = 10;
666
		info->var.red.offset = 10;
670
		info->var.green.offset = 5;
667
		info->var.green.offset = 5;
671
		info->var.blue.offset = 0;
668
		info->var.blue.offset = 0;
672
		info->var.red.length = 5;
669
		info->var.red.length = 5;
673
		info->var.green.length = 5;
670
		info->var.green.length = 5;
674
		info->var.blue.length = 5;
671
		info->var.blue.length = 5;
675
		info->var.transp.offset = 15;
672
		info->var.transp.offset = 15;
676
		info->var.transp.length = 1;
673
		info->var.transp.length = 1;
677
		break;
674
		break;
678
	case 16:
675
	case 16:
679
		info->var.red.offset = 11;
676
		info->var.red.offset = 11;
680
		info->var.green.offset = 5;
677
		info->var.green.offset = 5;
681
		info->var.blue.offset = 0;
678
		info->var.blue.offset = 0;
682
		info->var.red.length = 5;
679
		info->var.red.length = 5;
683
		info->var.green.length = 6;
680
		info->var.green.length = 6;
684
		info->var.blue.length = 5;
681
		info->var.blue.length = 5;
685
		info->var.transp.offset = 0;
682
		info->var.transp.offset = 0;
686
		break;
683
		break;
687
	case 24:
684
	case 24:
688
		info->var.red.offset = 16;
685
		info->var.red.offset = 16;
689
		info->var.green.offset = 8;
686
		info->var.green.offset = 8;
690
		info->var.blue.offset = 0;
687
		info->var.blue.offset = 0;
691
		info->var.red.length = 8;
688
		info->var.red.length = 8;
692
		info->var.green.length = 8;
689
		info->var.green.length = 8;
693
		info->var.blue.length = 8;
690
		info->var.blue.length = 8;
694
		info->var.transp.offset = 0;
691
		info->var.transp.offset = 0;
695
		info->var.transp.length = 0;
692
		info->var.transp.length = 0;
696
		break;
693
		break;
697
	case 32:
694
	case 32:
698
		info->var.red.offset = 16;
695
		info->var.red.offset = 16;
699
		info->var.green.offset = 8;
696
		info->var.green.offset = 8;
700
		info->var.blue.offset = 0;
697
		info->var.blue.offset = 0;
701
		info->var.red.length = 8;
698
		info->var.red.length = 8;
702
		info->var.green.length = 8;
699
		info->var.green.length = 8;
703
		info->var.blue.length = 8;
700
		info->var.blue.length = 8;
704
		info->var.transp.offset = 24;
701
		info->var.transp.offset = 24;
705
		info->var.transp.length = 8;
702
		info->var.transp.length = 8;
706
		break;
703
		break;
707
	default:
704
	default:
708
		break;
705
		break;
709
	}
706
	}
710
 
707
 
711
	info->var.xres = fb_width;
708
	info->var.xres = fb_width;
712
	info->var.yres = fb_height;
709
	info->var.yres = fb_height;
713
}
710
}
714
EXPORT_SYMBOL(drm_fb_helper_fill_var);
711
EXPORT_SYMBOL(drm_fb_helper_fill_var);
715
 
712
 
716
static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
713
static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
717
					       uint32_t maxX,
714
					       uint32_t maxX,
718
					       uint32_t maxY)
715
					       uint32_t maxY)
719
{
716
{
720
	struct drm_connector *connector;
717
	struct drm_connector *connector;
721
	int count = 0;
718
	int count = 0;
722
	int i;
719
	int i;
723
 
720
 
724
	for (i = 0; i < fb_helper->connector_count; i++) {
721
	for (i = 0; i < fb_helper->connector_count; i++) {
725
		connector = fb_helper->connector_info[i]->connector;
722
		connector = fb_helper->connector_info[i]->connector;
726
		count += connector->funcs->fill_modes(connector, maxX, maxY);
723
		count += connector->funcs->fill_modes(connector, maxX, maxY);
727
	}
724
	}
728
 
725
 
729
	return count;
726
	return count;
730
}
727
}
731
 
728
 
732
static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
729
static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
733
{
730
{
734
	struct drm_display_mode *mode;
731
	struct drm_display_mode *mode;
735
 
732
 
736
	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
733
	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
737
		if (drm_mode_width(mode) > width ||
734
		if (drm_mode_width(mode) > width ||
738
		    drm_mode_height(mode) > height)
735
		    drm_mode_height(mode) > height)
739
			continue;
736
			continue;
740
		if (mode->type & DRM_MODE_TYPE_PREFERRED)
737
		if (mode->type & DRM_MODE_TYPE_PREFERRED)
741
			return mode;
738
			return mode;
742
	}
739
	}
743
	return NULL;
740
	return NULL;
744
}
741
}
745
 
742
 
746
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
743
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
747
{
744
{
748
	struct drm_cmdline_mode *cmdline_mode;
745
	struct drm_cmdline_mode *cmdline_mode;
749
	cmdline_mode = &fb_connector->cmdline_mode;
746
	cmdline_mode = &fb_connector->cmdline_mode;
750
	return cmdline_mode->specified;
747
	return cmdline_mode->specified;
751
}
748
}
752
 
749
 
753
 
750
 
754
static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
751
static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
755
{
752
{
756
	bool enable;
753
	bool enable;
757
 
754
 
758
	if (strict) {
755
	if (strict) {
759
		enable = connector->status == connector_status_connected;
756
		enable = connector->status == connector_status_connected;
760
	} else {
757
	} else {
761
		enable = connector->status != connector_status_disconnected;
758
		enable = connector->status != connector_status_disconnected;
762
	}
759
	}
763
	return enable;
760
	return enable;
764
}
761
}
765
 
762
 
766
static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
763
static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
767
				  bool *enabled)
764
				  bool *enabled)
768
{
765
{
769
	bool any_enabled = false;
766
	bool any_enabled = false;
770
	struct drm_connector *connector;
767
	struct drm_connector *connector;
771
	int i = 0;
768
	int i = 0;
772
 
769
 
773
	for (i = 0; i < fb_helper->connector_count; i++) {
770
	for (i = 0; i < fb_helper->connector_count; i++) {
774
		connector = fb_helper->connector_info[i]->connector;
771
		connector = fb_helper->connector_info[i]->connector;
775
		enabled[i] = drm_connector_enabled(connector, true);
772
		enabled[i] = drm_connector_enabled(connector, true);
776
		DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
773
		DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
777
			  enabled[i] ? "yes" : "no");
774
			  enabled[i] ? "yes" : "no");
778
		any_enabled |= enabled[i];
775
		any_enabled |= enabled[i];
779
	}
776
	}
780
 
777
 
781
	if (any_enabled)
778
	if (any_enabled)
782
		return;
779
		return;
783
 
780
 
784
	for (i = 0; i < fb_helper->connector_count; i++) {
781
	for (i = 0; i < fb_helper->connector_count; i++) {
785
		connector = fb_helper->connector_info[i]->connector;
782
		connector = fb_helper->connector_info[i]->connector;
786
		enabled[i] = drm_connector_enabled(connector, false);
783
		enabled[i] = drm_connector_enabled(connector, false);
787
	}
784
	}
788
}
785
}
789
 
786
 
790
 
787
 
791
static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
788
static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
792
				 struct drm_display_mode **modes,
789
				 struct drm_display_mode **modes,
793
				 bool *enabled, int width, int height)
790
				 bool *enabled, int width, int height)
794
{
791
{
795
	struct drm_fb_helper_connector *fb_helper_conn;
792
	struct drm_fb_helper_connector *fb_helper_conn;
796
	int i;
793
	int i;
797
 
794
 
798
	for (i = 0; i < fb_helper->connector_count; i++) {
795
	for (i = 0; i < fb_helper->connector_count; i++) {
799
		fb_helper_conn = fb_helper->connector_info[i];
796
		fb_helper_conn = fb_helper->connector_info[i];
800
 
797
 
801
		if (enabled[i] == false)
798
		if (enabled[i] == false)
802
			continue;
799
			continue;
803
 
800
 
804
		DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
801
		DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
805
			      fb_helper_conn->connector->base.id);
802
			      fb_helper_conn->connector->base.id);
806
 
803
 
807
		/* got for command line mode first */
804
		/* got for command line mode first */
808
//       modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
805
//       modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
809
 
806
 
810
        modes[i] = NULL;
807
        modes[i] = NULL;
811
 
808
 
812
		if (!modes[i]) {
809
		if (!modes[i]) {
813
			DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
810
			DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
814
				      fb_helper_conn->connector->base.id);
811
				      fb_helper_conn->connector->base.id);
815
			modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
812
			modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
816
		}
813
		}
817
		/* No preferred modes, pick one off the list */
814
		/* No preferred modes, pick one off the list */
818
		if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
815
		if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
819
			list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
816
			list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
820
				break;
817
				break;
821
		}
818
		}
822
		DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
819
		DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
823
			  "none");
820
			  "none");
824
	}
821
	}
825
	return true;
822
	return true;
826
}
823
}
827
 
824
 
828
static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
825
static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
829
			  struct drm_fb_helper_crtc **best_crtcs,
826
			  struct drm_fb_helper_crtc **best_crtcs,
830
			  struct drm_display_mode **modes,
827
			  struct drm_display_mode **modes,
831
			  int n, int width, int height)
828
			  int n, int width, int height)
832
{
829
{
833
	int c, o;
830
	int c, o;
834
	struct drm_device *dev = fb_helper->dev;
831
	struct drm_device *dev = fb_helper->dev;
835
	struct drm_connector *connector;
832
	struct drm_connector *connector;
836
	struct drm_connector_helper_funcs *connector_funcs;
833
	struct drm_connector_helper_funcs *connector_funcs;
837
	struct drm_encoder *encoder;
834
	struct drm_encoder *encoder;
838
	struct drm_fb_helper_crtc *best_crtc;
835
	struct drm_fb_helper_crtc *best_crtc;
839
	int my_score, best_score, score;
836
	int my_score, best_score, score;
840
	struct drm_fb_helper_crtc **crtcs, *crtc;
837
	struct drm_fb_helper_crtc **crtcs, *crtc;
841
	struct drm_fb_helper_connector *fb_helper_conn;
838
	struct drm_fb_helper_connector *fb_helper_conn;
842
 
839
 
843
	if (n == fb_helper->connector_count)
840
	if (n == fb_helper->connector_count)
844
		return 0;
841
		return 0;
845
 
842
 
846
	fb_helper_conn = fb_helper->connector_info[n];
843
	fb_helper_conn = fb_helper->connector_info[n];
847
	connector = fb_helper_conn->connector;
844
	connector = fb_helper_conn->connector;
848
 
845
 
849
	best_crtcs[n] = NULL;
846
	best_crtcs[n] = NULL;
850
	best_crtc = NULL;
847
	best_crtc = NULL;
851
	best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
848
	best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
852
	if (modes[n] == NULL)
849
	if (modes[n] == NULL)
853
		return best_score;
850
		return best_score;
854
 
851
 
855
	crtcs = kzalloc(dev->mode_config.num_connector *
852
	crtcs = kzalloc(dev->mode_config.num_connector *
856
			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
853
			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
857
	if (!crtcs)
854
	if (!crtcs)
858
		return best_score;
855
		return best_score;
859
 
856
 
860
	my_score = 1;
857
	my_score = 1;
861
	if (connector->status == connector_status_connected)
858
	if (connector->status == connector_status_connected)
862
		my_score++;
859
		my_score++;
863
	if (drm_has_cmdline_mode(fb_helper_conn))
860
	if (drm_has_cmdline_mode(fb_helper_conn))
864
		my_score++;
861
		my_score++;
865
	if (drm_has_preferred_mode(fb_helper_conn, width, height))
862
	if (drm_has_preferred_mode(fb_helper_conn, width, height))
866
		my_score++;
863
		my_score++;
867
 
864
 
868
	connector_funcs = connector->helper_private;
865
	connector_funcs = connector->helper_private;
869
	encoder = connector_funcs->best_encoder(connector);
866
	encoder = connector_funcs->best_encoder(connector);
870
	if (!encoder)
867
	if (!encoder)
871
		goto out;
868
		goto out;
872
 
869
 
873
	/* select a crtc for this connector and then attempt to configure
870
	/* select a crtc for this connector and then attempt to configure
874
	   remaining connectors */
871
	   remaining connectors */
875
	for (c = 0; c < fb_helper->crtc_count; c++) {
872
	for (c = 0; c < fb_helper->crtc_count; c++) {
876
		crtc = &fb_helper->crtc_info[c];
873
		crtc = &fb_helper->crtc_info[c];
877
 
874
 
878
		if ((encoder->possible_crtcs & (1 << c)) == 0) {
875
		if ((encoder->possible_crtcs & (1 << c)) == 0) {
879
			continue;
876
			continue;
880
		}
877
		}
881
 
878
 
882
		for (o = 0; o < n; o++)
879
		for (o = 0; o < n; o++)
883
			if (best_crtcs[o] == crtc)
880
			if (best_crtcs[o] == crtc)
884
				break;
881
				break;
885
 
882
 
886
		if (o < n) {
883
		if (o < n) {
887
			/* ignore cloning unless only a single crtc */
884
			/* ignore cloning unless only a single crtc */
888
			if (fb_helper->crtc_count > 1)
885
			if (fb_helper->crtc_count > 1)
889
				continue;
886
				continue;
890
 
887
 
891
			if (!drm_mode_equal(modes[o], modes[n]))
888
			if (!drm_mode_equal(modes[o], modes[n]))
892
				continue;
889
				continue;
893
		}
890
		}
894
 
891
 
895
		crtcs[n] = crtc;
892
		crtcs[n] = crtc;
896
		memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
893
		memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
897
		score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
894
		score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
898
						  width, height);
895
						  width, height);
899
		if (score > best_score) {
896
		if (score > best_score) {
900
			best_crtc = crtc;
897
			best_crtc = crtc;
901
			best_score = score;
898
			best_score = score;
902
			memcpy(best_crtcs, crtcs,
899
			memcpy(best_crtcs, crtcs,
903
			       dev->mode_config.num_connector *
900
			       dev->mode_config.num_connector *
904
			       sizeof(struct drm_fb_helper_crtc *));
901
			       sizeof(struct drm_fb_helper_crtc *));
905
		}
902
		}
906
	}
903
	}
907
out:
904
out:
908
	kfree(crtcs);
905
	kfree(crtcs);
909
	return best_score;
906
	return best_score;
910
}
907
}
911
 
908
 
912
static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
909
static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
913
{
910
{
914
	struct drm_device *dev = fb_helper->dev;
911
	struct drm_device *dev = fb_helper->dev;
915
	struct drm_fb_helper_crtc **crtcs;
912
	struct drm_fb_helper_crtc **crtcs;
916
	struct drm_display_mode **modes;
913
	struct drm_display_mode **modes;
917
	struct drm_encoder *encoder;
914
	struct drm_encoder *encoder;
918
	struct drm_mode_set *modeset;
915
	struct drm_mode_set *modeset;
919
	bool *enabled;
916
	bool *enabled;
920
	int width, height;
917
	int width, height;
921
	int i, ret;
918
	int i, ret;
922
 
919
 
923
	DRM_DEBUG_KMS("\n");
920
	DRM_DEBUG_KMS("\n");
924
 
921
 
925
	width = dev->mode_config.max_width;
922
	width = dev->mode_config.max_width;
926
	height = dev->mode_config.max_height;
923
	height = dev->mode_config.max_height;
927
 
924
 
928
	/* clean out all the encoder/crtc combos */
925
	/* clean out all the encoder/crtc combos */
929
//   list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
926
   list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
930
//       encoder->crtc = NULL;
927
//       encoder->crtc = NULL;
931
//   }
928
   }
932
 
929
 
933
	crtcs = kcalloc(dev->mode_config.num_connector,
930
	crtcs = kcalloc(dev->mode_config.num_connector,
934
			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
931
			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
935
	modes = kcalloc(dev->mode_config.num_connector,
932
	modes = kcalloc(dev->mode_config.num_connector,
936
			sizeof(struct drm_display_mode *), GFP_KERNEL);
933
			sizeof(struct drm_display_mode *), GFP_KERNEL);
937
	enabled = kcalloc(dev->mode_config.num_connector,
934
	enabled = kcalloc(dev->mode_config.num_connector,
938
			  sizeof(bool), GFP_KERNEL);
935
			  sizeof(bool), GFP_KERNEL);
939
 
936
 
940
	drm_enable_connectors(fb_helper, enabled);
937
	drm_enable_connectors(fb_helper, enabled);
941
 
938
 
942
    //ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
939
    //ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
943
 
940
 
944
    ret = 0;
941
    ret = 0;
945
 
942
 
946
	if (!ret) {
943
	if (!ret) {
947
		ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
944
		ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
948
		if (!ret)
945
		if (!ret)
949
			DRM_ERROR("Unable to find initial modes\n");
946
			DRM_ERROR("Unable to find initial modes\n");
950
	}
947
	}
951
 
948
 
952
	DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
949
	DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
953
 
950
 
954
	drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
951
	drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
955
 
952
 
956
	/* need to set the modesets up here for use later */
953
	/* need to set the modesets up here for use later */
957
	/* fill out the connector<->crtc mappings into the modesets */
954
	/* fill out the connector<->crtc mappings into the modesets */
958
	for (i = 0; i < fb_helper->crtc_count; i++) {
955
	for (i = 0; i < fb_helper->crtc_count; i++) {
959
		modeset = &fb_helper->crtc_info[i].mode_set;
956
		modeset = &fb_helper->crtc_info[i].mode_set;
960
		modeset->num_connectors = 0;
957
		modeset->num_connectors = 0;
961
	}
958
	}
962
 
959
 
963
	for (i = 0; i < fb_helper->connector_count; i++) {
960
	for (i = 0; i < fb_helper->connector_count; i++) {
964
		struct drm_display_mode *mode = modes[i];
961
		struct drm_display_mode *mode = modes[i];
965
		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
962
		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
966
		modeset = &fb_crtc->mode_set;
963
		modeset = &fb_crtc->mode_set;
967
 
964
 
968
		if (mode && fb_crtc) {
965
		if (mode && fb_crtc) {
969
			DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
966
			DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
970
				      mode->name, fb_crtc->mode_set.crtc->base.id);
967
				      mode->name, fb_crtc->mode_set.crtc->base.id);
971
			fb_crtc->desired_mode = mode;
968
			fb_crtc->desired_mode = mode;
972
			if (modeset->mode)
969
			if (modeset->mode)
973
				drm_mode_destroy(dev, modeset->mode);
970
				drm_mode_destroy(dev, modeset->mode);
974
			modeset->mode = drm_mode_duplicate(dev,
971
			modeset->mode = drm_mode_duplicate(dev,
975
							   fb_crtc->desired_mode);
972
							   fb_crtc->desired_mode);
976
			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
973
			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
977
		}
974
		}
978
	}
975
	}
979
 
976
 
980
	kfree(crtcs);
977
	kfree(crtcs);
981
	kfree(modes);
978
	kfree(modes);
982
	kfree(enabled);
979
	kfree(enabled);
983
}
980
}
984
 
981
 
985
/**
982
/**
986
 * drm_helper_initial_config - setup a sane initial connector configuration
983
 * drm_helper_initial_config - setup a sane initial connector configuration
987
 * @dev: DRM device
984
 * @dev: DRM device
988
 *
985
 *
989
 * LOCKING:
986
 * LOCKING:
990
 * Called at init time, must take mode config lock.
987
 * Called at init time, must take mode config lock.
991
 *
988
 *
992
 * Scan the CRTCs and connectors and try to put together an initial setup.
989
 * 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
990
 * At the moment, this is a cloned configuration across all heads with
994
 * a new framebuffer object as the backing store.
991
 * a new framebuffer object as the backing store.
995
 *
992
 *
996
 * RETURNS:
993
 * RETURNS:
997
 * Zero if everything went ok, nonzero otherwise.
994
 * Zero if everything went ok, nonzero otherwise.
998
 */
995
 */
999
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
996
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1000
{
997
{
1001
	struct drm_device *dev = fb_helper->dev;
998
	struct drm_device *dev = fb_helper->dev;
1002
	int count = 0;
999
	int count = 0;
1003
 
1000
 
1004
	/* disable all the possible outputs/crtcs before entering KMS mode */
1001
	/* disable all the possible outputs/crtcs before entering KMS mode */
1005
//   drm_helper_disable_unused_functions(fb_helper->dev);
1002
//   drm_helper_disable_unused_functions(fb_helper->dev);
1006
 
1003
 
1007
//   drm_fb_helper_parse_command_line(fb_helper);
1004
//   drm_fb_helper_parse_command_line(fb_helper);
1008
 
1005
 
1009
	count = drm_fb_helper_probe_connector_modes(fb_helper,
1006
	count = drm_fb_helper_probe_connector_modes(fb_helper,
1010
						    dev->mode_config.max_width,
1007
						    dev->mode_config.max_width,
1011
						    dev->mode_config.max_height);
1008
						    dev->mode_config.max_height);
1012
	/*
1009
	/*
1013
	 * we shouldn't end up with no modes here.
1010
	 * we shouldn't end up with no modes here.
1014
	 */
1011
	 */
1015
	if (count == 0) {
1012
	if (count == 0) {
1016
		printk(KERN_INFO "No connectors reported connected with modes\n");
1013
		printk(KERN_INFO "No connectors reported connected with modes\n");
1017
	}
1014
	}
1018
	drm_setup_crtcs(fb_helper);
1015
	drm_setup_crtcs(fb_helper);
1019
 
-
 
1020
 
-
 
1021
 
1016
 
1022
	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1017
	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1023
}
1018
}
1024
EXPORT_SYMBOL(drm_fb_helper_initial_config);
1019
EXPORT_SYMBOL(drm_fb_helper_initial_config);