diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dp.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.c | 230 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.h | 6 |
3 files changed, 94 insertions, 148 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 5722fd55764..07bac360245 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -578,7 +578,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) dp.dcb = nv_encoder->dcb; dp.crtc = nv_crtc->index; - dp.auxch = auxch->rd; + dp.auxch = auxch->drive; dp.or = nv_encoder->or; dp.link = !(nv_encoder->dcb->sorconf.link & 1); dp.dpcd = nv_encoder->dp.dpcd; @@ -653,7 +653,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) if (!auxch) return false; - ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); + ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8); if (ret) return false; @@ -681,7 +681,7 @@ int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, uint8_t *data, int data_nr) { - return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); + return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr); } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 36ffcb84f55..d0d581440d5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -30,132 +30,83 @@ #include "nouveau_hw.h" static void -nv04_i2c_setscl(void *data, int state) +i2c_drive_scl(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) & 0xd0) | (state ? 0x20 : 0); - NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); -} - -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); -} - -static int -nv04_i2c_getscl(void *data) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - - return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4); -} - -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 -nv4e_i2c_setscl(void *data, int state) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - uint8_t val; - - val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0); - nv_wr32(dev, i2c->wr, val | 0x01); -} - -static void -nv4e_i2c_setsda(void *data, int state) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - uint8_t val; - - val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0); - nv_wr32(dev, i2c->wr, val | 0x01); -} - -static int -nv4e_i2c_getscl(void *data) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - - return !!((nv_rd32(dev, i2c->rd) >> 16) & 4); -} - -static int -nv4e_i2c_getsda(void *data) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - - return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); -} - -static int -nv50_i2c_getscl(void *data) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - - return !!(nv_rd32(dev, i2c->rd) & 1); -} - -static int -nv50_i2c_getsda(void *data) -{ - struct nouveau_i2c_chan *i2c = data; - struct drm_device *dev = i2c->dev; - - return !!(nv_rd32(dev, i2c->rd) & 2); -} - -static void -nv50_i2c_setscl(void *data, int state) -{ - struct nouveau_i2c_chan *i2c = data; - - nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); + struct nouveau_i2c_chan *port = data; + if (port->type == 0) { + u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + if (state) val |= 0x20; + else val &= 0xdf; + NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + } else + if (port->type == 4) { + nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01); + } else + if (port->type == 5) { + if (state) port->state |= 0x01; + else port->state &= 0xfe; + nv_wr32(port->dev, port->drive, 4 | port->state); + } } static void -nv50_i2c_setsda(void *data, int state) +i2c_drive_sda(void *data, int state) { - struct nouveau_i2c_chan *i2c = data; - - nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); - i2c->data = state; + struct nouveau_i2c_chan *port = data; + if (port->type == 0) { + u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + if (state) val |= 0x10; + else val &= 0xef; + NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + } else + if (port->type == 4) { + nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01); + } else + if (port->type == 5) { + if (state) port->state |= 0x02; + else port->state &= 0xfd; + nv_wr32(port->dev, port->drive, 4 | port->state); + } } static int -nvd0_i2c_getscl(void *data) +i2c_sense_scl(void *data) { - struct nouveau_i2c_chan *i2c = data; - return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); + struct nouveau_i2c_chan *port = data; + struct drm_nouveau_private *dev_priv = port->dev->dev_private; + if (port->type == 0) { + return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04); + } else + if (port->type == 4) { + return !!(nv_rd32(port->dev, port->sense) & 0x00040000); + } else + if (port->type == 5) { + if (dev_priv->card_type < NV_D0) + return !!(nv_rd32(port->dev, port->sense) & 0x01); + else + return !!(nv_rd32(port->dev, port->sense) & 0x10); + } + return 0; } static int -nvd0_i2c_getsda(void *data) +i2c_sense_sda(void *data) { - struct nouveau_i2c_chan *i2c = data; - return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); + struct nouveau_i2c_chan *port = data; + struct drm_nouveau_private *dev_priv = port->dev->dev_private; + if (port->type == 0) { + return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08); + } else + if (port->type == 4) { + return !!(nv_rd32(port->dev, port->sense) & 0x00080000); + } else + if (port->type == 5) { + if (dev_priv->card_type < NV_D0) + return !!(nv_rd32(port->dev, port->sense) & 0x02); + else + return !!(nv_rd32(port->dev, port->sense) & 0x20); + } + return 0; } static const uint32_t nv50_i2c_port[] = { @@ -258,51 +209,37 @@ nouveau_i2c_init(struct drm_device *dev) switch (port->type) { case 0: /* NV04:NV50 */ - port->wr = entry[0]; - port->rd = entry[1]; - port->bit.setsda = nv04_i2c_setsda; - port->bit.setscl = nv04_i2c_setscl; - port->bit.getsda = nv04_i2c_getsda; - port->bit.getscl = nv04_i2c_getscl; + port->drive = entry[0]; + port->sense = entry[1]; break; case 4: /* NV4E */ - port->wr = 0x600800 + entry[1]; - port->rd = port->wr; - port->bit.setsda = nv4e_i2c_setsda; - port->bit.setscl = nv4e_i2c_setscl; - port->bit.getsda = nv4e_i2c_getsda; - port->bit.getscl = nv4e_i2c_getscl; + port->drive = 0x600800 + entry[1]; + port->sense = port->drive; break; case 5: /* NV50- */ - port->wr = entry[0] & 0x0f; + port->drive = entry[0] & 0x0f; if (dev_priv->card_type < NV_D0) { - if (port->wr >= ARRAY_SIZE(nv50_i2c_port)) + if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) break; - port->wr = nv50_i2c_port[port->wr]; - port->rd = port->wr; - port->bit.getsda = nv50_i2c_getsda; - port->bit.getscl = nv50_i2c_getscl; + port->drive = nv50_i2c_port[port->drive]; + port->sense = port->drive; } else { - port->wr = 0x00d014 + (port->wr * 0x20); - port->rd = port->wr; - port->bit.getsda = nvd0_i2c_getsda; - port->bit.getscl = nvd0_i2c_getscl; + port->drive = 0x00d014 + (port->drive * 0x20); + port->sense = port->drive; } - port->bit.setsda = nv50_i2c_setsda; - port->bit.setscl = nv50_i2c_setscl; break; case 6: /* NV50- DP AUX */ - port->wr = entry[0]; - port->rd = port->wr; + port->drive = entry[0]; + port->sense = port->drive; port->adapter.algo = &nouveau_dp_i2c_algo; break; default: break; } - if (!port->adapter.algo && !port->wr) { + if (!port->adapter.algo && !port->drive) { NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", - i, port->type, port->wr, port->rd); + i, port->type, port->drive, port->sense); kfree(port); continue; } @@ -321,6 +258,15 @@ nouveau_i2c_init(struct drm_device *dev) port->bit.udelay = 40; port->bit.timeout = usecs_to_jiffies(5000); port->bit.data = port; + port->bit.setsda = i2c_drive_sda; + port->bit.setscl = i2c_drive_scl; + port->bit.getsda = i2c_sense_sda; + port->bit.getscl = i2c_sense_scl; + + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 1); + i2c_drive_scl(port, 1); + ret = i2c_bit_add_bus(&port->adapter); } else { port->adapter.algo = &nouveau_dp_i2c_algo; @@ -381,7 +327,7 @@ nouveau_i2c_find(struct drm_device *dev, u8 index) if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { u32 reg = 0x00e500, val; if (port->type == 6) { - reg += port->rd * 0x50; + reg += port->drive * 0x50; val = 0x2002; } else { reg += ((port->dcb & 0x1e00) >> 9) * 0x50; diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index cf5f67d51fb..1d083893a4d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h @@ -39,9 +39,9 @@ struct nouveau_i2c_chan { u8 index; u8 type; u32 dcb; - unsigned rd; - unsigned wr; - unsigned data; + u32 drive; + u32 sense; + u32 state; }; int nouveau_i2c_init(struct drm_device *); |