Subversion Repositories Kolibri OS

Rev

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

Rev 3031 Rev 3192
1
/*
1
/*
2
 * Copyright (c) 2006-2008 Intel Corporation
2
 * Copyright (c) 2006-2008 Intel Corporation
3
 * Copyright (c) 2007 Dave Airlie 
3
 * Copyright (c) 2007 Dave Airlie 
4
 * Copyright (c) 2008 Red Hat Inc.
4
 * Copyright (c) 2008 Red Hat Inc.
5
 *
5
 *
6
 * DRM core CRTC related functions
6
 * DRM core CRTC related 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
 *      Keith Packard
27
 *      Keith Packard
28
 *	Eric Anholt 
28
 *	Eric Anholt 
29
 *      Dave Airlie 
29
 *      Dave Airlie 
30
 *      Jesse Barnes 
30
 *      Jesse Barnes 
31
 */
31
 */
32
#include 
32
#include 
33
#include 
33
#include 
34
#include 
34
#include 
35
#include 
35
#include 
36
#include 
36
#include 
37
#include 
37
#include 
38
#include 
38
#include 
39
 
39
 
40
/* Avoid boilerplate.  I'm tired of typing. */
40
/* Avoid boilerplate.  I'm tired of typing. */
41
#define DRM_ENUM_NAME_FN(fnname, list)				\
41
#define DRM_ENUM_NAME_FN(fnname, list)				\
42
	char *fnname(int val)					\
42
	char *fnname(int val)					\
43
	{							\
43
	{							\
44
		int i;						\
44
		int i;						\
45
		for (i = 0; i < ARRAY_SIZE(list); i++) {	\
45
		for (i = 0; i < ARRAY_SIZE(list); i++) {	\
46
			if (list[i].type == val)		\
46
			if (list[i].type == val)		\
47
				return list[i].name;		\
47
				return list[i].name;		\
48
		}						\
48
		}						\
49
		return "(unknown)";				\
49
		return "(unknown)";				\
50
	}
50
	}
51
 
51
 
52
/*
52
/*
53
 * Global properties
53
 * Global properties
54
 */
54
 */
55
static struct drm_prop_enum_list drm_dpms_enum_list[] =
55
static struct drm_prop_enum_list drm_dpms_enum_list[] =
56
{	{ DRM_MODE_DPMS_ON, "On" },
56
{	{ DRM_MODE_DPMS_ON, "On" },
57
	{ DRM_MODE_DPMS_STANDBY, "Standby" },
57
	{ DRM_MODE_DPMS_STANDBY, "Standby" },
58
	{ DRM_MODE_DPMS_SUSPEND, "Suspend" },
58
	{ DRM_MODE_DPMS_SUSPEND, "Suspend" },
59
	{ DRM_MODE_DPMS_OFF, "Off" }
59
	{ DRM_MODE_DPMS_OFF, "Off" }
60
};
60
};
61
 
61
 
62
DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
62
DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
63
 
63
 
64
/*
64
/*
65
 * Optional properties
65
 * Optional properties
66
 */
66
 */
67
static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
67
static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
68
{
68
{
69
	{ DRM_MODE_SCALE_NONE, "None" },
69
	{ DRM_MODE_SCALE_NONE, "None" },
70
	{ DRM_MODE_SCALE_FULLSCREEN, "Full" },
70
	{ DRM_MODE_SCALE_FULLSCREEN, "Full" },
71
	{ DRM_MODE_SCALE_CENTER, "Center" },
71
	{ DRM_MODE_SCALE_CENTER, "Center" },
72
	{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
72
	{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
73
};
73
};
74
 
74
 
75
static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
75
static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
76
{
76
{
77
	{ DRM_MODE_DITHERING_OFF, "Off" },
77
	{ DRM_MODE_DITHERING_OFF, "Off" },
78
	{ DRM_MODE_DITHERING_ON, "On" },
78
	{ DRM_MODE_DITHERING_ON, "On" },
79
	{ DRM_MODE_DITHERING_AUTO, "Automatic" },
79
	{ DRM_MODE_DITHERING_AUTO, "Automatic" },
80
};
80
};
81
 
81
 
82
/*
82
/*
83
 * Non-global properties, but "required" for certain connectors.
83
 * Non-global properties, but "required" for certain connectors.
84
 */
84
 */
85
static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
85
static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
86
{
86
{
87
	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
87
	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
88
	{ DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
88
	{ DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
89
	{ DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
89
	{ DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
90
};
90
};
91
 
91
 
92
DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
92
DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
93
 
93
 
94
static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
94
static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
95
{
95
{
96
	{ DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
96
	{ DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
97
	{ DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
97
	{ DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
98
	{ DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
98
	{ DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
99
};
99
};
100
 
100
 
101
DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
101
DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
102
		 drm_dvi_i_subconnector_enum_list)
102
		 drm_dvi_i_subconnector_enum_list)
103
 
103
 
104
static struct drm_prop_enum_list drm_tv_select_enum_list[] =
104
static struct drm_prop_enum_list drm_tv_select_enum_list[] =
105
{
105
{
106
	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
106
	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
107
	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
107
	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
108
	{ DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
108
	{ DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
109
	{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
109
	{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
110
	{ DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
110
	{ DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
111
};
111
};
112
 
112
 
113
DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
113
DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
114
 
114
 
115
static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
115
static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
116
{
116
{
117
	{ DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
117
	{ DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
118
	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
118
	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
119
	{ DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
119
	{ DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
120
	{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
120
	{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
121
	{ DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
121
	{ DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
122
};
122
};
123
 
123
 
124
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
124
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
125
		 drm_tv_subconnector_enum_list)
125
		 drm_tv_subconnector_enum_list)
126
 
126
 
127
static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
127
static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
128
	{ DRM_MODE_DIRTY_OFF,      "Off"      },
128
	{ DRM_MODE_DIRTY_OFF,      "Off"      },
129
	{ DRM_MODE_DIRTY_ON,       "On"       },
129
	{ DRM_MODE_DIRTY_ON,       "On"       },
130
	{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
130
	{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
131
};
131
};
132
 
132
 
133
DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
133
DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
134
		 drm_dirty_info_enum_list)
134
		 drm_dirty_info_enum_list)
135
 
135
 
136
struct drm_conn_prop_enum_list {
136
struct drm_conn_prop_enum_list {
137
	int type;
137
	int type;
138
	char *name;
138
	char *name;
139
	int count;
139
	int count;
140
};
140
};
141
 
141
 
142
/*
142
/*
143
 * Connector and encoder types.
143
 * Connector and encoder types.
144
 */
144
 */
145
static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
145
static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
146
{	{ DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
146
{	{ DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
147
	{ DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
147
	{ DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
148
	{ DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
148
	{ DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
149
	{ DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
149
	{ DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
150
	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
150
	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
151
	{ DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
151
	{ DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
152
	{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
152
	{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
153
	{ DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
153
	{ DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
154
	{ DRM_MODE_CONNECTOR_Component, "Component", 0 },
154
	{ DRM_MODE_CONNECTOR_Component, "Component", 0 },
155
	{ DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
155
	{ DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
156
	{ DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
156
	{ DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
157
	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
157
	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
158
	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
158
	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
159
	{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
159
	{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
160
	{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
160
	{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
161
	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
161
	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
162
};
162
};
163
 
163
 
164
static struct drm_prop_enum_list drm_encoder_enum_list[] =
164
static struct drm_prop_enum_list drm_encoder_enum_list[] =
165
{	{ DRM_MODE_ENCODER_NONE, "None" },
165
{	{ DRM_MODE_ENCODER_NONE, "None" },
166
	{ DRM_MODE_ENCODER_DAC, "DAC" },
166
	{ DRM_MODE_ENCODER_DAC, "DAC" },
167
	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
167
	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
168
	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
168
	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
169
	{ DRM_MODE_ENCODER_TVDAC, "TV" },
169
	{ DRM_MODE_ENCODER_TVDAC, "TV" },
170
	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
170
	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
171
};
171
};
172
 
172
 
173
char *drm_get_encoder_name(struct drm_encoder *encoder)
173
char *drm_get_encoder_name(struct drm_encoder *encoder)
174
{
174
{
175
	static char buf[32];
175
	static char buf[32];
176
 
176
 
177
	snprintf(buf, 32, "%s-%d",
177
	snprintf(buf, 32, "%s-%d",
178
		 drm_encoder_enum_list[encoder->encoder_type].name,
178
		 drm_encoder_enum_list[encoder->encoder_type].name,
179
		 encoder->base.id);
179
		 encoder->base.id);
180
	return buf;
180
	return buf;
181
}
181
}
182
EXPORT_SYMBOL(drm_get_encoder_name);
182
EXPORT_SYMBOL(drm_get_encoder_name);
183
 
183
 
184
char *drm_get_connector_name(struct drm_connector *connector)
184
char *drm_get_connector_name(struct drm_connector *connector)
185
{
185
{
186
	static char buf[32];
186
	static char buf[32];
187
 
187
 
188
	snprintf(buf, 32, "%s-%d",
188
	snprintf(buf, 32, "%s-%d",
189
		 drm_connector_enum_list[connector->connector_type].name,
189
		 drm_connector_enum_list[connector->connector_type].name,
190
		 connector->connector_type_id);
190
		 connector->connector_type_id);
191
	return buf;
191
	return buf;
192
}
192
}
193
EXPORT_SYMBOL(drm_get_connector_name);
193
EXPORT_SYMBOL(drm_get_connector_name);
194
 
194
 
195
char *drm_get_connector_status_name(enum drm_connector_status status)
195
char *drm_get_connector_status_name(enum drm_connector_status status)
196
{
196
{
197
	if (status == connector_status_connected)
197
	if (status == connector_status_connected)
198
		return "connected";
198
		return "connected";
199
	else if (status == connector_status_disconnected)
199
	else if (status == connector_status_disconnected)
200
		return "disconnected";
200
		return "disconnected";
201
	else
201
	else
202
		return "unknown";
202
		return "unknown";
203
}
203
}
204
 
204
 
205
/**
205
/**
206
 * drm_mode_object_get - allocate a new identifier
206
 * drm_mode_object_get - allocate a new identifier
207
 * @dev: DRM device
207
 * @dev: DRM device
208
 * @ptr: object pointer, used to generate unique ID
208
 * @ptr: object pointer, used to generate unique ID
209
 * @type: object type
209
 * @type: object type
210
 *
210
 *
211
 * LOCKING:
211
 * LOCKING:
212
 *
212
 *
213
 * Create a unique identifier based on @ptr in @dev's identifier space.  Used
213
 * Create a unique identifier based on @ptr in @dev's identifier space.  Used
214
 * for tracking modes, CRTCs and connectors.
214
 * for tracking modes, CRTCs and connectors.
215
 *
215
 *
216
 * RETURNS:
216
 * RETURNS:
217
 * New unique (relative to other objects in @dev) integer identifier for the
217
 * New unique (relative to other objects in @dev) integer identifier for the
218
 * object.
218
 * object.
219
 */
219
 */
220
static int drm_mode_object_get(struct drm_device *dev,
220
static int drm_mode_object_get(struct drm_device *dev,
221
			       struct drm_mode_object *obj, uint32_t obj_type)
221
			       struct drm_mode_object *obj, uint32_t obj_type)
222
{
222
{
223
	int new_id = 0;
223
	int new_id = 0;
224
	int ret;
224
	int ret;
225
 
225
 
226
again:
226
again:
227
	if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
227
	if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
228
		DRM_ERROR("Ran out memory getting a mode number\n");
228
		DRM_ERROR("Ran out memory getting a mode number\n");
229
		return -ENOMEM;
229
		return -ENOMEM;
230
	}
230
	}
231
 
231
 
232
	mutex_lock(&dev->mode_config.idr_mutex);
232
	mutex_lock(&dev->mode_config.idr_mutex);
233
	ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
233
	ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
234
	mutex_unlock(&dev->mode_config.idr_mutex);
234
	mutex_unlock(&dev->mode_config.idr_mutex);
235
	if (ret == -EAGAIN)
235
	if (ret == -EAGAIN)
236
        goto again;
236
        goto again;
237
	else if (ret)
237
	else if (ret)
238
		return ret;
238
		return ret;
239
 
239
 
240
	obj->id = new_id;
240
	obj->id = new_id;
241
	obj->type = obj_type;
241
	obj->type = obj_type;
242
    return 0;
242
    return 0;
243
}
243
}
244
 
244
 
245
/**
245
/**
246
 * drm_mode_object_put - free an identifer
246
 * drm_mode_object_put - free an identifer
247
 * @dev: DRM device
247
 * @dev: DRM device
248
 * @id: ID to free
248
 * @id: ID to free
249
 *
249
 *
250
 * LOCKING:
250
 * LOCKING:
251
 * Caller must hold DRM mode_config lock.
251
 * Caller must hold DRM mode_config lock.
252
 *
252
 *
253
 * Free @id from @dev's unique identifier pool.
253
 * Free @id from @dev's unique identifier pool.
254
 */
254
 */
255
static void drm_mode_object_put(struct drm_device *dev,
255
static void drm_mode_object_put(struct drm_device *dev,
256
				struct drm_mode_object *object)
256
				struct drm_mode_object *object)
257
{
257
{
258
	mutex_lock(&dev->mode_config.idr_mutex);
258
	mutex_lock(&dev->mode_config.idr_mutex);
259
	idr_remove(&dev->mode_config.crtc_idr, object->id);
259
	idr_remove(&dev->mode_config.crtc_idr, object->id);
260
	mutex_unlock(&dev->mode_config.idr_mutex);
260
	mutex_unlock(&dev->mode_config.idr_mutex);
261
}
261
}
262
 
262
 
263
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
263
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
264
		uint32_t id, uint32_t type)
264
		uint32_t id, uint32_t type)
265
{
265
{
266
	struct drm_mode_object *obj = NULL;
266
	struct drm_mode_object *obj = NULL;
267
 
267
 
268
	mutex_lock(&dev->mode_config.idr_mutex);
268
	mutex_lock(&dev->mode_config.idr_mutex);
269
	obj = idr_find(&dev->mode_config.crtc_idr, id);
269
	obj = idr_find(&dev->mode_config.crtc_idr, id);
270
	if (!obj || (obj->type != type) || (obj->id != id))
270
	if (!obj || (obj->type != type) || (obj->id != id))
271
		obj = NULL;
271
		obj = NULL;
272
	mutex_unlock(&dev->mode_config.idr_mutex);
272
	mutex_unlock(&dev->mode_config.idr_mutex);
273
 
273
 
274
	return obj;
274
	return obj;
275
}
275
}
276
EXPORT_SYMBOL(drm_mode_object_find);
276
EXPORT_SYMBOL(drm_mode_object_find);
277
 
277
 
278
/**
278
/**
279
 * drm_framebuffer_init - initialize a framebuffer
279
 * drm_framebuffer_init - initialize a framebuffer
280
 * @dev: DRM device
280
 * @dev: DRM device
281
 *
281
 *
282
 * LOCKING:
282
 * LOCKING:
283
 * Caller must hold mode config lock.
283
 * Caller must hold mode config lock.
284
 *
284
 *
285
 * Allocates an ID for the framebuffer's parent mode object, sets its mode
285
 * Allocates an ID for the framebuffer's parent mode object, sets its mode
286
 * functions & device file and adds it to the master fd list.
286
 * functions & device file and adds it to the master fd list.
287
 *
287
 *
288
 * RETURNS:
288
 * RETURNS:
289
 * Zero on success, error code on failure.
289
 * Zero on success, error code on failure.
290
 */
290
 */
291
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
291
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
292
			 const struct drm_framebuffer_funcs *funcs)
292
			 const struct drm_framebuffer_funcs *funcs)
293
{
293
{
294
	int ret;
294
	int ret;
295
 
295
 
296
	ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
296
	ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
297
	if (ret)
297
	if (ret)
298
		return ret;
298
		return ret;
299
 
299
 
300
	fb->dev = dev;
300
	fb->dev = dev;
301
	fb->funcs = funcs;
301
	fb->funcs = funcs;
302
	dev->mode_config.num_fb++;
302
	dev->mode_config.num_fb++;
303
	list_add(&fb->head, &dev->mode_config.fb_list);
303
	list_add(&fb->head, &dev->mode_config.fb_list);
304
 
304
 
305
	return 0;
305
	return 0;
306
}
306
}
307
EXPORT_SYMBOL(drm_framebuffer_init);
307
EXPORT_SYMBOL(drm_framebuffer_init);
308
 
308
 
309
/**
309
/**
310
 * drm_framebuffer_cleanup - remove a framebuffer object
310
 * drm_framebuffer_cleanup - remove a framebuffer object
311
 * @fb: framebuffer to remove
311
 * @fb: framebuffer to remove
312
 *
312
 *
313
 * LOCKING:
313
 * LOCKING:
314
 * Caller must hold mode config lock.
314
 * Caller must hold mode config lock.
315
 *
315
 *
316
 * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
316
 * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
317
 * it, setting it to NULL.
317
 * it, setting it to NULL.
318
 */
318
 */
319
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
319
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
320
{
320
{
321
	struct drm_device *dev = fb->dev;
321
	struct drm_device *dev = fb->dev;
322
	/*
322
	/*
323
	 * This could be moved to drm_framebuffer_remove(), but for
323
	 * This could be moved to drm_framebuffer_remove(), but for
324
	 * debugging is nice to keep around the list of fb's that are
324
	 * debugging is nice to keep around the list of fb's that are
325
	 * no longer associated w/ a drm_file but are not unreferenced
325
	 * no longer associated w/ a drm_file but are not unreferenced
326
	 * yet.  (i915 and omapdrm have debugfs files which will show
326
	 * yet.  (i915 and omapdrm have debugfs files which will show
327
	 * this.)
327
	 * this.)
328
	 */
328
	 */
329
	drm_mode_object_put(dev, &fb->base);
329
	drm_mode_object_put(dev, &fb->base);
330
	list_del(&fb->head);
330
	list_del(&fb->head);
331
	dev->mode_config.num_fb--;
331
	dev->mode_config.num_fb--;
332
}
332
}
333
EXPORT_SYMBOL(drm_framebuffer_cleanup);
333
EXPORT_SYMBOL(drm_framebuffer_cleanup);
334
 
334
 
335
 
335
 
336
 
336
 
337
 
337
 
338
 
338
 
339
/**
339
/**
340
 * drm_crtc_init - Initialise a new CRTC object
340
 * drm_crtc_init - Initialise a new CRTC object
341
 * @dev: DRM device
341
 * @dev: DRM device
342
 * @crtc: CRTC object to init
342
 * @crtc: CRTC object to init
343
 * @funcs: callbacks for the new CRTC
343
 * @funcs: callbacks for the new CRTC
344
 *
344
 *
345
 * LOCKING:
345
 * LOCKING:
346
 * Takes mode_config lock.
346
 * Takes mode_config lock.
347
 *
347
 *
348
 * Inits a new object created as base part of an driver crtc object.
348
 * Inits a new object created as base part of an driver crtc object.
349
 *
349
 *
350
 * RETURNS:
350
 * RETURNS:
351
 * Zero on success, error code on failure.
351
 * Zero on success, error code on failure.
352
 */
352
 */
353
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
353
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
354
		   const struct drm_crtc_funcs *funcs)
354
		   const struct drm_crtc_funcs *funcs)
355
{
355
{
356
	int ret;
356
	int ret;
357
 
357
 
358
	crtc->dev = dev;
358
	crtc->dev = dev;
359
	crtc->funcs = funcs;
359
	crtc->funcs = funcs;
360
	crtc->invert_dimensions = false;
360
	crtc->invert_dimensions = false;
361
 
361
 
362
	mutex_lock(&dev->mode_config.mutex);
362
	mutex_lock(&dev->mode_config.mutex);
363
 
363
 
364
	ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
364
	ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
365
	if (ret)
365
	if (ret)
366
		goto out;
366
		goto out;
367
 
367
 
368
	crtc->base.properties = &crtc->properties;
368
	crtc->base.properties = &crtc->properties;
369
 
369
 
370
	list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
370
	list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
371
	dev->mode_config.num_crtc++;
371
	dev->mode_config.num_crtc++;
372
 
372
 
373
 out:
373
 out:
374
	mutex_unlock(&dev->mode_config.mutex);
374
	mutex_unlock(&dev->mode_config.mutex);
375
 
375
 
376
	return ret;
376
	return ret;
377
}
377
}
378
EXPORT_SYMBOL(drm_crtc_init);
378
EXPORT_SYMBOL(drm_crtc_init);
379
 
379
 
380
/**
380
/**
381
 * drm_crtc_cleanup - Cleans up the core crtc usage.
381
 * drm_crtc_cleanup - Cleans up the core crtc usage.
382
 * @crtc: CRTC to cleanup
382
 * @crtc: CRTC to cleanup
383
 *
383
 *
384
 * LOCKING:
384
 * LOCKING:
385
 * Caller must hold mode config lock.
385
 * Caller must hold mode config lock.
386
 *
386
 *
387
 * Cleanup @crtc. Removes from drm modesetting space
387
 * Cleanup @crtc. Removes from drm modesetting space
388
 * does NOT free object, caller does that.
388
 * does NOT free object, caller does that.
389
 */
389
 */
390
void drm_crtc_cleanup(struct drm_crtc *crtc)
390
void drm_crtc_cleanup(struct drm_crtc *crtc)
391
{
391
{
392
	struct drm_device *dev = crtc->dev;
392
	struct drm_device *dev = crtc->dev;
393
 
-
 
394
	if (crtc->gamma_store) {
393
 
395
		kfree(crtc->gamma_store);
394
		kfree(crtc->gamma_store);
396
		crtc->gamma_store = NULL;
-
 
397
	}
395
		crtc->gamma_store = NULL;
398
 
396
 
399
	drm_mode_object_put(dev, &crtc->base);
397
	drm_mode_object_put(dev, &crtc->base);
400
	list_del(&crtc->head);
398
	list_del(&crtc->head);
401
	dev->mode_config.num_crtc--;
399
	dev->mode_config.num_crtc--;
402
}
400
}
403
EXPORT_SYMBOL(drm_crtc_cleanup);
401
EXPORT_SYMBOL(drm_crtc_cleanup);
404
 
402
 
405
/**
403
/**
406
 * drm_mode_probed_add - add a mode to a connector's probed mode list
404
 * drm_mode_probed_add - add a mode to a connector's probed mode list
407
 * @connector: connector the new mode
405
 * @connector: connector the new mode
408
 * @mode: mode data
406
 * @mode: mode data
409
 *
407
 *
410
 * LOCKING:
408
 * LOCKING:
411
 * Caller must hold mode config lock.
409
 * Caller must hold mode config lock.
412
 *
410
 *
413
 * Add @mode to @connector's mode list for later use.
411
 * Add @mode to @connector's mode list for later use.
414
 */
412
 */
415
void drm_mode_probed_add(struct drm_connector *connector,
413
void drm_mode_probed_add(struct drm_connector *connector,
416
			 struct drm_display_mode *mode)
414
			 struct drm_display_mode *mode)
417
{
415
{
418
	list_add(&mode->head, &connector->probed_modes);
416
	list_add(&mode->head, &connector->probed_modes);
419
}
417
}
420
EXPORT_SYMBOL(drm_mode_probed_add);
418
EXPORT_SYMBOL(drm_mode_probed_add);
421
 
419
 
422
/**
420
/**
423
 * drm_mode_remove - remove and free a mode
421
 * drm_mode_remove - remove and free a mode
424
 * @connector: connector list to modify
422
 * @connector: connector list to modify
425
 * @mode: mode to remove
423
 * @mode: mode to remove
426
 *
424
 *
427
 * LOCKING:
425
 * LOCKING:
428
 * Caller must hold mode config lock.
426
 * Caller must hold mode config lock.
429
 *
427
 *
430
 * Remove @mode from @connector's mode list, then free it.
428
 * Remove @mode from @connector's mode list, then free it.
431
 */
429
 */
432
void drm_mode_remove(struct drm_connector *connector,
430
void drm_mode_remove(struct drm_connector *connector,
433
		     struct drm_display_mode *mode)
431
		     struct drm_display_mode *mode)
434
{
432
{
435
	list_del(&mode->head);
433
	list_del(&mode->head);
436
	drm_mode_destroy(connector->dev, mode);
434
	drm_mode_destroy(connector->dev, mode);
437
}
435
}
438
EXPORT_SYMBOL(drm_mode_remove);
436
EXPORT_SYMBOL(drm_mode_remove);
439
 
437
 
440
/**
438
/**
441
 * drm_connector_init - Init a preallocated connector
439
 * drm_connector_init - Init a preallocated connector
442
 * @dev: DRM device
440
 * @dev: DRM device
443
 * @connector: the connector to init
441
 * @connector: the connector to init
444
 * @funcs: callbacks for this connector
442
 * @funcs: callbacks for this connector
445
 * @name: user visible name of the connector
443
 * @name: user visible name of the connector
446
 *
444
 *
447
 * LOCKING:
445
 * LOCKING:
448
 * Takes mode config lock.
446
 * Takes mode config lock.
449
 *
447
 *
450
 * Initialises a preallocated connector. Connectors should be
448
 * Initialises a preallocated connector. Connectors should be
451
 * subclassed as part of driver connector objects.
449
 * subclassed as part of driver connector objects.
452
 *
450
 *
453
 * RETURNS:
451
 * RETURNS:
454
 * Zero on success, error code on failure.
452
 * Zero on success, error code on failure.
455
 */
453
 */
456
int drm_connector_init(struct drm_device *dev,
454
int drm_connector_init(struct drm_device *dev,
457
		     struct drm_connector *connector,
455
		     struct drm_connector *connector,
458
		     const struct drm_connector_funcs *funcs,
456
		     const struct drm_connector_funcs *funcs,
459
		     int connector_type)
457
		     int connector_type)
460
{
458
{
461
	int ret;
459
	int ret;
462
 
460
 
463
	mutex_lock(&dev->mode_config.mutex);
461
	mutex_lock(&dev->mode_config.mutex);
464
 
462
 
465
	ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
463
	ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
466
	if (ret)
464
	if (ret)
467
		goto out;
465
		goto out;
468
 
466
 
469
	connector->base.properties = &connector->properties;
467
	connector->base.properties = &connector->properties;
470
	connector->dev = dev;
468
	connector->dev = dev;
471
	connector->funcs = funcs;
469
	connector->funcs = funcs;
472
	connector->connector_type = connector_type;
470
	connector->connector_type = connector_type;
473
	connector->connector_type_id =
471
	connector->connector_type_id =
474
		++drm_connector_enum_list[connector_type].count; /* TODO */
472
		++drm_connector_enum_list[connector_type].count; /* TODO */
475
	INIT_LIST_HEAD(&connector->user_modes);
473
	INIT_LIST_HEAD(&connector->user_modes);
476
	INIT_LIST_HEAD(&connector->probed_modes);
474
	INIT_LIST_HEAD(&connector->probed_modes);
477
	INIT_LIST_HEAD(&connector->modes);
475
	INIT_LIST_HEAD(&connector->modes);
478
	connector->edid_blob_ptr = NULL;
476
	connector->edid_blob_ptr = NULL;
-
 
477
	connector->status = connector_status_unknown;
479
 
478
 
480
	list_add_tail(&connector->head, &dev->mode_config.connector_list);
479
	list_add_tail(&connector->head, &dev->mode_config.connector_list);
481
	dev->mode_config.num_connector++;
480
	dev->mode_config.num_connector++;
482
 
481
 
483
	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
482
	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
484
	drm_connector_attach_property(connector,
483
		drm_object_attach_property(&connector->base,
485
					      dev->mode_config.edid_property,
484
					      dev->mode_config.edid_property,
486
					      0);
485
					      0);
487
 
486
 
488
	drm_connector_attach_property(connector,
487
	drm_object_attach_property(&connector->base,
489
				      dev->mode_config.dpms_property, 0);
488
				      dev->mode_config.dpms_property, 0);
490
 
489
 
491
 out:
490
 out:
492
	mutex_unlock(&dev->mode_config.mutex);
491
	mutex_unlock(&dev->mode_config.mutex);
493
 
492
 
494
	return ret;
493
	return ret;
495
}
494
}
496
EXPORT_SYMBOL(drm_connector_init);
495
EXPORT_SYMBOL(drm_connector_init);
497
 
496
 
498
/**
497
/**
499
 * drm_connector_cleanup - cleans up an initialised connector
498
 * drm_connector_cleanup - cleans up an initialised connector
500
 * @connector: connector to cleanup
499
 * @connector: connector to cleanup
501
 *
500
 *
502
 * LOCKING:
501
 * LOCKING:
503
 * Takes mode config lock.
502
 * Takes mode config lock.
504
 *
503
 *
505
 * Cleans up the connector but doesn't free the object.
504
 * Cleans up the connector but doesn't free the object.
506
 */
505
 */
507
void drm_connector_cleanup(struct drm_connector *connector)
506
void drm_connector_cleanup(struct drm_connector *connector)
508
{
507
{
509
	struct drm_device *dev = connector->dev;
508
	struct drm_device *dev = connector->dev;
510
	struct drm_display_mode *mode, *t;
509
	struct drm_display_mode *mode, *t;
511
 
510
 
512
	list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
511
	list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
513
		drm_mode_remove(connector, mode);
512
		drm_mode_remove(connector, mode);
514
 
513
 
515
	list_for_each_entry_safe(mode, t, &connector->modes, head)
514
	list_for_each_entry_safe(mode, t, &connector->modes, head)
516
		drm_mode_remove(connector, mode);
515
		drm_mode_remove(connector, mode);
517
 
516
 
518
	list_for_each_entry_safe(mode, t, &connector->user_modes, head)
517
	list_for_each_entry_safe(mode, t, &connector->user_modes, head)
519
		drm_mode_remove(connector, mode);
518
		drm_mode_remove(connector, mode);
520
 
519
 
521
	mutex_lock(&dev->mode_config.mutex);
520
	mutex_lock(&dev->mode_config.mutex);
522
	drm_mode_object_put(dev, &connector->base);
521
	drm_mode_object_put(dev, &connector->base);
523
	list_del(&connector->head);
522
	list_del(&connector->head);
524
	dev->mode_config.num_connector--;
523
	dev->mode_config.num_connector--;
525
	mutex_unlock(&dev->mode_config.mutex);
524
	mutex_unlock(&dev->mode_config.mutex);
526
}
525
}
527
EXPORT_SYMBOL(drm_connector_cleanup);
526
EXPORT_SYMBOL(drm_connector_cleanup);
528
 
527
 
529
void drm_connector_unplug_all(struct drm_device *dev)
528
void drm_connector_unplug_all(struct drm_device *dev)
530
{
529
{
531
	struct drm_connector *connector;
530
	struct drm_connector *connector;
532
 
531
 
533
	/* taking the mode config mutex ends up in a clash with sysfs */
532
	/* taking the mode config mutex ends up in a clash with sysfs */
534
//   list_for_each_entry(connector, &dev->mode_config.connector_list, head)
533
//   list_for_each_entry(connector, &dev->mode_config.connector_list, head)
535
//       drm_sysfs_connector_remove(connector);
534
//       drm_sysfs_connector_remove(connector);
536
 
535
 
537
}
536
}
538
EXPORT_SYMBOL(drm_connector_unplug_all);
537
EXPORT_SYMBOL(drm_connector_unplug_all);
539
 
538
 
540
int drm_encoder_init(struct drm_device *dev,
539
int drm_encoder_init(struct drm_device *dev,
541
		      struct drm_encoder *encoder,
540
		      struct drm_encoder *encoder,
542
		      const struct drm_encoder_funcs *funcs,
541
		      const struct drm_encoder_funcs *funcs,
543
		      int encoder_type)
542
		      int encoder_type)
544
{
543
{
545
	int ret;
544
	int ret;
546
 
545
 
547
	mutex_lock(&dev->mode_config.mutex);
546
	mutex_lock(&dev->mode_config.mutex);
548
 
547
 
549
	ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
548
	ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
550
	if (ret)
549
	if (ret)
551
		goto out;
550
		goto out;
552
 
551
 
553
	encoder->dev = dev;
552
	encoder->dev = dev;
554
	encoder->encoder_type = encoder_type;
553
	encoder->encoder_type = encoder_type;
555
	encoder->funcs = funcs;
554
	encoder->funcs = funcs;
556
 
555
 
557
	list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
556
	list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
558
	dev->mode_config.num_encoder++;
557
	dev->mode_config.num_encoder++;
559
 
558
 
560
 out:
559
 out:
561
	mutex_unlock(&dev->mode_config.mutex);
560
	mutex_unlock(&dev->mode_config.mutex);
562
 
561
 
563
	return ret;
562
	return ret;
564
}
563
}
565
EXPORT_SYMBOL(drm_encoder_init);
564
EXPORT_SYMBOL(drm_encoder_init);
566
 
565
 
567
void drm_encoder_cleanup(struct drm_encoder *encoder)
566
void drm_encoder_cleanup(struct drm_encoder *encoder)
568
{
567
{
569
	struct drm_device *dev = encoder->dev;
568
	struct drm_device *dev = encoder->dev;
570
	mutex_lock(&dev->mode_config.mutex);
569
	mutex_lock(&dev->mode_config.mutex);
571
	drm_mode_object_put(dev, &encoder->base);
570
	drm_mode_object_put(dev, &encoder->base);
572
	list_del(&encoder->head);
571
	list_del(&encoder->head);
573
	dev->mode_config.num_encoder--;
572
	dev->mode_config.num_encoder--;
574
	mutex_unlock(&dev->mode_config.mutex);
573
	mutex_unlock(&dev->mode_config.mutex);
575
}
574
}
576
EXPORT_SYMBOL(drm_encoder_cleanup);
575
EXPORT_SYMBOL(drm_encoder_cleanup);
577
 
576
 
578
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
577
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
579
		   unsigned long possible_crtcs,
578
		   unsigned long possible_crtcs,
580
		   const struct drm_plane_funcs *funcs,
579
		   const struct drm_plane_funcs *funcs,
581
		   const uint32_t *formats, uint32_t format_count,
580
		   const uint32_t *formats, uint32_t format_count,
582
		   bool priv)
581
		   bool priv)
583
{
582
{
584
	int ret;
583
	int ret;
585
 
584
 
586
	mutex_lock(&dev->mode_config.mutex);
585
	mutex_lock(&dev->mode_config.mutex);
587
 
586
 
588
	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
587
	ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
589
	if (ret)
588
	if (ret)
590
		goto out;
589
		goto out;
591
 
590
 
592
	plane->base.properties = &plane->properties;
591
	plane->base.properties = &plane->properties;
593
	plane->dev = dev;
592
	plane->dev = dev;
594
	plane->funcs = funcs;
593
	plane->funcs = funcs;
595
	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
594
	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
596
				      GFP_KERNEL);
595
				      GFP_KERNEL);
597
	if (!plane->format_types) {
596
	if (!plane->format_types) {
598
		DRM_DEBUG_KMS("out of memory when allocating plane\n");
597
		DRM_DEBUG_KMS("out of memory when allocating plane\n");
599
		drm_mode_object_put(dev, &plane->base);
598
		drm_mode_object_put(dev, &plane->base);
600
		ret = -ENOMEM;
599
		ret = -ENOMEM;
601
		goto out;
600
		goto out;
602
	}
601
	}
603
 
602
 
604
	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
603
	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
605
	plane->format_count = format_count;
604
	plane->format_count = format_count;
606
	plane->possible_crtcs = possible_crtcs;
605
	plane->possible_crtcs = possible_crtcs;
607
 
606
 
608
	/* private planes are not exposed to userspace, but depending on
607
	/* private planes are not exposed to userspace, but depending on
609
	 * display hardware, might be convenient to allow sharing programming
608
	 * display hardware, might be convenient to allow sharing programming
610
	 * for the scanout engine with the crtc implementation.
609
	 * for the scanout engine with the crtc implementation.
611
	 */
610
	 */
612
	if (!priv) {
611
	if (!priv) {
613
		list_add_tail(&plane->head, &dev->mode_config.plane_list);
612
		list_add_tail(&plane->head, &dev->mode_config.plane_list);
614
		dev->mode_config.num_plane++;
613
		dev->mode_config.num_plane++;
615
	} else {
614
	} else {
616
		INIT_LIST_HEAD(&plane->head);
615
		INIT_LIST_HEAD(&plane->head);
617
	}
616
	}
618
 
617
 
619
 out:
618
 out:
620
	mutex_unlock(&dev->mode_config.mutex);
619
	mutex_unlock(&dev->mode_config.mutex);
621
 
620
 
622
	return ret;
621
	return ret;
623
}
622
}
624
EXPORT_SYMBOL(drm_plane_init);
623
EXPORT_SYMBOL(drm_plane_init);
625
 
624
 
626
void drm_plane_cleanup(struct drm_plane *plane)
625
void drm_plane_cleanup(struct drm_plane *plane)
627
{
626
{
628
	struct drm_device *dev = plane->dev;
627
	struct drm_device *dev = plane->dev;
629
 
628
 
630
	mutex_lock(&dev->mode_config.mutex);
629
	mutex_lock(&dev->mode_config.mutex);
631
	kfree(plane->format_types);
630
	kfree(plane->format_types);
632
	drm_mode_object_put(dev, &plane->base);
631
	drm_mode_object_put(dev, &plane->base);
633
	/* if not added to a list, it must be a private plane */
632
	/* if not added to a list, it must be a private plane */
634
	if (!list_empty(&plane->head)) {
633
	if (!list_empty(&plane->head)) {
635
		list_del(&plane->head);
634
		list_del(&plane->head);
636
		dev->mode_config.num_plane--;
635
		dev->mode_config.num_plane--;
637
	}
636
	}
638
	mutex_unlock(&dev->mode_config.mutex);
637
	mutex_unlock(&dev->mode_config.mutex);
639
}
638
}
640
EXPORT_SYMBOL(drm_plane_cleanup);
639
EXPORT_SYMBOL(drm_plane_cleanup);
641
 
640
 
642
/**
641
/**
643
 * drm_mode_create - create a new display mode
642
 * drm_mode_create - create a new display mode
644
 * @dev: DRM device
643
 * @dev: DRM device
645
 *
644
 *
646
 * LOCKING:
645
 * LOCKING:
647
 * Caller must hold DRM mode_config lock.
646
 * Caller must hold DRM mode_config lock.
648
 *
647
 *
649
 * Create a new drm_display_mode, give it an ID, and return it.
648
 * Create a new drm_display_mode, give it an ID, and return it.
650
 *
649
 *
651
 * RETURNS:
650
 * RETURNS:
652
 * Pointer to new mode on success, NULL on error.
651
 * Pointer to new mode on success, NULL on error.
653
 */
652
 */
654
struct drm_display_mode *drm_mode_create(struct drm_device *dev)
653
struct drm_display_mode *drm_mode_create(struct drm_device *dev)
655
{
654
{
656
	struct drm_display_mode *nmode;
655
	struct drm_display_mode *nmode;
657
 
656
 
658
	nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
657
	nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
659
	if (!nmode)
658
	if (!nmode)
660
		return NULL;
659
		return NULL;
661
 
660
 
662
	if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
661
	if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
663
		kfree(nmode);
662
		kfree(nmode);
664
		return NULL;
663
		return NULL;
665
	}
664
	}
666
 
665
 
667
	return nmode;
666
	return nmode;
668
}
667
}
669
EXPORT_SYMBOL(drm_mode_create);
668
EXPORT_SYMBOL(drm_mode_create);
670
 
669
 
671
/**
670
/**
672
 * drm_mode_destroy - remove a mode
671
 * drm_mode_destroy - remove a mode
673
 * @dev: DRM device
672
 * @dev: DRM device
674
 * @mode: mode to remove
673
 * @mode: mode to remove
675
 *
674
 *
676
 * LOCKING:
675
 * LOCKING:
677
 * Caller must hold mode config lock.
676
 * Caller must hold mode config lock.
678
 *
677
 *
679
 * Free @mode's unique identifier, then free it.
678
 * Free @mode's unique identifier, then free it.
680
 */
679
 */
681
void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
680
void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
682
{
681
{
683
	if (!mode)
682
	if (!mode)
684
		return;
683
		return;
685
 
684
 
686
	drm_mode_object_put(dev, &mode->base);
685
	drm_mode_object_put(dev, &mode->base);
687
 
686
 
688
	kfree(mode);
687
	kfree(mode);
689
}
688
}
690
EXPORT_SYMBOL(drm_mode_destroy);
689
EXPORT_SYMBOL(drm_mode_destroy);
691
 
690
 
692
static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
691
static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
693
{
692
{
694
	struct drm_property *edid;
693
	struct drm_property *edid;
695
	struct drm_property *dpms;
694
	struct drm_property *dpms;
696
 
695
 
697
	/*
696
	/*
698
	 * Standard properties (apply to all connectors)
697
	 * Standard properties (apply to all connectors)
699
	 */
698
	 */
700
	edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
699
	edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
701
				   DRM_MODE_PROP_IMMUTABLE,
700
				   DRM_MODE_PROP_IMMUTABLE,
702
				   "EDID", 0);
701
				   "EDID", 0);
703
	dev->mode_config.edid_property = edid;
702
	dev->mode_config.edid_property = edid;
704
 
703
 
705
	dpms = drm_property_create_enum(dev, 0,
704
	dpms = drm_property_create_enum(dev, 0,
706
				   "DPMS", drm_dpms_enum_list,
705
				   "DPMS", drm_dpms_enum_list,
707
				   ARRAY_SIZE(drm_dpms_enum_list));
706
				   ARRAY_SIZE(drm_dpms_enum_list));
708
	dev->mode_config.dpms_property = dpms;
707
	dev->mode_config.dpms_property = dpms;
709
 
708
 
710
	return 0;
709
	return 0;
711
}
710
}
712
 
711
 
713
/**
712
/**
714
 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
713
 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
715
 * @dev: DRM device
714
 * @dev: DRM device
716
 *
715
 *
717
 * Called by a driver the first time a DVI-I connector is made.
716
 * Called by a driver the first time a DVI-I connector is made.
718
 */
717
 */
719
int drm_mode_create_dvi_i_properties(struct drm_device *dev)
718
int drm_mode_create_dvi_i_properties(struct drm_device *dev)
720
{
719
{
721
	struct drm_property *dvi_i_selector;
720
	struct drm_property *dvi_i_selector;
722
	struct drm_property *dvi_i_subconnector;
721
	struct drm_property *dvi_i_subconnector;
723
 
722
 
724
	if (dev->mode_config.dvi_i_select_subconnector_property)
723
	if (dev->mode_config.dvi_i_select_subconnector_property)
725
		return 0;
724
		return 0;
726
 
725
 
727
	dvi_i_selector =
726
	dvi_i_selector =
728
		drm_property_create_enum(dev, 0,
727
		drm_property_create_enum(dev, 0,
729
				    "select subconnector",
728
				    "select subconnector",
730
				    drm_dvi_i_select_enum_list,
729
				    drm_dvi_i_select_enum_list,
731
				    ARRAY_SIZE(drm_dvi_i_select_enum_list));
730
				    ARRAY_SIZE(drm_dvi_i_select_enum_list));
732
	dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
731
	dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
733
 
732
 
734
	dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
733
	dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
735
				    "subconnector",
734
				    "subconnector",
736
				    drm_dvi_i_subconnector_enum_list,
735
				    drm_dvi_i_subconnector_enum_list,
737
				    ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
736
				    ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
738
	dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
737
	dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
739
 
738
 
740
	return 0;
739
	return 0;
741
}
740
}
742
EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
741
EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
743
 
742
 
744
/**
743
/**
745
 * drm_create_tv_properties - create TV specific connector properties
744
 * drm_create_tv_properties - create TV specific connector properties
746
 * @dev: DRM device
745
 * @dev: DRM device
747
 * @num_modes: number of different TV formats (modes) supported
746
 * @num_modes: number of different TV formats (modes) supported
748
 * @modes: array of pointers to strings containing name of each format
747
 * @modes: array of pointers to strings containing name of each format
749
 *
748
 *
750
 * Called by a driver's TV initialization routine, this function creates
749
 * Called by a driver's TV initialization routine, this function creates
751
 * the TV specific connector properties for a given device.  Caller is
750
 * the TV specific connector properties for a given device.  Caller is
752
 * responsible for allocating a list of format names and passing them to
751
 * responsible for allocating a list of format names and passing them to
753
 * this routine.
752
 * this routine.
754
 */
753
 */
755
int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
754
int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
756
				  char *modes[])
755
				  char *modes[])
757
{
756
{
758
	struct drm_property *tv_selector;
757
	struct drm_property *tv_selector;
759
	struct drm_property *tv_subconnector;
758
	struct drm_property *tv_subconnector;
760
	int i;
759
	int i;
761
 
760
 
762
	if (dev->mode_config.tv_select_subconnector_property)
761
	if (dev->mode_config.tv_select_subconnector_property)
763
		return 0;
762
		return 0;
764
 
763
 
765
	/*
764
	/*
766
	 * Basic connector properties
765
	 * Basic connector properties
767
	 */
766
	 */
768
	tv_selector = drm_property_create_enum(dev, 0,
767
	tv_selector = drm_property_create_enum(dev, 0,
769
					  "select subconnector",
768
					  "select subconnector",
770
					  drm_tv_select_enum_list,
769
					  drm_tv_select_enum_list,
771
					  ARRAY_SIZE(drm_tv_select_enum_list));
770
					  ARRAY_SIZE(drm_tv_select_enum_list));
772
	dev->mode_config.tv_select_subconnector_property = tv_selector;
771
	dev->mode_config.tv_select_subconnector_property = tv_selector;
773
 
772
 
774
	tv_subconnector =
773
	tv_subconnector =
775
		drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
774
		drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
776
				    "subconnector",
775
				    "subconnector",
777
				    drm_tv_subconnector_enum_list,
776
				    drm_tv_subconnector_enum_list,
778
				    ARRAY_SIZE(drm_tv_subconnector_enum_list));
777
				    ARRAY_SIZE(drm_tv_subconnector_enum_list));
779
	dev->mode_config.tv_subconnector_property = tv_subconnector;
778
	dev->mode_config.tv_subconnector_property = tv_subconnector;
780
 
779
 
781
	/*
780
	/*
782
	 * Other, TV specific properties: margins & TV modes.
781
	 * Other, TV specific properties: margins & TV modes.
783
	 */
782
	 */
784
	dev->mode_config.tv_left_margin_property =
783
	dev->mode_config.tv_left_margin_property =
785
		drm_property_create_range(dev, 0, "left margin", 0, 100);
784
		drm_property_create_range(dev, 0, "left margin", 0, 100);
786
 
785
 
787
	dev->mode_config.tv_right_margin_property =
786
	dev->mode_config.tv_right_margin_property =
788
		drm_property_create_range(dev, 0, "right margin", 0, 100);
787
		drm_property_create_range(dev, 0, "right margin", 0, 100);
789
 
788
 
790
	dev->mode_config.tv_top_margin_property =
789
	dev->mode_config.tv_top_margin_property =
791
		drm_property_create_range(dev, 0, "top margin", 0, 100);
790
		drm_property_create_range(dev, 0, "top margin", 0, 100);
792
 
791
 
793
	dev->mode_config.tv_bottom_margin_property =
792
	dev->mode_config.tv_bottom_margin_property =
794
		drm_property_create_range(dev, 0, "bottom margin", 0, 100);
793
		drm_property_create_range(dev, 0, "bottom margin", 0, 100);
795
 
794
 
796
	dev->mode_config.tv_mode_property =
795
	dev->mode_config.tv_mode_property =
797
		drm_property_create(dev, DRM_MODE_PROP_ENUM,
796
		drm_property_create(dev, DRM_MODE_PROP_ENUM,
798
				    "mode", num_modes);
797
				    "mode", num_modes);
799
	for (i = 0; i < num_modes; i++)
798
	for (i = 0; i < num_modes; i++)
800
		drm_property_add_enum(dev->mode_config.tv_mode_property, i,
799
		drm_property_add_enum(dev->mode_config.tv_mode_property, i,
801
				      i, modes[i]);
800
				      i, modes[i]);
802
 
801
 
803
	dev->mode_config.tv_brightness_property =
802
	dev->mode_config.tv_brightness_property =
804
		drm_property_create_range(dev, 0, "brightness", 0, 100);
803
		drm_property_create_range(dev, 0, "brightness", 0, 100);
805
 
804
 
806
	dev->mode_config.tv_contrast_property =
805
	dev->mode_config.tv_contrast_property =
807
		drm_property_create_range(dev, 0, "contrast", 0, 100);
806
		drm_property_create_range(dev, 0, "contrast", 0, 100);
808
 
807
 
809
	dev->mode_config.tv_flicker_reduction_property =
808
	dev->mode_config.tv_flicker_reduction_property =
810
		drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
809
		drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
811
 
810
 
812
	dev->mode_config.tv_overscan_property =
811
	dev->mode_config.tv_overscan_property =
813
		drm_property_create_range(dev, 0, "overscan", 0, 100);
812
		drm_property_create_range(dev, 0, "overscan", 0, 100);
814
 
813
 
815
	dev->mode_config.tv_saturation_property =
814
	dev->mode_config.tv_saturation_property =
816
		drm_property_create_range(dev, 0, "saturation", 0, 100);
815
		drm_property_create_range(dev, 0, "saturation", 0, 100);
817
 
816
 
818
	dev->mode_config.tv_hue_property =
817
	dev->mode_config.tv_hue_property =
819
		drm_property_create_range(dev, 0, "hue", 0, 100);
818
		drm_property_create_range(dev, 0, "hue", 0, 100);
820
 
819
 
821
	return 0;
820
	return 0;
822
}
821
}
823
EXPORT_SYMBOL(drm_mode_create_tv_properties);
822
EXPORT_SYMBOL(drm_mode_create_tv_properties);
824
 
823
 
825
/**
824
/**
826
 * drm_mode_create_scaling_mode_property - create scaling mode property
825
 * drm_mode_create_scaling_mode_property - create scaling mode property
827
 * @dev: DRM device
826
 * @dev: DRM device
828
 *
827
 *
829
 * Called by a driver the first time it's needed, must be attached to desired
828
 * Called by a driver the first time it's needed, must be attached to desired
830
 * connectors.
829
 * connectors.
831
 */
830
 */
832
int drm_mode_create_scaling_mode_property(struct drm_device *dev)
831
int drm_mode_create_scaling_mode_property(struct drm_device *dev)
833
{
832
{
834
	struct drm_property *scaling_mode;
833
	struct drm_property *scaling_mode;
835
 
834
 
836
	if (dev->mode_config.scaling_mode_property)
835
	if (dev->mode_config.scaling_mode_property)
837
		return 0;
836
		return 0;
838
 
837
 
839
	scaling_mode =
838
	scaling_mode =
840
		drm_property_create_enum(dev, 0, "scaling mode",
839
		drm_property_create_enum(dev, 0, "scaling mode",
841
				drm_scaling_mode_enum_list,
840
				drm_scaling_mode_enum_list,
842
				    ARRAY_SIZE(drm_scaling_mode_enum_list));
841
				    ARRAY_SIZE(drm_scaling_mode_enum_list));
843
 
842
 
844
	dev->mode_config.scaling_mode_property = scaling_mode;
843
	dev->mode_config.scaling_mode_property = scaling_mode;
845
 
844
 
846
	return 0;
845
	return 0;
847
}
846
}
848
EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
847
EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
849
 
848
 
850
/**
849
/**
851
 * drm_mode_create_dithering_property - create dithering property
850
 * drm_mode_create_dithering_property - create dithering property
852
 * @dev: DRM device
851
 * @dev: DRM device
853
 *
852
 *
854
 * Called by a driver the first time it's needed, must be attached to desired
853
 * Called by a driver the first time it's needed, must be attached to desired
855
 * connectors.
854
 * connectors.
856
 */
855
 */
857
int drm_mode_create_dithering_property(struct drm_device *dev)
856
int drm_mode_create_dithering_property(struct drm_device *dev)
858
{
857
{
859
	struct drm_property *dithering_mode;
858
	struct drm_property *dithering_mode;
860
 
859
 
861
	if (dev->mode_config.dithering_mode_property)
860
	if (dev->mode_config.dithering_mode_property)
862
		return 0;
861
		return 0;
863
 
862
 
864
	dithering_mode =
863
	dithering_mode =
865
		drm_property_create_enum(dev, 0, "dithering",
864
		drm_property_create_enum(dev, 0, "dithering",
866
				drm_dithering_mode_enum_list,
865
				drm_dithering_mode_enum_list,
867
				    ARRAY_SIZE(drm_dithering_mode_enum_list));
866
				    ARRAY_SIZE(drm_dithering_mode_enum_list));
868
	dev->mode_config.dithering_mode_property = dithering_mode;
867
	dev->mode_config.dithering_mode_property = dithering_mode;
869
 
868
 
870
	return 0;
869
	return 0;
871
}
870
}
872
EXPORT_SYMBOL(drm_mode_create_dithering_property);
871
EXPORT_SYMBOL(drm_mode_create_dithering_property);
873
 
872
 
874
/**
873
/**
875
 * drm_mode_create_dirty_property - create dirty property
874
 * drm_mode_create_dirty_property - create dirty property
876
 * @dev: DRM device
875
 * @dev: DRM device
877
 *
876
 *
878
 * Called by a driver the first time it's needed, must be attached to desired
877
 * Called by a driver the first time it's needed, must be attached to desired
879
 * connectors.
878
 * connectors.
880
 */
879
 */
881
int drm_mode_create_dirty_info_property(struct drm_device *dev)
880
int drm_mode_create_dirty_info_property(struct drm_device *dev)
882
{
881
{
883
	struct drm_property *dirty_info;
882
	struct drm_property *dirty_info;
884
 
883
 
885
	if (dev->mode_config.dirty_info_property)
884
	if (dev->mode_config.dirty_info_property)
886
		return 0;
885
		return 0;
887
 
886
 
888
	dirty_info =
887
	dirty_info =
889
		drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
888
		drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
890
				    "dirty",
889
				    "dirty",
891
				    drm_dirty_info_enum_list,
890
				    drm_dirty_info_enum_list,
892
				    ARRAY_SIZE(drm_dirty_info_enum_list));
891
				    ARRAY_SIZE(drm_dirty_info_enum_list));
893
	dev->mode_config.dirty_info_property = dirty_info;
892
	dev->mode_config.dirty_info_property = dirty_info;
894
 
893
 
895
	return 0;
894
	return 0;
896
}
895
}
897
EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
896
EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
898
 
897
 
899
/**
898
/**
900
 * drm_mode_config_init - initialize DRM mode_configuration structure
899
 * drm_mode_config_init - initialize DRM mode_configuration structure
901
 * @dev: DRM device
900
 * @dev: DRM device
902
 *
901
 *
903
 * LOCKING:
902
 * LOCKING:
904
 * None, should happen single threaded at init time.
903
 * None, should happen single threaded at init time.
905
 *
904
 *
906
 * Initialize @dev's mode_config structure, used for tracking the graphics
905
 * Initialize @dev's mode_config structure, used for tracking the graphics
907
 * configuration of @dev.
906
 * configuration of @dev.
908
 */
907
 */
909
void drm_mode_config_init(struct drm_device *dev)
908
void drm_mode_config_init(struct drm_device *dev)
910
{
909
{
911
	mutex_init(&dev->mode_config.mutex);
910
	mutex_init(&dev->mode_config.mutex);
912
	mutex_init(&dev->mode_config.idr_mutex);
911
	mutex_init(&dev->mode_config.idr_mutex);
913
	INIT_LIST_HEAD(&dev->mode_config.fb_list);
912
	INIT_LIST_HEAD(&dev->mode_config.fb_list);
914
	INIT_LIST_HEAD(&dev->mode_config.crtc_list);
913
	INIT_LIST_HEAD(&dev->mode_config.crtc_list);
915
	INIT_LIST_HEAD(&dev->mode_config.connector_list);
914
	INIT_LIST_HEAD(&dev->mode_config.connector_list);
916
	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
915
	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
917
	INIT_LIST_HEAD(&dev->mode_config.property_list);
916
	INIT_LIST_HEAD(&dev->mode_config.property_list);
918
	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
917
	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
919
	INIT_LIST_HEAD(&dev->mode_config.plane_list);
918
	INIT_LIST_HEAD(&dev->mode_config.plane_list);
920
	idr_init(&dev->mode_config.crtc_idr);
919
	idr_init(&dev->mode_config.crtc_idr);
921
 
920
 
922
	mutex_lock(&dev->mode_config.mutex);
921
	mutex_lock(&dev->mode_config.mutex);
923
	drm_mode_create_standard_connector_properties(dev);
922
	drm_mode_create_standard_connector_properties(dev);
924
	mutex_unlock(&dev->mode_config.mutex);
923
	mutex_unlock(&dev->mode_config.mutex);
925
 
924
 
926
	/* Just to be sure */
925
	/* Just to be sure */
927
	dev->mode_config.num_fb = 0;
926
	dev->mode_config.num_fb = 0;
928
	dev->mode_config.num_connector = 0;
927
	dev->mode_config.num_connector = 0;
929
	dev->mode_config.num_crtc = 0;
928
	dev->mode_config.num_crtc = 0;
930
	dev->mode_config.num_encoder = 0;
929
	dev->mode_config.num_encoder = 0;
931
}
930
}
932
EXPORT_SYMBOL(drm_mode_config_init);
931
EXPORT_SYMBOL(drm_mode_config_init);
933
 
932
 
934
int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
933
int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
935
{
934
{
936
	uint32_t total_objects = 0;
935
	uint32_t total_objects = 0;
937
 
936
 
938
	total_objects += dev->mode_config.num_crtc;
937
	total_objects += dev->mode_config.num_crtc;
939
	total_objects += dev->mode_config.num_connector;
938
	total_objects += dev->mode_config.num_connector;
940
	total_objects += dev->mode_config.num_encoder;
939
	total_objects += dev->mode_config.num_encoder;
941
 
940
 
942
	group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
941
	group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
943
	if (!group->id_list)
942
	if (!group->id_list)
944
		return -ENOMEM;
943
		return -ENOMEM;
945
 
944
 
946
	group->num_crtcs = 0;
945
	group->num_crtcs = 0;
947
	group->num_connectors = 0;
946
	group->num_connectors = 0;
948
	group->num_encoders = 0;
947
	group->num_encoders = 0;
949
	return 0;
948
	return 0;
950
}
949
}
951
 
950
 
952
int drm_mode_group_init_legacy_group(struct drm_device *dev,
951
int drm_mode_group_init_legacy_group(struct drm_device *dev,
953
				     struct drm_mode_group *group)
952
				     struct drm_mode_group *group)
954
{
953
{
955
	struct drm_crtc *crtc;
954
	struct drm_crtc *crtc;
956
	struct drm_encoder *encoder;
955
	struct drm_encoder *encoder;
957
	struct drm_connector *connector;
956
	struct drm_connector *connector;
958
	int ret;
957
	int ret;
959
 
958
 
960
	if ((ret = drm_mode_group_init(dev, group)))
959
	if ((ret = drm_mode_group_init(dev, group)))
961
		return ret;
960
		return ret;
962
 
961
 
963
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
962
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
964
		group->id_list[group->num_crtcs++] = crtc->base.id;
963
		group->id_list[group->num_crtcs++] = crtc->base.id;
965
 
964
 
966
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
965
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
967
		group->id_list[group->num_crtcs + group->num_encoders++] =
966
		group->id_list[group->num_crtcs + group->num_encoders++] =
968
		encoder->base.id;
967
		encoder->base.id;
969
 
968
 
970
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
969
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
971
		group->id_list[group->num_crtcs + group->num_encoders +
970
		group->id_list[group->num_crtcs + group->num_encoders +
972
			       group->num_connectors++] = connector->base.id;
971
			       group->num_connectors++] = connector->base.id;
973
 
972
 
974
	return 0;
973
	return 0;
975
}
974
}
976
EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
975
EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
977
 
976
 
978
/**
977
/**
979
 * drm_mode_config_cleanup - free up DRM mode_config info
978
 * drm_mode_config_cleanup - free up DRM mode_config info
980
 * @dev: DRM device
979
 * @dev: DRM device
981
 *
980
 *
982
 * LOCKING:
981
 * LOCKING:
983
 * Caller must hold mode config lock.
982
 * Caller must hold mode config lock.
984
 *
983
 *
985
 * Free up all the connectors and CRTCs associated with this DRM device, then
984
 * Free up all the connectors and CRTCs associated with this DRM device, then
986
 * free up the framebuffers and associated buffer objects.
985
 * free up the framebuffers and associated buffer objects.
987
 *
986
 *
988
 * FIXME: cleanup any dangling user buffer objects too
987
 * FIXME: cleanup any dangling user buffer objects too
989
 */
988
 */
990
void drm_mode_config_cleanup(struct drm_device *dev)
989
void drm_mode_config_cleanup(struct drm_device *dev)
991
{
990
{
992
	struct drm_connector *connector, *ot;
991
	struct drm_connector *connector, *ot;
993
	struct drm_crtc *crtc, *ct;
992
	struct drm_crtc *crtc, *ct;
994
	struct drm_encoder *encoder, *enct;
993
	struct drm_encoder *encoder, *enct;
995
	struct drm_framebuffer *fb, *fbt;
994
	struct drm_framebuffer *fb, *fbt;
996
	struct drm_property *property, *pt;
995
	struct drm_property *property, *pt;
997
	struct drm_plane *plane, *plt;
996
	struct drm_plane *plane, *plt;
998
 
997
 
999
	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
998
	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
1000
				 head) {
999
				 head) {
1001
		encoder->funcs->destroy(encoder);
1000
		encoder->funcs->destroy(encoder);
1002
	}
1001
	}
1003
 
1002
 
1004
	list_for_each_entry_safe(connector, ot,
1003
	list_for_each_entry_safe(connector, ot,
1005
				 &dev->mode_config.connector_list, head) {
1004
				 &dev->mode_config.connector_list, head) {
1006
		connector->funcs->destroy(connector);
1005
		connector->funcs->destroy(connector);
1007
	}
1006
	}
1008
 
1007
 
1009
	list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
1008
	list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
1010
				 head) {
1009
				 head) {
1011
		drm_property_destroy(dev, property);
1010
		drm_property_destroy(dev, property);
1012
	}
1011
	}
1013
 
1012
 
1014
	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
1013
	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
1015
				 head) {
1014
				 head) {
1016
		plane->funcs->destroy(plane);
1015
		plane->funcs->destroy(plane);
1017
	}
1016
	}
1018
 
1017
 
1019
	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1018
	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1020
		crtc->funcs->destroy(crtc);
1019
		crtc->funcs->destroy(crtc);
1021
	}
1020
	}
1022
 
1021
 
1023
	idr_remove_all(&dev->mode_config.crtc_idr);
1022
	idr_remove_all(&dev->mode_config.crtc_idr);
1024
	idr_destroy(&dev->mode_config.crtc_idr);
1023
	idr_destroy(&dev->mode_config.crtc_idr);
1025
}
1024
}
1026
EXPORT_SYMBOL(drm_mode_config_cleanup);
1025
EXPORT_SYMBOL(drm_mode_config_cleanup);
1027
 
1026
 
1028
/**
1027
/**
1029
 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
1028
 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
1030
 * @out: drm_mode_modeinfo struct to return to the user
1029
 * @out: drm_mode_modeinfo struct to return to the user
1031
 * @in: drm_display_mode to use
1030
 * @in: drm_display_mode to use
1032
 *
1031
 *
1033
 * LOCKING:
1032
 * LOCKING:
1034
 * None.
1033
 * None.
1035
 *
1034
 *
1036
 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
1035
 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
1037
 * the user.
1036
 * the user.
1038
 */
1037
 */
1039
static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
1038
static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
1040
				      const struct drm_display_mode *in)
1039
				      const struct drm_display_mode *in)
1041
{
1040
{
1042
	WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
1041
	WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
1043
	     in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
1042
	     in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
1044
	     in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
1043
	     in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
1045
	     in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
1044
	     in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
1046
	     in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX,
1045
	     in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX,
1047
	     "timing values too large for mode info\n");
1046
	     "timing values too large for mode info\n");
1048
 
1047
 
1049
	out->clock = in->clock;
1048
	out->clock = in->clock;
1050
	out->hdisplay = in->hdisplay;
1049
	out->hdisplay = in->hdisplay;
1051
	out->hsync_start = in->hsync_start;
1050
	out->hsync_start = in->hsync_start;
1052
	out->hsync_end = in->hsync_end;
1051
	out->hsync_end = in->hsync_end;
1053
	out->htotal = in->htotal;
1052
	out->htotal = in->htotal;
1054
	out->hskew = in->hskew;
1053
	out->hskew = in->hskew;
1055
	out->vdisplay = in->vdisplay;
1054
	out->vdisplay = in->vdisplay;
1056
	out->vsync_start = in->vsync_start;
1055
	out->vsync_start = in->vsync_start;
1057
	out->vsync_end = in->vsync_end;
1056
	out->vsync_end = in->vsync_end;
1058
	out->vtotal = in->vtotal;
1057
	out->vtotal = in->vtotal;
1059
	out->vscan = in->vscan;
1058
	out->vscan = in->vscan;
1060
	out->vrefresh = in->vrefresh;
1059
	out->vrefresh = in->vrefresh;
1061
	out->flags = in->flags;
1060
	out->flags = in->flags;
1062
	out->type = in->type;
1061
	out->type = in->type;
1063
	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1062
	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1064
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1063
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1065
}
1064
}
1066
 
1065
 
1067
/**
1066
/**
1068
 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
1067
 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
1069
 * @out: drm_display_mode to return to the user
1068
 * @out: drm_display_mode to return to the user
1070
 * @in: drm_mode_modeinfo to use
1069
 * @in: drm_mode_modeinfo to use
1071
 *
1070
 *
1072
 * LOCKING:
1071
 * LOCKING:
1073
 * None.
1072
 * None.
1074
 *
1073
 *
1075
 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
1074
 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
1076
 * the caller.
1075
 * the caller.
1077
 *
1076
 *
1078
 * RETURNS:
1077
 * RETURNS:
1079
 * Zero on success, errno on failure.
1078
 * Zero on success, errno on failure.
1080
 */
1079
 */
1081
static int drm_crtc_convert_umode(struct drm_display_mode *out,
1080
static int drm_crtc_convert_umode(struct drm_display_mode *out,
1082
				  const struct drm_mode_modeinfo *in)
1081
				  const struct drm_mode_modeinfo *in)
1083
{
1082
{
1084
	if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
1083
	if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
1085
		return -ERANGE;
1084
		return -ERANGE;
1086
 
1085
 
1087
	out->clock = in->clock;
1086
	out->clock = in->clock;
1088
	out->hdisplay = in->hdisplay;
1087
	out->hdisplay = in->hdisplay;
1089
	out->hsync_start = in->hsync_start;
1088
	out->hsync_start = in->hsync_start;
1090
	out->hsync_end = in->hsync_end;
1089
	out->hsync_end = in->hsync_end;
1091
	out->htotal = in->htotal;
1090
	out->htotal = in->htotal;
1092
	out->hskew = in->hskew;
1091
	out->hskew = in->hskew;
1093
	out->vdisplay = in->vdisplay;
1092
	out->vdisplay = in->vdisplay;
1094
	out->vsync_start = in->vsync_start;
1093
	out->vsync_start = in->vsync_start;
1095
	out->vsync_end = in->vsync_end;
1094
	out->vsync_end = in->vsync_end;
1096
	out->vtotal = in->vtotal;
1095
	out->vtotal = in->vtotal;
1097
	out->vscan = in->vscan;
1096
	out->vscan = in->vscan;
1098
	out->vrefresh = in->vrefresh;
1097
	out->vrefresh = in->vrefresh;
1099
	out->flags = in->flags;
1098
	out->flags = in->flags;
1100
	out->type = in->type;
1099
	out->type = in->type;
1101
	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1100
	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1102
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1101
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1103
 
1102
 
1104
	return 0;
1103
	return 0;
1105
}
1104
}
1106
 
1105
 
1107
 
1106
 
1108
#if 0
1107
#if 0
1109
/**
1108
/**
1110
 * drm_mode_getresources - get graphics configuration
1109
 * drm_mode_getresources - get graphics configuration
1111
 * @inode: inode from the ioctl
1110
 * @inode: inode from the ioctl
1112
 * @filp: file * from the ioctl
1111
 * @filp: file * from the ioctl
1113
 * @cmd: cmd from ioctl
1112
 * @cmd: cmd from ioctl
1114
 * @arg: arg from ioctl
1113
 * @arg: arg from ioctl
1115
 *
1114
 *
1116
 * LOCKING:
1115
 * LOCKING:
1117
 * Takes mode config lock.
1116
 * Takes mode config lock.
1118
 *
1117
 *
1119
 * Construct a set of configuration description structures and return
1118
 * Construct a set of configuration description structures and return
1120
 * them to the user, including CRTC, connector and framebuffer configuration.
1119
 * them to the user, including CRTC, connector and framebuffer configuration.
1121
 *
1120
 *
1122
 * Called by the user via ioctl.
1121
 * Called by the user via ioctl.
1123
 *
1122
 *
1124
 * RETURNS:
1123
 * RETURNS:
1125
 * Zero on success, errno on failure.
1124
 * Zero on success, errno on failure.
1126
 */
1125
 */
1127
int drm_mode_getresources(struct drm_device *dev, void *data,
1126
int drm_mode_getresources(struct drm_device *dev, void *data,
1128
			  struct drm_file *file_priv)
1127
			  struct drm_file *file_priv)
1129
{
1128
{
1130
	struct drm_mode_card_res *card_res = data;
1129
	struct drm_mode_card_res *card_res = data;
1131
	struct list_head *lh;
1130
	struct list_head *lh;
1132
	struct drm_framebuffer *fb;
1131
	struct drm_framebuffer *fb;
1133
	struct drm_connector *connector;
1132
	struct drm_connector *connector;
1134
	struct drm_crtc *crtc;
1133
	struct drm_crtc *crtc;
1135
	struct drm_encoder *encoder;
1134
	struct drm_encoder *encoder;
1136
	int ret = 0;
1135
	int ret = 0;
1137
	int connector_count = 0;
1136
	int connector_count = 0;
1138
	int crtc_count = 0;
1137
	int crtc_count = 0;
1139
	int fb_count = 0;
1138
	int fb_count = 0;
1140
	int encoder_count = 0;
1139
	int encoder_count = 0;
1141
	int copied = 0, i;
1140
	int copied = 0, i;
1142
	uint32_t __user *fb_id;
1141
	uint32_t __user *fb_id;
1143
	uint32_t __user *crtc_id;
1142
	uint32_t __user *crtc_id;
1144
	uint32_t __user *connector_id;
1143
	uint32_t __user *connector_id;
1145
	uint32_t __user *encoder_id;
1144
	uint32_t __user *encoder_id;
1146
	struct drm_mode_group *mode_group;
1145
	struct drm_mode_group *mode_group;
1147
 
1146
 
1148
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1147
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1149
		return -EINVAL;
1148
		return -EINVAL;
1150
 
1149
 
1151
	mutex_lock(&dev->mode_config.mutex);
1150
	mutex_lock(&dev->mode_config.mutex);
1152
 
1151
 
1153
	/*
1152
	/*
1154
	 * For the non-control nodes we need to limit the list of resources
1153
	 * For the non-control nodes we need to limit the list of resources
1155
	 * by IDs in the group list for this node
1154
	 * by IDs in the group list for this node
1156
	 */
1155
	 */
1157
	list_for_each(lh, &file_priv->fbs)
1156
	list_for_each(lh, &file_priv->fbs)
1158
		fb_count++;
1157
		fb_count++;
1159
 
1158
 
1160
	mode_group = &file_priv->master->minor->mode_group;
1159
	mode_group = &file_priv->master->minor->mode_group;
1161
	if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1160
	if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1162
 
1161
 
1163
		list_for_each(lh, &dev->mode_config.crtc_list)
1162
		list_for_each(lh, &dev->mode_config.crtc_list)
1164
			crtc_count++;
1163
			crtc_count++;
1165
 
1164
 
1166
		list_for_each(lh, &dev->mode_config.connector_list)
1165
		list_for_each(lh, &dev->mode_config.connector_list)
1167
			connector_count++;
1166
			connector_count++;
1168
 
1167
 
1169
		list_for_each(lh, &dev->mode_config.encoder_list)
1168
		list_for_each(lh, &dev->mode_config.encoder_list)
1170
			encoder_count++;
1169
			encoder_count++;
1171
	} else {
1170
	} else {
1172
 
1171
 
1173
		crtc_count = mode_group->num_crtcs;
1172
		crtc_count = mode_group->num_crtcs;
1174
		connector_count = mode_group->num_connectors;
1173
		connector_count = mode_group->num_connectors;
1175
		encoder_count = mode_group->num_encoders;
1174
		encoder_count = mode_group->num_encoders;
1176
	}
1175
	}
1177
 
1176
 
1178
	card_res->max_height = dev->mode_config.max_height;
1177
	card_res->max_height = dev->mode_config.max_height;
1179
	card_res->min_height = dev->mode_config.min_height;
1178
	card_res->min_height = dev->mode_config.min_height;
1180
	card_res->max_width = dev->mode_config.max_width;
1179
	card_res->max_width = dev->mode_config.max_width;
1181
	card_res->min_width = dev->mode_config.min_width;
1180
	card_res->min_width = dev->mode_config.min_width;
1182
 
1181
 
1183
	/* handle this in 4 parts */
1182
	/* handle this in 4 parts */
1184
	/* FBs */
1183
	/* FBs */
1185
	if (card_res->count_fbs >= fb_count) {
1184
	if (card_res->count_fbs >= fb_count) {
1186
		copied = 0;
1185
		copied = 0;
1187
		fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
1186
		fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
1188
		list_for_each_entry(fb, &file_priv->fbs, filp_head) {
1187
		list_for_each_entry(fb, &file_priv->fbs, filp_head) {
1189
			if (put_user(fb->base.id, fb_id + copied)) {
1188
			if (put_user(fb->base.id, fb_id + copied)) {
1190
				ret = -EFAULT;
1189
				ret = -EFAULT;
1191
				goto out;
1190
				goto out;
1192
			}
1191
			}
1193
			copied++;
1192
			copied++;
1194
		}
1193
		}
1195
	}
1194
	}
1196
	card_res->count_fbs = fb_count;
1195
	card_res->count_fbs = fb_count;
1197
 
1196
 
1198
	/* CRTCs */
1197
	/* CRTCs */
1199
	if (card_res->count_crtcs >= crtc_count) {
1198
	if (card_res->count_crtcs >= crtc_count) {
1200
		copied = 0;
1199
		copied = 0;
1201
		crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
1200
		crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
1202
		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1201
		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1203
			list_for_each_entry(crtc, &dev->mode_config.crtc_list,
1202
			list_for_each_entry(crtc, &dev->mode_config.crtc_list,
1204
					    head) {
1203
					    head) {
1205
				DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1204
				DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1206
				if (put_user(crtc->base.id, crtc_id + copied)) {
1205
				if (put_user(crtc->base.id, crtc_id + copied)) {
1207
					ret = -EFAULT;
1206
					ret = -EFAULT;
1208
					goto out;
1207
					goto out;
1209
				}
1208
				}
1210
				copied++;
1209
				copied++;
1211
			}
1210
			}
1212
		} else {
1211
		} else {
1213
			for (i = 0; i < mode_group->num_crtcs; i++) {
1212
			for (i = 0; i < mode_group->num_crtcs; i++) {
1214
				if (put_user(mode_group->id_list[i],
1213
				if (put_user(mode_group->id_list[i],
1215
					     crtc_id + copied)) {
1214
					     crtc_id + copied)) {
1216
					ret = -EFAULT;
1215
					ret = -EFAULT;
1217
					goto out;
1216
					goto out;
1218
				}
1217
				}
1219
				copied++;
1218
				copied++;
1220
			}
1219
			}
1221
		}
1220
		}
1222
	}
1221
	}
1223
	card_res->count_crtcs = crtc_count;
1222
	card_res->count_crtcs = crtc_count;
1224
 
1223
 
1225
	/* Encoders */
1224
	/* Encoders */
1226
	if (card_res->count_encoders >= encoder_count) {
1225
	if (card_res->count_encoders >= encoder_count) {
1227
		copied = 0;
1226
		copied = 0;
1228
		encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
1227
		encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
1229
		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1228
		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1230
			list_for_each_entry(encoder,
1229
			list_for_each_entry(encoder,
1231
					    &dev->mode_config.encoder_list,
1230
					    &dev->mode_config.encoder_list,
1232
					    head) {
1231
					    head) {
1233
				DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
1232
				DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
1234
						drm_get_encoder_name(encoder));
1233
						drm_get_encoder_name(encoder));
1235
				if (put_user(encoder->base.id, encoder_id +
1234
				if (put_user(encoder->base.id, encoder_id +
1236
					     copied)) {
1235
					     copied)) {
1237
					ret = -EFAULT;
1236
					ret = -EFAULT;
1238
					goto out;
1237
					goto out;
1239
				}
1238
				}
1240
				copied++;
1239
				copied++;
1241
			}
1240
			}
1242
		} else {
1241
		} else {
1243
			for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
1242
			for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
1244
				if (put_user(mode_group->id_list[i],
1243
				if (put_user(mode_group->id_list[i],
1245
					     encoder_id + copied)) {
1244
					     encoder_id + copied)) {
1246
					ret = -EFAULT;
1245
					ret = -EFAULT;
1247
					goto out;
1246
					goto out;
1248
				}
1247
				}
1249
				copied++;
1248
				copied++;
1250
			}
1249
			}
1251
 
1250
 
1252
		}
1251
		}
1253
	}
1252
	}
1254
	card_res->count_encoders = encoder_count;
1253
	card_res->count_encoders = encoder_count;
1255
 
1254
 
1256
	/* Connectors */
1255
	/* Connectors */
1257
	if (card_res->count_connectors >= connector_count) {
1256
	if (card_res->count_connectors >= connector_count) {
1258
		copied = 0;
1257
		copied = 0;
1259
		connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
1258
		connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
1260
		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1259
		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1261
			list_for_each_entry(connector,
1260
			list_for_each_entry(connector,
1262
					    &dev->mode_config.connector_list,
1261
					    &dev->mode_config.connector_list,
1263
					    head) {
1262
					    head) {
1264
				DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1263
				DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1265
					connector->base.id,
1264
					connector->base.id,
1266
					drm_get_connector_name(connector));
1265
					drm_get_connector_name(connector));
1267
				if (put_user(connector->base.id,
1266
				if (put_user(connector->base.id,
1268
					     connector_id + copied)) {
1267
					     connector_id + copied)) {
1269
					ret = -EFAULT;
1268
					ret = -EFAULT;
1270
					goto out;
1269
					goto out;
1271
				}
1270
				}
1272
				copied++;
1271
				copied++;
1273
			}
1272
			}
1274
		} else {
1273
		} else {
1275
			int start = mode_group->num_crtcs +
1274
			int start = mode_group->num_crtcs +
1276
				mode_group->num_encoders;
1275
				mode_group->num_encoders;
1277
			for (i = start; i < start + mode_group->num_connectors; i++) {
1276
			for (i = start; i < start + mode_group->num_connectors; i++) {
1278
				if (put_user(mode_group->id_list[i],
1277
				if (put_user(mode_group->id_list[i],
1279
					     connector_id + copied)) {
1278
					     connector_id + copied)) {
1280
					ret = -EFAULT;
1279
					ret = -EFAULT;
1281
					goto out;
1280
					goto out;
1282
				}
1281
				}
1283
				copied++;
1282
				copied++;
1284
			}
1283
			}
1285
		}
1284
		}
1286
	}
1285
	}
1287
	card_res->count_connectors = connector_count;
1286
	card_res->count_connectors = connector_count;
1288
 
1287
 
1289
	DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
1288
	DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
1290
		  card_res->count_connectors, card_res->count_encoders);
1289
		  card_res->count_connectors, card_res->count_encoders);
1291
 
1290
 
1292
out:
1291
out:
1293
	mutex_unlock(&dev->mode_config.mutex);
1292
	mutex_unlock(&dev->mode_config.mutex);
1294
	return ret;
1293
	return ret;
1295
}
1294
}
1296
 
1295
 
1297
/**
1296
/**
1298
 * drm_mode_getcrtc - get CRTC configuration
1297
 * drm_mode_getcrtc - get CRTC configuration
1299
 * @inode: inode from the ioctl
1298
 * @inode: inode from the ioctl
1300
 * @filp: file * from the ioctl
1299
 * @filp: file * from the ioctl
1301
 * @cmd: cmd from ioctl
1300
 * @cmd: cmd from ioctl
1302
 * @arg: arg from ioctl
1301
 * @arg: arg from ioctl
1303
 *
1302
 *
1304
 * LOCKING:
1303
 * LOCKING:
1305
 * Takes mode config lock.
1304
 * Takes mode config lock.
1306
 *
1305
 *
1307
 * Construct a CRTC configuration structure to return to the user.
1306
 * Construct a CRTC configuration structure to return to the user.
1308
 *
1307
 *
1309
 * Called by the user via ioctl.
1308
 * Called by the user via ioctl.
1310
 *
1309
 *
1311
 * RETURNS:
1310
 * RETURNS:
1312
 * Zero on success, errno on failure.
1311
 * Zero on success, errno on failure.
1313
 */
1312
 */
1314
int drm_mode_getcrtc(struct drm_device *dev,
1313
int drm_mode_getcrtc(struct drm_device *dev,
1315
		     void *data, struct drm_file *file_priv)
1314
		     void *data, struct drm_file *file_priv)
1316
{
1315
{
1317
	struct drm_mode_crtc *crtc_resp = data;
1316
	struct drm_mode_crtc *crtc_resp = data;
1318
	struct drm_crtc *crtc;
1317
	struct drm_crtc *crtc;
1319
	struct drm_mode_object *obj;
1318
	struct drm_mode_object *obj;
1320
	int ret = 0;
1319
	int ret = 0;
1321
 
1320
 
1322
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1321
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1323
		return -EINVAL;
1322
		return -EINVAL;
1324
 
1323
 
1325
	mutex_lock(&dev->mode_config.mutex);
1324
	mutex_lock(&dev->mode_config.mutex);
1326
 
1325
 
1327
	obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
1326
	obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
1328
				   DRM_MODE_OBJECT_CRTC);
1327
				   DRM_MODE_OBJECT_CRTC);
1329
	if (!obj) {
1328
	if (!obj) {
1330
		ret = -EINVAL;
1329
		ret = -EINVAL;
1331
		goto out;
1330
		goto out;
1332
	}
1331
	}
1333
	crtc = obj_to_crtc(obj);
1332
	crtc = obj_to_crtc(obj);
1334
 
1333
 
1335
	crtc_resp->x = crtc->x;
1334
	crtc_resp->x = crtc->x;
1336
	crtc_resp->y = crtc->y;
1335
	crtc_resp->y = crtc->y;
1337
	crtc_resp->gamma_size = crtc->gamma_size;
1336
	crtc_resp->gamma_size = crtc->gamma_size;
1338
	if (crtc->fb)
1337
	if (crtc->fb)
1339
		crtc_resp->fb_id = crtc->fb->base.id;
1338
		crtc_resp->fb_id = crtc->fb->base.id;
1340
	else
1339
	else
1341
		crtc_resp->fb_id = 0;
1340
		crtc_resp->fb_id = 0;
1342
 
1341
 
1343
	if (crtc->enabled) {
1342
	if (crtc->enabled) {
1344
 
1343
 
1345
		drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
1344
		drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
1346
		crtc_resp->mode_valid = 1;
1345
		crtc_resp->mode_valid = 1;
1347
 
1346
 
1348
	} else {
1347
	} else {
1349
		crtc_resp->mode_valid = 0;
1348
		crtc_resp->mode_valid = 0;
1350
	}
1349
	}
1351
 
1350
 
1352
out:
1351
out:
1353
	mutex_unlock(&dev->mode_config.mutex);
1352
	mutex_unlock(&dev->mode_config.mutex);
1354
	return ret;
1353
	return ret;
1355
}
1354
}
1356
 
1355
 
1357
/**
1356
/**
1358
 * drm_mode_getconnector - get connector configuration
1357
 * drm_mode_getconnector - get connector configuration
1359
 * @inode: inode from the ioctl
1358
 * @inode: inode from the ioctl
1360
 * @filp: file * from the ioctl
1359
 * @filp: file * from the ioctl
1361
 * @cmd: cmd from ioctl
1360
 * @cmd: cmd from ioctl
1362
 * @arg: arg from ioctl
1361
 * @arg: arg from ioctl
1363
 *
1362
 *
1364
 * LOCKING:
1363
 * LOCKING:
1365
 * Takes mode config lock.
1364
 * Takes mode config lock.
1366
 *
1365
 *
1367
 * Construct a connector configuration structure to return to the user.
1366
 * Construct a connector configuration structure to return to the user.
1368
 *
1367
 *
1369
 * Called by the user via ioctl.
1368
 * Called by the user via ioctl.
1370
 *
1369
 *
1371
 * RETURNS:
1370
 * RETURNS:
1372
 * Zero on success, errno on failure.
1371
 * Zero on success, errno on failure.
1373
 */
1372
 */
1374
int drm_mode_getconnector(struct drm_device *dev, void *data,
1373
int drm_mode_getconnector(struct drm_device *dev, void *data,
1375
			  struct drm_file *file_priv)
1374
			  struct drm_file *file_priv)
1376
{
1375
{
1377
	struct drm_mode_get_connector *out_resp = data;
1376
	struct drm_mode_get_connector *out_resp = data;
1378
	struct drm_mode_object *obj;
1377
	struct drm_mode_object *obj;
1379
	struct drm_connector *connector;
1378
	struct drm_connector *connector;
1380
	struct drm_display_mode *mode;
1379
	struct drm_display_mode *mode;
1381
	int mode_count = 0;
1380
	int mode_count = 0;
1382
	int props_count = 0;
1381
	int props_count = 0;
1383
	int encoders_count = 0;
1382
	int encoders_count = 0;
1384
	int ret = 0;
1383
	int ret = 0;
1385
	int copied = 0;
1384
	int copied = 0;
1386
	int i;
1385
	int i;
1387
	struct drm_mode_modeinfo u_mode;
1386
	struct drm_mode_modeinfo u_mode;
1388
	struct drm_mode_modeinfo __user *mode_ptr;
1387
	struct drm_mode_modeinfo __user *mode_ptr;
1389
	uint32_t __user *prop_ptr;
1388
	uint32_t __user *prop_ptr;
1390
	uint64_t __user *prop_values;
1389
	uint64_t __user *prop_values;
1391
	uint32_t __user *encoder_ptr;
1390
	uint32_t __user *encoder_ptr;
1392
 
1391
 
1393
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1392
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1394
		return -EINVAL;
1393
		return -EINVAL;
1395
 
1394
 
1396
	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1395
	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1397
 
1396
 
1398
	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
1397
	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
1399
 
1398
 
1400
	mutex_lock(&dev->mode_config.mutex);
1399
	mutex_lock(&dev->mode_config.mutex);
1401
 
1400
 
1402
	obj = drm_mode_object_find(dev, out_resp->connector_id,
1401
	obj = drm_mode_object_find(dev, out_resp->connector_id,
1403
				   DRM_MODE_OBJECT_CONNECTOR);
1402
				   DRM_MODE_OBJECT_CONNECTOR);
1404
	if (!obj) {
1403
	if (!obj) {
1405
		ret = -EINVAL;
1404
		ret = -EINVAL;
1406
		goto out;
1405
		goto out;
1407
	}
1406
	}
1408
	connector = obj_to_connector(obj);
1407
	connector = obj_to_connector(obj);
1409
 
1408
 
1410
	props_count = connector->properties.count;
1409
	props_count = connector->properties.count;
1411
 
1410
 
1412
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1411
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1413
		if (connector->encoder_ids[i] != 0) {
1412
		if (connector->encoder_ids[i] != 0) {
1414
			encoders_count++;
1413
			encoders_count++;
1415
		}
1414
		}
1416
	}
1415
	}
1417
 
1416
 
1418
	if (out_resp->count_modes == 0) {
1417
	if (out_resp->count_modes == 0) {
1419
		connector->funcs->fill_modes(connector,
1418
		connector->funcs->fill_modes(connector,
1420
					     dev->mode_config.max_width,
1419
					     dev->mode_config.max_width,
1421
					     dev->mode_config.max_height);
1420
					     dev->mode_config.max_height);
1422
	}
1421
	}
1423
 
1422
 
1424
	/* delayed so we get modes regardless of pre-fill_modes state */
1423
	/* delayed so we get modes regardless of pre-fill_modes state */
1425
	list_for_each_entry(mode, &connector->modes, head)
1424
	list_for_each_entry(mode, &connector->modes, head)
1426
		mode_count++;
1425
		mode_count++;
1427
 
1426
 
