Home | History | Annotate | Line # | Download | only in dispnv04
      1  1.2  riastrad /*	$NetBSD: hw.h,v 1.3 2021/12/18 23:45:32 riastradh Exp $	*/
      2  1.2  riastrad 
      3  1.1  riastrad /*
      4  1.1  riastrad  * Copyright 2008 Stuart Bennett
      5  1.1  riastrad  *
      6  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      7  1.1  riastrad  * copy of this software and associated documentation files (the "Software"),
      8  1.1  riastrad  * to deal in the Software without restriction, including without limitation
      9  1.1  riastrad  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  1.1  riastrad  * and/or sell copies of the Software, and to permit persons to whom the
     11  1.1  riastrad  * Software is furnished to do so, subject to the following conditions:
     12  1.1  riastrad  *
     13  1.1  riastrad  * The above copyright notice and this permission notice shall be included in
     14  1.1  riastrad  * all copies or substantial portions of the Software.
     15  1.1  riastrad  *
     16  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  1.1  riastrad  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     20  1.1  riastrad  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     21  1.1  riastrad  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  1.1  riastrad  * SOFTWARE.
     23  1.1  riastrad  */
     24  1.1  riastrad 
     25  1.1  riastrad #ifndef __NOUVEAU_HW_H__
     26  1.1  riastrad #define __NOUVEAU_HW_H__
     27  1.1  riastrad 
     28  1.1  riastrad #include "disp.h"
     29  1.1  riastrad #include "nvreg.h"
     30  1.1  riastrad 
     31  1.1  riastrad #include <subdev/bios/pll.h>
     32  1.1  riastrad 
     33  1.1  riastrad #define MASK(field) ( \
     34  1.1  riastrad 	(0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field))
     35  1.1  riastrad 
     36  1.1  riastrad #define XLATE(src, srclowbit, outfield) ( \
     37  1.1  riastrad 	(((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield))
     38  1.1  riastrad 
     39  1.1  riastrad void NVWriteVgaSeq(struct drm_device *, int head, uint8_t index, uint8_t value);
     40  1.1  riastrad uint8_t NVReadVgaSeq(struct drm_device *, int head, uint8_t index);
     41  1.1  riastrad void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value);
     42  1.1  riastrad uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index);
     43  1.1  riastrad void NVSetOwner(struct drm_device *, int owner);
     44  1.1  riastrad void NVBlankScreen(struct drm_device *, int head, bool blank);
     45  1.1  riastrad int nouveau_hw_get_pllvals(struct drm_device *, enum nvbios_pll_type plltype,
     46  1.2  riastrad 			   struct nvkm_pll_vals *pllvals);
     47  1.2  riastrad int nouveau_hw_pllvals_to_clk(struct nvkm_pll_vals *pllvals);
     48  1.1  riastrad int nouveau_hw_get_clock(struct drm_device *, enum nvbios_pll_type plltype);
     49  1.1  riastrad void nouveau_hw_save_vga_fonts(struct drm_device *, bool save);
     50  1.1  riastrad void nouveau_hw_save_state(struct drm_device *, int head,
     51  1.1  riastrad 			   struct nv04_mode_state *state);
     52  1.1  riastrad void nouveau_hw_load_state(struct drm_device *, int head,
     53  1.1  riastrad 			   struct nv04_mode_state *state);
     54  1.1  riastrad void nouveau_hw_load_state_palette(struct drm_device *, int head,
     55  1.1  riastrad 				   struct nv04_mode_state *state);
     56  1.1  riastrad 
     57  1.1  riastrad /* nouveau_calc.c */
     58  1.1  riastrad extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp,
     59  1.1  riastrad 			     int *burst, int *lwm);
     60  1.1  riastrad 
     61  1.1  riastrad static inline uint32_t NVReadCRTC(struct drm_device *dev,
     62  1.1  riastrad 					int head, uint32_t reg)
     63  1.1  riastrad {
     64  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
     65  1.1  riastrad 	uint32_t val;
     66  1.1  riastrad 	if (head)
     67  1.1  riastrad 		reg += NV_PCRTC0_SIZE;
     68  1.2  riastrad 	val = nvif_rd32(device, reg);
     69  1.1  riastrad 	return val;
     70  1.1  riastrad }
     71  1.1  riastrad 
     72  1.1  riastrad static inline void NVWriteCRTC(struct drm_device *dev,
     73  1.1  riastrad 					int head, uint32_t reg, uint32_t val)
     74  1.1  riastrad {
     75  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
     76  1.1  riastrad 	if (head)
     77  1.1  riastrad 		reg += NV_PCRTC0_SIZE;
     78  1.2  riastrad 	nvif_wr32(device, reg, val);
     79  1.1  riastrad }
     80  1.1  riastrad 
     81  1.1  riastrad static inline uint32_t NVReadRAMDAC(struct drm_device *dev,
     82  1.1  riastrad 					int head, uint32_t reg)
     83  1.1  riastrad {
     84  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
     85  1.1  riastrad 	uint32_t val;
     86  1.1  riastrad 	if (head)
     87  1.1  riastrad 		reg += NV_PRAMDAC0_SIZE;
     88  1.2  riastrad 	val = nvif_rd32(device, reg);
     89  1.1  riastrad 	return val;
     90  1.1  riastrad }
     91  1.1  riastrad 
     92  1.1  riastrad static inline void NVWriteRAMDAC(struct drm_device *dev,
     93  1.1  riastrad 					int head, uint32_t reg, uint32_t val)
     94  1.1  riastrad {
     95  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
     96  1.1  riastrad 	if (head)
     97  1.1  riastrad 		reg += NV_PRAMDAC0_SIZE;
     98  1.2  riastrad 	nvif_wr32(device, reg, val);
     99  1.1  riastrad }
    100  1.1  riastrad 
    101  1.1  riastrad static inline uint8_t nv_read_tmds(struct drm_device *dev,
    102  1.1  riastrad 					int or, int dl, uint8_t address)
    103  1.1  riastrad {
    104  1.1  riastrad 	int ramdac = (or & DCB_OUTPUT_C) >> 2;
    105  1.1  riastrad 
    106  1.1  riastrad 	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8,
    107  1.1  riastrad 	NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address);
    108  1.1  riastrad 	return NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8);
    109  1.1  riastrad }
    110  1.1  riastrad 
    111  1.1  riastrad static inline void nv_write_tmds(struct drm_device *dev,
    112  1.1  riastrad 					int or, int dl, uint8_t address,
    113  1.1  riastrad 					uint8_t data)
    114  1.1  riastrad {
    115  1.1  riastrad 	int ramdac = (or & DCB_OUTPUT_C) >> 2;
    116  1.1  riastrad 
    117  1.1  riastrad 	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data);
    118  1.1  riastrad 	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address);
    119  1.1  riastrad }
    120  1.1  riastrad 
    121  1.1  riastrad static inline void NVWriteVgaCrtc(struct drm_device *dev,
    122  1.1  riastrad 					int head, uint8_t index, uint8_t value)
    123  1.1  riastrad {
    124  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    125  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
    126  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
    127  1.1  riastrad }
    128  1.1  riastrad 
    129  1.1  riastrad static inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
    130  1.1  riastrad 					int head, uint8_t index)
    131  1.1  riastrad {
    132  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    133  1.1  riastrad 	uint8_t val;
    134  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
    135  1.2  riastrad 	val = nvif_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
    136  1.1  riastrad 	return val;
    137  1.1  riastrad }
    138  1.1  riastrad 
    139  1.1  riastrad /* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
    140  1.1  riastrad  * I suspect they in fact do nothing, but are merely a way to carry useful
    141  1.1  riastrad  * per-head variables around
    142  1.1  riastrad  *
    143  1.1  riastrad  * Known uses:
    144  1.1  riastrad  * CR57		CR58
    145  1.1  riastrad  * 0x00		index to the appropriate dcb entry (or 7f for inactive)
    146  1.1  riastrad  * 0x02		dcb entry's "or" value (or 00 for inactive)
    147  1.1  riastrad  * 0x03		bit0 set for dual link (LVDS, possibly elsewhere too)
    148  1.1  riastrad  * 0x08 or 0x09	pxclk in MHz
    149  1.1  riastrad  * 0x0f		laptop panel info -	low nibble for PEXTDEV_BOOT_0 strap
    150  1.1  riastrad  * 					high nibble for xlat strap value
    151  1.1  riastrad  */
    152  1.1  riastrad 
    153  1.1  riastrad static inline void
    154  1.1  riastrad NVWriteVgaCrtc5758(struct drm_device *dev, int head, uint8_t index, uint8_t value)
    155  1.1  riastrad {
    156  1.1  riastrad 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
    157  1.1  riastrad 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_58, value);
    158  1.1  riastrad }
    159  1.1  riastrad 
    160  1.1  riastrad static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_t index)
    161  1.1  riastrad {
    162  1.1  riastrad 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
    163  1.1  riastrad 	return NVReadVgaCrtc(dev, head, NV_CIO_CRE_58);
    164  1.1  riastrad }
    165  1.1  riastrad 
    166  1.1  riastrad static inline uint8_t NVReadPRMVIO(struct drm_device *dev,
    167  1.1  riastrad 					int head, uint32_t reg)
    168  1.1  riastrad {
    169  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    170  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    171  1.1  riastrad 	uint8_t val;
    172  1.1  riastrad 
    173  1.1  riastrad 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
    174  1.1  riastrad 	 * NVSetOwner for the relevant head to be programmed */
    175  1.3  riastrad 	if (head && drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
    176  1.1  riastrad 		reg += NV_PRMVIO_SIZE;
    177  1.1  riastrad 
    178  1.2  riastrad 	val = nvif_rd08(device, reg);
    179  1.1  riastrad 	return val;
    180  1.1  riastrad }
    181  1.1  riastrad 
    182  1.1  riastrad static inline void NVWritePRMVIO(struct drm_device *dev,
    183  1.1  riastrad 					int head, uint32_t reg, uint8_t value)
    184  1.1  riastrad {
    185  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    186  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    187  1.1  riastrad 
    188  1.1  riastrad 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
    189  1.1  riastrad 	 * NVSetOwner for the relevant head to be programmed */
    190  1.3  riastrad 	if (head && drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
    191  1.1  riastrad 		reg += NV_PRMVIO_SIZE;
    192  1.1  riastrad 
    193  1.2  riastrad 	nvif_wr08(device, reg, value);
    194  1.1  riastrad }
    195  1.1  riastrad 
    196  1.1  riastrad static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
    197  1.1  riastrad {
    198  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    199  1.2  riastrad 	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
    200  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
    201  1.1  riastrad }
    202  1.1  riastrad 
    203  1.1  riastrad static inline bool NVGetEnablePalette(struct drm_device *dev, int head)
    204  1.1  riastrad {
    205  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    206  1.2  riastrad 	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
    207  1.2  riastrad 	return !(nvif_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
    208  1.1  riastrad }
    209  1.1  riastrad 
    210  1.1  riastrad static inline void NVWriteVgaAttr(struct drm_device *dev,
    211  1.1  riastrad 					int head, uint8_t index, uint8_t value)
    212  1.1  riastrad {
    213  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    214  1.1  riastrad 	if (NVGetEnablePalette(dev, head))
    215  1.1  riastrad 		index &= ~0x20;
    216  1.1  riastrad 	else
    217  1.1  riastrad 		index |= 0x20;
    218  1.1  riastrad 
    219  1.2  riastrad 	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
    220  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
    221  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
    222  1.1  riastrad }
    223  1.1  riastrad 
    224  1.1  riastrad static inline uint8_t NVReadVgaAttr(struct drm_device *dev,
    225  1.1  riastrad 					int head, uint8_t index)
    226  1.1  riastrad {
    227  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    228  1.1  riastrad 	uint8_t val;
    229  1.1  riastrad 	if (NVGetEnablePalette(dev, head))
    230  1.1  riastrad 		index &= ~0x20;
    231  1.1  riastrad 	else
    232  1.1  riastrad 		index |= 0x20;
    233  1.1  riastrad 
    234  1.2  riastrad 	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
    235  1.2  riastrad 	nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
    236  1.2  riastrad 	val = nvif_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
    237  1.1  riastrad 	return val;
    238  1.1  riastrad }
    239  1.1  riastrad 
    240  1.1  riastrad static inline void NVVgaSeqReset(struct drm_device *dev, int head, bool start)
    241  1.1  riastrad {
    242  1.1  riastrad 	NVWriteVgaSeq(dev, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3);
    243  1.1  riastrad }
    244  1.1  riastrad 
    245  1.1  riastrad static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect)
    246  1.1  riastrad {
    247  1.1  riastrad 	uint8_t seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX);
    248  1.1  riastrad 
    249  1.1  riastrad 	if (protect) {
    250  1.1  riastrad 		NVVgaSeqReset(dev, head, true);
    251  1.1  riastrad 		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
    252  1.1  riastrad 	} else {
    253  1.1  riastrad 		/* Reenable sequencer, then turn on screen */
    254  1.1  riastrad 		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20);   /* reenable display */
    255  1.1  riastrad 		NVVgaSeqReset(dev, head, false);
    256  1.1  riastrad 	}
    257  1.1  riastrad 	NVSetEnablePalette(dev, head, protect);
    258  1.1  riastrad }
    259  1.1  riastrad 
    260  1.1  riastrad static inline bool
    261  1.1  riastrad nv_heads_tied(struct drm_device *dev)
    262  1.1  riastrad {
    263  1.3  riastrad 	struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
    264  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    265  1.1  riastrad 
    266  1.3  riastrad 	if (drm->client.device.info.chipset == 0x11)
    267  1.2  riastrad 		return !!(nvif_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
    268  1.1  riastrad 
    269  1.1  riastrad 	return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
    270  1.1  riastrad }
    271  1.1  riastrad 
    272  1.1  riastrad /* makes cr0-7 on the specified head read-only */
    273  1.1  riastrad static inline bool
    274  1.1  riastrad nv_lock_vga_crtc_base(struct drm_device *dev, int head, bool lock)
    275  1.1  riastrad {
    276  1.1  riastrad 	uint8_t cr11 = NVReadVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX);
    277  1.1  riastrad 	bool waslocked = cr11 & 0x80;
    278  1.1  riastrad 
    279  1.1  riastrad 	if (lock)
    280  1.1  riastrad 		cr11 |= 0x80;
    281  1.1  riastrad 	else
    282  1.1  riastrad 		cr11 &= ~0x80;
    283  1.1  riastrad 	NVWriteVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX, cr11);
    284  1.1  riastrad 
    285  1.1  riastrad 	return waslocked;
    286  1.1  riastrad }
    287  1.1  riastrad 
    288  1.1  riastrad static inline void
    289  1.1  riastrad nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock)
    290  1.1  riastrad {
    291  1.1  riastrad 	/* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
    292  1.1  riastrad 	 * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
    293  1.1  riastrad 	 * bit6: seems to have some effect on CR09 (double scan, VBS_9)
    294  1.1  riastrad 	 * bit5: unlocks HDE
    295  1.1  riastrad 	 * bit4: unlocks VDE
    296  1.1  riastrad 	 * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
    297  1.1  riastrad 	 * bit2: same as bit 1 of 0x60?804
    298  1.1  riastrad 	 * bit0: same as bit 0 of 0x60?804
    299  1.1  riastrad 	 */
    300  1.1  riastrad 
    301  1.1  riastrad 	uint8_t cr21 = lock;
    302  1.1  riastrad 
    303  1.1  riastrad 	if (lock < 0)
    304  1.1  riastrad 		/* 0xfa is generic "unlock all" mask */
    305  1.1  riastrad 		cr21 = NVReadVgaCrtc(dev, head, NV_CIO_CRE_21) | 0xfa;
    306  1.1  riastrad 
    307  1.1  riastrad 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_21, cr21);
    308  1.1  riastrad }
    309  1.1  riastrad 
    310  1.1  riastrad /* renders the extended crtc regs (cr19+) on all crtcs impervious:
    311  1.1  riastrad  * immutable and unreadable
    312  1.1  riastrad  */
    313  1.1  riastrad static inline bool
    314  1.1  riastrad NVLockVgaCrtcs(struct drm_device *dev, bool lock)
    315  1.1  riastrad {
    316  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    317  1.1  riastrad 	bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX);
    318  1.1  riastrad 
    319  1.1  riastrad 	NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
    320  1.1  riastrad 		       lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
    321  1.1  riastrad 	/* NV11 has independently lockable extended crtcs, except when tied */
    322  1.3  riastrad 	if (drm->client.device.info.chipset == 0x11 && !nv_heads_tied(dev))
    323  1.1  riastrad 		NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
    324  1.1  riastrad 			       lock ? NV_CIO_SR_LOCK_VALUE :
    325  1.1  riastrad 				      NV_CIO_SR_UNLOCK_RW_VALUE);
    326  1.1  riastrad 
    327  1.1  riastrad 	return waslocked;
    328  1.1  riastrad }
    329  1.1  riastrad 
    330  1.1  riastrad /* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
    331  1.1  riastrad #define NV04_CURSOR_SIZE 32
    332  1.1  riastrad /* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
    333  1.1  riastrad #define NV10_CURSOR_SIZE 64
    334  1.1  riastrad 
    335  1.1  riastrad static inline int nv_cursor_width(struct drm_device *dev)
    336  1.1  riastrad {
    337  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    338  1.1  riastrad 
    339  1.3  riastrad 	return drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
    340  1.1  riastrad }
    341  1.1  riastrad 
    342  1.1  riastrad static inline void
    343  1.1  riastrad nv_fix_nv40_hw_cursor(struct drm_device *dev, int head)
    344  1.1  riastrad {
    345  1.1  riastrad 	/* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
    346  1.1  riastrad 	 * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
    347  1.1  riastrad 	 * for changes to the CRTC CURCTL regs to take effect, whether changing
    348  1.1  riastrad 	 * the pixmap location, or just showing/hiding the cursor
    349  1.1  riastrad 	 */
    350  1.1  riastrad 	uint32_t curpos = NVReadRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS);
    351  1.1  riastrad 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos);
    352  1.1  riastrad }
    353  1.1  riastrad 
    354  1.1  riastrad static inline void
    355  1.1  riastrad nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
    356  1.1  riastrad {
    357  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    358  1.1  riastrad 
    359  1.1  riastrad 	NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
    360  1.1  riastrad 
    361  1.3  riastrad 	if (drm->client.device.info.family == NV_DEVICE_INFO_V0_TNT) {
    362  1.1  riastrad 		/*
    363  1.1  riastrad 		 * Hilarious, the 24th bit doesn't want to stick to
    364  1.1  riastrad 		 * PCRTC_START...
    365  1.1  riastrad 		 */
    366  1.1  riastrad 		int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX);
    367  1.1  riastrad 
    368  1.1  riastrad 		NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX,
    369  1.1  riastrad 			       (cre_heb & ~0x40) | ((offset >> 18) & 0x40));
    370  1.1  riastrad 	}
    371  1.1  riastrad }
    372  1.1  riastrad 
    373  1.1  riastrad static inline void
    374  1.1  riastrad nv_show_cursor(struct drm_device *dev, int head, bool show)
    375  1.1  riastrad {
    376  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    377  1.1  riastrad 	uint8_t *curctl1 =
    378  1.1  riastrad 		&nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX];
    379  1.1  riastrad 
    380  1.1  riastrad 	if (show)
    381  1.1  riastrad 		*curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
    382  1.1  riastrad 	else
    383  1.1  riastrad 		*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
    384  1.1  riastrad 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
    385  1.1  riastrad 
    386  1.3  riastrad 	if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
    387  1.1  riastrad 		nv_fix_nv40_hw_cursor(dev, head);
    388  1.1  riastrad }
    389  1.1  riastrad 
    390  1.1  riastrad static inline uint32_t
    391  1.1  riastrad nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
    392  1.1  riastrad {
    393  1.1  riastrad 	struct nouveau_drm *drm = nouveau_drm(dev);
    394  1.1  riastrad 	int mask;
    395  1.1  riastrad 
    396  1.1  riastrad 	if (bpp == 15)
    397  1.1  riastrad 		bpp = 16;
    398  1.1  riastrad 	if (bpp == 24)
    399  1.1  riastrad 		bpp = 8;
    400  1.1  riastrad 
    401  1.1  riastrad 	/* Alignment requirements taken from the Haiku driver */
    402  1.3  riastrad 	if (drm->client.device.info.family == NV_DEVICE_INFO_V0_TNT)
    403  1.1  riastrad 		mask = 128 / bpp - 1;
    404  1.1  riastrad 	else
    405  1.1  riastrad 		mask = 512 / bpp - 1;
    406  1.1  riastrad 
    407  1.1  riastrad 	return (width + mask) & ~mask;
    408  1.1  riastrad }
    409  1.1  riastrad 
    410  1.1  riastrad #endif	/* __NOUVEAU_HW_H__ */
    411