2 * Copyright 2008 Stuart Bennett
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 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #ifndef __NOUVEAU_HW_H__
24 #define __NOUVEAU_HW_H__
30 #include <subdev/bios/pll.h>
32 #define MASK(field) ( \
33 (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field))
35 #define XLATE(src, srclowbit, outfield) ( \
36 (((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield))
38 void NVWriteVgaSeq(struct drm_device
*, int head
, uint8_t index
, uint8_t value
);
39 uint8_t NVReadVgaSeq(struct drm_device
*, int head
, uint8_t index
);
40 void NVWriteVgaGr(struct drm_device
*, int head
, uint8_t index
, uint8_t value
);
41 uint8_t NVReadVgaGr(struct drm_device
*, int head
, uint8_t index
);
42 void NVSetOwner(struct drm_device
*, int owner
);
43 void NVBlankScreen(struct drm_device
*, int head
, bool blank
);
44 int nouveau_hw_get_pllvals(struct drm_device
*, enum nvbios_pll_type plltype
,
45 struct nvkm_pll_vals
*pllvals
);
46 int nouveau_hw_pllvals_to_clk(struct nvkm_pll_vals
*pllvals
);
47 int nouveau_hw_get_clock(struct drm_device
*, enum nvbios_pll_type plltype
);
48 void nouveau_hw_save_vga_fonts(struct drm_device
*, bool save
);
49 void nouveau_hw_save_state(struct drm_device
*, int head
,
50 struct nv04_mode_state
*state
);
51 void nouveau_hw_load_state(struct drm_device
*, int head
,
52 struct nv04_mode_state
*state
);
53 void nouveau_hw_load_state_palette(struct drm_device
*, int head
,
54 struct nv04_mode_state
*state
);
57 extern void nouveau_calc_arb(struct drm_device
*, int vclk
, int bpp
,
58 int *burst
, int *lwm
);
60 static inline uint32_t NVReadCRTC(struct drm_device
*dev
,
61 int head
, uint32_t reg
)
63 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
66 reg
+= NV_PCRTC0_SIZE
;
67 val
= nvif_rd32(device
, reg
);
71 static inline void NVWriteCRTC(struct drm_device
*dev
,
72 int head
, uint32_t reg
, uint32_t val
)
74 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
76 reg
+= NV_PCRTC0_SIZE
;
77 nvif_wr32(device
, reg
, val
);
80 static inline uint32_t NVReadRAMDAC(struct drm_device
*dev
,
81 int head
, uint32_t reg
)
83 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
86 reg
+= NV_PRAMDAC0_SIZE
;
87 val
= nvif_rd32(device
, reg
);
91 static inline void NVWriteRAMDAC(struct drm_device
*dev
,
92 int head
, uint32_t reg
, uint32_t val
)
94 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
96 reg
+= NV_PRAMDAC0_SIZE
;
97 nvif_wr32(device
, reg
, val
);
100 static inline uint8_t nv_read_tmds(struct drm_device
*dev
,
101 int or, int dl
, uint8_t address
)
103 int ramdac
= (or & DCB_OUTPUT_C
) >> 2;
105 NVWriteRAMDAC(dev
, ramdac
, NV_PRAMDAC_FP_TMDS_CONTROL
+ dl
* 8,
106 NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE
| address
);
107 return NVReadRAMDAC(dev
, ramdac
, NV_PRAMDAC_FP_TMDS_DATA
+ dl
* 8);
110 static inline void nv_write_tmds(struct drm_device
*dev
,
111 int or, int dl
, uint8_t address
,
114 int ramdac
= (or & DCB_OUTPUT_C
) >> 2;
116 NVWriteRAMDAC(dev
, ramdac
, NV_PRAMDAC_FP_TMDS_DATA
+ dl
* 8, data
);
117 NVWriteRAMDAC(dev
, ramdac
, NV_PRAMDAC_FP_TMDS_CONTROL
+ dl
* 8, address
);
120 static inline void NVWriteVgaCrtc(struct drm_device
*dev
,
121 int head
, uint8_t index
, uint8_t value
)
123 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
124 nvif_wr08(device
, NV_PRMCIO_CRX__COLOR
+ head
* NV_PRMCIO_SIZE
, index
);
125 nvif_wr08(device
, NV_PRMCIO_CR__COLOR
+ head
* NV_PRMCIO_SIZE
, value
);
128 static inline uint8_t NVReadVgaCrtc(struct drm_device
*dev
,
129 int head
, uint8_t index
)
131 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
133 nvif_wr08(device
, NV_PRMCIO_CRX__COLOR
+ head
* NV_PRMCIO_SIZE
, index
);
134 val
= nvif_rd08(device
, NV_PRMCIO_CR__COLOR
+ head
* NV_PRMCIO_SIZE
);
138 /* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
139 * I suspect they in fact do nothing, but are merely a way to carry useful
140 * per-head variables around
144 * 0x00 index to the appropriate dcb entry (or 7f for inactive)
145 * 0x02 dcb entry's "or" value (or 00 for inactive)
146 * 0x03 bit0 set for dual link (LVDS, possibly elsewhere too)
147 * 0x08 or 0x09 pxclk in MHz
148 * 0x0f laptop panel info - low nibble for PEXTDEV_BOOT_0 strap
149 * high nibble for xlat strap value
153 NVWriteVgaCrtc5758(struct drm_device
*dev
, int head
, uint8_t index
, uint8_t value
)
155 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_57
, index
);
156 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_58
, value
);
159 static inline uint8_t NVReadVgaCrtc5758(struct drm_device
*dev
, int head
, uint8_t index
)
161 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_57
, index
);
162 return NVReadVgaCrtc(dev
, head
, NV_CIO_CRE_58
);
165 static inline uint8_t NVReadPRMVIO(struct drm_device
*dev
,
166 int head
, uint32_t reg
)
168 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
169 struct nouveau_drm
*drm
= nouveau_drm(dev
);
172 /* Only NV4x have two pvio ranges; other twoHeads cards MUST call
173 * NVSetOwner for the relevant head to be programmed */
174 if (head
&& drm
->device
.info
.family
== NV_DEVICE_INFO_V0_CURIE
)
175 reg
+= NV_PRMVIO_SIZE
;
177 val
= nvif_rd08(device
, reg
);
181 static inline void NVWritePRMVIO(struct drm_device
*dev
,
182 int head
, uint32_t reg
, uint8_t value
)
184 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
185 struct nouveau_drm
*drm
= nouveau_drm(dev
);
187 /* Only NV4x have two pvio ranges; other twoHeads cards MUST call
188 * NVSetOwner for the relevant head to be programmed */
189 if (head
&& drm
->device
.info
.family
== NV_DEVICE_INFO_V0_CURIE
)
190 reg
+= NV_PRMVIO_SIZE
;
192 nvif_wr08(device
, reg
, value
);
195 static inline void NVSetEnablePalette(struct drm_device
*dev
, int head
, bool enable
)
197 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
198 nvif_rd08(device
, NV_PRMCIO_INP0__COLOR
+ head
* NV_PRMCIO_SIZE
);
199 nvif_wr08(device
, NV_PRMCIO_ARX
+ head
* NV_PRMCIO_SIZE
, enable
? 0 : 0x20);
202 static inline bool NVGetEnablePalette(struct drm_device
*dev
, int head
)
204 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
205 nvif_rd08(device
, NV_PRMCIO_INP0__COLOR
+ head
* NV_PRMCIO_SIZE
);
206 return !(nvif_rd08(device
, NV_PRMCIO_ARX
+ head
* NV_PRMCIO_SIZE
) & 0x20);
209 static inline void NVWriteVgaAttr(struct drm_device
*dev
,
210 int head
, uint8_t index
, uint8_t value
)
212 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
213 if (NVGetEnablePalette(dev
, head
))
218 nvif_rd08(device
, NV_PRMCIO_INP0__COLOR
+ head
* NV_PRMCIO_SIZE
);
219 nvif_wr08(device
, NV_PRMCIO_ARX
+ head
* NV_PRMCIO_SIZE
, index
);
220 nvif_wr08(device
, NV_PRMCIO_AR__WRITE
+ head
* NV_PRMCIO_SIZE
, value
);
223 static inline uint8_t NVReadVgaAttr(struct drm_device
*dev
,
224 int head
, uint8_t index
)
226 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
228 if (NVGetEnablePalette(dev
, head
))
233 nvif_rd08(device
, NV_PRMCIO_INP0__COLOR
+ head
* NV_PRMCIO_SIZE
);
234 nvif_wr08(device
, NV_PRMCIO_ARX
+ head
* NV_PRMCIO_SIZE
, index
);
235 val
= nvif_rd08(device
, NV_PRMCIO_AR__READ
+ head
* NV_PRMCIO_SIZE
);
239 static inline void NVVgaSeqReset(struct drm_device
*dev
, int head
, bool start
)
241 NVWriteVgaSeq(dev
, head
, NV_VIO_SR_RESET_INDEX
, start
? 0x1 : 0x3);
244 static inline void NVVgaProtect(struct drm_device
*dev
, int head
, bool protect
)
246 uint8_t seq1
= NVReadVgaSeq(dev
, head
, NV_VIO_SR_CLOCK_INDEX
);
249 NVVgaSeqReset(dev
, head
, true);
250 NVWriteVgaSeq(dev
, head
, NV_VIO_SR_CLOCK_INDEX
, seq1
| 0x20);
252 /* Reenable sequencer, then turn on screen */
253 NVWriteVgaSeq(dev
, head
, NV_VIO_SR_CLOCK_INDEX
, seq1
& ~0x20); /* reenable display */
254 NVVgaSeqReset(dev
, head
, false);
256 NVSetEnablePalette(dev
, head
, protect
);
260 nv_heads_tied(struct drm_device
*dev
)
262 struct nvif_device
*device
= &nouveau_drm(dev
)->device
;
263 struct nouveau_drm
*drm
= nouveau_drm(dev
);
265 if (drm
->device
.info
.chipset
== 0x11)
266 return !!(nvif_rd32(device
, NV_PBUS_DEBUG_1
) & (1 << 28));
268 return NVReadVgaCrtc(dev
, 0, NV_CIO_CRE_44
) & 0x4;
271 /* makes cr0-7 on the specified head read-only */
273 nv_lock_vga_crtc_base(struct drm_device
*dev
, int head
, bool lock
)
275 uint8_t cr11
= NVReadVgaCrtc(dev
, head
, NV_CIO_CR_VRE_INDEX
);
276 bool waslocked
= cr11
& 0x80;
282 NVWriteVgaCrtc(dev
, head
, NV_CIO_CR_VRE_INDEX
, cr11
);
288 nv_lock_vga_crtc_shadow(struct drm_device
*dev
, int head
, int lock
)
290 /* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
291 * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
292 * bit6: seems to have some effect on CR09 (double scan, VBS_9)
295 * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
296 * bit2: same as bit 1 of 0x60?804
297 * bit0: same as bit 0 of 0x60?804
303 /* 0xfa is generic "unlock all" mask */
304 cr21
= NVReadVgaCrtc(dev
, head
, NV_CIO_CRE_21
) | 0xfa;
306 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_21
, cr21
);
309 /* renders the extended crtc regs (cr19+) on all crtcs impervious:
310 * immutable and unreadable
313 NVLockVgaCrtcs(struct drm_device
*dev
, bool lock
)
315 struct nouveau_drm
*drm
= nouveau_drm(dev
);
316 bool waslocked
= !NVReadVgaCrtc(dev
, 0, NV_CIO_SR_LOCK_INDEX
);
318 NVWriteVgaCrtc(dev
, 0, NV_CIO_SR_LOCK_INDEX
,
319 lock
? NV_CIO_SR_LOCK_VALUE
: NV_CIO_SR_UNLOCK_RW_VALUE
);
320 /* NV11 has independently lockable extended crtcs, except when tied */
321 if (drm
->device
.info
.chipset
== 0x11 && !nv_heads_tied(dev
))
322 NVWriteVgaCrtc(dev
, 1, NV_CIO_SR_LOCK_INDEX
,
323 lock
? NV_CIO_SR_LOCK_VALUE
:
324 NV_CIO_SR_UNLOCK_RW_VALUE
);
329 /* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
330 #define NV04_CURSOR_SIZE 32
331 /* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
332 #define NV10_CURSOR_SIZE 64
334 static inline int nv_cursor_width(struct drm_device
*dev
)
336 struct nouveau_drm
*drm
= nouveau_drm(dev
);
338 return drm
->device
.info
.family
>= NV_DEVICE_INFO_V0_CELSIUS
? NV10_CURSOR_SIZE
: NV04_CURSOR_SIZE
;
342 nv_fix_nv40_hw_cursor(struct drm_device
*dev
, int head
)
344 /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
345 * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
346 * for changes to the CRTC CURCTL regs to take effect, whether changing
347 * the pixmap location, or just showing/hiding the cursor
349 uint32_t curpos
= NVReadRAMDAC(dev
, head
, NV_PRAMDAC_CU_START_POS
);
350 NVWriteRAMDAC(dev
, head
, NV_PRAMDAC_CU_START_POS
, curpos
);
354 nv_set_crtc_base(struct drm_device
*dev
, int head
, uint32_t offset
)
356 struct nouveau_drm
*drm
= nouveau_drm(dev
);
358 NVWriteCRTC(dev
, head
, NV_PCRTC_START
, offset
);
360 if (drm
->device
.info
.family
== NV_DEVICE_INFO_V0_TNT
) {
362 * Hilarious, the 24th bit doesn't want to stick to
365 int cre_heb
= NVReadVgaCrtc(dev
, head
, NV_CIO_CRE_HEB__INDEX
);
367 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_HEB__INDEX
,
368 (cre_heb
& ~0x40) | ((offset
>> 18) & 0x40));
373 nv_show_cursor(struct drm_device
*dev
, int head
, bool show
)
375 struct nouveau_drm
*drm
= nouveau_drm(dev
);
377 &nv04_display(dev
)->mode_reg
.crtc_reg
[head
].CRTC
[NV_CIO_CRE_HCUR_ADDR1_INDEX
];
380 *curctl1
|= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE
);
382 *curctl1
&= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE
);
383 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_HCUR_ADDR1_INDEX
, *curctl1
);
385 if (drm
->device
.info
.family
== NV_DEVICE_INFO_V0_CURIE
)
386 nv_fix_nv40_hw_cursor(dev
, head
);
389 static inline uint32_t
390 nv_pitch_align(struct drm_device
*dev
, uint32_t width
, int bpp
)
392 struct nouveau_drm
*drm
= nouveau_drm(dev
);
400 /* Alignment requirements taken from the Haiku driver */
401 if (drm
->device
.info
.family
== NV_DEVICE_INFO_V0_TNT
)
402 mask
= 128 / bpp
- 1;
404 mask
= 512 / bpp
- 1;
406 return (width
+ mask
) & ~mask
;
409 #endif /* __NOUVEAU_HW_H__ */