drm/nouveau/i2c: create proper chipset-specific class implementations
authorBen Skeggs <bskeggs@redhat.com>
Sat, 16 Feb 2013 05:21:58 +0000 (15:21 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 20 Feb 2013 06:01:01 +0000 (16:01 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
22 files changed:
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h
drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c
drivers/gpu/drm/nouveau/core/subdev/device/nv04.c
drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
drivers/gpu/drm/nouveau/core/subdev/device/nv20.c
drivers/gpu/drm/nouveau/core/subdev/device/nv30.c
drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c
drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c

index 29f8cc5..d8374ec 100644 (file)
@@ -95,7 +95,11 @@ nouveau-y += core/subdev/gpio/nve0.o
 nouveau-y += core/subdev/i2c/base.o
 nouveau-y += core/subdev/i2c/aux.o
 nouveau-y += core/subdev/i2c/bit.o
+nouveau-y += core/subdev/i2c/nv04.o
+nouveau-y += core/subdev/i2c/nv4e.o
+nouveau-y += core/subdev/i2c/nv50.o
 nouveau-y += core/subdev/i2c/nv94.o
+nouveau-y += core/subdev/i2c/nvd0.o
 nouveau-y += core/subdev/ibus/nvc0.o
 nouveau-y += core/subdev/ibus/nve0.o
 nouveau-y += core/subdev/instmem/base.o
index 5079bed..10b57a1 100644 (file)
@@ -15,7 +15,7 @@ struct dcb_i2c_entry {
        enum dcb_i2c_type type;
        u8 drive;
        u8 sense;
-       u32 data;
+       u8 share;
 };
 
 u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
index a804317..c5868cd 100644 (file)
 #define NV_I2C_PORT(n)    (0x00 + (n))
 #define NV_I2C_DEFAULT(n) (0x80 + (n))
 
+#define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n))
+#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8)
+#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8)
+
 struct nouveau_i2c_port {
+       struct nouveau_object base;
        struct i2c_adapter adapter;
-       struct nouveau_i2c *i2c;
-       struct i2c_algo_bit_data bit;
+
        struct list_head head;
        u8  index;
-       u16 type;
-       u32 dcb;
-       u32 drive;
-       u32 sense;
-       u32 state;
-       void (*aux_mux)(struct nouveau_i2c_port *);
+
+       const struct nouveau_i2c_func *func;
+};
+
+struct nouveau_i2c_func {
+       void (*acquire)(struct nouveau_i2c_port *);
+       void (*release)(struct nouveau_i2c_port *);
+
+       void (*drive_scl)(struct nouveau_i2c_port *, int);
+       void (*drive_sda)(struct nouveau_i2c_port *, int);
+       int  (*sense_scl)(struct nouveau_i2c_port *);
+       int  (*sense_sda)(struct nouveau_i2c_port *);
+
        int  (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8);
+       int  (*pattern)(struct nouveau_i2c_port *, int pattern);
+       int  (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh);
+       int  (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe);
 };
 
+#define nouveau_i2c_port_create(p,e,o,i,a,d)                                   \
+       nouveau_i2c_port_create_((p), (e), (o), (i), (a),                      \
+                                sizeof(**d), (void **)d)
+#define nouveau_i2c_port_destroy(p) ({                                         \
+       struct nouveau_i2c_port *port = (p);                                   \
+       _nouveau_i2c_port_dtor(nv_object(i2c));                                \
+})
+#define nouveau_i2c_port_init(p)                                               \
+       nouveau_object_init(&(p)->base)
+#define nouveau_i2c_port_fini(p,s)                                             \
+       nouveau_object_fini(&(p)->base, (s))
+
+int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *,
+                            struct nouveau_oclass *, u8,
+                            const struct i2c_algorithm *, int, void **);
+void _nouveau_i2c_port_dtor(struct nouveau_object *);
+#define _nouveau_i2c_port_init nouveau_object_init
+#define _nouveau_i2c_port_fini nouveau_object_fini
+
 struct nouveau_i2c {
        struct nouveau_subdev base;
 
@@ -43,24 +76,75 @@ nouveau_i2c(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C];
 }
 
-extern struct nouveau_oclass nouveau_i2c_oclass;
+#define nouveau_i2c_create(p,e,o,s,d)                                          \
+       nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d)
+#define nouveau_i2c_destroy(p) ({                                              \
+       struct nouveau_i2c *i2c = (p);                                         \
+       _nouveau_i2c_dtor(nv_object(i2c));                                     \
+})
+#define nouveau_i2c_init(p) ({                                                 \
+       struct nouveau_i2c *i2c = (p);                                         \
+       _nouveau_i2c_init(nv_object(i2c));                                     \
+})
+#define nouveau_i2c_fini(p,s) ({                                               \
+       struct nouveau_i2c *i2c = (p);                                         \
+       _nouveau_i2c_fini(nv_object(i2c), (s));                                \
+})
 
-void nouveau_i2c_drive_scl(void *, int);
-void nouveau_i2c_drive_sda(void *, int);
-int  nouveau_i2c_sense_scl(void *);
-int  nouveau_i2c_sense_sda(void *);
+int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *,
+                       struct nouveau_oclass *, struct nouveau_oclass *,
+                       int, void **);
+void _nouveau_i2c_dtor(struct nouveau_object *);
+int  _nouveau_i2c_init(struct nouveau_object *);
+int  _nouveau_i2c_fini(struct nouveau_object *, bool);
 
-int  nv_rdi2cr(struct nouveau_i2c_port *, u8 addr, u8 reg);
-int  nv_wri2cr(struct nouveau_i2c_port *, u8 addr, u8 reg, u8 val);
-bool nv_probe_i2c(struct nouveau_i2c_port *, u8 addr);
-
-int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size);
-int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size);
+extern struct nouveau_oclass nv04_i2c_oclass;
+extern struct nouveau_oclass nv4e_i2c_oclass;
+extern struct nouveau_oclass nv50_i2c_oclass;
+extern struct nouveau_oclass nv94_i2c_oclass;
+extern struct nouveau_oclass nvd0_i2c_oclass;
 
 extern const struct i2c_algorithm nouveau_i2c_bit_algo;
 extern const struct i2c_algorithm nouveau_i2c_aux_algo;
 
-void nv94_aux_mux(struct nouveau_i2c_port *);
-int  nv94_aux(struct nouveau_i2c_port *, u8, u32, u8 *, u8);
+static inline int
+nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg)
+{
+       u8 val;
+       struct i2c_msg msgs[] = {
+               { .addr = addr, .flags = 0, .len = 1, .buf = &reg },
+               { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val },
+       };
+
+       int ret = i2c_transfer(&port->adapter, msgs, 2);
+       if (ret != 2)
+               return -EIO;
+
+       return val;
+}
+
+static inline int
+nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val)
+{
+       u8 buf[2] = { reg, val };
+       struct i2c_msg msgs[] = {
+               { .addr = addr, .flags = 0, .len = 2, .buf = buf },
+       };
+
+       int ret = i2c_transfer(&port->adapter, msgs, 1);
+       if (ret != 1)
+               return -EIO;
+
+       return 0;
+}
+
+static inline bool
+nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr)
+{
+       return nv_rdi2cr(port, addr, 0) >= 0;
+}
+
+int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size);
+int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size);
 
 #endif
index ad577db..cfb9288 100644 (file)
@@ -70,12 +70,12 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
        u8  ver, len;
        u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
        if (ent) {
-               info->data = nv_ro32(bios, ent + 0);
-               info->type = nv_ro08(bios, ent + 3);
+               info->type  = nv_ro08(bios, ent + 3);
+               info->share = DCB_I2C_UNUSED;
                if (ver < 0x30) {
                        info->type &= 0x07;
                        if (info->type == 0x07)
-                               info->type = 0xff;
+                               info->type = DCB_I2C_UNUSED;
                }
 
                switch (info->type) {
@@ -88,7 +88,11 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
                        return 0;
                case DCB_I2C_NVIO_BIT:
                case DCB_I2C_NVIO_AUX:
-                       info->drive = nv_ro08(bios, ent + 0);
+                       info->drive = nv_ro08(bios, ent + 0) & 0x0f;
+                       if (nv_ro08(bios, ent + 1) & 0x01) {
+                               info->share  = nv_ro08(bios, ent + 1) >> 1;
+                               info->share &= 0x0f;
+                       }
                        return 0;
                case DCB_I2C_UNUSED:
                        return 0;
@@ -121,7 +125,8 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
                        if (!info->sense) info->sense = 0x36;
                }
 
-               info->type = DCB_I2C_NV04_BIT;
+               info->type  = DCB_I2C_NV04_BIT;
+               info->share = DCB_I2C_UNUSED;
                return 0;
        }
 
index f76bd4e..473c5c0 100644 (file)
@@ -47,7 +47,7 @@ nv04_identify(struct nouveau_device *device)
        case 0x04:
                device->cname = "NV04";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -65,7 +65,7 @@ nv04_identify(struct nouveau_device *device)
        case 0x05:
                device->cname = "NV05";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
index 46d55ea..d0774f5 100644 (file)
@@ -49,7 +49,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "NV10";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -66,7 +66,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "NV15";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -85,7 +85,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "NV16";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -104,7 +104,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "nForce";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -123,7 +123,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "NV11";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -142,7 +142,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "NV17";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -161,7 +161,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "nForce2";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -180,7 +180,7 @@ nv10_identify(struct nouveau_device *device)
                device->cname = "NV18";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
index ad09854..ab920e0 100644 (file)
@@ -50,7 +50,7 @@ nv20_identify(struct nouveau_device *device)
                device->cname = "NV20";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -69,7 +69,7 @@ nv20_identify(struct nouveau_device *device)
                device->cname = "NV25";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -88,7 +88,7 @@ nv20_identify(struct nouveau_device *device)
                device->cname = "NV28";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -107,7 +107,7 @@ nv20_identify(struct nouveau_device *device)
                device->cname = "NV2A";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
index 2a98223..5f21102 100644 (file)
@@ -50,7 +50,7 @@ nv30_identify(struct nouveau_device *device)
                device->cname = "NV30";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -69,7 +69,7 @@ nv30_identify(struct nouveau_device *device)
                device->cname = "NV35";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -88,7 +88,7 @@ nv30_identify(struct nouveau_device *device)
                device->cname = "NV31";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -108,7 +108,7 @@ nv30_identify(struct nouveau_device *device)
                device->cname = "NV36";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
@@ -128,7 +128,7 @@ nv30_identify(struct nouveau_device *device)
                device->cname = "NV34";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
index 3e43460..f3d55ef 100644 (file)
@@ -52,7 +52,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV40";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -73,7 +73,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV41";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -94,7 +94,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV42";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -115,7 +115,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV43";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -136,7 +136,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV45";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -157,7 +157,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "G70";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -178,7 +178,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "G71";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -199,7 +199,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "G73";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -220,7 +220,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV44";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -241,7 +241,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "G72";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -262,7 +262,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "NV44A";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -283,7 +283,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "C61";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -304,7 +304,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "C51";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv4e_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -325,7 +325,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "C73";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -346,7 +346,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "C67";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
@@ -367,7 +367,7 @@ nv40_identify(struct nouveau_device *device)
                device->cname = "C68";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
index 0444f46..5ed2fa5 100644 (file)
@@ -58,7 +58,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G80";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -81,7 +81,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G84";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -107,7 +107,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G86";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -133,7 +133,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G92";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -159,7 +159,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G94";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -185,7 +185,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G96";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -211,7 +211,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G98";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -237,7 +237,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "G200";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -263,7 +263,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "MCP77/MCP78";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -289,7 +289,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "MCP79/MCP7A";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -315,7 +315,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "GT215";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -342,7 +342,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "GT216";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -368,7 +368,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "GT218";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -394,7 +394,7 @@ nv50_identify(struct nouveau_device *device)
                device->cname = "MCP89";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
index a3e0e5d..4393eb4 100644 (file)
@@ -58,7 +58,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF100";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -87,7 +87,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF104";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -116,7 +116,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF106";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -145,7 +145,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF114";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -174,7 +174,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF116";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -203,7 +203,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF108";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -232,7 +232,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF110";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -261,7 +261,7 @@ nvc0_identify(struct nouveau_device *device)
                device->cname = "GF119";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nvd0_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
index 1e02bec..5c12391 100644 (file)
@@ -58,7 +58,7 @@ nve0_identify(struct nouveau_device *device)
                device->cname = "GK104";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -87,7 +87,7 @@ nve0_identify(struct nouveau_device *device)
                device->cname = "GK107";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
@@ -116,7 +116,7 @@ nve0_identify(struct nouveau_device *device)
                device->cname = "GK106";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass;
