Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2008 Stuart Bennett
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
0018  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
0019  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0020  * SOFTWARE.
0021  */
0022 
0023 #ifndef __NOUVEAU_HW_H__
0024 #define __NOUVEAU_HW_H__
0025 
0026 #include "disp.h"
0027 #include "nvreg.h"
0028 
0029 #include <subdev/bios/pll.h>
0030 
0031 #define MASK(field) ( \
0032     (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field))
0033 
0034 #define XLATE(src, srclowbit, outfield) ( \
0035     (((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield))
0036 
0037 void NVWriteVgaSeq(struct drm_device *, int head, uint8_t index, uint8_t value);
0038 uint8_t NVReadVgaSeq(struct drm_device *, int head, uint8_t index);
0039 void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value);
0040 uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index);
0041 void NVSetOwner(struct drm_device *, int owner);
0042 void NVBlankScreen(struct drm_device *, int head, bool blank);
0043 int nouveau_hw_get_pllvals(struct drm_device *, enum nvbios_pll_type plltype,
0044                struct nvkm_pll_vals *pllvals);
0045 int nouveau_hw_pllvals_to_clk(struct nvkm_pll_vals *pllvals);
0046 int nouveau_hw_get_clock(struct drm_device *, enum nvbios_pll_type plltype);
0047 void nouveau_hw_save_vga_fonts(struct drm_device *, bool save);
0048 void nouveau_hw_save_state(struct drm_device *, int head,
0049                struct nv04_mode_state *state);
0050 void nouveau_hw_load_state(struct drm_device *, int head,
0051                struct nv04_mode_state *state);
0052 void nouveau_hw_load_state_palette(struct drm_device *, int head,
0053                    struct nv04_mode_state *state);
0054 
0055 /* nouveau_calc.c */
0056 extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp,
0057                  int *burst, int *lwm);
0058 
0059 static inline uint32_t NVReadCRTC(struct drm_device *dev,
0060                     int head, uint32_t reg)
0061 {
0062     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0063     uint32_t val;
0064     if (head)
0065         reg += NV_PCRTC0_SIZE;
0066     val = nvif_rd32(device, reg);
0067     return val;
0068 }
0069 
0070 static inline void NVWriteCRTC(struct drm_device *dev,
0071                     int head, uint32_t reg, uint32_t val)
0072 {
0073     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0074     if (head)
0075         reg += NV_PCRTC0_SIZE;
0076     nvif_wr32(device, reg, val);
0077 }
0078 
0079 static inline uint32_t NVReadRAMDAC(struct drm_device *dev,
0080                     int head, uint32_t reg)
0081 {
0082     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0083     uint32_t val;
0084     if (head)
0085         reg += NV_PRAMDAC0_SIZE;
0086     val = nvif_rd32(device, reg);
0087     return val;
0088 }
0089 
0090 static inline void NVWriteRAMDAC(struct drm_device *dev,
0091                     int head, uint32_t reg, uint32_t val)
0092 {
0093     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0094     if (head)
0095         reg += NV_PRAMDAC0_SIZE;
0096     nvif_wr32(device, reg, val);
0097 }
0098 
0099 static inline uint8_t nv_read_tmds(struct drm_device *dev,
0100                     int or, int dl, uint8_t address)
0101 {
0102     int ramdac = (or & DCB_OUTPUT_C) >> 2;
0103 
0104     NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8,
0105     NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address);
0106     return NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8);
0107 }
0108 
0109 static inline void nv_write_tmds(struct drm_device *dev,
0110                     int or, int dl, uint8_t address,
0111                     uint8_t data)
0112 {
0113     int ramdac = (or & DCB_OUTPUT_C) >> 2;
0114 
0115     NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data);
0116     NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address);
0117 }
0118 
0119 static inline void NVWriteVgaCrtc(struct drm_device *dev,
0120                     int head, uint8_t index, uint8_t value)
0121 {
0122     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0123     nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
0124     nvif_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
0125 }
0126 
0127 static inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
0128                     int head, uint8_t index)
0129 {
0130     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0131     uint8_t val;
0132     nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
0133     val = nvif_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
0134     return val;
0135 }
0136 
0137 /* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
0138  * I suspect they in fact do nothing, but are merely a way to carry useful
0139  * per-head variables around
0140  *
0141  * Known uses:
0142  * CR57     CR58
0143  * 0x00     index to the appropriate dcb entry (or 7f for inactive)
0144  * 0x02     dcb entry's "or" value (or 00 for inactive)
0145  * 0x03     bit0 set for dual link (LVDS, possibly elsewhere too)
0146  * 0x08 or 0x09 pxclk in MHz
0147  * 0x0f     laptop panel info - low nibble for PEXTDEV_BOOT_0 strap
0148  *                  high nibble for xlat strap value
0149  */
0150 
0151 static inline void
0152 NVWriteVgaCrtc5758(struct drm_device *dev, int head, uint8_t index, uint8_t value)
0153 {
0154     NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
0155     NVWriteVgaCrtc(dev, head, NV_CIO_CRE_58, value);
0156 }
0157 
0158 static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_t index)
0159 {
0160     NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
0161     return NVReadVgaCrtc(dev, head, NV_CIO_CRE_58);
0162 }
0163 
0164 static inline uint8_t NVReadPRMVIO(struct drm_device *dev,
0165                     int head, uint32_t reg)
0166 {
0167     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0168     struct nouveau_drm *drm = nouveau_drm(dev);
0169     uint8_t val;
0170 
0171     /* Only NV4x have two pvio ranges; other twoHeads cards MUST call
0172      * NVSetOwner for the relevant head to be programmed */
0173     if (head && drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
0174         reg += NV_PRMVIO_SIZE;
0175 
0176     val = nvif_rd08(device, reg);
0177     return val;
0178 }
0179 
0180 static inline void NVWritePRMVIO(struct drm_device *dev,
0181                     int head, uint32_t reg, uint8_t value)
0182 {
0183     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0184     struct nouveau_drm *drm = nouveau_drm(dev);
0185 
0186     /* Only NV4x have two pvio ranges; other twoHeads cards MUST call
0187      * NVSetOwner for the relevant head to be programmed */
0188     if (head && drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
0189         reg += NV_PRMVIO_SIZE;
0190 
0191     nvif_wr08(device, reg, value);
0192 }
0193 
0194 static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
0195 {
0196     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0197     nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
0198     nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
0199 }
0200 
0201 static inline bool NVGetEnablePalette(struct drm_device *dev, int head)
0202 {
0203     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0204     nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
0205     return !(nvif_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
0206 }
0207 
0208 static inline void NVWriteVgaAttr(struct drm_device *dev,
0209                     int head, uint8_t index, uint8_t value)
0210 {
0211     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0212     if (NVGetEnablePalette(dev, head))
0213         index &= ~0x20;
0214     else
0215         index |= 0x20;
0216 
0217     nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
0218     nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
0219     nvif_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
0220 }
0221 
0222 static inline uint8_t NVReadVgaAttr(struct drm_device *dev,
0223                     int head, uint8_t index)
0224 {
0225     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0226     uint8_t val;
0227     if (NVGetEnablePalette(dev, head))
0228         index &= ~0x20;
0229     else
0230         index |= 0x20;
0231 
0232     nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
0233     nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
0234     val = nvif_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
0235     return val;
0236 }
0237 
0238 static inline void NVVgaSeqReset(struct drm_device *dev, int head, bool start)
0239 {
0240     NVWriteVgaSeq(dev, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3);
0241 }
0242 
0243 static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect)
0244 {
0245     uint8_t seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX);
0246 
0247     if (protect) {
0248         NVVgaSeqReset(dev, head, true);
0249         NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
0250     } else {
0251         /* Reenable sequencer, then turn on screen */
0252         NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20);   /* reenable display */
0253         NVVgaSeqReset(dev, head, false);
0254     }
0255     NVSetEnablePalette(dev, head, protect);
0256 }
0257 
0258 static inline bool
0259 nv_heads_tied(struct drm_device *dev)
0260 {
0261     struct nvif_object *device = &nouveau_drm(dev)->client.device.object;
0262     struct nouveau_drm *drm = nouveau_drm(dev);
0263 
0264     if (drm->client.device.info.chipset == 0x11)
0265         return !!(nvif_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
0266 
0267     return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
0268 }
0269 
0270 /* makes cr0-7 on the specified head read-only */
0271 static inline bool
0272 nv_lock_vga_crtc_base(struct drm_device *dev, int head, bool lock)
0273 {
0274     uint8_t cr11 = NVReadVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX);
0275     bool waslocked = cr11 & 0x80;
0276 
0277     if (lock)
0278         cr11 |= 0x80;
0279     else
0280         cr11 &= ~0x80;
0281     NVWriteVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX, cr11);
0282 
0283     return waslocked;
0284 }
0285 
0286 static inline void
0287 nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock)
0288 {
0289     /* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
0290      * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
0291      * bit6: seems to have some effect on CR09 (double scan, VBS_9)
0292      * bit5: unlocks HDE
0293      * bit4: unlocks VDE
0294      * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
0295      * bit2: same as bit 1 of 0x60?804
0296      * bit0: same as bit 0 of 0x60?804
0297      */
0298 
0299     uint8_t cr21 = lock;
0300 
0301     if (lock < 0)
0302         /* 0xfa is generic "unlock all" mask */
0303         cr21 = NVReadVgaCrtc(dev, head, NV_CIO_CRE_21) | 0xfa;
0304 
0305     NVWriteVgaCrtc(dev, head, NV_CIO_CRE_21, cr21);
0306 }
0307 
0308 /* renders the extended crtc regs (cr19+) on all crtcs impervious:
0309  * immutable and unreadable
0310  */
0311 static inline bool
0312 NVLockVgaCrtcs(struct drm_device *dev, bool lock)
0313 {
0314     struct nouveau_drm *drm = nouveau_drm(dev);
0315     bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX);
0316 
0317     NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
0318                lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
0319     /* NV11 has independently lockable extended crtcs, except when tied */
0320     if (drm->client.device.info.chipset == 0x11 && !nv_heads_tied(dev))
0321         NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
0322                    lock ? NV_CIO_SR_LOCK_VALUE :
0323                       NV_CIO_SR_UNLOCK_RW_VALUE);
0324 
0325     return waslocked;
0326 }
0327 
0328 /* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
0329 #define NV04_CURSOR_SIZE 32
0330 /* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
0331 #define NV10_CURSOR_SIZE 64
0332 
0333 static inline int nv_cursor_width(struct drm_device *dev)
0334 {
0335     struct nouveau_drm *drm = nouveau_drm(dev);
0336 
0337     return drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
0338 }
0339 
0340 static inline void
0341 nv_fix_nv40_hw_cursor(struct drm_device *dev, int head)
0342 {
0343     /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
0344      * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
0345      * for changes to the CRTC CURCTL regs to take effect, whether changing
0346      * the pixmap location, or just showing/hiding the cursor
0347      */
0348     uint32_t curpos = NVReadRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS);
0349     NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos);
0350 }
0351 
0352 static inline void
0353 nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
0354 {
0355     struct nouveau_drm *drm = nouveau_drm(dev);
0356 
0357     NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
0358 
0359     if (drm->client.device.info.family == NV_DEVICE_INFO_V0_TNT) {
0360         /*
0361          * Hilarious, the 24th bit doesn't want to stick to
0362          * PCRTC_START...
0363          */
0364         int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX);
0365 
0366         NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX,
0367                    (cre_heb & ~0x40) | ((offset >> 18) & 0x40));
0368     }
0369 }
0370 
0371 static inline void
0372 nv_show_cursor(struct drm_device *dev, int head, bool show)
0373 {
0374     struct nouveau_drm *drm = nouveau_drm(dev);
0375     uint8_t *curctl1 =
0376         &nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX];
0377 
0378     if (show)
0379         *curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
0380     else
0381         *curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
0382     NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
0383 
0384     if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE)
0385         nv_fix_nv40_hw_cursor(dev, head);
0386 }
0387 
0388 static inline uint32_t
0389 nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
0390 {
0391     struct nouveau_drm *drm = nouveau_drm(dev);
0392     int mask;
0393 
0394     if (bpp == 15)
0395         bpp = 16;
0396     if (bpp == 24)
0397         bpp = 8;
0398 
0399     /* Alignment requirements taken from the Haiku driver */
0400     if (drm->client.device.info.family == NV_DEVICE_INFO_V0_TNT)
0401         mask = 128 / bpp - 1;
0402     else
0403         mask = 512 / bpp - 1;
0404 
0405     return (width + mask) & ~mask;
0406 }
0407 
0408 #endif  /* __NOUVEAU_HW_H__ */