1428
	out_resp->connector_id = connector->base.id;
1427
	out_resp->connector_id = connector->base.id;
1429
	out_resp->connector_type = connector->connector_type;
1428
	out_resp->connector_type = connector->connector_type;
1430
	out_resp->connector_type_id = connector->connector_type_id;
1429
	out_resp->connector_type_id = connector->connector_type_id;
1431
	out_resp->mm_width = connector->display_info.width_mm;
1430
	out_resp->mm_width = connector->display_info.width_mm;
1432
	out_resp->mm_height = connector->display_info.height_mm;
1431
	out_resp->mm_height = connector->display_info.height_mm;
1433
	out_resp->subpixel = connector->display_info.subpixel_order;
1432
	out_resp->subpixel = connector->display_info.subpixel_order;
1434
	out_resp->connection = connector->status;
1433
	out_resp->connection = connector->status;
1435
	if (connector->encoder)
1434
	if (connector->encoder)
1436
		out_resp->encoder_id = connector->encoder->base.id;
1435
		out_resp->encoder_id = connector->encoder->base.id;
1437
	else
1436
	else
1438
		out_resp->encoder_id = 0;
1437
		out_resp->encoder_id = 0;
1439
 
1438
 
1440
	/*
1439
	/*
1441
	 * This ioctl is called twice, once to determine how much space is
1440
	 * This ioctl is called twice, once to determine how much space is
1442
	 * needed, and the 2nd time to fill it.
1441
	 * needed, and the 2nd time to fill it.
1443
	 */
1442
	 */
1444
	if ((out_resp->count_modes >= mode_count) && mode_count) {
1443
	if ((out_resp->count_modes >= mode_count) && mode_count) {
1445
		copied = 0;
1444
		copied = 0;
1446
		mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
1445
		mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
1447
		list_for_each_entry(mode, &connector->modes, head) {
1446
		list_for_each_entry(mode, &connector->modes, head) {
1448
			drm_crtc_convert_to_umode(&u_mode, mode);
1447
			drm_crtc_convert_to_umode(&u_mode, mode);
1449
			if (copy_to_user(mode_ptr + copied,
1448
			if (copy_to_user(mode_ptr + copied,
1450
					 &u_mode, sizeof(u_mode))) {
1449
					 &u_mode, sizeof(u_mode))) {
1451
				ret = -EFAULT;
1450
				ret = -EFAULT;
1452
				goto out;
1451
				goto out;
1453
			}
1452
			}
1454
			copied++;
1453
			copied++;
1455
		}
1454
		}
1456
	}
1455
	}
1457
	out_resp->count_modes = mode_count;
1456
	out_resp->count_modes = mode_count;
1458
 
1457
 
1459
	if ((out_resp->count_props >= props_count) && props_count) {
1458
	if ((out_resp->count_props >= props_count) && props_count) {
1460
		copied = 0;
1459
		copied = 0;
1461
		prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr);
1460
		prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr);
1462
		prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr);
1461
		prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr);
1463
		for (i = 0; i < connector->properties.count; i++) {
1462
		for (i = 0; i < connector->properties.count; i++) {
1464
			if (put_user(connector->properties.ids[i],
1463
			if (put_user(connector->properties.ids[i],
1465
					     prop_ptr + copied)) {
1464
					     prop_ptr + copied)) {
1466
					ret = -EFAULT;
1465
					ret = -EFAULT;
1467
					goto out;
1466
					goto out;
1468
				}
1467
				}
1469
 
1468
 
1470
			if (put_user(connector->properties.values[i],
1469
			if (put_user(connector->properties.values[i],
1471
					     prop_values + copied)) {
1470
					     prop_values + copied)) {
1472
					ret = -EFAULT;
1471
					ret = -EFAULT;
1473
					goto out;
1472
					goto out;
1474
				}
1473
				}
1475
				copied++;
1474
				copied++;
1476
			}
1475
			}
1477
		}
1476
		}
1478
	out_resp->count_props = props_count;
1477
	out_resp->count_props = props_count;
1479
 
1478
 
1480
	if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
1479
	if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
1481
		copied = 0;
1480
		copied = 0;
1482
		encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
1481
		encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
1483
		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1482
		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1484
			if (connector->encoder_ids[i] != 0) {
1483
			if (connector->encoder_ids[i] != 0) {
1485
				if (put_user(connector->encoder_ids[i],
1484
				if (put_user(connector->encoder_ids[i],
1486
					     encoder_ptr + copied)) {
1485
					     encoder_ptr + copied)) {
1487
					ret = -EFAULT;
1486
					ret = -EFAULT;
1488
					goto out;
1487
					goto out;
1489
				}
1488
				}
1490
				copied++;
1489
				copied++;
1491
			}
1490
			}
1492
		}
1491
		}
1493
	}
1492
	}
1494
	out_resp->count_encoders = encoders_count;
1493
	out_resp->count_encoders = encoders_count;
1495
 
1494
 
1496
out:
1495
out:
1497
	mutex_unlock(&dev->mode_config.mutex);
1496
	mutex_unlock(&dev->mode_config.mutex);
1498
	return ret;
1497
	return ret;
1499
}
1498
}
1500
 
1499
 
1501
int drm_mode_getencoder(struct drm_device *dev, void *data,
1500
int drm_mode_getencoder(struct drm_device *dev, void *data,
1502
			struct drm_file *file_priv)
1501
			struct drm_file *file_priv)
1503
{
1502
{
1504
	struct drm_mode_get_encoder *enc_resp = data;
1503
	struct drm_mode_get_encoder *enc_resp = data;
1505
	struct drm_mode_object *obj;
1504
	struct drm_mode_object *obj;
1506
	struct drm_encoder *encoder;
1505
	struct drm_encoder *encoder;
1507
	int ret = 0;
1506
	int ret = 0;
1508
 
1507
 
1509
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1508
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1510
		return -EINVAL;
1509
		return -EINVAL;
1511
 
1510
 
1512
	mutex_lock(&dev->mode_config.mutex);
1511
	mutex_lock(&dev->mode_config.mutex);
1513
	obj = drm_mode_object_find(dev, enc_resp->encoder_id,
1512
	obj = drm_mode_object_find(dev, enc_resp->encoder_id,
1514
				   DRM_MODE_OBJECT_ENCODER);
1513
				   DRM_MODE_OBJECT_ENCODER);
1515
	if (!obj) {
1514
	if (!obj) {
1516
		ret = -EINVAL;
1515
		ret = -EINVAL;
1517
		goto out;
1516
		goto out;
1518
	}
1517
	}
1519
	encoder = obj_to_encoder(obj);
1518
	encoder = obj_to_encoder(obj);
1520
 
1519
 
1521
	if (encoder->crtc)
1520
	if (encoder->crtc)
1522
		enc_resp->crtc_id = encoder->crtc->base.id;
1521
		enc_resp->crtc_id = encoder->crtc->base.id;
1523
	else
1522
	else
1524
		enc_resp->crtc_id = 0;
1523
		enc_resp->crtc_id = 0;
1525
	enc_resp->encoder_type = encoder->encoder_type;
1524
	enc_resp->encoder_type = encoder->encoder_type;
1526
	enc_resp->encoder_id = encoder->base.id;
1525
	enc_resp->encoder_id = encoder->base.id;
1527
	enc_resp->possible_crtcs = encoder->possible_crtcs;
1526
	enc_resp->possible_crtcs = encoder->possible_crtcs;
1528
	enc_resp->possible_clones = encoder->possible_clones;
1527
	enc_resp->possible_clones = encoder->possible_clones;
1529
 
1528
 
1530
out:
1529
out:
1531
	mutex_unlock(&dev->mode_config.mutex);
1530
	mutex_unlock(&dev->mode_config.mutex);
1532
	return ret;
1531
	return ret;
1533
}
1532
}
1534
 
1533
 
1535
/**
1534
/**
1536
 * drm_mode_getplane_res - get plane info
1535
 * drm_mode_getplane_res - get plane info
1537
 * @dev: DRM device
1536
 * @dev: DRM device
1538
 * @data: ioctl data
1537
 * @data: ioctl data
1539
 * @file_priv: DRM file info
1538
 * @file_priv: DRM file info
1540
 *
1539
 *
1541
 * LOCKING:
1540
 * LOCKING:
1542
 * Takes mode config lock.
1541
 * Takes mode config lock.
1543
 *
1542
 *
1544
 * Return an plane count and set of IDs.
1543
 * Return an plane count and set of IDs.
1545
 */
1544
 */
1546
int drm_mode_getplane_res(struct drm_device *dev, void *data,
1545
int drm_mode_getplane_res(struct drm_device *dev, void *data,
1547
			    struct drm_file *file_priv)
1546
			    struct drm_file *file_priv)
1548
{
1547
{
1549
	struct drm_mode_get_plane_res *plane_resp = data;
1548
	struct drm_mode_get_plane_res *plane_resp = data;
1550
	struct drm_mode_config *config;
1549
	struct drm_mode_config *config;
1551
	struct drm_plane *plane;
1550
	struct drm_plane *plane;
1552
	uint32_t __user *plane_ptr;
1551
	uint32_t __user *plane_ptr;
1553
	int copied = 0, ret = 0;
1552
	int copied = 0, ret = 0;
1554
 
1553
 
1555
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1554
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1556
		return -EINVAL;
1555
		return -EINVAL;
1557
 
1556
 
1558
	mutex_lock(&dev->mode_config.mutex);
1557
	mutex_lock(&dev->mode_config.mutex);
1559
	config = &dev->mode_config;
1558
	config = &dev->mode_config;
1560
 
1559
 
1561
	/*
1560
	/*
1562
	 * This ioctl is called twice, once to determine how much space is
1561
	 * This ioctl is called twice, once to determine how much space is
1563
	 * needed, and the 2nd time to fill it.
1562
	 * needed, and the 2nd time to fill it.
1564
	 */
1563
	 */
1565
	if (config->num_plane &&
1564
	if (config->num_plane &&
1566
	    (plane_resp->count_planes >= config->num_plane)) {
1565
	    (plane_resp->count_planes >= config->num_plane)) {
1567
		plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
1566
		plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
1568
 
1567
 
1569
		list_for_each_entry(plane, &config->plane_list, head) {
1568
		list_for_each_entry(plane, &config->plane_list, head) {
1570
			if (put_user(plane->base.id, plane_ptr + copied)) {
1569
			if (put_user(plane->base.id, plane_ptr + copied)) {
1571
				ret = -EFAULT;
1570
				ret = -EFAULT;
1572
				goto out;
1571
				goto out;
1573
			}
1572
			}
1574
			copied++;
1573
			copied++;
1575
		}
1574
		}
1576
	}
1575
	}
1577
	plane_resp->count_planes = config->num_plane;
1576
	plane_resp->count_planes = config->num_plane;
1578
 
1577
 
1579
out:
1578
out:
1580
	mutex_unlock(&dev->mode_config.mutex);
1579
	mutex_unlock(&dev->mode_config.mutex);
1581
	return ret;
1580
	return ret;
1582
}
1581
}
1583
 
1582
 
1584
/**
1583
/**
1585
 * drm_mode_getplane - get plane info
1584
 * drm_mode_getplane - get plane info
1586
 * @dev: DRM device
1585
 * @dev: DRM device
1587
 * @data: ioctl data
1586
 * @data: ioctl data
1588
 * @file_priv: DRM file info
1587
 * @file_priv: DRM file info
1589
 *
1588
 *
1590
 * LOCKING:
1589
 * LOCKING:
1591
 * Takes mode config lock.
1590
 * Takes mode config lock.
1592
 *
1591
 *
1593
 * Return plane info, including formats supported, gamma size, any
1592
 * Return plane info, including formats supported, gamma size, any
1594
 * current fb, etc.
1593
 * current fb, etc.
1595
 */
1594
 */
1596
int drm_mode_getplane(struct drm_device *dev, void *data,
1595
int drm_mode_getplane(struct drm_device *dev, void *data,
1597
			struct drm_file *file_priv)
1596
			struct drm_file *file_priv)
1598
{
1597
{
1599
	struct drm_mode_get_plane *plane_resp = data;
1598
	struct drm_mode_get_plane *plane_resp = data;
1600
	struct drm_mode_object *obj;
1599
	struct drm_mode_object *obj;
1601
	struct drm_plane *plane;
1600
	struct drm_plane *plane;
1602
	uint32_t __user *format_ptr;
1601
	uint32_t __user *format_ptr;
1603
	int ret = 0;
1602
	int ret = 0;
1604
 
1603
 
1605
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1604
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1606
		return -EINVAL;
1605
		return -EINVAL;
1607
 
1606
 
1608
	mutex_lock(&dev->mode_config.mutex);
1607
	mutex_lock(&dev->mode_config.mutex);
1609
	obj = drm_mode_object_find(dev, plane_resp->plane_id,
1608
	obj = drm_mode_object_find(dev, plane_resp->plane_id,
1610
				   DRM_MODE_OBJECT_PLANE);
1609
				   DRM_MODE_OBJECT_PLANE);
1611
	if (!obj) {
1610
	if (!obj) {
1612
		ret = -ENOENT;
1611
		ret = -ENOENT;
1613
		goto out;
1612
		goto out;
1614
	}
1613
	}
1615
	plane = obj_to_plane(obj);
1614
	plane = obj_to_plane(obj);
1616
 
1615
 
1617
	if (plane->crtc)
1616
	if (plane->crtc)
1618
		plane_resp->crtc_id = plane->crtc->base.id;
1617
		plane_resp->crtc_id = plane->crtc->base.id;
1619
	else
1618
	else
1620
		plane_resp->crtc_id = 0;
1619
		plane_resp->crtc_id = 0;
1621
 
1620
 
1622
	if (plane->fb)
1621
	if (plane->fb)
1623
		plane_resp->fb_id = plane->fb->base.id;
1622
		plane_resp->fb_id = plane->fb->base.id;
1624
	else
1623
	else
1625
		plane_resp->fb_id = 0;
1624
		plane_resp->fb_id = 0;
1626
 
1625
 
1627
	plane_resp->plane_id = plane->base.id;
1626
	plane_resp->plane_id = plane->base.id;
1628
	plane_resp->possible_crtcs = plane->possible_crtcs;
1627
	plane_resp->possible_crtcs = plane->possible_crtcs;
1629
	plane_resp->gamma_size = plane->gamma_size;
1628
	plane_resp->gamma_size = plane->gamma_size;
1630
 
1629
 
1631
	/*
1630
	/*
1632
	 * This ioctl is called twice, once to determine how much space is
1631
	 * This ioctl is called twice, once to determine how much space is
1633
	 * needed, and the 2nd time to fill it.
1632
	 * needed, and the 2nd time to fill it.
1634
	 */
1633
	 */
1635
	if (plane->format_count &&
1634
	if (plane->format_count &&
1636
	    (plane_resp->count_format_types >= plane->format_count)) {
1635
	    (plane_resp->count_format_types >= plane->format_count)) {
1637
		format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
1636
		format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
1638
		if (copy_to_user(format_ptr,
1637
		if (copy_to_user(format_ptr,
1639
				 plane->format_types,
1638
				 plane->format_types,
1640
				 sizeof(uint32_t) * plane->format_count)) {
1639
				 sizeof(uint32_t) * plane->format_count)) {
1641
			ret = -EFAULT;
1640
			ret = -EFAULT;
1642
			goto out;
1641
			goto out;
1643
		}
1642
		}
1644
	}
1643
	}
1645
	plane_resp->count_format_types = plane->format_count;
1644
	plane_resp->count_format_types = plane->format_count;
1646
 
1645
 
1647
out:
1646
out:
1648
	mutex_unlock(&dev->mode_config.mutex);
1647
	mutex_unlock(&dev->mode_config.mutex);
1649
	return ret;
1648
	return ret;
1650
}
1649
}
1651
 
1650
 
1652
/**
1651
/**
1653
 * drm_mode_setplane - set up or tear down an plane
1652
 * drm_mode_setplane - set up or tear down an plane
1654
 * @dev: DRM device
1653
 * @dev: DRM device
1655
 * @data: ioctl data*
1654
 * @data: ioctl data*
1656
 * @file_prive: DRM file info
1655
 * @file_prive: DRM file info
1657
 *
1656
 *
1658
 * LOCKING:
1657
 * LOCKING:
1659
 * Takes mode config lock.
1658
 * Takes mode config lock.
1660
 *
1659
 *
1661
 * Set plane info, including placement, fb, scaling, and other factors.
1660
 * Set plane info, including placement, fb, scaling, and other factors.
1662
 * Or pass a NULL fb to disable.
1661
 * Or pass a NULL fb to disable.
1663
 */
1662
 */
1664
int drm_mode_setplane(struct drm_device *dev, void *data,
1663
int drm_mode_setplane(struct drm_device *dev, void *data,
1665
			struct drm_file *file_priv)
1664
			struct drm_file *file_priv)
1666
{
1665
{
1667
	struct drm_mode_set_plane *plane_req = data;
1666
	struct drm_mode_set_plane *plane_req = data;
1668
	struct drm_mode_object *obj;
1667
	struct drm_mode_object *obj;
1669
	struct drm_plane *plane;
1668
	struct drm_plane *plane;
1670
	struct drm_crtc *crtc;
1669
	struct drm_crtc *crtc;
1671
	struct drm_framebuffer *fb;
1670
	struct drm_framebuffer *fb;
1672
	int ret = 0;
1671
	int ret = 0;
1673
	unsigned int fb_width, fb_height;
1672
	unsigned int fb_width, fb_height;
1674
	int i;
1673
	int i;
1675
 
1674
 
1676
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1675
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1677
		return -EINVAL;
1676
		return -EINVAL;
1678
 
1677
 
1679
	mutex_lock(&dev->mode_config.mutex);
1678
	mutex_lock(&dev->mode_config.mutex);
1680
 
1679
 
1681
	/*
1680
	/*
1682
	 * First, find the plane, crtc, and fb objects.  If not available,
1681
	 * First, find the plane, crtc, and fb objects.  If not available,
1683
	 * we don't bother to call the driver.
1682
	 * we don't bother to call the driver.
1684
	 */
1683
	 */
1685
	obj = drm_mode_object_find(dev, plane_req->plane_id,
1684
	obj = drm_mode_object_find(dev, plane_req->plane_id,
1686
				   DRM_MODE_OBJECT_PLANE);
1685
				   DRM_MODE_OBJECT_PLANE);
1687
	if (!obj) {
1686
	if (!obj) {
1688
		DRM_DEBUG_KMS("Unknown plane ID %d\n",
1687
		DRM_DEBUG_KMS("Unknown plane ID %d\n",
1689
			      plane_req->plane_id);
1688
			      plane_req->plane_id);
1690
		ret = -ENOENT;
1689
		ret = -ENOENT;
1691
		goto out;
1690
		goto out;
1692
	}
1691
	}
1693
	plane = obj_to_plane(obj);
1692
	plane = obj_to_plane(obj);
1694
 
1693
 
1695
	/* No fb means shut it down */
1694
	/* No fb means shut it down */
1696
	if (!plane_req->fb_id) {
1695
	if (!plane_req->fb_id) {
1697
		plane->funcs->disable_plane(plane);
1696
		plane->funcs->disable_plane(plane);
1698
		plane->crtc = NULL;
1697
		plane->crtc = NULL;
1699
		plane->fb = NULL;
1698
		plane->fb = NULL;
1700
		goto out;
1699
		goto out;
1701
	}
1700
	}
1702
 
1701
 
1703
	obj = drm_mode_object_find(dev, plane_req->crtc_id,
1702
	obj = drm_mode_object_find(dev, plane_req->crtc_id,
1704
				   DRM_MODE_OBJECT_CRTC);
1703
				   DRM_MODE_OBJECT_CRTC);
1705
	if (!obj) {
1704
	if (!obj) {
1706
		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
1705
		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
1707
			      plane_req->crtc_id);
1706
			      plane_req->crtc_id);
1708
		ret = -ENOENT;
1707
		ret = -ENOENT;
1709
		goto out;
1708
		goto out;
1710
	}
1709
	}
1711
	crtc = obj_to_crtc(obj);
1710
	crtc = obj_to_crtc(obj);
1712
 
1711
 
1713
	obj = drm_mode_object_find(dev, plane_req->fb_id,
1712
	obj = drm_mode_object_find(dev, plane_req->fb_id,
1714
				   DRM_MODE_OBJECT_FB);
1713
				   DRM_MODE_OBJECT_FB);
1715
	if (!obj) {
1714
	if (!obj) {
1716
		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
1715
		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
1717
			      plane_req->fb_id);
1716
			      plane_req->fb_id);
1718
		ret = -ENOENT;
1717
		ret = -ENOENT;
1719
		goto out;
1718
		goto out;
1720
	}
1719
	}
1721
	fb = obj_to_fb(obj);
1720
	fb = obj_to_fb(obj);
1722
 
1721
 
1723
	/* Check whether this plane supports the fb pixel format. */
1722
	/* Check whether this plane supports the fb pixel format. */
1724
	for (i = 0; i < plane->format_count; i++)
1723
	for (i = 0; i < plane->format_count; i++)
1725
		if (fb->pixel_format == plane->format_types[i])
1724
		if (fb->pixel_format == plane->format_types[i])
1726
			break;
1725
			break;
1727
	if (i == plane->format_count) {
1726
	if (i == plane->format_count) {
1728
		DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
1727
		DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
1729
		ret = -EINVAL;
1728
		ret = -EINVAL;
1730
		goto out;
1729
		goto out;
1731
	}
1730
	}
1732
 
1731
 
1733
	fb_width = fb->width << 16;
1732
	fb_width = fb->width << 16;
1734
	fb_height = fb->height << 16;
1733
	fb_height = fb->height << 16;
1735
 
1734
 
1736
	/* Make sure source coordinates are inside the fb. */
1735
	/* Make sure source coordinates are inside the fb. */
1737
	if (plane_req->src_w > fb_width ||
1736
	if (plane_req->src_w > fb_width ||
1738
	    plane_req->src_x > fb_width - plane_req->src_w ||
1737
	    plane_req->src_x > fb_width - plane_req->src_w ||
1739
	    plane_req->src_h > fb_height ||
1738
	    plane_req->src_h > fb_height ||
1740
	    plane_req->src_y > fb_height - plane_req->src_h) {
1739
	    plane_req->src_y > fb_height - plane_req->src_h) {
1741
		DRM_DEBUG_KMS("Invalid source coordinates "
1740
		DRM_DEBUG_KMS("Invalid source coordinates "
1742
			      "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
1741
			      "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
1743
			      plane_req->src_w >> 16,
1742
			      plane_req->src_w >> 16,
1744
			      ((plane_req->src_w & 0xffff) * 15625) >> 10,
1743
			      ((plane_req->src_w & 0xffff) * 15625) >> 10,
1745
			      plane_req->src_h >> 16,
1744
			      plane_req->src_h >> 16,
1746
			      ((plane_req->src_h & 0xffff) * 15625) >> 10,
1745
			      ((plane_req->src_h & 0xffff) * 15625) >> 10,
1747
			      plane_req->src_x >> 16,
1746
			      plane_req->src_x >> 16,
1748
			      ((plane_req->src_x & 0xffff) * 15625) >> 10,
1747
			      ((plane_req->src_x & 0xffff) * 15625) >> 10,
1749
			      plane_req->src_y >> 16,
1748
			      plane_req->src_y >> 16,
1750
			      ((plane_req->src_y & 0xffff) * 15625) >> 10);
1749
			      ((plane_req->src_y & 0xffff) * 15625) >> 10);
1751
		ret = -ENOSPC;
1750
		ret = -ENOSPC;
1752
		goto out;
1751
		goto out;
1753
	}
1752
	}
1754
 
1753
 
1755
	/* Give drivers some help against integer overflows */
1754
	/* Give drivers some help against integer overflows */
1756
	if (plane_req->crtc_w > INT_MAX ||
1755
	if (plane_req->crtc_w > INT_MAX ||
1757
	    plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
1756
	    plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
1758
	    plane_req->crtc_h > INT_MAX ||
1757
	    plane_req->crtc_h > INT_MAX ||
1759
	    plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
1758
	    plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
1760
		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
1759
		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
1761
			      plane_req->crtc_w, plane_req->crtc_h,
1760
			      plane_req->crtc_w, plane_req->crtc_h,
1762
			      plane_req->crtc_x, plane_req->crtc_y);
1761
			      plane_req->crtc_x, plane_req->crtc_y);
1763
		ret = -ERANGE;
1762
		ret = -ERANGE;
1764
		goto out;
1763
		goto out;
1765
	}
1764
	}
1766
 
1765
 
1767
	ret = plane->funcs->update_plane(plane, crtc, fb,
1766
	ret = plane->funcs->update_plane(plane, crtc, fb,
1768
					 plane_req->crtc_x, plane_req->crtc_y,
1767
					 plane_req->crtc_x, plane_req->crtc_y,
1769
					 plane_req->crtc_w, plane_req->crtc_h,
1768
					 plane_req->crtc_w, plane_req->crtc_h,
1770
					 plane_req->src_x, plane_req->src_y,
1769
					 plane_req->src_x, plane_req->src_y,
1771
					 plane_req->src_w, plane_req->src_h);
1770
					 plane_req->src_w, plane_req->src_h);
1772
	if (!ret) {
1771
	if (!ret) {
1773
		plane->crtc = crtc;
1772
		plane->crtc = crtc;
1774
		plane->fb = fb;
1773
		plane->fb = fb;
1775
	}
1774
	}
1776
 
1775
 
1777
out:
1776
out:
1778
	mutex_unlock(&dev->mode_config.mutex);
1777
	mutex_unlock(&dev->mode_config.mutex);
1779
 
1778
 
1780
	return ret;
1779
	return ret;
1781
}
1780
}
1782
 
1781
 
1783
/**
1782
/**
1784
 * drm_mode_setcrtc - set CRTC configuration
1783
 * drm_mode_setcrtc - set CRTC configuration
1785
 * @inode: inode from the ioctl
1784
 * @inode: inode from the ioctl
1786
 * @filp: file * from the ioctl
1785
 * @filp: file * from the ioctl
1787
 * @cmd: cmd from ioctl
1786
 * @cmd: cmd from ioctl
1788
 * @arg: arg from ioctl
1787
 * @arg: arg from ioctl
1789
 *
1788
 *
1790
 * LOCKING:
1789
 * LOCKING:
1791
 * Takes mode config lock.
1790
 * Takes mode config lock.
1792
 *
1791
 *
1793
 * Build a new CRTC configuration based on user request.
1792
 * Build a new CRTC configuration based on user request.
1794
 *
1793
 *
1795
 * Called by the user via ioctl.
1794
 * Called by the user via ioctl.
1796
 *
1795
 *
1797
 * RETURNS:
1796
 * RETURNS:
1798
 * Zero on success, errno on failure.
1797
 * Zero on success, errno on failure.
1799
 */
1798
 */
1800
int drm_mode_setcrtc(struct drm_device *dev, void *data,
1799
int drm_mode_setcrtc(struct drm_device *dev, void *data,
1801
		     struct drm_file *file_priv)
1800
		     struct drm_file *file_priv)
1802
{
1801
{
1803
	struct drm_mode_config *config = &dev->mode_config;
1802
	struct drm_mode_config *config = &dev->mode_config;
1804
	struct drm_mode_crtc *crtc_req = data;
1803
	struct drm_mode_crtc *crtc_req = data;
1805
	struct drm_mode_object *obj;
1804
	struct drm_mode_object *obj;
1806
	struct drm_crtc *crtc;
1805
	struct drm_crtc *crtc;
1807
	struct drm_connector **connector_set = NULL, *connector;
1806
	struct drm_connector **connector_set = NULL, *connector;
1808
	struct drm_framebuffer *fb = NULL;
1807
	struct drm_framebuffer *fb = NULL;
1809
	struct drm_display_mode *mode = NULL;
1808
	struct drm_display_mode *mode = NULL;
1810
	struct drm_mode_set set;
1809
	struct drm_mode_set set;
1811
	uint32_t __user *set_connectors_ptr;
1810
	uint32_t __user *set_connectors_ptr;
1812
	int ret;
1811
	int ret;
1813
	int i;
1812
	int i;
1814
 
1813
 
1815
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1814
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1816
		return -EINVAL;
1815
		return -EINVAL;
1817
 
1816
 
1818
	/* For some reason crtc x/y offsets are signed internally. */
1817
	/* For some reason crtc x/y offsets are signed internally. */
1819
	if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX)
1818
	if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX)
1820
		return -ERANGE;
1819
		return -ERANGE;
1821
 
1820
 
1822
	mutex_lock(&dev->mode_config.mutex);
1821
	mutex_lock(&dev->mode_config.mutex);
1823
	obj = drm_mode_object_find(dev, crtc_req->crtc_id,
1822
	obj = drm_mode_object_find(dev, crtc_req->crtc_id,
1824
				   DRM_MODE_OBJECT_CRTC);
1823
				   DRM_MODE_OBJECT_CRTC);
1825
	if (!obj) {
1824
	if (!obj) {
1826
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
1825
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
1827
		ret = -EINVAL;
1826
		ret = -EINVAL;
1828
		goto out;
1827
		goto out;
1829
	}
1828
	}
1830
	crtc = obj_to_crtc(obj);
1829
	crtc = obj_to_crtc(obj);
1831
	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1830
	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1832
 
1831
 
