Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

DRM: add mode setting support

Add mode setting support to the DRM layer.

This is a fairly big chunk of work that allows DRM drivers to provide
full output control and configuration capabilities to userspace. It was
motivated by several factors:
- the fb layer's APIs aren't suited for anything but simple
configurations
- coordination between the fb layer, DRM layer, and various userspace
drivers is poor to non-existent (radeonfb excepted)
- user level mode setting drivers makes displaying panic & oops
messages more difficult
- suspend/resume of graphics state is possible in many more
configurations with kernel level support

This commit just adds the core DRM part of the mode setting APIs.
Driver specific commits using these new structure and APIs will follow.

Co-authors: Jesse Barnes <jbarnes@virtuousgeek.org>, Jakob Bornecrantz <jakob@tungstengraphics.com>
Contributors: Alan Hourihane <alanh@tungstengraphics.com>, Maarten Maathuis <madman2003@gmail.com>

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Dave Airlie and committed by
Dave Airlie
f453ba04 de151cf6

+6470 -42
+2 -1
drivers/gpu/drm/Makefile
··· 9 9 drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ 10 10 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ 11 11 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ 12 - drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o 12 + drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ 13 + drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o 13 14 14 15 drm-$(CONFIG_COMPAT) += drm_ioc32.o 15 16
+2497
drivers/gpu/drm/drm_crtc.c
··· 1 + /* 2 + * Copyright (c) 2006-2008 Intel Corporation 3 + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 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 <eric@anholt.net> 29 + * Dave Airlie <airlied@linux.ie> 30 + * Jesse Barnes <jesse.barnes@intel.com> 31 + */ 32 + #include <linux/list.h> 33 + #include "drm.h" 34 + #include "drmP.h" 35 + #include "drm_crtc.h" 36 + 37 + struct drm_prop_enum_list { 38 + int type; 39 + char *name; 40 + }; 41 + 42 + /* Avoid boilerplate. I'm tired of typing. */ 43 + #define DRM_ENUM_NAME_FN(fnname, list) \ 44 + char *fnname(int val) \ 45 + { \ 46 + int i; \ 47 + for (i = 0; i < ARRAY_SIZE(list); i++) { \ 48 + if (list[i].type == val) \ 49 + return list[i].name; \ 50 + } \ 51 + return "(unknown)"; \ 52 + } 53 + 54 + /* 55 + * Global properties 56 + */ 57 + static struct drm_prop_enum_list drm_dpms_enum_list[] = 58 + { { DRM_MODE_DPMS_ON, "On" }, 59 + { DRM_MODE_DPMS_STANDBY, "Standby" }, 60 + { DRM_MODE_DPMS_SUSPEND, "Suspend" }, 61 + { DRM_MODE_DPMS_OFF, "Off" } 62 + }; 63 + 64 + DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) 65 + 66 + /* 67 + * Optional properties 68 + */ 69 + static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = 70 + { 71 + { DRM_MODE_SCALE_NON_GPU, "Non-GPU" }, 72 + { DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" }, 73 + { DRM_MODE_SCALE_NO_SCALE, "No scale" }, 74 + { DRM_MODE_SCALE_ASPECT, "Aspect" }, 75 + }; 76 + 77 + static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = 78 + { 79 + { DRM_MODE_DITHERING_OFF, "Off" }, 80 + { DRM_MODE_DITHERING_ON, "On" }, 81 + }; 82 + 83 + /* 84 + * Non-global properties, but "required" for certain connectors. 85 + */ 86 + static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = 87 + { 88 + { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ 89 + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ 90 + { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ 91 + }; 92 + 93 + DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) 94 + 95 + static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = 96 + { 97 + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ 98 + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ 99 + { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ 100 + }; 101 + 102 + DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, 103 + drm_dvi_i_subconnector_enum_list) 104 + 105 + static struct drm_prop_enum_list drm_tv_select_enum_list[] = 106 + { 107 + { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ 108 + { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ 109 + { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ 110 + { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ 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 */ 121 + }; 122 + 123 + DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, 124 + drm_tv_subconnector_enum_list) 125 + 126 + struct drm_conn_prop_enum_list { 127 + int type; 128 + char *name; 129 + int count; 130 + }; 131 + 132 + /* 133 + * Connector and encoder types. 134 + */ 135 + static struct drm_conn_prop_enum_list drm_connector_enum_list[] = 136 + { { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 }, 137 + { DRM_MODE_CONNECTOR_VGA, "VGA", 0 }, 138 + { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 }, 139 + { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 }, 140 + { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 }, 141 + { DRM_MODE_CONNECTOR_Composite, "Composite", 0 }, 142 + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, 143 + { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, 144 + { DRM_MODE_CONNECTOR_Component, "Component", 0 }, 145 + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 }, 146 + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 }, 147 + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, 148 + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, 149 + }; 150 + 151 + static struct drm_prop_enum_list drm_encoder_enum_list[] = 152 + { { DRM_MODE_ENCODER_NONE, "None" }, 153 + { DRM_MODE_ENCODER_DAC, "DAC" }, 154 + { DRM_MODE_ENCODER_TMDS, "TMDS" }, 155 + { DRM_MODE_ENCODER_LVDS, "LVDS" }, 156 + { DRM_MODE_ENCODER_TVDAC, "TV" }, 157 + }; 158 + 159 + char *drm_get_encoder_name(struct drm_encoder *encoder) 160 + { 161 + static char buf[32]; 162 + 163 + snprintf(buf, 32, "%s-%d", 164 + drm_encoder_enum_list[encoder->encoder_type].name, 165 + encoder->base.id); 166 + return buf; 167 + } 168 + 169 + char *drm_get_connector_name(struct drm_connector *connector) 170 + { 171 + static char buf[32]; 172 + 173 + snprintf(buf, 32, "%s-%d", 174 + drm_connector_enum_list[connector->connector_type].name, 175 + connector->connector_type_id); 176 + return buf; 177 + } 178 + EXPORT_SYMBOL(drm_get_connector_name); 179 + 180 + char *drm_get_connector_status_name(enum drm_connector_status status) 181 + { 182 + if (status == connector_status_connected) 183 + return "connected"; 184 + else if (status == connector_status_disconnected) 185 + return "disconnected"; 186 + else 187 + return "unknown"; 188 + } 189 + 190 + /** 191 + * drm_mode_object_get - allocate a new identifier 192 + * @dev: DRM device 193 + * @ptr: object pointer, used to generate unique ID 194 + * @type: object type 195 + * 196 + * LOCKING: 197 + * Caller must hold DRM mode_config lock. 198 + * 199 + * Create a unique identifier based on @ptr in @dev's identifier space. Used 200 + * for tracking modes, CRTCs and connectors. 201 + * 202 + * RETURNS: 203 + * New unique (relative to other objects in @dev) integer identifier for the 204 + * object. 205 + */ 206 + static int drm_mode_object_get(struct drm_device *dev, 207 + struct drm_mode_object *obj, uint32_t obj_type) 208 + { 209 + int new_id = 0; 210 + int ret; 211 + 212 + WARN(!mutex_is_locked(&dev->mode_config.mutex), 213 + "%s called w/o mode_config lock\n", __FUNCTION__); 214 + again: 215 + if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { 216 + DRM_ERROR("Ran out memory getting a mode number\n"); 217 + return -EINVAL; 218 + } 219 + 220 + ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); 221 + if (ret == -EAGAIN) 222 + goto again; 223 + 224 + obj->id = new_id; 225 + obj->type = obj_type; 226 + return 0; 227 + } 228 + 229 + /** 230 + * drm_mode_object_put - free an identifer 231 + * @dev: DRM device 232 + * @id: ID to free 233 + * 234 + * LOCKING: 235 + * Caller must hold DRM mode_config lock. 236 + * 237 + * Free @id from @dev's unique identifier pool. 238 + */ 239 + static void drm_mode_object_put(struct drm_device *dev, 240 + struct drm_mode_object *object) 241 + { 242 + idr_remove(&dev->mode_config.crtc_idr, object->id); 243 + } 244 + 245 + void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) 246 + { 247 + struct drm_mode_object *obj; 248 + 249 + obj = idr_find(&dev->mode_config.crtc_idr, id); 250 + if (!obj || (obj->type != type) || (obj->id != id)) 251 + return NULL; 252 + 253 + return obj; 254 + } 255 + EXPORT_SYMBOL(drm_mode_object_find); 256 + 257 + /** 258 + * drm_crtc_from_fb - find the CRTC structure associated with an fb 259 + * @dev: DRM device 260 + * @fb: framebuffer in question 261 + * 262 + * LOCKING: 263 + * Caller must hold mode_config lock. 264 + * 265 + * Find CRTC in the mode_config structure that matches @fb. 266 + * 267 + * RETURNS: 268 + * Pointer to the CRTC or NULL if it wasn't found. 269 + */ 270 + struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, 271 + struct drm_framebuffer *fb) 272 + { 273 + struct drm_crtc *crtc; 274 + 275 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 276 + if (crtc->fb == fb) 277 + return crtc; 278 + } 279 + return NULL; 280 + } 281 + 282 + /** 283 + * drm_framebuffer_init - initialize a framebuffer 284 + * @dev: DRM device 285 + * 286 + * LOCKING: 287 + * Caller must hold mode config lock. 288 + * 289 + * Allocates an ID for the framebuffer's parent mode object, sets its mode 290 + * functions & device file and adds it to the master fd list. 291 + * 292 + * RETURNS: 293 + * Zero on success, error code on falure. 294 + */ 295 + int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, 296 + const struct drm_framebuffer_funcs *funcs) 297 + { 298 + int ret; 299 + 300 + ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); 301 + if (ret) { 302 + return ret; 303 + } 304 + 305 + fb->dev = dev; 306 + fb->funcs = funcs; 307 + dev->mode_config.num_fb++; 308 + list_add(&fb->head, &dev->mode_config.fb_list); 309 + 310 + return 0; 311 + } 312 + EXPORT_SYMBOL(drm_framebuffer_init); 313 + 314 + /** 315 + * drm_framebuffer_cleanup - remove a framebuffer object 316 + * @fb: framebuffer to remove 317 + * 318 + * LOCKING: 319 + * Caller must hold mode config lock. 320 + * 321 + * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes 322 + * it, setting it to NULL. 323 + */ 324 + void drm_framebuffer_cleanup(struct drm_framebuffer *fb) 325 + { 326 + struct drm_device *dev = fb->dev; 327 + struct drm_crtc *crtc; 328 + 329 + /* remove from any CRTC */ 330 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 331 + if (crtc->fb == fb) 332 + crtc->fb = NULL; 333 + } 334 + 335 + drm_mode_object_put(dev, &fb->base); 336 + list_del(&fb->head); 337 + dev->mode_config.num_fb--; 338 + } 339 + EXPORT_SYMBOL(drm_framebuffer_cleanup); 340 + 341 + /** 342 + * drm_crtc_init - Initialise a new CRTC object 343 + * @dev: DRM device 344 + * @crtc: CRTC object to init 345 + * @funcs: callbacks for the new CRTC 346 + * 347 + * LOCKING: 348 + * Caller must hold mode config lock. 349 + * 350 + * Inits a new object created as base part of an driver crtc object. 351 + */ 352 + void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 353 + const struct drm_crtc_funcs *funcs) 354 + { 355 + crtc->dev = dev; 356 + crtc->funcs = funcs; 357 + 358 + mutex_lock(&dev->mode_config.mutex); 359 + drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 360 + 361 + list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 362 + dev->mode_config.num_crtc++; 363 + mutex_unlock(&dev->mode_config.mutex); 364 + } 365 + EXPORT_SYMBOL(drm_crtc_init); 366 + 367 + /** 368 + * drm_crtc_cleanup - Cleans up the core crtc usage. 369 + * @crtc: CRTC to cleanup 370 + * 371 + * LOCKING: 372 + * Caller must hold mode config lock. 373 + * 374 + * Cleanup @crtc. Removes from drm modesetting space 375 + * does NOT free object, caller does that. 376 + */ 377 + void drm_crtc_cleanup(struct drm_crtc *crtc) 378 + { 379 + struct drm_device *dev = crtc->dev; 380 + 381 + if (crtc->gamma_store) { 382 + kfree(crtc->gamma_store); 383 + crtc->gamma_store = NULL; 384 + } 385 + 386 + drm_mode_object_put(dev, &crtc->base); 387 + list_del(&crtc->head); 388 + dev->mode_config.num_crtc--; 389 + } 390 + EXPORT_SYMBOL(drm_crtc_cleanup); 391 + 392 + /** 393 + * drm_mode_probed_add - add a mode to a connector's probed mode list 394 + * @connector: connector the new mode 395 + * @mode: mode data 396 + * 397 + * LOCKING: 398 + * Caller must hold mode config lock. 399 + * 400 + * Add @mode to @connector's mode list for later use. 401 + */ 402 + void drm_mode_probed_add(struct drm_connector *connector, 403 + struct drm_display_mode *mode) 404 + { 405 + list_add(&mode->head, &connector->probed_modes); 406 + } 407 + EXPORT_SYMBOL(drm_mode_probed_add); 408 + 409 + /** 410 + * drm_mode_remove - remove and free a mode 411 + * @connector: connector list to modify 412 + * @mode: mode to remove 413 + * 414 + * LOCKING: 415 + * Caller must hold mode config lock. 416 + * 417 + * Remove @mode from @connector's mode list, then free it. 418 + */ 419 + void drm_mode_remove(struct drm_connector *connector, 420 + struct drm_display_mode *mode) 421 + { 422 + list_del(&mode->head); 423 + kfree(mode); 424 + } 425 + EXPORT_SYMBOL(drm_mode_remove); 426 + 427 + /** 428 + * drm_connector_init - Init a preallocated connector 429 + * @dev: DRM device 430 + * @connector: the connector to init 431 + * @funcs: callbacks for this connector 432 + * @name: user visible name of the connector 433 + * 434 + * LOCKING: 435 + * Caller must hold @dev's mode_config lock. 436 + * 437 + * Initialises a preallocated connector. Connectors should be 438 + * subclassed as part of driver connector objects. 439 + */ 440 + void drm_connector_init(struct drm_device *dev, 441 + struct drm_connector *connector, 442 + const struct drm_connector_funcs *funcs, 443 + int connector_type) 444 + { 445 + mutex_lock(&dev->mode_config.mutex); 446 + 447 + connector->dev = dev; 448 + connector->funcs = funcs; 449 + drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); 450 + connector->connector_type = connector_type; 451 + connector->connector_type_id = 452 + ++drm_connector_enum_list[connector_type].count; /* TODO */ 453 + INIT_LIST_HEAD(&connector->user_modes); 454 + INIT_LIST_HEAD(&connector->probed_modes); 455 + INIT_LIST_HEAD(&connector->modes); 456 + connector->edid_blob_ptr = NULL; 457 + 458 + list_add_tail(&connector->head, &dev->mode_config.connector_list); 459 + dev->mode_config.num_connector++; 460 + 461 + drm_connector_attach_property(connector, 462 + dev->mode_config.edid_property, 0); 463 + 464 + drm_connector_attach_property(connector, 465 + dev->mode_config.dpms_property, 0); 466 + 467 + mutex_unlock(&dev->mode_config.mutex); 468 + } 469 + EXPORT_SYMBOL(drm_connector_init); 470 + 471 + /** 472 + * drm_connector_cleanup - cleans up an initialised connector 473 + * @connector: connector to cleanup 474 + * 475 + * LOCKING: 476 + * Caller must hold @dev's mode_config lock. 477 + * 478 + * Cleans up the connector but doesn't free the object. 479 + */ 480 + void drm_connector_cleanup(struct drm_connector *connector) 481 + { 482 + struct drm_device *dev = connector->dev; 483 + struct drm_display_mode *mode, *t; 484 + 485 + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) 486 + drm_mode_remove(connector, mode); 487 + 488 + list_for_each_entry_safe(mode, t, &connector->modes, head) 489 + drm_mode_remove(connector, mode); 490 + 491 + list_for_each_entry_safe(mode, t, &connector->user_modes, head) 492 + drm_mode_remove(connector, mode); 493 + 494 + mutex_lock(&dev->mode_config.mutex); 495 + drm_mode_object_put(dev, &connector->base); 496 + list_del(&connector->head); 497 + mutex_unlock(&dev->mode_config.mutex); 498 + } 499 + EXPORT_SYMBOL(drm_connector_cleanup); 500 + 501 + void drm_encoder_init(struct drm_device *dev, 502 + struct drm_encoder *encoder, 503 + const struct drm_encoder_funcs *funcs, 504 + int encoder_type) 505 + { 506 + mutex_lock(&dev->mode_config.mutex); 507 + 508 + encoder->dev = dev; 509 + 510 + drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); 511 + encoder->encoder_type = encoder_type; 512 + encoder->funcs = funcs; 513 + 514 + list_add_tail(&encoder->head, &dev->mode_config.encoder_list); 515 + dev->mode_config.num_encoder++; 516 + 517 + mutex_unlock(&dev->mode_config.mutex); 518 + } 519 + EXPORT_SYMBOL(drm_encoder_init); 520 + 521 + void drm_encoder_cleanup(struct drm_encoder *encoder) 522 + { 523 + struct drm_device *dev = encoder->dev; 524 + mutex_lock(&dev->mode_config.mutex); 525 + drm_mode_object_put(dev, &encoder->base); 526 + list_del(&encoder->head); 527 + mutex_unlock(&dev->mode_config.mutex); 528 + } 529 + EXPORT_SYMBOL(drm_encoder_cleanup); 530 + 531 + /** 532 + * drm_mode_create - create a new display mode 533 + * @dev: DRM device 534 + * 535 + * LOCKING: 536 + * Caller must hold DRM mode_config lock. 537 + * 538 + * Create a new drm_display_mode, give it an ID, and return it. 539 + * 540 + * RETURNS: 541 + * Pointer to new mode on success, NULL on error. 542 + */ 543 + struct drm_display_mode *drm_mode_create(struct drm_device *dev) 544 + { 545 + struct drm_display_mode *nmode; 546 + 547 + nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); 548 + if (!nmode) 549 + return NULL; 550 + 551 + drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE); 552 + return nmode; 553 + } 554 + EXPORT_SYMBOL(drm_mode_create); 555 + 556 + /** 557 + * drm_mode_destroy - remove a mode 558 + * @dev: DRM device 559 + * @mode: mode to remove 560 + * 561 + * LOCKING: 562 + * Caller must hold mode config lock. 563 + * 564 + * Free @mode's unique identifier, then free it. 565 + */ 566 + void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) 567 + { 568 + drm_mode_object_put(dev, &mode->base); 569 + 570 + kfree(mode); 571 + } 572 + EXPORT_SYMBOL(drm_mode_destroy); 573 + 574 + static int drm_mode_create_standard_connector_properties(struct drm_device *dev) 575 + { 576 + struct drm_property *edid; 577 + struct drm_property *dpms; 578 + int i; 579 + 580 + /* 581 + * Standard properties (apply to all connectors) 582 + */ 583 + edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | 584 + DRM_MODE_PROP_IMMUTABLE, 585 + "EDID", 0); 586 + dev->mode_config.edid_property = edid; 587 + 588 + dpms = drm_property_create(dev, DRM_MODE_PROP_ENUM, 589 + "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); 590 + for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) 591 + drm_property_add_enum(dpms, i, drm_dpms_enum_list[i].type, 592 + drm_dpms_enum_list[i].name); 593 + dev->mode_config.dpms_property = dpms; 594 + 595 + return 0; 596 + } 597 + 598 + /** 599 + * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties 600 + * @dev: DRM device 601 + * 602 + * Called by a driver the first time a DVI-I connector is made. 603 + */ 604 + int drm_mode_create_dvi_i_properties(struct drm_device *dev) 605 + { 606 + struct drm_property *dvi_i_selector; 607 + struct drm_property *dvi_i_subconnector; 608 + int i; 609 + 610 + if (dev->mode_config.dvi_i_select_subconnector_property) 611 + return 0; 612 + 613 + dvi_i_selector = 614 + drm_property_create(dev, DRM_MODE_PROP_ENUM, 615 + "select subconnector", 616 + ARRAY_SIZE(drm_dvi_i_select_enum_list)); 617 + for (i = 0; i < ARRAY_SIZE(drm_dvi_i_select_enum_list); i++) 618 + drm_property_add_enum(dvi_i_selector, i, 619 + drm_dvi_i_select_enum_list[i].type, 620 + drm_dvi_i_select_enum_list[i].name); 621 + dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; 622 + 623 + dvi_i_subconnector = 624 + drm_property_create(dev, DRM_MODE_PROP_ENUM | 625 + DRM_MODE_PROP_IMMUTABLE, 626 + "subconnector", 627 + ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); 628 + for (i = 0; i < ARRAY_SIZE(drm_dvi_i_subconnector_enum_list); i++) 629 + drm_property_add_enum(dvi_i_subconnector, i, 630 + drm_dvi_i_subconnector_enum_list[i].type, 631 + drm_dvi_i_subconnector_enum_list[i].name); 632 + dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; 633 + 634 + return 0; 635 + } 636 + EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); 637 + 638 + /** 639 + * drm_create_tv_properties - create TV specific connector properties 640 + * @dev: DRM device 641 + * @num_modes: number of different TV formats (modes) supported 642 + * @modes: array of pointers to strings containing name of each format 643 + * 644 + * Called by a driver's TV initialization routine, this function creates 645 + * the TV specific connector properties for a given device. Caller is 646 + * responsible for allocating a list of format names and passing them to 647 + * this routine. 648 + */ 649 + int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, 650 + char *modes[]) 651 + { 652 + struct drm_property *tv_selector; 653 + struct drm_property *tv_subconnector; 654 + int i; 655 + 656 + if (dev->mode_config.tv_select_subconnector_property) 657 + return 0; 658 + 659 + /* 660 + * Basic connector properties 661 + */ 662 + tv_selector = drm_property_create(dev, DRM_MODE_PROP_ENUM, 663 + "select subconnector", 664 + ARRAY_SIZE(drm_tv_select_enum_list)); 665 + for (i = 0; i < ARRAY_SIZE(drm_tv_select_enum_list); i++) 666 + drm_property_add_enum(tv_selector, i, 667 + drm_tv_select_enum_list[i].type, 668 + drm_tv_select_enum_list[i].name); 669 + dev->mode_config.tv_select_subconnector_property = tv_selector; 670 + 671 + tv_subconnector = 672 + drm_property_create(dev, DRM_MODE_PROP_ENUM | 673 + DRM_MODE_PROP_IMMUTABLE, "subconnector", 674 + ARRAY_SIZE(drm_tv_subconnector_enum_list)); 675 + for (i = 0; i < ARRAY_SIZE(drm_tv_subconnector_enum_list); i++) 676 + drm_property_add_enum(tv_subconnector, i, 677 + drm_tv_subconnector_enum_list[i].type, 678 + drm_tv_subconnector_enum_list[i].name); 679 + dev->mode_config.tv_subconnector_property = tv_subconnector; 680 + 681 + /* 682 + * Other, TV specific properties: margins & TV modes. 683 + */ 684 + dev->mode_config.tv_left_margin_property = 685 + drm_property_create(dev, DRM_MODE_PROP_RANGE, 686 + "left margin", 2); 687 + dev->mode_config.tv_left_margin_property->values[0] = 0; 688 + dev->mode_config.tv_left_margin_property->values[1] = 100; 689 + 690 + dev->mode_config.tv_right_margin_property = 691 + drm_property_create(dev, DRM_MODE_PROP_RANGE, 692 + "right margin", 2); 693 + dev->mode_config.tv_right_margin_property->values[0] = 0; 694 + dev->mode_config.tv_right_margin_property->values[1] = 100; 695 + 696 + dev->mode_config.tv_top_margin_property = 697 + drm_property_create(dev, DRM_MODE_PROP_RANGE, 698 + "top margin", 2); 699 + dev->mode_config.tv_top_margin_property->values[0] = 0; 700 + dev->mode_config.tv_top_margin_property->values[1] = 100; 701 + 702 + dev->mode_config.tv_bottom_margin_property = 703 + drm_property_create(dev, DRM_MODE_PROP_RANGE, 704 + "bottom margin", 2); 705 + dev->mode_config.tv_bottom_margin_property->values[0] = 0; 706 + dev->mode_config.tv_bottom_margin_property->values[1] = 100; 707 + 708 + dev->mode_config.tv_mode_property = 709 + drm_property_create(dev, DRM_MODE_PROP_ENUM, 710 + "mode", num_modes); 711 + for (i = 0; i < num_modes; i++) 712 + drm_property_add_enum(dev->mode_config.tv_mode_property, i, 713 + i, modes[i]); 714 + 715 + return 0; 716 + } 717 + EXPORT_SYMBOL(drm_mode_create_tv_properties); 718 + 719 + /** 720 + * drm_mode_create_scaling_mode_property - create scaling mode property 721 + * @dev: DRM device 722 + * 723 + * Called by a driver the first time it's needed, must be attached to desired 724 + * connectors. 725 + */ 726 + int drm_mode_create_scaling_mode_property(struct drm_device *dev) 727 + { 728 + struct drm_property *scaling_mode; 729 + int i; 730 + 731 + if (dev->mode_config.scaling_mode_property) 732 + return 0; 733 + 734 + scaling_mode = 735 + drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode", 736 + ARRAY_SIZE(drm_scaling_mode_enum_list)); 737 + for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) 738 + drm_property_add_enum(scaling_mode, i, 739 + drm_scaling_mode_enum_list[i].type, 740 + drm_scaling_mode_enum_list[i].name); 741 + 742 + dev->mode_config.scaling_mode_property = scaling_mode; 743 + 744 + return 0; 745 + } 746 + EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); 747 + 748 + /** 749 + * drm_mode_create_dithering_property - create dithering property 750 + * @dev: DRM device 751 + * 752 + * Called by a driver the first time it's needed, must be attached to desired 753 + * connectors. 754 + */ 755 + int drm_mode_create_dithering_property(struct drm_device *dev) 756 + { 757 + struct drm_property *dithering_mode; 758 + int i; 759 + 760 + if (dev->mode_config.dithering_mode_property) 761 + return 0; 762 + 763 + dithering_mode = 764 + drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering", 765 + ARRAY_SIZE(drm_dithering_mode_enum_list)); 766 + for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++) 767 + drm_property_add_enum(dithering_mode, i, 768 + drm_dithering_mode_enum_list[i].type, 769 + drm_dithering_mode_enum_list[i].name); 770 + dev->mode_config.dithering_mode_property = dithering_mode; 771 + 772 + return 0; 773 + } 774 + EXPORT_SYMBOL(drm_mode_create_dithering_property); 775 + 776 + /** 777 + * drm_mode_config_init - initialize DRM mode_configuration structure 778 + * @dev: DRM device 779 + * 780 + * LOCKING: 781 + * None, should happen single threaded at init time. 782 + * 783 + * Initialize @dev's mode_config structure, used for tracking the graphics 784 + * configuration of @dev. 785 + */ 786 + void drm_mode_config_init(struct drm_device *dev) 787 + { 788 + mutex_init(&dev->mode_config.mutex); 789 + INIT_LIST_HEAD(&dev->mode_config.fb_list); 790 + INIT_LIST_HEAD(&dev->mode_config.fb_kernel_list); 791 + INIT_LIST_HEAD(&dev->mode_config.crtc_list); 792 + INIT_LIST_HEAD(&dev->mode_config.connector_list); 793 + INIT_LIST_HEAD(&dev->mode_config.encoder_list); 794 + INIT_LIST_HEAD(&dev->mode_config.property_list); 795 + INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 796 + idr_init(&dev->mode_config.crtc_idr); 797 + 798 + mutex_lock(&dev->mode_config.mutex); 799 + drm_mode_create_standard_connector_properties(dev); 800 + mutex_unlock(&dev->mode_config.mutex); 801 + 802 + /* Just to be sure */ 803 + dev->mode_config.num_fb = 0; 804 + dev->mode_config.num_connector = 0; 805 + dev->mode_config.num_crtc = 0; 806 + dev->mode_config.num_encoder = 0; 807 + dev->mode_config.hotplug_counter = 0; 808 + } 809 + EXPORT_SYMBOL(drm_mode_config_init); 810 + 811 + int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) 812 + { 813 + uint32_t total_objects = 0; 814 + 815 + total_objects += dev->mode_config.num_crtc; 816 + total_objects += dev->mode_config.num_connector; 817 + total_objects += dev->mode_config.num_encoder; 818 + 819 + if (total_objects == 0) 820 + return -EINVAL; 821 + 822 + group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); 823 + if (!group->id_list) 824 + return -ENOMEM; 825 + 826 + group->num_crtcs = 0; 827 + group->num_connectors = 0; 828 + group->num_encoders = 0; 829 + return 0; 830 + } 831 + 832 + int drm_mode_group_init_legacy_group(struct drm_device *dev, 833 + struct drm_mode_group *group) 834 + { 835 + struct drm_crtc *crtc; 836 + struct drm_encoder *encoder; 837 + struct drm_connector *connector; 838 + int ret; 839 + 840 + if ((ret = drm_mode_group_init(dev, group))) 841 + return ret; 842 + 843 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 844 + group->id_list[group->num_crtcs++] = crtc->base.id; 845 + 846 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 847 + group->id_list[group->num_crtcs + group->num_encoders++] = 848 + encoder->base.id; 849 + 850 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) 851 + group->id_list[group->num_crtcs + group->num_encoders + 852 + group->num_connectors++] = connector->base.id; 853 + 854 + return 0; 855 + } 856 + 857 + /** 858 + * drm_mode_config_cleanup - free up DRM mode_config info 859 + * @dev: DRM device 860 + * 861 + * LOCKING: 862 + * Caller must hold mode config lock. 863 + * 864 + * Free up all the connectors and CRTCs associated with this DRM device, then 865 + * free up the framebuffers and associated buffer objects. 866 + * 867 + * FIXME: cleanup any dangling user buffer objects too 868 + */ 869 + void drm_mode_config_cleanup(struct drm_device *dev) 870 + { 871 + struct drm_connector *connector, *ot; 872 + struct drm_crtc *crtc, *ct; 873 + struct drm_encoder *encoder, *enct; 874 + struct drm_framebuffer *fb, *fbt; 875 + struct drm_property *property, *pt; 876 + 877 + list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, 878 + head) { 879 + encoder->funcs->destroy(encoder); 880 + } 881 + 882 + list_for_each_entry_safe(connector, ot, 883 + &dev->mode_config.connector_list, head) { 884 + connector->funcs->destroy(connector); 885 + } 886 + 887 + list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, 888 + head) { 889 + drm_property_destroy(dev, property); 890 + } 891 + 892 + list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { 893 + fb->funcs->destroy(fb); 894 + } 895 + 896 + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { 897 + crtc->funcs->destroy(crtc); 898 + } 899 + 900 + } 901 + EXPORT_SYMBOL(drm_mode_config_cleanup); 902 + 903 + int drm_mode_hotplug_ioctl(struct drm_device *dev, 904 + void *data, struct drm_file *file_priv) 905 + { 906 + struct drm_mode_hotplug *arg = data; 907 + 908 + arg->counter = dev->mode_config.hotplug_counter; 909 + 910 + return 0; 911 + } 912 + 913 + /** 914 + * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo 915 + * @out: drm_mode_modeinfo struct to return to the user 916 + * @in: drm_display_mode to use 917 + * 918 + * LOCKING: 919 + * None. 920 + * 921 + * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to 922 + * the user. 923 + */ 924 + void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, 925 + struct drm_display_mode *in) 926 + { 927 + out->clock = in->clock; 928 + out->hdisplay = in->hdisplay; 929 + out->hsync_start = in->hsync_start; 930 + out->hsync_end = in->hsync_end; 931 + out->htotal = in->htotal; 932 + out->hskew = in->hskew; 933 + out->vdisplay = in->vdisplay; 934 + out->vsync_start = in->vsync_start; 935 + out->vsync_end = in->vsync_end; 936 + out->vtotal = in->vtotal; 937 + out->vscan = in->vscan; 938 + out->vrefresh = in->vrefresh; 939 + out->flags = in->flags; 940 + out->type = in->type; 941 + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 942 + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 943 + } 944 + 945 + /** 946 + * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode 947 + * @out: drm_display_mode to return to the user 948 + * @in: drm_mode_modeinfo to use 949 + * 950 + * LOCKING: 951 + * None. 952 + * 953 + * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to 954 + * the caller. 955 + */ 956 + void drm_crtc_convert_umode(struct drm_display_mode *out, 957 + struct drm_mode_modeinfo *in) 958 + { 959 + out->clock = in->clock; 960 + out->hdisplay = in->hdisplay; 961 + out->hsync_start = in->hsync_start; 962 + out->hsync_end = in->hsync_end; 963 + out->htotal = in->htotal; 964 + out->hskew = in->hskew; 965 + out->vdisplay = in->vdisplay; 966 + out->vsync_start = in->vsync_start; 967 + out->vsync_end = in->vsync_end; 968 + out->vtotal = in->vtotal; 969 + out->vscan = in->vscan; 970 + out->vrefresh = in->vrefresh; 971 + out->flags = in->flags; 972 + out->type = in->type; 973 + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 974 + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 975 + } 976 + 977 + /** 978 + * drm_mode_getresources - get graphics configuration 979 + * @inode: inode from the ioctl 980 + * @filp: file * from the ioctl 981 + * @cmd: cmd from ioctl 982 + * @arg: arg from ioctl 983 + * 984 + * LOCKING: 985 + * Takes mode config lock. 986 + * 987 + * Construct a set of configuration description structures and return 988 + * them to the user, including CRTC, connector and framebuffer configuration. 989 + * 990 + * Called by the user via ioctl. 991 + * 992 + * RETURNS: 993 + * Zero on success, errno on failure. 994 + */ 995 + int drm_mode_getresources(struct drm_device *dev, void *data, 996 + struct drm_file *file_priv) 997 + { 998 + struct drm_mode_card_res *card_res = data; 999 + struct list_head *lh; 1000 + struct drm_framebuffer *fb; 1001 + struct drm_connector *connector; 1002 + struct drm_crtc *crtc; 1003 + struct drm_encoder *encoder; 1004 + int ret = 0; 1005 + int connector_count = 0; 1006 + int crtc_count = 0; 1007 + int fb_count = 0; 1008 + int encoder_count = 0; 1009 + int copied = 0, i; 1010 + uint32_t __user *fb_id; 1011 + uint32_t __user *crtc_id; 1012 + uint32_t __user *connector_id; 1013 + uint32_t __user *encoder_id; 1014 + struct drm_mode_group *mode_group; 1015 + 1016 + mutex_lock(&dev->mode_config.mutex); 1017 + 1018 + /* 1019 + * For the non-control nodes we need to limit the list of resources 1020 + * by IDs in the group list for this node 1021 + */ 1022 + list_for_each(lh, &file_priv->fbs) 1023 + fb_count++; 1024 + 1025 + mode_group = &file_priv->master->minor->mode_group; 1026 + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1027 + 1028 + list_for_each(lh, &dev->mode_config.crtc_list) 1029 + crtc_count++; 1030 + 1031 + list_for_each(lh, &dev->mode_config.connector_list) 1032 + connector_count++; 1033 + 1034 + list_for_each(lh, &dev->mode_config.encoder_list) 1035 + encoder_count++; 1036 + } else { 1037 + 1038 + crtc_count = mode_group->num_crtcs; 1039 + connector_count = mode_group->num_connectors; 1040 + encoder_count = mode_group->num_encoders; 1041 + } 1042 + 1043 + card_res->max_height = dev->mode_config.max_height; 1044 + card_res->min_height = dev->mode_config.min_height; 1045 + card_res->max_width = dev->mode_config.max_width; 1046 + card_res->min_width = dev->mode_config.min_width; 1047 + 1048 + /* handle this in 4 parts */ 1049 + /* FBs */ 1050 + if (card_res->count_fbs >= fb_count) { 1051 + copied = 0; 1052 + fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; 1053 + list_for_each_entry(fb, &file_priv->fbs, head) { 1054 + if (put_user(fb->base.id, fb_id + copied)) { 1055 + ret = -EFAULT; 1056 + goto out; 1057 + } 1058 + copied++; 1059 + } 1060 + } 1061 + card_res->count_fbs = fb_count; 1062 + 1063 + /* CRTCs */ 1064 + if (card_res->count_crtcs >= crtc_count) { 1065 + copied = 0; 1066 + crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; 1067 + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1068 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, 1069 + head) { 1070 + DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); 1071 + if (put_user(crtc->base.id, crtc_id + copied)) { 1072 + ret = -EFAULT; 1073 + goto out; 1074 + } 1075 + copied++; 1076 + } 1077 + } else { 1078 + for (i = 0; i < mode_group->num_crtcs; i++) { 1079 + if (put_user(mode_group->id_list[i], 1080 + crtc_id + copied)) { 1081 + ret = -EFAULT; 1082 + goto out; 1083 + } 1084 + copied++; 1085 + } 1086 + } 1087 + } 1088 + card_res->count_crtcs = crtc_count; 1089 + 1090 + /* Encoders */ 1091 + if (card_res->count_encoders >= encoder_count) { 1092 + copied = 0; 1093 + encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; 1094 + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1095 + list_for_each_entry(encoder, 1096 + &dev->mode_config.encoder_list, 1097 + head) { 1098 + DRM_DEBUG("ENCODER ID is %d\n", 1099 + encoder->base.id); 1100 + if (put_user(encoder->base.id, encoder_id + 1101 + copied)) { 1102 + ret = -EFAULT; 1103 + goto out; 1104 + } 1105 + copied++; 1106 + } 1107 + } else { 1108 + for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) { 1109 + if (put_user(mode_group->id_list[i], 1110 + encoder_id + copied)) { 1111 + ret = -EFAULT; 1112 + goto out; 1113 + } 1114 + copied++; 1115 + } 1116 + 1117 + } 1118 + } 1119 + card_res->count_encoders = encoder_count; 1120 + 1121 + /* Connectors */ 1122 + if (card_res->count_connectors >= connector_count) { 1123 + copied = 0; 1124 + connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; 1125 + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1126 + list_for_each_entry(connector, 1127 + &dev->mode_config.connector_list, 1128 + head) { 1129 + DRM_DEBUG("CONNECTOR ID is %d\n", 1130 + connector->base.id); 1131 + if (put_user(connector->base.id, 1132 + connector_id + copied)) { 1133 + ret = -EFAULT; 1134 + goto out; 1135 + } 1136 + copied++; 1137 + } 1138 + } else { 1139 + int start = mode_group->num_crtcs + 1140 + mode_group->num_encoders; 1141 + for (i = start; i < start + mode_group->num_connectors; i++) { 1142 + if (put_user(mode_group->id_list[i], 1143 + connector_id + copied)) { 1144 + ret = -EFAULT; 1145 + goto out; 1146 + } 1147 + copied++; 1148 + } 1149 + } 1150 + } 1151 + card_res->count_connectors = connector_count; 1152 + 1153 + DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, 1154 + card_res->count_connectors, card_res->count_encoders); 1155 + 1156 + out: 1157 + mutex_unlock(&dev->mode_config.mutex); 1158 + return ret; 1159 + } 1160 + 1161 + /** 1162 + * drm_mode_getcrtc - get CRTC configuration 1163 + * @inode: inode from the ioctl 1164 + * @filp: file * from the ioctl 1165 + * @cmd: cmd from ioctl 1166 + * @arg: arg from ioctl 1167 + * 1168 + * LOCKING: 1169 + * Caller? (FIXME) 1170 + * 1171 + * Construct a CRTC configuration structure to return to the user. 1172 + * 1173 + * Called by the user via ioctl. 1174 + * 1175 + * RETURNS: 1176 + * Zero on success, errno on failure. 1177 + */ 1178 + int drm_mode_getcrtc(struct drm_device *dev, 1179 + void *data, struct drm_file *file_priv) 1180 + { 1181 + struct drm_mode_crtc *crtc_resp = data; 1182 + struct drm_crtc *crtc; 1183 + struct drm_mode_object *obj; 1184 + int ret = 0; 1185 + 1186 + mutex_lock(&dev->mode_config.mutex); 1187 + 1188 + obj = drm_mode_object_find(dev, crtc_resp->crtc_id, 1189 + DRM_MODE_OBJECT_CRTC); 1190 + if (!obj) { 1191 + ret = -EINVAL; 1192 + goto out; 1193 + } 1194 + crtc = obj_to_crtc(obj); 1195 + 1196 + crtc_resp->x = crtc->x; 1197 + crtc_resp->y = crtc->y; 1198 + crtc_resp->gamma_size = crtc->gamma_size; 1199 + if (crtc->fb) 1200 + crtc_resp->fb_id = crtc->fb->base.id; 1201 + else 1202 + crtc_resp->fb_id = 0; 1203 + 1204 + if (crtc->enabled) { 1205 + 1206 + drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); 1207 + crtc_resp->mode_valid = 1; 1208 + 1209 + } else { 1210 + crtc_resp->mode_valid = 0; 1211 + } 1212 + 1213 + out: 1214 + mutex_unlock(&dev->mode_config.mutex); 1215 + return ret; 1216 + } 1217 + 1218 + /** 1219 + * drm_mode_getconnector - get connector configuration 1220 + * @inode: inode from the ioctl 1221 + * @filp: file * from the ioctl 1222 + * @cmd: cmd from ioctl 1223 + * @arg: arg from ioctl 1224 + * 1225 + * LOCKING: 1226 + * Caller? (FIXME) 1227 + * 1228 + * Construct a connector configuration structure to return to the user. 1229 + * 1230 + * Called by the user via ioctl. 1231 + * 1232 + * RETURNS: 1233 + * Zero on success, errno on failure. 1234 + */ 1235 + int drm_mode_getconnector(struct drm_device *dev, void *data, 1236 + struct drm_file *file_priv) 1237 + { 1238 + struct drm_mode_get_connector *out_resp = data; 1239 + struct drm_mode_object *obj; 1240 + struct drm_connector *connector; 1241 + struct drm_display_mode *mode; 1242 + int mode_count = 0; 1243 + int props_count = 0; 1244 + int encoders_count = 0; 1245 + int ret = 0; 1246 + int copied = 0; 1247 + int i; 1248 + struct drm_mode_modeinfo u_mode; 1249 + struct drm_mode_modeinfo __user *mode_ptr; 1250 + uint32_t __user *prop_ptr; 1251 + uint64_t __user *prop_values; 1252 + uint32_t __user *encoder_ptr; 1253 + 1254 + memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); 1255 + 1256 + DRM_DEBUG("connector id %d:\n", out_resp->connector_id); 1257 + 1258 + mutex_lock(&dev->mode_config.mutex); 1259 + 1260 + obj = drm_mode_object_find(dev, out_resp->connector_id, 1261 + DRM_MODE_OBJECT_CONNECTOR); 1262 + if (!obj) { 1263 + ret = -EINVAL; 1264 + goto out; 1265 + } 1266 + connector = obj_to_connector(obj); 1267 + 1268 + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 1269 + if (connector->property_ids[i] != 0) { 1270 + props_count++; 1271 + } 1272 + } 1273 + 1274 + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1275 + if (connector->encoder_ids[i] != 0) { 1276 + encoders_count++; 1277 + } 1278 + } 1279 + 1280 + if (out_resp->count_modes == 0) { 1281 + connector->funcs->fill_modes(connector, 1282 + dev->mode_config.max_width, 1283 + dev->mode_config.max_height); 1284 + } 1285 + 1286 + /* delayed so we get modes regardless of pre-fill_modes state */ 1287 + list_for_each_entry(mode, &connector->modes, head) 1288 + mode_count++; 1289 + 1290 + out_resp->connector_id = connector->base.id; 1291 + out_resp->connector_type = connector->connector_type; 1292 + out_resp->connector_type_id = connector->connector_type_id; 1293 + out_resp->mm_width = connector->display_info.width_mm; 1294 + out_resp->mm_height = connector->display_info.height_mm; 1295 + out_resp->subpixel = connector->display_info.subpixel_order; 1296 + out_resp->connection = connector->status; 1297 + if (connector->encoder) 1298 + out_resp->encoder_id = connector->encoder->base.id; 1299 + else 1300 + out_resp->encoder_id = 0; 1301 + 1302 + /* 1303 + * This ioctl is called twice, once to determine how much space is 1304 + * needed, and the 2nd time to fill it. 1305 + */ 1306 + if ((out_resp->count_modes >= mode_count) && mode_count) { 1307 + copied = 0; 1308 + mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; 1309 + list_for_each_entry(mode, &connector->modes, head) { 1310 + drm_crtc_convert_to_umode(&u_mode, mode); 1311 + if (copy_to_user(mode_ptr + copied, 1312 + &u_mode, sizeof(u_mode))) { 1313 + ret = -EFAULT; 1314 + goto out; 1315 + } 1316 + copied++; 1317 + } 1318 + } 1319 + out_resp->count_modes = mode_count; 1320 + 1321 + if ((out_resp->count_props >= props_count) && props_count) { 1322 + copied = 0; 1323 + prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); 1324 + prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); 1325 + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 1326 + if (connector->property_ids[i] != 0) { 1327 + if (put_user(connector->property_ids[i], 1328 + prop_ptr + copied)) { 1329 + ret = -EFAULT; 1330 + goto out; 1331 + } 1332 + 1333 + if (put_user(connector->property_values[i], 1334 + prop_values + copied)) { 1335 + ret = -EFAULT; 1336 + goto out; 1337 + } 1338 + copied++; 1339 + } 1340 + } 1341 + } 1342 + out_resp->count_props = props_count; 1343 + 1344 + if ((out_resp->count_encoders >= encoders_count) && encoders_count) { 1345 + copied = 0; 1346 + encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); 1347 + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1348 + if (connector->encoder_ids[i] != 0) { 1349 + if (put_user(connector->encoder_ids[i], 1350 + encoder_ptr + copied)) { 1351 + ret = -EFAULT; 1352 + goto out; 1353 + } 1354 + copied++; 1355 + } 1356 + } 1357 + } 1358 + out_resp->count_encoders = encoders_count; 1359 + 1360 + out: 1361 + mutex_unlock(&dev->mode_config.mutex); 1362 + return ret; 1363 + } 1364 + 1365 + int drm_mode_getencoder(struct drm_device *dev, void *data, 1366 + struct drm_file *file_priv) 1367 + { 1368 + struct drm_mode_get_encoder *enc_resp = data; 1369 + struct drm_mode_object *obj; 1370 + struct drm_encoder *encoder; 1371 + int ret = 0; 1372 + 1373 + mutex_lock(&dev->mode_config.mutex); 1374 + obj = drm_mode_object_find(dev, enc_resp->encoder_id, 1375 + DRM_MODE_OBJECT_ENCODER); 1376 + if (!obj) { 1377 + ret = -EINVAL; 1378 + goto out; 1379 + } 1380 + encoder = obj_to_encoder(obj); 1381 + 1382 + if (encoder->crtc) 1383 + enc_resp->crtc_id = encoder->crtc->base.id; 1384 + else 1385 + enc_resp->crtc_id = 0; 1386 + enc_resp->encoder_type = encoder->encoder_type; 1387 + enc_resp->encoder_id = encoder->base.id; 1388 + enc_resp->possible_crtcs = encoder->possible_crtcs; 1389 + enc_resp->possible_clones = encoder->possible_clones; 1390 + 1391 + out: 1392 + mutex_unlock(&dev->mode_config.mutex); 1393 + return ret; 1394 + } 1395 + 1396 + /** 1397 + * drm_mode_setcrtc - set CRTC configuration 1398 + * @inode: inode from the ioctl 1399 + * @filp: file * from the ioctl 1400 + * @cmd: cmd from ioctl 1401 + * @arg: arg from ioctl 1402 + * 1403 + * LOCKING: 1404 + * Caller? (FIXME) 1405 + * 1406 + * Build a new CRTC configuration based on user request. 1407 + * 1408 + * Called by the user via ioctl. 1409 + * 1410 + * RETURNS: 1411 + * Zero on success, errno on failure. 1412 + */ 1413 + int drm_mode_setcrtc(struct drm_device *dev, void *data, 1414 + struct drm_file *file_priv) 1415 + { 1416 + struct drm_mode_config *config = &dev->mode_config; 1417 + struct drm_mode_crtc *crtc_req = data; 1418 + struct drm_mode_object *obj; 1419 + struct drm_crtc *crtc, *crtcfb; 1420 + struct drm_connector **connector_set = NULL, *connector; 1421 + struct drm_framebuffer *fb = NULL; 1422 + struct drm_display_mode *mode = NULL; 1423 + struct drm_mode_set set; 1424 + uint32_t __user *set_connectors_ptr; 1425 + int ret = 0; 1426 + int i; 1427 + 1428 + mutex_lock(&dev->mode_config.mutex); 1429 + obj = drm_mode_object_find(dev, crtc_req->crtc_id, 1430 + DRM_MODE_OBJECT_CRTC); 1431 + if (!obj) { 1432 + DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id); 1433 + ret = -EINVAL; 1434 + goto out; 1435 + } 1436 + crtc = obj_to_crtc(obj); 1437 + 1438 + if (crtc_req->mode_valid) { 1439 + /* If we have a mode we need a framebuffer. */ 1440 + /* If we pass -1, set the mode with the currently bound fb */ 1441 + if (crtc_req->fb_id == -1) { 1442 + list_for_each_entry(crtcfb, 1443 + &dev->mode_config.crtc_list, head) { 1444 + if (crtcfb == crtc) { 1445 + DRM_DEBUG("Using current fb for setmode\n"); 1446 + fb = crtc->fb; 1447 + } 1448 + } 1449 + } else { 1450 + obj = drm_mode_object_find(dev, crtc_req->fb_id, 1451 + DRM_MODE_OBJECT_FB); 1452 + if (!obj) { 1453 + DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id); 1454 + ret = -EINVAL; 1455 + goto out; 1456 + } 1457 + fb = obj_to_fb(obj); 1458 + } 1459 + 1460 + mode = drm_mode_create(dev); 1461 + drm_crtc_convert_umode(mode, &crtc_req->mode); 1462 + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1463 + } 1464 + 1465 + if (crtc_req->count_connectors == 0 && mode) { 1466 + DRM_DEBUG("Count connectors is 0 but mode set\n"); 1467 + ret = -EINVAL; 1468 + goto out; 1469 + } 1470 + 1471 + if (crtc_req->count_connectors > 0 && !mode && !fb) { 1472 + DRM_DEBUG("Count connectors is %d but no mode or fb set\n", 1473 + crtc_req->count_connectors); 1474 + ret = -EINVAL; 1475 + goto out; 1476 + } 1477 + 1478 + if (crtc_req->count_connectors > 0) { 1479 + u32 out_id; 1480 + 1481 + /* Avoid unbounded kernel memory allocation */ 1482 + if (crtc_req->count_connectors > config->num_connector) { 1483 + ret = -EINVAL; 1484 + goto out; 1485 + } 1486 + 1487 + connector_set = kmalloc(crtc_req->count_connectors * 1488 + sizeof(struct drm_connector *), 1489 + GFP_KERNEL); 1490 + if (!connector_set) { 1491 + ret = -ENOMEM; 1492 + goto out; 1493 + } 1494 + 1495 + for (i = 0; i < crtc_req->count_connectors; i++) { 1496 + set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr; 1497 + if (get_user(out_id, &set_connectors_ptr[i])) { 1498 + ret = -EFAULT; 1499 + goto out; 1500 + } 1501 + 1502 + obj = drm_mode_object_find(dev, out_id, 1503 + DRM_MODE_OBJECT_CONNECTOR); 1504 + if (!obj) { 1505 + DRM_DEBUG("Connector id %d unknown\n", out_id); 1506 + ret = -EINVAL; 1507 + goto out; 1508 + } 1509 + connector = obj_to_connector(obj); 1510 + 1511 + connector_set[i] = connector; 1512 + } 1513 + } 1514 + 1515 + set.crtc = crtc; 1516 + set.x = crtc_req->x; 1517 + set.y = crtc_req->y; 1518 + set.mode = mode; 1519 + set.connectors = connector_set; 1520 + set.num_connectors = crtc_req->count_connectors; 1521 + set.fb =fb; 1522 + ret = crtc->funcs->set_config(&set); 1523 + 1524 + out: 1525 + kfree(connector_set); 1526 + mutex_unlock(&dev->mode_config.mutex); 1527 + return ret; 1528 + } 1529 + 1530 + int drm_mode_cursor_ioctl(struct drm_device *dev, 1531 + void *data, struct drm_file *file_priv) 1532 + { 1533 + struct drm_mode_cursor *req = data; 1534 + struct drm_mode_object *obj; 1535 + struct drm_crtc *crtc; 1536 + int ret = 0; 1537 + 1538 + DRM_DEBUG("\n"); 1539 + 1540 + if (!req->flags) { 1541 + DRM_ERROR("no operation set\n"); 1542 + return -EINVAL; 1543 + } 1544 + 1545 + mutex_lock(&dev->mode_config.mutex); 1546 + obj = drm_mode_object_find(dev, req->crtc, DRM_MODE_OBJECT_CRTC); 1547 + if (!obj) { 1548 + DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc); 1549 + ret = -EINVAL; 1550 + goto out; 1551 + } 1552 + crtc = obj_to_crtc(obj); 1553 + 1554 + if (req->flags & DRM_MODE_CURSOR_BO) { 1555 + if (!crtc->funcs->cursor_set) { 1556 + DRM_ERROR("crtc does not support cursor\n"); 1557 + ret = -ENXIO; 1558 + goto out; 1559 + } 1560 + /* Turns off the cursor if handle is 0 */ 1561 + ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, 1562 + req->width, req->height); 1563 + } 1564 + 1565 + if (req->flags & DRM_MODE_CURSOR_MOVE) { 1566 + if (crtc->funcs->cursor_move) { 1567 + ret = crtc->funcs->cursor_move(crtc, req->x, req->y); 1568 + } else { 1569 + DRM_ERROR("crtc does not support cursor\n"); 1570 + ret = -EFAULT; 1571 + goto out; 1572 + } 1573 + } 1574 + out: 1575 + mutex_unlock(&dev->mode_config.mutex); 1576 + return ret; 1577 + } 1578 + 1579 + /** 1580 + * drm_mode_addfb - add an FB to the graphics configuration 1581 + * @inode: inode from the ioctl 1582 + * @filp: file * from the ioctl 1583 + * @cmd: cmd from ioctl 1584 + * @arg: arg from ioctl 1585 + * 1586 + * LOCKING: 1587 + * Takes mode config lock. 1588 + * 1589 + * Add a new FB to the specified CRTC, given a user request. 1590 + * 1591 + * Called by the user via ioctl. 1592 + * 1593 + * RETURNS: 1594 + * Zero on success, errno on failure. 1595 + */ 1596 + int drm_mode_addfb(struct drm_device *dev, 1597 + void *data, struct drm_file *file_priv) 1598 + { 1599 + struct drm_mode_fb_cmd *r = data; 1600 + struct drm_mode_config *config = &dev->mode_config; 1601 + struct drm_framebuffer *fb; 1602 + int ret = 0; 1603 + 1604 + if ((config->min_width > r->width) || (r->width > config->max_width)) { 1605 + DRM_ERROR("mode new framebuffer width not within limits\n"); 1606 + return -EINVAL; 1607 + } 1608 + if ((config->min_height > r->height) || (r->height > config->max_height)) { 1609 + DRM_ERROR("mode new framebuffer height not within limits\n"); 1610 + return -EINVAL; 1611 + } 1612 + 1613 + mutex_lock(&dev->mode_config.mutex); 1614 + 1615 + /* TODO check buffer is sufficently large */ 1616 + /* TODO setup destructor callback */ 1617 + 1618 + fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); 1619 + if (!fb) { 1620 + DRM_ERROR("could not create framebuffer\n"); 1621 + ret = -EINVAL; 1622 + goto out; 1623 + } 1624 + 1625 + r->buffer_id = fb->base.id; 1626 + list_add(&fb->filp_head, &file_priv->fbs); 1627 + 1628 + out: 1629 + mutex_unlock(&dev->mode_config.mutex); 1630 + return ret; 1631 + } 1632 + 1633 + /** 1634 + * drm_mode_rmfb - remove an FB from the configuration 1635 + * @inode: inode from the ioctl 1636 + * @filp: file * from the ioctl 1637 + * @cmd: cmd from ioctl 1638 + * @arg: arg from ioctl 1639 + * 1640 + * LOCKING: 1641 + * Takes mode config lock. 1642 + * 1643 + * Remove the FB specified by the user. 1644 + * 1645 + * Called by the user via ioctl. 1646 + * 1647 + * RETURNS: 1648 + * Zero on success, errno on failure. 1649 + */ 1650 + int drm_mode_rmfb(struct drm_device *dev, 1651 + void *data, struct drm_file *file_priv) 1652 + { 1653 + struct drm_mode_object *obj; 1654 + struct drm_framebuffer *fb = NULL; 1655 + struct drm_framebuffer *fbl = NULL; 1656 + uint32_t *id = data; 1657 + int ret = 0; 1658 + int found = 0; 1659 + 1660 + mutex_lock(&dev->mode_config.mutex); 1661 + obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); 1662 + /* TODO check that we realy get a framebuffer back. */ 1663 + if (!obj) { 1664 + DRM_ERROR("mode invalid framebuffer id\n"); 1665 + ret = -EINVAL; 1666 + goto out; 1667 + } 1668 + fb = obj_to_fb(obj); 1669 + 1670 + list_for_each_entry(fbl, &file_priv->fbs, filp_head) 1671 + if (fb == fbl) 1672 + found = 1; 1673 + 1674 + if (!found) { 1675 + DRM_ERROR("tried to remove a fb that we didn't own\n"); 1676 + ret = -EINVAL; 1677 + goto out; 1678 + } 1679 + 1680 + /* TODO release all crtc connected to the framebuffer */ 1681 + /* TODO unhock the destructor from the buffer object */ 1682 + 1683 + list_del(&fb->filp_head); 1684 + fb->funcs->destroy(fb); 1685 + 1686 + out: 1687 + mutex_unlock(&dev->mode_config.mutex); 1688 + return ret; 1689 + } 1690 + 1691 + /** 1692 + * drm_mode_getfb - get FB info 1693 + * @inode: inode from the ioctl 1694 + * @filp: file * from the ioctl 1695 + * @cmd: cmd from ioctl 1696 + * @arg: arg from ioctl 1697 + * 1698 + * LOCKING: 1699 + * Caller? (FIXME) 1700 + * 1701 + * Lookup the FB given its ID and return info about it. 1702 + * 1703 + * Called by the user via ioctl. 1704 + * 1705 + * RETURNS: 1706 + * Zero on success, errno on failure. 1707 + */ 1708 + int drm_mode_getfb(struct drm_device *dev, 1709 + void *data, struct drm_file *file_priv) 1710 + { 1711 + struct drm_mode_fb_cmd *r = data; 1712 + struct drm_mode_object *obj; 1713 + struct drm_framebuffer *fb; 1714 + int ret = 0; 1715 + 1716 + mutex_lock(&dev->mode_config.mutex); 1717 + obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); 1718 + if (!obj) { 1719 + DRM_ERROR("invalid framebuffer id\n"); 1720 + ret = -EINVAL; 1721 + goto out; 1722 + } 1723 + fb = obj_to_fb(obj); 1724 + 1725 + r->height = fb->height; 1726 + r->width = fb->width; 1727 + r->depth = fb->depth; 1728 + r->bpp = fb->bits_per_pixel; 1729 + r->pitch = fb->pitch; 1730 + fb->funcs->create_handle(fb, file_priv, &r->handle); 1731 + 1732 + out: 1733 + mutex_unlock(&dev->mode_config.mutex); 1734 + return ret; 1735 + } 1736 + 1737 + /** 1738 + * drm_fb_release - remove and free the FBs on this file 1739 + * @filp: file * from the ioctl 1740 + * 1741 + * LOCKING: 1742 + * Takes mode config lock. 1743 + * 1744 + * Destroy all the FBs associated with @filp. 1745 + * 1746 + * Called by the user via ioctl. 1747 + * 1748 + * RETURNS: 1749 + * Zero on success, errno on failure. 1750 + */ 1751 + void drm_fb_release(struct file *filp) 1752 + { 1753 + struct drm_file *priv = filp->private_data; 1754 + struct drm_device *dev = priv->minor->dev; 1755 + struct drm_framebuffer *fb, *tfb; 1756 + 1757 + mutex_lock(&dev->mode_config.mutex); 1758 + list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 1759 + list_del(&fb->filp_head); 1760 + fb->funcs->destroy(fb); 1761 + } 1762 + mutex_unlock(&dev->mode_config.mutex); 1763 + } 1764 + 1765 + /** 1766 + * drm_mode_attachmode - add a mode to the user mode list 1767 + * @dev: DRM device 1768 + * @connector: connector to add the mode to 1769 + * @mode: mode to add 1770 + * 1771 + * Add @mode to @connector's user mode list. 1772 + */ 1773 + static int drm_mode_attachmode(struct drm_device *dev, 1774 + struct drm_connector *connector, 1775 + struct drm_display_mode *mode) 1776 + { 1777 + int ret = 0; 1778 + 1779 + list_add_tail(&mode->head, &connector->user_modes); 1780 + return ret; 1781 + } 1782 + 1783 + int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, 1784 + struct drm_display_mode *mode) 1785 + { 1786 + struct drm_connector *connector; 1787 + int ret = 0; 1788 + struct drm_display_mode *dup_mode; 1789 + int need_dup = 0; 1790 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1791 + if (!connector->encoder) 1792 + break; 1793 + if (connector->encoder->crtc == crtc) { 1794 + if (need_dup) 1795 + dup_mode = drm_mode_duplicate(dev, mode); 1796 + else 1797 + dup_mode = mode; 1798 + ret = drm_mode_attachmode(dev, connector, dup_mode); 1799 + if (ret) 1800 + return ret; 1801 + need_dup = 1; 1802 + } 1803 + } 1804 + return 0; 1805 + } 1806 + EXPORT_SYMBOL(drm_mode_attachmode_crtc); 1807 + 1808 + static int drm_mode_detachmode(struct drm_device *dev, 1809 + struct drm_connector *connector, 1810 + struct drm_display_mode *mode) 1811 + { 1812 + int found = 0; 1813 + int ret = 0; 1814 + struct drm_display_mode *match_mode, *t; 1815 + 1816 + list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) { 1817 + if (drm_mode_equal(match_mode, mode)) { 1818 + list_del(&match_mode->head); 1819 + drm_mode_destroy(dev, match_mode); 1820 + found = 1; 1821 + break; 1822 + } 1823 + } 1824 + 1825 + if (!found) 1826 + ret = -EINVAL; 1827 + 1828 + return ret; 1829 + } 1830 + 1831 + int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) 1832 + { 1833 + struct drm_connector *connector; 1834 + 1835 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1836 + drm_mode_detachmode(dev, connector, mode); 1837 + } 1838 + return 0; 1839 + } 1840 + EXPORT_SYMBOL(drm_mode_detachmode_crtc); 1841 + 1842 + /** 1843 + * drm_fb_attachmode - Attach a user mode to an connector 1844 + * @inode: inode from the ioctl 1845 + * @filp: file * from the ioctl 1846 + * @cmd: cmd from ioctl 1847 + * @arg: arg from ioctl 1848 + * 1849 + * This attaches a user specified mode to an connector. 1850 + * Called by the user via ioctl. 1851 + * 1852 + * RETURNS: 1853 + * Zero on success, errno on failure. 1854 + */ 1855 + int drm_mode_attachmode_ioctl(struct drm_device *dev, 1856 + void *data, struct drm_file *file_priv) 1857 + { 1858 + struct drm_mode_mode_cmd *mode_cmd = data; 1859 + struct drm_connector *connector; 1860 + struct drm_display_mode *mode; 1861 + struct drm_mode_object *obj; 1862 + struct drm_mode_modeinfo *umode = &mode_cmd->mode; 1863 + int ret = 0; 1864 + 1865 + mutex_lock(&dev->mode_config.mutex); 1866 + 1867 + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 1868 + if (!obj) { 1869 + ret = -EINVAL; 1870 + goto out; 1871 + } 1872 + connector = obj_to_connector(obj); 1873 + 1874 + mode = drm_mode_create(dev); 1875 + if (!mode) { 1876 + ret = -ENOMEM; 1877 + goto out; 1878 + } 1879 + 1880 + drm_crtc_convert_umode(mode, umode); 1881 + 1882 + ret = drm_mode_attachmode(dev, connector, mode); 1883 + out: 1884 + mutex_unlock(&dev->mode_config.mutex); 1885 + return ret; 1886 + } 1887 + 1888 + 1889 + /** 1890 + * drm_fb_detachmode - Detach a user specified mode from an connector 1891 + * @inode: inode from the ioctl 1892 + * @filp: file * from the ioctl 1893 + * @cmd: cmd from ioctl 1894 + * @arg: arg from ioctl 1895 + * 1896 + * Called by the user via ioctl. 1897 + * 1898 + * RETURNS: 1899 + * Zero on success, errno on failure. 1900 + */ 1901 + int drm_mode_detachmode_ioctl(struct drm_device *dev, 1902 + void *data, struct drm_file *file_priv) 1903 + { 1904 + struct drm_mode_object *obj; 1905 + struct drm_mode_mode_cmd *mode_cmd = data; 1906 + struct drm_connector *connector; 1907 + struct drm_display_mode mode; 1908 + struct drm_mode_modeinfo *umode = &mode_cmd->mode; 1909 + int ret = 0; 1910 + 1911 + mutex_lock(&dev->mode_config.mutex); 1912 + 1913 + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 1914 + if (!obj) { 1915 + ret = -EINVAL; 1916 + goto out; 1917 + } 1918 + connector = obj_to_connector(obj); 1919 + 1920 + drm_crtc_convert_umode(&mode, umode); 1921 + ret = drm_mode_detachmode(dev, connector, &mode); 1922 + out: 1923 + mutex_unlock(&dev->mode_config.mutex); 1924 + return ret; 1925 + } 1926 + 1927 + struct drm_property *drm_property_create(struct drm_device *dev, int flags, 1928 + const char *name, int num_values) 1929 + { 1930 + struct drm_property *property = NULL; 1931 + 1932 + property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); 1933 + if (!property) 1934 + return NULL; 1935 + 1936 + if (num_values) { 1937 + property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); 1938 + if (!property->values) 1939 + goto fail; 1940 + } 1941 + 1942 + drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); 1943 + property->flags = flags; 1944 + property->num_values = num_values; 1945 + INIT_LIST_HEAD(&property->enum_blob_list); 1946 + 1947 + if (name) 1948 + strncpy(property->name, name, DRM_PROP_NAME_LEN); 1949 + 1950 + list_add_tail(&property->head, &dev->mode_config.property_list); 1951 + return property; 1952 + fail: 1953 + kfree(property); 1954 + return NULL; 1955 + } 1956 + EXPORT_SYMBOL(drm_property_create); 1957 + 1958 + int drm_property_add_enum(struct drm_property *property, int index, 1959 + uint64_t value, const char *name) 1960 + { 1961 + struct drm_property_enum *prop_enum; 1962 + 1963 + if (!(property->flags & DRM_MODE_PROP_ENUM)) 1964 + return -EINVAL; 1965 + 1966 + if (!list_empty(&property->enum_blob_list)) { 1967 + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 1968 + if (prop_enum->value == value) { 1969 + strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 1970 + prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 1971 + return 0; 1972 + } 1973 + } 1974 + } 1975 + 1976 + prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL); 1977 + if (!prop_enum) 1978 + return -ENOMEM; 1979 + 1980 + strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 1981 + prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 1982 + prop_enum->value = value; 1983 + 1984 + property->values[index] = value; 1985 + list_add_tail(&prop_enum->head, &property->enum_blob_list); 1986 + return 0; 1987 + } 1988 + EXPORT_SYMBOL(drm_property_add_enum); 1989 + 1990 + void drm_property_destroy(struct drm_device *dev, struct drm_property *property) 1991 + { 1992 + struct drm_property_enum *prop_enum, *pt; 1993 + 1994 + list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { 1995 + list_del(&prop_enum->head); 1996 + kfree(prop_enum); 1997 + } 1998 + 1999 + if (property->num_values) 2000 + kfree(property->values); 2001 + drm_mode_object_put(dev, &property->base); 2002 + list_del(&property->head); 2003 + kfree(property); 2004 + } 2005 + EXPORT_SYMBOL(drm_property_destroy); 2006 + 2007 + int drm_connector_attach_property(struct drm_connector *connector, 2008 + struct drm_property *property, uint64_t init_val) 2009 + { 2010 + int i; 2011 + 2012 + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2013 + if (connector->property_ids[i] == 0) { 2014 + connector->property_ids[i] = property->base.id; 2015 + connector->property_values[i] = init_val; 2016 + break; 2017 + } 2018 + } 2019 + 2020 + if (i == DRM_CONNECTOR_MAX_PROPERTY) 2021 + return -EINVAL; 2022 + return 0; 2023 + } 2024 + EXPORT_SYMBOL(drm_connector_attach_property); 2025 + 2026 + int drm_connector_property_set_value(struct drm_connector *connector, 2027 + struct drm_property *property, uint64_t value) 2028 + { 2029 + int i; 2030 + 2031 + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2032 + if (connector->property_ids[i] == property->base.id) { 2033 + connector->property_values[i] = value; 2034 + break; 2035 + } 2036 + } 2037 + 2038 + if (i == DRM_CONNECTOR_MAX_PROPERTY) 2039 + return -EINVAL; 2040 + return 0; 2041 + } 2042 + EXPORT_SYMBOL(drm_connector_property_set_value); 2043 + 2044 + int drm_connector_property_get_value(struct drm_connector *connector, 2045 + struct drm_property *property, uint64_t *val) 2046 + { 2047 + int i; 2048 + 2049 + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2050 + if (connector->property_ids[i] == property->base.id) { 2051 + *val = connector->property_values[i]; 2052 + break; 2053 + } 2054 + } 2055 + 2056 + if (i == DRM_CONNECTOR_MAX_PROPERTY) 2057 + return -EINVAL; 2058 + return 0; 2059 + } 2060 + EXPORT_SYMBOL(drm_connector_property_get_value); 2061 + 2062 + int drm_mode_getproperty_ioctl(struct drm_device *dev, 2063 + void *data, struct drm_file *file_priv) 2064 + { 2065 + struct drm_mode_object *obj; 2066 + struct drm_mode_get_property *out_resp = data; 2067 + struct drm_property *property; 2068 + int enum_count = 0; 2069 + int blob_count = 0; 2070 + int value_count = 0; 2071 + int ret = 0, i; 2072 + int copied; 2073 + struct drm_property_enum *prop_enum; 2074 + struct drm_mode_property_enum __user *enum_ptr; 2075 + struct drm_property_blob *prop_blob; 2076 + uint32_t *blob_id_ptr; 2077 + uint64_t __user *values_ptr; 2078 + uint32_t __user *blob_length_ptr; 2079 + 2080 + mutex_lock(&dev->mode_config.mutex); 2081 + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 2082 + if (!obj) { 2083 + ret = -EINVAL; 2084 + goto done; 2085 + } 2086 + property = obj_to_property(obj); 2087 + 2088 + if (property->flags & DRM_MODE_PROP_ENUM) { 2089 + list_for_each_entry(prop_enum, &property->enum_blob_list, head) 2090 + enum_count++; 2091 + } else if (property->flags & DRM_MODE_PROP_BLOB) { 2092 + list_for_each_entry(prop_blob, &property->enum_blob_list, head) 2093 + blob_count++; 2094 + } 2095 + 2096 + value_count = property->num_values; 2097 + 2098 + strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); 2099 + out_resp->name[DRM_PROP_NAME_LEN-1] = 0; 2100 + out_resp->flags = property->flags; 2101 + 2102 + if ((out_resp->count_values >= value_count) && value_count) { 2103 + values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; 2104 + for (i = 0; i < value_count; i++) { 2105 + if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { 2106 + ret = -EFAULT; 2107 + goto done; 2108 + } 2109 + } 2110 + } 2111 + out_resp->count_values = value_count; 2112 + 2113 + if (property->flags & DRM_MODE_PROP_ENUM) { 2114 + if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { 2115 + copied = 0; 2116 + enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; 2117 + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2118 + 2119 + if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { 2120 + ret = -EFAULT; 2121 + goto done; 2122 + } 2123 + 2124 + if (copy_to_user(&enum_ptr[copied].name, 2125 + &prop_enum->name, DRM_PROP_NAME_LEN)) { 2126 + ret = -EFAULT; 2127 + goto done; 2128 + } 2129 + copied++; 2130 + } 2131 + } 2132 + out_resp->count_enum_blobs = enum_count; 2133 + } 2134 + 2135 + if (property->flags & DRM_MODE_PROP_BLOB) { 2136 + if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { 2137 + copied = 0; 2138 + blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; 2139 + blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; 2140 + 2141 + list_for_each_entry(prop_blob, &property->enum_blob_list, head) { 2142 + if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { 2143 + ret = -EFAULT; 2144 + goto done; 2145 + } 2146 + 2147 + if (put_user(prop_blob->length, blob_length_ptr + copied)) { 2148 + ret = -EFAULT; 2149 + goto done; 2150 + } 2151 + 2152 + copied++; 2153 + } 2154 + } 2155 + out_resp->count_enum_blobs = blob_count; 2156 + } 2157 + done: 2158 + mutex_unlock(&dev->mode_config.mutex); 2159 + return ret; 2160 + } 2161 + 2162 + static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, 2163 + void *data) 2164 + { 2165 + struct drm_property_blob *blob; 2166 + 2167 + if (!length || !data) 2168 + return NULL; 2169 + 2170 + blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); 2171 + if (!blob) 2172 + return NULL; 2173 + 2174 + blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob)); 2175 + blob->length = length; 2176 + 2177 + memcpy(blob->data, data, length); 2178 + 2179 + drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); 2180 + 2181 + list_add_tail(&blob->head, &dev->mode_config.property_blob_list); 2182 + return blob; 2183 + } 2184 + 2185 + static void drm_property_destroy_blob(struct drm_device *dev, 2186 + struct drm_property_blob *blob) 2187 + { 2188 + drm_mode_object_put(dev, &blob->base); 2189 + list_del(&blob->head); 2190 + kfree(blob); 2191 + } 2192 + 2193 + int drm_mode_getblob_ioctl(struct drm_device *dev, 2194 + void *data, struct drm_file *file_priv) 2195 + { 2196 + struct drm_mode_object *obj; 2197 + struct drm_mode_get_blob *out_resp = data; 2198 + struct drm_property_blob *blob; 2199 + int ret = 0; 2200 + void *blob_ptr; 2201 + 2202 + mutex_lock(&dev->mode_config.mutex); 2203 + obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); 2204 + if (!obj) { 2205 + ret = -EINVAL; 2206 + goto done; 2207 + } 2208 + blob = obj_to_blob(obj); 2209 + 2210 + if (out_resp->length == blob->length) { 2211 + blob_ptr = (void *)(unsigned long)out_resp->data; 2212 + if (copy_to_user(blob_ptr, blob->data, blob->length)){ 2213 + ret = -EFAULT; 2214 + goto done; 2215 + } 2216 + } 2217 + out_resp->length = blob->length; 2218 + 2219 + done: 2220 + mutex_unlock(&dev->mode_config.mutex); 2221 + return ret; 2222 + } 2223 + 2224 + int drm_mode_connector_update_edid_property(struct drm_connector *connector, 2225 + struct edid *edid) 2226 + { 2227 + struct drm_device *dev = connector->dev; 2228 + int ret = 0; 2229 + 2230 + if (connector->edid_blob_ptr) 2231 + drm_property_destroy_blob(dev, connector->edid_blob_ptr); 2232 + 2233 + /* Delete edid, when there is none. */ 2234 + if (!edid) { 2235 + connector->edid_blob_ptr = NULL; 2236 + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); 2237 + return ret; 2238 + } 2239 + 2240 + connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); 2241 + 2242 + ret = drm_connector_property_set_value(connector, 2243 + dev->mode_config.edid_property, 2244 + connector->edid_blob_ptr->base.id); 2245 + 2246 + return ret; 2247 + } 2248 + EXPORT_SYMBOL(drm_mode_connector_update_edid_property); 2249 + 2250 + int drm_mode_connector_property_set_ioctl(struct drm_device *dev, 2251 + void *data, struct drm_file *file_priv) 2252 + { 2253 + struct drm_mode_connector_set_property *out_resp = data; 2254 + struct drm_mode_object *obj; 2255 + struct drm_property *property; 2256 + struct drm_connector *connector; 2257 + int ret = -EINVAL; 2258 + int i; 2259 + 2260 + mutex_lock(&dev->mode_config.mutex); 2261 + 2262 + obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2263 + if (!obj) { 2264 + goto out; 2265 + } 2266 + connector = obj_to_connector(obj); 2267 + 2268 + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2269 + if (connector->property_ids[i] == out_resp->prop_id) 2270 + break; 2271 + } 2272 + 2273 + if (i == DRM_CONNECTOR_MAX_PROPERTY) { 2274 + goto out; 2275 + } 2276 + 2277 + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 2278 + if (!obj) { 2279 + goto out; 2280 + } 2281 + property = obj_to_property(obj); 2282 + 2283 + if (property->flags & DRM_MODE_PROP_IMMUTABLE) 2284 + goto out; 2285 + 2286 + if (property->flags & DRM_MODE_PROP_RANGE) { 2287 + if (out_resp->value < property->values[0]) 2288 + goto out; 2289 + 2290 + if (out_resp->value > property->values[1]) 2291 + goto out; 2292 + } else { 2293 + int found = 0; 2294 + for (i = 0; i < property->num_values; i++) { 2295 + if (property->values[i] == out_resp->value) { 2296 + found = 1; 2297 + break; 2298 + } 2299 + } 2300 + if (!found) { 2301 + goto out; 2302 + } 2303 + } 2304 + 2305 + if (connector->funcs->set_property) 2306 + ret = connector->funcs->set_property(connector, property, out_resp->value); 2307 + 2308 + /* store the property value if succesful */ 2309 + if (!ret) 2310 + drm_connector_property_set_value(connector, property, out_resp->value); 2311 + out: 2312 + mutex_unlock(&dev->mode_config.mutex); 2313 + return ret; 2314 + } 2315 + 2316 + 2317 + int drm_mode_replacefb(struct drm_device *dev, 2318 + void *data, struct drm_file *file_priv) 2319 + { 2320 + struct drm_mode_fb_cmd *r = data; 2321 + struct drm_mode_object *obj; 2322 + struct drm_framebuffer *fb; 2323 + int found = 0; 2324 + struct drm_framebuffer *fbl = NULL; 2325 + int ret = 0; 2326 + 2327 + /* right replace the current bo attached to this fb with a new bo */ 2328 + mutex_lock(&dev->mode_config.mutex); 2329 + obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); 2330 + if (!obj) { 2331 + ret = -EINVAL; 2332 + goto out; 2333 + } 2334 + fb = obj_to_fb(obj); 2335 + 2336 + list_for_each_entry(fbl, &file_priv->fbs, filp_head) 2337 + if (fb == fbl) 2338 + found = 1; 2339 + 2340 + if (!found) { 2341 + DRM_ERROR("tried to replace an fb we didn't own\n"); 2342 + ret = -EINVAL; 2343 + goto out; 2344 + } 2345 + 2346 + if (dev->mode_config.funcs->resize_fb) 2347 + ret = dev->mode_config.funcs->resize_fb(dev, file_priv, fb, r); 2348 + else 2349 + ret = -EINVAL; 2350 + out: 2351 + mutex_unlock(&dev->mode_config.mutex); 2352 + return ret; 2353 + 2354 + } 2355 + 2356 + int drm_mode_connector_attach_encoder(struct drm_connector *connector, 2357 + struct drm_encoder *encoder) 2358 + { 2359 + int i; 2360 + 2361 + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 2362 + if (connector->encoder_ids[i] == 0) { 2363 + connector->encoder_ids[i] = encoder->base.id; 2364 + return 0; 2365 + } 2366 + } 2367 + return -ENOMEM; 2368 + } 2369 + EXPORT_SYMBOL(drm_mode_connector_attach_encoder); 2370 + 2371 + void drm_mode_connector_detach_encoder(struct drm_connector *connector, 2372 + struct drm_encoder *encoder) 2373 + { 2374 + int i; 2375 + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 2376 + if (connector->encoder_ids[i] == encoder->base.id) { 2377 + connector->encoder_ids[i] = 0; 2378 + if (connector->encoder == encoder) 2379 + connector->encoder = NULL; 2380 + break; 2381 + } 2382 + } 2383 + } 2384 + EXPORT_SYMBOL(drm_mode_connector_detach_encoder); 2385 + 2386 + bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 2387 + int gamma_size) 2388 + { 2389 + crtc->gamma_size = gamma_size; 2390 + 2391 + crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); 2392 + if (!crtc->gamma_store) { 2393 + crtc->gamma_size = 0; 2394 + return false; 2395 + } 2396 + 2397 + return true; 2398 + } 2399 + EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); 2400 + 2401 + int drm_mode_gamma_set_ioctl(struct drm_device *dev, 2402 + void *data, struct drm_file *file_priv) 2403 + { 2404 + struct drm_mode_crtc_lut *crtc_lut = data; 2405 + struct drm_mode_object *obj; 2406 + struct drm_crtc *crtc; 2407 + void *r_base, *g_base, *b_base; 2408 + int size; 2409 + int ret = 0; 2410 + 2411 + mutex_lock(&dev->mode_config.mutex); 2412 + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 2413 + if (!obj) { 2414 + ret = -EINVAL; 2415 + goto out; 2416 + } 2417 + crtc = obj_to_crtc(obj); 2418 + 2419 + /* memcpy into gamma store */ 2420 + if (crtc_lut->gamma_size != crtc->gamma_size) { 2421 + ret = -EINVAL; 2422 + goto out; 2423 + } 2424 + 2425 + size = crtc_lut->gamma_size * (sizeof(uint16_t)); 2426 + r_base = crtc->gamma_store; 2427 + if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) { 2428 + ret = -EFAULT; 2429 + goto out; 2430 + } 2431 + 2432 + g_base = r_base + size; 2433 + if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) { 2434 + ret = -EFAULT; 2435 + goto out; 2436 + } 2437 + 2438 + b_base = g_base + size; 2439 + if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) { 2440 + ret = -EFAULT; 2441 + goto out; 2442 + } 2443 + 2444 + crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); 2445 + 2446 + out: 2447 + mutex_unlock(&dev->mode_config.mutex); 2448 + return ret; 2449 + 2450 + } 2451 + 2452 + int drm_mode_gamma_get_ioctl(struct drm_device *dev, 2453 + void *data, struct drm_file *file_priv) 2454 + { 2455 + struct drm_mode_crtc_lut *crtc_lut = data; 2456 + struct drm_mode_object *obj; 2457 + struct drm_crtc *crtc; 2458 + void *r_base, *g_base, *b_base; 2459 + int size; 2460 + int ret = 0; 2461 + 2462 + mutex_lock(&dev->mode_config.mutex); 2463 + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 2464 + if (!obj) { 2465 + ret = -EINVAL; 2466 + goto out; 2467 + } 2468 + crtc = obj_to_crtc(obj); 2469 + 2470 + /* memcpy into gamma store */ 2471 + if (crtc_lut->gamma_size != crtc->gamma_size) { 2472 + ret = -EINVAL; 2473 + goto out; 2474 + } 2475 + 2476 + size = crtc_lut->gamma_size * (sizeof(uint16_t)); 2477 + r_base = crtc->gamma_store; 2478 + if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) { 2479 + ret = -EFAULT; 2480 + goto out; 2481 + } 2482 + 2483 + g_base = r_base + size; 2484 + if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) { 2485 + ret = -EFAULT; 2486 + goto out; 2487 + } 2488 + 2489 + b_base = g_base + size; 2490 + if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) { 2491 + ret = -EFAULT; 2492 + goto out; 2493 + } 2494 + out: 2495 + mutex_unlock(&dev->mode_config.mutex); 2496 + return ret; 2497 + }
+822
drivers/gpu/drm/drm_crtc_helper.c
··· 1 + /* 2 + * Copyright (c) 2006-2008 Intel Corporation 3 + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 4 + * 5 + * DRM core CRTC related functions 6 + * 7 + * Permission to use, copy, modify, distribute, and sell this software and its 8 + * documentation for any purpose is hereby granted without fee, provided that 9 + * the above copyright notice appear in all copies and that both that copyright 10 + * notice and this permission notice appear in supporting documentation, and 11 + * that the name of the copyright holders not be used in advertising or 12 + * publicity pertaining to distribution of the software without specific, 13 + * written prior permission. The copyright holders make no representations 14 + * about the suitability of this software for any purpose. It is provided "as 15 + * is" without express or implied warranty. 16 + * 17 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 23 + * OF THIS SOFTWARE. 24 + * 25 + * Authors: 26 + * Keith Packard 27 + * Eric Anholt <eric@anholt.net> 28 + * Dave Airlie <airlied@linux.ie> 29 + * Jesse Barnes <jesse.barnes@intel.com> 30 + */ 31 + 32 + #include "drmP.h" 33 + #include "drm_crtc.h" 34 + #include "drm_crtc_helper.h" 35 + 36 + /* 37 + * Detailed mode info for a standard 640x480@60Hz monitor 38 + */ 39 + static struct drm_display_mode std_mode[] = { 40 + { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656, 41 + 752, 800, 0, 480, 490, 492, 525, 0, 42 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, 43 + }; 44 + 45 + /** 46 + * drm_helper_probe_connector_modes - get complete set of display modes 47 + * @dev: DRM device 48 + * @maxX: max width for modes 49 + * @maxY: max height for modes 50 + * 51 + * LOCKING: 52 + * Caller must hold mode config lock. 53 + * 54 + * Based on @dev's mode_config layout, scan all the connectors and try to detect 55 + * modes on them. Modes will first be added to the connector's probed_modes 56 + * list, then culled (based on validity and the @maxX, @maxY parameters) and 57 + * put into the normal modes list. 58 + * 59 + * Intended to be used either at bootup time or when major configuration 60 + * changes have occurred. 61 + * 62 + * FIXME: take into account monitor limits 63 + */ 64 + void drm_helper_probe_single_connector_modes(struct drm_connector *connector, 65 + uint32_t maxX, uint32_t maxY) 66 + { 67 + struct drm_device *dev = connector->dev; 68 + struct drm_display_mode *mode, *t; 69 + struct drm_connector_helper_funcs *connector_funcs = 70 + connector->helper_private; 71 + int ret; 72 + 73 + DRM_DEBUG("%s\n", drm_get_connector_name(connector)); 74 + /* set all modes to the unverified state */ 75 + list_for_each_entry_safe(mode, t, &connector->modes, head) 76 + mode->status = MODE_UNVERIFIED; 77 + 78 + connector->status = connector->funcs->detect(connector); 79 + 80 + if (connector->status == connector_status_disconnected) { 81 + DRM_DEBUG("%s is disconnected\n", 82 + drm_get_connector_name(connector)); 83 + /* TODO set EDID to NULL */ 84 + return; 85 + } 86 + 87 + ret = (*connector_funcs->get_modes)(connector); 88 + 89 + if (ret) { 90 + drm_mode_connector_list_update(connector); 91 + } 92 + 93 + if (maxX && maxY) 94 + drm_mode_validate_size(dev, &connector->modes, maxX, 95 + maxY, 0); 96 + list_for_each_entry_safe(mode, t, &connector->modes, head) { 97 + if (mode->status == MODE_OK) 98 + mode->status = connector_funcs->mode_valid(connector, 99 + mode); 100 + } 101 + 102 + 103 + drm_mode_prune_invalid(dev, &connector->modes, true); 104 + 105 + if (list_empty(&connector->modes)) { 106 + struct drm_display_mode *stdmode; 107 + 108 + DRM_DEBUG("No valid modes on %s\n", 109 + drm_get_connector_name(connector)); 110 + 111 + /* Should we do this here ??? 112 + * When no valid EDID modes are available we end up 113 + * here and bailed in the past, now we add a standard 114 + * 640x480@60Hz mode and carry on. 115 + */ 116 + stdmode = drm_mode_duplicate(dev, &std_mode[0]); 117 + drm_mode_probed_add(connector, stdmode); 118 + drm_mode_list_concat(&connector->probed_modes, 119 + &connector->modes); 120 + 121 + DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", 122 + drm_get_connector_name(connector)); 123 + } 124 + 125 + drm_mode_sort(&connector->modes); 126 + 127 + DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector)); 128 + list_for_each_entry_safe(mode, t, &connector->modes, head) { 129 + mode->vrefresh = drm_mode_vrefresh(mode); 130 + 131 + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 132 + drm_mode_debug_printmodeline(mode); 133 + } 134 + } 135 + EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); 136 + 137 + void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, 138 + uint32_t maxY) 139 + { 140 + struct drm_connector *connector; 141 + 142 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 143 + drm_helper_probe_single_connector_modes(connector, maxX, maxY); 144 + } 145 + } 146 + EXPORT_SYMBOL(drm_helper_probe_connector_modes); 147 + 148 + 149 + /** 150 + * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config 151 + * @crtc: CRTC to check 152 + * 153 + * LOCKING: 154 + * Caller must hold mode config lock. 155 + * 156 + * Walk @crtc's DRM device's mode_config and see if it's in use. 157 + * 158 + * RETURNS: 159 + * True if @crtc is part of the mode_config, false otherwise. 160 + */ 161 + bool drm_helper_crtc_in_use(struct drm_crtc *crtc) 162 + { 163 + struct drm_encoder *encoder; 164 + struct drm_device *dev = crtc->dev; 165 + /* FIXME: Locking around list access? */ 166 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 167 + if (encoder->crtc == crtc) 168 + return true; 169 + return false; 170 + } 171 + EXPORT_SYMBOL(drm_helper_crtc_in_use); 172 + 173 + /** 174 + * drm_disable_unused_functions - disable unused objects 175 + * @dev: DRM device 176 + * 177 + * LOCKING: 178 + * Caller must hold mode config lock. 179 + * 180 + * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled 181 + * by calling its dpms function, which should power it off. 182 + */ 183 + void drm_helper_disable_unused_functions(struct drm_device *dev) 184 + { 185 + struct drm_encoder *encoder; 186 + struct drm_encoder_helper_funcs *encoder_funcs; 187 + struct drm_crtc *crtc; 188 + 189 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 190 + encoder_funcs = encoder->helper_private; 191 + if (!encoder->crtc) 192 + (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); 193 + } 194 + 195 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 196 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 197 + crtc->enabled = drm_helper_crtc_in_use(crtc); 198 + if (!crtc->enabled) { 199 + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 200 + crtc->fb = NULL; 201 + } 202 + } 203 + } 204 + EXPORT_SYMBOL(drm_helper_disable_unused_functions); 205 + 206 + static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) 207 + { 208 + struct drm_display_mode *mode; 209 + 210 + list_for_each_entry(mode, &connector->modes, head) { 211 + if (drm_mode_width(mode) > width || 212 + drm_mode_height(mode) > height) 213 + continue; 214 + if (mode->type & DRM_MODE_TYPE_PREFERRED) 215 + return mode; 216 + } 217 + return NULL; 218 + } 219 + 220 + static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 221 + { 222 + bool enable; 223 + 224 + if (strict) { 225 + enable = connector->status == connector_status_connected; 226 + } else { 227 + enable = connector->status != connector_status_disconnected; 228 + } 229 + return enable; 230 + } 231 + 232 + static void drm_enable_connectors(struct drm_device *dev, bool *enabled) 233 + { 234 + bool any_enabled = false; 235 + struct drm_connector *connector; 236 + int i = 0; 237 + 238 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 239 + enabled[i] = drm_connector_enabled(connector, true); 240 + any_enabled |= enabled[i]; 241 + i++; 242 + } 243 + 244 + if (any_enabled) 245 + return; 246 + 247 + i = 0; 248 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 249 + enabled[i] = drm_connector_enabled(connector, false); 250 + i++; 251 + } 252 + } 253 + 254 + static bool drm_target_preferred(struct drm_device *dev, 255 + struct drm_display_mode **modes, 256 + bool *enabled, int width, int height) 257 + { 258 + struct drm_connector *connector; 259 + int i = 0; 260 + 261 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 262 + 263 + if (enabled[i] == false) { 264 + i++; 265 + continue; 266 + } 267 + 268 + modes[i] = drm_has_preferred_mode(connector, width, height); 269 + if (!modes[i]) { 270 + list_for_each_entry(modes[i], &connector->modes, head) 271 + break; 272 + } 273 + i++; 274 + } 275 + return true; 276 + } 277 + 278 + static int drm_pick_crtcs(struct drm_device *dev, 279 + struct drm_crtc **best_crtcs, 280 + struct drm_display_mode **modes, 281 + int n, int width, int height) 282 + { 283 + int c, o; 284 + struct drm_connector *connector; 285 + struct drm_connector_helper_funcs *connector_funcs; 286 + struct drm_encoder *encoder; 287 + struct drm_crtc *best_crtc; 288 + int my_score, best_score, score; 289 + struct drm_crtc **crtcs, *crtc; 290 + 291 + if (n == dev->mode_config.num_connector) 292 + return 0; 293 + c = 0; 294 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 295 + if (c == n) 296 + break; 297 + c++; 298 + } 299 + 300 + best_crtcs[n] = NULL; 301 + best_crtc = NULL; 302 + best_score = drm_pick_crtcs(dev, best_crtcs, modes, n+1, width, height); 303 + if (modes[n] == NULL) 304 + return best_score; 305 + 306 + crtcs = kmalloc(dev->mode_config.num_connector * 307 + sizeof(struct drm_crtc *), GFP_KERNEL); 308 + if (!crtcs) 309 + return best_score; 310 + 311 + my_score = 1; 312 + if (connector->status == connector_status_connected) 313 + my_score++; 314 + if (drm_has_preferred_mode(connector, width, height)) 315 + my_score++; 316 + 317 + connector_funcs = connector->helper_private; 318 + encoder = connector_funcs->best_encoder(connector); 319 + if (!encoder) 320 + goto out; 321 + 322 + connector->encoder = encoder; 323 + 324 + /* select a crtc for this connector and then attempt to configure 325 + remaining connectors */ 326 + c = 0; 327 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 328 + 329 + if ((connector->encoder->possible_crtcs & (1 << c)) == 0) { 330 + c++; 331 + continue; 332 + } 333 + 334 + for (o = 0; o < n; o++) 335 + if (best_crtcs[o] == crtc) 336 + break; 337 + 338 + if (o < n) { 339 + /* ignore cloning for now */ 340 + c++; 341 + continue; 342 + } 343 + 344 + crtcs[n] = crtc; 345 + memcpy(crtcs, best_crtcs, n * sizeof(struct drm_crtc *)); 346 + score = my_score + drm_pick_crtcs(dev, crtcs, modes, n + 1, 347 + width, height); 348 + if (score > best_score) { 349 + best_crtc = crtc; 350 + best_score = score; 351 + memcpy(best_crtcs, crtcs, 352 + dev->mode_config.num_connector * 353 + sizeof(struct drm_crtc *)); 354 + } 355 + c++; 356 + } 357 + out: 358 + kfree(crtcs); 359 + return best_score; 360 + } 361 + 362 + static void drm_setup_crtcs(struct drm_device *dev) 363 + { 364 + struct drm_crtc **crtcs; 365 + struct drm_display_mode **modes; 366 + struct drm_encoder *encoder; 367 + struct drm_connector *connector; 368 + bool *enabled; 369 + int width, height; 370 + int i, ret; 371 + 372 + width = dev->mode_config.max_width; 373 + height = dev->mode_config.max_height; 374 + 375 + /* clean out all the encoder/crtc combos */ 376 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 377 + encoder->crtc = NULL; 378 + } 379 + 380 + crtcs = kcalloc(dev->mode_config.num_connector, 381 + sizeof(struct drm_crtc *), GFP_KERNEL); 382 + modes = kcalloc(dev->mode_config.num_connector, 383 + sizeof(struct drm_display_mode *), GFP_KERNEL); 384 + enabled = kcalloc(dev->mode_config.num_connector, 385 + sizeof(bool), GFP_KERNEL); 386 + 387 + drm_enable_connectors(dev, enabled); 388 + 389 + ret = drm_target_preferred(dev, modes, enabled, width, height); 390 + if (!ret) 391 + DRM_ERROR("Unable to find initial modes\n"); 392 + 393 + drm_pick_crtcs(dev, crtcs, modes, 0, width, height); 394 + 395 + i = 0; 396 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 397 + struct drm_display_mode *mode = modes[i]; 398 + struct drm_crtc *crtc = crtcs[i]; 399 + 400 + if (connector->encoder == NULL) { 401 + i++; 402 + continue; 403 + } 404 + 405 + if (mode && crtc) { 406 + crtc->desired_mode = mode; 407 + connector->encoder->crtc = crtc; 408 + } else 409 + connector->encoder->crtc = NULL; 410 + i++; 411 + } 412 + 413 + kfree(crtcs); 414 + kfree(modes); 415 + kfree(enabled); 416 + } 417 + /** 418 + * drm_crtc_set_mode - set a mode 419 + * @crtc: CRTC to program 420 + * @mode: mode to use 421 + * @x: width of mode 422 + * @y: height of mode 423 + * 424 + * LOCKING: 425 + * Caller must hold mode config lock. 426 + * 427 + * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance 428 + * to fixup or reject the mode prior to trying to set it. 429 + * 430 + * RETURNS: 431 + * True if the mode was set successfully, or false otherwise. 432 + */ 433 + bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 434 + struct drm_display_mode *mode, 435 + int x, int y) 436 + { 437 + struct drm_device *dev = crtc->dev; 438 + struct drm_display_mode *adjusted_mode, saved_mode; 439 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 440 + struct drm_encoder_helper_funcs *encoder_funcs; 441 + int saved_x, saved_y; 442 + struct drm_encoder *encoder; 443 + bool ret = true; 444 + 445 + adjusted_mode = drm_mode_duplicate(dev, mode); 446 + 447 + crtc->enabled = drm_helper_crtc_in_use(crtc); 448 + 449 + if (!crtc->enabled) 450 + return true; 451 + 452 + saved_mode = crtc->mode; 453 + saved_x = crtc->x; 454 + saved_y = crtc->y; 455 + 456 + /* Update crtc values up front so the driver can rely on them for mode 457 + * setting. 458 + */ 459 + crtc->mode = *mode; 460 + crtc->x = x; 461 + crtc->y = y; 462 + 463 + if (drm_mode_equal(&saved_mode, &crtc->mode)) { 464 + if (saved_x != crtc->x || saved_y != crtc->y) { 465 + crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y); 466 + goto done; 467 + } 468 + } 469 + 470 + /* Pass our mode to the connectors and the CRTC to give them a chance to 471 + * adjust it according to limitations or connector properties, and also 472 + * a chance to reject the mode entirely. 473 + */ 474 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 475 + 476 + if (encoder->crtc != crtc) 477 + continue; 478 + encoder_funcs = encoder->helper_private; 479 + if (!(ret = encoder_funcs->mode_fixup(encoder, mode, 480 + adjusted_mode))) { 481 + goto done; 482 + } 483 + } 484 + 485 + if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { 486 + goto done; 487 + } 488 + 489 + /* Prepare the encoders and CRTCs before setting the mode. */ 490 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 491 + 492 + if (encoder->crtc != crtc) 493 + continue; 494 + encoder_funcs = encoder->helper_private; 495 + /* Disable the encoders as the first thing we do. */ 496 + encoder_funcs->prepare(encoder); 497 + } 498 + 499 + crtc_funcs->prepare(crtc); 500 + 501 + /* Set up the DPLL and any encoders state that needs to adjust or depend 502 + * on the DPLL. 503 + */ 504 + crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y); 505 + 506 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 507 + 508 + if (encoder->crtc != crtc) 509 + continue; 510 + 511 + DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), 512 + mode->name, mode->base.id); 513 + encoder_funcs = encoder->helper_private; 514 + encoder_funcs->mode_set(encoder, mode, adjusted_mode); 515 + } 516 + 517 + /* Now enable the clocks, plane, pipe, and connectors that we set up. */ 518 + crtc_funcs->commit(crtc); 519 + 520 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 521 + 522 + if (encoder->crtc != crtc) 523 + continue; 524 + 525 + encoder_funcs = encoder->helper_private; 526 + encoder_funcs->commit(encoder); 527 + 528 + } 529 + 530 + /* XXX free adjustedmode */ 531 + drm_mode_destroy(dev, adjusted_mode); 532 + /* FIXME: add subpixel order */ 533 + done: 534 + if (!ret) { 535 + crtc->mode = saved_mode; 536 + crtc->x = saved_x; 537 + crtc->y = saved_y; 538 + } 539 + 540 + return ret; 541 + } 542 + EXPORT_SYMBOL(drm_crtc_helper_set_mode); 543 + 544 + 545 + /** 546 + * drm_crtc_helper_set_config - set a new config from userspace 547 + * @crtc: CRTC to setup 548 + * @crtc_info: user provided configuration 549 + * @new_mode: new mode to set 550 + * @connector_set: set of connectors for the new config 551 + * @fb: new framebuffer 552 + * 553 + * LOCKING: 554 + * Caller must hold mode config lock. 555 + * 556 + * Setup a new configuration, provided by the user in @crtc_info, and enable 557 + * it. 558 + * 559 + * RETURNS: 560 + * Zero. (FIXME) 561 + */ 562 + int drm_crtc_helper_set_config(struct drm_mode_set *set) 563 + { 564 + struct drm_device *dev; 565 + struct drm_crtc **save_crtcs, *new_crtc; 566 + struct drm_encoder **save_encoders, *new_encoder; 567 + bool save_enabled; 568 + bool changed = false; 569 + bool flip_or_move = false; 570 + struct drm_connector *connector; 571 + int count = 0, ro, fail = 0; 572 + struct drm_crtc_helper_funcs *crtc_funcs; 573 + int ret = 0; 574 + 575 + DRM_DEBUG("\n"); 576 + 577 + if (!set) 578 + return -EINVAL; 579 + 580 + if (!set->crtc) 581 + return -EINVAL; 582 + 583 + if (!set->crtc->helper_private) 584 + return -EINVAL; 585 + 586 + crtc_funcs = set->crtc->helper_private; 587 + 588 + DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n", 589 + set->crtc, set->crtc->base.id, set->fb, set->connectors, 590 + (int)set->num_connectors, set->x, set->y); 591 + 592 + dev = set->crtc->dev; 593 + 594 + /* save previous config */ 595 + save_enabled = set->crtc->enabled; 596 + 597 + /* this is meant to be num_connector not num_crtc */ 598 + save_crtcs = kzalloc(dev->mode_config.num_connector * 599 + sizeof(struct drm_crtc *), GFP_KERNEL); 600 + if (!save_crtcs) 601 + return -ENOMEM; 602 + 603 + save_encoders = kzalloc(dev->mode_config.num_connector * 604 + sizeof(struct drm_encoders *), GFP_KERNEL); 605 + if (!save_encoders) { 606 + kfree(save_crtcs); 607 + return -ENOMEM; 608 + } 609 + 610 + /* We should be able to check here if the fb has the same properties 611 + * and then just flip_or_move it */ 612 + if (set->crtc->fb != set->fb) { 613 + /* if we have no fb then its a change not a flip */ 614 + if (set->crtc->fb == NULL) 615 + changed = true; 616 + else 617 + flip_or_move = true; 618 + } 619 + 620 + if (set->x != set->crtc->x || set->y != set->crtc->y) 621 + flip_or_move = true; 622 + 623 + if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { 624 + DRM_DEBUG("modes are different\n"); 625 + drm_mode_debug_printmodeline(&set->crtc->mode); 626 + drm_mode_debug_printmodeline(set->mode); 627 + changed = true; 628 + } 629 + 630 + /* a) traverse passed in connector list and get encoders for them */ 631 + count = 0; 632 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 633 + struct drm_connector_helper_funcs *connector_funcs = 634 + connector->helper_private; 635 + save_encoders[count++] = connector->encoder; 636 + new_encoder = connector->encoder; 637 + for (ro = 0; ro < set->num_connectors; ro++) { 638 + if (set->connectors[ro] == connector) { 639 + new_encoder = connector_funcs->best_encoder(connector); 640 + /* if we can't get an encoder for a connector 641 + we are setting now - then fail */ 642 + if (new_encoder == NULL) 643 + /* don't break so fail path works correct */ 644 + fail = 1; 645 + break; 646 + } 647 + } 648 + 649 + if (new_encoder != connector->encoder) { 650 + changed = true; 651 + connector->encoder = new_encoder; 652 + } 653 + } 654 + 655 + if (fail) { 656 + ret = -EINVAL; 657 + goto fail_no_encoder; 658 + } 659 + 660 + count = 0; 661 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 662 + if (!connector->encoder) 663 + continue; 664 + 665 + save_crtcs[count++] = connector->encoder->crtc; 666 + 667 + if (connector->encoder->crtc == set->crtc) 668 + new_crtc = NULL; 669 + else 670 + new_crtc = connector->encoder->crtc; 671 + 672 + for (ro = 0; ro < set->num_connectors; ro++) { 673 + if (set->connectors[ro] == connector) 674 + new_crtc = set->crtc; 675 + } 676 + if (new_crtc != connector->encoder->crtc) { 677 + changed = true; 678 + connector->encoder->crtc = new_crtc; 679 + } 680 + } 681 + 682 + /* mode_set_base is not a required function */ 683 + if (flip_or_move && !crtc_funcs->mode_set_base) 684 + changed = true; 685 + 686 + if (changed) { 687 + set->crtc->fb = set->fb; 688 + set->crtc->enabled = (set->mode != NULL); 689 + if (set->mode != NULL) { 690 + DRM_DEBUG("attempting to set mode from userspace\n"); 691 + drm_mode_debug_printmodeline(set->mode); 692 + if (!drm_crtc_helper_set_mode(set->crtc, set->mode, 693 + set->x, set->y)) { 694 + ret = -EINVAL; 695 + goto fail_set_mode; 696 + } 697 + /* TODO are these needed? */ 698 + set->crtc->desired_x = set->x; 699 + set->crtc->desired_y = set->y; 700 + set->crtc->desired_mode = set->mode; 701 + } 702 + drm_helper_disable_unused_functions(dev); 703 + } else if (flip_or_move) { 704 + if (set->crtc->fb != set->fb) 705 + set->crtc->fb = set->fb; 706 + crtc_funcs->mode_set_base(set->crtc, set->x, set->y); 707 + } 708 + 709 + kfree(save_encoders); 710 + kfree(save_crtcs); 711 + return 0; 712 + 713 + fail_set_mode: 714 + set->crtc->enabled = save_enabled; 715 + count = 0; 716 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) 717 + connector->encoder->crtc = save_crtcs[count++]; 718 + fail_no_encoder: 719 + kfree(save_crtcs); 720 + count = 0; 721 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 722 + connector->encoder = save_encoders[count++]; 723 + } 724 + kfree(save_encoders); 725 + return ret; 726 + } 727 + EXPORT_SYMBOL(drm_crtc_helper_set_config); 728 + 729 + bool drm_helper_plugged_event(struct drm_device *dev) 730 + { 731 + DRM_DEBUG("\n"); 732 + 733 + drm_helper_probe_connector_modes(dev, dev->mode_config.max_width, 734 + dev->mode_config.max_height); 735 + 736 + drm_setup_crtcs(dev); 737 + 738 + /* alert the driver fb layer */ 739 + dev->mode_config.funcs->fb_changed(dev); 740 + 741 + /* FIXME: send hotplug event */ 742 + return true; 743 + } 744 + /** 745 + * drm_initial_config - setup a sane initial connector configuration 746 + * @dev: DRM device 747 + * @can_grow: this configuration is growable 748 + * 749 + * LOCKING: 750 + * Called at init time, must take mode config lock. 751 + * 752 + * Scan the CRTCs and connectors and try to put together an initial setup. 753 + * At the moment, this is a cloned configuration across all heads with 754 + * a new framebuffer object as the backing store. 755 + * 756 + * RETURNS: 757 + * Zero if everything went ok, nonzero otherwise. 758 + */ 759 + bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) 760 + { 761 + int ret = false; 762 + 763 + drm_helper_plugged_event(dev); 764 + return ret; 765 + } 766 + EXPORT_SYMBOL(drm_helper_initial_config); 767 + 768 + /** 769 + * drm_hotplug_stage_two 770 + * @dev DRM device 771 + * @connector hotpluged connector 772 + * 773 + * LOCKING. 774 + * Caller must hold mode config lock, function might grab struct lock. 775 + * 776 + * Stage two of a hotplug. 777 + * 778 + * RETURNS: 779 + * Zero on success, errno on failure. 780 + */ 781 + int drm_helper_hotplug_stage_two(struct drm_device *dev) 782 + { 783 + dev->mode_config.hotplug_counter++; 784 + 785 + drm_helper_plugged_event(dev); 786 + 787 + return 0; 788 + } 789 + EXPORT_SYMBOL(drm_helper_hotplug_stage_two); 790 + 791 + int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, 792 + struct drm_mode_fb_cmd *mode_cmd) 793 + { 794 + fb->width = mode_cmd->width; 795 + fb->height = mode_cmd->height; 796 + fb->pitch = mode_cmd->pitch; 797 + fb->bits_per_pixel = mode_cmd->bpp; 798 + fb->depth = mode_cmd->depth; 799 + 800 + return 0; 801 + } 802 + EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); 803 + 804 + int drm_helper_resume_force_mode(struct drm_device *dev) 805 + { 806 + struct drm_crtc *crtc; 807 + int ret; 808 + 809 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 810 + 811 + if (!crtc->enabled) 812 + continue; 813 + 814 + ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, 815 + crtc->y); 816 + 817 + if (ret == false) 818 + DRM_ERROR("failed to set mode on crtc %p\n", crtc); 819 + } 820 + return 0; 821 + } 822 + EXPORT_SYMBOL(drm_helper_resume_force_mode);
+30 -4
drivers/gpu/drm/drm_drv.c
··· 126 126 DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0), 127 127 DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), 128 128 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), 129 + 130 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW), 131 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), 132 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW), 133 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), 134 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 135 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), 136 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), 137 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), 138 + 139 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 140 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 141 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 142 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 143 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW), 144 + 145 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_REPLACEFB, drm_mode_replacefb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW), 146 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW), 147 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER), 148 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), 129 149 }; 130 150 131 151 #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) ··· 170 150 dev->driver->lastclose(dev); 171 151 DRM_DEBUG("driver lastclose completed\n"); 172 152 173 - if (dev->irq_enabled) 153 + if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET)) 174 154 drm_irq_uninstall(dev); 175 155 176 156 mutex_lock(&dev->struct_mutex); ··· 180 160 del_timer(&dev->timer); 181 161 182 162 /* Clear AGP information */ 183 - if (drm_core_has_AGP(dev) && dev->agp) { 163 + if (drm_core_has_AGP(dev) && dev->agp && 164 + !drm_core_check_feature(dev, DRIVER_MODESET)) { 184 165 struct drm_agp_mem *entry, *tempe; 185 166 186 167 /* Remove AGP resources, but leave dev->agp ··· 200 179 dev->agp->acquired = 0; 201 180 dev->agp->enabled = 0; 202 181 } 203 - if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) { 182 + if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg && 183 + !drm_core_check_feature(dev, DRIVER_MODESET)) { 204 184 drm_sg_cleanup(dev->sg); 205 185 dev->sg = NULL; 206 186 } ··· 228 206 } 229 207 dev->queue_count = 0; 230 208 231 - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 209 + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && 210 + !drm_core_check_feature(dev, DRIVER_MODESET)) 232 211 drm_dma_takedown(dev); 233 212 234 213 dev->dev_mapping = NULL; ··· 329 306 330 307 drm_ht_remove(&dev->map_hash); 331 308 drm_ctxbitmap_cleanup(dev); 309 + 310 + if (drm_core_check_feature(dev, DRIVER_MODESET)) 311 + drm_put_minor(&dev->control); 332 312 333 313 if (driver->driver_features & DRIVER_GEM) 334 314 drm_gem_destroy(dev);
+732
drivers/gpu/drm/drm_edid.c
··· 1 + /* 2 + * Copyright (c) 2006 Luc Verhaegen (quirks list) 3 + * Copyright (c) 2007-2008 Intel Corporation 4 + * Jesse Barnes <jesse.barnes@intel.com> 5 + * 6 + * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from 7 + * FB layer. 8 + * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com> 9 + * 10 + * Permission is hereby granted, free of charge, to any person obtaining a 11 + * copy of this software and associated documentation files (the "Software"), 12 + * to deal in the Software without restriction, including without limitation 13 + * the rights to use, copy, modify, merge, publish, distribute, sub license, 14 + * and/or sell copies of the Software, and to permit persons to whom the 15 + * Software is furnished to do so, subject to the following conditions: 16 + * 17 + * The above copyright notice and this permission notice (including the 18 + * next paragraph) shall be included in all copies or substantial portions 19 + * of the Software. 20 + * 21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 24 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 + * DEALINGS IN THE SOFTWARE. 28 + */ 29 + #include <linux/kernel.h> 30 + #include <linux/i2c.h> 31 + #include <linux/i2c-algo-bit.h> 32 + #include "drmP.h" 33 + #include "drm_edid.h" 34 + 35 + /* 36 + * TODO: 37 + * - support EDID 1.4 (incl. CE blocks) 38 + */ 39 + 40 + /* 41 + * EDID blocks out in the wild have a variety of bugs, try to collect 42 + * them here (note that userspace may work around broken monitors first, 43 + * but fixes should make their way here so that the kernel "just works" 44 + * on as many displays as possible). 45 + */ 46 + 47 + /* First detailed mode wrong, use largest 60Hz mode */ 48 + #define EDID_QUIRK_PREFER_LARGE_60 (1 << 0) 49 + /* Reported 135MHz pixel clock is too high, needs adjustment */ 50 + #define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1) 51 + /* Prefer the largest mode at 75 Hz */ 52 + #define EDID_QUIRK_PREFER_LARGE_75 (1 << 2) 53 + /* Detail timing is in cm not mm */ 54 + #define EDID_QUIRK_DETAILED_IN_CM (1 << 3) 55 + /* Detailed timing descriptors have bogus size values, so just take the 56 + * maximum size and use that. 57 + */ 58 + #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) 59 + /* Monitor forgot to set the first detailed is preferred bit. */ 60 + #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) 61 + /* use +hsync +vsync for detailed mode */ 62 + #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) 63 + 64 + static struct edid_quirk { 65 + char *vendor; 66 + int product_id; 67 + u32 quirks; 68 + } edid_quirk_list[] = { 69 + /* Acer AL1706 */ 70 + { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, 71 + /* Acer F51 */ 72 + { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 }, 73 + /* Unknown Acer */ 74 + { "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, 75 + 76 + /* Belinea 10 15 55 */ 77 + { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, 78 + { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, 79 + 80 + /* Envision Peripherals, Inc. EN-7100e */ 81 + { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, 82 + 83 + /* Funai Electronics PM36B */ 84 + { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | 85 + EDID_QUIRK_DETAILED_IN_CM }, 86 + 87 + /* LG Philips LCD LP154W01-A5 */ 88 + { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, 89 + { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, 90 + 91 + /* Philips 107p5 CRT */ 92 + { "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, 93 + 94 + /* Proview AY765C */ 95 + { "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, 96 + 97 + /* Samsung SyncMaster 205BW. Note: irony */ 98 + { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP }, 99 + /* Samsung SyncMaster 22[5-6]BW */ 100 + { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, 101 + { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, 102 + }; 103 + 104 + 105 + /* Valid EDID header has these bytes */ 106 + static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; 107 + 108 + /** 109 + * edid_is_valid - sanity check EDID data 110 + * @edid: EDID data 111 + * 112 + * Sanity check the EDID block by looking at the header, the version number 113 + * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's 114 + * valid. 115 + */ 116 + static bool edid_is_valid(struct edid *edid) 117 + { 118 + int i; 119 + u8 csum = 0; 120 + u8 *raw_edid = (u8 *)edid; 121 + 122 + if (memcmp(edid->header, edid_header, sizeof(edid_header))) 123 + goto bad; 124 + if (edid->version != 1) { 125 + DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); 126 + goto bad; 127 + } 128 + if (edid->revision <= 0 || edid->revision > 3) { 129 + DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); 130 + goto bad; 131 + } 132 + 133 + for (i = 0; i < EDID_LENGTH; i++) 134 + csum += raw_edid[i]; 135 + if (csum) { 136 + DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); 137 + goto bad; 138 + } 139 + 140 + return 1; 141 + 142 + bad: 143 + if (raw_edid) { 144 + DRM_ERROR("Raw EDID:\n"); 145 + print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); 146 + printk("\n"); 147 + } 148 + return 0; 149 + } 150 + 151 + /** 152 + * edid_vendor - match a string against EDID's obfuscated vendor field 153 + * @edid: EDID to match 154 + * @vendor: vendor string 155 + * 156 + * Returns true if @vendor is in @edid, false otherwise 157 + */ 158 + static bool edid_vendor(struct edid *edid, char *vendor) 159 + { 160 + char edid_vendor[3]; 161 + 162 + edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@'; 163 + edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) | 164 + ((edid->mfg_id[1] & 0xe0) >> 5)) + '@'; 165 + edid_vendor[2] = (edid->mfg_id[2] & 0x1f) + '@'; 166 + 167 + return !strncmp(edid_vendor, vendor, 3); 168 + } 169 + 170 + /** 171 + * edid_get_quirks - return quirk flags for a given EDID 172 + * @edid: EDID to process 173 + * 174 + * This tells subsequent routines what fixes they need to apply. 175 + */ 176 + static u32 edid_get_quirks(struct edid *edid) 177 + { 178 + struct edid_quirk *quirk; 179 + int i; 180 + 181 + for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) { 182 + quirk = &edid_quirk_list[i]; 183 + 184 + if (edid_vendor(edid, quirk->vendor) && 185 + (EDID_PRODUCT_ID(edid) == quirk->product_id)) 186 + return quirk->quirks; 187 + } 188 + 189 + return 0; 190 + } 191 + 192 + #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) 193 + #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) 194 + 195 + 196 + /** 197 + * edid_fixup_preferred - set preferred modes based on quirk list 198 + * @connector: has mode list to fix up 199 + * @quirks: quirks list 200 + * 201 + * Walk the mode list for @connector, clearing the preferred status 202 + * on existing modes and setting it anew for the right mode ala @quirks. 203 + */ 204 + static void edid_fixup_preferred(struct drm_connector *connector, 205 + u32 quirks) 206 + { 207 + struct drm_display_mode *t, *cur_mode, *preferred_mode; 208 + int target_refresh; 209 + 210 + if (list_empty(&connector->probed_modes)) 211 + return; 212 + 213 + if (quirks & EDID_QUIRK_PREFER_LARGE_60) 214 + target_refresh = 60; 215 + if (quirks & EDID_QUIRK_PREFER_LARGE_75) 216 + target_refresh = 75; 217 + 218 + preferred_mode = list_first_entry(&connector->probed_modes, 219 + struct drm_display_mode, head); 220 + 221 + list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) { 222 + cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED; 223 + 224 + if (cur_mode == preferred_mode) 225 + continue; 226 + 227 + /* Largest mode is preferred */ 228 + if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode)) 229 + preferred_mode = cur_mode; 230 + 231 + /* At a given size, try to get closest to target refresh */ 232 + if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) && 233 + MODE_REFRESH_DIFF(cur_mode, target_refresh) < 234 + MODE_REFRESH_DIFF(preferred_mode, target_refresh)) { 235 + preferred_mode = cur_mode; 236 + } 237 + } 238 + 239 + preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; 240 + } 241 + 242 + /** 243 + * drm_mode_std - convert standard mode info (width, height, refresh) into mode 244 + * @t: standard timing params 245 + * 246 + * Take the standard timing params (in this case width, aspect, and refresh) 247 + * and convert them into a real mode using CVT. 248 + * 249 + * Punts for now, but should eventually use the FB layer's CVT based mode 250 + * generation code. 251 + */ 252 + struct drm_display_mode *drm_mode_std(struct drm_device *dev, 253 + struct std_timing *t) 254 + { 255 + struct drm_display_mode *mode; 256 + int hsize = t->hsize * 8 + 248, vsize; 257 + 258 + mode = drm_mode_create(dev); 259 + if (!mode) 260 + return NULL; 261 + 262 + if (t->aspect_ratio == 0) 263 + vsize = (hsize * 10) / 16; 264 + else if (t->aspect_ratio == 1) 265 + vsize = (hsize * 3) / 4; 266 + else if (t->aspect_ratio == 2) 267 + vsize = (hsize * 4) / 5; 268 + else 269 + vsize = (hsize * 9) / 16; 270 + 271 + drm_mode_set_name(mode); 272 + 273 + return mode; 274 + } 275 + 276 + /** 277 + * drm_mode_detailed - create a new mode from an EDID detailed timing section 278 + * @dev: DRM device (needed to create new mode) 279 + * @edid: EDID block 280 + * @timing: EDID detailed timing info 281 + * @quirks: quirks to apply 282 + * 283 + * An EDID detailed timing block contains enough info for us to create and 284 + * return a new struct drm_display_mode. 285 + */ 286 + static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, 287 + struct edid *edid, 288 + struct detailed_timing *timing, 289 + u32 quirks) 290 + { 291 + struct drm_display_mode *mode; 292 + struct detailed_pixel_timing *pt = &timing->data.pixel_data; 293 + 294 + if (pt->stereo) { 295 + printk(KERN_WARNING "stereo mode not supported\n"); 296 + return NULL; 297 + } 298 + if (!pt->separate_sync) { 299 + printk(KERN_WARNING "integrated sync not supported\n"); 300 + return NULL; 301 + } 302 + 303 + mode = drm_mode_create(dev); 304 + if (!mode) 305 + return NULL; 306 + 307 + mode->type = DRM_MODE_TYPE_DRIVER; 308 + 309 + if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) 310 + timing->pixel_clock = 1088; 311 + 312 + mode->clock = timing->pixel_clock * 10; 313 + 314 + mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo; 315 + mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) | 316 + pt->hsync_offset_lo); 317 + mode->hsync_end = mode->hsync_start + 318 + ((pt->hsync_pulse_width_hi << 8) | 319 + pt->hsync_pulse_width_lo); 320 + mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); 321 + 322 + mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; 323 + mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | 324 + pt->vsync_offset_lo); 325 + mode->vsync_end = mode->vsync_start + 326 + ((pt->vsync_pulse_width_hi << 8) | 327 + pt->vsync_pulse_width_lo); 328 + mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); 329 + 330 + drm_mode_set_name(mode); 331 + 332 + if (pt->interlaced) 333 + mode->flags |= DRM_MODE_FLAG_INTERLACE; 334 + 335 + if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { 336 + pt->hsync_positive = 1; 337 + pt->vsync_positive = 1; 338 + } 339 + 340 + mode->flags |= pt->hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; 341 + mode->flags |= pt->vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; 342 + 343 + mode->width_mm = pt->width_mm_lo | (pt->width_mm_hi << 8); 344 + mode->height_mm = pt->height_mm_lo | (pt->height_mm_hi << 8); 345 + 346 + if (quirks & EDID_QUIRK_DETAILED_IN_CM) { 347 + mode->width_mm *= 10; 348 + mode->height_mm *= 10; 349 + } 350 + 351 + if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { 352 + mode->width_mm = edid->width_cm * 10; 353 + mode->height_mm = edid->height_cm * 10; 354 + } 355 + 356 + return mode; 357 + } 358 + 359 + /* 360 + * Detailed mode info for the EDID "established modes" data to use. 361 + */ 362 + static struct drm_display_mode edid_est_modes[] = { 363 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, 364 + 968, 1056, 0, 600, 601, 605, 628, 0, 365 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ 366 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, 367 + 896, 1024, 0, 600, 601, 603, 625, 0, 368 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ 369 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, 370 + 720, 840, 0, 480, 481, 484, 500, 0, 371 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ 372 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, 373 + 704, 832, 0, 480, 489, 491, 520, 0, 374 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ 375 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, 376 + 768, 864, 0, 480, 483, 486, 525, 0, 377 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ 378 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, 379 + 752, 800, 0, 480, 490, 492, 525, 0, 380 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ 381 + { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, 382 + 846, 900, 0, 400, 421, 423, 449, 0, 383 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ 384 + { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, 385 + 846, 900, 0, 400, 412, 414, 449, 0, 386 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ 387 + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, 388 + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, 389 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ 390 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, 391 + 1136, 1312, 0, 768, 769, 772, 800, 0, 392 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ 393 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, 394 + 1184, 1328, 0, 768, 771, 777, 806, 0, 395 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ 396 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, 397 + 1184, 1344, 0, 768, 771, 777, 806, 0, 398 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ 399 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, 400 + 1208, 1264, 0, 768, 768, 776, 817, 0, 401 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ 402 + { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, 403 + 928, 1152, 0, 624, 625, 628, 667, 0, 404 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ 405 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, 406 + 896, 1056, 0, 600, 601, 604, 625, 0, 407 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ 408 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, 409 + 976, 1040, 0, 600, 637, 643, 666, 0, 410 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ 411 + { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, 412 + 1344, 1600, 0, 864, 865, 868, 900, 0, 413 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ 414 + }; 415 + 416 + #define EDID_EST_TIMINGS 16 417 + #define EDID_STD_TIMINGS 8 418 + #define EDID_DETAILED_TIMINGS 4 419 + 420 + /** 421 + * add_established_modes - get est. modes from EDID and add them 422 + * @edid: EDID block to scan 423 + * 424 + * Each EDID block contains a bitmap of the supported "established modes" list 425 + * (defined above). Tease them out and add them to the global modes list. 426 + */ 427 + static int add_established_modes(struct drm_connector *connector, struct edid *edid) 428 + { 429 + struct drm_device *dev = connector->dev; 430 + unsigned long est_bits = edid->established_timings.t1 | 431 + (edid->established_timings.t2 << 8) | 432 + ((edid->established_timings.mfg_rsvd & 0x80) << 9); 433 + int i, modes = 0; 434 + 435 + for (i = 0; i <= EDID_EST_TIMINGS; i++) 436 + if (est_bits & (1<<i)) { 437 + struct drm_display_mode *newmode; 438 + newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); 439 + if (newmode) { 440 + drm_mode_probed_add(connector, newmode); 441 + modes++; 442 + } 443 + } 444 + 445 + return modes; 446 + } 447 + 448 + /** 449 + * add_standard_modes - get std. modes from EDID and add them 450 + * @edid: EDID block to scan 451 + * 452 + * Standard modes can be calculated using the CVT standard. Grab them from 453 + * @edid, calculate them, and add them to the list. 454 + */ 455 + static int add_standard_modes(struct drm_connector *connector, struct edid *edid) 456 + { 457 + struct drm_device *dev = connector->dev; 458 + int i, modes = 0; 459 + 460 + for (i = 0; i < EDID_STD_TIMINGS; i++) { 461 + struct std_timing *t = &edid->standard_timings[i]; 462 + struct drm_display_mode *newmode; 463 + 464 + /* If std timings bytes are 1, 1 it's empty */ 465 + if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1) 466 + continue; 467 + 468 + newmode = drm_mode_std(dev, &edid->standard_timings[i]); 469 + if (newmode) { 470 + drm_mode_probed_add(connector, newmode); 471 + modes++; 472 + } 473 + } 474 + 475 + return modes; 476 + } 477 + 478 + /** 479 + * add_detailed_modes - get detailed mode info from EDID data 480 + * @connector: attached connector 481 + * @edid: EDID block to scan 482 + * @quirks: quirks to apply 483 + * 484 + * Some of the detailed timing sections may contain mode information. Grab 485 + * it and add it to the list. 486 + */ 487 + static int add_detailed_info(struct drm_connector *connector, 488 + struct edid *edid, u32 quirks) 489 + { 490 + struct drm_device *dev = connector->dev; 491 + int i, j, modes = 0; 492 + 493 + for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { 494 + struct detailed_timing *timing = &edid->detailed_timings[i]; 495 + struct detailed_non_pixel *data = &timing->data.other_data; 496 + struct drm_display_mode *newmode; 497 + 498 + /* EDID up to and including 1.2 may put monitor info here */ 499 + if (edid->version == 1 && edid->revision < 3) 500 + continue; 501 + 502 + /* Detailed mode timing */ 503 + if (timing->pixel_clock) { 504 + newmode = drm_mode_detailed(dev, edid, timing, quirks); 505 + if (!newmode) 506 + continue; 507 + 508 + /* First detailed mode is preferred */ 509 + if (i == 0 && edid->preferred_timing) 510 + newmode->type |= DRM_MODE_TYPE_PREFERRED; 511 + drm_mode_probed_add(connector, newmode); 512 + 513 + modes++; 514 + continue; 515 + } 516 + 517 + /* Other timing or info */ 518 + switch (data->type) { 519 + case EDID_DETAIL_MONITOR_SERIAL: 520 + break; 521 + case EDID_DETAIL_MONITOR_STRING: 522 + break; 523 + case EDID_DETAIL_MONITOR_RANGE: 524 + /* Get monitor range data */ 525 + break; 526 + case EDID_DETAIL_MONITOR_NAME: 527 + break; 528 + case EDID_DETAIL_MONITOR_CPDATA: 529 + break; 530 + case EDID_DETAIL_STD_MODES: 531 + /* Five modes per detailed section */ 532 + for (j = 0; j < 5; i++) { 533 + struct std_timing *std; 534 + struct drm_display_mode *newmode; 535 + 536 + std = &data->data.timings[j]; 537 + newmode = drm_mode_std(dev, std); 538 + if (newmode) { 539 + drm_mode_probed_add(connector, newmode); 540 + modes++; 541 + } 542 + } 543 + break; 544 + default: 545 + break; 546 + } 547 + } 548 + 549 + return modes; 550 + } 551 + 552 + #define DDC_ADDR 0x50 553 + 554 + unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter) 555 + { 556 + unsigned char start = 0x0; 557 + unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL); 558 + struct i2c_msg msgs[] = { 559 + { 560 + .addr = DDC_ADDR, 561 + .flags = 0, 562 + .len = 1, 563 + .buf = &start, 564 + }, { 565 + .addr = DDC_ADDR, 566 + .flags = I2C_M_RD, 567 + .len = EDID_LENGTH, 568 + .buf = buf, 569 + } 570 + }; 571 + 572 + if (!buf) { 573 + dev_warn(&adapter->dev, "unable to allocate memory for EDID " 574 + "block.\n"); 575 + return NULL; 576 + } 577 + 578 + if (i2c_transfer(adapter, msgs, 2) == 2) 579 + return buf; 580 + 581 + dev_info(&adapter->dev, "unable to read EDID block.\n"); 582 + kfree(buf); 583 + return NULL; 584 + } 585 + EXPORT_SYMBOL(drm_do_probe_ddc_edid); 586 + 587 + static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) 588 + { 589 + struct i2c_algo_bit_data *algo_data = adapter->algo_data; 590 + unsigned char *edid = NULL; 591 + int i, j; 592 + 593 + algo_data->setscl(algo_data->data, 1); 594 + 595 + for (i = 0; i < 1; i++) { 596 + /* For some old monitors we need the 597 + * following process to initialize/stop DDC 598 + */ 599 + algo_data->setsda(algo_data->data, 1); 600 + msleep(13); 601 + 602 + algo_data->setscl(algo_data->data, 1); 603 + for (j = 0; j < 5; j++) { 604 + msleep(10); 605 + if (algo_data->getscl(algo_data->data)) 606 + break; 607 + } 608 + if (j == 5) 609 + continue; 610 + 611 + algo_data->setsda(algo_data->data, 0); 612 + msleep(15); 613 + algo_data->setscl(algo_data->data, 0); 614 + msleep(15); 615 + algo_data->setsda(algo_data->data, 1); 616 + msleep(15); 617 + 618 + /* Do the real work */ 619 + edid = drm_do_probe_ddc_edid(adapter); 620 + algo_data->setsda(algo_data->data, 0); 621 + algo_data->setscl(algo_data->data, 0); 622 + msleep(15); 623 + 624 + algo_data->setscl(algo_data->data, 1); 625 + for (j = 0; j < 10; j++) { 626 + msleep(10); 627 + if (algo_data->getscl(algo_data->data)) 628 + break; 629 + } 630 + 631 + algo_data->setsda(algo_data->data, 1); 632 + msleep(15); 633 + algo_data->setscl(algo_data->data, 0); 634 + algo_data->setsda(algo_data->data, 0); 635 + if (edid) 636 + break; 637 + } 638 + /* Release the DDC lines when done or the Apple Cinema HD display 639 + * will switch off 640 + */ 641 + algo_data->setsda(algo_data->data, 1); 642 + algo_data->setscl(algo_data->data, 1); 643 + 644 + return edid; 645 + } 646 + 647 + /** 648 + * drm_get_edid - get EDID data, if available 649 + * @connector: connector we're probing 650 + * @adapter: i2c adapter to use for DDC 651 + * 652 + * Poke the given connector's i2c channel to grab EDID data if possible. 653 + * 654 + * Return edid data or NULL if we couldn't find any. 655 + */ 656 + struct edid *drm_get_edid(struct drm_connector *connector, 657 + struct i2c_adapter *adapter) 658 + { 659 + struct edid *edid; 660 + 661 + edid = (struct edid *)drm_ddc_read(adapter); 662 + if (!edid) { 663 + dev_warn(&connector->dev->pdev->dev, "%s: no EDID data\n", 664 + drm_get_connector_name(connector)); 665 + return NULL; 666 + } 667 + if (!edid_is_valid(edid)) { 668 + dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", 669 + drm_get_connector_name(connector)); 670 + kfree(edid); 671 + return NULL; 672 + } 673 + 674 + connector->display_info.raw_edid = (char *)edid; 675 + 676 + return edid; 677 + } 678 + EXPORT_SYMBOL(drm_get_edid); 679 + 680 + /** 681 + * drm_add_edid_modes - add modes from EDID data, if available 682 + * @connector: connector we're probing 683 + * @edid: edid data 684 + * 685 + * Add the specified modes to the connector's mode list. 686 + * 687 + * Return number of modes added or 0 if we couldn't find any. 688 + */ 689 + int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) 690 + { 691 + int num_modes = 0; 692 + u32 quirks; 693 + 694 + if (edid == NULL) { 695 + return 0; 696 + } 697 + if (!edid_is_valid(edid)) { 698 + dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", 699 + drm_get_connector_name(connector)); 700 + return 0; 701 + } 702 + 703 + quirks = edid_get_quirks(edid); 704 + 705 + num_modes += add_established_modes(connector, edid); 706 + num_modes += add_standard_modes(connector, edid); 707 + num_modes += add_detailed_info(connector, edid, quirks); 708 + 709 + if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) 710 + edid_fixup_preferred(connector, quirks); 711 + 712 + connector->display_info.serration_vsync = edid->serration_vsync; 713 + connector->display_info.sync_on_green = edid->sync_on_green; 714 + connector->display_info.composite_sync = edid->composite_sync; 715 + connector->display_info.separate_syncs = edid->separate_syncs; 716 + connector->display_info.blank_to_black = edid->blank_to_black; 717 + connector->display_info.video_level = edid->video_level; 718 + connector->display_info.digital = edid->digital; 719 + connector->display_info.width_mm = edid->width_cm * 10; 720 + connector->display_info.height_mm = edid->height_cm * 10; 721 + connector->display_info.gamma = edid->gamma; 722 + connector->display_info.gtf_supported = edid->default_gtf; 723 + connector->display_info.standard_color = edid->standard_color; 724 + connector->display_info.display_type = edid->display_type; 725 + connector->display_info.active_off_supported = edid->pm_active_off; 726 + connector->display_info.suspend_supported = edid->pm_suspend; 727 + connector->display_info.standby_supported = edid->pm_standby; 728 + connector->display_info.gamma = edid->gamma; 729 + 730 + return num_modes; 731 + } 732 + EXPORT_SYMBOL(drm_add_edid_modes);
+12 -10
drivers/gpu/drm/drm_fops.c
··· 35 35 */ 36 36 37 37 #include "drmP.h" 38 - #include "drm_sarea.h" 39 38 #include <linux/poll.h> 40 39 #include <linux/smp_lock.h> 41 40 ··· 54 55 55 56 atomic_set(&dev->ioctl_count, 0); 56 57 atomic_set(&dev->vma_count, 0); 57 - dev->buf_use = 0; 58 - atomic_set(&dev->buf_alloc, 0); 59 58 60 - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) { 59 + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && 60 + !drm_core_check_feature(dev, DRIVER_MODESET)) { 61 + dev->buf_use = 0; 62 + atomic_set(&dev->buf_alloc, 0); 63 + 61 64 i = drm_dma_setup(dev); 62 65 if (i < 0) 63 66 return i; ··· 139 138 } 140 139 spin_unlock(&dev->count_lock); 141 140 } 142 - 143 141 out: 144 142 mutex_lock(&dev->struct_mutex); 145 - if (dev->dev_mapping == NULL) 146 - dev->dev_mapping = inode->i_mapping; 147 - else if (dev->dev_mapping != inode->i_mapping) 148 - WARN(1, "dev->dev_mapping not inode mapping (%p expected %p)\n", 149 - dev->dev_mapping, inode->i_mapping); 143 + if (minor->type == DRM_MINOR_LEGACY) { 144 + BUG_ON((dev->dev_mapping != NULL) && 145 + (dev->dev_mapping != inode->i_mapping)); 146 + if (dev->dev_mapping == NULL) 147 + dev->dev_mapping = inode->i_mapping; 148 + } 150 149 mutex_unlock(&dev->struct_mutex); 151 150 152 151 return retcode; ··· 252 251 priv->lock_count = 0; 253 252 254 253 INIT_LIST_HEAD(&priv->lhead); 254 + INIT_LIST_HEAD(&priv->fbs); 255 255 256 256 if (dev->driver->driver_features & DRIVER_GEM) 257 257 drm_gem_open(dev, priv);
+45 -19
drivers/gpu/drm/drm_irq.c
··· 305 305 case DRM_INST_HANDLER: 306 306 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 307 307 return 0; 308 + if (drm_core_check_feature(dev, DRIVER_MODESET)) 309 + return 0; 308 310 if (dev->if_version < DRM_IF_VERSION(1, 2) && 309 311 ctl->irq != dev->pdev->irq) 310 312 return -EINVAL; 311 313 return drm_irq_install(dev); 312 314 case DRM_UNINST_HANDLER: 313 315 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 316 + return 0; 317 + if (drm_core_check_feature(dev, DRIVER_MODESET)) 314 318 return 0; 315 319 return drm_irq_uninstall(dev); 316 320 default: ··· 431 427 EXPORT_SYMBOL(drm_vblank_put); 432 428 433 429 /** 430 + * drm_vblank_pre_modeset - account for vblanks across mode sets 431 + * @dev: DRM device 432 + * @crtc: CRTC in question 433 + * @post: post or pre mode set? 434 + * 435 + * Account for vblank events across mode setting events, which will likely 436 + * reset the hardware frame counter. 437 + */ 438 + void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) 439 + { 440 + /* 441 + * To avoid all the problems that might happen if interrupts 442 + * were enabled/disabled around or between these calls, we just 443 + * have the kernel take a reference on the CRTC (just once though 444 + * to avoid corrupting the count if multiple, mismatch calls occur), 445 + * so that interrupts remain enabled in the interim. 446 + */ 447 + if (!dev->vblank_inmodeset[crtc]) { 448 + dev->vblank_inmodeset[crtc] = 1; 449 + drm_vblank_get(dev, crtc); 450 + } 451 + } 452 + EXPORT_SYMBOL(drm_vblank_pre_modeset); 453 + 454 + void drm_vblank_post_modeset(struct drm_device *dev, int crtc) 455 + { 456 + unsigned long irqflags; 457 + 458 + if (dev->vblank_inmodeset[crtc]) { 459 + spin_lock_irqsave(&dev->vbl_lock, irqflags); 460 + dev->vblank_disable_allowed = 1; 461 + dev->vblank_inmodeset[crtc] = 0; 462 + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 463 + drm_vblank_put(dev, crtc); 464 + } 465 + } 466 + EXPORT_SYMBOL(drm_vblank_post_modeset); 467 + 468 + /** 434 469 * drm_modeset_ctl - handle vblank event counter changes across mode switch 435 470 * @DRM_IOCTL_ARGS: standard ioctl arguments 436 471 * ··· 484 441 struct drm_file *file_priv) 485 442 { 486 443 struct drm_modeset_ctl *modeset = data; 487 - unsigned long irqflags; 488 444 int crtc, ret = 0; 489 445 490 446 /* If drm_vblank_init() hasn't been called yet, just no-op */ ··· 496 454 goto out; 497 455 } 498 456 499 - /* 500 - * To avoid all the problems that might happen if interrupts 501 - * were enabled/disabled around or between these calls, we just 502 - * have the kernel take a reference on the CRTC (just once though 503 - * to avoid corrupting the count if multiple, mismatch calls occur), 504 - * so that interrupts remain enabled in the interim. 505 - */ 506 457 switch (modeset->cmd) { 507 458 case _DRM_PRE_MODESET: 508 - if (!dev->vblank_inmodeset[crtc]) { 509 - dev->vblank_inmodeset[crtc] = 1; 510 - drm_vblank_get(dev, crtc); 511 - } 459 + drm_vblank_pre_modeset(dev, crtc); 512 460 break; 513 461 case _DRM_POST_MODESET: 514 - if (dev->vblank_inmodeset[crtc]) { 515 - spin_lock_irqsave(&dev->vbl_lock, irqflags); 516 - dev->vblank_disable_allowed = 1; 517 - dev->vblank_inmodeset[crtc] = 0; 518 - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 519 - drm_vblank_put(dev, crtc); 520 - } 462 + drm_vblank_post_modeset(dev, crtc); 521 463 break; 522 464 default: 523 465 ret = -EINVAL;
+1
drivers/gpu/drm/drm_mm.c
··· 296 296 297 297 drm_free(entry, sizeof(*entry), DRM_MEM_MM); 298 298 } 299 + EXPORT_SYMBOL(drm_mm_takedown);
+576
drivers/gpu/drm/drm_modes.c
··· 1 + /* 2 + * The list_sort function is (presumably) licensed under the GPL (see the 3 + * top level "COPYING" file for details). 4 + * 5 + * The remainder of this file is: 6 + * 7 + * Copyright © 1997-2003 by The XFree86 Project, Inc. 8 + * Copyright © 2007 Dave Airlie 9 + * Copyright © 2007-2008 Intel Corporation 10 + * Jesse Barnes <jesse.barnes@intel.com> 11 + * 12 + * Permission is hereby granted, free of charge, to any person obtaining a 13 + * copy of this software and associated documentation files (the "Software"), 14 + * to deal in the Software without restriction, including without limitation 15 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 + * and/or sell copies of the Software, and to permit persons to whom the 17 + * Software is furnished to do so, subject to the following conditions: 18 + * 19 + * The above copyright notice and this permission notice shall be included in 20 + * all copies or substantial portions of the Software. 21 + * 22 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 + * OTHER DEALINGS IN THE SOFTWARE. 29 + * 30 + * Except as contained in this notice, the name of the copyright holder(s) 31 + * and author(s) shall not be used in advertising or otherwise to promote 32 + * the sale, use or other dealings in this Software without prior written 33 + * authorization from the copyright holder(s) and author(s). 34 + */ 35 + 36 + #include <linux/list.h> 37 + #include "drmP.h" 38 + #include "drm.h" 39 + #include "drm_crtc.h" 40 + 41 + /** 42 + * drm_mode_debug_printmodeline - debug print a mode 43 + * @dev: DRM device 44 + * @mode: mode to print 45 + * 46 + * LOCKING: 47 + * None. 48 + * 49 + * Describe @mode using DRM_DEBUG. 50 + */ 51 + void drm_mode_debug_printmodeline(struct drm_display_mode *mode) 52 + { 53 + DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", 54 + mode->base.id, mode->name, mode->vrefresh, mode->clock, 55 + mode->hdisplay, mode->hsync_start, 56 + mode->hsync_end, mode->htotal, 57 + mode->vdisplay, mode->vsync_start, 58 + mode->vsync_end, mode->vtotal, mode->type, mode->flags); 59 + } 60 + EXPORT_SYMBOL(drm_mode_debug_printmodeline); 61 + 62 + /** 63 + * drm_mode_set_name - set the name on a mode 64 + * @mode: name will be set in this mode 65 + * 66 + * LOCKING: 67 + * None. 68 + * 69 + * Set the name of @mode to a standard format. 70 + */ 71 + void drm_mode_set_name(struct drm_display_mode *mode) 72 + { 73 + snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay, 74 + mode->vdisplay); 75 + } 76 + EXPORT_SYMBOL(drm_mode_set_name); 77 + 78 + /** 79 + * drm_mode_list_concat - move modes from one list to another 80 + * @head: source list 81 + * @new: dst list 82 + * 83 + * LOCKING: 84 + * Caller must ensure both lists are locked. 85 + * 86 + * Move all the modes from @head to @new. 87 + */ 88 + void drm_mode_list_concat(struct list_head *head, struct list_head *new) 89 + { 90 + 91 + struct list_head *entry, *tmp; 92 + 93 + list_for_each_safe(entry, tmp, head) { 94 + list_move_tail(entry, new); 95 + } 96 + } 97 + EXPORT_SYMBOL(drm_mode_list_concat); 98 + 99 + /** 100 + * drm_mode_width - get the width of a mode 101 + * @mode: mode 102 + * 103 + * LOCKING: 104 + * None. 105 + * 106 + * Return @mode's width (hdisplay) value. 107 + * 108 + * FIXME: is this needed? 109 + * 110 + * RETURNS: 111 + * @mode->hdisplay 112 + */ 113 + int drm_mode_width(struct drm_display_mode *mode) 114 + { 115 + return mode->hdisplay; 116 + 117 + } 118 + EXPORT_SYMBOL(drm_mode_width); 119 + 120 + /** 121 + * drm_mode_height - get the height of a mode 122 + * @mode: mode 123 + * 124 + * LOCKING: 125 + * None. 126 + * 127 + * Return @mode's height (vdisplay) value. 128 + * 129 + * FIXME: is this needed? 130 + * 131 + * RETURNS: 132 + * @mode->vdisplay 133 + */ 134 + int drm_mode_height(struct drm_display_mode *mode) 135 + { 136 + return mode->vdisplay; 137 + } 138 + EXPORT_SYMBOL(drm_mode_height); 139 + 140 + /** 141 + * drm_mode_vrefresh - get the vrefresh of a mode 142 + * @mode: mode 143 + * 144 + * LOCKING: 145 + * None. 146 + * 147 + * Return @mode's vrefresh rate or calculate it if necessary. 148 + * 149 + * FIXME: why is this needed? shouldn't vrefresh be set already? 150 + * 151 + * RETURNS: 152 + * Vertical refresh rate of @mode x 1000. For precision reasons. 153 + */ 154 + int drm_mode_vrefresh(struct drm_display_mode *mode) 155 + { 156 + int refresh = 0; 157 + unsigned int calc_val; 158 + 159 + if (mode->vrefresh > 0) 160 + refresh = mode->vrefresh; 161 + else if (mode->htotal > 0 && mode->vtotal > 0) { 162 + /* work out vrefresh the value will be x1000 */ 163 + calc_val = (mode->clock * 1000); 164 + 165 + calc_val /= mode->htotal; 166 + calc_val *= 1000; 167 + calc_val /= mode->vtotal; 168 + 169 + refresh = calc_val; 170 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) 171 + refresh *= 2; 172 + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 173 + refresh /= 2; 174 + if (mode->vscan > 1) 175 + refresh /= mode->vscan; 176 + } 177 + return refresh; 178 + } 179 + EXPORT_SYMBOL(drm_mode_vrefresh); 180 + 181 + /** 182 + * drm_mode_set_crtcinfo - set CRTC modesetting parameters 183 + * @p: mode 184 + * @adjust_flags: unused? (FIXME) 185 + * 186 + * LOCKING: 187 + * None. 188 + * 189 + * Setup the CRTC modesetting parameters for @p, adjusting if necessary. 190 + */ 191 + void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) 192 + { 193 + if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN)) 194 + return; 195 + 196 + p->crtc_hdisplay = p->hdisplay; 197 + p->crtc_hsync_start = p->hsync_start; 198 + p->crtc_hsync_end = p->hsync_end; 199 + p->crtc_htotal = p->htotal; 200 + p->crtc_hskew = p->hskew; 201 + p->crtc_vdisplay = p->vdisplay; 202 + p->crtc_vsync_start = p->vsync_start; 203 + p->crtc_vsync_end = p->vsync_end; 204 + p->crtc_vtotal = p->vtotal; 205 + 206 + if (p->flags & DRM_MODE_FLAG_INTERLACE) { 207 + if (adjust_flags & CRTC_INTERLACE_HALVE_V) { 208 + p->crtc_vdisplay /= 2; 209 + p->crtc_vsync_start /= 2; 210 + p->crtc_vsync_end /= 2; 211 + p->crtc_vtotal /= 2; 212 + } 213 + 214 + p->crtc_vtotal |= 1; 215 + } 216 + 217 + if (p->flags & DRM_MODE_FLAG_DBLSCAN) { 218 + p->crtc_vdisplay *= 2; 219 + p->crtc_vsync_start *= 2; 220 + p->crtc_vsync_end *= 2; 221 + p->crtc_vtotal *= 2; 222 + } 223 + 224 + if (p->vscan > 1) { 225 + p->crtc_vdisplay *= p->vscan; 226 + p->crtc_vsync_start *= p->vscan; 227 + p->crtc_vsync_end *= p->vscan; 228 + p->crtc_vtotal *= p->vscan; 229 + } 230 + 231 + p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay); 232 + p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal); 233 + p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); 234 + p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); 235 + 236 + p->crtc_hadjusted = false; 237 + p->crtc_vadjusted = false; 238 + } 239 + EXPORT_SYMBOL(drm_mode_set_crtcinfo); 240 + 241 + 242 + /** 243 + * drm_mode_duplicate - allocate and duplicate an existing mode 244 + * @m: mode to duplicate 245 + * 246 + * LOCKING: 247 + * None. 248 + * 249 + * Just allocate a new mode, copy the existing mode into it, and return 250 + * a pointer to it. Used to create new instances of established modes. 251 + */ 252 + struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, 253 + struct drm_display_mode *mode) 254 + { 255 + struct drm_display_mode *nmode; 256 + int new_id; 257 + 258 + nmode = drm_mode_create(dev); 259 + if (!nmode) 260 + return NULL; 261 + 262 + new_id = nmode->base.id; 263 + *nmode = *mode; 264 + nmode->base.id = new_id; 265 + INIT_LIST_HEAD(&nmode->head); 266 + return nmode; 267 + } 268 + EXPORT_SYMBOL(drm_mode_duplicate); 269 + 270 + /** 271 + * drm_mode_equal - test modes for equality 272 + * @mode1: first mode 273 + * @mode2: second mode 274 + * 275 + * LOCKING: 276 + * None. 277 + * 278 + * Check to see if @mode1 and @mode2 are equivalent. 279 + * 280 + * RETURNS: 281 + * True if the modes are equal, false otherwise. 282 + */ 283 + bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2) 284 + { 285 + /* do clock check convert to PICOS so fb modes get matched 286 + * the same */ 287 + if (mode1->clock && mode2->clock) { 288 + if (KHZ2PICOS(mode1->clock) != KHZ2PICOS(mode2->clock)) 289 + return false; 290 + } else if (mode1->clock != mode2->clock) 291 + return false; 292 + 293 + if (mode1->hdisplay == mode2->hdisplay && 294 + mode1->hsync_start == mode2->hsync_start && 295 + mode1->hsync_end == mode2->hsync_end && 296 + mode1->htotal == mode2->htotal && 297 + mode1->hskew == mode2->hskew && 298 + mode1->vdisplay == mode2->vdisplay && 299 + mode1->vsync_start == mode2->vsync_start && 300 + mode1->vsync_end == mode2->vsync_end && 301 + mode1->vtotal == mode2->vtotal && 302 + mode1->vscan == mode2->vscan && 303 + mode1->flags == mode2->flags) 304 + return true; 305 + 306 + return false; 307 + } 308 + EXPORT_SYMBOL(drm_mode_equal); 309 + 310 + /** 311 + * drm_mode_validate_size - make sure modes adhere to size constraints 312 + * @dev: DRM device 313 + * @mode_list: list of modes to check 314 + * @maxX: maximum width 315 + * @maxY: maximum height 316 + * @maxPitch: max pitch 317 + * 318 + * LOCKING: 319 + * Caller must hold a lock protecting @mode_list. 320 + * 321 + * The DRM device (@dev) has size and pitch limits. Here we validate the 322 + * modes we probed for @dev against those limits and set their status as 323 + * necessary. 324 + */ 325 + void drm_mode_validate_size(struct drm_device *dev, 326 + struct list_head *mode_list, 327 + int maxX, int maxY, int maxPitch) 328 + { 329 + struct drm_display_mode *mode; 330 + 331 + list_for_each_entry(mode, mode_list, head) { 332 + if (maxPitch > 0 && mode->hdisplay > maxPitch) 333 + mode->status = MODE_BAD_WIDTH; 334 + 335 + if (maxX > 0 && mode->hdisplay > maxX) 336 + mode->status = MODE_VIRTUAL_X; 337 + 338 + if (maxY > 0 && mode->vdisplay > maxY) 339 + mode->status = MODE_VIRTUAL_Y; 340 + } 341 + } 342 + EXPORT_SYMBOL(drm_mode_validate_size); 343 + 344 + /** 345 + * drm_mode_validate_clocks - validate modes against clock limits 346 + * @dev: DRM device 347 + * @mode_list: list of modes to check 348 + * @min: minimum clock rate array 349 + * @max: maximum clock rate array 350 + * @n_ranges: number of clock ranges (size of arrays) 351 + * 352 + * LOCKING: 353 + * Caller must hold a lock protecting @mode_list. 354 + * 355 + * Some code may need to check a mode list against the clock limits of the 356 + * device in question. This function walks the mode list, testing to make 357 + * sure each mode falls within a given range (defined by @min and @max 358 + * arrays) and sets @mode->status as needed. 359 + */ 360 + void drm_mode_validate_clocks(struct drm_device *dev, 361 + struct list_head *mode_list, 362 + int *min, int *max, int n_ranges) 363 + { 364 + struct drm_display_mode *mode; 365 + int i; 366 + 367 + list_for_each_entry(mode, mode_list, head) { 368 + bool good = false; 369 + for (i = 0; i < n_ranges; i++) { 370 + if (mode->clock >= min[i] && mode->clock <= max[i]) { 371 + good = true; 372 + break; 373 + } 374 + } 375 + if (!good) 376 + mode->status = MODE_CLOCK_RANGE; 377 + } 378 + } 379 + EXPORT_SYMBOL(drm_mode_validate_clocks); 380 + 381 + /** 382 + * drm_mode_prune_invalid - remove invalid modes from mode list 383 + * @dev: DRM device 384 + * @mode_list: list of modes to check 385 + * @verbose: be verbose about it 386 + * 387 + * LOCKING: 388 + * Caller must hold a lock protecting @mode_list. 389 + * 390 + * Once mode list generation is complete, a caller can use this routine to 391 + * remove invalid modes from a mode list. If any of the modes have a 392 + * status other than %MODE_OK, they are removed from @mode_list and freed. 393 + */ 394 + void drm_mode_prune_invalid(struct drm_device *dev, 395 + struct list_head *mode_list, bool verbose) 396 + { 397 + struct drm_display_mode *mode, *t; 398 + 399 + list_for_each_entry_safe(mode, t, mode_list, head) { 400 + if (mode->status != MODE_OK) { 401 + list_del(&mode->head); 402 + if (verbose) { 403 + drm_mode_debug_printmodeline(mode); 404 + DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status); 405 + } 406 + drm_mode_destroy(dev, mode); 407 + } 408 + } 409 + } 410 + EXPORT_SYMBOL(drm_mode_prune_invalid); 411 + 412 + /** 413 + * drm_mode_compare - compare modes for favorability 414 + * @lh_a: list_head for first mode 415 + * @lh_b: list_head for second mode 416 + * 417 + * LOCKING: 418 + * None. 419 + * 420 + * Compare two modes, given by @lh_a and @lh_b, returning a value indicating 421 + * which is better. 422 + * 423 + * RETURNS: 424 + * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or 425 + * positive if @lh_b is better than @lh_a. 426 + */ 427 + static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b) 428 + { 429 + struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head); 430 + struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head); 431 + int diff; 432 + 433 + diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) - 434 + ((a->type & DRM_MODE_TYPE_PREFERRED) != 0); 435 + if (diff) 436 + return diff; 437 + diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay; 438 + if (diff) 439 + return diff; 440 + diff = b->clock - a->clock; 441 + return diff; 442 + } 443 + 444 + /* FIXME: what we don't have a list sort function? */ 445 + /* list sort from Mark J Roberts (mjr@znex.org) */ 446 + void list_sort(struct list_head *head, 447 + int (*cmp)(struct list_head *a, struct list_head *b)) 448 + { 449 + struct list_head *p, *q, *e, *list, *tail, *oldhead; 450 + int insize, nmerges, psize, qsize, i; 451 + 452 + list = head->next; 453 + list_del(head); 454 + insize = 1; 455 + for (;;) { 456 + p = oldhead = list; 457 + list = tail = NULL; 458 + nmerges = 0; 459 + 460 + while (p) { 461 + nmerges++; 462 + q = p; 463 + psize = 0; 464 + for (i = 0; i < insize; i++) { 465 + psize++; 466 + q = q->next == oldhead ? NULL : q->next; 467 + if (!q) 468 + break; 469 + } 470 + 471 + qsize = insize; 472 + while (psize > 0 || (qsize > 0 && q)) { 473 + if (!psize) { 474 + e = q; 475 + q = q->next; 476 + qsize--; 477 + if (q == oldhead) 478 + q = NULL; 479 + } else if (!qsize || !q) { 480 + e = p; 481 + p = p->next; 482 + psize--; 483 + if (p == oldhead) 484 + p = NULL; 485 + } else if (cmp(p, q) <= 0) { 486 + e = p; 487 + p = p->next; 488 + psize--; 489 + if (p == oldhead) 490 + p = NULL; 491 + } else { 492 + e = q; 493 + q = q->next; 494 + qsize--; 495 + if (q == oldhead) 496 + q = NULL; 497 + } 498 + if (tail) 499 + tail->next = e; 500 + else 501 + list = e; 502 + e->prev = tail; 503 + tail = e; 504 + } 505 + p = q; 506 + } 507 + 508 + tail->next = list; 509 + list->prev = tail; 510 + 511 + if (nmerges <= 1) 512 + break; 513 + 514 + insize *= 2; 515 + } 516 + 517 + head->next = list; 518 + head->prev = list->prev; 519 + list->prev->next = head; 520 + list->prev = head; 521 + } 522 + 523 + /** 524 + * drm_mode_sort - sort mode list 525 + * @mode_list: list to sort 526 + * 527 + * LOCKING: 528 + * Caller must hold a lock protecting @mode_list. 529 + * 530 + * Sort @mode_list by favorability, putting good modes first. 531 + */ 532 + void drm_mode_sort(struct list_head *mode_list) 533 + { 534 + list_sort(mode_list, drm_mode_compare); 535 + } 536 + EXPORT_SYMBOL(drm_mode_sort); 537 + 538 + /** 539 + * drm_mode_connector_list_update - update the mode list for the connector 540 + * @connector: the connector to update 541 + * 542 + * LOCKING: 543 + * Caller must hold a lock protecting @mode_list. 544 + * 545 + * This moves the modes from the @connector probed_modes list 546 + * to the actual mode list. It compares the probed mode against the current 547 + * list and only adds different modes. All modes unverified after this point 548 + * will be removed by the prune invalid modes. 549 + */ 550 + void drm_mode_connector_list_update(struct drm_connector *connector) 551 + { 552 + struct drm_display_mode *mode; 553 + struct drm_display_mode *pmode, *pt; 554 + int found_it; 555 + 556 + list_for_each_entry_safe(pmode, pt, &connector->probed_modes, 557 + head) { 558 + found_it = 0; 559 + /* go through current modes checking for the new probed mode */ 560 + list_for_each_entry(mode, &connector->modes, head) { 561 + if (drm_mode_equal(pmode, mode)) { 562 + found_it = 1; 563 + /* if equal delete the probed mode */ 564 + mode->status = pmode->status; 565 + list_del(&pmode->head); 566 + drm_mode_destroy(connector->dev, pmode); 567 + break; 568 + } 569 + } 570 + 571 + if (!found_it) { 572 + list_move_tail(&pmode->head, &connector->modes); 573 + } 574 + } 575 + } 576 + EXPORT_SYMBOL(drm_mode_connector_list_update);
+28 -4
drivers/gpu/drm/drm_stub.c
··· 57 57 int ret; 58 58 int base = 0, limit = 63; 59 59 60 + if (type == DRM_MINOR_CONTROL) { 61 + base += 64; 62 + limit = base + 127; 63 + } else if (type == DRM_MINOR_RENDER) { 64 + base += 128; 65 + limit = base + 255; 66 + } 67 + 60 68 again: 61 69 if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { 62 70 DRM_ERROR("Out of memory expanding drawable idr\n"); ··· 370 362 printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); 371 363 goto err_g2; 372 364 } 373 - if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) 374 - goto err_g2; 375 365 376 - if (dev->driver->load) 377 - if ((ret = dev->driver->load(dev, ent->driver_data))) 366 + if (drm_core_check_feature(dev, DRIVER_MODESET)) { 367 + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); 368 + if (ret) 369 + goto err_g2; 370 + } 371 + 372 + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) 373 + goto err_g3; 374 + 375 + if (dev->driver->load) { 376 + ret = dev->driver->load(dev, ent->driver_data); 377 + if (ret) 378 378 goto err_g3; 379 + } 380 + 381 + /* setup the grouping for the legacy output */ 382 + if (drm_core_check_feature(dev, DRIVER_MODESET)) { 383 + ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); 384 + if (ret) 385 + goto err_g3; 386 + } 379 387 380 388 list_add_tail(&dev->driver_item, &driver->device_list); 381 389
+326 -3
drivers/gpu/drm/drm_sysfs.c
··· 20 20 #include "drmP.h" 21 21 22 22 #define to_drm_minor(d) container_of(d, struct drm_minor, kdev) 23 + #define to_drm_connector(d) container_of(d, struct drm_connector, kdev) 23 24 24 25 /** 25 26 * drm_sysfs_suspend - DRM class suspend hook ··· 35 34 struct drm_minor *drm_minor = to_drm_minor(dev); 36 35 struct drm_device *drm_dev = drm_minor->dev; 37 36 38 - if (drm_dev->driver->suspend) 37 + if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->suspend) 39 38 return drm_dev->driver->suspend(drm_dev, state); 40 39 41 40 return 0; ··· 53 52 struct drm_minor *drm_minor = to_drm_minor(dev); 54 53 struct drm_device *drm_dev = drm_minor->dev; 55 54 56 - if (drm_dev->driver->resume) 55 + if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->resume) 57 56 return drm_dev->driver->resume(drm_dev); 58 57 59 58 return 0; ··· 145 144 return; 146 145 } 147 146 147 + /* 148 + * Connector properties 149 + */ 150 + static ssize_t status_show(struct device *device, 151 + struct device_attribute *attr, 152 + char *buf) 153 + { 154 + struct drm_connector *connector = to_drm_connector(device); 155 + enum drm_connector_status status; 156 + 157 + status = connector->funcs->detect(connector); 158 + return snprintf(buf, PAGE_SIZE, "%s", 159 + drm_get_connector_status_name(status)); 160 + } 161 + 162 + static ssize_t dpms_show(struct device *device, 163 + struct device_attribute *attr, 164 + char *buf) 165 + { 166 + struct drm_connector *connector = to_drm_connector(device); 167 + struct drm_device *dev = connector->dev; 168 + uint64_t dpms_status; 169 + int ret; 170 + 171 + ret = drm_connector_property_get_value(connector, 172 + dev->mode_config.dpms_property, 173 + &dpms_status); 174 + if (ret) 175 + return 0; 176 + 177 + return snprintf(buf, PAGE_SIZE, "%s", 178 + drm_get_dpms_name((int)dpms_status)); 179 + } 180 + 181 + static ssize_t enabled_show(struct device *device, 182 + struct device_attribute *attr, 183 + char *buf) 184 + { 185 + struct drm_connector *connector = to_drm_connector(device); 186 + 187 + return snprintf(buf, PAGE_SIZE, connector->encoder ? "enabled" : 188 + "disabled"); 189 + } 190 + 191 + static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *attr, 192 + char *buf, loff_t off, size_t count) 193 + { 194 + struct device *connector_dev = container_of(kobj, struct device, kobj); 195 + struct drm_connector *connector = to_drm_connector(connector_dev); 196 + unsigned char *edid; 197 + size_t size; 198 + 199 + if (!connector->edid_blob_ptr) 200 + return 0; 201 + 202 + edid = connector->edid_blob_ptr->data; 203 + size = connector->edid_blob_ptr->length; 204 + if (!edid) 205 + return 0; 206 + 207 + if (off >= size) 208 + return 0; 209 + 210 + if (off + count > size) 211 + count = size - off; 212 + memcpy(buf, edid + off, count); 213 + 214 + return count; 215 + } 216 + 217 + static ssize_t modes_show(struct device *device, 218 + struct device_attribute *attr, 219 + char *buf) 220 + { 221 + struct drm_connector *connector = to_drm_connector(device); 222 + struct drm_display_mode *mode; 223 + int written = 0; 224 + 225 + list_for_each_entry(mode, &connector->modes, head) { 226 + written += snprintf(buf + written, PAGE_SIZE - written, "%s\n", 227 + mode->name); 228 + } 229 + 230 + return written; 231 + } 232 + 233 + static ssize_t subconnector_show(struct device *device, 234 + struct device_attribute *attr, 235 + char *buf) 236 + { 237 + struct drm_connector *connector = to_drm_connector(device); 238 + struct drm_device *dev = connector->dev; 239 + struct drm_property *prop = NULL; 240 + uint64_t subconnector; 241 + int is_tv = 0; 242 + int ret; 243 + 244 + switch (connector->connector_type) { 245 + case DRM_MODE_CONNECTOR_DVII: 246 + prop = dev->mode_config.dvi_i_subconnector_property; 247 + break; 248 + case DRM_MODE_CONNECTOR_Composite: 249 + case DRM_MODE_CONNECTOR_SVIDEO: 250 + case DRM_MODE_CONNECTOR_Component: 251 + prop = dev->mode_config.tv_subconnector_property; 252 + is_tv = 1; 253 + break; 254 + default: 255 + DRM_ERROR("Wrong connector type for this property\n"); 256 + return 0; 257 + } 258 + 259 + if (!prop) { 260 + DRM_ERROR("Unable to find subconnector property\n"); 261 + return 0; 262 + } 263 + 264 + ret = drm_connector_property_get_value(connector, prop, &subconnector); 265 + if (ret) 266 + return 0; 267 + 268 + return snprintf(buf, PAGE_SIZE, "%s", is_tv ? 269 + drm_get_tv_subconnector_name((int)subconnector) : 270 + drm_get_dvi_i_subconnector_name((int)subconnector)); 271 + } 272 + 273 + static ssize_t select_subconnector_show(struct device *device, 274 + struct device_attribute *attr, 275 + char *buf) 276 + { 277 + struct drm_connector *connector = to_drm_connector(device); 278 + struct drm_device *dev = connector->dev; 279 + struct drm_property *prop = NULL; 280 + uint64_t subconnector; 281 + int is_tv = 0; 282 + int ret; 283 + 284 + switch (connector->connector_type) { 285 + case DRM_MODE_CONNECTOR_DVII: 286 + prop = dev->mode_config.dvi_i_select_subconnector_property; 287 + break; 288 + case DRM_MODE_CONNECTOR_Composite: 289 + case DRM_MODE_CONNECTOR_SVIDEO: 290 + case DRM_MODE_CONNECTOR_Component: 291 + prop = dev->mode_config.tv_select_subconnector_property; 292 + is_tv = 1; 293 + break; 294 + default: 295 + DRM_ERROR("Wrong connector type for this property\n"); 296 + return 0; 297 + } 298 + 299 + if (!prop) { 300 + DRM_ERROR("Unable to find select subconnector property\n"); 301 + return 0; 302 + } 303 + 304 + ret = drm_connector_property_get_value(connector, prop, &subconnector); 305 + if (ret) 306 + return 0; 307 + 308 + return snprintf(buf, PAGE_SIZE, "%s", is_tv ? 309 + drm_get_tv_select_name((int)subconnector) : 310 + drm_get_dvi_i_select_name((int)subconnector)); 311 + } 312 + 313 + static struct device_attribute connector_attrs[] = { 314 + __ATTR_RO(status), 315 + __ATTR_RO(enabled), 316 + __ATTR_RO(dpms), 317 + __ATTR_RO(modes), 318 + }; 319 + 320 + /* These attributes are for both DVI-I connectors and all types of tv-out. */ 321 + static struct device_attribute connector_attrs_opt1[] = { 322 + __ATTR_RO(subconnector), 323 + __ATTR_RO(select_subconnector), 324 + }; 325 + 326 + static struct bin_attribute edid_attr = { 327 + .attr.name = "edid", 328 + .size = 128, 329 + .read = edid_show, 330 + }; 331 + 332 + /** 333 + * drm_sysfs_connector_add - add an connector to sysfs 334 + * @connector: connector to add 335 + * 336 + * Create an connector device in sysfs, along with its associated connector 337 + * properties (so far, connection status, dpms, mode list & edid) and 338 + * generate a hotplug event so userspace knows there's a new connector 339 + * available. 340 + * 341 + * Note: 342 + * This routine should only be called *once* for each DRM minor registered. 343 + * A second call for an already registered device will trigger the BUG_ON 344 + * below. 345 + */ 346 + int drm_sysfs_connector_add(struct drm_connector *connector) 347 + { 348 + struct drm_device *dev = connector->dev; 349 + int ret = 0, i, j; 350 + 351 + /* We shouldn't get called more than once for the same connector */ 352 + BUG_ON(device_is_registered(&connector->kdev)); 353 + 354 + connector->kdev.parent = &dev->primary->kdev; 355 + connector->kdev.class = drm_class; 356 + connector->kdev.release = drm_sysfs_device_release; 357 + 358 + DRM_DEBUG("adding \"%s\" to sysfs\n", 359 + drm_get_connector_name(connector)); 360 + 361 + snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s", 362 + dev->primary->index, drm_get_connector_name(connector)); 363 + ret = device_register(&connector->kdev); 364 + 365 + if (ret) { 366 + DRM_ERROR("failed to register connector device: %d\n", ret); 367 + goto out; 368 + } 369 + 370 + /* Standard attributes */ 371 + 372 + for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) { 373 + ret = device_create_file(&connector->kdev, &connector_attrs[i]); 374 + if (ret) 375 + goto err_out_files; 376 + } 377 + 378 + /* Optional attributes */ 379 + /* 380 + * In the long run it maybe a good idea to make one set of 381 + * optionals per connector type. 382 + */ 383 + switch (connector->connector_type) { 384 + case DRM_MODE_CONNECTOR_DVII: 385 + case DRM_MODE_CONNECTOR_Composite: 386 + case DRM_MODE_CONNECTOR_SVIDEO: 387 + case DRM_MODE_CONNECTOR_Component: 388 + for (i = 0; i < ARRAY_SIZE(connector_attrs_opt1); i++) { 389 + ret = device_create_file(&connector->kdev, &connector_attrs_opt1[i]); 390 + if (ret) 391 + goto err_out_files; 392 + } 393 + break; 394 + default: 395 + break; 396 + } 397 + 398 + ret = sysfs_create_bin_file(&connector->kdev.kobj, &edid_attr); 399 + if (ret) 400 + goto err_out_files; 401 + 402 + /* Let userspace know we have a new connector */ 403 + drm_sysfs_hotplug_event(dev); 404 + 405 + return 0; 406 + 407 + err_out_files: 408 + if (i > 0) 409 + for (j = 0; j < i; j++) 410 + device_remove_file(&connector->kdev, 411 + &connector_attrs[i]); 412 + device_unregister(&connector->kdev); 413 + 414 + out: 415 + return ret; 416 + } 417 + EXPORT_SYMBOL(drm_sysfs_connector_add); 418 + 419 + /** 420 + * drm_sysfs_connector_remove - remove an connector device from sysfs 421 + * @connector: connector to remove 422 + * 423 + * Remove @connector and its associated attributes from sysfs. Note that 424 + * the device model core will take care of sending the "remove" uevent 425 + * at this time, so we don't need to do it. 426 + * 427 + * Note: 428 + * This routine should only be called if the connector was previously 429 + * successfully registered. If @connector hasn't been registered yet, 430 + * you'll likely see a panic somewhere deep in sysfs code when called. 431 + */ 432 + void drm_sysfs_connector_remove(struct drm_connector *connector) 433 + { 434 + int i; 435 + 436 + DRM_DEBUG("removing \"%s\" from sysfs\n", 437 + drm_get_connector_name(connector)); 438 + 439 + for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) 440 + device_remove_file(&connector->kdev, &connector_attrs[i]); 441 + sysfs_remove_bin_file(&connector->kdev.kobj, &edid_attr); 442 + device_unregister(&connector->kdev); 443 + } 444 + EXPORT_SYMBOL(drm_sysfs_connector_remove); 445 + 446 + /** 447 + * drm_sysfs_hotplug_event - generate a DRM uevent 448 + * @dev: DRM device 449 + * 450 + * Send a uevent for the DRM device specified by @dev. Currently we only 451 + * set HOTPLUG=1 in the uevent environment, but this could be expanded to 452 + * deal with other types of events. 453 + */ 454 + void drm_sysfs_hotplug_event(struct drm_device *dev) 455 + { 456 + char *event_string = "HOTPLUG=1"; 457 + char *envp[] = { event_string, NULL }; 458 + 459 + DRM_DEBUG("generating hotplug event\n"); 460 + 461 + kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp); 462 + } 463 + 148 464 /** 149 465 * drm_sysfs_device_add - adds a class device to sysfs for a character driver 150 466 * @dev: DRM device to be added ··· 481 163 minor->kdev.class = drm_class; 482 164 minor->kdev.release = drm_sysfs_device_release; 483 165 minor->kdev.devt = minor->device; 484 - minor_str = "card%d"; 166 + if (minor->type == DRM_MINOR_CONTROL) 167 + minor_str = "controlD%d"; 168 + else if (minor->type == DRM_MINOR_RENDER) 169 + minor_str = "renderD%d"; 170 + else 171 + minor_str = "card%d"; 485 172 486 173 snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); 487 174
+17
drivers/video/console/vgacon.c
··· 112 112 static int vga_scan_lines __read_mostly; 113 113 static unsigned int vga_rolled_over; 114 114 115 + int vgacon_text_mode_force = 0; 116 + 117 + bool vgacon_text_force(void) 118 + { 119 + return vgacon_text_mode_force ? true : false; 120 + } 121 + EXPORT_SYMBOL(vgacon_text_force); 122 + 123 + static int __init text_mode(char *str) 124 + { 125 + vgacon_text_mode_force = 1; 126 + return 1; 127 + } 128 + 129 + /* force text mode - used by kernel modesetting */ 130 + __setup("nomodeset", text_mode); 131 + 115 132 static int __init no_scroll(char *str) 116 133 { 117 134 /*
+1 -1
include/drm/Kbuild
··· 1 - unifdef-y += drm.h drm_sarea.h 1 + unifdef-y += drm.h drm_sarea.h drm_mode.h 2 2 unifdef-y += i810_drm.h 3 3 unifdef-y += i830_drm.h 4 4 unifdef-y += i915_drm.h
+21
include/drm/drm.h
··· 599 599 uint64_t size; 600 600 }; 601 601 602 + #include "drm_mode.h" 603 + 602 604 #define DRM_IOCTL_BASE 'd' 603 605 #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) 604 606 #define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) ··· 669 667 #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) 670 668 671 669 #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) 670 + 671 + #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) 672 + #define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) 673 + #define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) 674 + #define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) 675 + #define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) 676 + #define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) 677 + #define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) 678 + #define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) 679 + #define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) 680 + #define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) 681 + 682 + #define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) 683 + #define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) 684 + #define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) 685 + #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) 686 + #define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) 687 + #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) 688 + #define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xB0, struct drm_mode_fb_cmd) 672 689 673 690 /** 674 691 * Device specific ioctls should only be in their respective headers
+18
include/drm/drmP.h
··· 105 105 #define DRIVER_FB_DMA 0x400 106 106 #define DRIVER_IRQ_VBL2 0x800 107 107 #define DRIVER_GEM 0x1000 108 + #define DRIVER_MODESET 0x2000 108 109 109 110 /***********************************************************************/ 110 111 /** \name Begin the DRM... */ ··· 277 276 #define DRM_AUTH 0x1 278 277 #define DRM_MASTER 0x2 279 278 #define DRM_ROOT_ONLY 0x4 279 + #define DRM_CONTROL_ALLOW 0x8 280 280 281 281 struct drm_ioctl_desc { 282 282 unsigned int cmd; ··· 400 398 int is_master; /* this file private is a master for a minor */ 401 399 struct drm_master *master; /* master this node is currently associated with 402 400 N.B. not always minor->master */ 401 + struct list_head fbs; 403 402 }; 404 403 405 404 /** Wait queue */ ··· 632 629 void *driver_private; 633 630 }; 634 631 632 + #include "drm_crtc.h" 633 + 635 634 /* per-master structure */ 636 635 struct drm_master { 637 636 ··· 797 792 798 793 #define DRM_MINOR_UNASSIGNED 0 799 794 #define DRM_MINOR_LEGACY 1 795 + #define DRM_MINOR_CONTROL 2 796 + #define DRM_MINOR_RENDER 3 800 797 801 798 /** 802 799 * DRM minor structure. This structure represents a drm minor number. ··· 812 805 struct proc_dir_entry *dev_root; /**< proc directory entry */ 813 806 struct drm_master *master; /* currently active master for this node */ 814 807 struct list_head master_list; 808 + struct drm_mode_group mode_group; 815 809 }; 816 810 817 811 /** ··· 863 855 struct idr ctx_idr; 864 856 865 857 struct list_head vmalist; /**< List of vmas (for debugging) */ 858 + 866 859 /*@} */ 867 860 868 861 /** \name DMA queues (contexts) */ ··· 942 933 struct drm_driver *driver; 943 934 drm_local_map_t *agp_buffer_map; 944 935 unsigned int agp_buffer_token; 936 + struct drm_minor *control; /**< Control node for card */ 945 937 struct drm_minor *primary; /**< render type primary screen head */ 946 938 947 939 /** \name Drawable information */ ··· 950 940 spinlock_t drw_lock; 951 941 struct idr drw_idr; 952 942 /*@} */ 943 + 944 + struct drm_mode_config mode_config; /**< Current mode config */ 953 945 954 946 /** \name GEM information */ 955 947 /*@{ */ ··· 1213 1201 extern void drm_vblank_put(struct drm_device *dev, int crtc); 1214 1202 extern void drm_vblank_cleanup(struct drm_device *dev); 1215 1203 /* Modesetting support */ 1204 + extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); 1205 + extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); 1216 1206 extern int drm_modeset_ctl(struct drm_device *dev, void *data, 1217 1207 struct drm_file *file_priv); 1218 1208 ··· 1300 1286 extern struct class *drm_sysfs_create(struct module *owner, char *name); 1301 1287 extern void drm_sysfs_destroy(void); 1302 1288 extern int drm_sysfs_device_add(struct drm_minor *minor); 1289 + extern void drm_sysfs_hotplug_event(struct drm_device *dev); 1303 1290 extern void drm_sysfs_device_remove(struct drm_minor *minor); 1291 + extern char *drm_get_connector_status_name(enum drm_connector_status status); 1292 + extern int drm_sysfs_connector_add(struct drm_connector *connector); 1293 + extern void drm_sysfs_connector_remove(struct drm_connector *connector); 1304 1294 1305 1295 /* 1306 1296 * Basic memory manager support (drm_mm.c)
+737
include/drm/drm_crtc.h
··· 1 + /* 2 + * Copyright © 2006 Keith Packard 3 + * Copyright © 2007-2008 Dave Airlie 4 + * Copyright © 2007-2008 Intel Corporation 5 + * Jesse Barnes <jesse.barnes@intel.com> 6 + * 7 + * Permission is hereby granted, free of charge, to any person obtaining a 8 + * copy of this software and associated documentation files (the "Software"), 9 + * to deal in the Software without restriction, including without limitation 10 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 + * and/or sell copies of the Software, and to permit persons to whom the 12 + * Software is furnished to do so, subject to the following conditions: 13 + * 14 + * The above copyright notice and this permission notice shall be included in 15 + * all copies or substantial portions of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 + * OTHER DEALINGS IN THE SOFTWARE. 24 + */ 25 + #ifndef __DRM_CRTC_H__ 26 + #define __DRM_CRTC_H__ 27 + 28 + #include <linux/i2c.h> 29 + #include <linux/spinlock.h> 30 + #include <linux/types.h> 31 + #include <linux/idr.h> 32 + 33 + #include <linux/fb.h> 34 + 35 + struct drm_device; 36 + struct drm_mode_set; 37 + struct drm_framebuffer; 38 + 39 + 40 + #define DRM_MODE_OBJECT_CRTC 0xcccccccc 41 + #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 42 + #define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 43 + #define DRM_MODE_OBJECT_MODE 0xdededede 44 + #define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 45 + #define DRM_MODE_OBJECT_FB 0xfbfbfbfb 46 + #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb 47 + 48 + struct drm_mode_object { 49 + uint32_t id; 50 + uint32_t type; 51 + }; 52 + 53 + /* 54 + * Note on terminology: here, for brevity and convenience, we refer to connector 55 + * control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS, 56 + * DVI, etc. And 'screen' refers to the whole of the visible display, which 57 + * may span multiple monitors (and therefore multiple CRTC and connector 58 + * structures). 59 + */ 60 + 61 + enum drm_mode_status { 62 + MODE_OK = 0, /* Mode OK */ 63 + MODE_HSYNC, /* hsync out of range */ 64 + MODE_VSYNC, /* vsync out of range */ 65 + MODE_H_ILLEGAL, /* mode has illegal horizontal timings */ 66 + MODE_V_ILLEGAL, /* mode has illegal horizontal timings */ 67 + MODE_BAD_WIDTH, /* requires an unsupported linepitch */ 68 + MODE_NOMODE, /* no mode with a maching name */ 69 + MODE_NO_INTERLACE, /* interlaced mode not supported */ 70 + MODE_NO_DBLESCAN, /* doublescan mode not supported */ 71 + MODE_NO_VSCAN, /* multiscan mode not supported */ 72 + MODE_MEM, /* insufficient video memory */ 73 + MODE_VIRTUAL_X, /* mode width too large for specified virtual size */ 74 + MODE_VIRTUAL_Y, /* mode height too large for specified virtual size */ 75 + MODE_MEM_VIRT, /* insufficient video memory given virtual size */ 76 + MODE_NOCLOCK, /* no fixed clock available */ 77 + MODE_CLOCK_HIGH, /* clock required is too high */ 78 + MODE_CLOCK_LOW, /* clock required is too low */ 79 + MODE_CLOCK_RANGE, /* clock/mode isn't in a ClockRange */ 80 + MODE_BAD_HVALUE, /* horizontal timing was out of range */ 81 + MODE_BAD_VVALUE, /* vertical timing was out of range */ 82 + MODE_BAD_VSCAN, /* VScan value out of range */ 83 + MODE_HSYNC_NARROW, /* horizontal sync too narrow */ 84 + MODE_HSYNC_WIDE, /* horizontal sync too wide */ 85 + MODE_HBLANK_NARROW, /* horizontal blanking too narrow */ 86 + MODE_HBLANK_WIDE, /* horizontal blanking too wide */ 87 + MODE_VSYNC_NARROW, /* vertical sync too narrow */ 88 + MODE_VSYNC_WIDE, /* vertical sync too wide */ 89 + MODE_VBLANK_NARROW, /* vertical blanking too narrow */ 90 + MODE_VBLANK_WIDE, /* vertical blanking too wide */ 91 + MODE_PANEL, /* exceeds panel dimensions */ 92 + MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */ 93 + MODE_ONE_WIDTH, /* only one width is supported */ 94 + MODE_ONE_HEIGHT, /* only one height is supported */ 95 + MODE_ONE_SIZE, /* only one resolution is supported */ 96 + MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */ 97 + MODE_UNVERIFIED = -3, /* mode needs to reverified */ 98 + MODE_BAD = -2, /* unspecified reason */ 99 + MODE_ERROR = -1 /* error condition */ 100 + }; 101 + 102 + #define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \ 103 + DRM_MODE_TYPE_CRTC_C) 104 + 105 + #define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ 106 + .name = nm, .status = 0, .type = (t), .clock = (c), \ 107 + .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ 108 + .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ 109 + .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ 110 + .vscan = (vs), .flags = (f), .vrefresh = 0 111 + 112 + #define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */ 113 + 114 + struct drm_display_mode { 115 + /* Header */ 116 + struct list_head head; 117 + struct drm_mode_object base; 118 + 119 + char name[DRM_DISPLAY_MODE_LEN]; 120 + 121 + int connector_count; 122 + enum drm_mode_status status; 123 + int type; 124 + 125 + /* Proposed mode values */ 126 + int clock; 127 + int hdisplay; 128 + int hsync_start; 129 + int hsync_end; 130 + int htotal; 131 + int hskew; 132 + int vdisplay; 133 + int vsync_start; 134 + int vsync_end; 135 + int vtotal; 136 + int vscan; 137 + unsigned int flags; 138 + 139 + /* Addressable image size (may be 0 for projectors, etc.) */ 140 + int width_mm; 141 + int height_mm; 142 + 143 + /* Actual mode we give to hw */ 144 + int clock_index; 145 + int synth_clock; 146 + int crtc_hdisplay; 147 + int crtc_hblank_start; 148 + int crtc_hblank_end; 149 + int crtc_hsync_start; 150 + int crtc_hsync_end; 151 + int crtc_htotal; 152 + int crtc_hskew; 153 + int crtc_vdisplay; 154 + int crtc_vblank_start; 155 + int crtc_vblank_end; 156 + int crtc_vsync_start; 157 + int crtc_vsync_end; 158 + int crtc_vtotal; 159 + int crtc_hadjusted; 160 + int crtc_vadjusted; 161 + 162 + /* Driver private mode info */ 163 + int private_size; 164 + int *private; 165 + int private_flags; 166 + 167 + int vrefresh; 168 + float hsync; 169 + }; 170 + 171 + enum drm_connector_status { 172 + connector_status_connected = 1, 173 + connector_status_disconnected = 2, 174 + connector_status_unknown = 3, 175 + }; 176 + 177 + enum subpixel_order { 178 + SubPixelUnknown = 0, 179 + SubPixelHorizontalRGB, 180 + SubPixelHorizontalBGR, 181 + SubPixelVerticalRGB, 182 + SubPixelVerticalBGR, 183 + SubPixelNone, 184 + }; 185 + 186 + 187 + /* 188 + * Describes a given display (e.g. CRT or flat panel) and its limitations. 189 + */ 190 + struct drm_display_info { 191 + char name[DRM_DISPLAY_INFO_LEN]; 192 + /* Input info */ 193 + bool serration_vsync; 194 + bool sync_on_green; 195 + bool composite_sync; 196 + bool separate_syncs; 197 + bool blank_to_black; 198 + unsigned char video_level; 199 + bool digital; 200 + /* Physical size */ 201 + unsigned int width_mm; 202 + unsigned int height_mm; 203 + 204 + /* Display parameters */ 205 + unsigned char gamma; /* FIXME: storage format */ 206 + bool gtf_supported; 207 + bool standard_color; 208 + enum { 209 + monochrome = 0, 210 + rgb, 211 + other, 212 + unknown, 213 + } display_type; 214 + bool active_off_supported; 215 + bool suspend_supported; 216 + bool standby_supported; 217 + 218 + /* Color info FIXME: storage format */ 219 + unsigned short redx, redy; 220 + unsigned short greenx, greeny; 221 + unsigned short bluex, bluey; 222 + unsigned short whitex, whitey; 223 + 224 + /* Clock limits FIXME: storage format */ 225 + unsigned int min_vfreq, max_vfreq; 226 + unsigned int min_hfreq, max_hfreq; 227 + unsigned int pixel_clock; 228 + 229 + /* White point indices FIXME: storage format */ 230 + unsigned int wpx1, wpy1; 231 + unsigned int wpgamma1; 232 + unsigned int wpx2, wpy2; 233 + unsigned int wpgamma2; 234 + 235 + enum subpixel_order subpixel_order; 236 + 237 + char *raw_edid; /* if any */ 238 + }; 239 + 240 + struct drm_framebuffer_funcs { 241 + void (*destroy)(struct drm_framebuffer *framebuffer); 242 + int (*create_handle)(struct drm_framebuffer *fb, 243 + struct drm_file *file_priv, 244 + unsigned int *handle); 245 + }; 246 + 247 + struct drm_framebuffer { 248 + struct drm_device *dev; 249 + struct list_head head; 250 + struct drm_mode_object base; 251 + const struct drm_framebuffer_funcs *funcs; 252 + unsigned int pitch; 253 + unsigned int width; 254 + unsigned int height; 255 + /* depth can be 15 or 16 */ 256 + unsigned int depth; 257 + int bits_per_pixel; 258 + int flags; 259 + void *fbdev; 260 + u32 pseudo_palette[17]; 261 + struct list_head filp_head; 262 + }; 263 + 264 + struct drm_property_blob { 265 + struct drm_mode_object base; 266 + struct list_head head; 267 + unsigned int length; 268 + void *data; 269 + }; 270 + 271 + struct drm_property_enum { 272 + uint64_t value; 273 + struct list_head head; 274 + char name[DRM_PROP_NAME_LEN]; 275 + }; 276 + 277 + struct drm_property { 278 + struct list_head head; 279 + struct drm_mode_object base; 280 + uint32_t flags; 281 + char name[DRM_PROP_NAME_LEN]; 282 + uint32_t num_values; 283 + uint64_t *values; 284 + 285 + struct list_head enum_blob_list; 286 + }; 287 + 288 + struct drm_crtc; 289 + struct drm_connector; 290 + struct drm_encoder; 291 + 292 + /** 293 + * drm_crtc_funcs - control CRTCs for a given device 294 + * @dpms: control display power levels 295 + * @save: save CRTC state 296 + * @resore: restore CRTC state 297 + * @lock: lock the CRTC 298 + * @unlock: unlock the CRTC 299 + * @shadow_allocate: allocate shadow pixmap 300 + * @shadow_create: create shadow pixmap for rotation support 301 + * @shadow_destroy: free shadow pixmap 302 + * @mode_fixup: fixup proposed mode 303 + * @mode_set: set the desired mode on the CRTC 304 + * @gamma_set: specify color ramp for CRTC 305 + * @destroy: deinit and free object. 306 + * 307 + * The drm_crtc_funcs structure is the central CRTC management structure 308 + * in the DRM. Each CRTC controls one or more connectors (note that the name 309 + * CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc. 310 + * connectors, not just CRTs). 311 + * 312 + * Each driver is responsible for filling out this structure at startup time, 313 + * in addition to providing other modesetting features, like i2c and DDC 314 + * bus accessors. 315 + */ 316 + struct drm_crtc_funcs { 317 + /* Save CRTC state */ 318 + void (*save)(struct drm_crtc *crtc); /* suspend? */ 319 + /* Restore CRTC state */ 320 + void (*restore)(struct drm_crtc *crtc); /* resume? */ 321 + 322 + /* cursor controls */ 323 + int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv, 324 + uint32_t handle, uint32_t width, uint32_t height); 325 + int (*cursor_move)(struct drm_crtc *crtc, int x, int y); 326 + 327 + /* Set gamma on the CRTC */ 328 + void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, 329 + uint32_t size); 330 + /* Object destroy routine */ 331 + void (*destroy)(struct drm_crtc *crtc); 332 + 333 + int (*set_config)(struct drm_mode_set *set); 334 + }; 335 + 336 + /** 337 + * drm_crtc - central CRTC control structure 338 + * @enabled: is this CRTC enabled? 339 + * @x: x position on screen 340 + * @y: y position on screen 341 + * @desired_mode: new desired mode 342 + * @desired_x: desired x for desired_mode 343 + * @desired_y: desired y for desired_mode 344 + * @funcs: CRTC control functions 345 + * 346 + * Each CRTC may have one or more connectors associated with it. This structure 347 + * allows the CRTC to be controlled. 348 + */ 349 + struct drm_crtc { 350 + struct drm_device *dev; 351 + struct list_head head; 352 + 353 + struct drm_mode_object base; 354 + 355 + /* framebuffer the connector is currently bound to */ 356 + struct drm_framebuffer *fb; 357 + 358 + bool enabled; 359 + 360 + struct drm_display_mode mode; 361 + 362 + int x, y; 363 + struct drm_display_mode *desired_mode; 364 + int desired_x, desired_y; 365 + const struct drm_crtc_funcs *funcs; 366 + 367 + /* CRTC gamma size for reporting to userspace */ 368 + uint32_t gamma_size; 369 + uint16_t *gamma_store; 370 + 371 + /* if you are using the helper */ 372 + void *helper_private; 373 + }; 374 + 375 + 376 + /** 377 + * drm_connector_funcs - control connectors on a given device 378 + * @dpms: set power state (see drm_crtc_funcs above) 379 + * @save: save connector state 380 + * @restore: restore connector state 381 + * @mode_valid: is this mode valid on the given connector? 382 + * @mode_fixup: try to fixup proposed mode for this connector 383 + * @mode_set: set this mode 384 + * @detect: is this connector active? 385 + * @get_modes: get mode list for this connector 386 + * @set_property: property for this connector may need update 387 + * @destroy: make object go away 388 + * 389 + * Each CRTC may have one or more connectors attached to it. The functions 390 + * below allow the core DRM code to control connectors, enumerate available modes, 391 + * etc. 392 + */ 393 + struct drm_connector_funcs { 394 + void (*dpms)(struct drm_connector *connector, int mode); 395 + void (*save)(struct drm_connector *connector); 396 + void (*restore)(struct drm_connector *connector); 397 + enum drm_connector_status (*detect)(struct drm_connector *connector); 398 + void (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); 399 + int (*set_property)(struct drm_connector *connector, struct drm_property *property, 400 + uint64_t val); 401 + void (*destroy)(struct drm_connector *connector); 402 + }; 403 + 404 + struct drm_encoder_funcs { 405 + void (*destroy)(struct drm_encoder *encoder); 406 + }; 407 + 408 + #define DRM_CONNECTOR_MAX_UMODES 16 409 + #define DRM_CONNECTOR_MAX_PROPERTY 16 410 + #define DRM_CONNECTOR_LEN 32 411 + #define DRM_CONNECTOR_MAX_ENCODER 2 412 + 413 + /** 414 + * drm_encoder - central DRM encoder structure 415 + */ 416 + struct drm_encoder { 417 + struct drm_device *dev; 418 + struct list_head head; 419 + 420 + struct drm_mode_object base; 421 + int encoder_type; 422 + uint32_t possible_crtcs; 423 + uint32_t possible_clones; 424 + 425 + struct drm_crtc *crtc; 426 + const struct drm_encoder_funcs *funcs; 427 + void *helper_private; 428 + }; 429 + 430 + /** 431 + * drm_connector - central DRM connector control structure 432 + * @crtc: CRTC this connector is currently connected to, NULL if none 433 + * @interlace_allowed: can this connector handle interlaced modes? 434 + * @doublescan_allowed: can this connector handle doublescan? 435 + * @available_modes: modes available on this connector (from get_modes() + user) 436 + * @initial_x: initial x position for this connector 437 + * @initial_y: initial y position for this connector 438 + * @status: connector connected? 439 + * @funcs: connector control functions 440 + * 441 + * Each connector may be connected to one or more CRTCs, or may be clonable by 442 + * another connector if they can share a CRTC. Each connector also has a specific 443 + * position in the broader display (referred to as a 'screen' though it could 444 + * span multiple monitors). 445 + */ 446 + struct drm_connector { 447 + struct drm_device *dev; 448 + struct device kdev; 449 + struct device_attribute *attr; 450 + struct list_head head; 451 + 452 + struct drm_mode_object base; 453 + 454 + int connector_type; 455 + int connector_type_id; 456 + bool interlace_allowed; 457 + bool doublescan_allowed; 458 + struct list_head modes; /* list of modes on this connector */ 459 + 460 + int initial_x, initial_y; 461 + enum drm_connector_status status; 462 + 463 + /* these are modes added by probing with DDC or the BIOS */ 464 + struct list_head probed_modes; 465 + 466 + struct drm_display_info display_info; 467 + const struct drm_connector_funcs *funcs; 468 + 469 + struct list_head user_modes; 470 + struct drm_property_blob *edid_blob_ptr; 471 + u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY]; 472 + uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY]; 473 + 474 + void *helper_private; 475 + 476 + uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; 477 + uint32_t force_encoder_id; 478 + struct drm_encoder *encoder; /* currently active encoder */ 479 + }; 480 + 481 + /** 482 + * struct drm_mode_set 483 + * 484 + * Represents a single crtc the connectors that it drives with what mode 485 + * and from which framebuffer it scans out from. 486 + * 487 + * This is used to set modes. 488 + */ 489 + struct drm_mode_set { 490 + struct list_head head; 491 + 492 + struct drm_framebuffer *fb; 493 + struct drm_crtc *crtc; 494 + struct drm_display_mode *mode; 495 + 496 + uint32_t x; 497 + uint32_t y; 498 + 499 + struct drm_connector **connectors; 500 + size_t num_connectors; 501 + }; 502 + 503 + /** 504 + * struct drm_mode_config_funcs - configure CRTCs for a given screen layout 505 + * @resize: adjust CRTCs as necessary for the proposed layout 506 + * 507 + * Currently only a resize hook is available. DRM will call back into the 508 + * driver with a new screen width and height. If the driver can't support 509 + * the proposed size, it can return false. Otherwise it should adjust 510 + * the CRTC<->connector mappings as needed and update its view of the screen. 511 + */ 512 + struct drm_mode_config_funcs { 513 + int (*resize_fb)(struct drm_device *dev, struct drm_file *file_priv, struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd); 514 + struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); 515 + int (*fb_changed)(struct drm_device *dev); 516 + }; 517 + 518 + struct drm_mode_group { 519 + uint32_t num_crtcs; 520 + uint32_t num_encoders; 521 + uint32_t num_connectors; 522 + 523 + /* list of object IDs for this group */ 524 + uint32_t *id_list; 525 + }; 526 + 527 + /** 528 + * drm_mode_config - Mode configuration control structure 529 + * 530 + */ 531 + struct drm_mode_config { 532 + struct mutex mutex; /* protects configuration and IDR */ 533 + struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ 534 + /* this is limited to one for now */ 535 + int num_fb; 536 + struct list_head fb_list; 537 + int num_connector; 538 + struct list_head connector_list; 539 + int num_encoder; 540 + struct list_head encoder_list; 541 + 542 + int num_crtc; 543 + struct list_head crtc_list; 544 + 545 + struct list_head property_list; 546 + 547 + /* in-kernel framebuffers - hung of filp_head in drm_framebuffer */ 548 + struct list_head fb_kernel_list; 549 + 550 + int min_width, min_height; 551 + int max_width, max_height; 552 + struct drm_mode_config_funcs *funcs; 553 + unsigned long fb_base; 554 + 555 + /* pointers to standard properties */ 556 + struct list_head property_blob_list; 557 + struct drm_property *edid_property; 558 + struct drm_property *dpms_property; 559 + 560 + /* DVI-I properties */ 561 + struct drm_property *dvi_i_subconnector_property; 562 + struct drm_property *dvi_i_select_subconnector_property; 563 + 564 + /* TV properties */ 565 + struct drm_property *tv_subconnector_property; 566 + struct drm_property *tv_select_subconnector_property; 567 + struct drm_property *tv_mode_property; 568 + struct drm_property *tv_left_margin_property; 569 + struct drm_property *tv_right_margin_property; 570 + struct drm_property *tv_top_margin_property; 571 + struct drm_property *tv_bottom_margin_property; 572 + 573 + /* Optional properties */ 574 + struct drm_property *scaling_mode_property; 575 + struct drm_property *dithering_mode_property; 576 + 577 + /* hotplug */ 578 + uint32_t hotplug_counter; 579 + }; 580 + 581 + #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) 582 + #define obj_to_connector(x) container_of(x, struct drm_connector, base) 583 + #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) 584 + #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) 585 + #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) 586 + #define obj_to_property(x) container_of(x, struct drm_property, base) 587 + #define obj_to_blob(x) container_of(x, struct drm_property_blob, base) 588 + 589 + 590 + extern void drm_crtc_init(struct drm_device *dev, 591 + struct drm_crtc *crtc, 592 + const struct drm_crtc_funcs *funcs); 593 + extern void drm_crtc_cleanup(struct drm_crtc *crtc); 594 + 595 + extern void drm_connector_init(struct drm_device *dev, 596 + struct drm_connector *connector, 597 + const struct drm_connector_funcs *funcs, 598 + int connector_type); 599 + 600 + extern void drm_connector_cleanup(struct drm_connector *connector); 601 + 602 + extern void drm_encoder_init(struct drm_device *dev, 603 + struct drm_encoder *encoder, 604 + const struct drm_encoder_funcs *funcs, 605 + int encoder_type); 606 + 607 + extern void drm_encoder_cleanup(struct drm_encoder *encoder); 608 + 609 + extern char *drm_get_connector_name(struct drm_connector *connector); 610 + extern char *drm_get_dpms_name(int val); 611 + extern char *drm_get_dvi_i_subconnector_name(int val); 612 + extern char *drm_get_dvi_i_select_name(int val); 613 + extern char *drm_get_tv_subconnector_name(int val); 614 + extern char *drm_get_tv_select_name(int val); 615 + extern void drm_fb_release(struct file *filp); 616 + extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); 617 + extern struct edid *drm_get_edid(struct drm_connector *connector, 618 + struct i2c_adapter *adapter); 619 + extern unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter); 620 + extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); 621 + extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); 622 + extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode); 623 + extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, 624 + struct drm_display_mode *mode); 625 + extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode); 626 + extern void drm_mode_config_init(struct drm_device *dev); 627 + extern void drm_mode_config_cleanup(struct drm_device *dev); 628 + extern void drm_mode_set_name(struct drm_display_mode *mode); 629 + extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2); 630 + extern int drm_mode_width(struct drm_display_mode *mode); 631 + extern int drm_mode_height(struct drm_display_mode *mode); 632 + 633 + /* for us by fb module */ 634 + extern int drm_mode_attachmode_crtc(struct drm_device *dev, 635 + struct drm_crtc *crtc, 636 + struct drm_display_mode *mode); 637 + extern int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode); 638 + 639 + extern struct drm_display_mode *drm_mode_create(struct drm_device *dev); 640 + extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); 641 + extern void drm_mode_list_concat(struct list_head *head, 642 + struct list_head *new); 643 + extern void drm_mode_validate_size(struct drm_device *dev, 644 + struct list_head *mode_list, 645 + int maxX, int maxY, int maxPitch); 646 + extern void drm_mode_prune_invalid(struct drm_device *dev, 647 + struct list_head *mode_list, bool verbose); 648 + extern void drm_mode_sort(struct list_head *mode_list); 649 + extern int drm_mode_vrefresh(struct drm_display_mode *mode); 650 + extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, 651 + int adjust_flags); 652 + extern void drm_mode_connector_list_update(struct drm_connector *connector); 653 + extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, 654 + struct edid *edid); 655 + extern int drm_connector_property_set_value(struct drm_connector *connector, 656 + struct drm_property *property, 657 + uint64_t value); 658 + extern int drm_connector_property_get_value(struct drm_connector *connector, 659 + struct drm_property *property, 660 + uint64_t *value); 661 + extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); 662 + extern void drm_framebuffer_set_object(struct drm_device *dev, 663 + unsigned long handle); 664 + extern int drm_framebuffer_init(struct drm_device *dev, 665 + struct drm_framebuffer *fb, 666 + const struct drm_framebuffer_funcs *funcs); 667 + extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb); 668 + extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc); 669 + extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); 670 + extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY); 671 + extern bool drm_crtc_in_use(struct drm_crtc *crtc); 672 + 673 + extern int drm_connector_attach_property(struct drm_connector *connector, 674 + struct drm_property *property, uint64_t init_val); 675 + extern struct drm_property *drm_property_create(struct drm_device *dev, int flags, 676 + const char *name, int num_values); 677 + extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); 678 + extern int drm_property_add_enum(struct drm_property *property, int index, 679 + uint64_t value, const char *name); 680 + extern int drm_mode_create_dvi_i_properties(struct drm_device *dev); 681 + extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats, 682 + char *formats[]); 683 + extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); 684 + extern int drm_mode_create_dithering_property(struct drm_device *dev); 685 + extern char *drm_get_encoder_name(struct drm_encoder *encoder); 686 + 687 + extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, 688 + struct drm_encoder *encoder); 689 + extern void drm_mode_connector_detach_encoder(struct drm_connector *connector, 690 + struct drm_encoder *encoder); 691 + extern bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 692 + int gamma_size); 693 + extern void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type); 694 + /* IOCTLs */ 695 + extern int drm_mode_getresources(struct drm_device *dev, 696 + void *data, struct drm_file *file_priv); 697 + 698 + extern int drm_mode_getcrtc(struct drm_device *dev, 699 + void *data, struct drm_file *file_priv); 700 + extern int drm_mode_getconnector(struct drm_device *dev, 701 + void *data, struct drm_file *file_priv); 702 + extern int drm_mode_setcrtc(struct drm_device *dev, 703 + void *data, struct drm_file *file_priv); 704 + extern int drm_mode_cursor_ioctl(struct drm_device *dev, 705 + void *data, struct drm_file *file_priv); 706 + extern int drm_mode_addfb(struct drm_device *dev, 707 + void *data, struct drm_file *file_priv); 708 + extern int drm_mode_rmfb(struct drm_device *dev, 709 + void *data, struct drm_file *file_priv); 710 + extern int drm_mode_getfb(struct drm_device *dev, 711 + void *data, struct drm_file *file_priv); 712 + extern int drm_mode_addmode_ioctl(struct drm_device *dev, 713 + void *data, struct drm_file *file_priv); 714 + extern int drm_mode_rmmode_ioctl(struct drm_device *dev, 715 + void *data, struct drm_file *file_priv); 716 + extern int drm_mode_attachmode_ioctl(struct drm_device *dev, 717 + void *data, struct drm_file *file_priv); 718 + extern int drm_mode_detachmode_ioctl(struct drm_device *dev, 719 + void *data, struct drm_file *file_priv); 720 + 721 + extern int drm_mode_getproperty_ioctl(struct drm_device *dev, 722 + void *data, struct drm_file *file_priv); 723 + extern int drm_mode_getblob_ioctl(struct drm_device *dev, 724 + void *data, struct drm_file *file_priv); 725 + extern int drm_mode_connector_property_set_ioctl(struct drm_device *dev, 726 + void *data, struct drm_file *file_priv); 727 + extern int drm_mode_hotplug_ioctl(struct drm_device *dev, 728 + void *data, struct drm_file *file_priv); 729 + extern int drm_mode_replacefb(struct drm_device *dev, 730 + void *data, struct drm_file *file_priv); 731 + extern int drm_mode_getencoder(struct drm_device *dev, 732 + void *data, struct drm_file *file_priv); 733 + extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, 734 + void *data, struct drm_file *file_priv); 735 + extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, 736 + void *data, struct drm_file *file_priv); 737 + #endif /* __DRM_CRTC_H__ */
+121
include/drm/drm_crtc_helper.h
··· 1 + /* 2 + * Copyright © 2006 Keith Packard 3 + * Copyright © 2007-2008 Dave Airlie 4 + * Copyright © 2007-2008 Intel Corporation 5 + * Jesse Barnes <jesse.barnes@intel.com> 6 + * 7 + * Permission is hereby granted, free of charge, to any person obtaining a 8 + * copy of this software and associated documentation files (the "Software"), 9 + * to deal in the Software without restriction, including without limitation 10 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 + * and/or sell copies of the Software, and to permit persons to whom the 12 + * Software is furnished to do so, subject to the following conditions: 13 + * 14 + * The above copyright notice and this permission notice shall be included in 15 + * all copies or substantial portions of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 + * OTHER DEALINGS IN THE SOFTWARE. 24 + */ 25 + 26 + /* 27 + * The DRM mode setting helper functions are common code for drivers to use if 28 + * they wish. Drivers are not forced to use this code in their 29 + * implementations but it would be useful if they code they do use at least 30 + * provides a consistent interface and operation to userspace 31 + */ 32 + 33 + #ifndef __DRM_CRTC_HELPER_H__ 34 + #define __DRM_CRTC_HELPER_H__ 35 + 36 + #include <linux/i2c.h> 37 + #include <linux/spinlock.h> 38 + #include <linux/types.h> 39 + #include <linux/idr.h> 40 + 41 + #include <linux/fb.h> 42 + 43 + struct drm_crtc_helper_funcs { 44 + /* 45 + * Control power levels on the CRTC. If the mode passed in is 46 + * unsupported, the provider must use the next lowest power level. 47 + */ 48 + void (*dpms)(struct drm_crtc *crtc, int mode); 49 + void (*prepare)(struct drm_crtc *crtc); 50 + void (*commit)(struct drm_crtc *crtc); 51 + 52 + /* Provider can fixup or change mode timings before modeset occurs */ 53 + bool (*mode_fixup)(struct drm_crtc *crtc, 54 + struct drm_display_mode *mode, 55 + struct drm_display_mode *adjusted_mode); 56 + /* Actually set the mode */ 57 + void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, 58 + struct drm_display_mode *adjusted_mode, int x, int y); 59 + 60 + /* Move the crtc on the current fb to the given position *optional* */ 61 + void (*mode_set_base)(struct drm_crtc *crtc, int x, int y); 62 + }; 63 + 64 + struct drm_encoder_helper_funcs { 65 + void (*dpms)(struct drm_encoder *encoder, int mode); 66 + void (*save)(struct drm_encoder *encoder); 67 + void (*restore)(struct drm_encoder *encoder); 68 + 69 + bool (*mode_fixup)(struct drm_encoder *encoder, 70 + struct drm_display_mode *mode, 71 + struct drm_display_mode *adjusted_mode); 72 + void (*prepare)(struct drm_encoder *encoder); 73 + void (*commit)(struct drm_encoder *encoder); 74 + void (*mode_set)(struct drm_encoder *encoder, 75 + struct drm_display_mode *mode, 76 + struct drm_display_mode *adjusted_mode); 77 + /* detect for DAC style encoders */ 78 + enum drm_connector_status (*detect)(struct drm_encoder *encoder, 79 + struct drm_connector *connector); 80 + }; 81 + 82 + struct drm_connector_helper_funcs { 83 + int (*get_modes)(struct drm_connector *connector); 84 + int (*mode_valid)(struct drm_connector *connector, 85 + struct drm_display_mode *mode); 86 + struct drm_encoder *(*best_encoder)(struct drm_connector *connector); 87 + }; 88 + 89 + extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); 90 + extern void drm_helper_disable_unused_functions(struct drm_device *dev); 91 + extern int drm_helper_hotplug_stage_two(struct drm_device *dev); 92 + extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow); 93 + extern int drm_crtc_helper_set_config(struct drm_mode_set *set); 94 + extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 95 + struct drm_display_mode *mode, 96 + int x, int y); 97 + extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); 98 + 99 + extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, 100 + struct drm_mode_fb_cmd *mode_cmd); 101 + 102 + static inline void drm_crtc_helper_add(struct drm_crtc *crtc, 103 + const struct drm_crtc_helper_funcs *funcs) 104 + { 105 + crtc->helper_private = (void *)funcs; 106 + } 107 + 108 + static inline void drm_encoder_helper_add(struct drm_encoder *encoder, 109 + const struct drm_encoder_helper_funcs *funcs) 110 + { 111 + encoder->helper_private = (void *)funcs; 112 + } 113 + 114 + static inline void drm_connector_helper_add(struct drm_connector *connector, 115 + const struct drm_connector_helper_funcs *funcs) 116 + { 117 + connector->helper_private = (void *)funcs; 118 + } 119 + 120 + extern int drm_helper_resume_force_mode(struct drm_device *dev); 121 + #endif
+202
include/drm/drm_edid.h
··· 1 + /* 2 + * Copyright © 2007-2008 Intel Corporation 3 + * Jesse Barnes <jesse.barnes@intel.com> 4 + * 5 + * Permission is hereby granted, free of charge, to any person obtaining a 6 + * copy of this software and associated documentation files (the "Software"), 7 + * to deal in the Software without restriction, including without limitation 8 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 + * and/or sell copies of the Software, and to permit persons to whom the 10 + * Software is furnished to do so, subject to the following conditions: 11 + * 12 + * The above copyright notice and this permission notice shall be included in 13 + * all copies or substantial portions of the Software. 14 + * 15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 + * OTHER DEALINGS IN THE SOFTWARE. 22 + */ 23 + #ifndef __DRM_EDID_H__ 24 + #define __DRM_EDID_H__ 25 + 26 + #include <linux/types.h> 27 + 28 + #define EDID_LENGTH 128 29 + #define DDC_ADDR 0x50 30 + 31 + #ifdef BIG_ENDIAN 32 + #error "EDID structure is little endian, need big endian versions" 33 + #else 34 + 35 + struct est_timings { 36 + u8 t1; 37 + u8 t2; 38 + u8 mfg_rsvd; 39 + } __attribute__((packed)); 40 + 41 + struct std_timing { 42 + u8 hsize; /* need to multiply by 8 then add 248 */ 43 + u8 vfreq:6; /* need to add 60 */ 44 + u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ 45 + } __attribute__((packed)); 46 + 47 + /* If detailed data is pixel timing */ 48 + struct detailed_pixel_timing { 49 + u8 hactive_lo; 50 + u8 hblank_lo; 51 + u8 hblank_hi:4; 52 + u8 hactive_hi:4; 53 + u8 vactive_lo; 54 + u8 vblank_lo; 55 + u8 vblank_hi:4; 56 + u8 vactive_hi:4; 57 + u8 hsync_offset_lo; 58 + u8 hsync_pulse_width_lo; 59 + u8 vsync_pulse_width_lo:4; 60 + u8 vsync_offset_lo:4; 61 + u8 hsync_pulse_width_hi:2; 62 + u8 hsync_offset_hi:2; 63 + u8 vsync_pulse_width_hi:2; 64 + u8 vsync_offset_hi:2; 65 + u8 width_mm_lo; 66 + u8 height_mm_lo; 67 + u8 height_mm_hi:4; 68 + u8 width_mm_hi:4; 69 + u8 hborder; 70 + u8 vborder; 71 + u8 unknown0:1; 72 + u8 vsync_positive:1; 73 + u8 hsync_positive:1; 74 + u8 separate_sync:2; 75 + u8 stereo:1; 76 + u8 unknown6:1; 77 + u8 interlaced:1; 78 + } __attribute__((packed)); 79 + 80 + /* If it's not pixel timing, it'll be one of the below */ 81 + struct detailed_data_string { 82 + u8 str[13]; 83 + } __attribute__((packed)); 84 + 85 + struct detailed_data_monitor_range { 86 + u8 min_vfreq; 87 + u8 max_vfreq; 88 + u8 min_hfreq_khz; 89 + u8 max_hfreq_khz; 90 + u8 pixel_clock_mhz; /* need to multiply by 10 */ 91 + u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */ 92 + u8 hfreq_start_khz; /* need to multiply by 2 */ 93 + u8 c; /* need to divide by 2 */ 94 + u16 m; /* FIXME: byte order */ 95 + u8 k; 96 + u8 j; /* need to divide by 2 */ 97 + } __attribute__((packed)); 98 + 99 + struct detailed_data_wpindex { 100 + u8 white_y_lo:2; 101 + u8 white_x_lo:2; 102 + u8 pad:4; 103 + u8 white_x_hi; 104 + u8 white_y_hi; 105 + u8 gamma; /* need to divide by 100 then add 1 */ 106 + } __attribute__((packed)); 107 + 108 + struct detailed_data_color_point { 109 + u8 windex1; 110 + u8 wpindex1[3]; 111 + u8 windex2; 112 + u8 wpindex2[3]; 113 + } __attribute__((packed)); 114 + 115 + struct detailed_non_pixel { 116 + u8 pad1; 117 + u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name 118 + fb=color point data, fa=standard timing data, 119 + f9=undefined, f8=mfg. reserved */ 120 + u8 pad2; 121 + union { 122 + struct detailed_data_string str; 123 + struct detailed_data_monitor_range range; 124 + struct detailed_data_wpindex color; 125 + struct std_timing timings[5]; 126 + } data; 127 + } __attribute__((packed)); 128 + 129 + #define EDID_DETAIL_STD_MODES 0xfa 130 + #define EDID_DETAIL_MONITOR_CPDATA 0xfb 131 + #define EDID_DETAIL_MONITOR_NAME 0xfc 132 + #define EDID_DETAIL_MONITOR_RANGE 0xfd 133 + #define EDID_DETAIL_MONITOR_STRING 0xfe 134 + #define EDID_DETAIL_MONITOR_SERIAL 0xff 135 + 136 + struct detailed_timing { 137 + u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */ 138 + union { 139 + struct detailed_pixel_timing pixel_data; 140 + struct detailed_non_pixel other_data; 141 + } data; 142 + } __attribute__((packed)); 143 + 144 + struct edid { 145 + u8 header[8]; 146 + /* Vendor & product info */ 147 + u8 mfg_id[2]; 148 + u8 prod_code[2]; 149 + u32 serial; /* FIXME: byte order */ 150 + u8 mfg_week; 151 + u8 mfg_year; 152 + /* EDID version */ 153 + u8 version; 154 + u8 revision; 155 + /* Display info: */ 156 + /* input definition */ 157 + u8 serration_vsync:1; 158 + u8 sync_on_green:1; 159 + u8 composite_sync:1; 160 + u8 separate_syncs:1; 161 + u8 blank_to_black:1; 162 + u8 video_level:2; 163 + u8 digital:1; /* bits below must be zero if set */ 164 + u8 width_cm; 165 + u8 height_cm; 166 + u8 gamma; 167 + /* feature support */ 168 + u8 default_gtf:1; 169 + u8 preferred_timing:1; 170 + u8 standard_color:1; 171 + u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ 172 + u8 pm_active_off:1; 173 + u8 pm_suspend:1; 174 + u8 pm_standby:1; 175 + /* Color characteristics */ 176 + u8 red_green_lo; 177 + u8 black_white_lo; 178 + u8 red_x; 179 + u8 red_y; 180 + u8 green_x; 181 + u8 green_y; 182 + u8 blue_x; 183 + u8 blue_y; 184 + u8 white_x; 185 + u8 white_y; 186 + /* Est. timings and mfg rsvd timings*/ 187 + struct est_timings established_timings; 188 + /* Standard timings 1-8*/ 189 + struct std_timing standard_timings[8]; 190 + /* Detailing timings 1-4 */ 191 + struct detailed_timing detailed_timings[4]; 192 + /* Number of 128 byte ext. blocks */ 193 + u8 extensions; 194 + /* Checksum */ 195 + u8 checksum; 196 + } __attribute__((packed)); 197 + 198 + #endif /* little endian structs */ 199 + 200 + #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8)) 201 + 202 + #endif /* __DRM_EDID_H__ */
+278
include/drm/drm_mode.h
··· 1 + /* 2 + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 3 + * Copyright (c) 2007 Jakob Bornecrantz <wallbraker@gmail.com> 4 + * Copyright (c) 2008 Red Hat Inc. 5 + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA 6 + * Copyright (c) 2007-2008 Intel Corporation 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining a 9 + * copy of this software and associated documentation files (the "Software"), 10 + * to deal in the Software without restriction, including without limitation 11 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 + * and/or sell copies of the Software, and to permit persons to whom the 13 + * Software is furnished to do so, subject to the following conditions: 14 + * 15 + * The above copyright notice and this permission notice shall be included in 16 + * all copies or substantial portions of the Software. 17 + * 18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 + * IN THE SOFTWARE. 25 + */ 26 + 27 + #ifndef _DRM_MODE_H 28 + #define _DRM_MODE_H 29 + 30 + #if !defined(__KERNEL__) && !defined(_KERNEL) 31 + #include <stdint.h> 32 + #else 33 + #include <linux/kernel.h> 34 + #endif 35 + 36 + #define DRM_DISPLAY_INFO_LEN 32 37 + #define DRM_CONNECTOR_NAME_LEN 32 38 + #define DRM_DISPLAY_MODE_LEN 32 39 + #define DRM_PROP_NAME_LEN 32 40 + 41 + #define DRM_MODE_TYPE_BUILTIN (1<<0) 42 + #define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) 43 + #define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) 44 + #define DRM_MODE_TYPE_PREFERRED (1<<3) 45 + #define DRM_MODE_TYPE_DEFAULT (1<<4) 46 + #define DRM_MODE_TYPE_USERDEF (1<<5) 47 + #define DRM_MODE_TYPE_DRIVER (1<<6) 48 + 49 + /* Video mode flags */ 50 + /* bit compatible with the xorg definitions. */ 51 + #define DRM_MODE_FLAG_PHSYNC (1<<0) 52 + #define DRM_MODE_FLAG_NHSYNC (1<<1) 53 + #define DRM_MODE_FLAG_PVSYNC (1<<2) 54 + #define DRM_MODE_FLAG_NVSYNC (1<<3) 55 + #define DRM_MODE_FLAG_INTERLACE (1<<4) 56 + #define DRM_MODE_FLAG_DBLSCAN (1<<5) 57 + #define DRM_MODE_FLAG_CSYNC (1<<6) 58 + #define DRM_MODE_FLAG_PCSYNC (1<<7) 59 + #define DRM_MODE_FLAG_NCSYNC (1<<8) 60 + #define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ 61 + #define DRM_MODE_FLAG_BCAST (1<<10) 62 + #define DRM_MODE_FLAG_PIXMUX (1<<11) 63 + #define DRM_MODE_FLAG_DBLCLK (1<<12) 64 + #define DRM_MODE_FLAG_CLKDIV2 (1<<13) 65 + 66 + /* DPMS flags */ 67 + /* bit compatible with the xorg definitions. */ 68 + #define DRM_MODE_DPMS_ON 0 69 + #define DRM_MODE_DPMS_STANDBY 1 70 + #define DRM_MODE_DPMS_SUSPEND 2 71 + #define DRM_MODE_DPMS_OFF 3 72 + 73 + /* Scaling mode options */ 74 + #define DRM_MODE_SCALE_NON_GPU 0 75 + #define DRM_MODE_SCALE_FULLSCREEN 1 76 + #define DRM_MODE_SCALE_NO_SCALE 2 77 + #define DRM_MODE_SCALE_ASPECT 3 78 + 79 + /* Dithering mode options */ 80 + #define DRM_MODE_DITHERING_OFF 0 81 + #define DRM_MODE_DITHERING_ON 1 82 + 83 + struct drm_mode_modeinfo { 84 + unsigned int clock; 85 + unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew; 86 + unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan; 87 + 88 + unsigned int vrefresh; /* vertical refresh * 1000 */ 89 + 90 + unsigned int flags; 91 + unsigned int type; 92 + char name[DRM_DISPLAY_MODE_LEN]; 93 + }; 94 + 95 + struct drm_mode_card_res { 96 + uint64_t fb_id_ptr; 97 + uint64_t crtc_id_ptr; 98 + uint64_t connector_id_ptr; 99 + uint64_t encoder_id_ptr; 100 + int count_fbs; 101 + int count_crtcs; 102 + int count_connectors; 103 + int count_encoders; 104 + int min_width, max_width; 105 + int min_height, max_height; 106 + }; 107 + 108 + struct drm_mode_crtc { 109 + uint64_t set_connectors_ptr; 110 + int count_connectors; 111 + 112 + unsigned int crtc_id; /**< Id */ 113 + unsigned int fb_id; /**< Id of framebuffer */ 114 + 115 + int x, y; /**< Position on the frameuffer */ 116 + 117 + uint32_t gamma_size; 118 + int mode_valid; 119 + struct drm_mode_modeinfo mode; 120 + }; 121 + 122 + #define DRM_MODE_ENCODER_NONE 0 123 + #define DRM_MODE_ENCODER_DAC 1 124 + #define DRM_MODE_ENCODER_TMDS 2 125 + #define DRM_MODE_ENCODER_LVDS 3 126 + #define DRM_MODE_ENCODER_TVDAC 4 127 + 128 + struct drm_mode_get_encoder { 129 + unsigned int encoder_id; 130 + unsigned int encoder_type; 131 + 132 + unsigned int crtc_id; /**< Id of crtc */ 133 + 134 + uint32_t possible_crtcs; 135 + uint32_t possible_clones; 136 + }; 137 + 138 + /* This is for connectors with multiple signal types. */ 139 + /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ 140 + #define DRM_MODE_SUBCONNECTOR_Automatic 0 141 + #define DRM_MODE_SUBCONNECTOR_Unknown 0 142 + #define DRM_MODE_SUBCONNECTOR_DVID 3 143 + #define DRM_MODE_SUBCONNECTOR_DVIA 4 144 + #define DRM_MODE_SUBCONNECTOR_Composite 5 145 + #define DRM_MODE_SUBCONNECTOR_SVIDEO 6 146 + #define DRM_MODE_SUBCONNECTOR_Component 8 147 + 148 + #define DRM_MODE_CONNECTOR_Unknown 0 149 + #define DRM_MODE_CONNECTOR_VGA 1 150 + #define DRM_MODE_CONNECTOR_DVII 2 151 + #define DRM_MODE_CONNECTOR_DVID 3 152 + #define DRM_MODE_CONNECTOR_DVIA 4 153 + #define DRM_MODE_CONNECTOR_Composite 5 154 + #define DRM_MODE_CONNECTOR_SVIDEO 6 155 + #define DRM_MODE_CONNECTOR_LVDS 7 156 + #define DRM_MODE_CONNECTOR_Component 8 157 + #define DRM_MODE_CONNECTOR_9PinDIN 9 158 + #define DRM_MODE_CONNECTOR_DisplayPort 10 159 + #define DRM_MODE_CONNECTOR_HDMIA 11 160 + #define DRM_MODE_CONNECTOR_HDMIB 12 161 + 162 + struct drm_mode_get_connector { 163 + 164 + uint64_t encoders_ptr; 165 + uint64_t modes_ptr; 166 + uint64_t props_ptr; 167 + uint64_t prop_values_ptr; 168 + 169 + int count_modes; 170 + int count_props; 171 + int count_encoders; 172 + 173 + unsigned int encoder_id; /**< Current Encoder */ 174 + unsigned int connector_id; /**< Id */ 175 + unsigned int connector_type; 176 + unsigned int connector_type_id; 177 + 178 + unsigned int connection; 179 + unsigned int mm_width, mm_height; /**< HxW in millimeters */ 180 + unsigned int subpixel; 181 + }; 182 + 183 + #define DRM_MODE_PROP_PENDING (1<<0) 184 + #define DRM_MODE_PROP_RANGE (1<<1) 185 + #define DRM_MODE_PROP_IMMUTABLE (1<<2) 186 + #define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ 187 + #define DRM_MODE_PROP_BLOB (1<<4) 188 + 189 + struct drm_mode_property_enum { 190 + uint64_t value; 191 + unsigned char name[DRM_PROP_NAME_LEN]; 192 + }; 193 + 194 + struct drm_mode_get_property { 195 + uint64_t values_ptr; /* values and blob lengths */ 196 + uint64_t enum_blob_ptr; /* enum and blob id ptrs */ 197 + 198 + unsigned int prop_id; 199 + unsigned int flags; 200 + unsigned char name[DRM_PROP_NAME_LEN]; 201 + 202 + int count_values; 203 + int count_enum_blobs; 204 + }; 205 + 206 + struct drm_mode_connector_set_property { 207 + uint64_t value; 208 + unsigned int prop_id; 209 + unsigned int connector_id; 210 + }; 211 + 212 + struct drm_mode_get_blob { 213 + uint32_t blob_id; 214 + uint32_t length; 215 + uint64_t data; 216 + }; 217 + 218 + struct drm_mode_fb_cmd { 219 + unsigned int buffer_id; 220 + unsigned int width, height; 221 + unsigned int pitch; 222 + unsigned int bpp; 223 + unsigned int depth; 224 + 225 + unsigned int handle; 226 + }; 227 + 228 + struct drm_mode_mode_cmd { 229 + unsigned int connector_id; 230 + struct drm_mode_modeinfo mode; 231 + }; 232 + 233 + #define DRM_MODE_CURSOR_BO 0x01 234 + #define DRM_MODE_CURSOR_MOVE 0x02 235 + 236 + /* 237 + * depending on the value in flags diffrent members are used. 238 + * 239 + * CURSOR_BO uses 240 + * crtc 241 + * width 242 + * height 243 + * handle - if 0 turns the cursor of 244 + * 245 + * CURSOR_MOVE uses 246 + * crtc 247 + * x 248 + * y 249 + */ 250 + struct drm_mode_cursor { 251 + unsigned int flags; 252 + unsigned int crtc; 253 + int x; 254 + int y; 255 + uint32_t width; 256 + uint32_t height; 257 + unsigned int handle; 258 + }; 259 + 260 + /* 261 + * oh so ugly hotplug 262 + */ 263 + struct drm_mode_hotplug { 264 + uint32_t counter; 265 + }; 266 + 267 + struct drm_mode_crtc_lut { 268 + 269 + uint32_t crtc_id; 270 + uint32_t gamma_size; 271 + 272 + /* pointers to arrays */ 273 + uint64_t red; 274 + uint64_t green; 275 + uint64_t blue; 276 + }; 277 + 278 + #endif
+4
include/linux/console.h
··· 153 153 #define VESA_HSYNC_SUSPEND 2 154 154 #define VESA_POWERDOWN 3 155 155 156 + #ifdef CONFIG_VGA_CONSOLE 157 + extern bool vgacon_text_force(void); 158 + #endif 159 + 156 160 #endif /* _LINUX_CONSOLE_H */