-               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
index 7ad0d94..5de074a 100644 (file)
 int
 nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)
 {
-       if (port->aux) {
-               if (port->aux_mux)
-                       port->aux_mux(port);
-               return port->aux(port, 9, addr, data, size);
+       if (port->func->aux) {
+               if (port->func->acquire)
+                       port->func->acquire(port);
+               return port->func->aux(port, 9, addr, data, size);
        }
        return -ENODEV;
 }
@@ -38,10 +38,10 @@ nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)
 int
 nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)
 {
-       if (port->aux) {
-               if (port->aux_mux)
-                       port->aux_mux(port);
-               return port->aux(port, 8, addr, data, size);
+       if (port->func->aux) {
+               if (port->func->acquire)
+                       port->func->acquire(port);
+               return port->func->aux(port, 8, addr, data, size);
        }
        return -ENODEV;
 }
@@ -49,14 +49,14 @@ nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)
 static int
 aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
-       struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap;
+       struct nouveau_i2c_port *port = adap->algo_data;
        struct i2c_msg *msg = msgs;
        int ret, mcnt = num;
 
-       if (!port->aux)
+       if (!port->func->aux)
                return -ENODEV;
-       if ( port->aux_mux)
-               port->aux_mux(port);
+       if ( port->func->acquire)
+               port->func->acquire(port);
 
        while (mcnt--) {
                u8 remaining = msg->len;
@@ -74,7 +74,7 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                        if (mcnt || remaining > 16)
                                cmd |= 4; /* MOT */
 
-                       ret = port->aux(port, cmd, msg->addr, ptr, cnt);
+                       ret = port->func->aux(port, cmd, msg->addr, ptr, cnt);
                        if (ret < 0)
                                return ret;
 
index 6ab51d3..34a0523 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Red Hat Inc.
+ * Copyright 2013 Red Hat Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * Authors: Ben Skeggs
  */
 
-#include "core/option.h"
+#include <core/option.h>
 
-#include "subdev/i2c.h"
-#include "subdev/vga.h"
+#include <subdev/i2c.h>
+#include <subdev/vga.h>
 
-int
-nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg)
+/******************************************************************************
+ * interface to linux i2c bit-banging algorithm
+ *****************************************************************************/
+
+#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
+#define CSTMSEL true
+#else
+#define CSTMSEL false
+#endif
+
+static int
+nouveau_i2c_pre_xfer(struct i2c_adapter *adap)
 {
-       u8 val;
-       struct i2c_msg msgs[] = {
-               { .addr = addr, .flags = 0, .len = 1, .buf = &reg },
-               { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val },
-       };
+       struct i2c_algo_bit_data *bit = adap->algo_data;
+       struct nouveau_i2c_port *port = bit->data;
+       if (port->func->acquire)
+               port->func->acquire(port);
+       return 0;
+}
 
-       int ret = i2c_transfer(&port->adapter, msgs, 2);
-       if (ret != 2)
-               return -EIO;
+static void
+nouveau_i2c_setscl(void *data, int state)
+{
+       struct nouveau_i2c_port *port = data;
+       port->func->drive_scl(port, state);
+}
 
-       return val;
+static void
+nouveau_i2c_setsda(void *data, int state)
+{
+       struct nouveau_i2c_port *port = data;
+       port->func->drive_sda(port, state);
 }
 
-int
-nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val)
+static int
+nouveau_i2c_getscl(void *data)
 {
-       u8 buf[2] = { reg, val };
-       struct i2c_msg msgs[] = {
-               { .addr = addr, .flags = 0, .len = 2, .buf = buf },
-       };
+       struct nouveau_i2c_port *port = data;
+       return port->func->sense_scl(port);
+}
 
-       int ret = i2c_transfer(&port->adapter, msgs, 1);
-       if (ret != 1)
-               return -EIO;
+static int
+nouveau_i2c_getsda(void *data)
+{
+       struct nouveau_i2c_port *port = data;
+       return port->func->sense_sda(port);
+}
 
-       return 0;
+/******************************************************************************
+ * base i2c "port" class implementation
+ *****************************************************************************/
+
+void
+_nouveau_i2c_port_dtor(struct nouveau_object *object)
+{
+       struct nouveau_i2c_port *port = (void *)object;
+       i2c_del_adapter(&port->adapter);
+       nouveau_object_destroy(&port->base);
 }
 
-bool
-nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr)
+int
+nouveau_i2c_port_create_(struct nouveau_object *parent,
+                        struct nouveau_object *engine,
+                        struct nouveau_oclass *oclass, u8 index,
+                        const struct i2c_algorithm *algo,
+                        int size, void **pobject)
 {
-       u8 buf[] = { 0 };
-       struct i2c_msg msgs[] = {
-               {
-                       .addr = addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = buf,
-               },
-               {
-                       .addr = addr,
-                       .flags = I2C_M_RD,
-                       .len = 1,
-                       .buf = buf,
-               }
-       };
+       struct nouveau_device *device = nv_device(parent);
+       struct nouveau_i2c *i2c = (void *)engine;
+       struct nouveau_i2c_port *port;
+       int ret;
+
+       ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject);
+       port = *pobject;
+       if (ret)
+               return ret;
+
+       snprintf(port->adapter.name, sizeof(port->adapter.name),
+                "nouveau-%s-%d", device->name, index);
+       port->adapter.owner = THIS_MODULE;
+       port->adapter.dev.parent = &device->pdev->dev;
+       port->index = index;
+       i2c_set_adapdata(&port->adapter, i2c);
+
+       if ( algo == &nouveau_i2c_bit_algo &&
+           !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) {
+               struct i2c_algo_bit_data *bit;
+
+               bit = kzalloc(sizeof(*bit), GFP_KERNEL);
+               if (!bit)
+                       return -ENOMEM;
+
+               bit->udelay = 10;
+               bit->timeout = usecs_to_jiffies(2200);
+               bit->data = port;
+               bit->pre_xfer = nouveau_i2c_pre_xfer;
+               bit->setsda = nouveau_i2c_setsda;
+               bit->setscl = nouveau_i2c_setscl;
+               bit->getsda = nouveau_i2c_getsda;
+               bit->getscl = nouveau_i2c_getscl;
+
+               port->adapter.algo_data = bit;
+               ret = i2c_bit_add_bus(&port->adapter);
+       } else {
+               port->adapter.algo_data = port;
+               port->adapter.algo = algo;
+               ret = i2c_add_adapter(&port->adapter);
+       }
+
+       /* drop port's i2c subdev refcount, i2c handles this itself */
+       if (ret == 0) {
+               list_add_tail(&port->head, &i2c->ports);
+               atomic_dec(&engine->refcount);
+       }
 
-       return i2c_transfer(&port->adapter, msgs, 2) == 2;
+       return ret;
 }
 
