Commit 66146da0 authored by Francisco Jerez's avatar Francisco Jerez Committed by Ben Skeggs

drm/nouveau: Add support for I2C hardware monitoring devices.

Signed-off-by: default avatarFrancisco Jerez <currojerez@riseup.net>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 8155cac4
...@@ -299,7 +299,10 @@ nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) ...@@ -299,7 +299,10 @@ nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
int int
nouveau_i2c_identify(struct drm_device *dev, const char *what, nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info, int index) struct i2c_board_info *info,
bool (*match)(struct nouveau_i2c_chan *,
struct i2c_board_info *),
int index)
{ {
struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
int i; int i;
...@@ -307,7 +310,8 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, ...@@ -307,7 +310,8 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what,
NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
for (i = 0; info[i].addr; i++) { for (i = 0; info[i].addr; i++) {
if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
(!match || match(i2c, &info[i]))) {
NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
return i; return i;
} }
......
...@@ -44,7 +44,10 @@ void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); ...@@ -44,7 +44,10 @@ void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
int nouveau_i2c_identify(struct drm_device *dev, const char *what, int nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info, int index); struct i2c_board_info *info,
bool (*match)(struct nouveau_i2c_chan *,
struct i2c_board_info *),
int index);
extern const struct i2c_algorithm nouveau_dp_i2c_algo; extern const struct i2c_algorithm nouveau_dp_i2c_algo;
......
...@@ -235,6 +235,48 @@ nouveau_temp_safety_checks(struct drm_device *dev) ...@@ -235,6 +235,48 @@ nouveau_temp_safety_checks(struct drm_device *dev)
temps->fan_boost = 40; temps->fan_boost = 40;
} }
static bool
probe_monitoring_device(struct nouveau_i2c_chan *i2c,
struct i2c_board_info *info)
{
char modalias[16] = "i2c:";
struct i2c_client *client;
strlcat(modalias, info->type, sizeof(modalias));
request_module(modalias);
client = i2c_new_device(&i2c->adapter, info);
if (!client)
return false;
if (!client->driver || client->driver->detect(client, info)) {
i2c_unregister_device(client);
return false;
}
return true;
}
static void
nouveau_temp_probe_i2c(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_table *dcb = &dev_priv->vbios.dcb;
struct i2c_board_info info[] = {
{ I2C_BOARD_INFO("w83l785ts", 0x2d) },
{ I2C_BOARD_INFO("w83781d", 0x2d) },
{ I2C_BOARD_INFO("f75375", 0x2e) },
{ I2C_BOARD_INFO("adt7473", 0x2e) },
{ I2C_BOARD_INFO("lm99", 0x4c) },
{ }
};
int idx = (dcb->version >= 0x40 ?
dcb->i2c_default_indices & 0xf : 2);
nouveau_i2c_identify(dev, "monitoring device", info,
probe_monitoring_device, idx);
}
void void
nouveau_temp_init(struct drm_device *dev) nouveau_temp_init(struct drm_device *dev)
{ {
...@@ -253,11 +295,11 @@ nouveau_temp_init(struct drm_device *dev) ...@@ -253,11 +295,11 @@ nouveau_temp_init(struct drm_device *dev)
temp = ROMPTR(bios, P.data[16]); temp = ROMPTR(bios, P.data[16]);
else else
NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); NV_WARN(dev, "unknown temp for BIT P %d\n", P.version);
} else {
NV_WARN(dev, "BMP entry unknown for temperature table.\n"); nouveau_temp_vbios_parse(dev, temp);
} }
nouveau_temp_vbios_parse(dev, temp); nouveau_temp_probe_i2c(dev);
} }
void void
......
...@@ -635,7 +635,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) ...@@ -635,7 +635,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
get_tmds_slave(encoder)) get_tmds_slave(encoder))
return; return;
type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); type = nouveau_i2c_identify(dev, "TMDS transmitter", info, NULL, 2);
if (type < 0) if (type < 0)
return; return;
......
...@@ -49,8 +49,8 @@ static struct i2c_board_info nv04_tv_encoder_info[] = { ...@@ -49,8 +49,8 @@ static struct i2c_board_info nv04_tv_encoder_info[] = {
int nv04_tv_identify(struct drm_device *dev, int i2c_index) int nv04_tv_identify(struct drm_device *dev, int i2c_index)
{ {
return nouveau_i2c_identify(dev, "TV encoder", return nouveau_i2c_identify(dev, "TV encoder", nv04_tv_encoder_info,
nv04_tv_encoder_info, i2c_index); NULL, i2c_index);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment