static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; uint8_t crtc1A; NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); if (mode == DRM_MODE_DPMS_ON) { int head = nouveau_crtc(encoder->crtc)->index; crtc1A = NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX); state->pllsel |= head ? PLLSEL_TV_CRTC2_MASK : PLLSEL_TV_CRTC1_MASK; /* Inhibit hsync */ crtc1A |= 0x80; NVWriteVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX, crtc1A); } NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); get_slave_funcs(encoder)->dpms(encoder, mode); }
static int nv04_i2c_getsda(void *data) { struct nouveau_i2c_chan *i2c = data; struct drm_device *dev = i2c->dev; return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8); }
static void nv04_i2c_setsda(void *data, int state) { struct nouveau_i2c_chan *i2c = data; struct drm_device *dev = i2c->dev; uint8_t val; val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0); NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); }
/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied) * it affects only the 8 bit vga io regs, which we access using mmio at * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d* * in general, the set value of cr44 does not matter: reg access works as * expected and values can be set for the appropriate head by using a 0x2000 * offset as required * however: * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and * cr44 must be set to 0 or 3 for accessing values on the correct head * through the common 0xc03c* addresses * b) in tied mode (4) head B is programmed to the values set on head A, and * access using the head B addresses can have strange results, ergo we leave * tied mode in init once we know to what cr44 should be restored on exit * * the owner parameter is slightly abused: * 0 and 1 are treated as head values and so the set value is (owner * 3) * other values are treated as literal values to set */ void NVSetOwner(struct drm_device *dev, int owner) { struct nouveau_drm *drm = nouveau_drm(dev); if (owner == 1) owner *= 3; if (nv_device(drm->device)->chipset == 0x11) { /* This might seem stupid, but the blob does it and * omitting it often locks the system up. */ NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); NVReadVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX); } /* CR44 is always changed on CRTC0 */ NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner); if (nv_device(drm->device)->chipset == 0x11) { /* set me harder */ NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); } }