+/******************************************************************************
+ * base i2c subdev class implementation
+ *****************************************************************************/
+
 static struct nouveau_i2c_port *
 nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index)
 {
@@ -115,7 +184,7 @@ nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type)
        struct nouveau_i2c_port *port;
 
        list_for_each_entry(port, &i2c->ports, head) {
-               if (port->type == type)
+               if (nv_hclass(port) == type)
                        return port;
        }
 
@@ -149,126 +218,78 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
        return -ENODEV;
 }
 
-void
-nouveau_i2c_drive_scl(void *data, int state)
+int
+_nouveau_i2c_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nouveau_i2c_port *port = data;
+       struct nouveau_i2c *i2c = (void *)object;
+       struct nouveau_i2c_port *port;
+       int ret;
 
-       if (port->type == DCB_I2C_NV04_BIT) {
-               u8 val = nv_rdvgac(port->i2c, 0, port->drive);
-               if (state) val |= 0x20;
-               else       val &= 0xdf;
-               nv_wrvgac(port->i2c, 0, port->drive, val | 0x01);
-       } else
-       if (port->type == DCB_I2C_NV4E_BIT) {
-               nv_mask(port->i2c, port->drive, 0x2f, state ? 0x21 : 0x01);
-       } else
-       if (port->type == DCB_I2C_NVIO_BIT) {
-               if (state) port->state |= 0x01;
-               else       port->state &= 0xfe;
-               nv_wr32(port->i2c, port->drive, 4 | port->state);
+       list_for_each_entry(port, &i2c->ports, head) {
+               ret = nv_ofuncs(port)->fini(nv_object(port), suspend);
+               if (ret && suspend)
+                       goto fail;
        }
-}
-
-void
-nouveau_i2c_drive_sda(void *data, int state)
-{
-       struct nouveau_i2c_port *port = data;
 
-       if (port->type == DCB_I2C_NV04_BIT) {
-               u8 val = nv_rdvgac(port->i2c, 0, port->drive);
-               if (state) val |= 0x10;
-               else       val &= 0xef;
-               nv_wrvgac(port->i2c, 0, port->drive, val | 0x01);
-       } else
-       if (port->type == DCB_I2C_NV4E_BIT) {
-               nv_mask(port->i2c, port->drive, 0x1f, state ? 0x11 : 0x01);
-       } else
-       if (port->type == DCB_I2C_NVIO_BIT) {
-               if (state) port->state |= 0x02;
-               else       port->state &= 0xfd;
-               nv_wr32(port->i2c, port->drive, 4 | port->state);
+       return nouveau_subdev_fini(&i2c->base, suspend);
+fail:
+       list_for_each_entry_continue_reverse(port, &i2c->ports, head) {
+               nv_ofuncs(port)->init(nv_object(port));
        }
+
+       return ret;
 }
 
 int
-nouveau_i2c_sense_scl(void *data)
+_nouveau_i2c_init(struct nouveau_object *object)
 {
-       struct nouveau_i2c_port *port = data;
-       struct nouveau_device *device = nv_device(port->i2c);
-
-       if (port->type == DCB_I2C_NV04_BIT) {
-               return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x04);
-       } else
-       if (port->type == DCB_I2C_NV4E_BIT) {
-               return !!(nv_rd32(port->i2c, port->sense) & 0x00040000);
-       } else
-       if (port->type == DCB_I2C_NVIO_BIT) {
-               if (device->card_type < NV_D0)
-                       return !!(nv_rd32(port->i2c, port->sense) & 0x01);
-               else
-                       return !!(nv_rd32(port->i2c, port->sense) & 0x10);
+       struct nouveau_i2c *i2c = (void *)object;
+       struct nouveau_i2c_port *port;
+       int ret;
+
+       ret = nouveau_subdev_init(&i2c->base);
+       if (ret == 0) {
+               list_for_each_entry(port, &i2c->ports, head) {
+                       ret = nv_ofuncs(port)->init(nv_object(port));
+                       if (ret)
+                               goto fail;
+               }
        }
 
-       return 0;
-}
-
-int
-nouveau_i2c_sense_sda(void *data)
-{
-       struct nouveau_i2c_port *port = data;
-       struct nouveau_device *device = nv_device(port->i2c);
-
-       if (port->type == DCB_I2C_NV04_BIT) {
-               return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x08);
-       } else
-       if (port->type == DCB_I2C_NV4E_BIT) {
-               return !!(nv_rd32(port->i2c, port->sense) & 0x00080000);
-       } else
-       if (port->type == DCB_I2C_NVIO_BIT) {
-               if (device->card_type < NV_D0)
-                       return !!(nv_rd32(port->i2c, port->sense) & 0x02);
-               else
-                       return !!(nv_rd32(port->i2c, port->sense) & 0x20);
+       return ret;
+fail:
+       list_for_each_entry_continue_reverse(port, &i2c->ports, head) {
+               nv_ofuncs(port)->fini(nv_object(port), false);
        }
 
-       return 0;
+       return ret;
 }
 
-static int
-nouveau_i2c_pre_xfer(struct i2c_adapter *adap)
+void
+_nouveau_i2c_dtor(struct nouveau_object *object)
 {
-       struct nouveau_i2c_port *port = (void *)adap;
-       struct nouveau_i2c *i2c = port->i2c;
-
-       if (nv_device(i2c)->card_type >= NV_50 && (port->dcb & 0x00000100)) {
-               u32 reg = 0x00e500 + ((port->dcb & 0x1e00) >> 9) * 0x50;
-               /* nfi, but neither auxch or i2c work if it's 1 */
-               nv_mask(i2c, reg + 0x0c, 0x00000001, 0x00000000);
-               /* nfi, but switches auxch vs normal i2c */
-               nv_mask(i2c, reg + 0x00, 0x0000f003, 0x0000e001);
+       struct nouveau_i2c *i2c = (void *)object;
+       struct nouveau_i2c_port *port, *temp;
+
+       list_for_each_entry_safe(port, temp, &i2c->ports, head) {
+               nouveau_object_ref(NULL, (struct nouveau_object **)&port);
        }
 
-       return 0;
+       nouveau_subdev_destroy(&i2c->base);
 }
 
-static const u32 nv50_i2c_port[] = {
-       0x00e138, 0x00e150, 0x00e168, 0x00e180,
-       0x00e254, 0x00e274, 0x00e764, 0x00e780,
-       0x00e79c, 0x00e7b8
-};
-
-static int
-nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                struct nouveau_oclass *oclass, void *data, u32 size,
-                struct nouveau_object **pobject)
+int
+nouveau_i2c_create_(struct nouveau_object *parent,
+                   struct nouveau_object *engine,
+                   struct nouveau_oclass *oclass,
+                   struct nouveau_oclass *sclass,
+                   int length, void **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nouveau_bios *bios = nouveau_bios(parent);
-       struct nouveau_i2c_port *port;
        struct nouveau_i2c *i2c;
+       struct nouveau_object *object;
        struct dcb_i2c_entry info;
-       int ret, i = -1;
+       int ret, index = -1;
 
        ret = nouveau_subdev_create(parent, engine, oclass, 0,
                                    "I2C", "i2c", &i2c);
@@ -281,142 +302,20 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        i2c->identify = nouveau_i2c_identify;
        INIT_LIST_HEAD(&i2c->ports);
 
-       while (!dcb_i2c_parse(bios, ++i, &info)) {
+       while (!dcb_i2c_parse(bios, ++index, &info)) {
                if (info.type == DCB_I2C_UNUSED)
                        continue;
 
-               port = kzalloc(sizeof(*port), GFP_KERNEL);
-               if (!port) {
-                       nv_error(i2c, "failed port memory alloc at %d\n", i);
-                       break;
-               }
-
-               port->type = info.type;
-               switch (port->type) {
-               case DCB_I2C_NV04_BIT:
-                       port->drive = info.drive;
-                       port->sense = info.sense;
-                       break;
-               case DCB_I2C_NV4E_BIT:
-                       port->drive = 0x600800 + info.drive;
-                       port->sense = port->drive;
-                       break;
-               case DCB_I2C_NVIO_BIT:
-                       port->drive = info.drive & 0x0f;
-                       if (device->card_type < NV_D0) {
-                               if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
-                                       break;
-                               port->drive = nv50_i2c_port[port->drive];
-                               port->sense = port->drive;
-                       } else {
-                               port->drive = 0x00d014 + (port->drive * 0x20);
-                               port->sense = port->drive;
-                       }
-                       break;
-               case DCB_I2C_NVIO_AUX:
-                       port->drive = info.drive & 0x0f;
-                       port->sense = port->drive;
-                       port->adapter.algo = &nouveau_i2c_aux_algo;
-                       port->aux_mux = nv94_aux_mux;
-                       port->aux = nv94_aux;
-                       break;
-               default:
-                       break;
-               }
-
-               if (!port->adapter.algo && !port->drive) {
-                       nv_error(i2c, "I2C%d: type %d index %x/%x unknown\n",
-                                i, port->type, port->drive, port->sense);
-                       kfree(port);
-                       continue;
-               }
-
-               snprintf(port->adapter.name, sizeof(port->adapter.name),
-                        "nouveau-%s-%d", device->name, i);
-               port->adapter.owner = THIS_MODULE;
-               port->adapter.dev.parent = &device->pdev->dev;
-               port->i2c = i2c;
-               port->index = i;
-               port->dcb = info.data;
-               i2c_set_adapdata(&port->adapter, i2c);
-
-               if (port->adapter.algo != &nouveau_i2c_aux_algo) {
-                       nouveau_i2c_drive_scl(port, 0);
-                       nouveau_i2c_drive_sda(port, 1);
-                       nouveau_i2c_drive_scl(port, 1);
-
-#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
-                       if (nouveau_boolopt(device->cfgopt, "NvI2C", true)) {
-#else
-                       if (nouveau_boolopt(device->cfgopt, "NvI2C", false)) {
-#endif
-                               port->adapter.algo = &nouveau_i2c_bit_algo;
-                               ret = i2c_add_adapter(&port->adapter);
-                       } else {
-                               port->adapter.algo_data = &port->bit;
-                               port->bit.udelay = 10;
-                               port->bit.timeout = usecs_to_jiffies(2200);
-                               port->bit.data = port;
-                               port->bit.setsda = nouveau_i2c_drive_sda;
-                               port->bit.setscl = nouveau_i2c_drive_scl;
-                               port->bit.getsda = nouveau_i2c_sense_sda;
-                               port->bit.getscl = nouveau_i2c_sense_scl;
-                               port->bit.pre_xfer = nouveau_i2c_pre_xfer;
-                               ret = i2c_bit_add_bus(&port->adapter);
+               oclass = sclass;
+               do {
+                       ret = -EINVAL;
+                       if (oclass->handle == info.type) {
+                               ret = nouveau_object_ctor(*pobject, *pobject,
+                                                         oclass, &info,
+                                                         index, &object);
                        }
-               } else {
-                       port->adapter.algo = &nouveau_i2c_aux_algo;
-                       ret = i2c_add_adapter(&port->adapter);
-               }
-
-               if (ret) {
-                       nv_error(i2c, "I2C%d: failed register: %d\n", i, ret);
-                       kfree(port);
-                       continue;
-               }
-
-               list_add_tail(&port->head, &i2c->ports);
+               } while (ret && (++oclass)->handle);
        }
 
        return 0;
 }
-
-static void
-nouveau_i2c_dtor(struct nouveau_object *object)
-{
-       struct nouveau_i2c *i2c = (void *)object;
-       struct nouveau_i2c_port *port, *temp;
-
-       list_for_each_entry_safe(port, temp, &i2c->ports, head) {
-               i2c_del_adapter(&port->adapter);
-               list_del(&port->head);
-               kfree(port);
-       }
-
-       nouveau_subdev_destroy(&i2c->base);
-}
-
-static int
-nouveau_i2c_init(struct nouveau_object *object)
-{
-       struct nouveau_i2c *i2c = (void *)object;
-       return nouveau_subdev_init(&i2c->base);
-}
-
-static int
-nouveau_i2c_fini(struct nouveau_object *object, bool suspend)
-{
-       struct nouveau_i2c *i2c = (void *)object;
-       return nouveau_subdev_fini(&i2c->base, suspend);
-}
-
-struct nouveau_oclass
-nouveau_i2c_oclass = {
-       .handle = NV_SUBDEV(I2C, 0x00),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nouveau_i2c_ctor,
-               .dtor = nouveau_i2c_dtor,
-               .init = nouveau_i2c_init,
-               .fini = nouveau_i2c_fini,
-       },
-};
index 1c4c9a5..a6e72d3 100644 (file)
 static inline void
 i2c_drive_scl(struct nouveau_i2c_port *port, int state)
 {
-       nouveau_i2c_drive_scl(port, state);
+       port->func->drive_scl(port, state);
 }
 
 static inline void
 i2c_drive_sda(struct nouveau_i2c_port *port, int state)
 {
-       nouveau_i2c_drive_sda(port, state);
+       port->func->drive_sda(port, state);
 }
 
 static inline int
 i2c_sense_scl(struct nouveau_i2c_port *port)
 {
-       return nouveau_i2c_sense_scl(port);
+       return port->func->sense_scl(port);
 }
 
 static inline int
 i2c_sense_sda(struct nouveau_i2c_port *port)
 {
-       return nouveau_i2c_sense_sda(port);
+       return port->func->sense_sda(port);
 }
 
 static void
@@ -77,9 +77,8 @@ i2c_start(struct nouveau_i2c_port *port)
 {
        int ret = 0;
 
-       port->state  = i2c_sense_scl(port);
-       port->state |= i2c_sense_sda(port) << 1;
-       if (port->state != 3) {
+       if (!i2c_sense_scl(port) ||
+           !i2c_sense_sda(port)) {
                i2c_drive_scl(port, 0);
                i2c_drive_sda(port, 1);
                if (!i2c_raise_scl(port))
@@ -184,10 +183,13 @@ i2c_addr(struct nouveau_i2c_port *port, struct i2c_msg *msg)
 static int
 i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
-       struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap;
+       struct nouveau_i2c_port *port = adap->algo_data;
        struct i2c_msg *msg = msgs;
        int ret = 0, mcnt = num;
 
+       if (port->func->acquire)
+               port->func->acquire(port);
+
        while (!ret && mcnt--) {
                u8 remaining = msg->len;
                u8 *ptr = msg->buf;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
new file mode 100644 (file)
index 0000000..2ad1884
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/i2c.h>
+#include <subdev/vga.h>
+
+struct nv04_i2c_priv {
+       struct nouveau_i2c base;
+};
+
+struct nv04_i2c_port {
+       struct nouveau_i2c_port base;
+       u8 drive;
+       u8 sense;
+};
+
+static void
+nv04_i2c_drive_scl(struct nouveau_i2c_port *base, int state)
+{
+       struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv04_i2c_port *port = (void *)base;
+       u8 val = nv_rdvgac(priv, 0, port->drive);
+       if (state) val |= 0x20;
+       else       val &= 0xdf;
+       nv_wrvgac(priv, 0, port->drive, val | 0x01);
+}
+
+static void
+nv04_i2c_drive_sda(struct nouveau_i2c_port *base, int state)
+{
+       struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv04_i2c_port *port = (void *)base;
+       u8 val = nv_rdvgac(priv, 0, port->drive);
+       if (state) val |= 0x10;
+       else       val &= 0xef;
+       nv_wrvgac(priv, 0, port->drive, val | 0x01);
+}
+
+static int
+nv04_i2c_sense_scl(struct nouveau_i2c_port *base)
+{
+       struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv04_i2c_port *port = (void *)base;
+       return !!(nv_rdvgac(priv, 0, port->sense) & 0x04);
+}
+
+static int
+nv04_i2c_sense_sda(struct nouveau_i2c_port *base)
+{
+       struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv04_i2c_port *port = (void *)base;
+       return !!(nv_rdvgac(priv, 0, port->sense) & 0x08);
+}
+
+static const struct nouveau_i2c_func
+nv04_i2c_func = {
+       .drive_scl = nv04_i2c_drive_scl,
+       .drive_sda = nv04_i2c_drive_sda,
+       .sense_scl = nv04_i2c_sense_scl,
+       .sense_sda = nv04_i2c_sense_sda,
+};
+
+static int
+nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                  struct nouveau_oclass *oclass, void *data, u32 index,
+                  struct nouveau_object **pobject)
+{
+       struct dcb_i2c_entry *info = data;
+       struct nv04_i2c_port *port;
+       int ret;
+
+       ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+                                    &nouveau_i2c_bit_algo, &port);
+       *pobject = nv_object(port);
+       if (ret)
+               return ret;
+
+       port->base.func = &nv04_i2c_func;
+       port->drive = info->drive;
+       port->sense = info->sense;
+       return 0;
+}
+
+static struct nouveau_oclass
+nv04_i2c_sclass[] = {
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV04_BIT),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nv04_i2c_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = _nouveau_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       {}
+};
+
+static int
+nv04_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 size,
+             struct nouveau_object **pobject)
+{
+       struct nv04_i2c_priv *priv;
+       int ret;
+
+       ret = nouveau_i2c_create(parent, engine, oclass, nv04_i2c_sclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass
+nv04_i2c_oclass = {
+       .handle = NV_SUBDEV(I2C, 0x04),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_i2c_ctor,
+               .dtor = _nouveau_i2c_dtor,
+               .init = _nouveau_i2c_init,
+               .fini = _nouveau_i2c_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
new file mode 100644 (file)
index 0000000..f501ae2
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/i2c.h>
+#include <subdev/vga.h>
+
+struct nv4e_i2c_priv {
+       struct nouveau_i2c base;
+};
+
+struct nv4e_i2c_port {
+       struct nouveau_i2c_port base;
+       u32 addr;
+};
+
+static void
+nv4e_i2c_drive_scl(struct nouveau_i2c_port *base, int state)
+{
+       struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv4e_i2c_port *port = (void *)base;
+       nv_mask(priv, port->addr, 0x2f, state ? 0x21 : 0x01);
+}
+
+static void
+nv4e_i2c_drive_sda(struct nouveau_i2c_port *base, int state)
+{
+       struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv4e_i2c_port *port = (void *)base;
+       nv_mask(priv, port->addr, 0x1f, state ? 0x11 : 0x01);
+}
+
+static int
+nv4e_i2c_sense_scl(struct nouveau_i2c_port *base)
+{
+       struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv4e_i2c_port *port = (void *)base;
+       return !!(nv_rd32(priv, port->addr) & 0x00040000);
+}
+
+static int
+nv4e_i2c_sense_sda(struct nouveau_i2c_port *base)
+{
+       struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv4e_i2c_port *port = (void *)base;
+       return !!(nv_rd32(priv, port->addr) & 0x00080000);
+}
+
+static const struct nouveau_i2c_func
+nv4e_i2c_func = {
+       .drive_scl = nv4e_i2c_drive_scl,
+       .drive_sda = nv4e_i2c_drive_sda,
+       .sense_scl = nv4e_i2c_sense_scl,
+       .sense_sda = nv4e_i2c_sense_sda,
+};
+
+static int
+nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                  struct nouveau_oclass *oclass, void *data, u32 index,
+                  struct nouveau_object **pobject)
+{
+       struct dcb_i2c_entry *info = data;
+       struct nv4e_i2c_port *port;
+       int ret;
+
+       ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+                                    &nouveau_i2c_bit_algo, &port);
+       *pobject = nv_object(port);
+       if (ret)
+               return ret;
+
+       port->base.func = &nv4e_i2c_func;
+       port->addr = 0x600800 + info->drive;
+       return 0;
+}
+
+static struct nouveau_oclass
+nv4e_i2c_sclass[] = {
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV4E_BIT),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nv4e_i2c_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = _nouveau_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       {}
+};
+
+static int
+nv4e_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 size,
+             struct nouveau_object **pobject)
+{
+       struct nv4e_i2c_priv *priv;
+       int ret;
+
+       ret = nouveau_i2c_create(parent, engine, oclass, nv4e_i2c_sclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass
+nv4e_i2c_oclass = {
+       .handle = NV_SUBDEV(I2C, 0x4e),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv4e_i2c_ctor,
+               .dtor = _nouveau_i2c_dtor,
+               .init = _nouveau_i2c_init,
+               .fini = _nouveau_i2c_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
new file mode 100644 (file)
index 0000000..378dfa3
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+void
+nv50_i2c_drive_scl(struct nouveau_i2c_port *base, int state)
+{
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       if (state) port->state |= 0x01;
+       else       port->state &= 0xfe;
+       nv_wr32(priv, port->addr, port->state);
+}
+
+void
+nv50_i2c_drive_sda(struct nouveau_i2c_port *base, int state)
+{
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       if (state) port->state |= 0x02;
+       else       port->state &= 0xfd;
+       nv_wr32(priv, port->addr, port->state);
+}
+
+int
+nv50_i2c_sense_scl(struct nouveau_i2c_port *base)
+{
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       return !!(nv_rd32(priv, port->addr) & 0x00000001);
+}
+
+int
+nv50_i2c_sense_sda(struct nouveau_i2c_port *base)
+{
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       return !!(nv_rd32(priv, port->addr) & 0x00000002);
+}
+
+static const struct nouveau_i2c_func
+nv50_i2c_func = {
+       .drive_scl = nv50_i2c_drive_scl,
+       .drive_sda = nv50_i2c_drive_sda,
+       .sense_scl = nv50_i2c_sense_scl,
+       .sense_sda = nv50_i2c_sense_sda,
+};
+
+const u32 nv50_i2c_addr[] = {
+       0x00e138, 0x00e150, 0x00e168, 0x00e180,
+       0x00e254, 0x00e274, 0x00e764, 0x00e780,
+       0x00e79c, 0x00e7b8
+};
+const int nv50_i2c_addr_nr = ARRAY_SIZE(nv50_i2c_addr);
+
+static int
+nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                  struct nouveau_oclass *oclass, void *data, u32 index,
+                  struct nouveau_object **pobject)
+{
+       struct dcb_i2c_entry *info = data;
+       struct nv50_i2c_port *port;
+       int ret;
+
+       ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+                                    &nouveau_i2c_bit_algo, &port);
+       *pobject = nv_object(port);
+       if (ret)
+               return ret;
+
+       if (info->drive >= nv50_i2c_addr_nr)
+               return -EINVAL;
+
+       port->base.func = &nv50_i2c_func;
+       port->state = 0x00000007;
+       port->addr = nv50_i2c_addr[info->drive];
+       return 0;
+}
+
+int
+nv50_i2c_port_init(struct nouveau_object *object)
+{
+       struct nv50_i2c_priv *priv = (void *)object->engine;
+       struct nv50_i2c_port *port = (void *)object;
+       nv_wr32(priv, port->addr, port->state);
+       return nouveau_i2c_port_init(&port->base);
+}
+
+static struct nouveau_oclass
+nv50_i2c_sclass[] = {
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nv50_i2c_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = nv50_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       {}
+};
+
+static int
+nv50_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 size,
+             struct nouveau_object **pobject)
+{
+       struct nv50_i2c_priv *priv;
+       int ret;
+
+       ret = nouveau_i2c_create(parent, engine, oclass, nv50_i2c_sclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass
+nv50_i2c_oclass = {
+       .handle = NV_SUBDEV(I2C, 0x50),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_i2c_ctor,
+               .dtor = _nouveau_i2c_dtor,
+               .init = _nouveau_i2c_init,
+               .fini = _nouveau_i2c_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h
new file mode 100644 (file)
index 0000000..4e5ba48
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __NV50_I2C_H__
+#define __NV50_I2C_H__
+
+#include <subdev/i2c.h>
+
+struct nv50_i2c_priv {
+       struct nouveau_i2c base;
+};
+
+struct nv50_i2c_port {
+       struct nouveau_i2c_port base;
+       u32 addr;
+       u32 ctrl;
+       u32 data;
+       u32 state;
+};
+
+extern const u32 nv50_i2c_addr[];
+extern const int nv50_i2c_addr_nr;
+int  nv50_i2c_port_init(struct nouveau_object *);
+int  nv50_i2c_sense_scl(struct nouveau_i2c_port *);
+int  nv50_i2c_sense_sda(struct nouveau_i2c_port *);
+void nv50_i2c_drive_scl(struct nouveau_i2c_port *, int state);
+void nv50_i2c_drive_sda(struct nouveau_i2c_port *, int state);
+
+int  nv94_aux_port_ctor(struct nouveau_object *, struct nouveau_object *,
+                       struct nouveau_oclass *, void *, u32,
+                       struct nouveau_object **);
+void nv94_i2c_acquire(struct nouveau_i2c_port *);
+void nv94_i2c_release(struct nouveau_i2c_port *);
+
+#endif
index 4c49853..61b7716 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Red Hat Inc.
+ * Copyright 2012 Red Hat Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * Authors: Ben Skeggs
  */
 
-#include <subdev/i2c.h>
+#include "nv50.h"
 
-/******************************************************************************
- * aux channel util functions
- *****************************************************************************/
 #define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args)
 #define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args)
 
@@ -72,12 +69,13 @@ auxch_init(struct nouveau_i2c *aux, int ch)
 }
 
 int
-nv94_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size)
+nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size)
 {
-       struct nouveau_i2c *aux = port->i2c;
+       struct nouveau_i2c *aux = nouveau_i2c(base);
+       struct nv50_i2c_port *port = (void *)base;
        u32 ctrl, stat, timeout, retries;
        u32 xbuf[4] = {};
-       int ch = port->drive;
+       int ch = port->addr;
        int ret, i;
 
        AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
@@ -153,13 +151,135 @@ out:
 }
 
 void
-nv94_aux_mux(struct nouveau_i2c_port *port)
+nv94_i2c_acquire(struct nouveau_i2c_port *base)
 {
-       if (port->dcb & 0x00000100) {
-               u32 reg = 0x00e500 + (port->drive * 0x50);
-               /* nfi, but neither auxch or i2c work if it's 1 */
-               nv_mask(port->i2c, reg + 0x0c, 0x00000001, 0x00000000);
-               /* nfi, but switches auxch vs normal i2c */
-               nv_mask(port->i2c, reg + 0x00, 0x0000f003, 0x00002002);
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       if (port->ctrl) {
+               nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000);
+               nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data);
        }
 }
+
+void
+nv94_i2c_release(struct nouveau_i2c_port *base)
+{
+}
+
+static const struct nouveau_i2c_func
+nv94_i2c_func = {
+       .acquire   = nv94_i2c_acquire,
+       .release   = nv94_i2c_release,
+       .drive_scl = nv50_i2c_drive_scl,
+       .drive_sda = nv50_i2c_drive_sda,
+       .sense_scl = nv50_i2c_sense_scl,
+       .sense_sda = nv50_i2c_sense_sda,
+};
+
+static int
+nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                  struct nouveau_oclass *oclass, void *data, u32 index,
+                  struct nouveau_object **pobject)
+{
+       struct dcb_i2c_entry *info = data;
+       struct nv50_i2c_port *port;
+       int ret;
+
+       ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+                                    &nouveau_i2c_bit_algo, &port);
+       *pobject = nv_object(port);
+       if (ret)
+               return ret;
+
+       if (info->drive >= nv50_i2c_addr_nr)
+               return -EINVAL;
+
+       port->base.func = &nv94_i2c_func;
+       port->state = 7;
+       port->addr = nv50_i2c_addr[info->drive];
+       if (info->share != DCB_I2C_UNUSED) {
+               port->ctrl = 0x00e500 + (info->share * 0x50);
+               port->data = 0x0000e001;
+       }
+       return 0;
+}
+
+static const struct nouveau_i2c_func
+nv94_aux_func = {
+       .acquire   = nv94_i2c_acquire,
+       .release   = nv94_i2c_release,
+       .aux       = nv94_aux,
+};
+
+int
+nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                  struct nouveau_oclass *oclass, void *data, u32 index,
+                  struct nouveau_object **pobject)
+{
+       struct dcb_i2c_entry *info = data;
+       struct nv50_i2c_port *port;
+       int ret;
+
+       ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+                                    &nouveau_i2c_aux_algo, &port);
+       *pobject = nv_object(port);
+       if (ret)
+               return ret;
+
+       port->base.func = &nv94_aux_func;
+       port->addr = info->drive;
+       if (info->share != DCB_I2C_UNUSED) {
+               port->ctrl = 0x00e500 + (info->drive * 0x50);
+               port->data = 0x00002002;
+       }
+
+       return 0;
+}
+
+static struct nouveau_oclass
+nv94_i2c_sclass[] = {
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nv94_i2c_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = nv50_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nv94_aux_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = _nouveau_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       {}
+};
+
+static int
+nv94_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 size,
+             struct nouveau_object **pobject)
+{
+       struct nv50_i2c_priv *priv;
+       int ret;
+
+       ret = nouveau_i2c_create(parent, engine, oclass, nv94_i2c_sclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass
+nv94_i2c_oclass = {
+       .handle = NV_SUBDEV(I2C, 0x94),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv94_i2c_ctor,
+               .dtor = _nouveau_i2c_dtor,
+               .init = _nouveau_i2c_init,
+               .fini = _nouveau_i2c_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
new file mode 100644 (file)
index 0000000..f761b8a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static int
+nvd0_i2c_sense_scl(struct nouveau_i2c_port *base)
+{
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       return !!(nv_rd32(priv, port->addr) & 0x00000010);
+}
+
+static int
+nvd0_i2c_sense_sda(struct nouveau_i2c_port *base)
+{
+       struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
+       struct nv50_i2c_port *port = (void *)base;
+       return !!(nv_rd32(priv, port->addr) & 0x00000020);
+}
+
+static const struct nouveau_i2c_func
+nvd0_i2c_func = {
+       .acquire   = nv94_i2c_acquire,
+       .release   = nv94_i2c_release,
+       .drive_scl = nv50_i2c_drive_scl,
+       .drive_sda = nv50_i2c_drive_sda,
+       .sense_scl = nvd0_i2c_sense_scl,
+       .sense_sda = nvd0_i2c_sense_sda,
+};
+
+static int
+nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                  struct nouveau_oclass *oclass, void *data, u32 index,
+                  struct nouveau_object **pobject)
+{
+       struct dcb_i2c_entry *info = data;
+       struct nv50_i2c_port *port;
+       int ret;
+
+       ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+                                    &nouveau_i2c_bit_algo, &port);
+       *pobject = nv_object(port);
+       if (ret)
+               return ret;
+
+       port->base.func = &nvd0_i2c_func;
+       port->state = 0x00000007;
+       port->addr = 0x00d014 + (info->drive * 0x20);
+       if (info->share != DCB_I2C_UNUSED) {
+               port->ctrl = 0x00e500 + (info->share * 0x50);
+               port->data = 0x0000e001;
+       }
+       return 0;
+}
+
+static struct nouveau_oclass
+nvd0_i2c_sclass[] = {
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nvd0_i2c_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = nv50_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX),
+         .ofuncs = &(struct nouveau_ofuncs) {
+                 .ctor = nv94_aux_port_ctor,
+                 .dtor = _nouveau_i2c_port_dtor,
+                 .init = _nouveau_i2c_port_init,
+                 .fini = _nouveau_i2c_port_fini,
+         },
+       },
+       {}
+};
+
+static int
+nvd0_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 size,
+             struct nouveau_object **pobject)
+{
+       struct nv50_i2c_priv *priv;
+       int ret;
+
+       ret = nouveau_i2c_create(parent, engine, oclass, nvd0_i2c_sclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass
+nvd0_i2c_oclass = {
+       .handle = NV_SUBDEV(I2C, 0xd0),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvd0_i2c_ctor,
+               .dtor = _nouveau_i2c_dtor,
+               .init = _nouveau_i2c_init,
+               .fini = _nouveau_i2c_fini,
+       },
+};
index 95a63e1..e24090b 100644 (file)
@@ -31,7 +31,7 @@ static bool
 probe_monitoring_device(struct nouveau_i2c_port *i2c,
                        struct i2c_board_info *info)
 {
-       struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c->i2c);
+       struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
        struct i2c_client *client;
 
        request_module("%s%s", I2C_MODULE_PREFIX, info->type);