1833
	if (crtc_req->mode_valid) {
1832
	if (crtc_req->mode_valid) {
1834
		int hdisplay, vdisplay;
1833
		int hdisplay, vdisplay;
1835
		/* If we have a mode we need a framebuffer. */
1834
		/* If we have a mode we need a framebuffer. */
1836
		/* If we pass -1, set the mode with the currently bound fb */
1835
		/* If we pass -1, set the mode with the currently bound fb */
1837
		if (crtc_req->fb_id == -1) {
1836
		if (crtc_req->fb_id == -1) {
1838
			if (!crtc->fb) {
1837
			if (!crtc->fb) {
1839
				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
1838
				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
1840
				ret = -EINVAL;
1839
				ret = -EINVAL;
1841
				goto out;
1840
				goto out;
1842
			}
1841
			}
1843
					fb = crtc->fb;
1842
					fb = crtc->fb;
1844
		} else {
1843
		} else {
1845
			obj = drm_mode_object_find(dev, crtc_req->fb_id,
1844
			obj = drm_mode_object_find(dev, crtc_req->fb_id,
1846
						   DRM_MODE_OBJECT_FB);
1845
						   DRM_MODE_OBJECT_FB);
1847
			if (!obj) {
1846
			if (!obj) {
1848
				DRM_DEBUG_KMS("Unknown FB ID%d\n",
1847
				DRM_DEBUG_KMS("Unknown FB ID%d\n",
1849
						crtc_req->fb_id);
1848
						crtc_req->fb_id);
1850
				ret = -EINVAL;
1849
				ret = -EINVAL;
1851
				goto out;
1850
				goto out;
1852
			}
1851
			}
1853
			fb = obj_to_fb(obj);
1852
			fb = obj_to_fb(obj);
1854
		}
1853
		}
1855
 
1854
 
1856
		mode = drm_mode_create(dev);
1855
		mode = drm_mode_create(dev);
1857
		if (!mode) {
1856
		if (!mode) {
1858
			ret = -ENOMEM;
1857
			ret = -ENOMEM;
1859
			goto out;
1858
			goto out;
1860
		}
1859
		}
1861
 
1860
 
1862
		ret = drm_crtc_convert_umode(mode, &crtc_req->mode);
1861
		ret = drm_crtc_convert_umode(mode, &crtc_req->mode);
1863
		if (ret) {
1862
		if (ret) {
1864
			DRM_DEBUG_KMS("Invalid mode\n");
1863
			DRM_DEBUG_KMS("Invalid mode\n");
1865
			goto out;
1864
			goto out;
1866
		}
1865
		}
1867
 
1866
 
1868
		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1867
		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1869
 
1868
 
1870
		hdisplay = mode->hdisplay;
1869
		hdisplay = mode->hdisplay;
1871
		vdisplay = mode->vdisplay;
1870
		vdisplay = mode->vdisplay;
1872
 
1871
 
1873
		if (crtc->invert_dimensions)
1872
		if (crtc->invert_dimensions)
1874
			swap(hdisplay, vdisplay);
1873
			swap(hdisplay, vdisplay);
1875
 
1874
 
1876
		if (hdisplay > fb->width ||
1875
		if (hdisplay > fb->width ||
1877
		    vdisplay > fb->height ||
1876
		    vdisplay > fb->height ||
1878
		    crtc_req->x > fb->width - hdisplay ||
1877
		    crtc_req->x > fb->width - hdisplay ||
1879
		    crtc_req->y > fb->height - vdisplay) {
1878
		    crtc_req->y > fb->height - vdisplay) {
1880
			DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
1879
			DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
1881
				      fb->width, fb->height,
1880
				      fb->width, fb->height,
1882
				      hdisplay, vdisplay, crtc_req->x, crtc_req->y,
1881
				      hdisplay, vdisplay, crtc_req->x, crtc_req->y,
1883
				      crtc->invert_dimensions ? " (inverted)" : "");
1882
				      crtc->invert_dimensions ? " (inverted)" : "");
1884
			ret = -ENOSPC;
1883
			ret = -ENOSPC;
1885
			goto out;
1884
			goto out;
1886
		}
1885
		}
1887
	}
1886
	}
1888
 
1887
 
1889
	if (crtc_req->count_connectors == 0 && mode) {
1888
	if (crtc_req->count_connectors == 0 && mode) {
1890
		DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
1889
		DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
1891
		ret = -EINVAL;
1890
		ret = -EINVAL;
1892
		goto out;
1891
		goto out;
1893
	}
1892
	}
1894
 
1893
 
1895
	if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
1894
	if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
1896
		DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
1895
		DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
1897
			  crtc_req->count_connectors);
1896
			  crtc_req->count_connectors);
1898
		ret = -EINVAL;
1897
		ret = -EINVAL;
1899
		goto out;
1898
		goto out;
1900
	}
1899
	}
1901
 
1900
 
1902
	if (crtc_req->count_connectors > 0) {
1901
	if (crtc_req->count_connectors > 0) {
1903
		u32 out_id;
1902
		u32 out_id;
1904
 
1903
 
1905
		/* Avoid unbounded kernel memory allocation */
1904
		/* Avoid unbounded kernel memory allocation */
1906
		if (crtc_req->count_connectors > config->num_connector) {
1905
		if (crtc_req->count_connectors > config->num_connector) {
1907
			ret = -EINVAL;
1906
			ret = -EINVAL;
1908
			goto out;
1907
			goto out;
1909
		}
1908
		}
1910
 
1909
 
1911
		connector_set = kmalloc(crtc_req->count_connectors *
1910
		connector_set = kmalloc(crtc_req->count_connectors *
1912
					sizeof(struct drm_connector *),
1911
					sizeof(struct drm_connector *),
1913
					GFP_KERNEL);
1912
					GFP_KERNEL);
1914
		if (!connector_set) {
1913
		if (!connector_set) {
1915
			ret = -ENOMEM;
1914
			ret = -ENOMEM;
1916
			goto out;
1915
			goto out;
1917
		}
1916
		}
1918
 
1917
 
1919
		for (i = 0; i < crtc_req->count_connectors; i++) {
1918
		for (i = 0; i < crtc_req->count_connectors; i++) {
1920
			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
1919
			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
1921
			if (get_user(out_id, &set_connectors_ptr[i])) {
1920
			if (get_user(out_id, &set_connectors_ptr[i])) {
1922
				ret = -EFAULT;
1921
				ret = -EFAULT;
1923
				goto out;
1922
				goto out;
1924
			}
1923
			}
1925
 
1924
 
1926
			obj = drm_mode_object_find(dev, out_id,
1925
			obj = drm_mode_object_find(dev, out_id,
1927
						   DRM_MODE_OBJECT_CONNECTOR);
1926
						   DRM_MODE_OBJECT_CONNECTOR);
1928
			if (!obj) {
1927
			if (!obj) {
1929
				DRM_DEBUG_KMS("Connector id %d unknown\n",
1928
				DRM_DEBUG_KMS("Connector id %d unknown\n",
1930
						out_id);
1929
						out_id);
1931
				ret = -EINVAL;
1930
				ret = -EINVAL;
1932
				goto out;
1931
				goto out;
1933
			}
1932
			}
1934
			connector = obj_to_connector(obj);
1933
			connector = obj_to_connector(obj);
1935
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1934
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1936
					connector->base.id,
1935
					connector->base.id,
1937
					drm_get_connector_name(connector));
1936
					drm_get_connector_name(connector));
1938
 
1937
 
1939
			connector_set[i] = connector;
1938
			connector_set[i] = connector;
1940
		}
1939
		}
1941
	}
1940
	}
1942
 
1941
 
1943
	set.crtc = crtc;
1942
	set.crtc = crtc;
1944
	set.x = crtc_req->x;
1943
	set.x = crtc_req->x;
1945
	set.y = crtc_req->y;
1944
	set.y = crtc_req->y;
1946
	set.mode = mode;
1945
	set.mode = mode;
1947
	set.connectors = connector_set;
1946
	set.connectors = connector_set;
1948
	set.num_connectors = crtc_req->count_connectors;
1947
	set.num_connectors = crtc_req->count_connectors;
1949
	set.fb = fb;
1948
	set.fb = fb;
1950
	ret = crtc->funcs->set_config(&set);
1949
	ret = crtc->funcs->set_config(&set);
1951
 
1950
 
1952
out:
1951
out:
1953
	kfree(connector_set);
1952
	kfree(connector_set);
1954
	drm_mode_destroy(dev, mode);
1953
	drm_mode_destroy(dev, mode);
1955
	mutex_unlock(&dev->mode_config.mutex);
1954
	mutex_unlock(&dev->mode_config.mutex);
1956
	return ret;
1955
	return ret;
1957
}
1956
}
1958
 
1957
 
1959
int drm_mode_cursor_ioctl(struct drm_device *dev,
1958
int drm_mode_cursor_ioctl(struct drm_device *dev,
1960
			void *data, struct drm_file *file_priv)
1959
			void *data, struct drm_file *file_priv)
1961
{
1960
{
1962
	struct drm_mode_cursor *req = data;
1961
	struct drm_mode_cursor *req = data;
1963
	struct drm_mode_object *obj;
1962
	struct drm_mode_object *obj;
1964
	struct drm_crtc *crtc;
1963
	struct drm_crtc *crtc;
1965
	int ret = 0;
1964
	int ret = 0;
1966
 
1965
 
1967
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1966
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
1968
		return -EINVAL;
1967
		return -EINVAL;
1969
 
1968
 
1970
	if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
1969
	if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
1971
		return -EINVAL;
1970
		return -EINVAL;
1972
 
1971
 
1973
	mutex_lock(&dev->mode_config.mutex);
1972
	mutex_lock(&dev->mode_config.mutex);
1974
	obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
1973
	obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
1975
	if (!obj) {
1974
	if (!obj) {
1976
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
1975
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
1977
		ret = -EINVAL;
1976
		ret = -EINVAL;
1978
		goto out;
1977
		goto out;
1979
	}
1978
	}
1980
	crtc = obj_to_crtc(obj);
1979
	crtc = obj_to_crtc(obj);
1981
 
1980
 
1982
	if (req->flags & DRM_MODE_CURSOR_BO) {
1981
	if (req->flags & DRM_MODE_CURSOR_BO) {
1983
		if (!crtc->funcs->cursor_set) {
1982
		if (!crtc->funcs->cursor_set) {
1984
			ret = -ENXIO;
1983
			ret = -ENXIO;
1985
			goto out;
1984
			goto out;
1986
		}
1985
		}
1987
		/* Turns off the cursor if handle is 0 */
1986
		/* Turns off the cursor if handle is 0 */
1988
		ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
1987
		ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
1989
					      req->width, req->height);
1988
					      req->width, req->height);
1990
	}
1989
	}
1991
 
1990
 
1992
	if (req->flags & DRM_MODE_CURSOR_MOVE) {
1991
	if (req->flags & DRM_MODE_CURSOR_MOVE) {
1993
		if (crtc->funcs->cursor_move) {
1992
		if (crtc->funcs->cursor_move) {
1994
			ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
1993
			ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
1995
		} else {
1994
		} else {
1996
			ret = -EFAULT;
1995
			ret = -EFAULT;
1997
			goto out;
1996
			goto out;
1998
		}
1997
		}
1999
	}
1998
	}
2000
out:
1999
out:
2001
	mutex_unlock(&dev->mode_config.mutex);
2000
	mutex_unlock(&dev->mode_config.mutex);
2002
	return ret;
2001
	return ret;
2003
}
2002
}
2004
#endif
2003
#endif
2005
/* Original addfb only supported RGB formats, so figure out which one */
2004
/* Original addfb only supported RGB formats, so figure out which one */
2006
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
2005
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
2007
{
2006
{
2008
	uint32_t fmt;
2007
	uint32_t fmt;
2009
 
2008
 
2010
	switch (bpp) {
2009
	switch (bpp) {
2011
	case 8:
2010
	case 8:
2012
		fmt = DRM_FORMAT_RGB332;
2011
		fmt = DRM_FORMAT_RGB332;
2013
		break;
2012
		break;
2014
	case 16:
2013
	case 16:
2015
		if (depth == 15)
2014
		if (depth == 15)
2016
			fmt = DRM_FORMAT_XRGB1555;
2015
			fmt = DRM_FORMAT_XRGB1555;
2017
		else
2016
		else
2018
			fmt = DRM_FORMAT_RGB565;
2017
			fmt = DRM_FORMAT_RGB565;
2019
		break;
2018
		break;
2020
	case 24:
2019
	case 24:
2021
		fmt = DRM_FORMAT_RGB888;
2020
		fmt = DRM_FORMAT_RGB888;
2022
		break;
2021
		break;
2023
	case 32:
2022
	case 32:
2024
		if (depth == 24)
2023
		if (depth == 24)
2025
			fmt = DRM_FORMAT_XRGB8888;
2024
			fmt = DRM_FORMAT_XRGB8888;
2026
		else if (depth == 30)
2025
		else if (depth == 30)
2027
			fmt = DRM_FORMAT_XRGB2101010;
2026
			fmt = DRM_FORMAT_XRGB2101010;
2028
		else
2027
		else
2029
			fmt = DRM_FORMAT_ARGB8888;
2028
			fmt = DRM_FORMAT_ARGB8888;
2030
		break;
2029
		break;
2031
	default:
2030
	default:
2032
		DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
2031
		DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
2033
		fmt = DRM_FORMAT_XRGB8888;
2032
		fmt = DRM_FORMAT_XRGB8888;
2034
		break;
2033
		break;
2035
	}
2034
	}
2036
 
2035
 
2037
	return fmt;
2036
	return fmt;
2038
}
2037
}
2039
EXPORT_SYMBOL(drm_mode_legacy_fb_format);
2038
EXPORT_SYMBOL(drm_mode_legacy_fb_format);
2040
#if 0
2039
#if 0
2041
/**
2040
/**
2042
 * drm_mode_addfb - add an FB to the graphics configuration
2041
 * drm_mode_addfb - add an FB to the graphics configuration
2043
 * @inode: inode from the ioctl
2042
 * @inode: inode from the ioctl
2044
 * @filp: file * from the ioctl
2043
 * @filp: file * from the ioctl
2045
 * @cmd: cmd from ioctl
2044
 * @cmd: cmd from ioctl
2046
 * @arg: arg from ioctl
2045
 * @arg: arg from ioctl
2047
 *
2046
 *
2048
 * LOCKING:
2047
 * LOCKING:
2049
 * Takes mode config lock.
2048
 * Takes mode config lock.
2050
 *
2049
 *
2051
 * Add a new FB to the specified CRTC, given a user request.
2050
 * Add a new FB to the specified CRTC, given a user request.
2052
 *
2051
 *
2053
 * Called by the user via ioctl.
2052
 * Called by the user via ioctl.
2054
 *
2053
 *
2055
 * RETURNS:
2054
 * RETURNS:
2056
 * Zero on success, errno on failure.
2055
 * Zero on success, errno on failure.
2057
 */
2056
 */
2058
int drm_mode_addfb(struct drm_device *dev,
2057
int drm_mode_addfb(struct drm_device *dev,
2059
		   void *data, struct drm_file *file_priv)
2058
		   void *data, struct drm_file *file_priv)
2060
{
2059
{
2061
	struct drm_mode_fb_cmd *or = data;
2060
	struct drm_mode_fb_cmd *or = data;
2062
	struct drm_mode_fb_cmd2 r = {};
2061
	struct drm_mode_fb_cmd2 r = {};
2063
	struct drm_mode_config *config = &dev->mode_config;
2062
	struct drm_mode_config *config = &dev->mode_config;
2064
	struct drm_framebuffer *fb;
2063
	struct drm_framebuffer *fb;
2065
	int ret = 0;
2064
	int ret = 0;
2066
 
2065
 
2067
	/* Use new struct with format internally */
2066
	/* Use new struct with format internally */
2068
	r.fb_id = or->fb_id;
2067
	r.fb_id = or->fb_id;
2069
	r.width = or->width;
2068
	r.width = or->width;
2070
	r.height = or->height;
2069
	r.height = or->height;
2071
	r.pitches[0] = or->pitch;
2070
	r.pitches[0] = or->pitch;
2072
	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
2071
	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
2073
	r.handles[0] = or->handle;
2072
	r.handles[0] = or->handle;
2074
 
2073
 
2075
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2074
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2076
		return -EINVAL;
2075
		return -EINVAL;
2077
 
2076
 
2078
	if ((config->min_width > r.width) || (r.width > config->max_width))
2077
	if ((config->min_width > r.width) || (r.width > config->max_width))
2079
		return -EINVAL;
2078
		return -EINVAL;
2080
 
2079
 
2081
	if ((config->min_height > r.height) || (r.height > config->max_height))
2080
	if ((config->min_height > r.height) || (r.height > config->max_height))
2082
		return -EINVAL;
2081
		return -EINVAL;
2083
 
2082
 
2084
	mutex_lock(&dev->mode_config.mutex);
2083
	mutex_lock(&dev->mode_config.mutex);
2085
 
2084
 
2086
	/* TODO check buffer is sufficiently large */
2085
	/* TODO check buffer is sufficiently large */
2087
	/* TODO setup destructor callback */
2086
	/* TODO setup destructor callback */
2088
 
2087
 
2089
	fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
2088
	fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
2090
	if (IS_ERR(fb)) {
2089
	if (IS_ERR(fb)) {
2091
		DRM_DEBUG_KMS("could not create framebuffer\n");
2090
		DRM_DEBUG_KMS("could not create framebuffer\n");
2092
		ret = PTR_ERR(fb);
2091
		ret = PTR_ERR(fb);
2093
		goto out;
2092
		goto out;
2094
	}
2093
	}
2095
 
2094
 
2096
	or->fb_id = fb->base.id;
2095
	or->fb_id = fb->base.id;
2097
	list_add(&fb->filp_head, &file_priv->fbs);
2096
	list_add(&fb->filp_head, &file_priv->fbs);
2098
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2097
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2099
 
2098
 
2100
out:
2099
out:
2101
	mutex_unlock(&dev->mode_config.mutex);
2100
	mutex_unlock(&dev->mode_config.mutex);
2102
	return ret;
2101
	return ret;
2103
}
2102
}
2104
 
2103
 
2105
static int format_check(const struct drm_mode_fb_cmd2 *r)
2104
static int format_check(const struct drm_mode_fb_cmd2 *r)
2106
{
2105
{
2107
	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
2106
	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
2108
 
2107
 
2109
	switch (format) {
2108
	switch (format) {
2110
	case DRM_FORMAT_C8:
2109
	case DRM_FORMAT_C8:
2111
	case DRM_FORMAT_RGB332:
2110
	case DRM_FORMAT_RGB332:
2112
	case DRM_FORMAT_BGR233:
2111
	case DRM_FORMAT_BGR233:
2113
	case DRM_FORMAT_XRGB4444:
2112
	case DRM_FORMAT_XRGB4444:
2114
	case DRM_FORMAT_XBGR4444:
2113
	case DRM_FORMAT_XBGR4444:
2115
	case DRM_FORMAT_RGBX4444:
2114
	case DRM_FORMAT_RGBX4444:
2116
	case DRM_FORMAT_BGRX4444:
2115
	case DRM_FORMAT_BGRX4444:
2117
	case DRM_FORMAT_ARGB4444:
2116
	case DRM_FORMAT_ARGB4444:
2118
	case DRM_FORMAT_ABGR4444:
2117
	case DRM_FORMAT_ABGR4444:
2119
	case DRM_FORMAT_RGBA4444:
2118
	case DRM_FORMAT_RGBA4444:
2120
	case DRM_FORMAT_BGRA4444:
2119
	case DRM_FORMAT_BGRA4444:
2121
	case DRM_FORMAT_XRGB1555:
2120
	case DRM_FORMAT_XRGB1555:
2122
	case DRM_FORMAT_XBGR1555:
2121
	case DRM_FORMAT_XBGR1555:
2123
	case DRM_FORMAT_RGBX5551:
2122
	case DRM_FORMAT_RGBX5551:
2124
	case DRM_FORMAT_BGRX5551:
2123
	case DRM_FORMAT_BGRX5551:
2125
	case DRM_FORMAT_ARGB1555:
2124
	case DRM_FORMAT_ARGB1555:
2126
	case DRM_FORMAT_ABGR1555:
2125
	case DRM_FORMAT_ABGR1555:
2127
	case DRM_FORMAT_RGBA5551:
2126
	case DRM_FORMAT_RGBA5551:
2128
	case DRM_FORMAT_BGRA5551:
2127
	case DRM_FORMAT_BGRA5551:
2129
	case DRM_FORMAT_RGB565:
2128
	case DRM_FORMAT_RGB565:
2130
	case DRM_FORMAT_BGR565:
2129
	case DRM_FORMAT_BGR565:
2131
	case DRM_FORMAT_RGB888:
2130
	case DRM_FORMAT_RGB888:
2132
	case DRM_FORMAT_BGR888:
2131
	case DRM_FORMAT_BGR888:
2133
	case DRM_FORMAT_XRGB8888:
2132
	case DRM_FORMAT_XRGB8888:
2134
	case DRM_FORMAT_XBGR8888:
2133
	case DRM_FORMAT_XBGR8888:
2135
	case DRM_FORMAT_RGBX8888:
2134
	case DRM_FORMAT_RGBX8888:
2136
	case DRM_FORMAT_BGRX8888:
2135
	case DRM_FORMAT_BGRX8888:
2137
	case DRM_FORMAT_ARGB8888:
2136
	case DRM_FORMAT_ARGB8888:
2138
	case DRM_FORMAT_ABGR8888:
2137
	case DRM_FORMAT_ABGR8888:
2139
	case DRM_FORMAT_RGBA8888:
2138
	case DRM_FORMAT_RGBA8888:
2140
	case DRM_FORMAT_BGRA8888:
2139
	case DRM_FORMAT_BGRA8888:
2141
	case DRM_FORMAT_XRGB2101010:
2140
	case DRM_FORMAT_XRGB2101010:
2142
	case DRM_FORMAT_XBGR2101010:
2141
	case DRM_FORMAT_XBGR2101010:
2143
	case DRM_FORMAT_RGBX1010102:
2142
	case DRM_FORMAT_RGBX1010102:
2144
	case DRM_FORMAT_BGRX1010102:
2143
	case DRM_FORMAT_BGRX1010102:
2145
	case DRM_FORMAT_ARGB2101010:
2144
	case DRM_FORMAT_ARGB2101010:
2146
	case DRM_FORMAT_ABGR2101010:
2145
	case DRM_FORMAT_ABGR2101010:
2147
	case DRM_FORMAT_RGBA1010102:
2146
	case DRM_FORMAT_RGBA1010102:
2148
	case DRM_FORMAT_BGRA1010102:
2147
	case DRM_FORMAT_BGRA1010102:
2149
	case DRM_FORMAT_YUYV:
2148
	case DRM_FORMAT_YUYV:
2150
	case DRM_FORMAT_YVYU:
2149
	case DRM_FORMAT_YVYU:
2151
	case DRM_FORMAT_UYVY:
2150
	case DRM_FORMAT_UYVY:
2152
	case DRM_FORMAT_VYUY:
2151
	case DRM_FORMAT_VYUY:
2153
	case DRM_FORMAT_AYUV:
2152
	case DRM_FORMAT_AYUV:
2154
	case DRM_FORMAT_NV12:
2153
	case DRM_FORMAT_NV12:
2155
	case DRM_FORMAT_NV21:
2154
	case DRM_FORMAT_NV21:
2156
	case DRM_FORMAT_NV16:
2155
	case DRM_FORMAT_NV16:
2157
	case DRM_FORMAT_NV61:
2156
	case DRM_FORMAT_NV61:
2158
	case DRM_FORMAT_NV24:
2157
	case DRM_FORMAT_NV24:
2159
	case DRM_FORMAT_NV42:
2158
	case DRM_FORMAT_NV42:
2160
	case DRM_FORMAT_YUV410:
2159
	case DRM_FORMAT_YUV410:
2161
	case DRM_FORMAT_YVU410:
2160
	case DRM_FORMAT_YVU410:
2162
	case DRM_FORMAT_YUV411:
2161
	case DRM_FORMAT_YUV411:
2163
	case DRM_FORMAT_YVU411:
2162
	case DRM_FORMAT_YVU411:
2164
	case DRM_FORMAT_YUV420:
2163
	case DRM_FORMAT_YUV420:
2165
	case DRM_FORMAT_YVU420:
2164
	case DRM_FORMAT_YVU420:
2166
	case DRM_FORMAT_YUV422:
2165
	case DRM_FORMAT_YUV422:
2167
	case DRM_FORMAT_YVU422:
2166
	case DRM_FORMAT_YVU422:
2168
	case DRM_FORMAT_YUV444:
2167
	case DRM_FORMAT_YUV444:
2169
	case DRM_FORMAT_YVU444:
2168
	case DRM_FORMAT_YVU444:
2170
		return 0;
2169
		return 0;
2171
	default:
2170
	default:
2172
		return -EINVAL;
2171
		return -EINVAL;
2173
	}
2172
	}
2174
}
2173
}
2175
 
2174
 
2176
static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
2175
static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
2177
{
2176
{
2178
	int ret, hsub, vsub, num_planes, i;
2177
	int ret, hsub, vsub, num_planes, i;
2179
 
2178
 
2180
	ret = format_check(r);
2179
	ret = format_check(r);
2181
	if (ret) {
2180
	if (ret) {
2182
		DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
2181
		DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
2183
		return ret;
2182
		return ret;
2184
	}
2183
	}
2185
 
2184
 
2186
	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
2185
	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
2187
	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
2186
	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
2188
	num_planes = drm_format_num_planes(r->pixel_format);
2187
	num_planes = drm_format_num_planes(r->pixel_format);
2189
 
2188
 
2190
	if (r->width == 0 || r->width % hsub) {
2189
	if (r->width == 0 || r->width % hsub) {
2191
		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
2190
		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
2192
		return -EINVAL;
2191
		return -EINVAL;
2193
	}
2192
	}
2194
 
2193
 
2195
	if (r->height == 0 || r->height % vsub) {
2194
	if (r->height == 0 || r->height % vsub) {
2196
		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
2195
		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
2197
		return -EINVAL;
2196
		return -EINVAL;
2198
	}
2197
	}
2199
 
2198
 
2200
	for (i = 0; i < num_planes; i++) {
2199
	for (i = 0; i < num_planes; i++) {
2201
		unsigned int width = r->width / (i != 0 ? hsub : 1);
2200
		unsigned int width = r->width / (i != 0 ? hsub : 1);
-
 
2201
		unsigned int height = r->height / (i != 0 ? vsub : 1);
-
 
2202
		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
2202
 
2203
 
2203
		if (!r->handles[i]) {
2204
		if (!r->handles[i]) {
2204
			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
2205
			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
2205
			return -EINVAL;
2206
			return -EINVAL;
2206
		}
2207
		}
-
 
2208
 
-
 
2209
		if ((uint64_t) width * cpp > UINT_MAX)
-
 
2210
			return -ERANGE;
-
 
2211
 
-
 
2212
		if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
-
 
2213
			return -ERANGE;
2207
 
2214
 
2208
		if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) {
2215
		if (r->pitches[i] < width * cpp) {
2209
			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
2216
			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
2210
			return -EINVAL;
2217
			return -EINVAL;
2211
		}
2218
		}
2212
	}
2219
	}
2213
 
2220
 
2214
	return 0;
2221
	return 0;
2215
}
2222
}
2216
 
2223
 
2217
/**
2224
/**
2218
 * drm_mode_addfb2 - add an FB to the graphics configuration
2225
 * drm_mode_addfb2 - add an FB to the graphics configuration
2219
 * @inode: inode from the ioctl
2226
 * @inode: inode from the ioctl
2220
 * @filp: file * from the ioctl
2227
 * @filp: file * from the ioctl
2221
 * @cmd: cmd from ioctl
2228
 * @cmd: cmd from ioctl
2222
 * @arg: arg from ioctl
2229
 * @arg: arg from ioctl
2223
 *
2230
 *
2224
 * LOCKING:
2231
 * LOCKING:
2225
 * Takes mode config lock.
2232
 * Takes mode config lock.
2226
 *
2233
 *
2227
 * Add a new FB to the specified CRTC, given a user request with format.
2234
 * Add a new FB to the specified CRTC, given a user request with format.
2228
 *
2235
 *
2229
 * Called by the user via ioctl.
2236
 * Called by the user via ioctl.
2230
 *
2237
 *
2231
 * RETURNS:
2238
 * RETURNS:
2232
 * Zero on success, errno on failure.
2239
 * Zero on success, errno on failure.
2233
 */
2240
 */
2234
int drm_mode_addfb2(struct drm_device *dev,
2241
int drm_mode_addfb2(struct drm_device *dev,
2235
		    void *data, struct drm_file *file_priv)
2242
		    void *data, struct drm_file *file_priv)
2236
{
2243
{
2237
	struct drm_mode_fb_cmd2 *r = data;
2244
	struct drm_mode_fb_cmd2 *r = data;
2238
	struct drm_mode_config *config = &dev->mode_config;
2245
	struct drm_mode_config *config = &dev->mode_config;
2239
	struct drm_framebuffer *fb;
2246
	struct drm_framebuffer *fb;
2240
	int ret;
2247
	int ret;
2241
 
2248
 
2242
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2249
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2243
		return -EINVAL;
2250
		return -EINVAL;
-
 
2251
 
-
 
2252
	if (r->flags & ~DRM_MODE_FB_INTERLACED) {
-
 
2253
		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
-
 
2254
		return -EINVAL;
-
 
2255
	}
2244
 
2256
 
2245
	if ((config->min_width > r->width) || (r->width > config->max_width)) {
2257
	if ((config->min_width > r->width) || (r->width > config->max_width)) {
2246
		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
2258
		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
2247
			  r->width, config->min_width, config->max_width);
2259
			  r->width, config->min_width, config->max_width);
2248
		return -EINVAL;
2260
		return -EINVAL;
2249
	}
2261
	}
2250
	if ((config->min_height > r->height) || (r->height > config->max_height)) {
2262
	if ((config->min_height > r->height) || (r->height > config->max_height)) {
2251
		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
2263
		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
2252
			  r->height, config->min_height, config->max_height);
2264
			  r->height, config->min_height, config->max_height);
