linux/drivers/gpu/drm/nouveau/nouveau_display.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008 Maarten Maathuis.
   3 * All Rights Reserved.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining
   6 * a copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sublicense, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * The above copyright notice and this permission notice (including the
  14 * next paragraph) shall be included in all copies or substantial
  15 * portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24 *
  25 */
  26
  27#include <acpi/video.h>
  28#include <drm/drmP.h>
  29#include <drm/drm_atomic.h>
  30#include <drm/drm_atomic_helper.h>
  31#include <drm/drm_crtc_helper.h>
  32#include <drm/drm_fb_helper.h>
  33
  34#include <nvif/class.h>
  35
  36#include "nouveau_fbcon.h"
  37#include "dispnv04/hw.h"
  38#include "nouveau_crtc.h"
  39#include "nouveau_dma.h"
  40#include "nouveau_gem.h"
  41#include "nouveau_connector.h"
  42#include "nv50_display.h"
  43
  44#include "nouveau_fence.h"
  45
  46#include <nvif/cl0046.h>
  47#include <nvif/event.h>
  48
  49static int
  50nouveau_display_vblank_handler(struct nvif_notify *notify)
  51{
  52        struct nouveau_crtc *nv_crtc =
  53                container_of(notify, typeof(*nv_crtc), vblank);
  54        drm_crtc_handle_vblank(&nv_crtc->base);
  55        return NVIF_NOTIFY_KEEP;
  56}
  57
  58int
  59nouveau_display_vblank_enable(struct drm_device *dev, unsigned int pipe)
  60{
  61        struct drm_crtc *crtc;
  62        struct nouveau_crtc *nv_crtc;
  63
  64        crtc = drm_crtc_from_index(dev, pipe);
  65        if (!crtc)
  66                return -EINVAL;
  67
  68        nv_crtc = nouveau_crtc(crtc);
  69        nvif_notify_get(&nv_crtc->vblank);
  70
  71        return 0;
  72}
  73
  74void
  75nouveau_display_vblank_disable(struct drm_device *dev, unsigned int pipe)
  76{
  77        struct drm_crtc *crtc;
  78        struct nouveau_crtc *nv_crtc;
  79
  80        crtc = drm_crtc_from_index(dev, pipe);
  81        if (!crtc)
  82                return;
  83
  84        nv_crtc = nouveau_crtc(crtc);
  85        nvif_notify_put(&nv_crtc->vblank);
  86}
  87
  88static inline int
  89calc(int blanks, int blanke, int total, int line)
  90{
  91        if (blanke >= blanks) {
  92                if (line >= blanks)
  93                        line -= total;
  94        } else {
  95                if (line >= blanks)
  96                        line -= total;
  97                line -= blanke + 1;
  98        }
  99        return line;
 100}
 101
 102static bool
 103nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
 104                                ktime_t *stime, ktime_t *etime)
 105{
 106        struct {
 107                struct nv04_disp_mthd_v0 base;
 108                struct nv04_disp_scanoutpos_v0 scan;
 109        } args = {
 110                .base.method = NV04_DISP_SCANOUTPOS,
 111                .base.head = nouveau_crtc(crtc)->index,
 112        };
 113        struct nouveau_display *disp = nouveau_display(crtc->dev);
 114        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
 115        int retry = 20;
 116        bool ret = false;
 117
 118        do {
 119                ret = nvif_mthd(&disp->disp.object, 0, &args, sizeof(args));
 120                if (ret != 0)
 121                        return false;
 122
 123                if (args.scan.vline) {
 124                        ret = true;
 125                        break;
 126                }
 127
 128                if (retry) ndelay(vblank->linedur_ns);
 129        } while (retry--);
 130
 131        *hpos = args.scan.hline;
 132        *vpos = calc(args.scan.vblanks, args.scan.vblanke,
 133                     args.scan.vtotal, args.scan.vline);
 134        if (stime) *stime = ns_to_ktime(args.scan.time[0]);
 135        if (etime) *etime = ns_to_ktime(args.scan.time[1]);
 136
 137        return ret;
 138}
 139
 140bool
 141nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
 142                           bool in_vblank_irq, int *vpos, int *hpos,
 143                           ktime_t *stime, ktime_t *etime,
 144                           const struct drm_display_mode *mode)
 145{
 146        struct drm_crtc *crtc;
 147
 148        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 149                if (nouveau_crtc(crtc)->index == pipe) {
 150                        return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
 151                                                               stime, etime);
 152                }
 153        }
 154
 155        return false;
 156}
 157
 158static void
 159nouveau_display_vblank_fini(struct drm_device *dev)
 160{
 161        struct drm_crtc *crtc;
 162
 163        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 164                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 165                nvif_notify_fini(&nv_crtc->vblank);
 166        }
 167}
 168
 169static int
 170nouveau_display_vblank_init(struct drm_device *dev)
 171{
 172        struct nouveau_display *disp = nouveau_display(dev);
 173        struct drm_crtc *crtc;
 174        int ret;
 175
 176        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 177                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 178                ret = nvif_notify_init(&disp->disp.object,
 179                                       nouveau_display_vblank_handler, false,
 180                                       NV04_DISP_NTFY_VBLANK,
 181                                       &(struct nvif_notify_head_req_v0) {
 182                                        .head = nv_crtc->index,
 183                                       },
 184                                       sizeof(struct nvif_notify_head_req_v0),
 185                                       sizeof(struct nvif_notify_head_rep_v0),
 186                                       &nv_crtc->vblank);
 187                if (ret) {
 188                        nouveau_display_vblank_fini(dev);
 189                        return ret;
 190                }
 191        }
 192
 193        ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 194        if (ret) {
 195                nouveau_display_vblank_fini(dev);
 196                return ret;
 197        }
 198
 199        return 0;
 200}
 201
 202static void
 203nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
 204{
 205        struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
 206
 207        if (fb->nvbo)
 208                drm_gem_object_put_unlocked(&fb->nvbo->gem);
 209
 210        drm_framebuffer_cleanup(drm_fb);
 211        kfree(fb);
 212}
 213
 214static int
 215nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
 216                                       struct drm_file *file_priv,
 217                                       unsigned int *handle)
 218{
 219        struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
 220
 221        return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle);
 222}
 223
 224static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
 225        .destroy = nouveau_user_framebuffer_destroy,
 226        .create_handle = nouveau_user_framebuffer_create_handle,
 227};
 228
 229int
 230nouveau_framebuffer_new(struct drm_device *dev,
 231                        const struct drm_mode_fb_cmd2 *mode_cmd,
 232                        struct nouveau_bo *nvbo,
 233                        struct nouveau_framebuffer **pfb)
 234{
 235        struct nouveau_drm *drm = nouveau_drm(dev);
 236        struct nouveau_framebuffer *fb;
 237        int ret;
 238
 239        /* YUV overlays have special requirements pre-NV50 */
 240        if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA &&
 241
 242            (mode_cmd->pixel_format == DRM_FORMAT_YUYV ||
 243             mode_cmd->pixel_format == DRM_FORMAT_UYVY ||
 244             mode_cmd->pixel_format == DRM_FORMAT_NV12 ||
 245             mode_cmd->pixel_format == DRM_FORMAT_NV21) &&
 246            (mode_cmd->pitches[0] & 0x3f || /* align 64 */
 247             mode_cmd->pitches[0] >= 0x10000 || /* at most 64k pitch */
 248             (mode_cmd->pitches[1] && /* pitches for planes must match */
 249              mode_cmd->pitches[0] != mode_cmd->pitches[1]))) {
 250                struct drm_format_name_buf format_name;
 251                DRM_DEBUG_KMS("Unsuitable framebuffer: format: %s; pitches: 0x%x\n 0x%x\n",
 252                              drm_get_format_name(mode_cmd->pixel_format,
 253                                                  &format_name),
 254                              mode_cmd->pitches[0],
 255                              mode_cmd->pitches[1]);
 256                return -EINVAL;
 257        }
 258
 259        if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
 260                return -ENOMEM;
 261
 262        drm_helper_mode_fill_fb_struct(dev, &fb->base, mode_cmd);
 263        fb->nvbo = nvbo;
 264
 265        ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs);
 266        if (ret)
 267                kfree(fb);
 268        return ret;
 269}
 270
 271struct drm_framebuffer *
 272nouveau_user_framebuffer_create(struct drm_device *dev,
 273                                struct drm_file *file_priv,
 274                                const struct drm_mode_fb_cmd2 *mode_cmd)
 275{
 276        struct nouveau_framebuffer *fb;
 277        struct nouveau_bo *nvbo;
 278        struct drm_gem_object *gem;
 279        int ret;
 280
 281        gem = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
 282        if (!gem)
 283                return ERR_PTR(-ENOENT);
 284        nvbo = nouveau_gem_object(gem);
 285
 286        ret = nouveau_framebuffer_new(dev, mode_cmd, nvbo, &fb);
 287        if (ret == 0)
 288                return &fb->base;
 289
 290        drm_gem_object_put_unlocked(gem);
 291        return ERR_PTR(ret);
 292}
 293
 294static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
 295        .fb_create = nouveau_user_framebuffer_create,
 296        .output_poll_changed = nouveau_fbcon_output_poll_changed,
 297};
 298
 299
 300struct nouveau_drm_prop_enum_list {
 301        u8 gen_mask;
 302        int type;
 303        char *name;
 304};
 305
 306static struct nouveau_drm_prop_enum_list underscan[] = {
 307        { 6, UNDERSCAN_AUTO, "auto" },
 308        { 6, UNDERSCAN_OFF, "off" },
 309        { 6, UNDERSCAN_ON, "on" },
 310        {}
 311};
 312
 313static struct nouveau_drm_prop_enum_list dither_mode[] = {
 314        { 7, DITHERING_MODE_AUTO, "auto" },
 315        { 7, DITHERING_MODE_OFF, "off" },
 316        { 1, DITHERING_MODE_ON, "on" },
 317        { 6, DITHERING_MODE_STATIC2X2, "static 2x2" },
 318        { 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" },
 319        { 4, DITHERING_MODE_TEMPORAL, "temporal" },
 320        {}
 321};
 322
 323static struct nouveau_drm_prop_enum_list dither_depth[] = {
 324        { 6, DITHERING_DEPTH_AUTO, "auto" },
 325        { 6, DITHERING_DEPTH_6BPC, "6 bpc" },
 326        { 6, DITHERING_DEPTH_8BPC, "8 bpc" },
 327        {}
 328};
 329
 330#define PROP_ENUM(p,gen,n,list) do {                                           \
 331        struct nouveau_drm_prop_enum_list *l = (list);                         \
 332        int c = 0;                                                             \
 333        while (l->gen_mask) {                                                  \
 334                if (l->gen_mask & (1 << (gen)))                                \
 335                        c++;                                                   \
 336                l++;                                                           \
 337        }                                                                      \
 338        if (c) {                                                               \
 339                p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c);        \
 340                l = (list);                                                    \
 341                while (p && l->gen_mask) {                                     \
 342                        if (l->gen_mask & (1 << (gen))) {                      \
 343                                drm_property_add_enum(p, l->type, l->name);    \
 344                        }                                                      \
 345                        l++;                                                   \
 346                }                                                              \
 347        }                                                                      \
 348} while(0)
 349
 350static void
 351nouveau_display_hpd_work(struct work_struct *work)
 352{
 353        struct nouveau_drm *drm = container_of(work, typeof(*drm), hpd_work);
 354
 355        pm_runtime_get_sync(drm->dev->dev);
 356
 357        drm_helper_hpd_irq_event(drm->dev);
 358
 359        pm_runtime_mark_last_busy(drm->dev->dev);
 360        pm_runtime_put_sync(drm->dev->dev);
 361}
 362
 363#ifdef CONFIG_ACPI
 364
 365/*
 366 * Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch
 367 * to the acpi subsys to move it there from drivers/acpi/acpi_video.c .
 368 * This should be dropped once that is merged.
 369 */
 370#ifndef ACPI_VIDEO_NOTIFY_PROBE
 371#define ACPI_VIDEO_NOTIFY_PROBE                 0x81
 372#endif
 373
 374static int
 375nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
 376                          void *data)
 377{
 378        struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
 379        struct acpi_bus_event *info = data;
 380        int ret;
 381
 382        if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
 383                if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
 384                        ret = pm_runtime_get(drm->dev->dev);
 385                        if (ret == 1 || ret == -EACCES) {
 386                                /* If the GPU is already awake, or in a state
 387                                 * where we can't wake it up, it can handle
 388                                 * it's own hotplug events.
 389                                 */
 390                                pm_runtime_put_autosuspend(drm->dev->dev);
 391                        } else if (ret == 0) {
 392                                /* This may be the only indication we receive
 393                                 * of a connector hotplug on a runtime
 394                                 * suspended GPU, schedule hpd_work to check.
 395                                 */
 396                                NV_DEBUG(drm, "ACPI requested connector reprobe\n");
 397                                schedule_work(&drm->hpd_work);
 398                                pm_runtime_put_noidle(drm->dev->dev);
 399                        } else {
 400                                NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n",
 401                                        ret);
 402                        }
 403
 404                        /* acpi-video should not generate keypresses for this */
 405                        return NOTIFY_BAD;
 406                }
 407        }
 408
 409        return NOTIFY_DONE;
 410}
 411#endif
 412
 413int
 414nouveau_display_init(struct drm_device *dev)
 415{
 416        struct nouveau_display *disp = nouveau_display(dev);
 417        struct nouveau_drm *drm = nouveau_drm(dev);
 418        struct drm_connector *connector;
 419        struct drm_connector_list_iter conn_iter;
 420        int ret;
 421
 422        ret = disp->init(dev);
 423        if (ret)
 424                return ret;
 425
 426        /* enable connector detection and polling for connectors without HPD
 427         * support
 428         */
 429        drm_kms_helper_poll_enable(dev);
 430
 431        /* enable hotplug interrupts */
 432        drm_connector_list_iter_begin(dev, &conn_iter);
 433        nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
 434                struct nouveau_connector *conn = nouveau_connector(connector);
 435                nvif_notify_get(&conn->hpd);
 436        }
 437        drm_connector_list_iter_end(&conn_iter);
 438
 439        /* enable flip completion events */
 440        nvif_notify_get(&drm->flip);
 441        return ret;
 442}
 443
 444void
 445nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
 446{
 447        struct nouveau_display *disp = nouveau_display(dev);
 448        struct nouveau_drm *drm = nouveau_drm(dev);
 449        struct drm_connector *connector;
 450        struct drm_connector_list_iter conn_iter;
 451
 452        if (!suspend) {
 453                if (drm_drv_uses_atomic_modeset(dev))
 454                        drm_atomic_helper_shutdown(dev);
 455                else
 456                        drm_crtc_force_disable_all(dev);
 457        }
 458
 459        /* disable flip completion events */
 460        nvif_notify_put(&drm->flip);
 461
 462        /* disable hotplug interrupts */
 463        drm_connector_list_iter_begin(dev, &conn_iter);
 464        nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
 465                struct nouveau_connector *conn = nouveau_connector(connector);
 466                nvif_notify_put(&conn->hpd);
 467        }
 468        drm_connector_list_iter_end(&conn_iter);
 469
 470        if (!runtime)
 471                cancel_work_sync(&drm->hpd_work);
 472
 473        drm_kms_helper_poll_disable(dev);
 474        disp->fini(dev);
 475}
 476
 477static void
 478nouveau_display_create_properties(struct drm_device *dev)
 479{
 480        struct nouveau_display *disp = nouveau_display(dev);
 481        int gen;
 482
 483        if (disp->disp.object.oclass < NV50_DISP)
 484                gen = 0;
 485        else
 486        if (disp->disp.object.oclass < GF110_DISP)
 487                gen = 1;
 488        else
 489                gen = 2;
 490
 491        PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode);
 492        PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth);
 493        PROP_ENUM(disp->underscan_property, gen, "underscan", underscan);
 494
 495        disp->underscan_hborder_property =
 496                drm_property_create_range(dev, 0, "underscan hborder", 0, 128);
 497
 498        disp->underscan_vborder_property =
 499                drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
 500
 501        if (gen < 1)
 502                return;
 503
 504        /* -90..+90 */
 505        disp->vibrant_hue_property =
 506                drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
 507
 508        /* -100..+100 */
 509        disp->color_vibrance_property =
 510                drm_property_create_range(dev, 0, "color vibrance", 0, 200);
 511}
 512
 513int
 514nouveau_display_create(struct drm_device *dev)
 515{
 516        struct nouveau_drm *drm = nouveau_drm(dev);
 517        struct nvkm_device *device = nvxx_device(&drm->client.device);
 518        struct nouveau_display *disp;
 519        int ret;
 520
 521        disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
 522        if (!disp)
 523                return -ENOMEM;
 524
 525        drm_mode_config_init(dev);
 526        drm_mode_create_scaling_mode_property(dev);
 527        drm_mode_create_dvi_i_properties(dev);
 528
 529        dev->mode_config.funcs = &nouveau_mode_config_funcs;
 530        dev->mode_config.fb_base = device->func->resource_addr(device, 1);
 531
 532        dev->mode_config.min_width = 0;
 533        dev->mode_config.min_height = 0;
 534        if (drm->client.device.info.family < NV_DEVICE_INFO_V0_CELSIUS) {
 535                dev->mode_config.max_width = 2048;
 536                dev->mode_config.max_height = 2048;
 537        } else
 538        if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
 539                dev->mode_config.max_width = 4096;
 540                dev->mode_config.max_height = 4096;
 541        } else
 542        if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI) {
 543                dev->mode_config.max_width = 8192;
 544                dev->mode_config.max_height = 8192;
 545        } else {
 546                dev->mode_config.max_width = 16384;
 547                dev->mode_config.max_height = 16384;
 548        }
 549
 550        dev->mode_config.preferred_depth = 24;
 551        dev->mode_config.prefer_shadow = 1;
 552
 553        if (drm->client.device.info.chipset < 0x11)
 554                dev->mode_config.async_page_flip = false;
 555        else
 556                dev->mode_config.async_page_flip = true;
 557
 558        drm_kms_helper_poll_init(dev);
 559        drm_kms_helper_poll_disable(dev);
 560
 561        if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
 562                ret = nvif_disp_ctor(&drm->client.device, 0, &disp->disp);
 563                if (ret == 0) {
 564                        nouveau_display_create_properties(dev);
 565                        if (disp->disp.object.oclass < NV50_DISP)
 566                                ret = nv04_display_create(dev);
 567                        else
 568                                ret = nv50_display_create(dev);
 569                }
 570        } else {
 571                ret = 0;
 572        }
 573
 574        if (ret)
 575                goto disp_create_err;
 576
 577        drm_mode_config_reset(dev);
 578
 579        if (dev->mode_config.num_crtc) {
 580                ret = nouveau_display_vblank_init(dev);
 581                if (ret)
 582                        goto vblank_err;
 583        }
 584
 585        INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
 586#ifdef CONFIG_ACPI
 587        drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
 588        register_acpi_notifier(&drm->acpi_nb);
 589#endif
 590
 591        return 0;
 592
 593vblank_err:
 594        disp->dtor(dev);
 595disp_create_err:
 596        drm_kms_helper_poll_fini(dev);
 597        drm_mode_config_cleanup(dev);
 598        return ret;
 599}
 600
 601void
 602nouveau_display_destroy(struct drm_device *dev)
 603{
 604        struct nouveau_display *disp = nouveau_display(dev);
 605
 606#ifdef CONFIG_ACPI
 607        unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
 608#endif
 609        nouveau_display_vblank_fini(dev);
 610
 611        drm_kms_helper_poll_fini(dev);
 612        drm_mode_config_cleanup(dev);
 613
 614        if (disp->dtor)
 615                disp->dtor(dev);
 616
 617        nvif_disp_dtor(&disp->disp);
 618
 619        nouveau_drm(dev)->display = NULL;
 620        kfree(disp);
 621}
 622
 623int
 624nouveau_display_suspend(struct drm_device *dev, bool runtime)
 625{
 626        struct nouveau_display *disp = nouveau_display(dev);
 627        struct drm_crtc *crtc;
 628
 629        if (drm_drv_uses_atomic_modeset(dev)) {
 630                if (!runtime) {
 631                        disp->suspend = drm_atomic_helper_suspend(dev);
 632                        if (IS_ERR(disp->suspend)) {
 633                                int ret = PTR_ERR(disp->suspend);
 634                                disp->suspend = NULL;
 635                                return ret;
 636                        }
 637                }
 638
 639                nouveau_display_fini(dev, true, runtime);
 640                return 0;
 641        }
 642
 643        nouveau_display_fini(dev, true, runtime);
 644
 645        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 646                struct nouveau_framebuffer *nouveau_fb;
 647
 648                nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
 649                if (!nouveau_fb || !nouveau_fb->nvbo)
 650                        continue;
 651
 652                nouveau_bo_unpin(nouveau_fb->nvbo);
 653        }
 654
 655        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 656                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 657                if (nv_crtc->cursor.nvbo) {
 658                        if (nv_crtc->cursor.set_offset)
 659                                nouveau_bo_unmap(nv_crtc->cursor.nvbo);
 660                        nouveau_bo_unpin(nv_crtc->cursor.nvbo);
 661                }
 662        }
 663
 664        return 0;
 665}
 666
 667void
 668nouveau_display_resume(struct drm_device *dev, bool runtime)
 669{
 670        struct nouveau_display *disp = nouveau_display(dev);
 671        struct nouveau_drm *drm = nouveau_drm(dev);
 672        struct drm_crtc *crtc;
 673        int ret;
 674
 675        if (drm_drv_uses_atomic_modeset(dev)) {
 676                nouveau_display_init(dev);
 677                if (disp->suspend) {
 678                        drm_atomic_helper_resume(dev, disp->suspend);
 679                        disp->suspend = NULL;
 680                }
 681                return;
 682        }
 683
 684        /* re-pin fb/cursors */
 685        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 686                struct nouveau_framebuffer *nouveau_fb;
 687
 688                nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
 689                if (!nouveau_fb || !nouveau_fb->nvbo)
 690                        continue;
 691
 692                ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM, true);
 693                if (ret)
 694                        NV_ERROR(drm, "Could not pin framebuffer\n");
 695        }
 696
 697        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 698                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 699                if (!nv_crtc->cursor.nvbo)
 700                        continue;
 701
 702                ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true);
 703                if (!ret && nv_crtc->cursor.set_offset)
 704                        ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
 705                if (ret)
 706                        NV_ERROR(drm, "Could not pin/map cursor.\n");
 707        }
 708
 709        nouveau_display_init(dev);
 710
 711        /* Force CLUT to get re-loaded during modeset */
 712        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 713                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 714
 715                nv_crtc->lut.depth = 0;
 716        }
 717
 718        /* This should ensure we don't hit a locking problem when someone
 719         * wakes us up via a connector.  We should never go into suspend
 720         * while the display is on anyways.
 721         */
 722        if (runtime)
 723                return;
 724
 725        drm_helper_resume_force_mode(dev);
 726
 727        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 728                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 729
 730                if (!nv_crtc->cursor.nvbo)
 731                        continue;
 732
 733                if (nv_crtc->cursor.set_offset)
 734                        nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
 735                nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
 736                                                 nv_crtc->cursor_saved_y);
 737        }
 738}
 739
 740static int
 741nouveau_page_flip_emit(struct nouveau_channel *chan,
 742                       struct nouveau_bo *old_bo,
 743                       struct nouveau_bo *new_bo,
 744                       struct nouveau_page_flip_state *s,
 745                       struct nouveau_fence **pfence)
 746{
 747        struct nouveau_fence_chan *fctx = chan->fence;
 748        struct nouveau_drm *drm = chan->drm;
 749        struct drm_device *dev = drm->dev;
 750        unsigned long flags;
 751        int ret;
 752
 753        /* Queue it to the pending list */
 754        spin_lock_irqsave(&dev->event_lock, flags);
 755        list_add_tail(&s->head, &fctx->flip);
 756        spin_unlock_irqrestore(&dev->event_lock, flags);
 757
 758        /* Synchronize with the old framebuffer */
 759        ret = nouveau_fence_sync(old_bo, chan, false, false);
 760        if (ret)
 761                goto fail;
 762
 763        /* Emit the pageflip */
 764        ret = RING_SPACE(chan, 2);
 765        if (ret)
 766                goto fail;
 767
 768        BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
 769        OUT_RING  (chan, 0x00000000);
 770        FIRE_RING (chan);
 771
 772        ret = nouveau_fence_new(chan, false, pfence);
 773        if (ret)
 774                goto fail;
 775
 776        return 0;
 777fail:
 778        spin_lock_irqsave(&dev->event_lock, flags);
 779        list_del(&s->head);
 780        spin_unlock_irqrestore(&dev->event_lock, flags);
 781        return ret;
 782}
 783
 784int
 785nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 786                       struct drm_pending_vblank_event *event, u32 flags,
 787                       struct drm_modeset_acquire_ctx *ctx)
 788{
 789        const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
 790        struct drm_device *dev = crtc->dev;
 791        struct nouveau_drm *drm = nouveau_drm(dev);
 792        struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
 793        struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
 794        struct nouveau_page_flip_state *s;
 795        struct nouveau_channel *chan;
 796        struct nouveau_cli *cli;
 797        struct nouveau_fence *fence;
 798        struct nv04_display *dispnv04 = nv04_display(dev);
 799        int head = nouveau_crtc(crtc)->index;
 800        int ret;
 801
 802        chan = drm->channel;
 803        if (!chan)
 804                return -ENODEV;
 805        cli = (void *)chan->user.client;
 806
 807        s = kzalloc(sizeof(*s), GFP_KERNEL);
 808        if (!s)
 809                return -ENOMEM;
 810
 811        if (new_bo != old_bo) {
 812                ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM, true);
 813                if (ret)
 814                        goto fail_free;
 815        }
 816
 817        mutex_lock(&cli->mutex);
 818        ret = ttm_bo_reserve(&new_bo->bo, true, false, NULL);
 819        if (ret)
 820                goto fail_unpin;
 821
 822        /* synchronise rendering channel with the kernel's channel */
 823        ret = nouveau_fence_sync(new_bo, chan, false, true);
 824        if (ret) {
 825                ttm_bo_unreserve(&new_bo->bo);
 826                goto fail_unpin;
 827        }
 828
 829        if (new_bo != old_bo) {
 830                ttm_bo_unreserve(&new_bo->bo);
 831
 832                ret = ttm_bo_reserve(&old_bo->bo, true, false, NULL);
 833                if (ret)
 834                        goto fail_unpin;
 835        }
 836
 837        /* Initialize a page flip struct */
 838        *s = (struct nouveau_page_flip_state)
 839                { { }, event, crtc, fb->format->cpp[0] * 8, fb->pitches[0],
 840                  new_bo->bo.offset };
 841
 842        /* Keep vblanks on during flip, for the target crtc of this flip */
 843        drm_crtc_vblank_get(crtc);
 844
 845        /* Emit a page flip */
 846        if (swap_interval) {
 847                ret = RING_SPACE(chan, 8);
 848                if (ret)
 849                        goto fail_unreserve;
 850
 851                BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
 852                OUT_RING  (chan, 0);
 853                BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
 854                OUT_RING  (chan, head);
 855                BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
 856                OUT_RING  (chan, 0);
 857                BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
 858                OUT_RING  (chan, 0);
 859        }
 860
 861        nouveau_bo_ref(new_bo, &dispnv04->image[head]);
 862
 863        ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
 864        if (ret)
 865                goto fail_unreserve;
 866        mutex_unlock(&cli->mutex);
 867
 868        /* Update the crtc struct and cleanup */
 869        crtc->primary->fb = fb;
 870
 871        nouveau_bo_fence(old_bo, fence, false);
 872        ttm_bo_unreserve(&old_bo->bo);
 873        if (old_bo != new_bo)
 874                nouveau_bo_unpin(old_bo);
 875        nouveau_fence_unref(&fence);
 876        return 0;
 877
 878fail_unreserve:
 879        drm_crtc_vblank_put(crtc);
 880        ttm_bo_unreserve(&old_bo->bo);
 881fail_unpin:
 882        mutex_unlock(&cli->mutex);
 883        if (old_bo != new_bo)
 884                nouveau_bo_unpin(new_bo);
 885fail_free:
 886        kfree(s);
 887        return ret;
 888}
 889
 890int
 891nouveau_finish_page_flip(struct nouveau_channel *chan,
 892                         struct nouveau_page_flip_state *ps)
 893{
 894        struct nouveau_fence_chan *fctx = chan->fence;
 895        struct nouveau_drm *drm = chan->drm;
 896        struct drm_device *dev = drm->dev;
 897        struct nouveau_page_flip_state *s;
 898        unsigned long flags;
 899
 900        spin_lock_irqsave(&dev->event_lock, flags);
 901
 902        if (list_empty(&fctx->flip)) {
 903                NV_ERROR(drm, "unexpected pageflip\n");
 904                spin_unlock_irqrestore(&dev->event_lock, flags);
 905                return -EINVAL;
 906        }
 907
 908        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
 909        if (s->event) {
 910                drm_crtc_arm_vblank_event(s->crtc, s->event);
 911        } else {
 912                /* Give up ownership of vblank for page-flipped crtc */
 913                drm_crtc_vblank_put(s->crtc);
 914        }
 915
 916        list_del(&s->head);
 917        if (ps)
 918                *ps = *s;
 919        kfree(s);
 920
 921        spin_unlock_irqrestore(&dev->event_lock, flags);
 922        return 0;
 923}
 924
 925int
 926nouveau_flip_complete(struct nvif_notify *notify)
 927{
 928        struct nouveau_drm *drm = container_of(notify, typeof(*drm), flip);
 929        struct nouveau_channel *chan = drm->channel;
 930        struct nouveau_page_flip_state state;
 931
 932        if (!nouveau_finish_page_flip(chan, &state)) {
 933                nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
 934                                 state.offset + state.crtc->y *
 935                                 state.pitch + state.crtc->x *
 936                                 state.bpp / 8);
 937        }
 938
 939        return NVIF_NOTIFY_KEEP;
 940}
 941
 942int
 943nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
 944                            struct drm_mode_create_dumb *args)
 945{
 946        struct nouveau_cli *cli = nouveau_cli(file_priv);
 947        struct nouveau_bo *bo;
 948        uint32_t domain;
 949        int ret;
 950
 951        args->pitch = roundup(args->width * (args->bpp / 8), 256);
 952        args->size = args->pitch * args->height;
 953        args->size = roundup(args->size, PAGE_SIZE);
 954
 955        /* Use VRAM if there is any ; otherwise fallback to system memory */
 956        if (nouveau_drm(dev)->client.device.info.ram_size != 0)
 957                domain = NOUVEAU_GEM_DOMAIN_VRAM;
 958        else
 959                domain = NOUVEAU_GEM_DOMAIN_GART;
 960
 961        ret = nouveau_gem_new(cli, args->size, 0, domain, 0, 0, &bo);
 962        if (ret)
 963                return ret;
 964
 965        ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
 966        drm_gem_object_put_unlocked(&bo->gem);
 967        return ret;
 968}
 969
 970int
 971nouveau_display_dumb_map_offset(struct drm_file *file_priv,
 972                                struct drm_device *dev,
 973                                uint32_t handle, uint64_t *poffset)
 974{
 975        struct drm_gem_object *gem;
 976
 977        gem = drm_gem_object_lookup(file_priv, handle);
 978        if (gem) {
 979                struct nouveau_bo *bo = nouveau_gem_object(gem);
 980                *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
 981                drm_gem_object_put_unlocked(gem);
 982                return 0;
 983        }
 984
 985        return -ENOENT;
 986}
 987