From 7dcd060c0e6e4f76ce7eea94c66437ce8f546530 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 16 Feb 2013 15:21:58 +1000 Subject: [PATCH] drm/nouveau/i2c: create proper chipset-specific class implementations Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 4 + .../nouveau/core/include/subdev/bios/i2c.h | 2 +- .../gpu/drm/nouveau/core/include/subdev/i2c.h | 128 ++++- .../gpu/drm/nouveau/core/subdev/bios/i2c.c | 15 +- .../gpu/drm/nouveau/core/subdev/device/nv04.c | 4 +- .../gpu/drm/nouveau/core/subdev/device/nv10.c | 16 +- .../gpu/drm/nouveau/core/subdev/device/nv20.c | 8 +- .../gpu/drm/nouveau/core/subdev/device/nv30.c | 10 +- .../gpu/drm/nouveau/core/subdev/device/nv40.c | 32 +- .../gpu/drm/nouveau/core/subdev/device/nv50.c | 28 +- .../gpu/drm/nouveau/core/subdev/device/nvc0.c | 16 +- .../gpu/drm/nouveau/core/subdev/device/nve0.c | 6 +- drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c | 26 +- .../gpu/drm/nouveau/core/subdev/i2c/base.c | 493 +++++++----------- drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c | 18 +- .../gpu/drm/nouveau/core/subdev/i2c/nv04.c | 143 +++++ .../gpu/drm/nouveau/core/subdev/i2c/nv4e.c | 135 +++++ .../gpu/drm/nouveau/core/subdev/i2c/nv50.c | 149 ++++++ .../gpu/drm/nouveau/core/subdev/i2c/nv50.h | 32 ++ .../gpu/drm/nouveau/core/subdev/i2c/nv94.c | 150 +++++- .../gpu/drm/nouveau/core/subdev/i2c/nvd0.c | 124 +++++ .../gpu/drm/nouveau/core/subdev/therm/ic.c | 2 +- 22 files changed, 1119 insertions(+), 422 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 29f8cc5f46d8..d8374ec77b7e 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h index 5079bedfd985..10b57a19a7de 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h @@ -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); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index a8043178f926..c5868cd73100 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -10,21 +10,54 @@ #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 *); - int (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8); + + 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 = ® }, + { .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 diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c index ad577db83766..cfb9288c6d28 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index f76bd4e9ae29..473c5c03d3c9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 46d55eac310d..d0774f5bebe1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index ad09854eb1c1..ab920e0dc45b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 2a982238d61a..5f2110261b04 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 3e43460dab82..f3d55efe9ac9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 0444f468f6bd..5ed2fa51ddc2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index a3e0e5deaca1..4393eb4d6564 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 1e02bec8ba61..5c12391619fd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c index 7ad0d94db4f7..5de074ad170b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c @@ -27,10 +27,10 @@ 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; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 6ab51d3b3016..34a05230affa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -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"), @@ -22,64 +22,133 @@ * Authors: Ben Skeggs */ -#include "core/option.h" +#include -#include "subdev/i2c.h" -#include "subdev/vga.h" +#include +#include -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 = ® }, - { .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; -} - -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; - + 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; } -bool -nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) +static void +nouveau_i2c_setscl(void *data, int state) { - 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, - } - }; - - return i2c_transfer(&port->adapter, msgs, 2) == 2; + struct nouveau_i2c_port *port = data; + port->func->drive_scl(port, state); } +static void +nouveau_i2c_setsda(void *data, int state) +{ + struct nouveau_i2c_port *port = data; + port->func->drive_sda(port, state); +} + +static int +nouveau_i2c_getscl(void *data) +{ + struct nouveau_i2c_port *port = data; + return port->func->sense_scl(port); +} + +static int +nouveau_i2c_getsda(void *data) +{ + struct nouveau_i2c_port *port = data; + return port->func->sense_sda(port); +} + +/****************************************************************************** + * 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); +} + +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) +{ + 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 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) -{ - 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 |= 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); - } -} - -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); - } -} - int -nouveau_i2c_sense_scl(void *data) +_nouveau_i2c_fini(struct nouveau_object *object, bool suspend) { - 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); - } - - 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 0; -} - -static int -nouveau_i2c_pre_xfer(struct i2c_adapter *adap) -{ - 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); - } - - return 0; -} - -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) -{ - struct nouveau_device *device = nv_device(parent); - struct nouveau_bios *bios = nouveau_bios(parent); + struct nouveau_i2c *i2c = (void *)object; struct nouveau_i2c_port *port; + int ret; + + list_for_each_entry(port, &i2c->ports, head) { + ret = nv_ofuncs(port)->fini(nv_object(port), suspend); + if (ret && suspend) + goto fail; + } + + 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_init(struct nouveau_object *object) +{ + 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 ret; +fail: + list_for_each_entry_continue_reverse(port, &i2c->ports, head) { + nv_ofuncs(port)->fini(nv_object(port), false); + } + + return ret; +} + +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) { + nouveau_object_ref(NULL, (struct nouveau_object **)&port); + } + + nouveau_subdev_destroy(&i2c->base); +} + +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_bios *bios = nouveau_bios(parent); 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; + oclass = sclass; + do { + ret = -EINVAL; + if (oclass->handle == info.type) { + ret = nouveau_object_ctor(*pobject, *pobject, + oclass, &info, + index, &object); } - 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); - } - } 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, - }, -}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c index 1c4c9a5c8e2e..a6e72d3b06b5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c @@ -32,25 +32,25 @@ 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 index 000000000000..2ad18840fe63 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c @@ -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 +#include + +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 index 000000000000..f501ae25dbb3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c @@ -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 +#include + +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 index 000000000000..378dfa324e5f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c @@ -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 index 000000000000..4e5ba48ebf5a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h @@ -0,0 +1,32 @@ +#ifndef __NV50_I2C_H__ +#define __NV50_I2C_H__ + +#include + +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 diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c index 4c498532d793..61b771670bfe 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c @@ -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"), @@ -22,11 +22,8 @@ * Authors: Ben Skeggs */ -#include +#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 index 000000000000..f761b8a610f1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c @@ -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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index 95a63e12c52c..e24090bac195 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -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);