2253
		return -EINVAL;
2265
		return -EINVAL;
2254
	}
2266
	}
2255
 
2267
 
2256
	ret = framebuffer_check(r);
2268
	ret = framebuffer_check(r);
2257
	if (ret)
2269
	if (ret)
2258
		return ret;
2270
		return ret;
2259
 
2271
 
2260
	mutex_lock(&dev->mode_config.mutex);
2272
	mutex_lock(&dev->mode_config.mutex);
2261
 
2273
 
2262
	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
2274
	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
2263
	if (IS_ERR(fb)) {
2275
	if (IS_ERR(fb)) {
2264
		DRM_DEBUG_KMS("could not create framebuffer\n");
2276
		DRM_DEBUG_KMS("could not create framebuffer\n");
2265
		ret = PTR_ERR(fb);
2277
		ret = PTR_ERR(fb);
2266
		goto out;
2278
		goto out;
2267
	}
2279
	}
2268
 
2280
 
2269
	r->fb_id = fb->base.id;
2281
	r->fb_id = fb->base.id;
2270
	list_add(&fb->filp_head, &file_priv->fbs);
2282
	list_add(&fb->filp_head, &file_priv->fbs);
2271
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2283
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2272
 
2284
 
2273
out:
2285
out:
2274
	mutex_unlock(&dev->mode_config.mutex);
2286
	mutex_unlock(&dev->mode_config.mutex);
2275
	return ret;
2287
	return ret;
2276
}
2288
}
2277
 
2289
 
2278
/**
2290
/**
2279
 * drm_mode_rmfb - remove an FB from the configuration
2291
 * drm_mode_rmfb - remove an FB from the configuration
2280
 * @inode: inode from the ioctl
2292
 * @inode: inode from the ioctl
2281
 * @filp: file * from the ioctl
2293
 * @filp: file * from the ioctl
2282
 * @cmd: cmd from ioctl
2294
 * @cmd: cmd from ioctl
2283
 * @arg: arg from ioctl
2295
 * @arg: arg from ioctl
2284
 *
2296
 *
2285
 * LOCKING:
2297
 * LOCKING:
2286
 * Takes mode config lock.
2298
 * Takes mode config lock.
2287
 *
2299
 *
2288
 * Remove the FB specified by the user.
2300
 * Remove the FB specified by the user.
2289
 *
2301
 *
2290
 * Called by the user via ioctl.
2302
 * Called by the user via ioctl.
2291
 *
2303
 *
2292
 * RETURNS:
2304
 * RETURNS:
2293
 * Zero on success, errno on failure.
2305
 * Zero on success, errno on failure.
2294
 */
2306
 */
2295
int drm_mode_rmfb(struct drm_device *dev,
2307
int drm_mode_rmfb(struct drm_device *dev,
2296
		   void *data, struct drm_file *file_priv)
2308
		   void *data, struct drm_file *file_priv)
2297
{
2309
{
2298
	struct drm_mode_object *obj;
2310
	struct drm_mode_object *obj;
2299
	struct drm_framebuffer *fb = NULL;
2311
	struct drm_framebuffer *fb = NULL;
2300
	struct drm_framebuffer *fbl = NULL;
2312
	struct drm_framebuffer *fbl = NULL;
2301
	uint32_t *id = data;
2313
	uint32_t *id = data;
2302
	int ret = 0;
2314
	int ret = 0;
2303
	int found = 0;
2315
	int found = 0;
2304
 
2316
 
2305
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2317
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2306
		return -EINVAL;
2318
		return -EINVAL;
2307
 
2319
 
2308
	mutex_lock(&dev->mode_config.mutex);
2320
	mutex_lock(&dev->mode_config.mutex);
2309
	obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
2321
	obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
2310
	/* TODO check that we really get a framebuffer back. */
2322
	/* TODO check that we really get a framebuffer back. */
2311
	if (!obj) {
2323
	if (!obj) {
2312
		ret = -EINVAL;
2324
		ret = -EINVAL;
2313
		goto out;
2325
		goto out;
2314
	}
2326
	}
2315
	fb = obj_to_fb(obj);
2327
	fb = obj_to_fb(obj);
2316
 
2328
 
2317
	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
2329
	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
2318
		if (fb == fbl)
2330
		if (fb == fbl)
2319
			found = 1;
2331
			found = 1;
2320
 
2332
 
2321
	if (!found) {
2333
	if (!found) {
2322
		ret = -EINVAL;
2334
		ret = -EINVAL;
2323
		goto out;
2335
		goto out;
2324
	}
2336
	}
2325
 
2337
 
2326
	drm_framebuffer_remove(fb);
2338
	drm_framebuffer_remove(fb);
2327
 
2339
 
2328
out:
2340
out:
2329
	mutex_unlock(&dev->mode_config.mutex);
2341
	mutex_unlock(&dev->mode_config.mutex);
2330
	return ret;
2342
	return ret;
2331
}
2343
}
2332
 
2344
 
2333
/**
2345
/**
2334
 * drm_mode_getfb - get FB info
2346
 * drm_mode_getfb - get FB info
2335
 * @inode: inode from the ioctl
2347
 * @inode: inode from the ioctl
2336
 * @filp: file * from the ioctl
2348
 * @filp: file * from the ioctl
2337
 * @cmd: cmd from ioctl
2349
 * @cmd: cmd from ioctl
2338
 * @arg: arg from ioctl
2350
 * @arg: arg from ioctl
2339
 *
2351
 *
2340
 * LOCKING:
2352
 * LOCKING:
2341
 * Takes mode config lock.
2353
 * Takes mode config lock.
2342
 *
2354
 *
2343
 * Lookup the FB given its ID and return info about it.
2355
 * Lookup the FB given its ID and return info about it.
2344
 *
2356
 *
2345
 * Called by the user via ioctl.
2357
 * Called by the user via ioctl.
2346
 *
2358
 *
2347
 * RETURNS:
2359
 * RETURNS:
2348
 * Zero on success, errno on failure.
2360
 * Zero on success, errno on failure.
2349
 */
2361
 */
2350
int drm_mode_getfb(struct drm_device *dev,
2362
int drm_mode_getfb(struct drm_device *dev,
2351
		   void *data, struct drm_file *file_priv)
2363
		   void *data, struct drm_file *file_priv)
2352
{
2364
{
2353
	struct drm_mode_fb_cmd *r = data;
2365
	struct drm_mode_fb_cmd *r = data;
2354
	struct drm_mode_object *obj;
2366
	struct drm_mode_object *obj;
2355
	struct drm_framebuffer *fb;
2367
	struct drm_framebuffer *fb;
2356
	int ret = 0;
2368
	int ret = 0;
2357
 
2369
 
2358
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2370
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2359
		return -EINVAL;
2371
		return -EINVAL;
2360
 
2372
 
2361
	mutex_lock(&dev->mode_config.mutex);
2373
	mutex_lock(&dev->mode_config.mutex);
2362
	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2374
	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2363
	if (!obj) {
2375
	if (!obj) {
2364
		ret = -EINVAL;
2376
		ret = -EINVAL;
2365
		goto out;
2377
		goto out;
2366
	}
2378
	}
2367
	fb = obj_to_fb(obj);
2379
	fb = obj_to_fb(obj);
2368
 
2380
 
2369
	r->height = fb->height;
2381
	r->height = fb->height;
2370
	r->width = fb->width;
2382
	r->width = fb->width;
2371
	r->depth = fb->depth;
2383
	r->depth = fb->depth;
2372
	r->bpp = fb->bits_per_pixel;
2384
	r->bpp = fb->bits_per_pixel;
2373
	r->pitch = fb->pitches[0];
2385
	r->pitch = fb->pitches[0];
2374
	fb->funcs->create_handle(fb, file_priv, &r->handle);
2386
	fb->funcs->create_handle(fb, file_priv, &r->handle);
2375
 
2387
 
2376
out:
2388
out:
2377
	mutex_unlock(&dev->mode_config.mutex);
2389
	mutex_unlock(&dev->mode_config.mutex);
2378
	return ret;
2390
	return ret;
2379
}
2391
}
2380
 
2392
 
2381
int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2393
int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2382
			   void *data, struct drm_file *file_priv)
2394
			   void *data, struct drm_file *file_priv)
2383
{
2395
{
2384
	struct drm_clip_rect __user *clips_ptr;
2396
	struct drm_clip_rect __user *clips_ptr;
2385
	struct drm_clip_rect *clips = NULL;
2397
	struct drm_clip_rect *clips = NULL;
2386
	struct drm_mode_fb_dirty_cmd *r = data;
2398
	struct drm_mode_fb_dirty_cmd *r = data;
2387
	struct drm_mode_object *obj;
2399
	struct drm_mode_object *obj;
2388
	struct drm_framebuffer *fb;
2400
	struct drm_framebuffer *fb;
2389
	unsigned flags;
2401
	unsigned flags;
2390
	int num_clips;
2402
	int num_clips;
2391
	int ret;
2403
	int ret;
2392
 
2404
 
2393
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2405
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2394
		return -EINVAL;
2406
		return -EINVAL;
2395
 
2407
 
2396
	mutex_lock(&dev->mode_config.mutex);
2408
	mutex_lock(&dev->mode_config.mutex);
2397
	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2409
	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2398
	if (!obj) {
2410
	if (!obj) {
2399
		ret = -EINVAL;
2411
		ret = -EINVAL;
2400
		goto out_err1;
2412
		goto out_err1;
2401
	}
2413
	}
2402
	fb = obj_to_fb(obj);
2414
	fb = obj_to_fb(obj);
2403
 
2415
 
2404
	num_clips = r->num_clips;
2416
	num_clips = r->num_clips;
2405
	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
2417
	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
2406
 
2418
 
2407
	if (!num_clips != !clips_ptr) {
2419
	if (!num_clips != !clips_ptr) {
2408
		ret = -EINVAL;
2420
		ret = -EINVAL;
2409
		goto out_err1;
2421
		goto out_err1;
2410
	}
2422
	}
2411
 
2423
 
2412
	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
2424
	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
2413
 
2425
 
2414
	/* If userspace annotates copy, clips must come in pairs */
2426
	/* If userspace annotates copy, clips must come in pairs */
2415
	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
2427
	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
2416
		ret = -EINVAL;
2428
		ret = -EINVAL;
2417
		goto out_err1;
2429
		goto out_err1;
2418
	}
2430
	}
2419
 
2431
 
2420
	if (num_clips && clips_ptr) {
2432
	if (num_clips && clips_ptr) {
2421
		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
2433
		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
2422
			ret = -EINVAL;
2434
			ret = -EINVAL;
2423
			goto out_err1;
2435
			goto out_err1;
2424
		}
2436
		}
2425
		clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
2437
		clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
2426
		if (!clips) {
2438
		if (!clips) {
2427
			ret = -ENOMEM;
2439
			ret = -ENOMEM;
2428
			goto out_err1;
2440
			goto out_err1;
2429
		}
2441
		}
2430
 
2442
 
2431
		ret = copy_from_user(clips, clips_ptr,
2443
		ret = copy_from_user(clips, clips_ptr,
2432
				     num_clips * sizeof(*clips));
2444
				     num_clips * sizeof(*clips));
2433
		if (ret) {
2445
		if (ret) {
2434
			ret = -EFAULT;
2446
			ret = -EFAULT;
2435
			goto out_err2;
2447
			goto out_err2;
2436
	}
2448
	}
2437
	}
2449
	}
2438
 
2450
 
2439
	if (fb->funcs->dirty) {
2451
	if (fb->funcs->dirty) {
2440
		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
2452
		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
2441
				       clips, num_clips);
2453
				       clips, num_clips);
2442
	} else {
2454
	} else {
2443
		ret = -ENOSYS;
2455
		ret = -ENOSYS;
2444
		goto out_err2;
2456
		goto out_err2;
2445
	}
2457
	}
2446
 
2458
 
2447
out_err2:
2459
out_err2:
2448
	kfree(clips);
2460
	kfree(clips);
2449
out_err1:
2461
out_err1:
2450
	mutex_unlock(&dev->mode_config.mutex);
2462
	mutex_unlock(&dev->mode_config.mutex);
2451
	return ret;
2463
	return ret;
2452
}
2464
}
2453
 
2465
 
2454
 
2466
 
2455
/**
2467
/**
2456
 * drm_fb_release - remove and free the FBs on this file
2468
 * drm_fb_release - remove and free the FBs on this file
2457
 * @filp: file * from the ioctl
2469
 * @filp: file * from the ioctl
2458
 *
2470
 *
2459
 * LOCKING:
2471
 * LOCKING:
2460
 * Takes mode config lock.
2472
 * Takes mode config lock.
2461
 *
2473
 *
2462
 * Destroy all the FBs associated with @filp.
2474
 * Destroy all the FBs associated with @filp.
2463
 *
2475
 *
2464
 * Called by the user via ioctl.
2476
 * Called by the user via ioctl.
2465
 *
2477
 *
2466
 * RETURNS:
2478
 * RETURNS:
2467
 * Zero on success, errno on failure.
2479
 * Zero on success, errno on failure.
2468
 */
2480
 */
2469
void drm_fb_release(struct drm_file *priv)
2481
void drm_fb_release(struct drm_file *priv)
2470
{
2482
{
2471
	struct drm_device *dev = priv->minor->dev;
2483
	struct drm_device *dev = priv->minor->dev;
2472
	struct drm_framebuffer *fb, *tfb;
2484
	struct drm_framebuffer *fb, *tfb;
2473
 
2485
 
2474
	mutex_lock(&dev->mode_config.mutex);
2486
	mutex_lock(&dev->mode_config.mutex);
2475
	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
2487
	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
2476
		drm_framebuffer_remove(fb);
2488
		drm_framebuffer_remove(fb);
2477
	}
2489
	}
2478
	mutex_unlock(&dev->mode_config.mutex);
2490
	mutex_unlock(&dev->mode_config.mutex);
2479
}
2491
}
2480
#endif
2492
#endif
2481
 
2493
 
2482
/**
2494
/**
2483
 * drm_mode_attachmode - add a mode to the user mode list
2495
 * drm_mode_attachmode - add a mode to the user mode list
2484
 * @dev: DRM device
2496
 * @dev: DRM device
2485
 * @connector: connector to add the mode to
2497
 * @connector: connector to add the mode to
2486
 * @mode: mode to add
2498
 * @mode: mode to add
2487
 *
2499
 *
2488
 * Add @mode to @connector's user mode list.
2500
 * Add @mode to @connector's user mode list.
2489
 */
2501
 */
2490
static void drm_mode_attachmode(struct drm_device *dev,
2502
static void drm_mode_attachmode(struct drm_device *dev,
2491
			       struct drm_connector *connector,
2503
			       struct drm_connector *connector,
2492
			       struct drm_display_mode *mode)
2504
			       struct drm_display_mode *mode)
2493
{
2505
{
2494
	list_add_tail(&mode->head, &connector->user_modes);
2506
	list_add_tail(&mode->head, &connector->user_modes);
2495
}
2507
}
2496
 
2508
 
2497
int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
2509
int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
2498
			     const struct drm_display_mode *mode)
2510
			     const struct drm_display_mode *mode)
2499
{
2511
{
2500
	struct drm_connector *connector;
2512
	struct drm_connector *connector;
2501
	int ret = 0;
2513
	int ret = 0;
2502
	struct drm_display_mode *dup_mode, *next;
2514
	struct drm_display_mode *dup_mode, *next;
2503
	LIST_HEAD(list);
2515
	LIST_HEAD(list);
2504
 
2516
 
2505
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2517
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2506
		if (!connector->encoder)
2518
		if (!connector->encoder)
2507
			continue;
2519
			continue;
2508
		if (connector->encoder->crtc == crtc) {
2520
		if (connector->encoder->crtc == crtc) {
2509
				dup_mode = drm_mode_duplicate(dev, mode);
2521
				dup_mode = drm_mode_duplicate(dev, mode);
2510
			if (!dup_mode) {
2522
			if (!dup_mode) {
2511
				ret = -ENOMEM;
2523
				ret = -ENOMEM;
2512
				goto out;
2524
				goto out;
2513
		}
2525
		}
2514
			list_add_tail(&dup_mode->head, &list);
2526
			list_add_tail(&dup_mode->head, &list);
2515
		}
2527
		}
2516
	}
2528
	}
2517
 
2529
 
2518
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2530
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2519
		if (!connector->encoder)
2531
		if (!connector->encoder)
2520
			continue;
2532
			continue;
2521
		if (connector->encoder->crtc == crtc)
2533
		if (connector->encoder->crtc == crtc)
2522
			list_move_tail(list.next, &connector->user_modes);
2534
			list_move_tail(list.next, &connector->user_modes);
2523
	}
2535
	}
2524
 
2536
 
2525
	WARN_ON(!list_empty(&list));
2537
	WARN_ON(!list_empty(&list));
2526
 
2538
 
2527
 out:
2539
 out:
2528
	list_for_each_entry_safe(dup_mode, next, &list, head)
2540
	list_for_each_entry_safe(dup_mode, next, &list, head)
2529
		drm_mode_destroy(dev, dup_mode);
2541
		drm_mode_destroy(dev, dup_mode);
2530
 
2542
 
2531
	return ret;
2543
	return ret;
2532
}
2544
}
2533
EXPORT_SYMBOL(drm_mode_attachmode_crtc);
2545
EXPORT_SYMBOL(drm_mode_attachmode_crtc);
2534
 
2546
 
2535
static int drm_mode_detachmode(struct drm_device *dev,
2547
static int drm_mode_detachmode(struct drm_device *dev,
2536
			       struct drm_connector *connector,
2548
			       struct drm_connector *connector,
2537
			       struct drm_display_mode *mode)
2549
			       struct drm_display_mode *mode)
2538
{
2550
{
2539
	int found = 0;
2551
	int found = 0;
2540
	int ret = 0;
2552
	int ret = 0;
2541
	struct drm_display_mode *match_mode, *t;
2553
	struct drm_display_mode *match_mode, *t;
2542
 
2554
 
2543
	list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) {
2555
	list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) {
2544
		if (drm_mode_equal(match_mode, mode)) {
2556
		if (drm_mode_equal(match_mode, mode)) {
2545
			list_del(&match_mode->head);
2557
			list_del(&match_mode->head);
2546
			drm_mode_destroy(dev, match_mode);
2558
			drm_mode_destroy(dev, match_mode);
2547
			found = 1;
2559
			found = 1;
2548
			break;
2560
			break;
2549
		}
2561
		}
2550
	}
2562
	}
2551
 
2563
 
2552
	if (!found)
2564
	if (!found)
2553
		ret = -EINVAL;
2565
		ret = -EINVAL;
2554
 
2566
 
2555
	return ret;
2567
	return ret;
2556
}
2568
}
2557
 
2569
 
2558
int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
2570
int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
2559
{
2571
{
2560
	struct drm_connector *connector;
2572
	struct drm_connector *connector;
2561
 
2573
 
2562
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2574
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2563
		drm_mode_detachmode(dev, connector, mode);
2575
		drm_mode_detachmode(dev, connector, mode);
2564
	}
2576
	}
2565
	return 0;
2577
	return 0;
2566
}
2578
}
2567
EXPORT_SYMBOL(drm_mode_detachmode_crtc);
2579
EXPORT_SYMBOL(drm_mode_detachmode_crtc);
2568
 
2580
 
2569
#if 0
2581
#if 0
2570
 
2582
 
2571
/**
2583
/**
2572
 * drm_fb_attachmode - Attach a user mode to an connector
2584
 * drm_fb_attachmode - Attach a user mode to an connector
2573
 * @inode: inode from the ioctl
2585
 * @inode: inode from the ioctl
2574
 * @filp: file * from the ioctl
2586
 * @filp: file * from the ioctl
2575
 * @cmd: cmd from ioctl
2587
 * @cmd: cmd from ioctl
2576
 * @arg: arg from ioctl
2588
 * @arg: arg from ioctl
2577
 *
2589
 *
2578
 * This attaches a user specified mode to an connector.
2590
 * This attaches a user specified mode to an connector.
2579
 * Called by the user via ioctl.
2591
 * Called by the user via ioctl.
2580
 *
2592
 *
2581
 * RETURNS:
2593
 * RETURNS:
2582
 * Zero on success, errno on failure.
2594
 * Zero on success, errno on failure.
2583
 */
2595
 */
2584
int drm_mode_attachmode_ioctl(struct drm_device *dev,
2596
int drm_mode_attachmode_ioctl(struct drm_device *dev,
2585
			      void *data, struct drm_file *file_priv)
2597
			      void *data, struct drm_file *file_priv)
2586
{
2598
{
2587
	struct drm_mode_mode_cmd *mode_cmd = data;
2599
	struct drm_mode_mode_cmd *mode_cmd = data;
2588
	struct drm_connector *connector;
2600
	struct drm_connector *connector;
2589
	struct drm_display_mode *mode;
2601
	struct drm_display_mode *mode;
2590
	struct drm_mode_object *obj;
2602
	struct drm_mode_object *obj;
2591
	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2603
	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2592
	int ret;
2604
	int ret;
2593
 
2605
 
2594
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2606
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2595
		return -EINVAL;
2607
		return -EINVAL;
2596
 
2608
 
2597
	mutex_lock(&dev->mode_config.mutex);
2609
	mutex_lock(&dev->mode_config.mutex);
2598
 
2610
 
2599
	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2611
	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2600
	if (!obj) {
2612
	if (!obj) {
2601
		ret = -EINVAL;
2613
		ret = -EINVAL;
2602
		goto out;
2614
		goto out;
2603
	}
2615
	}
2604
	connector = obj_to_connector(obj);
2616
	connector = obj_to_connector(obj);
2605
 
2617
 
2606
	mode = drm_mode_create(dev);
2618
	mode = drm_mode_create(dev);
2607
	if (!mode) {
2619
	if (!mode) {
2608
		ret = -ENOMEM;
2620
		ret = -ENOMEM;
2609
		goto out;
2621
		goto out;
2610
	}
2622
	}
2611
 
2623
 
2612
	ret = drm_crtc_convert_umode(mode, umode);
2624
	ret = drm_crtc_convert_umode(mode, umode);
2613
	if (ret) {
2625
	if (ret) {
2614
		DRM_DEBUG_KMS("Invalid mode\n");
2626
		DRM_DEBUG_KMS("Invalid mode\n");
2615
		drm_mode_destroy(dev, mode);
2627
		drm_mode_destroy(dev, mode);
2616
		goto out;
2628
		goto out;
2617
	}
2629
	}
2618
 
2630
 
2619
	drm_mode_attachmode(dev, connector, mode);
2631
	drm_mode_attachmode(dev, connector, mode);
2620
out:
2632
out:
2621
	mutex_unlock(&dev->mode_config.mutex);
2633
	mutex_unlock(&dev->mode_config.mutex);
2622
	return ret;
2634
	return ret;
2623
}
2635
}
2624
 
2636
 
2625
 
2637
 
2626
/**
2638
/**
2627
 * drm_fb_detachmode - Detach a user specified mode from an connector
2639
 * drm_fb_detachmode - Detach a user specified mode from an connector
2628
 * @inode: inode from the ioctl
2640
 * @inode: inode from the ioctl
2629
 * @filp: file * from the ioctl
2641
 * @filp: file * from the ioctl
2630
 * @cmd: cmd from ioctl
2642
 * @cmd: cmd from ioctl
2631
 * @arg: arg from ioctl
2643
 * @arg: arg from ioctl
2632
 *
2644
 *
2633
 * Called by the user via ioctl.
2645
 * Called by the user via ioctl.
2634
 *
2646
 *
2635
 * RETURNS:
2647
 * RETURNS:
2636
 * Zero on success, errno on failure.
2648
 * Zero on success, errno on failure.
2637
 */
2649
 */
2638
int drm_mode_detachmode_ioctl(struct drm_device *dev,
2650
int drm_mode_detachmode_ioctl(struct drm_device *dev,
2639
			      void *data, struct drm_file *file_priv)
2651
			      void *data, struct drm_file *file_priv)
2640
{
2652
{
2641
	struct drm_mode_object *obj;
2653
	struct drm_mode_object *obj;
2642
	struct drm_mode_mode_cmd *mode_cmd = data;
2654
	struct drm_mode_mode_cmd *mode_cmd = data;
2643
	struct drm_connector *connector;
2655
	struct drm_connector *connector;
2644
	struct drm_display_mode mode;
2656
	struct drm_display_mode mode;
2645
	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2657
	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2646
	int ret;
2658
	int ret;
2647
 
2659
 
2648
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2660
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2649
		return -EINVAL;
2661
		return -EINVAL;
2650
 
2662
 
2651
	mutex_lock(&dev->mode_config.mutex);
2663
	mutex_lock(&dev->mode_config.mutex);
2652
 
2664
 
2653
	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2665
	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2654
	if (!obj) {
2666
	if (!obj) {
2655
		ret = -EINVAL;
2667
		ret = -EINVAL;
2656
		goto out;
2668
		goto out;
2657
	}
2669
	}
2658
	connector = obj_to_connector(obj);
2670
	connector = obj_to_connector(obj);
2659
 
2671
 
2660
	ret = drm_crtc_convert_umode(&mode, umode);
2672
	ret = drm_crtc_convert_umode(&mode, umode);
2661
	if (ret) {
2673
	if (ret) {
2662
		DRM_DEBUG_KMS("Invalid mode\n");
2674
		DRM_DEBUG_KMS("Invalid mode\n");
2663
		goto out;
2675
		goto out;
2664
	}
2676
	}
2665
 
2677
 
2666
	ret = drm_mode_detachmode(dev, connector, &mode);
2678
	ret = drm_mode_detachmode(dev, connector, &mode);
2667
out:
2679
out:
2668
	mutex_unlock(&dev->mode_config.mutex);
2680
	mutex_unlock(&dev->mode_config.mutex);
2669
	return ret;
2681
	return ret;
2670
}
2682
}
2671
#endif
2683
#endif
2672
 
2684
 
2673
struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2685
struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2674
					 const char *name, int num_values)
2686
					 const char *name, int num_values)
2675
{
2687
{
2676
	struct drm_property *property = NULL;
2688
	struct drm_property *property = NULL;
2677
	int ret;
2689
	int ret;
2678
 
2690
 
2679
	property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
2691
	property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
2680
	if (!property)
2692
	if (!property)
2681
		return NULL;
2693
		return NULL;
2682
 
2694
 
2683
	if (num_values) {
2695
	if (num_values) {
2684
		property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
2696
		property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
2685
		if (!property->values)
2697
		if (!property->values)
2686
			goto fail;
2698
			goto fail;
2687
	}
2699
	}
2688
 
2700
 
2689
	ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
2701
	ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
2690
	if (ret)
2702
	if (ret)
2691
		goto fail;
2703
		goto fail;
2692
 
2704
 
2693
	property->flags = flags;
2705
	property->flags = flags;
2694
	property->num_values = num_values;
2706
	property->num_values = num_values;
2695
	INIT_LIST_HEAD(&property->enum_blob_list);
2707
	INIT_LIST_HEAD(&property->enum_blob_list);
2696
 
2708
 
2697
	if (name) {
2709
	if (name) {
2698
		strncpy(property->name, name, DRM_PROP_NAME_LEN);
2710
		strncpy(property->name, name, DRM_PROP_NAME_LEN);
2699
		property->name[DRM_PROP_NAME_LEN-1] = '\0';
2711
		property->name[DRM_PROP_NAME_LEN-1] = '\0';
2700
	}
2712
	}
2701
 
2713
 
2702
	list_add_tail(&property->head, &dev->mode_config.property_list);
2714
	list_add_tail(&property->head, &dev->mode_config.property_list);
2703
	return property;
2715
	return property;
2704
fail:
2716
fail:
2705
	kfree(property->values);
2717
	kfree(property->values);
2706
	kfree(property);
2718
	kfree(property);
2707
	return NULL;
2719
	return NULL;
2708
}
2720
}
2709
EXPORT_SYMBOL(drm_property_create);
2721
EXPORT_SYMBOL(drm_property_create);
2710
 
2722
 
2711
struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
2723
struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
2712
					 const char *name,
2724
					 const char *name,
2713
					 const struct drm_prop_enum_list *props,
2725
					 const struct drm_prop_enum_list *props,
2714
					 int num_values)
2726
					 int num_values)
2715
{
2727
{
2716
	struct drm_property *property;
2728
	struct drm_property *property;
2717
	int i, ret;
2729
	int i, ret;
2718
 
2730
 
2719
	flags |= DRM_MODE_PROP_ENUM;
2731
	flags |= DRM_MODE_PROP_ENUM;
2720
 
2732
 
2721
	property = drm_property_create(dev, flags, name, num_values);
2733
	property = drm_property_create(dev, flags, name, num_values);
2722
	if (!property)
2734
	if (!property)
2723
		return NULL;
2735
		return NULL;
2724
 
2736
 
2725
	for (i = 0; i < num_values; i++) {
2737
	for (i = 0; i < num_values; i++) {
2726
		ret = drm_property_add_enum(property, i,
2738
		ret = drm_property_add_enum(property, i,
2727
				      props[i].type,
2739
				      props[i].type,
2728
				      props[i].name);
2740
				      props[i].name);
2729
		if (ret) {
2741
		if (ret) {
2730
			drm_property_destroy(dev, property);
2742
			drm_property_destroy(dev, property);
2731
			return NULL;
2743
			return NULL;
2732
		}
2744
		}
2733
	}
2745
	}
2734
 
2746
 
2735
	return property;
2747
	return property;
2736
}
2748
}
2737
EXPORT_SYMBOL(drm_property_create_enum);
2749
EXPORT_SYMBOL(drm_property_create_enum);
2738
 
2750
 
2739
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
2751
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
2740
					 int flags, const char *name,
2752
					 int flags, const char *name,
