aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/dispnv04/crtc.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-03-21 01:45:11 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-04-26 01:37:51 -0400
commit1a6463425552a8b9960e5a19b25421895846925c (patch)
treedda4f2208f78dbc654fbfcecb97575c3cc564a7e /drivers/gpu/drm/nouveau/dispnv04/crtc.c
parentb9a3140ce8fcd616b02533fbdef375a87a910daf (diff)
drm/nv04/disp: hide all the cruft away in its own little hole
It'd be pretty awesome if someone would care enough to port this all properly to a class interface, perhaps submitting a command stream to the core via a sw object on PFIFO (emulating how EVO works basically, and also what nvidia have done forever..).. But, this seems unlikely given how old this hardware is now, so, lets just hide it away. There's a heap of other bits and pieces laying around that are still tangled. I'll (re)move them in pieces. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/dispnv04/crtc.c')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c1072
1 files changed, 1072 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
new file mode 100644
index 000000000000..0782bd2f1e04
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -0,0 +1,1072 @@
1/*
2 * Copyright 1993-2003 NVIDIA, Corporation
3 * Copyright 2006 Dave Airlie
4 * Copyright 2007 Maarten Maathuis
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26#include <drm/drmP.h>
27#include <drm/drm_crtc_helper.h>
28
29#include "nouveau_drm.h"
30#include "nouveau_reg.h"
31#include "nouveau_bo.h"
32#include "nouveau_gem.h"
33#include "nouveau_encoder.h"
34#include "nouveau_connector.h"
35#include "nouveau_crtc.h"
36#include "hw.h"
37#include "nvreg.h"
38#include "nouveau_fbcon.h"
39#include "disp.h"
40
41#include <subdev/bios/pll.h>
42#include <subdev/clock.h>
43
44static int
45nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
46 struct drm_framebuffer *old_fb);
47
48static void
49crtc_wr_cio_state(struct drm_crtc *crtc, struct nv04_crtc_reg *crtcstate, int index)
50{
51 NVWriteVgaCrtc(crtc->dev, nouveau_crtc(crtc)->index, index,
52 crtcstate->CRTC[index]);
53}
54
55static void nv_crtc_set_digital_vibrance(struct drm_crtc *crtc, int level)
56{
57 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
58 struct drm_device *dev = crtc->dev;
59 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
60
61 regp->CRTC[NV_CIO_CRE_CSB] = nv_crtc->saturation = level;
62 if (nv_crtc->saturation && nv_gf4_disp_arch(crtc->dev)) {
63 regp->CRTC[NV_CIO_CRE_CSB] = 0x80;
64 regp->CRTC[NV_CIO_CRE_5B] = nv_crtc->saturation << 2;
65 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_5B);
66 }
67 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_CSB);
68}
69
70static void nv_crtc_set_image_sharpening(struct drm_crtc *crtc, int level)
71{
72 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
73 struct drm_device *dev = crtc->dev;
74 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
75
76 nv_crtc->sharpness = level;
77 if (level < 0) /* blur is in hw range 0x3f -> 0x20 */
78 level += 0x40;
79 regp->ramdac_634 = level;
80 NVWriteRAMDAC(crtc->dev, nv_crtc->index, NV_PRAMDAC_634, regp->ramdac_634);
81}
82
83#define PLLSEL_VPLL1_MASK \
84 (NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL \
85 | NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2)
86#define PLLSEL_VPLL2_MASK \
87 (NV_PRAMDAC_PLL_COEFF_SELECT_PLL_SOURCE_VPLL2 \
88 | NV_PRAMDAC_PLL_COEFF_SELECT_VCLK2_RATIO_DB2)
89#define PLLSEL_TV_MASK \
90 (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \
91 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1 \
92 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2 \
93 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2)
94
95/* NV4x 0x40.. pll notes:
96 * gpu pll: 0x4000 + 0x4004
97 * ?gpu? pll: 0x4008 + 0x400c
98 * vpll1: 0x4010 + 0x4014
99 * vpll2: 0x4018 + 0x401c
100 * mpll: 0x4020 + 0x4024
101 * mpll: 0x4038 + 0x403c
102 *
103 * the first register of each pair has some unknown details:
104 * bits 0-7: redirected values from elsewhere? (similar to PLL_SETUP_CONTROL?)
105 * bits 20-23: (mpll) something to do with post divider?
106 * bits 28-31: related to single stage mode? (bit 8/12)
107 */
108
109static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock)
110{
111 struct drm_device *dev = crtc->dev;
112 struct nouveau_drm *drm = nouveau_drm(dev);
113 struct nouveau_bios *bios = nouveau_bios(drm->device);
114 struct nouveau_clock *clk = nouveau_clock(drm->device);
115 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
116 struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
117 struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index];
118 struct nouveau_pll_vals *pv = &regp->pllvals;
119 struct nvbios_pll pll_lim;
120
121 if (nvbios_pll_parse(bios, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0,
122 &pll_lim))
123 return;
124
125 /* NM2 == 0 is used to determine single stage mode on two stage plls */
126 pv->NM2 = 0;
127
128 /* for newer nv4x the blob uses only the first stage of the vpll below a
129 * certain clock. for a certain nv4b this is 150MHz. since the max
130 * output frequency of the first stage for this card is 300MHz, it is
131 * assumed the threshold is given by vco1 maxfreq/2
132 */
133 /* for early nv4x, specifically nv40 and *some* nv43 (devids 0 and 6,
134 * not 8, others unknown), the blob always uses both plls. no problem
135 * has yet been observed in allowing the use a single stage pll on all
136 * nv43 however. the behaviour of single stage use is untested on nv40
137 */
138 if (nv_device(drm->device)->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2))
139 memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2));
140
141
142 if (!clk->pll_calc(clk, &pll_lim, dot_clock, pv))
143 return;
144
145 state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK;
146
147 /* The blob uses this always, so let's do the same */
148 if (nv_device(drm->device)->card_type == NV_40)
149 state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE;
150 /* again nv40 and some nv43 act more like nv3x as described above */
151 if (nv_device(drm->device)->chipset < 0x41)
152 state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL |
153 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL;
154 state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK;
155
156 if (pv->NM2)
157 NV_DEBUG(drm, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n",
158 pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P);
159 else
160 NV_DEBUG(drm, "vpll: n %d m %d log2p %d\n",
161 pv->N1, pv->M1, pv->log2P);
162
163 nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
164}
165
166static void
167nv_crtc_dpms(struct drm_crtc *crtc, int mode)
168{
169 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
170 struct drm_device *dev = crtc->dev;
171 struct nouveau_drm *drm = nouveau_drm(dev);
172 unsigned char seq1 = 0, crtc17 = 0;
173 unsigned char crtc1A;
174
175 NV_DEBUG(drm, "Setting dpms mode %d on CRTC %d\n", mode,
176 nv_crtc->index);
177
178 if (nv_crtc->last_dpms == mode) /* Don't do unnecessary mode changes. */
179 return;
180
181 nv_crtc->last_dpms = mode;
182
183 if (nv_two_heads(dev))
184 NVSetOwner(dev, nv_crtc->index);
185
186 /* nv4ref indicates these two RPC1 bits inhibit h/v sync */
187 crtc1A = NVReadVgaCrtc(dev, nv_crtc->index,
188 NV_CIO_CRE_RPC1_INDEX) & ~0xC0;
189 switch (mode) {
190 case DRM_MODE_DPMS_STANDBY:
191 /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
192 seq1 = 0x20;
193 crtc17 = 0x80;
194 crtc1A |= 0x80;
195 break;
196 case DRM_MODE_DPMS_SUSPEND:
197 /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
198 seq1 = 0x20;
199 crtc17 = 0x80;
200 crtc1A |= 0x40;
201 break;
202 case DRM_MODE_DPMS_OFF:
203 /* Screen: Off; HSync: Off, VSync: Off */
204 seq1 = 0x20;
205 crtc17 = 0x00;
206 crtc1A |= 0xC0;
207 break;
208 case DRM_MODE_DPMS_ON:
209 default:
210 /* Screen: On; HSync: On, VSync: On */
211 seq1 = 0x00;
212 crtc17 = 0x80;
213 break;
214 }
215
216 NVVgaSeqReset(dev, nv_crtc->index, true);
217 /* Each head has it's own sequencer, so we can turn it off when we want */
218 seq1 |= (NVReadVgaSeq(dev, nv_crtc->index, NV_VIO_SR_CLOCK_INDEX) & ~0x20);
219 NVWriteVgaSeq(dev, nv_crtc->index, NV_VIO_SR_CLOCK_INDEX, seq1);
220 crtc17 |= (NVReadVgaCrtc(dev, nv_crtc->index, NV_CIO_CR_MODE_INDEX) & ~0x80);
221 mdelay(10);
222 NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CR_MODE_INDEX, crtc17);
223 NVVgaSeqReset(dev, nv_crtc->index, false);
224
225 NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
226}
227
228static bool
229nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
230 struct drm_display_mode *adjusted_mode)
231{
232 return true;
233}
234
235static void
236nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
237{
238 struct drm_device *dev = crtc->dev;
239 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
240 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
241 struct drm_framebuffer *fb = crtc->fb;
242
243 /* Calculate our timings */
244 int horizDisplay = (mode->crtc_hdisplay >> 3) - 1;
245 int horizStart = (mode->crtc_hsync_start >> 3) + 1;
246 int horizEnd = (mode->crtc_hsync_end >> 3) + 1;
247 int horizTotal = (mode->crtc_htotal >> 3) - 5;
248 int horizBlankStart = (mode->crtc_hdisplay >> 3) - 1;
249 int horizBlankEnd = (mode->crtc_htotal >> 3) - 1;
250 int vertDisplay = mode->crtc_vdisplay - 1;
251 int vertStart = mode->crtc_vsync_start - 1;
252 int vertEnd = mode->crtc_vsync_end - 1;
253 int vertTotal = mode->crtc_vtotal - 2;
254 int vertBlankStart = mode->crtc_vdisplay - 1;
255 int vertBlankEnd = mode->crtc_vtotal - 1;
256
257 struct drm_encoder *encoder;
258 bool fp_output = false;
259
260 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
261 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
262
263 if (encoder->crtc == crtc &&
264 (nv_encoder->dcb->type == DCB_OUTPUT_LVDS ||
265 nv_encoder->dcb->type == DCB_OUTPUT_TMDS))
266 fp_output = true;
267 }
268
269 if (fp_output) {
270 vertStart = vertTotal - 3;
271 vertEnd = vertTotal - 2;
272 vertBlankStart = vertStart;
273 horizStart = horizTotal - 5;
274 horizEnd = horizTotal - 2;
275 horizBlankEnd = horizTotal + 4;
276#if 0
277 if (dev->overlayAdaptor && nv_device(drm->device)->card_type >= NV_10)
278 /* This reportedly works around some video overlay bandwidth problems */
279 horizTotal += 2;
280#endif
281 }
282
283 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
284 vertTotal |= 1;
285
286#if 0
287 ErrorF("horizDisplay: 0x%X \n", horizDisplay);
288 ErrorF("horizStart: 0x%X \n", horizStart);
289 ErrorF("horizEnd: 0x%X \n", horizEnd);
290 ErrorF("horizTotal: 0x%X \n", horizTotal);
291 ErrorF("horizBlankStart: 0x%X \n", horizBlankStart);
292 ErrorF("horizBlankEnd: 0x%X \n", horizBlankEnd);
293 ErrorF("vertDisplay: 0x%X \n", vertDisplay);
294 ErrorF("vertStart: 0x%X \n", vertStart);
295 ErrorF("vertEnd: 0x%X \n", vertEnd);
296 ErrorF("vertTotal: 0x%X \n", vertTotal);
297 ErrorF("vertBlankStart: 0x%X \n", vertBlankStart);
298 ErrorF("vertBlankEnd: 0x%X \n", vertBlankEnd);
299#endif
300
301 /*
302 * compute correct Hsync & Vsync polarity
303 */
304 if ((mode->flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))
305 && (mode->flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) {
306
307 regp->MiscOutReg = 0x23;
308 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
309 regp->MiscOutReg |= 0x40;
310 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
311 regp->MiscOutReg |= 0x80;
312 } else {
313 int vdisplay = mode->vdisplay;
314 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
315 vdisplay *= 2;
316 if (mode->vscan > 1)
317 vdisplay *= mode->vscan;
318 if (vdisplay < 400)
319 regp->MiscOutReg = 0xA3; /* +hsync -vsync */
320 else if (vdisplay < 480)
321 regp->MiscOutReg = 0x63; /* -hsync +vsync */
322 else if (vdisplay < 768)
323 regp->MiscOutReg = 0xE3; /* -hsync -vsync */
324 else
325 regp->MiscOutReg = 0x23; /* +hsync +vsync */
326 }
327
328 regp->MiscOutReg |= (mode->clock_index & 0x03) << 2;
329
330 /*
331 * Time Sequencer
332 */
333 regp->Sequencer[NV_VIO_SR_RESET_INDEX] = 0x00;
334 /* 0x20 disables the sequencer */
335 if (mode->flags & DRM_MODE_FLAG_CLKDIV2)
336 regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x29;
337 else
338 regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x21;
339 regp->Sequencer[NV_VIO_SR_PLANE_MASK_INDEX] = 0x0F;
340 regp->Sequencer[NV_VIO_SR_CHAR_MAP_INDEX] = 0x00;
341 regp->Sequencer[NV_VIO_SR_MEM_MODE_INDEX] = 0x0E;
342
343 /*
344 * CRTC
345 */
346 regp->CRTC[NV_CIO_CR_HDT_INDEX] = horizTotal;
347 regp->CRTC[NV_CIO_CR_HDE_INDEX] = horizDisplay;
348 regp->CRTC[NV_CIO_CR_HBS_INDEX] = horizBlankStart;
349 regp->CRTC[NV_CIO_CR_HBE_INDEX] = (1 << 7) |
350 XLATE(horizBlankEnd, 0, NV_CIO_CR_HBE_4_0);
351 regp->CRTC[NV_CIO_CR_HRS_INDEX] = horizStart;
352 regp->CRTC[NV_CIO_CR_HRE_INDEX] = XLATE(horizBlankEnd, 5, NV_CIO_CR_HRE_HBE_5) |
353 XLATE(horizEnd, 0, NV_CIO_CR_HRE_4_0);
354 regp->CRTC[NV_CIO_CR_VDT_INDEX] = vertTotal;
355 regp->CRTC[NV_CIO_CR_OVL_INDEX] = XLATE(vertStart, 9, NV_CIO_CR_OVL_VRS_9) |
356 XLATE(vertDisplay, 9, NV_CIO_CR_OVL_VDE_9) |
357 XLATE(vertTotal, 9, NV_CIO_CR_OVL_VDT_9) |
358 (1 << 4) |
359 XLATE(vertBlankStart, 8, NV_CIO_CR_OVL_VBS_8) |
360 XLATE(vertStart, 8, NV_CIO_CR_OVL_VRS_8) |
361 XLATE(vertDisplay, 8, NV_CIO_CR_OVL_VDE_8) |
362 XLATE(vertTotal, 8, NV_CIO_CR_OVL_VDT_8);
363 regp->CRTC[NV_CIO_CR_RSAL_INDEX] = 0x00;
364 regp->CRTC[NV_CIO_CR_CELL_HT_INDEX] = ((mode->flags & DRM_MODE_FLAG_DBLSCAN) ? MASK(NV_CIO_CR_CELL_HT_SCANDBL) : 0) |
365 1 << 6 |
366 XLATE(vertBlankStart, 9, NV_CIO_CR_CELL_HT_VBS_9);
367 regp->CRTC[NV_CIO_CR_CURS_ST_INDEX] = 0x00;
368 regp->CRTC[NV_CIO_CR_CURS_END_INDEX] = 0x00;
369 regp->CRTC[NV_CIO_CR_SA_HI_INDEX] = 0x00;
370 regp->CRTC[NV_CIO_CR_SA_LO_INDEX] = 0x00;
371 regp->CRTC[NV_CIO_CR_TCOFF_HI_INDEX] = 0x00;
372 regp->CRTC[NV_CIO_CR_TCOFF_LO_INDEX] = 0x00;
373 regp->CRTC[NV_CIO_CR_VRS_INDEX] = vertStart;
374 regp->CRTC[NV_CIO_CR_VRE_INDEX] = 1 << 5 | XLATE(vertEnd, 0, NV_CIO_CR_VRE_3_0);
375 regp->CRTC[NV_CIO_CR_VDE_INDEX] = vertDisplay;
376 /* framebuffer can be larger than crtc scanout area. */
377 regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = fb->pitches[0] / 8;
378 regp->CRTC[NV_CIO_CR_ULINE_INDEX] = 0x00;
379 regp->CRTC[NV_CIO_CR_VBS_INDEX] = vertBlankStart;
380 regp->CRTC[NV_CIO_CR_VBE_INDEX] = vertBlankEnd;
381 regp->CRTC[NV_CIO_CR_MODE_INDEX] = 0x43;
382 regp->CRTC[NV_CIO_CR_LCOMP_INDEX] = 0xff;
383
384 /*
385 * Some extended CRTC registers (they are not saved with the rest of the vga regs).
386 */
387
388 /* framebuffer can be larger than crtc scanout area. */
389 regp->CRTC[NV_CIO_CRE_RPC0_INDEX] =
390 XLATE(fb->pitches[0] / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
391 regp->CRTC[NV_CIO_CRE_42] =
392 XLATE(fb->pitches[0] / 8, 11, NV_CIO_CRE_42_OFFSET_11);
393 regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ?
394 MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00;
395 regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) |
396 XLATE(vertBlankStart, 10, NV_CIO_CRE_LSR_VBS_10) |
397 XLATE(vertStart, 10, NV_CIO_CRE_LSR_VRS_10) |
398 XLATE(vertDisplay, 10, NV_CIO_CRE_LSR_VDE_10) |
399 XLATE(vertTotal, 10, NV_CIO_CRE_LSR_VDT_10);
400 regp->CRTC[NV_CIO_CRE_HEB__INDEX] = XLATE(horizStart, 8, NV_CIO_CRE_HEB_HRS_8) |
401 XLATE(horizBlankStart, 8, NV_CIO_CRE_HEB_HBS_8) |
402 XLATE(horizDisplay, 8, NV_CIO_CRE_HEB_HDE_8) |
403 XLATE(horizTotal, 8, NV_CIO_CRE_HEB_HDT_8);
404 regp->CRTC[NV_CIO_CRE_EBR_INDEX] = XLATE(vertBlankStart, 11, NV_CIO_CRE_EBR_VBS_11) |
405 XLATE(vertStart, 11, NV_CIO_CRE_EBR_VRS_11) |
406 XLATE(vertDisplay, 11, NV_CIO_CRE_EBR_VDE_11) |
407 XLATE(vertTotal, 11, NV_CIO_CRE_EBR_VDT_11);
408
409 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
410 horizTotal = (horizTotal >> 1) & ~1;
411 regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = horizTotal;
412 regp->CRTC[NV_CIO_CRE_HEB__INDEX] |= XLATE(horizTotal, 8, NV_CIO_CRE_HEB_ILC_8);
413 } else
414 regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = 0xff; /* interlace off */
415
416 /*
417 * Graphics Display Controller
418 */
419 regp->Graphics[NV_VIO_GX_SR_INDEX] = 0x00;
420 regp->Graphics[NV_VIO_GX_SREN_INDEX] = 0x00;
421 regp->Graphics[NV_VIO_GX_CCOMP_INDEX] = 0x00;
422 regp->Graphics[NV_VIO_GX_ROP_INDEX] = 0x00;
423 regp->Graphics[NV_VIO_GX_READ_MAP_INDEX] = 0x00;
424 regp->Graphics[NV_VIO_GX_MODE_INDEX] = 0x40; /* 256 color mode */
425 regp->Graphics[NV_VIO_GX_MISC_INDEX] = 0x05; /* map 64k mem + graphic mode */
426 regp->Graphics[NV_VIO_GX_DONT_CARE_INDEX] = 0x0F;
427 regp->Graphics[NV_VIO_GX_BIT_MASK_INDEX] = 0xFF;
428
429 regp->Attribute[0] = 0x00; /* standard colormap translation */
430 regp->Attribute[1] = 0x01;
431 regp->Attribute[2] = 0x02;
432 regp->Attribute[3] = 0x03;
433 regp->Attribute[4] = 0x04;
434 regp->Attribute[5] = 0x05;
435 regp->Attribute[6] = 0x06;
436 regp->Attribute[7] = 0x07;
437 regp->Attribute[8] = 0x08;
438 regp->Attribute[9] = 0x09;
439 regp->Attribute[10] = 0x0A;
440 regp->Attribute[11] = 0x0B;
441 regp->Attribute[12] = 0x0C;
442 regp->Attribute[13] = 0x0D;
443 regp->Attribute[14] = 0x0E;
444 regp->Attribute[15] = 0x0F;
445 regp->Attribute[NV_CIO_AR_MODE_INDEX] = 0x01; /* Enable graphic mode */
446 /* Non-vga */
447 regp->Attribute[NV_CIO_AR_OSCAN_INDEX] = 0x00;
448 regp->Attribute[NV_CIO_AR_PLANE_INDEX] = 0x0F; /* enable all color planes */
449 regp->Attribute[NV_CIO_AR_HPP_INDEX] = 0x00;
450 regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00;
451}
452
453/**
454 * Sets up registers for the given mode/adjusted_mode pair.
455 *
456 * The clocks, CRTCs and outputs attached to this CRTC must be off.
457 *
458 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
459 * be easily turned on/off after this.
460 */
461static void
462nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
463{
464 struct drm_device *dev = crtc->dev;
465 struct nouveau_drm *drm = nouveau_drm(dev);
466 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
467 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
468 struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index];
469 struct drm_encoder *encoder;
470 bool lvds_output = false, tmds_output = false, tv_output = false,
471 off_chip_digital = false;
472
473 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
474 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
475 bool digital = false;
476
477 if (encoder->crtc != crtc)
478 continue;
479
480 if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS)
481 digital = lvds_output = true;
482 if (nv_encoder->dcb->type == DCB_OUTPUT_TV)
483 tv_output = true;
484 if (nv_encoder->dcb->type == DCB_OUTPUT_TMDS)
485 digital = tmds_output = true;
486 if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && digital)
487 off_chip_digital = true;
488 }
489
490 /* Registers not directly related to the (s)vga mode */
491
492 /* What is the meaning of this register? */
493 /* A few popular values are 0x18, 0x1c, 0x38, 0x3c */
494 regp->CRTC[NV_CIO_CRE_ENH_INDEX] = savep->CRTC[NV_CIO_CRE_ENH_INDEX] & ~(1<<5);
495
496 regp->crtc_eng_ctrl = 0;
497 /* Except for rare conditions I2C is enabled on the primary crtc */
498 if (nv_crtc->index == 0)
499 regp->crtc_eng_ctrl |= NV_CRTC_FSEL_I2C;
500#if 0
501 /* Set overlay to desired crtc. */
502 if (dev->overlayAdaptor) {
503 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(dev);
504 if (pPriv->overlayCRTC == nv_crtc->index)
505 regp->crtc_eng_ctrl |= NV_CRTC_FSEL_OVERLAY;
506 }
507#endif
508
509 /* ADDRESS_SPACE_PNVM is the same as setting HCUR_ASI */
510 regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 |
511 NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 |
512 NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM;
513 if (nv_device(drm->device)->chipset >= 0x11)
514 regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32;
515 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
516 regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE;
517
518 /* Unblock some timings */
519 regp->CRTC[NV_CIO_CRE_53] = 0;
520 regp->CRTC[NV_CIO_CRE_54] = 0;
521
522 /* 0x00 is disabled, 0x11 is lvds, 0x22 crt and 0x88 tmds */
523 if (lvds_output)
524 regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x11;
525 else if (tmds_output)
526 regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x88;
527 else
528 regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x22;
529
530 /* These values seem to vary */
531 /* This register seems to be used by the bios to make certain decisions on some G70 cards? */
532 regp->CRTC[NV_CIO_CRE_SCRATCH4__INDEX] = savep->CRTC[NV_CIO_CRE_SCRATCH4__INDEX];
533
534 nv_crtc_set_digital_vibrance(crtc, nv_crtc->saturation);
535
536 /* probably a scratch reg, but kept for cargo-cult purposes:
537 * bit0: crtc0?, head A
538 * bit6: lvds, head A
539 * bit7: (only in X), head A
540 */
541 if (nv_crtc->index == 0)
542 regp->CRTC[NV_CIO_CRE_4B] = savep->CRTC[NV_CIO_CRE_4B] | 0x80;
543
544 /* The blob seems to take the current value from crtc 0, add 4 to that
545 * and reuse the old value for crtc 1 */
546 regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] = nv04_display(dev)->saved_reg.crtc_reg[0].CRTC[NV_CIO_CRE_TVOUT_LATENCY];
547 if (!nv_crtc->index)
548 regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] += 4;
549
550 /* the blob sometimes sets |= 0x10 (which is the same as setting |=
551 * 1 << 30 on 0x60.830), for no apparent reason */
552 regp->CRTC[NV_CIO_CRE_59] = off_chip_digital;
553
554 if (nv_device(drm->device)->card_type >= NV_30)
555 regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1;
556
557 regp->crtc_830 = mode->crtc_vdisplay - 3;
558 regp->crtc_834 = mode->crtc_vdisplay - 1;
559
560 if (nv_device(drm->device)->card_type == NV_40)
561 /* This is what the blob does */
562 regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850);
563
564 if (nv_device(drm->device)->card_type >= NV_30)
565 regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT);
566
567 if (nv_device(drm->device)->card_type >= NV_10)
568 regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC;
569 else
570 regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC;
571
572 /* Some misc regs */
573 if (nv_device(drm->device)->card_type == NV_40) {
574 regp->CRTC[NV_CIO_CRE_85] = 0xFF;
575 regp->CRTC[NV_CIO_CRE_86] = 0x1;
576 }
577
578 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
579 /* Enable slaved mode (called MODE_TV in nv4ref.h) */
580 if (lvds_output || tmds_output || tv_output)
581 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
582
583 /* Generic PRAMDAC regs */
584
585 if (nv_device(drm->device)->card_type >= NV_10)
586 /* Only bit that bios and blob set. */
587 regp->nv10_cursync = (1 << 25);
588
589 regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
590 NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
591 NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
592 if (crtc->fb->depth == 16)
593 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
594 if (nv_device(drm->device)->chipset >= 0x11)
595 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
596
597 regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */
598 regp->tv_setup = 0;
599
600 nv_crtc_set_image_sharpening(crtc, nv_crtc->sharpness);
601
602 /* Some values the blob sets */
603 regp->ramdac_8c0 = 0x100;
604 regp->ramdac_a20 = 0x0;
605 regp->ramdac_a24 = 0xfffff;
606 regp->ramdac_a34 = 0x1;
607}
608
609/**
610 * Sets up registers for the given mode/adjusted_mode pair.
611 *
612 * The clocks, CRTCs and outputs attached to this CRTC must be off.
613 *
614 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
615 * be easily turned on/off after this.
616 */
617static int
618nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
619 struct drm_display_mode *adjusted_mode,
620 int x, int y, struct drm_framebuffer *old_fb)
621{
622 struct drm_device *dev = crtc->dev;
623 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
624 struct nouveau_drm *drm = nouveau_drm(dev);
625
626 NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
627 drm_mode_debug_printmodeline(adjusted_mode);
628
629 /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
630 nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
631
632 nv_crtc_mode_set_vga(crtc, adjusted_mode);
633 /* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */
634 if (nv_device(drm->device)->card_type == NV_40)
635 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, nv04_display(dev)->mode_reg.sel_clk);
636 nv_crtc_mode_set_regs(crtc, adjusted_mode);
637 nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock);
638 return 0;
639}
640
641static void nv_crtc_save(struct drm_crtc *crtc)
642{
643 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
644 struct drm_device *dev = crtc->dev;
645 struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
646 struct nv04_crtc_reg *crtc_state = &state->crtc_reg[nv_crtc->index];
647 struct nv04_mode_state *saved = &nv04_display(dev)->saved_reg;
648 struct nv04_crtc_reg *crtc_saved = &saved->crtc_reg[nv_crtc->index];
649
650 if (nv_two_heads(crtc->dev))
651 NVSetOwner(crtc->dev, nv_crtc->index);
652
653 nouveau_hw_save_state(crtc->dev, nv_crtc->index, saved);
654
655 /* init some state to saved value */
656 state->sel_clk = saved->sel_clk & ~(0x5 << 16);
657 crtc_state->CRTC[NV_CIO_CRE_LCD__INDEX] = crtc_saved->CRTC[NV_CIO_CRE_LCD__INDEX];
658 state->pllsel = saved->pllsel & ~(PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK);
659 crtc_state->gpio_ext = crtc_saved->gpio_ext;
660}
661
662static void nv_crtc_restore(struct drm_crtc *crtc)
663{
664 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
665 struct drm_device *dev = crtc->dev;
666 int head = nv_crtc->index;
667 uint8_t saved_cr21 = nv04_display(dev)->saved_reg.crtc_reg[head].CRTC[NV_CIO_CRE_21];
668
669 if (nv_two_heads(crtc->dev))
670 NVSetOwner(crtc->dev, head);
671
672 nouveau_hw_load_state(crtc->dev, head, &nv04_display(dev)->saved_reg);
673 nv_lock_vga_crtc_shadow(crtc->dev, head, saved_cr21);
674
675 nv_crtc->last_dpms = NV_DPMS_CLEARED;
676}
677
678static void nv_crtc_prepare(struct drm_crtc *crtc)
679{
680 struct drm_device *dev = crtc->dev;
681 struct nouveau_drm *drm = nouveau_drm(dev);
682 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
683 struct drm_crtc_helper_funcs *funcs = crtc->helper_private;
684
685 if (nv_two_heads(dev))
686 NVSetOwner(dev, nv_crtc->index);
687
688 drm_vblank_pre_modeset(dev, nv_crtc->index);
689 funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
690
691 NVBlankScreen(dev, nv_crtc->index, true);
692
693 /* Some more preparation. */
694 NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
695 if (nv_device(drm->device)->card_type == NV_40) {
696 uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900);
697 NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000);
698 }
699}
700
701static void nv_crtc_commit(struct drm_crtc *crtc)
702{
703 struct drm_device *dev = crtc->dev;
704 struct drm_crtc_helper_funcs *funcs = crtc->helper_private;
705 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
706
707 nouveau_hw_load_state(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
708 nv04_crtc_mode_set_base(crtc, crtc->x, crtc->y, NULL);
709
710#ifdef __BIG_ENDIAN
711 /* turn on LFB swapping */
712 {
713 uint8_t tmp = NVReadVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RCR);
714 tmp |= MASK(NV_CIO_CRE_RCR_ENDIAN_BIG);
715 NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RCR, tmp);
716 }
717#endif
718
719 funcs->dpms(crtc, DRM_MODE_DPMS_ON);
720 drm_vblank_post_modeset(dev, nv_crtc->index);
721}
722
723static void nv_crtc_destroy(struct drm_crtc *crtc)
724{
725 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
726
727 if (!nv_crtc)
728 return;
729
730 drm_crtc_cleanup(crtc);
731
732 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
733 nouveau_bo_unpin(nv_crtc->cursor.nvbo);
734 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
735 kfree(nv_crtc);
736}
737
738static void
739nv_crtc_gamma_load(struct drm_crtc *crtc)
740{
741 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
742 struct drm_device *dev = nv_crtc->base.dev;
743 struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs;
744 int i;
745
746 rgbs = (struct rgb *)nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index].DAC;
747 for (i = 0; i < 256; i++) {
748 rgbs[i].r = nv_crtc->lut.r[i] >> 8;
749 rgbs[i].g = nv_crtc->lut.g[i] >> 8;
750 rgbs[i].b = nv_crtc->lut.b[i] >> 8;
751 }
752
753 nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
754}
755
756static void
757nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
758 uint32_t size)
759{
760 int end = (start + size > 256) ? 256 : start + size, i;
761 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
762
763 for (i = start; i < end; i++) {
764 nv_crtc->lut.r[i] = r[i];
765 nv_crtc->lut.g[i] = g[i];
766 nv_crtc->lut.b[i] = b[i];
767 }
768
769 /* We need to know the depth before we upload, but it's possible to
770 * get called before a framebuffer is bound. If this is the case,
771 * mark the lut values as dirty by setting depth==0, and it'll be
772 * uploaded on the first mode_set_base()
773 */
774 if (!nv_crtc->base.fb) {
775 nv_crtc->lut.depth = 0;
776 return;
777 }
778
779 nv_crtc_gamma_load(crtc);
780}
781
782static int
783nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
784 struct drm_framebuffer *passed_fb,
785 int x, int y, bool atomic)
786{
787 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
788 struct drm_device *dev = crtc->dev;
789 struct nouveau_drm *drm = nouveau_drm(dev);
790 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
791 struct drm_framebuffer *drm_fb;
792 struct nouveau_framebuffer *fb;
793 int arb_burst, arb_lwm;
794 int ret;
795
796 NV_DEBUG(drm, "index %d\n", nv_crtc->index);
797
798 /* no fb bound */
799 if (!atomic && !crtc->fb) {
800 NV_DEBUG(drm, "No FB bound\n");
801 return 0;
802 }
803
804
805 /* If atomic, we want to switch to the fb we were passed, so
806 * now we update pointers to do that. (We don't pin; just
807 * assume we're already pinned and update the base address.)
808 */
809 if (atomic) {
810 drm_fb = passed_fb;
811 fb = nouveau_framebuffer(passed_fb);
812 } else {
813 drm_fb = crtc->fb;
814 fb = nouveau_framebuffer(crtc->fb);
815 /* If not atomic, we can go ahead and pin, and unpin the
816 * old fb we were passed.
817 */
818 ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
819 if (ret)
820 return ret;
821
822 if (passed_fb) {
823 struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
824 nouveau_bo_unpin(ofb->nvbo);
825 }
826 }
827
828 nv_crtc->fb.offset = fb->nvbo->bo.offset;
829
830 if (nv_crtc->lut.depth != drm_fb->depth) {
831 nv_crtc->lut.depth = drm_fb->depth;
832 nv_crtc_gamma_load(crtc);
833 }
834
835 /* Update the framebuffer format. */
836 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
837 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
838 regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
839 if (crtc->fb->depth == 16)
840 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
841 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
842 NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
843 regp->ramdac_gen_ctrl);
844
845 regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitches[0] >> 3;
846 regp->CRTC[NV_CIO_CRE_RPC0_INDEX] =
847 XLATE(drm_fb->pitches[0] >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
848 regp->CRTC[NV_CIO_CRE_42] =
849 XLATE(drm_fb->pitches[0] / 8, 11, NV_CIO_CRE_42_OFFSET_11);
850 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX);
851 crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX);
852 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_42);
853
854 /* Update the framebuffer location. */
855 regp->fb_start = nv_crtc->fb.offset & ~3;
856 regp->fb_start += (y * drm_fb->pitches[0]) + (x * drm_fb->bits_per_pixel / 8);
857 nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start);
858
859 /* Update the arbitration parameters. */
860 nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel,
861 &arb_burst, &arb_lwm);
862
863 regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst;
864 regp->CRTC[NV_CIO_CRE_FFLWM__INDEX] = arb_lwm & 0xff;
865 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX);
866 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX);
867
868 if (nv_device(drm->device)->card_type >= NV_20) {
869 regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8;
870 crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
871 }
872
873 return 0;
874}
875
876static int
877nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
878 struct drm_framebuffer *old_fb)
879{
880 return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
881}
882
883static int
884nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
885 struct drm_framebuffer *fb,
886 int x, int y, enum mode_set_atomic state)
887{
888 struct nouveau_drm *drm = nouveau_drm(crtc->dev);
889 struct drm_device *dev = drm->dev;
890
891 if (state == ENTER_ATOMIC_MODE_SET)
892 nouveau_fbcon_save_disable_accel(dev);
893 else
894 nouveau_fbcon_restore_accel(dev);
895
896 return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true);
897}
898
899static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
900 struct nouveau_bo *dst)
901{
902 int width = nv_cursor_width(dev);
903 uint32_t pixel;
904 int i, j;
905
906 for (i = 0; i < width; i++) {
907 for (j = 0; j < width; j++) {
908 pixel = nouveau_bo_rd32(src, i*64 + j);
909
910 nouveau_bo_wr16(dst, i*width + j, (pixel & 0x80000000) >> 16
911 | (pixel & 0xf80000) >> 9
912 | (pixel & 0xf800) >> 6
913 | (pixel & 0xf8) >> 3);
914 }
915 }
916}
917
918static void nv11_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
919 struct nouveau_bo *dst)
920{
921 uint32_t pixel;
922 int alpha, i;
923
924 /* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) alpha
925 * cursors (though NPM in combination with fp dithering may not work on
926 * nv11, from "nv" driver history)
927 * NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND set and is what the
928 * blob uses, however we get given PM cursors so we use PM mode
929 */
930 for (i = 0; i < 64 * 64; i++) {
931 pixel = nouveau_bo_rd32(src, i);
932
933 /* hw gets unhappy if alpha <= rgb values. for a PM image "less
934 * than" shouldn't happen; fix "equal to" case by adding one to
935 * alpha channel (slightly inaccurate, but so is attempting to
936 * get back to NPM images, due to limits of integer precision)
937 */
938 alpha = pixel >> 24;
939 if (alpha > 0 && alpha < 255)
940 pixel = (pixel & 0x00ffffff) | ((alpha + 1) << 24);
941
942#ifdef __BIG_ENDIAN
943 {
944 struct nouveau_drm *drm = nouveau_drm(dev);
945
946 if (nv_device(drm->device)->chipset == 0x11) {
947 pixel = ((pixel & 0x000000ff) << 24) |
948 ((pixel & 0x0000ff00) << 8) |
949 ((pixel & 0x00ff0000) >> 8) |
950 ((pixel & 0xff000000) >> 24);
951 }
952 }
953#endif
954
955 nouveau_bo_wr32(dst, i, pixel);
956 }
957}
958
959static int
960nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
961 uint32_t buffer_handle, uint32_t width, uint32_t height)
962{
963 struct nouveau_drm *drm = nouveau_drm(crtc->dev);
964 struct drm_device *dev = drm->dev;
965 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
966 struct nouveau_bo *cursor = NULL;
967 struct drm_gem_object *gem;
968 int ret = 0;
969
970 if (!buffer_handle) {
971 nv_crtc->cursor.hide(nv_crtc, true);
972 return 0;
973 }
974
975 if (width != 64 || height != 64)
976 return -EINVAL;
977
978 gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
979 if (!gem)
980 return -ENOENT;
981 cursor = nouveau_gem_object(gem);
982
983 ret = nouveau_bo_map(cursor);
984 if (ret)
985 goto out;
986
987 if (nv_device(drm->device)->chipset >= 0x11)
988 nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
989 else
990 nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
991
992 nouveau_bo_unmap(cursor);
993 nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->bo.offset;
994 nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
995 nv_crtc->cursor.show(nv_crtc, true);
996out:
997 drm_gem_object_unreference_unlocked(gem);
998 return ret;
999}
1000
1001static int
1002nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
1003{
1004 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
1005
1006 nv_crtc->cursor.set_pos(nv_crtc, x, y);
1007 return 0;
1008}
1009
1010static const struct drm_crtc_funcs nv04_crtc_funcs = {
1011 .save = nv_crtc_save,
1012 .restore = nv_crtc_restore,
1013 .cursor_set = nv04_crtc_cursor_set,
1014 .cursor_move = nv04_crtc_cursor_move,
1015 .gamma_set = nv_crtc_gamma_set,
1016 .set_config = drm_crtc_helper_set_config,
1017 .page_flip = nouveau_crtc_page_flip,
1018 .destroy = nv_crtc_destroy,
1019};
1020
1021static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
1022 .dpms = nv_crtc_dpms,
1023 .prepare = nv_crtc_prepare,
1024 .commit = nv_crtc_commit,
1025 .mode_fixup = nv_crtc_mode_fixup,
1026 .mode_set = nv_crtc_mode_set,
1027 .mode_set_base = nv04_crtc_mode_set_base,
1028 .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
1029 .load_lut = nv_crtc_gamma_load,
1030};
1031
1032int
1033nv04_crtc_create(struct drm_device *dev, int crtc_num)
1034{
1035 struct nouveau_crtc *nv_crtc;
1036 int ret, i;
1037
1038 nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
1039 if (!nv_crtc)
1040 return -ENOMEM;
1041
1042 for (i = 0; i < 256; i++) {
1043 nv_crtc->lut.r[i] = i << 8;
1044 nv_crtc->lut.g[i] = i << 8;
1045 nv_crtc->lut.b[i] = i << 8;
1046 }
1047 nv_crtc->lut.depth = 0;
1048
1049 nv_crtc->index = crtc_num;
1050 nv_crtc->last_dpms = NV_DPMS_CLEARED;
1051
1052 drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs);
1053 drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
1054 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
1055
1056 ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
1057 0, 0x0000, NULL, &nv_crtc->cursor.nvbo);
1058 if (!ret) {
1059 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
1060 if (!ret) {
1061 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
1062 if (ret)
1063 nouveau_bo_unpin(nv_crtc->cursor.nvbo);
1064 }
1065 if (ret)
1066 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
1067 }
1068
1069 nv04_cursor_init(nv_crtc);
1070
1071 return 0;
1072}