diff --git a/kernel/chips/mtp008.c b/kernel/chips/mtp008.c index 9848c353..64875b72 100644 --- a/kernel/chips/mtp008.c +++ b/kernel/chips/mtp008.c @@ -726,6 +726,7 @@ void mtp008_update_client(struct i2c_client *client) */ inp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2); mtp008_getsensortype(data, inp); + data->pwmenable = inp; /* * Read the PWM registers if enabled. @@ -740,10 +741,10 @@ void mtp008_update_client(struct i2c_client *client) } /* - * Read the fan sensors. Skip 3 if PWM3 enabled. + * Read the fan sensors. Skip 3 if PWM1 enabled. */ for (i = 1; i <= 3; i++) { - if(i == 3 && PWMENABLE_FROM_REG(3, inp)) { + if(i == 3 && PWMENABLE_FROM_REG(1, inp)) { data->fan[2] = 0; data->fan_min[2] = 0; } else { @@ -1079,12 +1080,20 @@ void mtp008_pwm(struct i2c_client *client, int operation, int ctl_name, mtp008_update_client(client); results[0] = PWM_FROM_REG(data->pwm[nr]); - - *nrels_mag = 1; + results[1] = PWMENABLE_FROM_REG(nr + 1, data->pwmenable); + *nrels_mag = 2; break; case SENSORS_PROC_REAL_WRITE: if (*nrels_mag >= 1) { + if (*nrels_mag >= 2) { + if(results[1]) + data->pwmenable |= 0x10 << nr; + else + data->pwmenable &= ~(0x10 << nr); + mtp008_write_value(client, MTP008_REG_PIN_CTRL2, + data->pwmenable); + } data->pwm[nr] = PWM_TO_REG(results[0]); mtp008_write_value(client, MTP008_REG_PWM_CTRL(nr), data->pwm[nr]); diff --git a/kernel/chips/vt1211.c b/kernel/chips/vt1211.c index ca704f3f..a11f6a16 100644 --- a/kernel/chips/vt1211.c +++ b/kernel/chips/vt1211.c @@ -163,8 +163,8 @@ static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e, 0x2c, 0x2e, 0x30, 0x32 }; #define DIV_FROM_REG(val) (1 << (val)) #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) -#define PWM_FROM_REG(val) (((val) * 1005) / 2550) -#define PWM_TO_REG(val) SENSORS_LIMIT((((val) * 2555) / 1000), 0, 255) +#define PWM_FROM_REG(val) (val) +#define PWM_TO_REG(val) SENSORS_LIMIT((val), 0, 255) #define TEMP_FROM_REG(val) ((val)*10) #define TEMP_FROM_REG10(val) (((val)*10)/4) diff --git a/kernel/chips/vt8231.c b/kernel/chips/vt8231.c index cc7b394c..408672a4 100644 --- a/kernel/chips/vt8231.c +++ b/kernel/chips/vt8231.c @@ -121,8 +121,8 @@ static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e, 0x2c, 0x2e, 0x30, 0x32 }; #define DIV_FROM_REG(val) (1 << (val)) #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) -#define PWM_FROM_REG(val) (((val) * 1005) / 2550) -#define PWM_TO_REG(val) SENSORS_LIMIT((((val) * 2555) / 1000), 0, 255) +#define PWM_FROM_REG(val) (val) +#define PWM_TO_REG(val) SENSORS_LIMIT((val), 0, 255) #define TEMP_FROM_REG(val) ((val)*10) #define TEMP_FROM_REG10(val) (((val)*10)/4) diff --git a/kernel/chips/w83627hf.c b/kernel/chips/w83627hf.c index 950753b0..326ec24c 100644 --- a/kernel/chips/w83627hf.c +++ b/kernel/chips/w83627hf.c @@ -51,6 +51,10 @@ #define init_MUTEX(s) do { *(s) = MUTEX; } while(0) #endif +#ifndef I2C_DRIVERID_W83627HF +#define I2C_DRIVERID_W83627HF 1038 +#endif + #ifndef THIS_MODULE #define THIS_MODULE NULL #endif @@ -59,7 +63,7 @@ static int force_addr; MODULE_PARM(force_addr, "i"); MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); -static int force_i2c = 0x29; +static int force_i2c = 0x1f; MODULE_PARM(force_i2c, "i"); MODULE_PARM_DESC(force_i2c, "Initialize the i2c address of the sensors"); @@ -404,7 +408,8 @@ struct w83627hf_data { u32 alarms; /* Register encoding, combined */ u32 beeps; /* Register encoding, combined */ u8 beep_enable; /* Boolean */ - u8 pwm[4]; /* Register value */ + u8 pwm[2]; /* Register value */ + u8 pwmenable[2]; /* bool */ u16 sens[3]; /* 782D/783S only. 1 = pentium diode; 2 = 3904 diode; 3000-5000 = thermistor beta. @@ -465,7 +470,7 @@ static int w83627hf_id = 0; static struct i2c_driver w83627hf_driver = { /* name */ "W83781D sensor driver", - /* id */ I2C_DRIVERID_W83781D, + /* id */ I2C_DRIVERID_W83627HF, /* flags */ I2C_DF_NOTIFY, /* attach_adapter */ &w83627hf_attach_adapter, /* detach_client */ &w83627hf_detach_client, @@ -726,9 +731,6 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address, very code-efficient in this case. */ ERROR7: - ERROR6: - ERROR5: - ERROR4: i2c_detach_client(new_client); ERROR3: release_region(address, WINB_EXTENT); @@ -905,6 +907,9 @@ void w83627hf_init_client(struct i2c_client *client) break; } + data->pwmenable[0] = 1; + data->pwmenable[1] = 1; + if(init) { w83627hf_write_value(client, W83781D_REG_IN_MIN(0), IN_TO_REG(W83781D_INIT_IN_MIN_0)); @@ -1375,7 +1380,8 @@ void w83627hf_pwm(struct i2c_client *client, int operation, int ctl_name, else if (operation == SENSORS_PROC_REAL_READ) { w83627hf_update_client(client); results[0] = data->pwm[nr - 1]; - *nrels_mag = 1; + results[1] = data->pwmenable[nr - 1]; + *nrels_mag = 2; } else if (operation == SENSORS_PROC_REAL_WRITE) { if (*nrels_mag >= 1) { data->pwm[nr - 1] = PWM_TO_REG(results[0]); diff --git a/kernel/chips/w83781d.c b/kernel/chips/w83781d.c index 3316e141..d9404a64 100644 --- a/kernel/chips/w83781d.c +++ b/kernel/chips/w83781d.c @@ -367,6 +367,7 @@ struct w83781d_data { u32 beeps; /* Register encoding, combined */ u8 beep_enable; /* Boolean */ u8 pwm[4]; /* Register value */ + u8 pwmenable[4]; /* bool */ u16 sens[3]; /* 782D/783S only. 1 = pentium diode; 2 = 3904 diode; 3000-5000 = thermistor beta. @@ -1275,20 +1276,22 @@ int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) void w83781d_init_client(struct i2c_client *client) { struct w83781d_data *data = client->data; - int vid = 0, i; + int vid = 0, i, p; int type = data->type; u8 tmp; if(init && type != as99127f) { /* this resets registers we don't have documentation for on the as99127f */ - /* save this register */ + /* save these registers */ i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); + p = w83781d_read_value(client, W83781D_REG_PWMCLK12); /* Reset all except Watchdog values and last conversion values This sets fan-divs to 2, among others */ w83781d_write_value(client, W83781D_REG_CONFIG, 0x80); - /* Restore the register and disable power-on abnormal beep. + /* Restore the registers and disable power-on abnormal beep. This saves FAN 1/2/3 input/output values set by BIOS. */ w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); + w83781d_write_value(client, W83781D_REG_PWMCLK12, p); /* Disable master beep-enable (reset turns it on). Individual beeps should be reset to off but for some reason disabling this bit helps some people not get beeped */ @@ -1459,12 +1462,11 @@ void w83781d_init_client(struct i2c_client *client) 0x00); } if (type != w83781d) { - /* enable PWM2 control (can't hurt since PWM reg - should have been reset to 0xff) */ - w83781d_write_value(client, W83781D_REG_PWMCLK12, 0x19); /* enable comparator mode for temp2 and temp3 so alarm indication will work correctly */ w83781d_write_value(client, W83781D_REG_IRQ, 0x41); + for(i = 0; i < 3; i++) + data->pwmenable[i] = 1; } } @@ -1478,7 +1480,7 @@ void w83781d_init_client(struct i2c_client *client) void w83781d_update_client(struct i2c_client *client) { struct w83781d_data *data = client->data; - int i; + int i, j; down(&data->update_lock); @@ -1504,7 +1506,16 @@ void w83781d_update_client(struct i2c_client *client) && (data->type != w83627hf) && (i == 6)) break; } + /* PWM2 pin shared with FAN3 */ + j = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG) & 0x10; + data->pwmenable[1] = (!j) && + (w83781d_read_value(client, W83781D_REG_PWMCLK12) & 0x08); for (i = 1; i <= 3; i++) { + if(i == 3 && !j) { + data->fan[2] = 255; + data->fan_min[2] = 255; + break; + } data->fan[i - 1] = w83781d_read_value(client, W83781D_REG_FAN(i)); data->fan_min[i - 1] = @@ -1899,19 +1910,43 @@ void w83781d_pwm(struct i2c_client *client, int operation, int ctl_name, { struct w83781d_data *data = client->data; int nr = 1 + ctl_name - W83781D_SYSCTL_PWM1; + int j, k; if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; else if (operation == SENSORS_PROC_REAL_READ) { w83781d_update_client(client); results[0] = PWM_FROM_REG(data->pwm[nr - 1]); - *nrels_mag = 1; + results[1] = data->pwmenable[nr - 1]; + *nrels_mag = 2; } else if (operation == SENSORS_PROC_REAL_WRITE) { if (*nrels_mag >= 1) { data->pwm[nr - 1] = PWM_TO_REG(results[0]); w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); } + /* only PWM2 can be enabled/disabled */ + if (*nrels_mag >= 2 && nr == 2) { + j = w83781d_read_value(client, W83781D_REG_PWMCLK12); + k = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); + if(results[1]) { + if(!(j & 0x08)) + w83781d_write_value(client, + W83781D_REG_PWMCLK12, j | 0x08); + if(k & 0x10) + w83781d_write_value(client, + W83781D_REG_BEEP_CONFIG, k & 0xef); + data->pwmenable[1] = 1; + } else { + if(j & 0x08) + w83781d_write_value(client, + W83781D_REG_PWMCLK12, j & 0xf7); + if(!(k & 0x10)) + w83781d_write_value(client, + W83781D_REG_BEEP_CONFIG, j | 0x10); + data->pwmenable[1] = 0; + } + } } }