aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2013-10-20 19:48:55 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-11-08 00:39:54 -0500
commit9e2b734f1cc43e94558bfd2b779d8e493abea0f4 (patch)
tree7506e6f685b099eff0667484112834f5cae83e45
parentfd34381b0e2827228cbda45aa2cca4127ff073b2 (diff)
drm/nouveau/i2c: use a custom bitbanging delay for the adt7473
This patch adds a way to define a custom delay when scanning for i2c devices because the adt7473 sometimes doesn't like the default bitbanging udelay. Signed-off-by: Martin Peres <martin.peres@labri.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/i2c.h7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c27
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/ic.c54
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c16
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv04.c22
5 files changed, 77 insertions, 49 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
index 7e4e2775f249..9fa5da723871 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
@@ -60,13 +60,18 @@ void _nouveau_i2c_port_dtor(struct nouveau_object *);
60#define _nouveau_i2c_port_init nouveau_object_init 60#define _nouveau_i2c_port_init nouveau_object_init
61#define _nouveau_i2c_port_fini nouveau_object_fini 61#define _nouveau_i2c_port_fini nouveau_object_fini
62 62
63struct nouveau_i2c_board_info {
64 struct i2c_board_info dev;
65 u8 udelay; /* set to 0 to use the standard delay */
66};
67
63struct nouveau_i2c { 68struct nouveau_i2c {
64 struct nouveau_subdev base; 69 struct nouveau_subdev base;
65 70
66 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); 71 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index);
67 struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type); 72 struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type);
68 int (*identify)(struct nouveau_i2c *, int index, 73 int (*identify)(struct nouveau_i2c *, int index,
69 const char *what, struct i2c_board_info *, 74 const char *what, struct nouveau_i2c_board_info *,
70 bool (*match)(struct nouveau_i2c_port *, 75 bool (*match)(struct nouveau_i2c_port *,
71 struct i2c_board_info *)); 76 struct i2c_board_info *));
72 struct list_head ports; 77 struct list_head ports;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index 2895c19bb152..041fd5edaebf 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -195,7 +195,7 @@ nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type)
195 195
196static int 196static int
197nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, 197nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
198 struct i2c_board_info *info, 198 struct nouveau_i2c_board_info *info,
199 bool (*match)(struct nouveau_i2c_port *, 199 bool (*match)(struct nouveau_i2c_port *,
200 struct i2c_board_info *)) 200 struct i2c_board_info *))
201{ 201{
@@ -208,12 +208,29 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
208 } 208 }
209 209
210 nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index); 210 nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index);
211 for (i = 0; info[i].addr; i++) { 211 for (i = 0; info[i].dev.addr; i++) {
212 if (nv_probe_i2c(port, info[i].addr) && 212 u8 orig_udelay = 0;
213 (!match || match(port, &info[i]))) { 213
214 nv_info(i2c, "detected %s: %s\n", what, info[i].type); 214 if ((port->adapter.algo == &i2c_bit_algo) &&
215 (info[i].udelay != 0)) {
216 struct i2c_algo_bit_data *algo = port->adapter.algo_data;
217 nv_debug(i2c, "using custom udelay %d instead of %d\n",
218 info[i].udelay, algo->udelay);
219 orig_udelay = algo->udelay;
220 algo->udelay = info[i].udelay;
221 }
222
223 if (nv_probe_i2c(port, info[i].dev.addr) &&
224 (!match || match(port, &info[i].dev))) {
225 nv_info(i2c, "detected %s: %s\n", what,
226 info[i].dev.type);
215 return i; 227 return i;
216 } 228 }
229
230 if (orig_udelay) {
231 struct i2c_algo_bit_data *algo = port->adapter.algo_data;
232 algo->udelay = orig_udelay;
233 }
217 } 234 }
218 235
219 nv_debug(i2c, "no devices found.\n"); 236 nv_debug(i2c, "no devices found.\n");
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
index 8b3adec5fbb1..13b850076443 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
@@ -55,28 +55,28 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
55 return true; 55 return true;
56} 56}
57 57
58static struct i2c_board_info 58static struct nouveau_i2c_board_info
59nv_board_infos[] = { 59nv_board_infos[] = {
60 { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 60 { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 },
61 { I2C_BOARD_INFO("w83781d", 0x2d) }, 61 { { I2C_BOARD_INFO("w83781d", 0x2d) }, 0 },
62 { I2C_BOARD_INFO("adt7473", 0x2e) }, 62 { { I2C_BOARD_INFO("adt7473", 0x2e) }, 20 },
63 { I2C_BOARD_INFO("adt7473", 0x2d) }, 63 { { I2C_BOARD_INFO("adt7473", 0x2d) }, 20 },
64 { I2C_BOARD_INFO("adt7473", 0x2c) }, 64 { { I2C_BOARD_INFO("adt7473", 0x2c) }, 20 },
65 { I2C_BOARD_INFO("f75375", 0x2e) }, 65 { { I2C_BOARD_INFO("f75375", 0x2e) }, 0 },
66 { I2C_BOARD_INFO("lm99", 0x4c) }, 66 { { I2C_BOARD_INFO("lm99", 0x4c) }, 0 },
67 { I2C_BOARD_INFO("lm90", 0x4c) }, 67 { { I2C_BOARD_INFO("lm90", 0x4c) }, 0 },
68 { I2C_BOARD_INFO("lm90", 0x4d) }, 68 { { I2C_BOARD_INFO("lm90", 0x4d) }, 0 },
69 { I2C_BOARD_INFO("adm1021", 0x18) }, 69 { { I2C_BOARD_INFO("adm1021", 0x18) }, 0 },
70 { I2C_BOARD_INFO("adm1021", 0x19) }, 70 { { I2C_BOARD_INFO("adm1021", 0x19) }, 0 },
71 { I2C_BOARD_INFO("adm1021", 0x1a) }, 71 { { I2C_BOARD_INFO("adm1021", 0x1a) }, 0 },
72 { I2C_BOARD_INFO("adm1021", 0x29) }, 72 { { I2C_BOARD_INFO("adm1021", 0x29) }, 0 },
73 { I2C_BOARD_INFO("adm1021", 0x2a) }, 73 { { I2C_BOARD_INFO("adm1021", 0x2a) }, 0 },
74 { I2C_BOARD_INFO("adm1021", 0x2b) }, 74 { { I2C_BOARD_INFO("adm1021", 0x2b) }, 0 },
75 { I2C_BOARD_INFO("adm1021", 0x4c) }, 75 { { I2C_BOARD_INFO("adm1021", 0x4c) }, 0 },
76 { I2C_BOARD_INFO("adm1021", 0x4d) }, 76 { { I2C_BOARD_INFO("adm1021", 0x4d) }, 0 },
77 { I2C_BOARD_INFO("adm1021", 0x4e) }, 77 { { I2C_BOARD_INFO("adm1021", 0x4e) }, 0 },
78 { I2C_BOARD_INFO("lm63", 0x18) }, 78 { { I2C_BOARD_INFO("lm63", 0x18) }, 0 },
79 { I2C_BOARD_INFO("lm63", 0x4e) }, 79 { { I2C_BOARD_INFO("lm63", 0x4e) }, 0 },
80 { } 80 { }
81}; 81};
82 82
@@ -89,9 +89,9 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
89 struct nvbios_extdev_func extdev_entry; 89 struct nvbios_extdev_func extdev_entry;
90 90
91 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { 91 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) {
92 struct i2c_board_info board[] = { 92 struct nouveau_i2c_board_info board[] = {
93 { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 93 { { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 0},
94 { } 94 { }
95 }; 95 };
96 96
97 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", 97 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
@@ -101,9 +101,9 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
101 } 101 }
102 102
103 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) { 103 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) {
104 struct i2c_board_info board[] = { 104 struct nouveau_i2c_board_info board[] = {
105 { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, 105 { { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, 20 },
106 { } 106 { }
107 }; 107 };
108 108
109 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", 109 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index bb6c3c3f981d..936a71c59080 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -625,13 +625,15 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
625 struct nouveau_drm *drm = nouveau_drm(dev); 625 struct nouveau_drm *drm = nouveau_drm(dev);
626 struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 626 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
627 struct nouveau_i2c_port *port = i2c->find(i2c, 2); 627 struct nouveau_i2c_port *port = i2c->find(i2c, 2);
628 struct i2c_board_info info[] = { 628 struct nouveau_i2c_board_info info[] = {
629 { 629 {
630 .type = "sil164", 630 {
631 .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38), 631 .type = "sil164",
632 .platform_data = &(struct sil164_encoder_params) { 632 .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38),
633 SIL164_INPUT_EDGE_RISING 633 .platform_data = &(struct sil164_encoder_params) {
634 } 634 SIL164_INPUT_EDGE_RISING
635 }
636 }, 0
635 }, 637 },
636 { } 638 { }
637 }; 639 };
@@ -646,7 +648,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
646 return; 648 return;
647 649
648 drm_i2c_encoder_init(dev, to_encoder_slave(encoder), 650 drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
649 &port->adapter, &info[type]); 651 &port->adapter, &info[type].dev);
650} 652}
651 653
652static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { 654static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
index bf13db4e8631..cc4b208ce546 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
@@ -37,15 +37,18 @@
37 37
38#include <subdev/i2c.h> 38#include <subdev/i2c.h>
39 39
40static struct i2c_board_info nv04_tv_encoder_info[] = { 40static struct nouveau_i2c_board_info nv04_tv_encoder_info[] = {
41 { 41 {
42 I2C_BOARD_INFO("ch7006", 0x75), 42 {
43 .platform_data = &(struct ch7006_encoder_params) { 43 I2C_BOARD_INFO("ch7006", 0x75),
44 CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, 44 .platform_data = &(struct ch7006_encoder_params) {
45 0, 0, 0, 45 CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
46 CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, 46 0, 0, 0,
47 CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC 47 CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
48 } 48 CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
49 }
50 },
51 0
49 }, 52 },
50 { } 53 { }
51}; 54};
@@ -229,7 +232,8 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
229 232
230 /* Run the slave-specific initialization */ 233 /* Run the slave-specific initialization */
231 ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), 234 ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
232 &port->adapter, &nv04_tv_encoder_info[type]); 235 &port->adapter,
236 &nv04_tv_encoder_info[type].dev);
233 if (ret < 0) 237 if (ret < 0)
234 goto fail_cleanup; 238 goto fail_cleanup;
235 239