Subversion Repositories Kolibri OS

Rev

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