2741
					 const struct drm_prop_enum_list *props,
2753
					 const struct drm_prop_enum_list *props,
2742
					 int num_values)
2754
					 int num_values)
2743
{
2755
{
2744
	struct drm_property *property;
2756
	struct drm_property *property;
2745
	int i, ret;
2757
	int i, ret;
2746
 
2758
 
2747
	flags |= DRM_MODE_PROP_BITMASK;
2759
	flags |= DRM_MODE_PROP_BITMASK;
2748
 
2760
 
2749
	property = drm_property_create(dev, flags, name, num_values);
2761
	property = drm_property_create(dev, flags, name, num_values);
2750
	if (!property)
2762
	if (!property)
2751
		return NULL;
2763
		return NULL;
2752
 
2764
 
2753
	for (i = 0; i < num_values; i++) {
2765
	for (i = 0; i < num_values; i++) {
2754
		ret = drm_property_add_enum(property, i,
2766
		ret = drm_property_add_enum(property, i,
2755
				      props[i].type,
2767
				      props[i].type,
2756
				      props[i].name);
2768
				      props[i].name);
2757
		if (ret) {
2769
		if (ret) {
2758
			drm_property_destroy(dev, property);
2770
			drm_property_destroy(dev, property);
2759
			return NULL;
2771
			return NULL;
2760
		}
2772
		}
2761
	}
2773
	}
2762
 
2774
 
2763
	return property;
2775
	return property;
2764
}
2776
}
2765
EXPORT_SYMBOL(drm_property_create_bitmask);
2777
EXPORT_SYMBOL(drm_property_create_bitmask);
2766
 
2778
 
2767
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
2779
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
2768
					 const char *name,
2780
					 const char *name,
2769
					 uint64_t min, uint64_t max)
2781
					 uint64_t min, uint64_t max)
2770
{
2782
{
2771
	struct drm_property *property;
2783
	struct drm_property *property;
2772
 
2784
 
2773
	flags |= DRM_MODE_PROP_RANGE;
2785
	flags |= DRM_MODE_PROP_RANGE;
2774
 
2786
 
2775
	property = drm_property_create(dev, flags, name, 2);
2787
	property = drm_property_create(dev, flags, name, 2);
2776
	if (!property)
2788
	if (!property)
2777
		return NULL;
2789
		return NULL;
2778
 
2790
 
2779
	property->values[0] = min;
2791
	property->values[0] = min;
2780
	property->values[1] = max;
2792
	property->values[1] = max;
2781
 
2793
 
2782
	return property;
2794
	return property;
2783
}
2795
}
2784
EXPORT_SYMBOL(drm_property_create_range);
2796
EXPORT_SYMBOL(drm_property_create_range);
2785
 
2797
 
2786
int drm_property_add_enum(struct drm_property *property, int index,
2798
int drm_property_add_enum(struct drm_property *property, int index,
2787
			  uint64_t value, const char *name)
2799
			  uint64_t value, const char *name)
2788
{
2800
{
2789
	struct drm_property_enum *prop_enum;
2801
	struct drm_property_enum *prop_enum;
2790
 
2802
 
2791
	if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
2803
	if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
2792
		return -EINVAL;
2804
		return -EINVAL;
2793
 
2805
 
2794
	/*
2806
	/*
2795
	 * Bitmask enum properties have the additional constraint of values
2807
	 * Bitmask enum properties have the additional constraint of values
2796
	 * from 0 to 63
2808
	 * from 0 to 63
2797
	 */
2809
	 */
2798
	if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
2810
	if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
2799
		return -EINVAL;
2811
		return -EINVAL;
2800
 
2812
 
2801
	if (!list_empty(&property->enum_blob_list)) {
2813
	if (!list_empty(&property->enum_blob_list)) {
2802
		list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2814
		list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2803
			if (prop_enum->value == value) {
2815
			if (prop_enum->value == value) {
2804
				strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2816
				strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2805
				prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2817
				prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2806
				return 0;
2818
				return 0;
2807
			}
2819
			}
2808
		}
2820
		}
2809
	}
2821
	}
2810
 
2822
 
2811
	prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
2823
	prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
2812
	if (!prop_enum)
2824
	if (!prop_enum)
2813
		return -ENOMEM;
2825
		return -ENOMEM;
2814
 
2826
 
2815
	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2827
	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2816
	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2828
	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2817
	prop_enum->value = value;
2829
	prop_enum->value = value;
2818
 
2830
 
2819
	property->values[index] = value;
2831
	property->values[index] = value;
2820
	list_add_tail(&prop_enum->head, &property->enum_blob_list);
2832
	list_add_tail(&prop_enum->head, &property->enum_blob_list);
2821
	return 0;
2833
	return 0;
2822
}
2834
}
2823
EXPORT_SYMBOL(drm_property_add_enum);
2835
EXPORT_SYMBOL(drm_property_add_enum);
2824
 
2836
 
2825
void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2837
void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2826
{
2838
{
2827
	struct drm_property_enum *prop_enum, *pt;
2839
	struct drm_property_enum *prop_enum, *pt;
2828
 
2840
 
2829
	list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
2841
	list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
2830
		list_del(&prop_enum->head);
2842
		list_del(&prop_enum->head);
2831
		kfree(prop_enum);
2843
		kfree(prop_enum);
2832
	}
2844
	}
2833
 
2845
 
2834
	if (property->num_values)
2846
	if (property->num_values)
2835
		kfree(property->values);
2847
		kfree(property->values);
2836
	drm_mode_object_put(dev, &property->base);
2848
	drm_mode_object_put(dev, &property->base);
2837
	list_del(&property->head);
2849
	list_del(&property->head);
2838
	kfree(property);
2850
	kfree(property);
2839
}
2851
}
2840
EXPORT_SYMBOL(drm_property_destroy);
2852
EXPORT_SYMBOL(drm_property_destroy);
2841
 
-
 
2842
void drm_connector_attach_property(struct drm_connector *connector,
-
 
2843
			       struct drm_property *property, uint64_t init_val)
-
 
2844
{
-
 
2845
	drm_object_attach_property(&connector->base, property, init_val);
-
 
2846
}
-
 
2847
EXPORT_SYMBOL(drm_connector_attach_property);
-
 
2848
 
-
 
2849
int drm_connector_property_set_value(struct drm_connector *connector,
-
 
2850
				  struct drm_property *property, uint64_t value)
-
 
2851
{
-
 
2852
	return drm_object_property_set_value(&connector->base, property, value);
-
 
2853
}
-
 
2854
EXPORT_SYMBOL(drm_connector_property_set_value);
-
 
2855
 
-
 
2856
int drm_connector_property_get_value(struct drm_connector *connector,
-
 
2857
				  struct drm_property *property, uint64_t *val)
-
 
2858
{
-
 
2859
	return drm_object_property_get_value(&connector->base, property, val);
-
 
2860
}
-
 
2861
EXPORT_SYMBOL(drm_connector_property_get_value);
-
 
2862
 
2853
 
2863
void drm_object_attach_property(struct drm_mode_object *obj,
2854
void drm_object_attach_property(struct drm_mode_object *obj,
2864
				struct drm_property *property,
2855
				struct drm_property *property,
2865
				uint64_t init_val)
2856
				uint64_t init_val)
2866
{
2857
{
2867
	int count = obj->properties->count;
2858
	int count = obj->properties->count;
2868
 
2859
 
2869
	if (count == DRM_OBJECT_MAX_PROPERTY) {
2860
	if (count == DRM_OBJECT_MAX_PROPERTY) {
2870
		WARN(1, "Failed to attach object property (type: 0x%x). Please "
2861
		WARN(1, "Failed to attach object property (type: 0x%x). Please "
2871
			"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
2862
			"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
2872
			"you see this message on the same object type.\n",
2863
			"you see this message on the same object type.\n",
2873
			obj->type);
2864
			obj->type);
2874
		return;
2865
		return;
2875
	}
2866
	}
2876
 
2867
 
2877
	obj->properties->ids[count] = property->base.id;
2868
	obj->properties->ids[count] = property->base.id;
2878
	obj->properties->values[count] = init_val;
2869
	obj->properties->values[count] = init_val;
2879
	obj->properties->count++;
2870
	obj->properties->count++;
2880
}
2871
}
2881
EXPORT_SYMBOL(drm_object_attach_property);
2872
EXPORT_SYMBOL(drm_object_attach_property);
2882
 
2873
 
2883
int drm_object_property_set_value(struct drm_mode_object *obj,
2874
int drm_object_property_set_value(struct drm_mode_object *obj,
2884
				  struct drm_property *property, uint64_t val)
2875
				  struct drm_property *property, uint64_t val)
2885
{
2876
{
2886
	int i;
2877
	int i;
2887
 
2878
 
2888
	for (i = 0; i < obj->properties->count; i++) {
2879
	for (i = 0; i < obj->properties->count; i++) {
2889
		if (obj->properties->ids[i] == property->base.id) {
2880
		if (obj->properties->ids[i] == property->base.id) {
2890
			obj->properties->values[i] = val;
2881
			obj->properties->values[i] = val;
2891
			return 0;
2882
			return 0;
2892
		}
2883
		}
2893
	}
2884
	}
2894
 
2885
 
2895
		return -EINVAL;
2886
		return -EINVAL;
2896
}
2887
}
2897
EXPORT_SYMBOL(drm_object_property_set_value);
2888
EXPORT_SYMBOL(drm_object_property_set_value);
2898
 
2889
 
2899
int drm_object_property_get_value(struct drm_mode_object *obj,
2890
int drm_object_property_get_value(struct drm_mode_object *obj,
2900
				  struct drm_property *property, uint64_t *val)
2891
				  struct drm_property *property, uint64_t *val)
2901
{
2892
{
2902
	int i;
2893
	int i;
2903
 
2894
 
2904
	for (i = 0; i < obj->properties->count; i++) {
2895
	for (i = 0; i < obj->properties->count; i++) {
2905
		if (obj->properties->ids[i] == property->base.id) {
2896
		if (obj->properties->ids[i] == property->base.id) {
2906
			*val = obj->properties->values[i];
2897
			*val = obj->properties->values[i];
2907
			return 0;
2898
			return 0;
2908
		}
2899
		}
2909
	}
2900
	}
2910
 
2901
 
2911
		return -EINVAL;
2902
		return -EINVAL;
2912
}
2903
}
2913
EXPORT_SYMBOL(drm_object_property_get_value);
2904
EXPORT_SYMBOL(drm_object_property_get_value);
2914
 
2905
 
2915
#if 0
2906
#if 0
2916
int drm_mode_getproperty_ioctl(struct drm_device *dev,
2907
int drm_mode_getproperty_ioctl(struct drm_device *dev,
2917
			       void *data, struct drm_file *file_priv)
2908
			       void *data, struct drm_file *file_priv)
2918
{
2909
{
2919
	struct drm_mode_object *obj;
2910
	struct drm_mode_object *obj;
2920
	struct drm_mode_get_property *out_resp = data;
2911
	struct drm_mode_get_property *out_resp = data;
2921
	struct drm_property *property;
2912
	struct drm_property *property;
2922
	int enum_count = 0;
2913
	int enum_count = 0;
2923
	int blob_count = 0;
2914
	int blob_count = 0;
2924
	int value_count = 0;
2915
	int value_count = 0;
2925
	int ret = 0, i;
2916
	int ret = 0, i;
2926
	int copied;
2917
	int copied;
2927
	struct drm_property_enum *prop_enum;
2918
	struct drm_property_enum *prop_enum;
2928
	struct drm_mode_property_enum __user *enum_ptr;
2919
	struct drm_mode_property_enum __user *enum_ptr;
2929
	struct drm_property_blob *prop_blob;
2920
	struct drm_property_blob *prop_blob;
2930
	uint32_t __user *blob_id_ptr;
2921
	uint32_t __user *blob_id_ptr;
2931
	uint64_t __user *values_ptr;
2922
	uint64_t __user *values_ptr;
2932
	uint32_t __user *blob_length_ptr;
2923
	uint32_t __user *blob_length_ptr;
2933
 
2924
 
2934
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2925
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2935
		return -EINVAL;
2926
		return -EINVAL;
2936
 
2927
 
2937
	mutex_lock(&dev->mode_config.mutex);
2928
	mutex_lock(&dev->mode_config.mutex);
2938
	obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
2929
	obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
2939
	if (!obj) {
2930
	if (!obj) {
2940
		ret = -EINVAL;
2931
		ret = -EINVAL;
2941
		goto done;
2932
		goto done;
2942
	}
2933
	}
2943
	property = obj_to_property(obj);
2934
	property = obj_to_property(obj);
2944
 
2935
 
2945
	if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
2936
	if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
2946
		list_for_each_entry(prop_enum, &property->enum_blob_list, head)
2937
		list_for_each_entry(prop_enum, &property->enum_blob_list, head)
2947
			enum_count++;
2938
			enum_count++;
2948
	} else if (property->flags & DRM_MODE_PROP_BLOB) {
2939
	} else if (property->flags & DRM_MODE_PROP_BLOB) {
2949
		list_for_each_entry(prop_blob, &property->enum_blob_list, head)
2940
		list_for_each_entry(prop_blob, &property->enum_blob_list, head)
2950
			blob_count++;
2941
			blob_count++;
2951
	}
2942
	}
2952
 
2943
 
2953
	value_count = property->num_values;
2944
	value_count = property->num_values;
2954
 
2945
 
2955
	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2946
	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2956
	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2947
	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2957
	out_resp->flags = property->flags;
2948
	out_resp->flags = property->flags;
2958
 
2949
 
2959
	if ((out_resp->count_values >= value_count) && value_count) {
2950
	if ((out_resp->count_values >= value_count) && value_count) {
2960
		values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
2951
		values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
2961
		for (i = 0; i < value_count; i++) {
2952
		for (i = 0; i < value_count; i++) {
2962
			if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
2953
			if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
2963
				ret = -EFAULT;
2954
				ret = -EFAULT;
2964
				goto done;
2955
				goto done;
2965
			}
2956
			}
2966
		}
2957
		}
2967
	}
2958
	}
2968
	out_resp->count_values = value_count;
2959
	out_resp->count_values = value_count;
2969
 
2960
 
2970
	if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
2961
	if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
2971
		if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2962
		if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2972
			copied = 0;
2963
			copied = 0;
2973
			enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
2964
			enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
2974
			list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2965
			list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2975
 
2966
 
2976
				if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
2967
				if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
2977
					ret = -EFAULT;
2968
					ret = -EFAULT;
2978
					goto done;
2969
					goto done;
2979
				}
2970
				}
2980
 
2971
 
2981
				if (copy_to_user(&enum_ptr[copied].name,
2972
				if (copy_to_user(&enum_ptr[copied].name,
2982
						 &prop_enum->name, DRM_PROP_NAME_LEN)) {
2973
						 &prop_enum->name, DRM_PROP_NAME_LEN)) {
2983
					ret = -EFAULT;
2974
					ret = -EFAULT;
2984
					goto done;
2975
					goto done;
2985
				}
2976
				}
2986
				copied++;
2977
				copied++;
2987
			}
2978
			}
2988
		}
2979
		}
2989
		out_resp->count_enum_blobs = enum_count;
2980
		out_resp->count_enum_blobs = enum_count;
2990
	}
2981
	}
2991
 
2982
 
2992
	if (property->flags & DRM_MODE_PROP_BLOB) {
2983
	if (property->flags & DRM_MODE_PROP_BLOB) {
2993
		if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
2984
		if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
2994
			copied = 0;
2985
			copied = 0;
2995
			blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
2986
			blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
2996
			blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
2987
			blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
2997
 
2988
 
2998
			list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
2989
			list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
2999
				if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
2990
				if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
3000
					ret = -EFAULT;
2991
					ret = -EFAULT;
3001
					goto done;
2992
					goto done;
3002
				}
2993
				}
3003
 
2994
 
3004
				if (put_user(prop_blob->length, blob_length_ptr + copied)) {
2995
				if (put_user(prop_blob->length, blob_length_ptr + copied)) {
3005
					ret = -EFAULT;
2996
					ret = -EFAULT;
3006
					goto done;
2997
					goto done;
3007
				}
2998
				}
3008
 
2999
 
3009
				copied++;
3000
				copied++;
3010
			}
3001
			}
3011
		}
3002
		}
3012
		out_resp->count_enum_blobs = blob_count;
3003
		out_resp->count_enum_blobs = blob_count;
3013
	}
3004
	}
3014
done:
3005
done:
3015
	mutex_unlock(&dev->mode_config.mutex);
3006
	mutex_unlock(&dev->mode_config.mutex);
3016
	return ret;
3007
	return ret;
3017
}
3008
}
3018
#endif
3009
#endif
3019
 
3010
 
3020
static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
3011
static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
3021
							  void *data)
3012
							  void *data)
3022
{
3013
{
3023
	struct drm_property_blob *blob;
3014
	struct drm_property_blob *blob;
3024
	int ret;
3015
	int ret;
3025
 
3016
 
3026
	if (!length || !data)
3017
	if (!length || !data)
3027
		return NULL;
3018
		return NULL;
3028
 
3019
 
3029
	blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
3020
	blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
3030
	if (!blob)
3021
	if (!blob)
3031
		return NULL;
3022
		return NULL;
3032
 
3023
 
3033
	ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
3024
	ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
3034
	if (ret) {
3025
	if (ret) {
3035
		kfree(blob);
3026
		kfree(blob);
3036
		return NULL;
3027
		return NULL;
3037
	}
3028
	}
3038
 
3029
 
3039
	blob->length = length;
3030
	blob->length = length;
3040
 
3031
 
3041
	memcpy(blob->data, data, length);
3032
	memcpy(blob->data, data, length);
3042
 
3033
 
3043
	list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
3034
	list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
3044
	return blob;
3035
	return blob;
3045
}
3036
}
3046
 
3037
 
3047
static void drm_property_destroy_blob(struct drm_device *dev,
3038
static void drm_property_destroy_blob(struct drm_device *dev,
3048
			       struct drm_property_blob *blob)
3039
			       struct drm_property_blob *blob)
3049
{
3040
{
3050
	drm_mode_object_put(dev, &blob->base);
3041
	drm_mode_object_put(dev, &blob->base);
3051
	list_del(&blob->head);
3042
	list_del(&blob->head);
3052
	kfree(blob);
3043
	kfree(blob);
3053
}
3044
}
3054
 
3045
 
3055
#if 0
3046
#if 0
3056
int drm_mode_getblob_ioctl(struct drm_device *dev,
3047
int drm_mode_getblob_ioctl(struct drm_device *dev,
3057
			   void *data, struct drm_file *file_priv)
3048
			   void *data, struct drm_file *file_priv)
3058
{
3049
{
3059
	struct drm_mode_object *obj;
3050
	struct drm_mode_object *obj;
3060
	struct drm_mode_get_blob *out_resp = data;
3051
	struct drm_mode_get_blob *out_resp = data;
3061
	struct drm_property_blob *blob;
3052
	struct drm_property_blob *blob;
3062
	int ret = 0;
3053
	int ret = 0;
3063
	void __user *blob_ptr;
3054
	void __user *blob_ptr;
3064
 
3055
 
3065
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3056
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3066
		return -EINVAL;
3057
		return -EINVAL;
3067
 
3058
 
3068
	mutex_lock(&dev->mode_config.mutex);
3059
	mutex_lock(&dev->mode_config.mutex);
3069
	obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
3060
	obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
3070
	if (!obj) {
3061
	if (!obj) {
3071
		ret = -EINVAL;
3062
		ret = -EINVAL;
3072
		goto done;
3063
		goto done;
3073
	}
3064
	}
3074
	blob = obj_to_blob(obj);
3065
	blob = obj_to_blob(obj);
3075
 
3066
 
3076
	if (out_resp->length == blob->length) {
3067
	if (out_resp->length == blob->length) {
3077
		blob_ptr = (void __user *)(unsigned long)out_resp->data;
3068
		blob_ptr = (void __user *)(unsigned long)out_resp->data;
3078
		if (copy_to_user(blob_ptr, blob->data, blob->length)){
3069
		if (copy_to_user(blob_ptr, blob->data, blob->length)){
3079
			ret = -EFAULT;
3070
			ret = -EFAULT;
3080
			goto done;
3071
			goto done;
3081
		}
3072
		}
3082
	}
3073
	}
3083
	out_resp->length = blob->length;
3074
	out_resp->length = blob->length;
3084
 
3075
 
3085
done:
3076
done:
3086
	mutex_unlock(&dev->mode_config.mutex);
3077
	mutex_unlock(&dev->mode_config.mutex);
3087
	return ret;
3078
	return ret;
3088
}
3079
}
3089
#endif
3080
#endif
3090
 
3081
 
3091
int drm_mode_connector_update_edid_property(struct drm_connector *connector,
3082
int drm_mode_connector_update_edid_property(struct drm_connector *connector,
3092
					    struct edid *edid)
3083
					    struct edid *edid)
3093
{
3084
{
3094
	struct drm_device *dev = connector->dev;
3085
	struct drm_device *dev = connector->dev;
3095
	int ret, size;
3086
	int ret, size;
3096
 
3087
 
3097
	if (connector->edid_blob_ptr)
3088
	if (connector->edid_blob_ptr)
3098
		drm_property_destroy_blob(dev, connector->edid_blob_ptr);
3089
		drm_property_destroy_blob(dev, connector->edid_blob_ptr);
3099
 
3090
 
3100
	/* Delete edid, when there is none. */
3091
	/* Delete edid, when there is none. */
3101
	if (!edid) {
3092
	if (!edid) {
3102
		connector->edid_blob_ptr = NULL;
3093
		connector->edid_blob_ptr = NULL;
3103
		ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0);
3094
		ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0);
3104
		return ret;
3095
		return ret;
3105
	}
3096
	}
3106
 
3097
 
3107
	size = EDID_LENGTH * (1 + edid->extensions);
3098
	size = EDID_LENGTH * (1 + edid->extensions);
3108
	connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
3099
	connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
3109
							    size, edid);
3100
							    size, edid);
-
 
3101
	if (!connector->edid_blob_ptr)
-
 
3102
		return -EINVAL;
3110
 
3103
 
3111
	ret = drm_connector_property_set_value(connector,
3104
	ret = drm_object_property_set_value(&connector->base,
3112
					       dev->mode_config.edid_property,
3105
					       dev->mode_config.edid_property,
3113
					       connector->edid_blob_ptr->base.id);
3106
					       connector->edid_blob_ptr->base.id);
3114
 
3107
 
3115
	return ret;
3108
	return ret;
3116
}
3109
}
3117
EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
3110
EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
3118
 
3111
 
3119
#if 0
3112
#if 0
3120
 
3113
 
3121
static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
3114
static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
3122
					   struct drm_property *property,
3115
					   struct drm_property *property,
3123
					   uint64_t value)
3116
					   uint64_t value)
3124
{
3117
{
3125
	int ret = -EINVAL;
3118
	int ret = -EINVAL;
3126
	struct drm_connector *connector = obj_to_connector(obj);
3119
	struct drm_connector *connector = obj_to_connector(obj);
3127
 
3120
 
3128
	/* Do DPMS ourselves */
3121
	/* Do DPMS ourselves */
3129
	if (property == connector->dev->mode_config.dpms_property) {
3122
	if (property == connector->dev->mode_config.dpms_property) {
3130
		if (connector->funcs->dpms)
3123
		if (connector->funcs->dpms)
3131
			(*connector->funcs->dpms)(connector, (int)value);
3124
			(*connector->funcs->dpms)(connector, (int)value);
3132
		ret = 0;
3125
		ret = 0;
3133
	} else if (connector->funcs->set_property)
3126
	} else if (connector->funcs->set_property)
3134
		ret = connector->funcs->set_property(connector, property, value);
3127
		ret = connector->funcs->set_property(connector, property, value);
3135
 
3128
 
3136
	/* store the property value if successful */
3129
	/* store the property value if successful */
3137
	if (!ret)
3130
	if (!ret)
3138
		drm_connector_property_set_value(connector, property, value);
3131
		drm_object_property_set_value(&connector->base, property, value);
3139
	return ret;
3132
	return ret;
3140
}
3133
}
3141
 
3134
 
3142
static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
3135
static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
3143
				      struct drm_property *property,
3136
				      struct drm_property *property,
3144
				      uint64_t value)
3137
				      uint64_t value)
3145
{
3138
{
3146
	int ret = -EINVAL;
3139
	int ret = -EINVAL;
3147
	struct drm_crtc *crtc = obj_to_crtc(obj);
3140
	struct drm_crtc *crtc = obj_to_crtc(obj);
3148
 
3141
 
3149
	if (crtc->funcs->set_property)
3142
	if (crtc->funcs->set_property)
3150
		ret = crtc->funcs->set_property(crtc, property, value);
3143
		ret = crtc->funcs->set_property(crtc, property, value);
3151
	if (!ret)
3144
	if (!ret)
3152
		drm_object_property_set_value(obj, property, value);
3145
		drm_object_property_set_value(obj, property, value);
3153
 
3146
 
3154
	return ret;
3147
	return ret;
3155
}
3148
}
3156
 
3149
 
3157
static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
3150
static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
3158
				      struct drm_property *property,
3151
				      struct drm_property *property,
3159
				      uint64_t value)
3152
				      uint64_t value)
3160
{
3153
{
3161
	int ret = -EINVAL;
3154
	int ret = -EINVAL;
3162
	struct drm_plane *plane = obj_to_plane(obj);
3155
	struct drm_plane *plane = obj_to_plane(obj);
3163
 
3156
 
3164
	if (plane->funcs->set_property)
3157
	if (plane->funcs->set_property)
3165
		ret = plane->funcs->set_property(plane, property, value);
3158
		ret = plane->funcs->set_property(plane, property, value);
3166
	if (!ret)
3159
	if (!ret)
3167
		drm_object_property_set_value(obj, property, value);
3160
		drm_object_property_set_value(obj, property, value);
3168
 
3161
 
3169
	return ret;
3162
	return ret;
3170
}
3163
}
3171
 
3164
 
3172
int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
3165
int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
3173
				      struct drm_file *file_priv)
3166
				      struct drm_file *file_priv)
3174
{
3167
{
3175
	struct drm_mode_obj_get_properties *arg = data;
3168
	struct drm_mode_obj_get_properties *arg = data;
3176
	struct drm_mode_object *obj;
3169
	struct drm_mode_object *obj;
3177
	int ret = 0;
3170
	int ret = 0;
3178
	int i;
3171
	int i;
3179
	int copied = 0;
3172
	int copied = 0;
3180
	int props_count = 0;
3173
	int props_count = 0;
3181
	uint32_t __user *props_ptr;
3174
	uint32_t __user *props_ptr;
3182
	uint64_t __user *prop_values_ptr;
3175
	uint64_t __user *prop_values_ptr;
3183
 
3176
 
3184
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3177
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3185
		return -EINVAL;
3178
		return -EINVAL;
3186
 
3179
 
3187
	mutex_lock(&dev->mode_config.mutex);
3180
	mutex_lock(&dev->mode_config.mutex);
3188
 
3181
 
3189
	obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3182
	obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3190
	if (!obj) {
3183
	if (!obj) {
3191
		ret = -EINVAL;
3184
		ret = -EINVAL;
3192
		goto out;
3185
		goto out;
3193
	}
3186
	}
3194
	if (!obj->properties) {
3187
	if (!obj->properties) {
3195
		ret = -EINVAL;
3188
		ret = -EINVAL;
3196
		goto out;
3189
		goto out;
3197
	}
3190
	}
3198
 
3191
 
3199
	props_count = obj->properties->count;
3192
	props_count = obj->properties->count;
3200
 
3193
 
3201
	/* This ioctl is called twice, once to determine how much space is
3194
	/* This ioctl is called twice, once to determine how much space is
3202
	 * needed, and the 2nd time to fill it. */
3195
	 * needed, and the 2nd time to fill it. */
3203
	if ((arg->count_props >= props_count) && props_count) {
3196
	if ((arg->count_props >= props_count) && props_count) {
3204
		copied = 0;
3197
		copied = 0;
3205
		props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
3198
		props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
3206
		prop_values_ptr = (uint64_t __user *)(unsigned long)
3199
		prop_values_ptr = (uint64_t __user *)(unsigned long)
3207
				  (arg->prop_values_ptr);
3200
				  (arg->prop_values_ptr);
3208
		for (i = 0; i < props_count; i++) {
3201
		for (i = 0; i < props_count; i++) {
3209
			if (put_user(obj->properties->ids[i],
3202
			if (put_user(obj->properties->ids[i],
3210
				     props_ptr + copied)) {
3203
				     props_ptr + copied)) {
3211
				ret = -EFAULT;
3204
				ret = -EFAULT;
3212
				goto out;
3205
				goto out;
3213
	}
3206
	}
3214
			if (put_user(obj->properties->values[i],
3207
			if (put_user(obj->properties->values[i],
3215
				     prop_values_ptr + copied)) {
3208
				     prop_values_ptr + copied)) {
3216
				ret = -EFAULT;
3209
				ret = -EFAULT;
3217
		goto out;
3210
		goto out;
3218
	}
3211
	}
3219
			copied++;
3212
			copied++;
3220
		}
3213
		}
3221
	}
3214
	}
3222
	arg->count_props = props_count;
3215
	arg->count_props = props_count;
3223
out:
3216
out:
3224
	mutex_unlock(&dev->mode_config.mutex);
3217
	mutex_unlock(&dev->mode_config.mutex);
3225
	return ret;
3218
	return ret;
3226
}
3219
}
3227
 
3220
 
3228
int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
3221
int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
3229
				    struct drm_file *file_priv)
3222
				    struct drm_file *file_priv)
