linux/drivers/gpu/drm/drm_crtc_helper.c
<<
>>
Prefs
   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#include "drm_fb_helper.h"
  36
  37static bool drm_kms_helper_poll = true;
  38module_param_named(poll, drm_kms_helper_poll, bool, 0600);
  39
  40static void drm_mode_validate_flag(struct drm_connector *connector,
  41                                   int flags)
  42{
  43        struct drm_display_mode *mode, *t;
  44
  45        if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
  46                return;
  47
  48        list_for_each_entry_safe(mode, t, &connector->modes, head) {
  49                if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
  50                                !(flags & DRM_MODE_FLAG_INTERLACE))
  51                        mode->status = MODE_NO_INTERLACE;
  52                if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
  53                                !(flags & DRM_MODE_FLAG_DBLSCAN))
  54                        mode->status = MODE_NO_DBLESCAN;
  55        }
  56
  57        return;
  58}
  59
  60/**
  61 * drm_helper_probe_single_connector_modes - get complete set of display modes
  62 * @dev: DRM device
  63 * @maxX: max width for modes
  64 * @maxY: max height for modes
  65 *
  66 * LOCKING:
  67 * Caller must hold mode config lock.
  68 *
  69 * Based on @dev's mode_config layout, scan all the connectors and try to detect
  70 * modes on them.  Modes will first be added to the connector's probed_modes
  71 * list, then culled (based on validity and the @maxX, @maxY parameters) and
  72 * put into the normal modes list.
  73 *
  74 * Intended to be used either at bootup time or when major configuration
  75 * changes have occurred.
  76 *
  77 * FIXME: take into account monitor limits
  78 *
  79 * RETURNS:
  80 * Number of modes found on @connector.
  81 */
  82int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
  83                                            uint32_t maxX, uint32_t maxY)
  84{
  85        struct drm_device *dev = connector->dev;
  86        struct drm_display_mode *mode, *t;
  87        struct drm_connector_helper_funcs *connector_funcs =
  88                connector->helper_private;
  89        int count = 0;
  90        int mode_flags = 0;
  91
  92        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
  93                        drm_get_connector_name(connector));
  94        /* set all modes to the unverified state */
  95        list_for_each_entry_safe(mode, t, &connector->modes, head)
  96                mode->status = MODE_UNVERIFIED;
  97
  98        if (connector->force) {
  99                if (connector->force == DRM_FORCE_ON)
 100                        connector->status = connector_status_connected;
 101                else
 102                        connector->status = connector_status_disconnected;
 103                if (connector->funcs->force)
 104                        connector->funcs->force(connector);
 105        } else {
 106                connector->status = connector->funcs->detect(connector, true);
 107                drm_kms_helper_poll_enable(dev);
 108        }
 109
 110        if (connector->status == connector_status_disconnected) {
 111                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
 112                        connector->base.id, drm_get_connector_name(connector));
 113                drm_mode_connector_update_edid_property(connector, NULL);
 114                goto prune;
 115        }
 116
 117        count = (*connector_funcs->get_modes)(connector);
 118        if (count == 0 && connector->status == connector_status_connected)
 119                count = drm_add_modes_noedid(connector, 1024, 768);
 120        if (count == 0)
 121                goto prune;
 122
 123        drm_mode_connector_list_update(connector);
 124
 125        if (maxX && maxY)
 126                drm_mode_validate_size(dev, &connector->modes, maxX,
 127                                       maxY, 0);
 128
 129        if (connector->interlace_allowed)
 130                mode_flags |= DRM_MODE_FLAG_INTERLACE;
 131        if (connector->doublescan_allowed)
 132                mode_flags |= DRM_MODE_FLAG_DBLSCAN;
 133        drm_mode_validate_flag(connector, mode_flags);
 134
 135        list_for_each_entry_safe(mode, t, &connector->modes, head) {
 136                if (mode->status == MODE_OK)
 137                        mode->status = connector_funcs->mode_valid(connector,
 138                                                                   mode);
 139        }
 140
 141prune:
 142        drm_mode_prune_invalid(dev, &connector->modes, true);
 143
 144        if (list_empty(&connector->modes))
 145                return 0;
 146
 147        drm_mode_sort(&connector->modes);
 148
 149        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
 150                        drm_get_connector_name(connector));
 151        list_for_each_entry_safe(mode, t, &connector->modes, head) {
 152                mode->vrefresh = drm_mode_vrefresh(mode);
 153
 154                drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
 155                drm_mode_debug_printmodeline(mode);
 156        }
 157
 158        return count;
 159}
 160EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
 161
 162/**
 163 * drm_helper_encoder_in_use - check if a given encoder is in use
 164 * @encoder: encoder to check
 165 *
 166 * LOCKING:
 167 * Caller must hold mode config lock.
 168 *
 169 * Walk @encoders's DRM device's mode_config and see if it's in use.
 170 *
 171 * RETURNS:
 172 * True if @encoder is part of the mode_config, false otherwise.
 173 */
 174bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
 175{
 176        struct drm_connector *connector;
 177        struct drm_device *dev = encoder->dev;
 178        list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 179                if (connector->encoder == encoder)
 180                        return true;
 181        return false;
 182}
 183EXPORT_SYMBOL(drm_helper_encoder_in_use);
 184
 185/**
 186 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
 187 * @crtc: CRTC to check
 188 *
 189 * LOCKING:
 190 * Caller must hold mode config lock.
 191 *
 192 * Walk @crtc's DRM device's mode_config and see if it's in use.
 193 *
 194 * RETURNS:
 195 * True if @crtc is part of the mode_config, false otherwise.
 196 */
 197bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
 198{
 199        struct drm_encoder *encoder;
 200        struct drm_device *dev = crtc->dev;
 201        /* FIXME: Locking around list access? */
 202        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
 203                if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
 204                        return true;
 205        return false;
 206}
 207EXPORT_SYMBOL(drm_helper_crtc_in_use);
 208
 209static void
 210drm_encoder_disable(struct drm_encoder *encoder)
 211{
 212        struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 213
 214        if (encoder_funcs->disable)
 215                (*encoder_funcs->disable)(encoder);
 216        else
 217                (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
 218}
 219
 220/**
 221 * drm_helper_disable_unused_functions - disable unused objects
 222 * @dev: DRM device
 223 *
 224 * LOCKING:
 225 * Caller must hold mode config lock.
 226 *
 227 * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
 228 * by calling its dpms function, which should power it off.
 229 */
 230void drm_helper_disable_unused_functions(struct drm_device *dev)
 231{
 232        struct drm_encoder *encoder;
 233        struct drm_connector *connector;
 234        struct drm_crtc *crtc;
 235
 236        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 237                if (!connector->encoder)
 238                        continue;
 239                if (connector->status == connector_status_disconnected)
 240                        connector->encoder = NULL;
 241        }
 242
 243        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 244                if (!drm_helper_encoder_in_use(encoder)) {
 245                        drm_encoder_disable(encoder);
 246                        /* disconnector encoder from any connector */
 247                        encoder->crtc = NULL;
 248                }
 249        }
 250
 251        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 252                struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 253                crtc->enabled = drm_helper_crtc_in_use(crtc);
 254                if (!crtc->enabled) {
 255                        if (crtc_funcs->disable)
 256                                (*crtc_funcs->disable)(crtc);
 257                        else
 258                                (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
 259                        crtc->fb = NULL;
 260                }
 261        }
 262}
 263EXPORT_SYMBOL(drm_helper_disable_unused_functions);
 264
 265/**
 266 * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
 267 * @encoder: encoder to test
 268 * @crtc: crtc to test
 269 *
 270 * Return false if @encoder can't be driven by @crtc, true otherwise.
 271 */
 272static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 273                                struct drm_crtc *crtc)
 274{
 275        struct drm_device *dev;
 276        struct drm_crtc *tmp;
 277        int crtc_mask = 1;
 278
 279        WARN(!crtc, "checking null crtc?\n");
 280
 281        dev = crtc->dev;
 282
 283        list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
 284                if (tmp == crtc)
 285                        break;
 286                crtc_mask <<= 1;
 287        }
 288
 289        if (encoder->possible_crtcs & crtc_mask)
 290                return true;
 291        return false;
 292}
 293
 294/*
 295 * Check the CRTC we're going to map each output to vs. its current
 296 * CRTC.  If they don't match, we have to disable the output and the CRTC
 297 * since the driver will have to re-route things.
 298 */
 299static void
 300drm_crtc_prepare_encoders(struct drm_device *dev)
 301{
 302        struct drm_encoder_helper_funcs *encoder_funcs;
 303        struct drm_encoder *encoder;
 304
 305        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 306                encoder_funcs = encoder->helper_private;
 307                /* Disable unused encoders */
 308                if (encoder->crtc == NULL)
 309                        drm_encoder_disable(encoder);
 310                /* Disable encoders whose CRTC is about to change */
 311                if (encoder_funcs->get_crtc &&
 312                    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
 313                        drm_encoder_disable(encoder);
 314        }
 315}
 316
 317/**
 318 * drm_crtc_set_mode - set a mode
 319 * @crtc: CRTC to program
 320 * @mode: mode to use
 321 * @x: width of mode
 322 * @y: height of mode
 323 *
 324 * LOCKING:
 325 * Caller must hold mode config lock.
 326 *
 327 * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
 328 * to fixup or reject the mode prior to trying to set it.
 329 *
 330 * RETURNS:
 331 * True if the mode was set successfully, or false otherwise.
 332 */
 333bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 334                              struct drm_display_mode *mode,
 335                              int x, int y,
 336                              struct drm_framebuffer *old_fb)
 337{
 338        struct drm_device *dev = crtc->dev;
 339        struct drm_display_mode *adjusted_mode, saved_mode;
 340        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 341        struct drm_encoder_helper_funcs *encoder_funcs;
 342        int saved_x, saved_y;
 343        struct drm_encoder *encoder;
 344        bool ret = true;
 345
 346        adjusted_mode = drm_mode_duplicate(dev, mode);
 347
 348        crtc->enabled = drm_helper_crtc_in_use(crtc);
 349
 350        if (!crtc->enabled)
 351                return true;
 352
 353        saved_mode = crtc->mode;
 354        saved_x = crtc->x;
 355        saved_y = crtc->y;
 356
 357        /* Update crtc values up front so the driver can rely on them for mode
 358         * setting.
 359         */
 360        crtc->mode = *mode;
 361        crtc->x = x;
 362        crtc->y = y;
 363
 364        /* Pass our mode to the connectors and the CRTC to give them a chance to
 365         * adjust it according to limitations or connector properties, and also
 366         * a chance to reject the mode entirely.
 367         */
 368        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 369
 370                if (encoder->crtc != crtc)
 371                        continue;
 372                encoder_funcs = encoder->helper_private;
 373                if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
 374                                                      adjusted_mode))) {
 375                        goto done;
 376                }
 377        }
 378
 379        if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
 380                goto done;
 381        }
 382        DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 383
 384        /* Prepare the encoders and CRTCs before setting the mode. */
 385        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 386
 387                if (encoder->crtc != crtc)
 388                        continue;
 389                encoder_funcs = encoder->helper_private;
 390                /* Disable the encoders as the first thing we do. */
 391                encoder_funcs->prepare(encoder);
 392        }
 393
 394        drm_crtc_prepare_encoders(dev);
 395
 396        crtc_funcs->prepare(crtc);
 397
 398        /* Set up the DPLL and any encoders state that needs to adjust or depend
 399         * on the DPLL.
 400         */
 401        ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
 402        if (!ret)
 403            goto done;
 404
 405        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 406
 407                if (encoder->crtc != crtc)
 408                        continue;
 409
 410                DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
 411                        encoder->base.id, drm_get_encoder_name(encoder),
 412                        mode->base.id, mode->name);
 413                encoder_funcs = encoder->helper_private;
 414                encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 415        }
 416
 417        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
 418        crtc_funcs->commit(crtc);
 419
 420        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 421
 422                if (encoder->crtc != crtc)
 423                        continue;
 424
 425                encoder_funcs = encoder->helper_private;
 426                encoder_funcs->commit(encoder);
 427
 428        }
 429
 430        /* XXX free adjustedmode */
 431        drm_mode_destroy(dev, adjusted_mode);
 432        /* FIXME: add subpixel order */
 433done:
 434        if (!ret) {
 435                crtc->mode = saved_mode;
 436                crtc->x = saved_x;
 437                crtc->y = saved_y;
 438        }
 439
 440        return ret;
 441}
 442EXPORT_SYMBOL(drm_crtc_helper_set_mode);
 443
 444
 445/**
 446 * drm_crtc_helper_set_config - set a new config from userspace
 447 * @crtc: CRTC to setup
 448 * @crtc_info: user provided configuration
 449 * @new_mode: new mode to set
 450 * @connector_set: set of connectors for the new config
 451 * @fb: new framebuffer
 452 *
 453 * LOCKING:
 454 * Caller must hold mode config lock.
 455 *
 456 * Setup a new configuration, provided by the user in @crtc_info, and enable
 457 * it.
 458 *
 459 * RETURNS:
 460 * Zero. (FIXME)
 461 */
 462int drm_crtc_helper_set_config(struct drm_mode_set *set)
 463{
 464        struct drm_device *dev;
 465        struct drm_crtc *save_crtcs, *new_crtc, *crtc;
 466        struct drm_encoder *save_encoders, *new_encoder, *encoder;
 467        struct drm_framebuffer *old_fb = NULL;
 468        bool mode_changed = false; /* if true do a full mode set */
 469        bool fb_changed = false; /* if true and !mode_changed just do a flip */
 470        struct drm_connector *save_connectors, *connector;
 471        int count = 0, ro, fail = 0;
 472        struct drm_crtc_helper_funcs *crtc_funcs;
 473        int ret = 0;
 474        int i;
 475
 476        DRM_DEBUG_KMS("\n");
 477
 478        if (!set)
 479                return -EINVAL;
 480
 481        if (!set->crtc)
 482                return -EINVAL;
 483
 484        if (!set->crtc->helper_private)
 485                return -EINVAL;
 486
 487        crtc_funcs = set->crtc->helper_private;
 488
 489        if (set->fb) {
 490                DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
 491                                set->crtc->base.id, set->fb->base.id,
 492                                (int)set->num_connectors, set->x, set->y);
 493        } else {
 494                DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n",
 495                                set->crtc->base.id, (int)set->num_connectors,
 496                                set->x, set->y);
 497        }
 498
 499        dev = set->crtc->dev;
 500
 501        /* Allocate space for the backup of all (non-pointer) crtc, encoder and
 502         * connector data. */
 503        save_crtcs = kzalloc(dev->mode_config.num_crtc *
 504                             sizeof(struct drm_crtc), GFP_KERNEL);
 505        if (!save_crtcs)
 506                return -ENOMEM;
 507
 508        save_encoders = kzalloc(dev->mode_config.num_encoder *
 509                                sizeof(struct drm_encoder), GFP_KERNEL);
 510        if (!save_encoders) {
 511                kfree(save_crtcs);
 512                return -ENOMEM;
 513        }
 514
 515        save_connectors = kzalloc(dev->mode_config.num_connector *
 516                                sizeof(struct drm_connector), GFP_KERNEL);
 517        if (!save_connectors) {
 518                kfree(save_crtcs);
 519                kfree(save_encoders);
 520                return -ENOMEM;
 521        }
 522
 523        /* Copy data. Note that driver private data is not affected.
 524         * Should anything bad happen only the expected state is
 525         * restored, not the drivers personal bookkeeping.
 526         */
 527        count = 0;
 528        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 529                save_crtcs[count++] = *crtc;
 530        }
 531
 532        count = 0;
 533        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 534                save_encoders[count++] = *encoder;
 535        }
 536
 537        count = 0;
 538        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 539                save_connectors[count++] = *connector;
 540        }
 541
 542        /* We should be able to check here if the fb has the same properties
 543         * and then just flip_or_move it */
 544        if (set->crtc->fb != set->fb) {
 545                /* If we have no fb then treat it as a full mode set */
 546                if (set->crtc->fb == NULL) {
 547                        DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
 548                        mode_changed = true;
 549                } else if (set->fb == NULL) {
 550                        mode_changed = true;
 551                } else
 552                        fb_changed = true;
 553        }
 554
 555        if (set->x != set->crtc->x || set->y != set->crtc->y)
 556                fb_changed = true;
 557
 558        if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
 559                DRM_DEBUG_KMS("modes are different, full mode set\n");
 560                drm_mode_debug_printmodeline(&set->crtc->mode);
 561                drm_mode_debug_printmodeline(set->mode);
 562                mode_changed = true;
 563        }
 564
 565        /* a) traverse passed in connector list and get encoders for them */
 566        count = 0;
 567        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 568                struct drm_connector_helper_funcs *connector_funcs =
 569                        connector->helper_private;
 570                new_encoder = connector->encoder;
 571                for (ro = 0; ro < set->num_connectors; ro++) {
 572                        if (set->connectors[ro] == connector) {
 573                                new_encoder = connector_funcs->best_encoder(connector);
 574                                /* if we can't get an encoder for a connector
 575                                   we are setting now - then fail */
 576                                if (new_encoder == NULL)
 577                                        /* don't break so fail path works correct */
 578                                        fail = 1;
 579                                break;
 580                        }
 581                }
 582
 583                if (new_encoder != connector->encoder) {
 584                        DRM_DEBUG_KMS("encoder changed, full mode switch\n");
 585                        mode_changed = true;
 586                        /* If the encoder is reused for another connector, then
 587                         * the appropriate crtc will be set later.
 588                         */
 589                        if (connector->encoder)
 590                                connector->encoder->crtc = NULL;
 591                        connector->encoder = new_encoder;
 592                }
 593        }
 594
 595        if (fail) {
 596                ret = -EINVAL;
 597                goto fail;
 598        }
 599
 600        count = 0;
 601        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 602                if (!connector->encoder)
 603                        continue;
 604
 605                if (connector->encoder->crtc == set->crtc)
 606                        new_crtc = NULL;
 607                else
 608                        new_crtc = connector->encoder->crtc;
 609
 610                for (ro = 0; ro < set->num_connectors; ro++) {
 611                        if (set->connectors[ro] == connector)
 612                                new_crtc = set->crtc;
 613                }
 614
 615                /* Make sure the new CRTC will work with the encoder */
 616                if (new_crtc &&
 617                    !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
 618                        ret = -EINVAL;
 619                        goto fail;
 620                }
 621                if (new_crtc != connector->encoder->crtc) {
 622                        DRM_DEBUG_KMS("crtc changed, full mode switch\n");
 623                        mode_changed = true;
 624                        connector->encoder->crtc = new_crtc;
 625                }
 626                if (new_crtc) {
 627                        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
 628                                connector->base.id, drm_get_connector_name(connector),
 629                                new_crtc->base.id);
 630                } else {
 631                        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
 632                                connector->base.id, drm_get_connector_name(connector));
 633                }
 634        }
 635
 636        /* mode_set_base is not a required function */
 637        if (fb_changed && !crtc_funcs->mode_set_base)
 638                mode_changed = true;
 639
 640        if (mode_changed) {
 641                set->crtc->enabled = (set->mode != NULL);
 642                if (set->mode != NULL) {
 643                        DRM_DEBUG_KMS("attempting to set mode from"
 644                                        " userspace\n");
 645                        drm_mode_debug_printmodeline(set->mode);
 646                        old_fb = set->crtc->fb;
 647                        set->crtc->fb = set->fb;
 648                        if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 649                                                      set->x, set->y,
 650                                                      old_fb)) {
 651                                DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 652                                          set->crtc->base.id);
 653                                set->crtc->fb = old_fb;
 654                                ret = -EINVAL;
 655                                goto fail;
 656                        }
 657                        DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
 658                        for (i = 0; i < set->num_connectors; i++) {
 659                                DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
 660                                              drm_get_connector_name(set->connectors[i]));
 661                                set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
 662                        }
 663                }
 664                drm_helper_disable_unused_functions(dev);
 665        } else if (fb_changed) {
 666                set->crtc->x = set->x;
 667                set->crtc->y = set->y;
 668
 669                old_fb = set->crtc->fb;
 670                if (set->crtc->fb != set->fb)
 671                        set->crtc->fb = set->fb;
 672                ret = crtc_funcs->mode_set_base(set->crtc,
 673                                                set->x, set->y, old_fb);
 674                if (ret != 0) {
 675                        set->crtc->fb = old_fb;
 676                        goto fail;
 677                }
 678        }
 679
 680        kfree(save_connectors);
 681        kfree(save_encoders);
 682        kfree(save_crtcs);
 683        return 0;
 684
 685fail:
 686        /* Restore all previous data. */
 687        count = 0;
 688        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 689                *crtc = save_crtcs[count++];
 690        }
 691
 692        count = 0;
 693        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 694                *encoder = save_encoders[count++];
 695        }
 696
 697        count = 0;
 698        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 699                *connector = save_connectors[count++];
 700        }
 701
 702        kfree(save_connectors);
 703        kfree(save_encoders);
 704        kfree(save_crtcs);
 705        return ret;
 706}
 707EXPORT_SYMBOL(drm_crtc_helper_set_config);
 708
 709static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
 710{
 711        int dpms = DRM_MODE_DPMS_OFF;
 712        struct drm_connector *connector;
 713        struct drm_device *dev = encoder->dev;
 714
 715        list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 716                if (connector->encoder == encoder)
 717                        if (connector->dpms < dpms)
 718                                dpms = connector->dpms;
 719        return dpms;
 720}
 721
 722static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
 723{
 724        int dpms = DRM_MODE_DPMS_OFF;
 725        struct drm_connector *connector;
 726        struct drm_device *dev = crtc->dev;
 727
 728        list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 729                if (connector->encoder && connector->encoder->crtc == crtc)
 730                        if (connector->dpms < dpms)
 731                                dpms = connector->dpms;
 732        return dpms;
 733}
 734
 735/**
 736 * drm_helper_connector_dpms
 737 * @connector affected connector
 738 * @mode DPMS mode
 739 *
 740 * Calls the low-level connector DPMS function, then
 741 * calls appropriate encoder and crtc DPMS functions as well
 742 */
 743void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
 744{
 745        struct drm_encoder *encoder = connector->encoder;
 746        struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
 747        int old_dpms;
 748
 749        if (mode == connector->dpms)
 750                return;
 751
 752        old_dpms = connector->dpms;
 753        connector->dpms = mode;
 754
 755        /* from off to on, do crtc then encoder */
 756        if (mode < old_dpms) {
 757                if (crtc) {
 758                        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 759                        if (crtc_funcs->dpms)
 760                                (*crtc_funcs->dpms) (crtc,
 761                                                     drm_helper_choose_crtc_dpms(crtc));
 762                }
 763                if (encoder) {
 764                        struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 765                        if (encoder_funcs->dpms)
 766                                (*encoder_funcs->dpms) (encoder,
 767                                                        drm_helper_choose_encoder_dpms(encoder));
 768                }
 769        }
 770
 771        /* from on to off, do encoder then crtc */
 772        if (mode > old_dpms) {
 773                if (encoder) {
 774                        struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 775                        if (encoder_funcs->dpms)
 776                                (*encoder_funcs->dpms) (encoder,
 777                                                        drm_helper_choose_encoder_dpms(encoder));
 778                }
 779                if (crtc) {
 780                        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 781                        if (crtc_funcs->dpms)
 782                                (*crtc_funcs->dpms) (crtc,
 783                                                     drm_helper_choose_crtc_dpms(crtc));
 784                }
 785        }
 786
 787        return;
 788}
 789EXPORT_SYMBOL(drm_helper_connector_dpms);
 790
 791int 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}
 802EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
 803
 804int drm_helper_resume_force_mode(struct drm_device *dev)
 805{
 806        struct drm_crtc *crtc;
 807        struct drm_encoder *encoder;
 808        struct drm_encoder_helper_funcs *encoder_funcs;
 809        struct drm_crtc_helper_funcs *crtc_funcs;
 810        int ret;
 811
 812        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 813
 814                if (!crtc->enabled)
 815                        continue;
 816
 817                ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
 818                                               crtc->x, crtc->y, crtc->fb);
 819
 820                if (ret == false)
 821                        DRM_ERROR("failed to set mode on crtc %p\n", crtc);
 822
 823                /* Turn off outputs that were already powered off */
 824                if (drm_helper_choose_crtc_dpms(crtc)) {
 825                        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 826
 827                                if(encoder->crtc != crtc)
 828                                        continue;
 829
 830                                encoder_funcs = encoder->helper_private;
 831                                if (encoder_funcs->dpms)
 832                                        (*encoder_funcs->dpms) (encoder,
 833                                                                drm_helper_choose_encoder_dpms(encoder));
 834                        }
 835
 836                        crtc_funcs = crtc->helper_private;
 837                        if (crtc_funcs->dpms)
 838                                (*crtc_funcs->dpms) (crtc,
 839                                                     drm_helper_choose_crtc_dpms(crtc));
 840                }
 841        }
 842        /* disable the unused connectors while restoring the modesetting */
 843        drm_helper_disable_unused_functions(dev);
 844        return 0;
 845}
 846EXPORT_SYMBOL(drm_helper_resume_force_mode);
 847
 848#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
 849static void output_poll_execute(struct work_struct *work)
 850{
 851        struct delayed_work *delayed_work = to_delayed_work(work);
 852        struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
 853        struct drm_connector *connector;
 854        enum drm_connector_status old_status;
 855        bool repoll = false, changed = false;
 856
 857        if (!drm_kms_helper_poll)
 858                return;
 859
 860        mutex_lock(&dev->mode_config.mutex);
 861        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 862
 863                /* if this is HPD or polled don't check it -
 864                   TV out for instance */
 865                if (!connector->polled)
 866                        continue;
 867
 868                else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
 869                        repoll = true;
 870
 871                old_status = connector->status;
 872                /* if we are connected and don't want to poll for disconnect
 873                   skip it */
 874                if (old_status == connector_status_connected &&
 875                    !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
 876                    !(connector->polled & DRM_CONNECTOR_POLL_HPD))
 877                        continue;
 878
 879                connector->status = connector->funcs->detect(connector, false);
 880                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
 881                              connector->base.id,
 882                              drm_get_connector_name(connector),
 883                              old_status, connector->status);
 884                if (old_status != connector->status)
 885                        changed = true;
 886        }
 887
 888        mutex_unlock(&dev->mode_config.mutex);
 889
 890        if (changed) {
 891                /* send a uevent + call fbdev */
 892                drm_sysfs_hotplug_event(dev);
 893                if (dev->mode_config.funcs->output_poll_changed)
 894                        dev->mode_config.funcs->output_poll_changed(dev);
 895        }
 896
 897        if (repoll)
 898                queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD);
 899}
 900
 901void drm_kms_helper_poll_disable(struct drm_device *dev)
 902{
 903        if (!dev->mode_config.poll_enabled)
 904                return;
 905        cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
 906}
 907EXPORT_SYMBOL(drm_kms_helper_poll_disable);
 908
 909void drm_kms_helper_poll_enable(struct drm_device *dev)
 910{
 911        bool poll = false;
 912        struct drm_connector *connector;
 913
 914        if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
 915                return;
 916
 917        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 918                if (connector->polled)
 919                        poll = true;
 920        }
 921
 922        if (poll)
 923                queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
 924}
 925EXPORT_SYMBOL(drm_kms_helper_poll_enable);
 926
 927void drm_kms_helper_poll_init(struct drm_device *dev)
 928{
 929        INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
 930        dev->mode_config.poll_enabled = true;
 931
 932        drm_kms_helper_poll_enable(dev);
 933}
 934EXPORT_SYMBOL(drm_kms_helper_poll_init);
 935
 936void drm_kms_helper_poll_fini(struct drm_device *dev)
 937{
 938        drm_kms_helper_poll_disable(dev);
 939}
 940EXPORT_SYMBOL(drm_kms_helper_poll_fini);
 941
 942void drm_helper_hpd_irq_event(struct drm_device *dev)
 943{
 944        if (!dev->mode_config.poll_enabled)
 945                return;
 946
 947        /* kill timer and schedule immediate execution, this doesn't block */
 948        cancel_delayed_work(&dev->mode_config.output_poll_work);
 949        if (drm_kms_helper_poll)
 950                queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
 951}
 952EXPORT_SYMBOL(drm_helper_hpd_irq_event);
 953
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.