Show
Ignore:
Timestamp:
12/17/05 18:26:35 (7 years ago)
Author:
khali
Message:

Fix fan div auto-adjust. Patch from Yuan Mu.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lm-sensors/trunk/kernel/chips/w83792d.c

    r3211 r3217  
    307307static void w83792d_vrm(struct i2c_client *client, int operation, 
    308308                        int ctl_name, int *nrels_mag, long *results); */ 
     309static void w83792d_set_fan_div(struct i2c_client *client, 
     310                                int nr, u8 newdiv); 
    309311static void w83792d_fan_div(struct i2c_client *client, int operation, 
    310312                            int ctl_name, int *nrels_mag, long *results); 
     
    444446        /*{W83792D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real, 
    445447         &i2c_sysctl_real, NULL, &w83792d_vid}, */ 
    446         {W83792D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real, 
     448        {W83792D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0444, NULL, &i2c_proc_real, 
    447449         &i2c_sysctl_real, NULL, &w83792d_fan_div}, 
    448450        {W83792D_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, 
     
    833835                data->fan_div[6] = reg_array_tmp[3] & 0x07; 
    834836 
     837                for (i = 0; i < 7; i++) { 
     838                        if (!(data->has_fan & (1 << i))) 
     839                                continue; 
     840                        if (data->fan[i] == 0xff && data->fan_div[i] < 7) 
     841                                w83792d_set_fan_div(client, i, 7); 
     842                        else if (data->fan[i] < 0x70 && data->fan_div[i] > 0) { 
     843                                w83792d_set_fan_div(client, i, 
     844                                                        data->fan_div[i] - 1); 
     845                        } else if (data->fan[i] > 0xf8 && 
     846                                                data->fan_div[i] < 7) { 
     847                                w83792d_set_fan_div(client, i, 
     848                                                        data->fan_div[i] + 1); 
     849                        } 
     850                } 
     851 
    835852                /* Update the Temperature1 measured value and limits */ 
    836853                data->temp1[0] = w83792d_read_value(client, W83792D_REG_TEMP1); 
     
    10021019} 
    10031020 
     1021static void w83792d_set_fan_div(struct i2c_client *client, int nr, u8 newdiv) 
     1022{ 
     1023        struct w83792d_data *data = client->data; 
     1024        int min = 0; 
     1025        int old = 0; 
     1026        u8 tmp = 0; 
     1027 
     1028        newdiv = SENSORS_LIMIT(newdiv, 0, 7); 
     1029 
     1030        if (newdiv == data->fan_div[nr]) { 
     1031                return; 
     1032        } 
     1033 
     1034        min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); 
     1035        old = FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr])); 
     1036        data->fan_div[nr] = newdiv; 
     1037        tmp = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]); 
     1038        tmp &= (nr & 1) ? 0x8f : 0xf8; 
     1039        tmp |= (nr & 1) ? ((newdiv << 4) & 0x70) : (newdiv & 0x07); 
     1040        w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1], tmp); 
     1041        data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); 
     1042        data->fan[nr] = FAN_TO_REG(old, DIV_FROM_REG(data->fan_div[nr])); 
     1043        w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], 
     1044                                data->fan_min[nr]); 
     1045} 
     1046 
    10041047/* read/write fan meaured value and limits */ 
    10051048static void w83792d_fan(struct i2c_client *client, int operation, int ctl_name, 
     
    10081051        struct w83792d_data *data = client->data; 
    10091052        int nr = ctl_name - W83792D_SYSCTL_FAN1; 
    1010         u8 tmp_reg, tmp_fan_div; 
    10111053 
    10121054        /* result[0]: low limit, result[1]: measured value */ 
     
    10161058                w83792d_update_client(client); 
    10171059                results[0] = FAN_FROM_REG(data->fan_min[nr], 
    1018                                   DIV_FROM_REG(data->fan_div[nr])); 
    1019                 /* adjust Fan Divisor, then change RPM */ 
    1020                 do { 
    1021                         w83792d_update_client(client); 
    1022                         if ((data->fan[nr]>0x50) && (data->fan[nr]<0xff)) { 
    1023                         /* optimal case. 0x50 and 0xff are experience data */ 
    1024                                 results[1] = FAN_FROM_REG(data->fan[nr], 
    1025                                                 DIV_FROM_REG(data->fan_div[nr])); 
    1026                                 break; /* go out of the do-while loop. */ 
    1027                         } else { 
    1028                                 if (((data->fan_div[nr])>=0x07 && 
    1029                                         (data->fan[nr])==0xff) || 
    1030                                     ((data->fan_div[nr])<=0 && 
    1031                                         (data->fan[nr])<0x78)) { 
    1032                                         results[1] = 0; 
    1033                                         break; 
    1034                                 } else if ((data->fan_div[nr])<0x07 && 
    1035                                          (data->fan[nr])==0xff) { 
    1036                                         (data->fan_div[nr])++; 
    1037                                         results[1] = FAN_FROM_REG(data->fan[nr], 
    1038                                                      DIV_FROM_REG(data->fan_div[nr])); 
    1039                                 } else if ((data->fan_div[nr])>0 && 
    1040                                           (data->fan[nr])<0x78) { 
    1041                                         (data->fan_div[nr])--; 
    1042                                         results[1] = FAN_FROM_REG(data->fan[nr], 
    1043                                                      DIV_FROM_REG(data->fan_div[nr])); 
    1044                                 } 
    1045  
    1046                                 tmp_reg = w83792d_read_value(client, 
    1047                                                 W83792D_REG_FAN_DIV[nr/2]); 
    1048                                 tmp_reg &= (nr%2 == 0) ? 0xf8 : 0x8f; 
    1049                                 tmp_fan_div = (nr%2 == 0) ? (data->fan_div[nr]) 
    1050                                         : (((data->fan_div[nr])<<4)&0x70); 
    1051                                 w83792d_write_value(client, 
    1052                                                     W83792D_REG_FAN_DIV[nr/2], 
    1053                                                     tmp_reg|tmp_fan_div); 
    1054                         } 
    1055                 } while (0); 
     1060                                        DIV_FROM_REG(data->fan_div[nr])); 
     1061                results[1] = FAN_FROM_REG(data->fan[nr], 
     1062                                        DIV_FROM_REG(data->fan_div[nr])); 
     1063                if (!(data->has_fan & (1 << nr))) { 
     1064                        results[0] = 0; 
     1065                        results[1] = 0; 
     1066                } 
    10561067                *nrels_mag = 2; 
    10571068        } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     
    11841195{ 
    11851196        struct w83792d_data *data = client->data; 
    1186         int i=0, j=0; 
    1187         u8 temp_reg=0, k=1, fan_div_reg=0; 
    1188         u8 tmp_fan_div; 
     1197        int i = 0; 
    11891198 
    11901199        if (operation == SENSORS_PROC_REAL_INFO) 
     
    11961205                } 
    11971206                *nrels_mag = 7; 
    1198         } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    1199                 if (*nrels_mag < 7) { 
    1200                         return; 
    1201                 } 
    1202                 for (i=0; i<7; i++) { 
    1203                         temp_reg = SENSORS_LIMIT(results[i], 1, 128); 
    1204                         for (k=0,j=0; j<7; j++) { 
    1205                                 temp_reg = temp_reg>>1; 
    1206                                 if (temp_reg == 0) 
    1207                                         break; 
    1208                                 k++; 
    1209                         } 
    1210                         fan_div_reg = w83792d_read_value(client, 
    1211                                         W83792D_REG_FAN_DIV[i/2]); 
    1212                         fan_div_reg &= (i%2 == 0) ? 0xf8 : 0x8f; 
    1213                         tmp_fan_div = (i%2 == 0) ? (k&0x07) 
    1214                                         : ((k<<4)&0x70); 
    1215                         w83792d_write_value(client, 
    1216                                         W83792D_REG_FAN_DIV[i/2], 
    1217                                         fan_div_reg|tmp_fan_div); 
    1218                 } 
    12191207        } 
    12201208}