3230
{
3223
{
3231
	struct drm_mode_obj_set_property *arg = data;
3224
	struct drm_mode_obj_set_property *arg = data;
3232
	struct drm_mode_object *arg_obj;
3225
	struct drm_mode_object *arg_obj;
3233
	struct drm_mode_object *prop_obj;
3226
	struct drm_mode_object *prop_obj;
3234
	struct drm_property *property;
3227
	struct drm_property *property;
3235
	int ret = -EINVAL;
3228
	int ret = -EINVAL;
3236
	int i;
3229
	int i;
3237
 
3230
 
3238
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3231
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3239
		return -EINVAL;
3232
		return -EINVAL;
3240
 
3233
 
3241
	mutex_lock(&dev->mode_config.mutex);
3234
	mutex_lock(&dev->mode_config.mutex);
3242
 
3235
 
3243
	arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3236
	arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3244
	if (!arg_obj)
3237
	if (!arg_obj)
3245
		goto out;
3238
		goto out;
3246
	if (!arg_obj->properties)
3239
	if (!arg_obj->properties)
3247
		goto out;
3240
		goto out;
3248
 
3241
 
3249
	for (i = 0; i < arg_obj->properties->count; i++)
3242
	for (i = 0; i < arg_obj->properties->count; i++)
3250
		if (arg_obj->properties->ids[i] == arg->prop_id)
3243
		if (arg_obj->properties->ids[i] == arg->prop_id)
3251
			break;
3244
			break;
3252
 
3245
 
3253
	if (i == arg_obj->properties->count)
3246
	if (i == arg_obj->properties->count)
3254
		goto out;
3247
		goto out;
3255
 
3248
 
3256
	prop_obj = drm_mode_object_find(dev, arg->prop_id,
3249
	prop_obj = drm_mode_object_find(dev, arg->prop_id,
3257
					DRM_MODE_OBJECT_PROPERTY);
3250
					DRM_MODE_OBJECT_PROPERTY);
3258
	if (!prop_obj)
3251
	if (!prop_obj)
3259
			goto out;
3252
			goto out;
3260
	property = obj_to_property(prop_obj);
3253
	property = obj_to_property(prop_obj);
3261
 
3254
 
3262
	if (!drm_property_change_is_valid(property, arg->value))
3255
	if (!drm_property_change_is_valid(property, arg->value))
3263
			goto out;
3256
			goto out;
3264
 
3257
 
3265
	switch (arg_obj->type) {
3258
	switch (arg_obj->type) {
3266
	case DRM_MODE_OBJECT_CONNECTOR:
3259
	case DRM_MODE_OBJECT_CONNECTOR:
3267
		ret = drm_mode_connector_set_obj_prop(arg_obj, property,
3260
		ret = drm_mode_connector_set_obj_prop(arg_obj, property,
3268
						      arg->value);
3261
						      arg->value);
3269
		break;
3262
		break;
3270
	case DRM_MODE_OBJECT_CRTC:
3263
	case DRM_MODE_OBJECT_CRTC:
3271
		ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
3264
		ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
3272
		break;
3265
		break;
3273
	case DRM_MODE_OBJECT_PLANE:
3266
	case DRM_MODE_OBJECT_PLANE:
3274
		ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
3267
		ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
3275
				break;
3268
				break;
3276
			}
3269
			}
3277
 
3270
 
3278
out:
3271
out:
3279
	mutex_unlock(&dev->mode_config.mutex);
3272
	mutex_unlock(&dev->mode_config.mutex);
3280
	return ret;
3273
	return ret;
3281
}
3274
}
3282
#endif
3275
#endif
3283
 
3276
 
3284
int drm_mode_connector_attach_encoder(struct drm_connector *connector,
3277
int drm_mode_connector_attach_encoder(struct drm_connector *connector,
3285
				      struct drm_encoder *encoder)
3278
				      struct drm_encoder *encoder)
3286
{
3279
{
3287
	int i;
3280
	int i;
3288
 
3281
 
3289
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3282
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3290
		if (connector->encoder_ids[i] == 0) {
3283
		if (connector->encoder_ids[i] == 0) {
3291
			connector->encoder_ids[i] = encoder->base.id;
3284
			connector->encoder_ids[i] = encoder->base.id;
3292
			return 0;
3285
			return 0;
3293
		}
3286
		}
3294
	}
3287
	}
3295
	return -ENOMEM;
3288
	return -ENOMEM;
3296
}
3289
}
3297
EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
3290
EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
3298
 
3291
 
3299
void drm_mode_connector_detach_encoder(struct drm_connector *connector,
3292
void drm_mode_connector_detach_encoder(struct drm_connector *connector,
3300
				    struct drm_encoder *encoder)
3293
				    struct drm_encoder *encoder)
3301
{
3294
{
3302
	int i;
3295
	int i;
3303
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3296
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3304
		if (connector->encoder_ids[i] == encoder->base.id) {
3297
		if (connector->encoder_ids[i] == encoder->base.id) {
3305
			connector->encoder_ids[i] = 0;
3298
			connector->encoder_ids[i] = 0;
3306
			if (connector->encoder == encoder)
3299
			if (connector->encoder == encoder)
3307
				connector->encoder = NULL;
3300
				connector->encoder = NULL;
3308
			break;
3301
			break;
3309
		}
3302
		}
3310
	}
3303
	}
3311
}
3304
}
3312
EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
3305
EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
3313
 
3306
 
3314
int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
3307
int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
3315
				  int gamma_size)
3308
				  int gamma_size)
3316
{
3309
{
3317
	crtc->gamma_size = gamma_size;
3310
	crtc->gamma_size = gamma_size;
3318
 
3311
 
3319
	crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL);
3312
	crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL);
3320
	if (!crtc->gamma_store) {
3313
	if (!crtc->gamma_store) {
3321
		crtc->gamma_size = 0;
3314
		crtc->gamma_size = 0;
3322
		return -ENOMEM;
3315
		return -ENOMEM;
3323
	}
3316
	}
3324
 
3317
 
3325
	return 0;
3318
	return 0;
3326
}
3319
}
3327
EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
3320
EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
3328
 
3321
 
3329
#if 0
3322
#if 0
3330
int drm_mode_gamma_set_ioctl(struct drm_device *dev,
3323
int drm_mode_gamma_set_ioctl(struct drm_device *dev,
3331
			     void *data, struct drm_file *file_priv)
3324
			     void *data, struct drm_file *file_priv)
3332
{
3325
{
3333
	struct drm_mode_crtc_lut *crtc_lut = data;
3326
	struct drm_mode_crtc_lut *crtc_lut = data;
3334
	struct drm_mode_object *obj;
3327
	struct drm_mode_object *obj;
3335
	struct drm_crtc *crtc;
3328
	struct drm_crtc *crtc;
3336
	void *r_base, *g_base, *b_base;
3329
	void *r_base, *g_base, *b_base;
3337
	int size;
3330
	int size;
3338
	int ret = 0;
3331
	int ret = 0;
3339
 
3332
 
3340
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3333
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3341
		return -EINVAL;
3334
		return -EINVAL;
3342
 
3335
 
3343
	mutex_lock(&dev->mode_config.mutex);
3336
	mutex_lock(&dev->mode_config.mutex);
3344
	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3337
	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3345
	if (!obj) {
3338
	if (!obj) {
3346
		ret = -EINVAL;
3339
		ret = -EINVAL;
3347
		goto out;
3340
		goto out;
3348
	}
3341
	}
3349
	crtc = obj_to_crtc(obj);
3342
	crtc = obj_to_crtc(obj);
3350
 
3343
 
3351
	if (crtc->funcs->gamma_set == NULL) {
3344
	if (crtc->funcs->gamma_set == NULL) {
3352
		ret = -ENOSYS;
3345
		ret = -ENOSYS;
3353
		goto out;
3346
		goto out;
3354
	}
3347
	}
3355
 
3348
 
3356
	/* memcpy into gamma store */
3349
	/* memcpy into gamma store */
3357
	if (crtc_lut->gamma_size != crtc->gamma_size) {
3350
	if (crtc_lut->gamma_size != crtc->gamma_size) {
3358
		ret = -EINVAL;
3351
		ret = -EINVAL;
3359
		goto out;
3352
		goto out;
3360
	}
3353
	}
3361
 
3354
 
3362
	size = crtc_lut->gamma_size * (sizeof(uint16_t));
3355
	size = crtc_lut->gamma_size * (sizeof(uint16_t));
3363
	r_base = crtc->gamma_store;
3356
	r_base = crtc->gamma_store;
3364
	if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
3357
	if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
3365
		ret = -EFAULT;
3358
		ret = -EFAULT;
3366
		goto out;
3359
		goto out;
3367
	}
3360
	}
3368
 
3361
 
3369
	g_base = r_base + size;
3362
	g_base = r_base + size;
3370
	if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
3363
	if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
3371
		ret = -EFAULT;
3364
		ret = -EFAULT;
3372
		goto out;
3365
		goto out;
3373
	}
3366
	}
3374
 
3367
 
3375
	b_base = g_base + size;
3368
	b_base = g_base + size;
3376
	if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
3369
	if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
3377
		ret = -EFAULT;
3370
		ret = -EFAULT;
3378
		goto out;
3371
		goto out;
3379
	}
3372
	}
3380
 
3373
 
3381
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
3374
	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
3382
 
3375
 
3383
out:
3376
out:
3384
	mutex_unlock(&dev->mode_config.mutex);
3377
	mutex_unlock(&dev->mode_config.mutex);
3385
	return ret;
3378
	return ret;
3386
 
3379
 
3387
}
3380
}
3388
 
3381
 
3389
int drm_mode_gamma_get_ioctl(struct drm_device *dev,
3382
int drm_mode_gamma_get_ioctl(struct drm_device *dev,
3390
			     void *data, struct drm_file *file_priv)
3383
			     void *data, struct drm_file *file_priv)
3391
{
3384
{
3392
	struct drm_mode_crtc_lut *crtc_lut = data;
3385
	struct drm_mode_crtc_lut *crtc_lut = data;
3393
	struct drm_mode_object *obj;
3386
	struct drm_mode_object *obj;
3394
	struct drm_crtc *crtc;
3387
	struct drm_crtc *crtc;
3395
	void *r_base, *g_base, *b_base;
3388
	void *r_base, *g_base, *b_base;
3396
	int size;
3389
	int size;
3397
	int ret = 0;
3390
	int ret = 0;
3398
 
3391
 
3399
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3392
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
3400
		return -EINVAL;
3393
		return -EINVAL;
3401
 
3394
 
3402
	mutex_lock(&dev->mode_config.mutex);
3395
	mutex_lock(&dev->mode_config.mutex);
3403
	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3396
	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3404
	if (!obj) {
3397
	if (!obj) {
3405
		ret = -EINVAL;
3398
		ret = -EINVAL;
3406
		goto out;
3399
		goto out;
3407
	}
3400
	}
3408
	crtc = obj_to_crtc(obj);
3401
	crtc = obj_to_crtc(obj);
3409
 
3402
 
3410
	/* memcpy into gamma store */
3403
	/* memcpy into gamma store */
3411
	if (crtc_lut->gamma_size != crtc->gamma_size) {
3404
	if (crtc_lut->gamma_size != crtc->gamma_size) {
3412
		ret = -EINVAL;
3405
		ret = -EINVAL;
3413
		goto out;
3406
		goto out;
3414
	}
3407
	}
3415
 
3408
 
3416
	size = crtc_lut->gamma_size * (sizeof(uint16_t));
3409
	size = crtc_lut->gamma_size * (sizeof(uint16_t));
3417
	r_base = crtc->gamma_store;
3410
	r_base = crtc->gamma_store;
3418
	if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
3411
	if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
3419
		ret = -EFAULT;
3412
		ret = -EFAULT;
3420
		goto out;
3413
		goto out;
3421
	}
3414
	}
3422
 
3415
 
3423
	g_base = r_base + size;
3416
	g_base = r_base + size;
3424
	if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
3417
	if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
3425
		ret = -EFAULT;
3418
		ret = -EFAULT;
3426
		goto out;
3419
		goto out;
3427
	}
3420
	}
3428
 
3421
 
3429
	b_base = g_base + size;
3422
	b_base = g_base + size;
3430
	if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
3423
	if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
3431
		ret = -EFAULT;
3424
		ret = -EFAULT;
3432
		goto out;
3425
		goto out;
3433
	}
3426
	}
3434
out:
3427
out:
3435
	mutex_unlock(&dev->mode_config.mutex);
3428
	mutex_unlock(&dev->mode_config.mutex);
3436
	return ret;
3429
	return ret;
3437
}
3430
}
3438
 
3431
 
3439
#endif
3432
#endif
3440
 
3433
 
3441
 
3434
 
3442
void drm_mode_config_reset(struct drm_device *dev)
3435
void drm_mode_config_reset(struct drm_device *dev)
3443
{
3436
{
3444
	struct drm_crtc *crtc;
3437
	struct drm_crtc *crtc;
3445
	struct drm_encoder *encoder;
3438
	struct drm_encoder *encoder;
3446
	struct drm_connector *connector;
3439
	struct drm_connector *connector;
3447
 
3440
 
3448
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
3441
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
3449
		if (crtc->funcs->reset)
3442
		if (crtc->funcs->reset)
3450
			crtc->funcs->reset(crtc);
3443
			crtc->funcs->reset(crtc);
3451
 
3444
 
3452
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
3445
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
3453
		if (encoder->funcs->reset)
3446
		if (encoder->funcs->reset)
3454
			encoder->funcs->reset(encoder);
3447
			encoder->funcs->reset(encoder);
3455
 
3448
 
-
 
3449
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-
 
3450
		connector->status = connector_status_unknown;
3456
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
3451
 
3457
		if (connector->funcs->reset)
3452
		if (connector->funcs->reset)
3458
			connector->funcs->reset(connector);
3453
			connector->funcs->reset(connector);
3459
}
3454
	}
-
 
3455
}
3460
EXPORT_SYMBOL(drm_mode_config_reset);
3456
EXPORT_SYMBOL(drm_mode_config_reset);
3461
/*
3457
/*
3462
 * Just need to support RGB formats here for compat with code that doesn't
3458
 * Just need to support RGB formats here for compat with code that doesn't
3463
 * use pixel formats directly yet.
3459
 * use pixel formats directly yet.
3464
 */
3460
 */
3465
void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
3461
void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
3466
			  int *bpp)
3462
			  int *bpp)
3467
{
3463
{
3468
	switch (format) {
3464
	switch (format) {
3469
	case DRM_FORMAT_RGB332:
3465
	case DRM_FORMAT_RGB332:
3470
	case DRM_FORMAT_BGR233:
3466
	case DRM_FORMAT_BGR233:
3471
		*depth = 8;
3467
		*depth = 8;
3472
		*bpp = 8;
3468
		*bpp = 8;
3473
		break;
3469
		break;
3474
	case DRM_FORMAT_XRGB1555:
3470
	case DRM_FORMAT_XRGB1555:
3475
	case DRM_FORMAT_XBGR1555:
3471
	case DRM_FORMAT_XBGR1555:
3476
	case DRM_FORMAT_RGBX5551:
3472
	case DRM_FORMAT_RGBX5551:
3477
	case DRM_FORMAT_BGRX5551:
3473
	case DRM_FORMAT_BGRX5551:
3478
	case DRM_FORMAT_ARGB1555:
3474
	case DRM_FORMAT_ARGB1555:
3479
	case DRM_FORMAT_ABGR1555:
3475
	case DRM_FORMAT_ABGR1555:
3480
	case DRM_FORMAT_RGBA5551:
3476
	case DRM_FORMAT_RGBA5551:
3481
	case DRM_FORMAT_BGRA5551:
3477
	case DRM_FORMAT_BGRA5551:
3482
		*depth = 15;
3478
		*depth = 15;
3483
		*bpp = 16;
3479
		*bpp = 16;
3484
		break;
3480
		break;
3485
	case DRM_FORMAT_RGB565:
3481
	case DRM_FORMAT_RGB565:
3486
	case DRM_FORMAT_BGR565:
3482
	case DRM_FORMAT_BGR565:
3487
		*depth = 16;
3483
		*depth = 16;
3488
		*bpp = 16;
3484
		*bpp = 16;
3489
		break;
3485
		break;
3490
	case DRM_FORMAT_RGB888:
3486
	case DRM_FORMAT_RGB888:
3491
	case DRM_FORMAT_BGR888:
3487
	case DRM_FORMAT_BGR888:
3492
		*depth = 24;
3488
		*depth = 24;
3493
		*bpp = 24;
3489
		*bpp = 24;
3494
		break;
3490
		break;
3495
	case DRM_FORMAT_XRGB8888:
3491
	case DRM_FORMAT_XRGB8888:
3496
	case DRM_FORMAT_XBGR8888:
3492
	case DRM_FORMAT_XBGR8888:
3497
	case DRM_FORMAT_RGBX8888:
3493
	case DRM_FORMAT_RGBX8888:
3498
	case DRM_FORMAT_BGRX8888:
3494
	case DRM_FORMAT_BGRX8888:
3499
		*depth = 24;
3495
		*depth = 24;
3500
		*bpp = 32;
3496
		*bpp = 32;
3501
		break;
3497
		break;
3502
	case DRM_FORMAT_XRGB2101010:
3498
	case DRM_FORMAT_XRGB2101010:
3503
	case DRM_FORMAT_XBGR2101010:
3499
	case DRM_FORMAT_XBGR2101010:
3504
	case DRM_FORMAT_RGBX1010102:
3500
	case DRM_FORMAT_RGBX1010102:
3505
	case DRM_FORMAT_BGRX1010102:
3501
	case DRM_FORMAT_BGRX1010102:
3506
	case DRM_FORMAT_ARGB2101010:
3502
	case DRM_FORMAT_ARGB2101010:
3507
	case DRM_FORMAT_ABGR2101010:
3503
	case DRM_FORMAT_ABGR2101010:
3508
	case DRM_FORMAT_RGBA1010102:
3504
	case DRM_FORMAT_RGBA1010102:
3509
	case DRM_FORMAT_BGRA1010102:
3505
	case DRM_FORMAT_BGRA1010102:
3510
		*depth = 30;
3506
		*depth = 30;
3511
		*bpp = 32;
3507
		*bpp = 32;
3512
		break;
3508
		break;
3513
	case DRM_FORMAT_ARGB8888:
3509
	case DRM_FORMAT_ARGB8888:
3514
	case DRM_FORMAT_ABGR8888:
3510
	case DRM_FORMAT_ABGR8888:
3515
	case DRM_FORMAT_RGBA8888:
3511
	case DRM_FORMAT_RGBA8888:
3516
	case DRM_FORMAT_BGRA8888:
3512
	case DRM_FORMAT_BGRA8888:
3517
		*depth = 32;
3513
		*depth = 32;
3518
		*bpp = 32;
3514
		*bpp = 32;
3519
		break;
3515
		break;
3520
	default:
3516
	default:
3521
		DRM_DEBUG_KMS("unsupported pixel format\n");
3517
		DRM_DEBUG_KMS("unsupported pixel format\n");
3522
		*depth = 0;
3518
		*depth = 0;
3523
		*bpp = 0;
3519
		*bpp = 0;
3524
		break;
3520
		break;
3525
	}
3521
	}
3526
}
3522
}
3527
EXPORT_SYMBOL(drm_fb_get_bpp_depth);
3523
EXPORT_SYMBOL(drm_fb_get_bpp_depth);
3528
 
3524
 
3529
/**
3525
/**
3530
 * drm_format_num_planes - get the number of planes for format
3526
 * drm_format_num_planes - get the number of planes for format
3531
 * @format: pixel format (DRM_FORMAT_*)
3527
 * @format: pixel format (DRM_FORMAT_*)
3532
 *
3528
 *
3533
 * RETURNS:
3529
 * RETURNS:
3534
 * The number of planes used by the specified pixel format.
3530
 * The number of planes used by the specified pixel format.
3535
 */
3531
 */
3536
int drm_format_num_planes(uint32_t format)
3532
int drm_format_num_planes(uint32_t format)
3537
{
3533
{
3538
	switch (format) {
3534
	switch (format) {
3539
	case DRM_FORMAT_YUV410:
3535
	case DRM_FORMAT_YUV410:
3540
	case DRM_FORMAT_YVU410:
3536
	case DRM_FORMAT_YVU410:
3541
	case DRM_FORMAT_YUV411:
3537
	case DRM_FORMAT_YUV411:
3542
	case DRM_FORMAT_YVU411:
3538
	case DRM_FORMAT_YVU411:
3543
	case DRM_FORMAT_YUV420:
3539
	case DRM_FORMAT_YUV420:
3544
	case DRM_FORMAT_YVU420:
3540
	case DRM_FORMAT_YVU420:
3545
	case DRM_FORMAT_YUV422:
3541
	case DRM_FORMAT_YUV422:
3546
	case DRM_FORMAT_YVU422:
3542
	case DRM_FORMAT_YVU422:
3547
	case DRM_FORMAT_YUV444:
3543
	case DRM_FORMAT_YUV444:
3548
	case DRM_FORMAT_YVU444:
3544
	case DRM_FORMAT_YVU444:
3549
		return 3;
3545
		return 3;
3550
	case DRM_FORMAT_NV12:
3546
	case DRM_FORMAT_NV12:
3551
	case DRM_FORMAT_NV21:
3547
	case DRM_FORMAT_NV21:
3552
	case DRM_FORMAT_NV16:
3548
	case DRM_FORMAT_NV16:
3553
	case DRM_FORMAT_NV61:
3549
	case DRM_FORMAT_NV61:
3554
	case DRM_FORMAT_NV24:
3550
	case DRM_FORMAT_NV24:
3555
	case DRM_FORMAT_NV42:
3551
	case DRM_FORMAT_NV42:
3556
		return 2;
3552
		return 2;
3557
	default:
3553
	default:
3558
		return 1;
3554
		return 1;
3559
	}
3555
	}
3560
}
3556
}
3561
EXPORT_SYMBOL(drm_format_num_planes);
3557
EXPORT_SYMBOL(drm_format_num_planes);
3562
 
3558
 
3563
/**
3559
/**
3564
 * drm_format_plane_cpp - determine the bytes per pixel value
3560
 * drm_format_plane_cpp - determine the bytes per pixel value
3565
 * @format: pixel format (DRM_FORMAT_*)
3561
 * @format: pixel format (DRM_FORMAT_*)
3566
 * @plane: plane index
3562
 * @plane: plane index
3567
 *
3563
 *
3568
 * RETURNS:
3564
 * RETURNS:
3569
 * The bytes per pixel value for the specified plane.
3565
 * The bytes per pixel value for the specified plane.
3570
 */
3566
 */
3571
int drm_format_plane_cpp(uint32_t format, int plane)
3567
int drm_format_plane_cpp(uint32_t format, int plane)
3572
{
3568
{
3573
	unsigned int depth;
3569
	unsigned int depth;
3574
	int bpp;
3570
	int bpp;
3575
 
3571
 
3576
	if (plane >= drm_format_num_planes(format))
3572
	if (plane >= drm_format_num_planes(format))
3577
		return 0;
3573
		return 0;
3578
 
3574
 
3579
	switch (format) {
3575
	switch (format) {
3580
	case DRM_FORMAT_YUYV:
3576
	case DRM_FORMAT_YUYV:
3581
	case DRM_FORMAT_YVYU:
3577
	case DRM_FORMAT_YVYU:
3582
	case DRM_FORMAT_UYVY:
3578
	case DRM_FORMAT_UYVY:
3583
	case DRM_FORMAT_VYUY:
3579
	case DRM_FORMAT_VYUY:
3584
		return 2;
3580
		return 2;
3585
	case DRM_FORMAT_NV12:
3581
	case DRM_FORMAT_NV12:
3586
	case DRM_FORMAT_NV21:
3582
	case DRM_FORMAT_NV21:
3587
	case DRM_FORMAT_NV16:
3583
	case DRM_FORMAT_NV16:
3588
	case DRM_FORMAT_NV61:
3584
	case DRM_FORMAT_NV61:
3589
	case DRM_FORMAT_NV24:
3585
	case DRM_FORMAT_NV24:
3590
	case DRM_FORMAT_NV42:
3586
	case DRM_FORMAT_NV42:
3591
		return plane ? 2 : 1;
3587
		return plane ? 2 : 1;
3592
	case DRM_FORMAT_YUV410:
3588
	case DRM_FORMAT_YUV410:
3593
	case DRM_FORMAT_YVU410:
3589
	case DRM_FORMAT_YVU410:
3594
	case DRM_FORMAT_YUV411:
3590
	case DRM_FORMAT_YUV411:
3595
	case DRM_FORMAT_YVU411:
3591
	case DRM_FORMAT_YVU411:
3596
	case DRM_FORMAT_YUV420:
3592
	case DRM_FORMAT_YUV420:
3597
	case DRM_FORMAT_YVU420:
3593
	case DRM_FORMAT_YVU420:
3598
	case DRM_FORMAT_YUV422:
3594
	case DRM_FORMAT_YUV422:
3599
	case DRM_FORMAT_YVU422:
3595
	case DRM_FORMAT_YVU422:
3600
	case DRM_FORMAT_YUV444:
3596
	case DRM_FORMAT_YUV444:
3601
	case DRM_FORMAT_YVU444:
3597
	case DRM_FORMAT_YVU444:
3602
		return 1;
3598
		return 1;
3603
	default:
3599
	default:
3604
		drm_fb_get_bpp_depth(format, &depth, &bpp);
3600
		drm_fb_get_bpp_depth(format, &depth, &bpp);
3605
		return bpp >> 3;
3601
		return bpp >> 3;
3606
	}
3602
	}
3607
}
3603
}
3608
EXPORT_SYMBOL(drm_format_plane_cpp);
3604
EXPORT_SYMBOL(drm_format_plane_cpp);
3609
 
3605
 
3610
/**
3606
/**
3611
 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
3607
 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
3612
 * @format: pixel format (DRM_FORMAT_*)
3608
 * @format: pixel format (DRM_FORMAT_*)
3613
 *
3609
 *
3614
 * RETURNS:
3610
 * RETURNS:
3615
 * The horizontal chroma subsampling factor for the
3611
 * The horizontal chroma subsampling factor for the
3616
 * specified pixel format.
3612
 * specified pixel format.
3617
 */
3613
 */
3618
int drm_format_horz_chroma_subsampling(uint32_t format)
3614
int drm_format_horz_chroma_subsampling(uint32_t format)
3619
{
3615
{
3620
	switch (format) {
3616
	switch (format) {
3621
	case DRM_FORMAT_YUV411:
3617
	case DRM_FORMAT_YUV411:
3622
	case DRM_FORMAT_YVU411:
3618
	case DRM_FORMAT_YVU411:
3623
	case DRM_FORMAT_YUV410:
3619
	case DRM_FORMAT_YUV410:
3624
	case DRM_FORMAT_YVU410:
3620
	case DRM_FORMAT_YVU410:
3625
		return 4;
3621
		return 4;
3626
	case DRM_FORMAT_YUYV:
3622
	case DRM_FORMAT_YUYV:
3627
	case DRM_FORMAT_YVYU:
3623
	case DRM_FORMAT_YVYU:
3628
	case DRM_FORMAT_UYVY:
3624
	case DRM_FORMAT_UYVY:
3629
	case DRM_FORMAT_VYUY:
3625
	case DRM_FORMAT_VYUY:
3630
	case DRM_FORMAT_NV12:
3626
	case DRM_FORMAT_NV12:
3631
	case DRM_FORMAT_NV21:
3627
	case DRM_FORMAT_NV21:
3632
	case DRM_FORMAT_NV16:
3628
	case DRM_FORMAT_NV16:
3633
	case DRM_FORMAT_NV61:
3629
	case DRM_FORMAT_NV61:
3634
	case DRM_FORMAT_YUV422:
3630
	case DRM_FORMAT_YUV422:
3635
	case DRM_FORMAT_YVU422:
3631
	case DRM_FORMAT_YVU422:
3636
	case DRM_FORMAT_YUV420:
3632
	case DRM_FORMAT_YUV420:
3637
	case DRM_FORMAT_YVU420:
3633
	case DRM_FORMAT_YVU420:
3638
		return 2;
3634
		return 2;
3639
	default:
3635
	default:
3640
		return 1;
3636
		return 1;
3641
	}
3637
	}
3642
}
3638
}
3643
EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
3639
EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
3644
 
3640
 
3645
/**
3641
/**
3646
 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
3642
 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
3647
 * @format: pixel format (DRM_FORMAT_*)
3643
 * @format: pixel format (DRM_FORMAT_*)
3648
 *
3644
 *
3649
 * RETURNS:
3645
 * RETURNS:
3650
 * The vertical chroma subsampling factor for the
3646
 * The vertical chroma subsampling factor for the
3651
 * specified pixel format.
3647
 * specified pixel format.
3652
 */
3648
 */
3653
int drm_format_vert_chroma_subsampling(uint32_t format)
3649
int drm_format_vert_chroma_subsampling(uint32_t format)
3654
{
3650
{
3655
	switch (format) {
3651
	switch (format) {
3656
	case DRM_FORMAT_YUV410:
3652
	case DRM_FORMAT_YUV410:
3657
	case DRM_FORMAT_YVU410:
3653
	case DRM_FORMAT_YVU410:
3658
		return 4;
3654
		return 4;
3659
	case DRM_FORMAT_YUV420:
3655
	case DRM_FORMAT_YUV420:
3660
	case DRM_FORMAT_YVU420:
3656
	case DRM_FORMAT_YVU420:
3661
	case DRM_FORMAT_NV12:
3657
	case DRM_FORMAT_NV12:
3662
	case DRM_FORMAT_NV21:
3658
	case DRM_FORMAT_NV21:
3663
		return 2;
3659
		return 2;
3664
	default:
3660
	default:
3665
		return 1;
3661
		return 1;
3666
	}
3662
	}
3667
}
3663
}
3668
EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
3664
EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);