[go: nahoru, domu]

nouveau_display.c revision fdb751ef2bbc78314d1e01d3425cfacfb19b9f86
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
4579ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggsnouveau_display_vblank_handler(struct nvkm_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);
5079ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs	return NVKM_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) {
6079ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs			nvkm_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) {
7479ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs			nvkm_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{
98d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
99d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct nouveau_display *disp = nouveau_display(crtc->dev);
100d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct nv04_display_scanoutpos args;
101d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	int ret, retry = 1;
102d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
103d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	do {
1040ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs		ret = nvif_exec(&disp->disp, mthd, &args, sizeof(args));
105d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (ret != 0)
106d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			return 0;
107d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
108d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (args.vline) {
109d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			ret |= DRM_SCANOUTPOS_ACCURATE;
110d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			ret |= DRM_SCANOUTPOS_VALID;
111d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			break;
112d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		}
113d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
114d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (retry) ndelay(crtc->linedur_ns);
115d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	} while (retry--);
116d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
1176c3252bc83155ae69d78fefdc7458aa64d8a87dbMario Kleiner	*hpos = args.hline;
118d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	*vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
119d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	if (stime) *stime = ns_to_ktime(args.time[0]);
120d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	if (etime) *etime = ns_to_ktime(args.time[1]);
121d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
122d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	if (*vpos < 0)
123d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		ret |= DRM_SCANOUTPOS_INVBL;
124d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return ret;
125d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
126d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
127d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsint
128d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsnouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
129d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			   int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
130d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs{
131d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct drm_crtc *crtc;
132d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
133d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
134d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (nouveau_crtc(crtc)->index == head) {
135d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
136d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs							       stime, etime);
137d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		}
138d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	}
139d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
140d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return 0;
141d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
142d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
143d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsint
144d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggsnouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
145d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			 struct timeval *time, unsigned flags)
146d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs{
147d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	struct drm_crtc *crtc;
148d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
149d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
150d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		if (nouveau_crtc(crtc)->index == head) {
151d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs			return drm_calc_vbltimestamp_from_scanoutpos(dev,
152d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs					head, max_error, time, flags, crtc,
153d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs					&crtc->hwmode);
154d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs		}
155d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	}
156d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
157d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs	return -EINVAL;
158d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs}
159d83ef85395c9c1fae7636dca59f95c64963b307dBen Skeggs
16051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsstatic void
16151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsnouveau_display_vblank_fini(struct drm_device *dev)
16251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
163b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	struct drm_crtc *crtc;
16451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
1651139ffb96b3f4e8be9006552d2dd4d302d62c2eeBen Skeggs	drm_vblank_cleanup(dev);
1661139ffb96b3f4e8be9006552d2dd4d302d62c2eeBen Skeggs
167b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
168b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
16979ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs		nvkm_notify_fini(&nv_crtc->vblank);
17051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
17151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
17251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
17351cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsstatic int
17451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggsnouveau_display_vblank_init(struct drm_device *dev)
17551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs{
17651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
177967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	struct nouveau_disp *pdisp = nvkm_disp(&drm->device);
178b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	struct drm_crtc *crtc;
179b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	int ret;
18051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
181b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
182b12f0ae9e8dfee55c7757f9c4be3b1154c366754Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
18379ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs		ret = nvkm_notify_init(&pdisp->vblank,
18479ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       nouveau_display_vblank_handler, false,
18579ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       &(struct nvif_notify_head_req_v0) {
18679ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs					.head = nv_crtc->index,
18779ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       },
18879ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       sizeof(struct nvif_notify_head_req_v0),
18979ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       sizeof(struct nvif_notify_head_rep_v0),
19079ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs				       &nv_crtc->vblank);
19151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		if (ret) {
19251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs			nouveau_display_vblank_fini(dev);
19351cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs			return ret;
19451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		}
19551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
19651cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
19751cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
19851cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	if (ret) {
19951cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		nouveau_display_vblank_fini(dev);
20051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		return ret;
20151cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	}
20251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
20351cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	return 0;
20451cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs}
20551cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs
2066ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic void
2076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
2086ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2096ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
210ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	struct nouveau_display *disp = nouveau_display(drm_fb->dev);
211ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs
212ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	if (disp->fb_dtor)
213ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs		disp->fb_dtor(drm_fb);
2146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
215bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	if (fb->nvbo)
21655fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann		drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
2176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	drm_framebuffer_cleanup(drm_fb);
2196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	kfree(fb);
2206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic int
2236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
2246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				       struct drm_file *file_priv,
2256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				       unsigned int *handle)
2266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
2286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
22955fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann	return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle);
2306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
2336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	.destroy = nouveau_user_framebuffer_destroy,
2346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	.create_handle = nouveau_user_framebuffer_create_handle,
2356ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs};
2366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
237386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlieint
23845c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggsnouveau_framebuffer_init(struct drm_device *dev,
23945c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs			 struct nouveau_framebuffer *nv_fb,
240308e5bcbdb10452e8aba31aa21432fb67ee46d72Jesse Barnes			 struct drm_mode_fb_cmd2 *mode_cmd,
24145c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs			 struct nouveau_bo *nvbo)
2426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
243ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
24445c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs	struct drm_framebuffer *fb = &nv_fb->base;
2456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	int ret;
2466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
24745c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
24845c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs	nv_fb->nvbo = nvbo;
24945c4e0aae96c6354bf5131a282a74fe38d032de3Ben Skeggs
250c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
251ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	if (ret)
252c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter		return ret;
253ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs
254ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	if (disp->fb_ctor) {
255ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs		ret = disp->fb_ctor(fb);
256ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs		if (ret)
257ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs			disp->fb_dtor(fb);
258c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter	}
259c7d73f6a8ad71f9d9f58c86981322c6e48093a4fDaniel Vetter
260ab0af559d34b6817768c1720859aef7d7009ee57Ben Skeggs	return ret;
2616ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2626ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic struct drm_framebuffer *
2646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_user_framebuffer_create(struct drm_device *dev,
2656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				struct drm_file *file_priv,
266308e5bcbdb10452e8aba31aa21432fb67ee46d72Jesse Barnes				struct drm_mode_fb_cmd2 *mode_cmd)
2676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
268386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	struct nouveau_framebuffer *nouveau_fb;
2696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_gem_object *gem;
270fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	int ret = -ENOMEM;
2716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
272308e5bcbdb10452e8aba31aa21432fb67ee46d72Jesse Barnes	gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
2736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (!gem)
274cce13ff7596985903ad924504562190a2c163a63Chris Wilson		return ERR_PTR(-ENOENT);
2756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
276386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
277386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	if (!nouveau_fb)
278fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst		goto err_unref;
279386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie
280386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
281fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	if (ret)
282fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst		goto err;
2836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
284386516744ba45d50f42c6999151cc210cb4f96e4Dave Airlie	return &nouveau_fb->base;
285fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst
286fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorsterr:
287fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	kfree(nouveau_fb);
288fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorsterr_unref:
289fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	drm_gem_object_unreference(gem);
290fdfb8332651db7a280851dfccfc4f0cff4bcd052Maarten Lankhorst	return ERR_PTR(ret);
2916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
29327d5030a235d89842ed70e18d924f017b34a496dBen Skeggsstatic const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
2946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	.fb_create = nouveau_user_framebuffer_create,
295eb1f8e4f3be898df808e2dfc131099f5831d491dDave Airlie	.output_poll_changed = nouveau_fbcon_output_poll_changed,
2966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs};
2976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
298b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
2994a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstruct nouveau_drm_prop_enum_list {
300de69185573586302ada2e59ba41835df36986277Ben Skeggs	u8 gen_mask;
301b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	int type;
302b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	char *name;
303b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs};
304b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
3054a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstatic struct nouveau_drm_prop_enum_list underscan[] = {
3069285462273cbccb27187d5308ed95f94a9ceb1deBen Skeggs	{ 6, UNDERSCAN_AUTO, "auto" },
3079285462273cbccb27187d5308ed95f94a9ceb1deBen Skeggs	{ 6, UNDERSCAN_OFF, "off" },
3089285462273cbccb27187d5308ed95f94a9ceb1deBen Skeggs	{ 6, UNDERSCAN_ON, "on" },
309de69185573586302ada2e59ba41835df36986277Ben Skeggs	{}
310b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs};
311b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
3124a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstatic struct nouveau_drm_prop_enum_list dither_mode[] = {
313de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 7, DITHERING_MODE_AUTO, "auto" },
314de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 7, DITHERING_MODE_OFF, "off" },
315de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 1, DITHERING_MODE_ON, "on" },
316de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_MODE_STATIC2X2, "static 2x2" },
317de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" },
318de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 4, DITHERING_MODE_TEMPORAL, "temporal" },
319de69185573586302ada2e59ba41835df36986277Ben Skeggs	{}
320de69185573586302ada2e59ba41835df36986277Ben Skeggs};
321de69185573586302ada2e59ba41835df36986277Ben Skeggs
3224a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauerstatic struct nouveau_drm_prop_enum_list dither_depth[] = {
323de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_DEPTH_AUTO, "auto" },
324de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_DEPTH_6BPC, "6 bpc" },
325de69185573586302ada2e59ba41835df36986277Ben Skeggs	{ 6, DITHERING_DEPTH_8BPC, "8 bpc" },
326de69185573586302ada2e59ba41835df36986277Ben Skeggs	{}
327de69185573586302ada2e59ba41835df36986277Ben Skeggs};
328de69185573586302ada2e59ba41835df36986277Ben Skeggs
329de69185573586302ada2e59ba41835df36986277Ben Skeggs#define PROP_ENUM(p,gen,n,list) do {                                           \
3304a67d39190315558631d944b1cea4466ed4c86d8Sascha Hauer	struct nouveau_drm_prop_enum_list *l = (list);                         \
331de69185573586302ada2e59ba41835df36986277Ben Skeggs	int c = 0;                                                             \
332de69185573586302ada2e59ba41835df36986277Ben Skeggs	while (l->gen_mask) {                                                  \
333de69185573586302ada2e59ba41835df36986277Ben Skeggs		if (l->gen_mask & (1 << (gen)))                                \
334de69185573586302ada2e59ba41835df36986277Ben Skeggs			c++;                                                   \
335de69185573586302ada2e59ba41835df36986277Ben Skeggs		l++;                                                           \
336de69185573586302ada2e59ba41835df36986277Ben Skeggs	}                                                                      \
337de69185573586302ada2e59ba41835df36986277Ben Skeggs	if (c) {                                                               \
338de69185573586302ada2e59ba41835df36986277Ben Skeggs		p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c);        \
339de69185573586302ada2e59ba41835df36986277Ben Skeggs		l = (list);                                                    \
340de69185573586302ada2e59ba41835df36986277Ben Skeggs		c = 0;                                                         \
341de69185573586302ada2e59ba41835df36986277Ben Skeggs		while (p && l->gen_mask) {                                     \
342de69185573586302ada2e59ba41835df36986277Ben Skeggs			if (l->gen_mask & (1 << (gen))) {                      \
343de69185573586302ada2e59ba41835df36986277Ben Skeggs				drm_property_add_enum(p, c, l->type, l->name); \
344de69185573586302ada2e59ba41835df36986277Ben Skeggs				c++;                                           \
345de69185573586302ada2e59ba41835df36986277Ben Skeggs			}                                                      \
346de69185573586302ada2e59ba41835df36986277Ben Skeggs			l++;                                                   \
347de69185573586302ada2e59ba41835df36986277Ben Skeggs		}                                                              \
348de69185573586302ada2e59ba41835df36986277Ben Skeggs	}                                                                      \
349de69185573586302ada2e59ba41835df36986277Ben Skeggs} while(0)
350de69185573586302ada2e59ba41835df36986277Ben Skeggs
351042206c0cd4924879c4292c5ffa2bf1e8023ae5aFrancisco Jerezint
352f62b27db6b5479efe376b408802a081a834ef50eBen Skeggsnouveau_display_init(struct drm_device *dev)
353f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs{
35477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
35552c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	struct drm_connector *connector;
356f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	int ret;
357f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
358f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	ret = disp->init(dev);
35952c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	if (ret)
36052c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs		return ret;
36152c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs
3627df898b1a70b13c3a8892625f4ead929d9554293Ben Skeggs	/* enable polling for external displays */
36352c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	drm_kms_helper_poll_enable(dev);
36452c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs
36552c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	/* enable hotplug interrupts */
36652c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
36752c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs		struct nouveau_connector *conn = nouveau_connector(connector);
36879ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs		nvkm_notify_get(&conn->hpd);
369f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	}
370f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
371f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	return ret;
372f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs}
373f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
374f62b27db6b5479efe376b408802a081a834ef50eBen Skeggsvoid
375f62b27db6b5479efe376b408802a081a834ef50eBen Skeggsnouveau_display_fini(struct drm_device *dev)
376f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs{
37777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
37852c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	struct drm_connector *connector;
3799cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	int head;
3809cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner
3819cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	/* Make sure that drm and hw vblank irqs get properly disabled. */
3829cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	for (head = 0; head < dev->mode_config.num_crtc; head++)
3839cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner		drm_vblank_off(dev, head);
38452c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs
38552c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	/* disable hotplug interrupts */
38652c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
38752c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs		struct nouveau_connector *conn = nouveau_connector(connector);
38879ca27706a034b683196c85f5c6901b78e5ab8f0Ben Skeggs		nvkm_notify_put(&conn->hpd);
38952c4d767437b40b0cbc02d6a4480abb45ace64bbBen Skeggs	}
390f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
391f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	drm_kms_helper_poll_disable(dev);
392f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	disp->fini(dev);
393f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs}
394f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
3959c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsstatic void
3969c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsnouveau_display_create_properties(struct drm_device *dev)
39727d5030a235d89842ed70e18d924f017b34a496dBen Skeggs{
3989c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	struct nouveau_display *disp = nouveau_display(dev);
3999c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	int gen;
400de69185573586302ada2e59ba41835df36986277Ben Skeggs
4010ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	if (disp->disp.oclass < NV50_DISP_CLASS)
402de69185573586302ada2e59ba41835df36986277Ben Skeggs		gen = 0;
403de69185573586302ada2e59ba41835df36986277Ben Skeggs	else
4040ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	if (disp->disp.oclass < NVD0_DISP_CLASS)
405de69185573586302ada2e59ba41835df36986277Ben Skeggs		gen = 1;
406de69185573586302ada2e59ba41835df36986277Ben Skeggs	else
407de69185573586302ada2e59ba41835df36986277Ben Skeggs		gen = 2;
408de69185573586302ada2e59ba41835df36986277Ben Skeggs
409de69185573586302ada2e59ba41835df36986277Ben Skeggs	PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode);
410de69185573586302ada2e59ba41835df36986277Ben Skeggs	PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth);
411de69185573586302ada2e59ba41835df36986277Ben Skeggs	PROP_ENUM(disp->underscan_property, gen, "underscan", underscan);
412b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
413b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	disp->underscan_hborder_property =
414d9bc3c02e36d844c2d980e65ddda5c7699e073f8Sascha Hauer		drm_property_create_range(dev, 0, "underscan hborder", 0, 128);
415b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
416b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs	disp->underscan_vborder_property =
417d9bc3c02e36d844c2d980e65ddda5c7699e073f8Sascha Hauer		drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
418b29caa5885e85bbda7c84ea55721b9e79718583aBen Skeggs
4199c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	if (gen < 1)
4209c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		return;
421df26bc9c320602539b1b5b3d85786e4c8de7bf43Christoph Bumiller
4229c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	/* -90..+90 */
4239c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	disp->vibrant_hue_property =
4249c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
4259c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4269c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	/* -100..+100 */
4279c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	disp->color_vibrance_property =
4289c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		drm_property_create_range(dev, 0, "color vibrance", 0, 200);
4299c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs}
4309c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4319c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsint
4329c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggsnouveau_display_create(struct drm_device *dev)
4339c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs{
4349c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
4359c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	struct nouveau_display *disp;
4369c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	int ret;
4379c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4389c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
4399c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	if (!disp)
4409c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs		return -ENOMEM;
4419c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs
4429c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	drm_mode_config_init(dev);
4439c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	drm_mode_create_scaling_mode_property(dev);
4449c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs	drm_mode_create_dvi_i_properties(dev);
445df26bc9c320602539b1b5b3d85786e4c8de7bf43Christoph Bumiller
446e6ecefaadfcdb03db8ac9e739b4ba7a93a8811b3Laurent Pinchart	dev->mode_config.funcs = &nouveau_mode_config_funcs;
447967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	dev->mode_config.fb_base = nv_device_resource_start(nvkm_device(&drm->device), 1);
44827d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
44927d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	dev->mode_config.min_width = 0;
45027d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	dev->mode_config.min_height = 0;
451967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family < NV_DEVICE_INFO_V0_CELSIUS) {
45227d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_width = 2048;
45327d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_height = 2048;
45427d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	} else
455967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
45627d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_width = 4096;
45727d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_height = 4096;
45827d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	} else {
45927d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_width = 8192;
46027d5030a235d89842ed70e18d924f017b34a496dBen Skeggs		dev->mode_config.max_height = 8192;
46127d5030a235d89842ed70e18d924f017b34a496dBen Skeggs	}
46227d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
463f1377998eede7a8caa124fcf6a589b02c9e2bac7Dave Airlie	dev->mode_config.preferred_depth = 24;
464f1377998eede7a8caa124fcf6a589b02c9e2bac7Dave Airlie	dev->mode_config.prefer_shadow = 1;
465f1377998eede7a8caa124fcf6a589b02c9e2bac7Dave Airlie
466967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.chipset < 0x11)
467b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		dev->mode_config.async_page_flip = false;
468b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs	else
469b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		dev->mode_config.async_page_flip = true;
470b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
471f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	drm_kms_helper_poll_init(dev);
472f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	drm_kms_helper_poll_disable(dev);
473f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
474fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	if (drm->vbios.dcb.entries) {
4752332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		static const u16 oclass[] = {
4760b681687fe9eaa552059030a90897a78fea8f86aBen Skeggs			GM107_DISP_CLASS,
4772332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NVF0_DISP_CLASS,
4782332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NVE0_DISP_CLASS,
4792332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NVD0_DISP_CLASS,
4802332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NVA3_DISP_CLASS,
4812332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NV94_DISP_CLASS,
4822332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NVA0_DISP_CLASS,
4832332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NV84_DISP_CLASS,
4842332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NV50_DISP_CLASS,
4852332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			NV04_DISP_CLASS,
4862332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		};
4872332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		int i;
4882332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs
4892332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
4900ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs			ret = nvif_object_init(nvif_object(&drm->device), NULL,
4910ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs					       NVDRM_DISPLAY, oclass[i],
4920ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs					       NULL, 0, &disp->disp);
4932332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		}
4942332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs
4952332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		if (ret == 0) {
4969c210f378f7cee5f1a5eabe5a78c5ec98251cb5bBen Skeggs			nouveau_display_create_properties(dev);
4970ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs			if (disp->disp.oclass < NV50_DISP_CLASS)
4982332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs				ret = nv04_display_create(dev);
4992332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs			else
5002332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs				ret = nv50_display_create(dev);
5012332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs		}
502fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	} else {
503fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs		ret = 0;
504fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	}
5059430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs
506fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	if (ret)
507fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs		goto disp_create_err;
5089430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs
509fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	if (dev->mode_config.num_crtc) {
51051cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs		ret = nouveau_display_vblank_init(dev);
511fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs		if (ret)
512fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs			goto vblank_err;
513f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs	}
514f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
515fc1620883af8cbc10bfb1a4ef2eb4e8113243012Ben Skeggs	nouveau_backlight_init(dev);
5165ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz	return 0;
5175ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz
5185ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarzvblank_err:
51977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	disp->dtor(dev);
5205ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarzdisp_create_err:
5215ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz	drm_kms_helper_poll_fini(dev);
5225ace2c9d6f5bc4600ca43fe188a33efc4c2dba79Marcin Slusarz	drm_mode_config_cleanup(dev);
5232a44e4997c5fee8e1da1589ff57e0bd1c53f03ceBen Skeggs	return ret;
52427d5030a235d89842ed70e18d924f017b34a496dBen Skeggs}
52527d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
52627d5030a235d89842ed70e18d924f017b34a496dBen Skeggsvoid
52727d5030a235d89842ed70e18d924f017b34a496dBen Skeggsnouveau_display_destroy(struct drm_device *dev)
52827d5030a235d89842ed70e18d924f017b34a496dBen Skeggs{
52977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_display *disp = nouveau_display(dev);
53027d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
53177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_backlight_exit(dev);
53251cb4b392a307a8293b4f1f300ab803d7ad3b036Ben Skeggs	nouveau_display_vblank_fini(dev);
533f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
534d6bf2f370703c0cab60bf1f5bf871a3f00eb8872Ben Skeggs	drm_kms_helper_poll_fini(dev);
535d6bf2f370703c0cab60bf1f5bf871a3f00eb8872Ben Skeggs	drm_mode_config_cleanup(dev);
536d6bf2f370703c0cab60bf1f5bf871a3f00eb8872Ben Skeggs
5379430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs	if (disp->dtor)
5389430738d80223a1cd791a2baa74fa170d3df1262Ben Skeggs		disp->dtor(dev);
539f62b27db6b5479efe376b408802a081a834ef50eBen Skeggs
5400ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	nvif_object_fini(&disp->disp);
5412332b31116d5500d05173b2a7aaa95ba15d7983aBen Skeggs
54277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_drm(dev)->display = NULL;
54377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	kfree(disp);
54477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs}
54577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
54677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggsint
54777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggsnouveau_display_suspend(struct drm_device *dev)
54877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs{
54977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
55077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_crtc *crtc;
55177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
55277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	nouveau_display_fini(dev);
55377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
554c52f4fa61d7504bacd94fd54f43fd0b5bdf74bbcBen Skeggs	NV_INFO(drm, "unpinning framebuffer(s)...\n");
55577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
55677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_framebuffer *nouveau_fb;
55777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
558f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
55977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (!nouveau_fb || !nouveau_fb->nvbo)
56077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			continue;
56177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
56277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_unpin(nouveau_fb->nvbo);
56377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
56477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
56577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
56677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
56777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
56877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_unmap(nv_crtc->cursor.nvbo);
56977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_unpin(nv_crtc->cursor.nvbo);
57077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
57177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
57277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	return 0;
57377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs}
57477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
57577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggsvoid
5765addcf0a5f0fadceba6bd562d0616a1c5d4c1a4dDave Airlienouveau_display_repin(struct drm_device *dev)
57777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs{
57877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
57977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_crtc *crtc;
58077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	int ret;
58177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
58277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
58377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_framebuffer *nouveau_fb;
58477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
585f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
58677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (!nouveau_fb || !nouveau_fb->nvbo)
58777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			continue;
58877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
58977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
59077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
59177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
59277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
59377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
59477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
59577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
59677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (!ret)
59777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
59877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		if (ret)
59977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			NV_ERROR(drm, "Could not pin/map cursor.\n");
60077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
6015addcf0a5f0fadceba6bd562d0616a1c5d4c1a4dDave Airlie}
60277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
6035addcf0a5f0fadceba6bd562d0616a1c5d4c1a4dDave Airlievoid
6045addcf0a5f0fadceba6bd562d0616a1c5d4c1a4dDave Airlienouveau_display_resume(struct drm_device *dev)
6055addcf0a5f0fadceba6bd562d0616a1c5d4c1a4dDave Airlie{
6065addcf0a5f0fadceba6bd562d0616a1c5d4c1a4dDave Airlie	struct drm_crtc *crtc;
6079cba5efab5a8145ae6c52ea273553f069c294482Mario Kleiner	int head;
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
62277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	drm_helper_resume_force_mode(dev);
62377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
62477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
62577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
62677145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		u32 offset = nv_crtc->cursor.nvbo->bo.offset;
62777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
62877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nv_crtc->cursor.set_offset(nv_crtc, offset);
62977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
63077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs						 nv_crtc->cursor_saved_y);
63177145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	}
63227d5030a235d89842ed70e18d924f017b34a496dBen Skeggs}
63327d5030a235d89842ed70e18d924f017b34a496dBen Skeggs
634332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezstatic int
635332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jereznouveau_page_flip_emit(struct nouveau_channel *chan,
636332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_bo *old_bo,
637332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_bo *new_bo,
638332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_page_flip_state *s,
639332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		       struct nouveau_fence **pfence)
640332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez{
641f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_fence_chan *fctx = chan->fence;
64277145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = chan->drm;
64377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_device *dev = drm->dev;
644332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	unsigned long flags;
645332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	int ret;
646332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
647332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Queue it to the pending list */
648332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_lock_irqsave(&dev->event_lock, flags);
649f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	list_add_tail(&s->head, &fctx->flip);
650332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_unlock_irqrestore(&dev->event_lock, flags);
651332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
652332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Synchronize with the old framebuffer */
653332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan);
654332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
655332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail;
656332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
657332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Emit the pageflip */
6581e303c03af1e631de37ec77cc2513210910a812cBen Skeggs	ret = RING_SPACE(chan, 2);
659332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
660332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail;
661332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
662967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
6636d597027755b2eed4298b85ebe3cb5c93b29d1a9Ben Skeggs		BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
6641e303c03af1e631de37ec77cc2513210910a812cBen Skeggs	else
6651e303c03af1e631de37ec77cc2513210910a812cBen Skeggs		BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1);
6661e303c03af1e631de37ec77cc2513210910a812cBen Skeggs	OUT_RING  (chan, 0x00000000);
667bd2f2037a42d4657ead3be2918db22e63626cd35Ben Skeggs	FIRE_RING (chan);
668332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
669264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	ret = nouveau_fence_new(chan, false, pfence);
670332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
671332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail;
672332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
673332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return 0;
674332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezfail:
675332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_lock_irqsave(&dev->event_lock, flags);
676332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	list_del(&s->head);
677332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_unlock_irqrestore(&dev->event_lock, flags);
678332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return ret;
679332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez}
680332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
681332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezint
682332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jereznouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
683b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		       struct drm_pending_vblank_event *event, u32 flags)
684332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez{
685b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
686332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct drm_device *dev = crtc->dev;
68777145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = nouveau_drm(dev);
688f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
689332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
690332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_page_flip_state *s;
6910ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	struct nouveau_channel *chan;
6920ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	struct nouveau_cli *cli;
693332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_fence *fence;
694332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	int ret;
695332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
6960ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	chan = drm->channel;
6970ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	if (!chan)
698332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		return -ENODEV;
6990ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	cli = (void *)nvif_client(&chan->device->base);
700332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
701332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	s = kzalloc(sizeof(*s), GFP_KERNEL);
702332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (!s)
703332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		return -ENOMEM;
704332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
705d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst	if (new_bo != old_bo) {
706d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst		ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
707d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst		if (ret)
708d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst			goto fail_free;
709d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst	}
710d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst
7110ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	mutex_lock(&cli->mutex);
712d5c1e84b3a130f0743b218b33ff7d9cb493ab5b4Maarten Lankhorst
713eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	/* synchronise rendering channel with the kernel's channel */
714eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	spin_lock(&new_bo->bo.bdev->fence_lock);
715eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	fence = nouveau_fence_ref(new_bo->bo.sync_obj);
716eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	spin_unlock(&new_bo->bo.bdev->fence_lock);
717eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	ret = nouveau_fence_sync(fence, chan);
7182fd04c81dc652689b104ab16eba26146dde5c43fBen Skeggs	nouveau_fence_unref(&fence);
719eae389f9b1e08a6e6e8da68937706d89517b1796Ben Skeggs	if (ret)
72009c3de135063f93d7137ad112f551f293b1204cfMaarten Lankhorst		goto fail_unpin;
721b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
72207ad6ca0d391758ae3bffa95554abbae6c84e641Ben Skeggs	ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);
723060810d7abaabcab282e062c595871d661561400Ben Skeggs	if (ret)
724060810d7abaabcab282e062c595871d661561400Ben Skeggs		goto fail_unpin;
725b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
726b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst	/* Initialize a page flip struct */
727b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst	*s = (struct nouveau_page_flip_state)
728b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		{ { }, event, nouveau_crtc(crtc)->index,
729b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		  fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y,
730b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		  new_bo->bo.offset };
731b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst
732ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	/* Keep vblanks on during flip, for the target crtc of this flip */
733ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	drm_vblank_get(dev, nouveau_crtc(crtc)->index);
734ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner
735332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Emit a page flip */
736967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
737b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
738060810d7abaabcab282e062c595871d661561400Ben Skeggs		if (ret)
739d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs			goto fail_unreserve;
74078ae0ad403daf11cf63da86923d2b5dbeda3af8fBen Skeggs	} else {
74178ae0ad403daf11cf63da86923d2b5dbeda3af8fBen Skeggs		struct nv04_display *dispnv04 = nv04_display(dev);
742b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		int head = nouveau_crtc(crtc)->index;
743b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
744b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		if (swap_interval) {
745b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			ret = RING_SPACE(chan, 8);
746b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			if (ret)
747b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs				goto fail_unreserve;
748b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
749b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
750b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, 0);
751b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
752b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, head);
753b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
754b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, 0);
755b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
756b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs			OUT_RING  (chan, 0);
757b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		}
758b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs
759b9d9dcdaae4a9284ba3484c528f44a9db18faabfBen Skeggs		nouveau_bo_ref(new_bo, &dispnv04->image[head]);
760d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs	}
761d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs
762332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
763332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	if (ret)
764332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		goto fail_unreserve;
7650ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	mutex_unlock(&cli->mutex);
766332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
767332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	/* Update the crtc struct and cleanup */
768f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper	crtc->primary->fb = fb;
769332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
77007ad6ca0d391758ae3bffa95554abbae6c84e641Ben Skeggs	nouveau_bo_fence(old_bo, fence);
77107ad6ca0d391758ae3bffa95554abbae6c84e641Ben Skeggs	ttm_bo_unreserve(&old_bo->bo);
772060810d7abaabcab282e062c595871d661561400Ben Skeggs	if (old_bo != new_bo)
773b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		nouveau_bo_unpin(old_bo);
774332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	nouveau_fence_unref(&fence);
775332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return 0;
776332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
777332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezfail_unreserve:
778ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	drm_vblank_put(dev, nouveau_crtc(crtc)->index);
77907ad6ca0d391758ae3bffa95554abbae6c84e641Ben Skeggs	ttm_bo_unreserve(&old_bo->bo);
780060810d7abaabcab282e062c595871d661561400Ben Skeggsfail_unpin:
7810ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	mutex_unlock(&cli->mutex);
782060810d7abaabcab282e062c595871d661561400Ben Skeggs	if (old_bo != new_bo)
783b580c9e2b7ba5030a795aa2fb73b796523d65a78Maarten Lankhorst		nouveau_bo_unpin(new_bo);
784332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezfail_free:
785332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	kfree(s);
786332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return ret;
787332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez}
788332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
789332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerezint
790332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jereznouveau_finish_page_flip(struct nouveau_channel *chan,
791332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez			 struct nouveau_page_flip_state *ps)
792332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez{
793f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_fence_chan *fctx = chan->fence;
79477145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = chan->drm;
79577145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct drm_device *dev = drm->dev;
796332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	struct nouveau_page_flip_state *s;
797332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	unsigned long flags;
798af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner	int crtcid = -1;
799332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
800332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_lock_irqsave(&dev->event_lock, flags);
801332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
802f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	if (list_empty(&fctx->flip)) {
80377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs		NV_ERROR(drm, "unexpected pageflip\n");
804332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		spin_unlock_irqrestore(&dev->event_lock, flags);
805332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez		return -EINVAL;
806332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	}
807332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
808f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
809af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner	if (s->event) {
810af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner		/* Vblank timestamps/counts are only correct on >= NV-50 */
811967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
812af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner			crtcid = s->crtc;
813af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner
814af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner		drm_send_vblank_event(dev, crtcid, s->event);
815af4870e406126b7ac0ae7c7ce5751f25ebe60f28Mario Kleiner	}
816332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
817ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	/* Give up ownership of vblank for page-flipped crtc */
818ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner	drm_vblank_put(dev, s->crtc);
819ba124a41058b300a5464206d2d33803cc3dc82ecMario Kleiner
820332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	list_del(&s->head);
821d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs	if (ps)
822d7117e0d4e21034202833088e51fc21f8c8271f9Ben Skeggs		*ps = *s;
823332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	kfree(s);
824332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez
825332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	spin_unlock_irqrestore(&dev->event_lock, flags);
826332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez	return 0;
827332b242f47786d1a43bd7a19a0513dd5d493db8eFrancisco Jerez}
82833dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
82933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsint
830f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggsnouveau_flip_complete(void *data)
831f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs{
832f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_channel *chan = data;
83377145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs	struct nouveau_drm *drm = chan->drm;
834f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	struct nouveau_page_flip_state state;
835f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
836f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	if (!nouveau_finish_page_flip(chan, &state)) {
837967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
83877145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs			nv_set_crtc_base(drm->dev, state.crtc, state.offset +
839f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs					 state.y * state.pitch +
840f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs					 state.x * state.bpp / 8);
841f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs		}
842f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	}
843f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
844f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	return 0;
845f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs}
846f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
847f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggsint
84833dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsnouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
84933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs			    struct drm_mode_create_dumb *args)
85033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs{
85133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	struct nouveau_bo *bo;
85233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	int ret;
85333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
85433dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	args->pitch = roundup(args->width * (args->bpp / 8), 256);
85533dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	args->size = args->pitch * args->height;
85633dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	args->size = roundup(args->size, PAGE_SIZE);
85733dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
858610bd7da160f76f1644ecb4cd7f39511b49a22ccDave Airlie	ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);
85933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	if (ret)
86033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs		return ret;
86133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
86255fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann	ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
86355fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann	drm_gem_object_unreference_unlocked(&bo->gem);
86433dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	return ret;
86533dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs}
86633dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
86733dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsint
86833dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggsnouveau_display_dumb_map_offset(struct drm_file *file_priv,
86933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs				struct drm_device *dev,
87033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs				uint32_t handle, uint64_t *poffset)
87133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs{
87233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	struct drm_gem_object *gem;
87333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
87433dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	gem = drm_gem_object_lookup(dev, file_priv, handle);
87533dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	if (gem) {
87655fb74adc628b99424360b0123f47ea4484c56fdDavid Herrmann		struct nouveau_bo *bo = nouveau_gem_object(gem);
87772525b3f333de54fa0c42ef87f27861e41478f1eDavid Herrmann		*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
87833dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs		drm_gem_object_unreference_unlocked(gem);
87933dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs		return 0;
88033dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	}
88133dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs
88233dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs	return -ENOENT;
88333dbc27f1ab3a37d04a8d226327fb3d384870e43Ben Skeggs}
884