2 * Copyright 2009 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <drm/drm_crtc_helper.h>
27 #include "nouveau_drv.h"
28 #include "nouveau_reg.h"
30 #include "nouveau_encoder.h"
31 #include "nouveau_connector.h"
32 #include "nouveau_bo.h"
34 #include <nvif/if0004.h>
37 nv04_display_fini(struct drm_device
*dev
, bool suspend
)
39 struct nv04_display
*disp
= nv04_display(dev
);
40 struct drm_crtc
*crtc
;
42 /* Disable flip completion events. */
43 nvif_notify_put(&disp
->flip
);
45 /* Disable vblank interrupts. */
46 NVWriteCRTC(dev
, 0, NV_PCRTC_INTR_EN_0
, 0);
47 if (nv_two_heads(dev
))
48 NVWriteCRTC(dev
, 1, NV_PCRTC_INTR_EN_0
, 0);
53 /* Un-pin FB and cursors so they'll be evicted to system memory. */
54 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
55 struct nouveau_framebuffer
*nouveau_fb
;
57 nouveau_fb
= nouveau_framebuffer(crtc
->primary
->fb
);
58 if (!nouveau_fb
|| !nouveau_fb
->nvbo
)
61 nouveau_bo_unpin(nouveau_fb
->nvbo
);
64 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
65 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(crtc
);
66 if (nv_crtc
->cursor
.nvbo
) {
67 if (nv_crtc
->cursor
.set_offset
)
68 nouveau_bo_unmap(nv_crtc
->cursor
.nvbo
);
69 nouveau_bo_unpin(nv_crtc
->cursor
.nvbo
);
75 nv04_display_init(struct drm_device
*dev
, bool resume
, bool runtime
)
77 struct nv04_display
*disp
= nv04_display(dev
);
78 struct nouveau_drm
*drm
= nouveau_drm(dev
);
79 struct nouveau_encoder
*encoder
;
80 struct drm_crtc
*crtc
;
83 /* meh.. modeset apparently doesn't setup all the regs and depends
84 * on pre-existing state, for now load the state of the card *before*
85 * nouveau was loaded, and then do a modeset.
87 * best thing to do probably is to make save/restore routines not
88 * save/restore "pre-load" state, but more general so we can save
91 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
92 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(crtc
);
93 nv_crtc
->save(&nv_crtc
->base
);
96 list_for_each_entry(encoder
, &dev
->mode_config
.encoder_list
, base
.base
.head
)
97 encoder
->enc_save(&encoder
->base
.base
);
99 /* Enable flip completion events. */
100 nvif_notify_get(&disp
->flip
);
105 /* Re-pin FB/cursors. */
106 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
107 struct nouveau_framebuffer
*nouveau_fb
;
109 nouveau_fb
= nouveau_framebuffer(crtc
->primary
->fb
);
110 if (!nouveau_fb
|| !nouveau_fb
->nvbo
)
113 ret
= nouveau_bo_pin(nouveau_fb
->nvbo
, TTM_PL_FLAG_VRAM
, true);
115 NV_ERROR(drm
, "Could not pin framebuffer\n");
118 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
119 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(crtc
);
120 if (!nv_crtc
->cursor
.nvbo
)
123 ret
= nouveau_bo_pin(nv_crtc
->cursor
.nvbo
, TTM_PL_FLAG_VRAM
, true);
124 if (!ret
&& nv_crtc
->cursor
.set_offset
)
125 ret
= nouveau_bo_map(nv_crtc
->cursor
.nvbo
);
127 NV_ERROR(drm
, "Could not pin/map cursor.\n");
130 /* Force CLUT to get re-loaded during modeset. */
131 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
132 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(crtc
);
134 nv_crtc
->lut
.depth
= 0;
137 /* This should ensure we don't hit a locking problem when someone
138 * wakes us up via a connector. We should never go into suspend
139 * while the display is on anyways.
145 drm_helper_resume_force_mode(dev
);
147 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, head
) {
148 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(crtc
);
150 if (!nv_crtc
->cursor
.nvbo
)
153 if (nv_crtc
->cursor
.set_offset
)
154 nv_crtc
->cursor
.set_offset(nv_crtc
, nv_crtc
->cursor
.nvbo
->bo
.offset
);
155 nv_crtc
->cursor
.set_pos(nv_crtc
, nv_crtc
->cursor_saved_x
,
156 nv_crtc
->cursor_saved_y
);
163 nv04_display_destroy(struct drm_device
*dev
)
165 struct nv04_display
*disp
= nv04_display(dev
);
166 struct nouveau_drm
*drm
= nouveau_drm(dev
);
167 struct nouveau_encoder
*encoder
;
168 struct nouveau_crtc
*nv_crtc
;
171 list_for_each_entry(encoder
, &dev
->mode_config
.encoder_list
, base
.base
.head
)
172 encoder
->enc_restore(&encoder
->base
.base
);
174 list_for_each_entry(nv_crtc
, &dev
->mode_config
.crtc_list
, base
.head
)
175 nv_crtc
->restore(&nv_crtc
->base
);
177 nouveau_hw_save_vga_fonts(dev
, 0);
179 nvif_notify_fini(&disp
->flip
);
181 nouveau_display(dev
)->priv
= NULL
;
184 nvif_object_unmap(&drm
->client
.device
.object
);
188 nv04_display_create(struct drm_device
*dev
)
190 struct nouveau_drm
*drm
= nouveau_drm(dev
);
191 struct nvkm_i2c
*i2c
= nvxx_i2c(&drm
->client
.device
);
192 struct dcb_table
*dcb
= &drm
->vbios
.dcb
;
193 struct drm_connector
*connector
, *ct
;
194 struct drm_encoder
*encoder
;
195 struct nouveau_encoder
*nv_encoder
;
196 struct nouveau_crtc
*crtc
;
197 struct nv04_display
*disp
;
200 disp
= kzalloc(sizeof(*disp
), GFP_KERNEL
);
204 nvif_object_map(&drm
->client
.device
.object
, NULL
, 0);
206 nouveau_display(dev
)->priv
= disp
;
207 nouveau_display(dev
)->dtor
= nv04_display_destroy
;
208 nouveau_display(dev
)->init
= nv04_display_init
;
209 nouveau_display(dev
)->fini
= nv04_display_fini
;
211 /* Pre-nv50 doesn't support atomic, so don't expose the ioctls */
212 dev
->driver_features
&= ~DRIVER_ATOMIC
;
214 /* Request page flip completion event. */
215 if (drm
->nvsw
.client
) {
216 nvif_notify_init(&drm
->nvsw
, nv04_flip_complete
,
217 false, NV04_NVSW_NTFY_UEVENT
,
218 NULL
, 0, 0, &disp
->flip
);
221 nouveau_hw_save_vga_fonts(dev
, 1);
223 nv04_crtc_create(dev
, 0);
224 if (nv_two_heads(dev
))
225 nv04_crtc_create(dev
, 1);
227 for (i
= 0; i
< dcb
->entries
; i
++) {
228 struct dcb_output
*dcbent
= &dcb
->entry
[i
];
230 connector
= nouveau_connector_create(dev
, dcbent
);
231 if (IS_ERR(connector
))
234 switch (dcbent
->type
) {
235 case DCB_OUTPUT_ANALOG
:
236 ret
= nv04_dac_create(connector
, dcbent
);
238 case DCB_OUTPUT_LVDS
:
239 case DCB_OUTPUT_TMDS
:
240 ret
= nv04_dfp_create(connector
, dcbent
);
243 if (dcbent
->location
== DCB_LOC_ON_CHIP
)
244 ret
= nv17_tv_create(connector
, dcbent
);
246 ret
= nv04_tv_create(connector
, dcbent
);
249 NV_WARN(drm
, "DCB type %d not known\n", dcbent
->type
);
257 list_for_each_entry_safe(connector
, ct
,
258 &dev
->mode_config
.connector_list
, head
) {
259 if (!connector
->possible_encoders
) {
260 NV_WARN(drm
, "%s has no encoders, removing\n",
262 connector
->funcs
->destroy(connector
);
266 list_for_each_entry(encoder
, &dev
->mode_config
.encoder_list
, head
) {
267 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
268 struct nvkm_i2c_bus
*bus
=
269 nvkm_i2c_bus_find(i2c
, nv_encoder
->dcb
->i2c_index
);
270 nv_encoder
->i2c
= bus
? &bus
->i2c
: NULL
;
273 /* Save previous state */
274 list_for_each_entry(crtc
, &dev
->mode_config
.crtc_list
, base
.head
)
275 crtc
->save(&crtc
->base
);
277 list_for_each_entry(nv_encoder
, &dev
->mode_config
.encoder_list
, base
.base
.head
)
278 nv_encoder
->enc_save(&nv_encoder
->base
.base
);
280 nouveau_overlay_init(dev
);