[go: nahoru, domu]

16ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/*
26ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Copyright (C) 2008 Maarten Maathuis.
36ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * All Rights Reserved.
46ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
56ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining
66ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * a copy of this software and associated documentation files (the
76ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * "Software"), to deal in the Software without restriction, including
86ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * without limitation the rights to use, copy, modify, merge, publish,
96ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * distribute, sublicense, and/or sell copies of the Software, and to
106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * permit persons to whom the Software is furnished to do so, subject to
116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the following conditions:
126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * The above copyright notice and this permission notice (including the
146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * next paragraph) shall be included in all copies or substantial
156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * portions of the Software.
166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */
266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
27760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/drmP.h>
28760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/drm_crtc_helper.h>
2977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
30fdb751ef2bbc78314d1e01d3425cfacfb19b9f86Ben Skeggs#include <nvif/class.h>
31fdb751ef2bbc78314d1e01d3425cfacfb19b9f86Ben Skeggs
326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "nouveau_fbcon.h"
331a6463425552a8b9960e5a19b25421895846925cBen Skeggs#include "dispnv04/hw.h"
34332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez#include "nouveau_crtc.h"
35332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez#include "nouveau_dma.h"
3677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs#include "nouveau_gem.h"
37de69185573586302ada2e59ba41835df36986277Ben Skeggs#include "nouveau_connector.h"
3845c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs#include "nv50_display.h"
396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
40ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs#include "nouveau_fence.h"
41ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs
4279ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs#include <nvif/event.h>
431d7c71a3e2f77336df536855b0efd2dc5bdeb41bBen Skeggs
4451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsstatic int
4580bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggsnouveau_display_vblank_handler(struct nvif_notify *notify)
4651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
4779ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs	struct nouveau_crtc *nv_crtc =
4879ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs		container_of(notify, typeof(*nv_crtc), vblank);
49b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index);
5080bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs	return NVIF_NOTIFY_KEEP;
5151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
5251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
5351cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsint
5451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsnouveau_display_vblank_enable(struct drm_device *dev, int head)
5551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
56b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	struct drm_crtc *crtc;
57b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
58b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
59b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		if (nv_crtc->index == head) {
6080bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs			nvif_notify_get(&nv_crtc->vblank);
61b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs			return 0;
62b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		}
6351cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
64b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	return -EINVAL;
6551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
6651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
6751cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsvoid
6851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsnouveau_display_vblank_disable(struct drm_device *dev, int head)
6951cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
70b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	struct drm_crtc *crtc;
71b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
72b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
73b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		if (nv_crtc->index == head) {
7480bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs			nvif_notify_put(&nv_crtc->vblank);
75b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs			return;
76b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		}
77b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	}
7851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
7951cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
80d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsstatic inline int
81d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggscalc(int blanks, int blanke, int total, int line)
82d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs{
83d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	if (blanke >= blanks) {
84d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (line >= blanks)
85d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			line -= total;
86d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	} else {
87d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (line >= blanks)
88d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			line -= total;
89d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		line -= blanke + 1;
90d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	}
91d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return line;
92d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
93d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
94d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsint
95d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsnouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
96d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs				ktime_t *stime, ktime_t *etime)
97d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs{
984952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	struct {
994952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		struct nv04_disp_mthd_v0 base;
1004952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		struct nv04_disp_scanoutpos_v0 scan;
1014952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	} args = {
1024952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		.base.method = NV04_DISP_SCANOUTPOS,
1034952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		.base.head = nouveau_crtc(crtc)->index,
1044952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	};
105d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct nouveau_display *disp = nouveau_display(crtc->dev);
106d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	int ret, retry = 1;
107d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
108d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	do {
1094952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
110d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (ret != 0)
111d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			return 0;
112d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
1134952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		if (args.scan.vline) {
114d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			ret |= DRM_SCANOUTPOS_ACCURATE;
115d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			ret |= DRM_SCANOUTPOS_VALID;
116d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			break;
117d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		}
118d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
119d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (retry) ndelay(crtc->linedur_ns);
120d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	} while (retry--);
121d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
1224952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	*hpos = args.scan.hline;
1234952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	*vpos = calc(args.scan.vblanks, args.scan.vblanke,
1244952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs		     args.scan.vtotal, args.scan.vline);
1254952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	if (stime) *stime = ns_to_ktime(args.scan.time[0]);
1264952b4d339033c2019bbd00f28f422b6fc340408Ben Skeggs	if (etime) *etime = ns_to_ktime(args.scan.time[1]);
127d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
128d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	if (*vpos < 0)
1293d3cbd84300e7be1e53083cac0f6f9c12978ecb4Daniel Vetter		ret |= DRM_SCANOUTPOS_IN_VBLANK;
130d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return ret;
131d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
132d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
133d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsint
134d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsnouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
135d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			   int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
136d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs{
137d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct drm_crtc *crtc;
138d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
139d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
140d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (nouveau_crtc(crtc)->index == head) {
141d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
142d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs							       stime, etime);
143d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		}
144d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	}
145d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
146d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return 0;
147d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
148d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
149d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsint
150d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsnouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
151d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			 struct timeval *time, unsigned flags)
152d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs{
153d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct drm_crtc *crtc;
154d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
155d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
156d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (nouveau_crtc(crtc)->index == head) {
157d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			return drm_calc_vbltimestamp_from_scanoutpos(dev,
158d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs					head, max_error, time, flags, crtc,
159d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs					&crtc->hwmode);
160d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		}
161d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	}
162d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
163d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return -EINVAL;
164d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
165d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
16651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsstatic void
16751cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsnouveau_display_vblank_fini(struct drm_device *dev)
16851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
169b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	struct drm_crtc *crtc;
17051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
1711139ffb96b3f4e8be9006552d2dd4d302d62c2eeBen Skeggs	drm_vblank_cleanup(dev);
1721139ffb96b3f4e8be9006552d2dd4d302d62c2eeBen Skeggs
173b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
174b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
17580bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs		nvif_notify_fini(&nv_crtc->vblank);
17651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
17751cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
17851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
17951cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsstatic int
18051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsnouveau_display_vblank_init(struct drm_device *dev)
18151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
18280bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
183b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	struct drm_crtc *crtc;
184b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	int ret;
18551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
186b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
187b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
18880bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs		ret = nvif_notify_init(&disp->disp, NULL,
18979ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       nouveau_display_vblank_handler, false,
19080bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs				       NV04_DISP_NTFY_VBLANK,
19179ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       &(struct nvif_notify_head_req_v0) {
19279ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs					.head = nv_crtc->index,
19379ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       },
19479ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       sizeof(struct nvif_notify_head_req_v0),
19579ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       sizeof(struct nvif_notify_head_rep_v0),
19679ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       &nv_crtc->vblank);
19751cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		if (ret) {
19851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs			nouveau_display_vblank_fini(dev);
19951cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs			return ret;
20051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		}
20151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
20251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
20351cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
20451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	if (ret) {
20551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		nouveau_display_vblank_fini(dev);
20651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		return ret;
20751cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
20851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
20951cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	return 0;
21051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
21151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
2126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic void
2136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
2146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
216ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	struct nouveau_display *disp = nouveau_display(drm_fb->dev);
217ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs
218ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	if (disp->fb_dtor)
219ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs		disp->fb_dtor(drm_fb);
2206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
221bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	if (fb->nvbo)
22255fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann		drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
2236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	drm_framebuffer_cleanup(drm_fb);
2256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	kfree(fb);
2266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic int
2296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
2306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				       struct drm_file *file_priv,
2316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				       unsigned int *handle)
2326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
2346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
23555fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann	return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle);
2366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
2396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	.destroy = nouveau_user_framebuffer_destroy,
2406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	.create_handle = nouveau_user_framebuffer_create_handle,
2416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs};
2426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
243386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlieint
24445c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggsnouveau_framebuffer_init(struct drm_device *dev,
24545c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs			 struct nouveau_framebuffer *nv_fb,
246308e5bcbdb10452e8aba31aa21432fb67ee46d72Jesse Barnes			 struct drm_mode_fb_cmd2 *mode_cmd,
24745c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs			 struct nouveau_bo *nvbo)
2486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
249ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
25045c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs	struct drm_framebuffer *fb = &nv_fb->base;
2516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	int ret;
2526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
25345c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
25445c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs	nv_fb->nvbo = nvbo;
25545c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs
256c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
257ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	if (ret)
258c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter		return ret;
259ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs
260ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	if (disp->fb_ctor) {
261ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs		ret = disp->fb_ctor(fb);
262ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs		if (ret)
263ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs			disp->fb_dtor(fb);
264c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter	}
265c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter
266ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	return ret;
2676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic struct drm_framebuffer *
2706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_user_framebuffer_create(struct drm_device *dev,
2716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				struct drm_file *file_priv,
272308e5bcbdb10452e8aba31aa21432fb67ee46d72Jesse Barnes				struct drm_mode_fb_cmd2 *mode_cmd)
2736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
274386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	struct nouveau_framebuffer *nouveau_fb;
2756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_gem_object *gem;
276fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	int ret = -ENOMEM;
2776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
278308e5bcbdb10452e8aba31aa21432fb67ee46d72Jesse Barnes	gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
2796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (!gem)
280cce13ff7596985903ad924504562190a2c163a63Chris Wilson		return ERR_PTR(-ENOENT);
2816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
282386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
283386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	if (!nouveau_fb)
284fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst		goto err_unref;
285386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie
286386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
287fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	if (ret)
288fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst		goto err;
2896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
290386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	return &nouveau_fb->base;
291fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst
292fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorsterr:
293fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	kfree(nouveau_fb);
294fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorsterr_unref:
295fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	drm_gem_object_unreference(gem);
296fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	return ERR_PTR(ret);
2976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
29927d5030a235d89842ed70e18d924f017b34a496dBen Skeggsstatic const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
3006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	.fb_create = nouveau_user_framebuffer_create,
301eb1f8e4f3be898df808e2dfc131099f5831d491dDave Airlie	.output_poll_changed = nouveau_fbcon_output_poll_changed,
3026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs};
3036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
304b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
3054a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstruct nouveau_drm_prop_enum_list {
306de69185573586302ada2e59ba41835df36986277Ben Skeggs	u8 gen_mask;
307b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	int type;
308b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	char *name;
309b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs};
310b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
3114a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstatic struct nouveau_drm_prop_enum_list underscan[] = {
3129285462273cbccb27187d5308ed95f94a9ceb1deBen Skeggs	{ 6, UNDERSCAN_AUTO, "auto" },
3139285462273cbccb27187d5308ed95f94a9ceb1deBen Skeggs	{ 6, UNDERSCAN_OFF, "off" },
3149285462273cbccb27187d5308ed95f94a9ceb1deBen Skeggs	{ 6, UNDERSCAN_ON, "on" },
315de69185573586302ada2e59ba41835df36986277Ben Skeggs	{}
316b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs};
317b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
3184a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstatic struct nouveau_drm_prop_enum_list dither_mode[] = {
319de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 7, DITHERING_MODE_AUTO, "auto" },
320de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 7, DITHERING_MODE_OFF, "off" },
321de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 1, DITHERING_MODE_ON, "on" },
322de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_MODE_STATIC2X2, "static 2x2" },
323de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" },
324de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 4, DITHERING_MODE_TEMPORAL, "temporal" },
325de69185573586302ada2e59ba41835df36986277Ben Skeggs	{}
326de69185573586302ada2e59ba41835df36986277Ben Skeggs};
327de69185573586302ada2e59ba41835df36986277Ben Skeggs
3284a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstatic struct nouveau_drm_prop_enum_list dither_depth[] = {
329de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_DEPTH_AUTO, "auto" },
330de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_DEPTH_6BPC, "6 bpc" },
331de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_DEPTH_8BPC, "8 bpc" },
332de69185573586302ada2e59ba41835df36986277Ben Skeggs	{}
333de69185573586302ada2e59ba41835df36986277Ben Skeggs};
334de69185573586302ada2e59ba41835df36986277Ben Skeggs
335de69185573586302ada2e59ba41835df36986277Ben Skeggs#define PROP_ENUM(p,gen,n,list) do {                                           \
3364a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauer	struct nouveau_drm_prop_enum_list *l = (list);                         \
337de69185573586302ada2e59ba41835df36986277Ben Skeggs	int c = 0;                                                             \
338de69185573586302ada2e59ba41835df36986277Ben Skeggs	while (l->gen_mask) {                                                  \
339de69185573586302ada2e59ba41835df36986277Ben Skeggs		if (l->gen_mask & (1 << (gen)))                                \
340de69185573586302ada2e59ba41835df36986277Ben Skeggs			c++;                                                   \
341de69185573586302ada2e59ba41835df36986277Ben Skeggs		l++;                                                           \
342de69185573586302ada2e59ba41835df36986277Ben Skeggs	}                                                                      \
343de69185573586302ada2e59ba41835df36986277Ben Skeggs	if (c) {                                                               \
344de69185573586302ada2e59ba41835df36986277Ben Skeggs		p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c);        \
345de69185573586302ada2e59ba41835df36986277Ben Skeggs		l = (list);                                                    \
346de69185573586302ada2e59ba41835df36986277Ben Skeggs		c = 0;                                                         \
347de69185573586302ada2e59ba41835df36986277Ben Skeggs		while (p && l->gen_mask) {                                     \
348de69185573586302ada2e59ba41835df36986277Ben Skeggs			if (l->gen_mask & (1 << (gen))) {                      \
349de69185573586302ada2e59ba41835df36986277Ben Skeggs				drm_property_add_enum(p, c, l->type, l->name); \
350de69185573586302ada2e59ba41835df36986277Ben Skeggs				c++;                                           \
351de69185573586302ada2e59ba41835df36986277Ben Skeggs			}                                                      \
352de69185573586302ada2e59ba41835df36986277Ben Skeggs			l++;                                                   \
353de69185573586302ada2e59ba41835df36986277Ben Skeggs		}                                                              \
354de69185573586302ada2e59ba41835df36986277Ben Skeggs	}                                                                      \
355de69185573586302ada2e59ba41835df36986277Ben Skeggs} while(0)
356de69185573586302ada2e59ba41835df36986277Ben Skeggs
357042206c0cd4924879c4292c5ffa2bf1e8023ae5aFrancisco Jerezint
358f62b27db6b5479efe376b408802a081a834ef50eBen Skeggsnouveau_display_init(struct drm_device *dev)
359f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs{
36077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
36152c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	struct drm_connector *connector;
362f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	int ret;
363f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
364f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	ret = disp->init(dev);
36552c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	if (ret)
36652c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs		return ret;
36752c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs
3687df898b1a70b13c3a8892625f4ead929d9554293Ben Skeggs	/* enable polling for external displays */
36952c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	drm_kms_helper_poll_enable(dev);
37052c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs
37152c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	/* enable hotplug interrupts */
37252c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
37352c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs		struct nouveau_connector *conn = nouveau_connector(connector);
37480bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs		nvif_notify_get(&conn->hpd);
375f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	}
376f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
377f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	return ret;
378f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs}
379f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
380f62b27db6b5479efe376b408802a081a834ef50eBen Skeggsvoid
381f62b27db6b5479efe376b408802a081a834ef50eBen Skeggsnouveau_display_fini(struct drm_device *dev)
382f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs{
38377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
38452c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	struct drm_connector *connector;
3859cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	int head;
3869cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner
3879cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	/* Make sure that drm and hw vblank irqs get properly disabled. */
3889cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	for (head = 0; head < dev->mode_config.num_crtc; head++)
3899cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner		drm_vblank_off(dev, head);
39052c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs
39152c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	/* disable hotplug interrupts */
39252c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
39352c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs		struct nouveau_connector *conn = nouveau_connector(connector);
39480bc340b3dd720c5b7818e21a9a1ee36e1d7ef30Ben Skeggs		nvif_notify_put(&conn->hpd);
39552c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	}
396f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
397f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	drm_kms_helper_poll_disable(dev);
398f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	disp->fini(dev);
399f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs}
400f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
4019c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsstatic void
4029c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsnouveau_display_create_properties(struct drm_device *dev)
40327d5030a235d89842ed70e18d924f017b34a496dBen Skeggs{
4049c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	struct nouveau_display *disp = nouveau_display(dev);
4059c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	int gen;
406de69185573586302ada2e59ba41835df36986277Ben Skeggs
407648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs	if (disp->disp.oclass < NV50_DISP)
408de69185573586302ada2e59ba41835df36986277Ben Skeggs		gen = 0;
409de69185573586302ada2e59ba41835df36986277Ben Skeggs	else
410648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs	if (disp->disp.oclass < GF110_DISP)
411de69185573586302ada2e59ba41835df36986277Ben Skeggs		gen = 1;
412de69185573586302ada2e59ba41835df36986277Ben Skeggs	else
413de69185573586302ada2e59ba41835df36986277Ben Skeggs		gen = 2;
414de69185573586302ada2e59ba41835df36986277Ben Skeggs
415de69185573586302ada2e59ba41835df36986277Ben Skeggs	PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode);
416de69185573586302ada2e59ba41835df36986277Ben Skeggs	PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth);
417de69185573586302ada2e59ba41835df36986277Ben Skeggs	PROP_ENUM(disp->underscan_property, gen, "underscan", underscan);
418b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
419b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	disp->underscan_hborder_property =
420d9bc3c02e36d844c2d980e65ddda5c7699e073f8Sascha Hauer		drm_property_create_range(dev, 0, "underscan hborder", 0, 128);
421b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
422b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	disp->underscan_vborder_property =
423d9bc3c02e36d844c2d980e65ddda5c7699e073f8Sascha Hauer		drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
424b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
4259c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	if (gen < 1)
4269c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		return;
427df26bc9c320602539b1b5b3d85786e4c8de7bf43Christoph Bumiller
4289c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	/* -90..+90 */
4299c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	disp->vibrant_hue_property =
4309c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
4319c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4329c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	/* -100..+100 */
4339c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	disp->color_vibrance_property =
4349c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		drm_property_create_range(dev, 0, "color vibrance", 0, 200);
4359c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs}
4369c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4379c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsint
4389c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsnouveau_display_create(struct drm_device *dev)
4399c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs{
4409c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
4419c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	struct nouveau_display *disp;
4429c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	int ret;
4439c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4449c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
4459c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	if (!disp)
4469c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		return -ENOMEM;
4479c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4489c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	drm_mode_config_init(dev);
4499c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	drm_mode_create_scaling_mode_property(dev);
4509c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	drm_mode_create_dvi_i_properties(dev);
451df26bc9c320602539b1b5b3d85786e4c8de7bf43Christoph Bumiller
452e6ecefaadfcdb03db8ac9e739b4ba7a93a8811b3Laurent Pinchart	dev->mode_config.funcs = &nouveau_mode_config_funcs;
453967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	dev->mode_config.fb_base = nv_device_resource_start(nvkm_device(&drm->device), 1);
45427d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
45527d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	dev->mode_config.min_width = 0;
45627d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	dev->mode_config.min_height = 0;
457967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family < NV_DEVICE_INFO_V0_CELSIUS) {
45827d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_width = 2048;
45927d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_height = 2048;
46027d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	} else
461967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
46227d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_width = 4096;
46327d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_height = 4096;
46427d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	} else {
46527d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_width = 8192;
46627d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_height = 8192;
46727d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	}
46827d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
469f1377998eede7a8caa124fcf6a589b02c9e2bac7Dave Airlie	dev->mode_config.preferred_depth = 24;
470f1377998eede7a8caa124fcf6a589b02c9e2bac7Dave Airlie	dev->mode_config.prefer_shadow = 1;
471f1377998eede7a8caa124fcf6a589b02c9e2bac7Dave Airlie
472967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.chipset < 0x11)
473b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		dev->mode_config.async_page_flip = false;
474b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs	else
475b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		dev->mode_config.async_page_flip = true;
476b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
477f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	drm_kms_helper_poll_init(dev);
478f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	drm_kms_helper_poll_disable(dev);
479f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
480771fa0e4d0c5cf6f5cfc915603e7a4a196346048Ben Skeggs	if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
4812332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		static const u16 oclass[] = {
482648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GM107_DISP,
483648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GK110_DISP,
484648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GK104_DISP,
485648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GF110_DISP,
486648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GT214_DISP,
487648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GT206_DISP,
488648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			GT200_DISP,
489648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			G82_DISP,
490648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			NV50_DISP,
491648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			NV04_DISP,
4922332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		};
4932332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		int i;
4942332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs
4952332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
4960ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs			ret = nvif_object_init(nvif_object(&drm->device), NULL,
4970ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs					       NVDRM_DISPLAY, oclass[i],
4980ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs					       NULL, 0, &disp->disp);
4992332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		}
5002332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs
5012332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		if (ret == 0) {
5029c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs			nouveau_display_create_properties(dev);
503648d4dfde721885737b33a06f2b73ee125acf271Ben Skeggs			if (disp->disp.oclass < NV50_DISP)
5042332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs				ret = nv04_display_create(dev);
5052332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			else
5062332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs				ret = nv50_display_create(dev);
5072332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		}
508fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	} else {
509fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs		ret = 0;
510fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	}
5119430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs
512fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	if (ret)
513fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs		goto disp_create_err;
5149430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs
515fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	if (dev->mode_config.num_crtc) {
51651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		ret = nouveau_display_vblank_init(dev);
517fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs		if (ret)
518fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs			goto vblank_err;
519f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	}
520f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
521fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	nouveau_backlight_init(dev);
5225ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz	return 0;
5235ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz
5245ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarzvblank_err:
52577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	disp->dtor(dev);
5265ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarzdisp_create_err:
5275ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz	drm_kms_helper_poll_fini(dev);
5285ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz	drm_mode_config_cleanup(dev);
5292a44e4997c5fee8e1da1589ff57e0bd1c53f03ceBen Skeggs	return ret;
53027d5030a235d89842ed70e18d924f017b34a496dBen Skeggs}
53127d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
53227d5030a235d89842ed70e18d924f017b34a496dBen Skeggsvoid
53327d5030a235d89842ed70e18d924f017b34a496dBen Skeggsnouveau_display_destroy(struct drm_device *dev)
53427d5030a235d89842ed70e18d924f017b34a496dBen Skeggs{
53577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
53627d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
53777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_backlight_exit(dev);
53851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	nouveau_display_vblank_fini(dev);
539f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
540d6bf2f370703c0cab60bf1f5bf871a3f00eb8872Ben Skeggs	drm_kms_helper_poll_fini(dev);
541d6bf2f370703c0cab60bf1f5bf871a3f00eb8872Ben Skeggs	drm_mode_config_cleanup(dev);
542d6bf2f370703c0cab60bf1f5bf871a3f00eb8872Ben Skeggs
5439430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs	if (disp->dtor)
5449430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs		disp->dtor(dev);
545f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
5460ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	nvif_object_fini(&disp->disp);
5472332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs
54877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_drm(dev)->display = NULL;
54977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	kfree(disp);
55077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs}
55177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
55277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggsint
5536fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggsnouveau_display_suspend(struct drm_device *dev, bool runtime)
55477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs{
55577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_crtc *crtc;
55677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
55777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_display_fini(dev);
55877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
55977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
56077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_framebuffer *nouveau_fb;
56177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
562f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
56377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (!nouveau_fb || !nouveau_fb->nvbo)
56477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			continue;
56577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
56677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_unpin(nouveau_fb->nvbo);
56777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
56877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
56977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
57077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
57177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
57277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_unmap(nv_crtc->cursor.nvbo);
57377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_unpin(nv_crtc->cursor.nvbo);
57477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
57577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
57677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	return 0;
57777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs}
57877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
57977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggsvoid
5806fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggsnouveau_display_resume(struct drm_device *dev, bool runtime)
58177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs{
58277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
58377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_crtc *crtc;
5846fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	int ret, head;
58577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
5866fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	/* re-pin fb/cursors */
58777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
58877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_framebuffer *nouveau_fb;
58977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
590f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
59177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (!nouveau_fb || !nouveau_fb->nvbo)
59277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			continue;
59377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
594c9a6fd97335e59a113b53390579379c27fe64ed4Ben Skeggs		ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
595c9a6fd97335e59a113b53390579379c27fe64ed4Ben Skeggs		if (ret)
596c9a6fd97335e59a113b53390579379c27fe64ed4Ben Skeggs			NV_ERROR(drm, "Could not pin framebuffer\n");
59777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
59877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
59977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
60077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
60177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
60277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
60377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (!ret)
60477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
60577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (ret)
60677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			NV_ERROR(drm, "Could not pin/map cursor.\n");
60777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
6089cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner
60977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_display_init(dev);
61077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
61177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	/* Force CLUT to get re-loaded during modeset */
61277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
61377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
61477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
61577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nv_crtc->lut.depth = 0;
61677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
61777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
6189cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	/* Make sure that drm and hw vblank irqs get resumed if needed. */
6199cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	for (head = 0; head < dev->mode_config.num_crtc; head++)
6209cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner		drm_vblank_on(dev, head);
6219cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner
6226fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	/* This should ensure we don't hit a locking problem when someone
6236fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	 * wakes us up via a connector.  We should never go into suspend
6246fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	 * while the display is on anyways.
6256fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	 */
6266fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs	if (runtime)
6276fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs		return;
6286fbb702e27d78ad2458df048b58cca3454bc0965Ben Skeggs
62977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	drm_helper_resume_force_mode(dev);
63077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
63177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
63277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
63377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		u32 offset = nv_crtc->cursor.nvbo->bo.offset;
63477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
63577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nv_crtc->cursor.set_offset(nv_crtc, offset);
63677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
63777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs						 nv_crtc->cursor_saved_y);
63877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
63927d5030a235d89842ed70e18d924f017b34a496dBen Skeggs}
64027d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
641332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezstatic int
642332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jereznouveau_page_flip_emit(struct nouveau_channel *chan,
643332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_bo *old_bo,
644332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_bo *new_bo,
645332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_page_flip_state *s,
646332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_fence **pfence)
647332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez{
648f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_fence_chan *fctx = chan->fence;
64977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = chan->drm;
65077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_device *dev = drm->dev;
651332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	unsigned long flags;
652332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	int ret;
653332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
654332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Queue it to the pending list */
655332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_lock_irqsave(&dev->event_lock, flags);
656f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	list_add_tail(&s->head, &fctx->flip);
657332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_unlock_irqrestore(&dev->event_lock, flags);
658332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
659332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Synchronize with the old framebuffer */
660e3be4c230dfadf79567a245505a47a90db97f968Maarten Lankhorst	ret = nouveau_fence_sync(old_bo, chan, false, false);
661332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
662332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail;
663332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
664332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Emit the pageflip */
6651e303c03af1e631de37ec77cc2513210910a812cBen Skeggs	ret = RING_SPACE(chan, 2);
666332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
667332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail;
668332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
669967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
6706d597027755b2eed4298b85ebe3cb5c93b29d1a9Ben Skeggs		BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
6711e303c03af1e631de37ec77cc2513210910a812cBen Skeggs	else
6721e303c03af1e631de37ec77cc2513210910a812cBen Skeggs		BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1);
6731e303c03af1e631de37ec77cc2513210910a812cBen Skeggs	OUT_RING  (chan, 0x00000000);
674bd2f2037a42d4657ead3be2918db22e63626cd35Ben Skeggs	FIRE_RING (chan);
675332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
676264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	ret = nouveau_fence_new(chan, false, pfence);
677332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
678332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail;
679332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
680332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return 0;
681332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezfail:
682332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_lock_irqsave(&dev->event_lock, flags);
683332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	list_del(&s->head);
684332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_unlock_irqrestore(&dev->event_lock, flags);
685332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return ret;
686332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez}
687332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
688332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezint
689332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jereznouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
690b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		       struct drm_pending_vblank_event *event, u32 flags)
691332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez{
692b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
693332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct drm_device *dev = crtc->dev;
69477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
695f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
696332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
697332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_page_flip_state *s;
6980ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	struct nouveau_channel *chan;
6990ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	struct nouveau_cli *cli;
700332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_fence *fence;
701332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	int ret;
702332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
7030ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	chan = drm->channel;
7040ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	if (!chan)
705332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		return -ENODEV;
7060ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	cli = (void *)nvif_client(&chan->device->base);
707332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
708332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	s = kzalloc(sizeof(*s), GFP_KERNEL);
709332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (!s)
710332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		return -ENOMEM;
711332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
712d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst	if (new_bo != old_bo) {
713d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst		ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
714d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst		if (ret)
715d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst			goto fail_free;
716d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst	}
717d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst
7180ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	mutex_lock(&cli->mutex);
719bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst	ret = ttm_bo_reserve(&new_bo->bo, true, false, false, NULL);
720eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	if (ret)
72109c3de135063f93d7137ad112f551f293b1204cfMaarten Lankhorst		goto fail_unpin;
722b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
723eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	/* synchronise rendering channel with the kernel's channel */
724e3be4c230dfadf79567a245505a47a90db97f968Maarten Lankhorst	ret = nouveau_fence_sync(new_bo, chan, false, true);
725bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst	if (ret) {
726bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst		ttm_bo_unreserve(&new_bo->bo);
727060810d7abaabcab282e062c595871d661561400Ben Skeggs		goto fail_unpin;
728bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst	}
729b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
730bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst	if (new_bo != old_bo) {
731bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst		ttm_bo_unreserve(&new_bo->bo);
732bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst
733bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst		ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);
734bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst		if (ret)
735bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst			goto fail_unpin;
736bdaf7ddf652ef51fd363b052e320711c06f6f553Maarten Lankhorst	}
737b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
738b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst	/* Initialize a page flip struct */
739b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst	*s = (struct nouveau_page_flip_state)
740b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		{ { }, event, nouveau_crtc(crtc)->index,
741b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		  fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y,
742b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		  new_bo->bo.offset };
743b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
744ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	/* Keep vblanks on during flip, for the target crtc of this flip */
745ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	drm_vblank_get(dev, nouveau_crtc(crtc)->index);
746ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner
747332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Emit a page flip */
748967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
749b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
750060810d7abaabcab282e062c595871d661561400Ben Skeggs		if (ret)
751d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs			goto fail_unreserve;
75278ae0ad403daf11cf63da86923d2b5dbeda3af8fBen Skeggs	} else {
75378ae0ad403daf11cf63da86923d2b5dbeda3af8fBen Skeggs		struct nv04_display *dispnv04 = nv04_display(dev);
754b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		int head = nouveau_crtc(crtc)->index;
755b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
756b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		if (swap_interval) {
757b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			ret = RING_SPACE(chan, 8);
758b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			if (ret)
759b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs				goto fail_unreserve;
760b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
761b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
762b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, 0);
763b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
764b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, head);
765b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
766b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, 0);
767b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
768b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, 0);
769b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		}
770b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
771b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		nouveau_bo_ref(new_bo, &dispnv04->image[head]);
772d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs	}
773d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs
774332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
775332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
776332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail_unreserve;
7770ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	mutex_unlock(&cli->mutex);
778332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
779332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Update the crtc struct and cleanup */
780f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper	crtc->primary->fb = fb;
781332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
782809e9447b92ffe1346b2d6ec390e212d5307f61cMaarten Lankhorst	nouveau_bo_fence(old_bo, fence, false);
78307ad6ca0d391758ae3bffa95554abbae6c84e641Ben Skeggs	ttm_bo_unreserve(&old_bo->bo);
784060810d7abaabcab282e062c595871d661561400Ben Skeggs	if (old_bo != new_bo)
785b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		nouveau_bo_unpin(old_bo);
786332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	nouveau_fence_unref(&fence);
787332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return 0;
788332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
789332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezfail_unreserve:
790ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	drm_vblank_put(dev, nouveau_crtc(crtc)->index);
79107ad6ca0d391758ae3bffa95554abbae6c84e641Ben Skeggs	ttm_bo_unreserve(&old_bo->bo);
792060810d7abaabcab282e062c595871d661561400Ben Skeggsfail_unpin:
7930ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	mutex_unlock(&cli->mutex);
794060810d7abaabcab282e062c595871d661561400Ben Skeggs	if (old_bo != new_bo)
795b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		nouveau_bo_unpin(new_bo);
796332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezfail_free:
797332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	kfree(s);
798332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return ret;
799332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez}
800332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
801332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezint
802332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jereznouveau_finish_page_flip(struct nouveau_channel *chan,
803332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez			 struct nouveau_page_flip_state *ps)
804332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez{
805f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_fence_chan *fctx = chan->fence;
80677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = chan->drm;
80777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_device *dev = drm->dev;
808332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_page_flip_state *s;
809332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	unsigned long flags;
810af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner	int crtcid = -1;
811332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
812332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_lock_irqsave(&dev->event_lock, flags);
813332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
814f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	if (list_empty(&fctx->flip)) {
81577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		NV_ERROR(drm, "unexpected pageflip\n");
816332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		spin_unlock_irqrestore(&dev->event_lock, flags);
817332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		return -EINVAL;
818332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	}
819332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
820f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
821af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner	if (s->event) {
822af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner		/* Vblank timestamps/counts are only correct on >= NV-50 */
823967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
824af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner			crtcid = s->crtc;
825af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner
826af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner		drm_send_vblank_event(dev, crtcid, s->event);
827af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner	}
828332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
829ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	/* Give up ownership of vblank for page-flipped crtc */
830ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	drm_vblank_put(dev, s->crtc);
831ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner
832332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	list_del(&s->head);
833d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs	if (ps)
834d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs		*ps = *s;
835332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	kfree(s);
836332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
837332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_unlock_irqrestore(&dev->event_lock, flags);
838332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return 0;
839332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez}
84033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
84133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsint
842f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggsnouveau_flip_complete(void *data)
843f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs{
844f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_channel *chan = data;
84577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = chan->drm;
846f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_page_flip_state state;
847f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
848f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	if (!nouveau_finish_page_flip(chan, &state)) {
849967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
85077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			nv_set_crtc_base(drm->dev, state.crtc, state.offset +
851f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs					 state.y * state.pitch +
852f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs					 state.x * state.bpp / 8);
853f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs		}
854f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	}
855f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
856f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	return 0;
857f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs}
858f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
859f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggsint
86033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsnouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
86133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs			    struct drm_mode_create_dumb *args)
86233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs{
86333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	struct nouveau_bo *bo;
86433dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	int ret;
86533dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
86633dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	args->pitch = roundup(args->width * (args->bpp / 8), 256);
86733dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	args->size = args->pitch * args->height;
86833dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	args->size = roundup(args->size, PAGE_SIZE);
86933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
870610bd7da160f76f1644ecb4cd7f39511b49a22ccDave Airlie	ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);
87133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	if (ret)
87233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs		return ret;
87333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
87455fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann	ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
87555fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann	drm_gem_object_unreference_unlocked(&bo->gem);
87633dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	return ret;
87733dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs}
87833dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
87933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsint
88033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsnouveau_display_dumb_map_offset(struct drm_file *file_priv,
88133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs				struct drm_device *dev,
88233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs				uint32_t handle, uint64_t *poffset)
88333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs{
88433dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	struct drm_gem_object *gem;
88533dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
88633dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	gem = drm_gem_object_lookup(dev, file_priv, handle);
88733dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	if (gem) {
88855fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann		struct nouveau_bo *bo = nouveau_gem_object(gem);
88972525b3f333de54fa0c42ef87f27861e41478f1eDavid Herrmann		*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
89033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs		drm_gem_object_unreference_unlocked(gem);
89133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs		return 0;
89233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	}
89333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
89433dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	return -ENOENT;
89533dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs}
896