Commit | Line | Data |
---|---|---|
6ee73861 BS |
1 | /* |
2 | * Copyright 2008 Stuart Bennett | |
3 | * | |
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: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
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 | |
20 | * SOFTWARE. | |
21 | */ | |
22 | ||
23 | #ifndef __NOUVEAU_HW_H__ | |
24 | #define __NOUVEAU_HW_H__ | |
25 | ||
760285e7 | 26 | #include <drm/drmP.h> |
6ee73861 BS |
27 | #include "nouveau_drv.h" |
28 | ||
29 | #define MASK(field) ( \ | |
30 | (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field)) | |
31 | ||
32 | #define XLATE(src, srclowbit, outfield) ( \ | |
33 | (((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield)) | |
34 | ||
35 | void NVWriteVgaSeq(struct drm_device *, int head, uint8_t index, uint8_t value); | |
36 | uint8_t NVReadVgaSeq(struct drm_device *, int head, uint8_t index); | |
37 | void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value); | |
38 | uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index); | |
39 | void NVSetOwner(struct drm_device *, int owner); | |
40 | void NVBlankScreen(struct drm_device *, int head, bool blank); | |
41 | void nouveau_hw_setpll(struct drm_device *, uint32_t reg1, | |
42 | struct nouveau_pll_vals *pv); | |
43 | int nouveau_hw_get_pllvals(struct drm_device *, enum pll_types plltype, | |
44 | struct nouveau_pll_vals *pllvals); | |
45 | int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals); | |
46 | int nouveau_hw_get_clock(struct drm_device *, enum pll_types plltype); | |
47 | void nouveau_hw_save_vga_fonts(struct drm_device *, bool save); | |
48 | void nouveau_hw_save_state(struct drm_device *, int head, | |
49 | struct nv04_mode_state *state); | |
50 | void nouveau_hw_load_state(struct drm_device *, int head, | |
51 | struct nv04_mode_state *state); | |
52 | void nouveau_hw_load_state_palette(struct drm_device *, int head, | |
53 | struct nv04_mode_state *state); | |
54 | ||
55 | /* nouveau_calc.c */ | |
56 | extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, | |
57 | int *burst, int *lwm); | |
58 | extern int nouveau_calc_pll_mnp(struct drm_device *, struct pll_lims *pll_lim, | |
59 | int clk, struct nouveau_pll_vals *pv); | |
60 | ||
61 | static inline uint32_t | |
62 | nvReadMC(struct drm_device *dev, uint32_t reg) | |
63 | { | |
64 | uint32_t val = nv_rd32(dev, reg); | |
65 | NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val); | |
66 | return val; | |
67 | } | |
68 | ||
69 | static inline void | |
70 | nvWriteMC(struct drm_device *dev, uint32_t reg, uint32_t val) | |
71 | { | |
72 | NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val); | |
73 | nv_wr32(dev, reg, val); | |
74 | } | |
75 | ||
76 | static inline uint32_t | |
77 | nvReadVIDEO(struct drm_device *dev, uint32_t reg) | |
78 | { | |
79 | uint32_t val = nv_rd32(dev, reg); | |
80 | NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val); | |
81 | return val; | |
82 | } | |
83 | ||
84 | static inline void | |
85 | nvWriteVIDEO(struct drm_device *dev, uint32_t reg, uint32_t val) | |
86 | { | |
87 | NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val); | |
88 | nv_wr32(dev, reg, val); | |
89 | } | |
90 | ||
91 | static inline uint32_t | |
92 | nvReadFB(struct drm_device *dev, uint32_t reg) | |
93 | { | |
94 | uint32_t val = nv_rd32(dev, reg); | |
95 | NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val); | |
96 | return val; | |
97 | } | |
98 | ||
99 | static inline void | |
100 | nvWriteFB(struct drm_device *dev, uint32_t reg, uint32_t val) | |
101 | { | |
102 | NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val); | |
103 | nv_wr32(dev, reg, val); | |
104 | } | |
105 | ||
106 | static inline uint32_t | |
107 | nvReadEXTDEV(struct drm_device *dev, uint32_t reg) | |
108 | { | |
109 | uint32_t val = nv_rd32(dev, reg); | |
110 | NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val); | |
111 | return val; | |
112 | } | |
113 | ||
114 | static inline void | |
115 | nvWriteEXTDEV(struct drm_device *dev, uint32_t reg, uint32_t val) | |
116 | { | |
117 | NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val); | |
118 | nv_wr32(dev, reg, val); | |
119 | } | |
120 | ||
121 | static inline uint32_t NVReadCRTC(struct drm_device *dev, | |
122 | int head, uint32_t reg) | |
123 | { | |
124 | uint32_t val; | |
125 | if (head) | |
126 | reg += NV_PCRTC0_SIZE; | |
127 | val = nv_rd32(dev, reg); | |
128 | NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val); | |
129 | return val; | |
130 | } | |
131 | ||
132 | static inline void NVWriteCRTC(struct drm_device *dev, | |
133 | int head, uint32_t reg, uint32_t val) | |
134 | { | |
135 | if (head) | |
136 | reg += NV_PCRTC0_SIZE; | |
137 | NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val); | |
138 | nv_wr32(dev, reg, val); | |
139 | } | |
140 | ||
141 | static inline uint32_t NVReadRAMDAC(struct drm_device *dev, | |
142 | int head, uint32_t reg) | |
143 | { | |
144 | uint32_t val; | |
145 | if (head) | |
146 | reg += NV_PRAMDAC0_SIZE; | |
147 | val = nv_rd32(dev, reg); | |
148 | NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n", | |
149 | head, reg, val); | |
150 | return val; | |
151 | } | |
152 | ||
153 | static inline void NVWriteRAMDAC(struct drm_device *dev, | |
154 | int head, uint32_t reg, uint32_t val) | |
155 | { | |
156 | if (head) | |
157 | reg += NV_PRAMDAC0_SIZE; | |
158 | NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n", | |
159 | head, reg, val); | |
160 | nv_wr32(dev, reg, val); | |
161 | } | |
162 | ||
163 | static inline uint8_t nv_read_tmds(struct drm_device *dev, | |
164 | int or, int dl, uint8_t address) | |
165 | { | |
166 | int ramdac = (or & OUTPUT_C) >> 2; | |
167 | ||
168 | NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, | |
169 | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address); | |
170 | return NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8); | |
171 | } | |
172 | ||
173 | static inline void nv_write_tmds(struct drm_device *dev, | |
174 | int or, int dl, uint8_t address, | |
175 | uint8_t data) | |
176 | { | |
177 | int ramdac = (or & OUTPUT_C) >> 2; | |
178 | ||
179 | NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data); | |
180 | NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address); | |
181 | } | |
182 | ||
183 | static inline void NVWriteVgaCrtc(struct drm_device *dev, | |
184 | int head, uint8_t index, uint8_t value) | |
185 | { | |
186 | NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n", | |
187 | head, index, value); | |
188 | nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); | |
189 | nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); | |
190 | } | |
191 | ||
192 | static inline uint8_t NVReadVgaCrtc(struct drm_device *dev, | |
193 | int head, uint8_t index) | |
194 | { | |
195 | uint8_t val; | |
196 | nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); | |
197 | val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); | |
198 | NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n", | |
199 | head, index, val); | |
200 | return val; | |
201 | } | |
202 | ||
203 | /* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58 | |
204 | * I suspect they in fact do nothing, but are merely a way to carry useful | |
205 | * per-head variables around | |
206 | * | |
207 | * Known uses: | |
208 | * CR57 CR58 | |
209 | * 0x00 index to the appropriate dcb entry (or 7f for inactive) | |
210 | * 0x02 dcb entry's "or" value (or 00 for inactive) | |
211 | * 0x03 bit0 set for dual link (LVDS, possibly elsewhere too) | |
212 | * 0x08 or 0x09 pxclk in MHz | |
213 | * 0x0f laptop panel info - low nibble for PEXTDEV_BOOT_0 strap | |
214 | * high nibble for xlat strap value | |
215 | */ | |
216 | ||
217 | static inline void | |
218 | NVWriteVgaCrtc5758(struct drm_device *dev, int head, uint8_t index, uint8_t value) | |
219 | { | |
220 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index); | |
221 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_58, value); | |
222 | } | |
223 | ||
224 | static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_t index) | |
225 | { | |
226 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index); | |
227 | return NVReadVgaCrtc(dev, head, NV_CIO_CRE_58); | |
228 | } | |
229 | ||
230 | static inline uint8_t NVReadPRMVIO(struct drm_device *dev, | |
231 | int head, uint32_t reg) | |
232 | { | |
233 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
234 | uint8_t val; | |
235 | ||
236 | /* Only NV4x have two pvio ranges; other twoHeads cards MUST call | |
237 | * NVSetOwner for the relevant head to be programmed */ | |
238 | if (head && dev_priv->card_type == NV_40) | |
239 | reg += NV_PRMVIO_SIZE; | |
240 | ||
241 | val = nv_rd08(dev, reg); | |
242 | NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", head, reg, val); | |
243 | return val; | |
244 | } | |
245 | ||
246 | static inline void NVWritePRMVIO(struct drm_device *dev, | |
247 | int head, uint32_t reg, uint8_t value) | |
248 | { | |
249 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
250 | ||
251 | /* Only NV4x have two pvio ranges; other twoHeads cards MUST call | |
252 | * NVSetOwner for the relevant head to be programmed */ | |
253 | if (head && dev_priv->card_type == NV_40) | |
254 | reg += NV_PRMVIO_SIZE; | |
255 | ||
256 | NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", | |
257 | head, reg, value); | |
258 | nv_wr08(dev, reg, value); | |
259 | } | |
260 | ||
261 | static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable) | |
262 | { | |
263 | nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | |
264 | nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); | |
265 | } | |
266 | ||
267 | static inline bool NVGetEnablePalette(struct drm_device *dev, int head) | |
268 | { | |
269 | nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | |
270 | return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); | |
271 | } | |
272 | ||
273 | static inline void NVWriteVgaAttr(struct drm_device *dev, | |
274 | int head, uint8_t index, uint8_t value) | |
275 | { | |
276 | if (NVGetEnablePalette(dev, head)) | |
277 | index &= ~0x20; | |
278 | else | |
279 | index |= 0x20; | |
280 | ||
281 | nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | |
282 | NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n", | |
283 | head, index, value); | |
284 | nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); | |
285 | nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); | |
286 | } | |
287 | ||
288 | static inline uint8_t NVReadVgaAttr(struct drm_device *dev, | |
289 | int head, uint8_t index) | |
290 | { | |
291 | uint8_t val; | |
292 | if (NVGetEnablePalette(dev, head)) | |
293 | index &= ~0x20; | |
294 | else | |
295 | index |= 0x20; | |
296 | ||
297 | nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | |
298 | nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); | |
299 | val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); | |
300 | NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n", | |
301 | head, index, val); | |
302 | return val; | |
303 | } | |
304 | ||
305 | static inline void NVVgaSeqReset(struct drm_device *dev, int head, bool start) | |
306 | { | |
307 | NVWriteVgaSeq(dev, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3); | |
308 | } | |
309 | ||
310 | static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect) | |
311 | { | |
312 | uint8_t seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX); | |
313 | ||
314 | if (protect) { | |
315 | NVVgaSeqReset(dev, head, true); | |
316 | NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20); | |
317 | } else { | |
318 | /* Reenable sequencer, then turn on screen */ | |
319 | NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20); /* reenable display */ | |
320 | NVVgaSeqReset(dev, head, false); | |
321 | } | |
322 | NVSetEnablePalette(dev, head, protect); | |
323 | } | |
324 | ||
325 | static inline bool | |
326 | nv_heads_tied(struct drm_device *dev) | |
327 | { | |
328 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
329 | ||
330 | if (dev_priv->chipset == 0x11) | |
331 | return !!(nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28)); | |
332 | ||
333 | return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4; | |
334 | } | |
335 | ||
336 | /* makes cr0-7 on the specified head read-only */ | |
337 | static inline bool | |
338 | nv_lock_vga_crtc_base(struct drm_device *dev, int head, bool lock) | |
339 | { | |
340 | uint8_t cr11 = NVReadVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX); | |
341 | bool waslocked = cr11 & 0x80; | |
342 | ||
343 | if (lock) | |
344 | cr11 |= 0x80; | |
345 | else | |
346 | cr11 &= ~0x80; | |
347 | NVWriteVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX, cr11); | |
348 | ||
349 | return waslocked; | |
350 | } | |
351 | ||
352 | static inline void | |
353 | nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock) | |
354 | { | |
355 | /* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs | |
356 | * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB | |
357 | * bit6: seems to have some effect on CR09 (double scan, VBS_9) | |
358 | * bit5: unlocks HDE | |
359 | * bit4: unlocks VDE | |
360 | * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR | |
361 | * bit2: same as bit 1 of 0x60?804 | |
362 | * bit0: same as bit 0 of 0x60?804 | |
363 | */ | |
364 | ||
365 | uint8_t cr21 = lock; | |
366 | ||
367 | if (lock < 0) | |
368 | /* 0xfa is generic "unlock all" mask */ | |
369 | cr21 = NVReadVgaCrtc(dev, head, NV_CIO_CRE_21) | 0xfa; | |
370 | ||
371 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_21, cr21); | |
372 | } | |
373 | ||
374 | /* renders the extended crtc regs (cr19+) on all crtcs impervious: | |
375 | * immutable and unreadable | |
376 | */ | |
377 | static inline bool | |
378 | NVLockVgaCrtcs(struct drm_device *dev, bool lock) | |
379 | { | |
380 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
381 | bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); | |
382 | ||
383 | NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX, | |
384 | lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); | |
385 | /* NV11 has independently lockable extended crtcs, except when tied */ | |
386 | if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev)) | |
387 | NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX, | |
388 | lock ? NV_CIO_SR_LOCK_VALUE : | |
389 | NV_CIO_SR_UNLOCK_RW_VALUE); | |
390 | ||
391 | return waslocked; | |
392 | } | |
393 | ||
394 | /* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */ | |
395 | #define NV04_CURSOR_SIZE 32 | |
396 | /* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */ | |
397 | #define NV10_CURSOR_SIZE 64 | |
398 | ||
399 | static inline int nv_cursor_width(struct drm_device *dev) | |
400 | { | |
401 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
402 | ||
403 | return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; | |
404 | } | |
405 | ||
406 | static inline void | |
407 | nv_fix_nv40_hw_cursor(struct drm_device *dev, int head) | |
408 | { | |
409 | /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40, | |
410 | * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS | |
411 | * for changes to the CRTC CURCTL regs to take effect, whether changing | |
412 | * the pixmap location, or just showing/hiding the cursor | |
413 | */ | |
414 | uint32_t curpos = NVReadRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS); | |
415 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos); | |
416 | } | |
417 | ||
5794b5fd FJ |
418 | static inline void |
419 | nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) | |
420 | { | |
421 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
422 | ||
423 | NVWriteCRTC(dev, head, NV_PCRTC_START, offset); | |
424 | ||
425 | if (dev_priv->card_type == NV_04) { | |
426 | /* | |
427 | * Hilarious, the 24th bit doesn't want to stick to | |
428 | * PCRTC_START... | |
429 | */ | |
430 | int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX); | |
431 | ||
432 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX, | |
433 | (cre_heb & ~0x40) | ((offset >> 18) & 0x40)); | |
434 | } | |
435 | } | |
436 | ||
6ee73861 BS |
437 | static inline void |
438 | nv_show_cursor(struct drm_device *dev, int head, bool show) | |
439 | { | |
440 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
441 | uint8_t *curctl1 = | |
442 | &dev_priv->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX]; | |
443 | ||
444 | if (show) | |
445 | *curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); | |
446 | else | |
447 | *curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); | |
448 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1); | |
449 | ||
450 | if (dev_priv->card_type == NV_40) | |
451 | nv_fix_nv40_hw_cursor(dev, head); | |
452 | } | |
453 | ||
454 | static inline uint32_t | |
455 | nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) | |
456 | { | |
457 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
458 | int mask; | |
459 | ||
460 | if (bpp == 15) | |
461 | bpp = 16; | |
462 | if (bpp == 24) | |
463 | bpp = 8; | |
464 | ||
465 | /* Alignment requirements taken from the Haiku driver */ | |
466 | if (dev_priv->card_type == NV_04) | |
467 | mask = 128 / bpp - 1; | |
468 | else | |
469 | mask = 512 / bpp - 1; | |
470 | ||
471 | return (width + mask) & ~mask; | |
472 | } | |
473 | ||
474 | #endif /* __NOUVEAU_HW_H__ */ |