#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[] = {
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;
}
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;
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;