Subversion Repositories Kolibri OS

Rev

Rev 2160 | Rev 3192 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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