diff options
Diffstat (limited to 'drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c')
| -rw-r--r-- | drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c index 6f0d332ccf51..c8916afefa62 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c @@ -132,29 +132,45 @@ static void get_common_inputs(struct common_input_property *common, int report_i common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM; } -static int float_to_int(u32 float32) +int amd_sfh_float_to_int(u32 flt32_val) { int fraction, shift, mantissa, sign, exp, zeropre; - mantissa = float32 & GENMASK(22, 0); - sign = (float32 & BIT(31)) ? -1 : 1; - exp = (float32 & ~BIT(31)) >> 23; + mantissa = flt32_val & GENMASK(22, 0); + sign = (flt32_val & BIT(31)) ? -1 : 1; + exp = (flt32_val & ~BIT(31)) >> 23; if (!exp && !mantissa) return 0; + /* + * Calculate the exponent and fraction part of floating + * point representation. + */ exp -= 127; if (exp < 0) { exp = -exp; + if (exp >= BITS_PER_TYPE(u32)) + return 0; zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp; return zeropre >= 50 ? sign : 0; } shift = 23 - exp; - float32 = BIT(exp) + (mantissa >> shift); - fraction = mantissa & GENMASK(shift - 1, 0); + if (abs(shift) >= BITS_PER_TYPE(u32)) + return 0; + + if (shift < 0) { + shift = -shift; + flt32_val = BIT(exp) + (mantissa << shift); + shift = 0; + } else { + flt32_val = BIT(exp) + (mantissa >> shift); + } + + fraction = (shift == 0) ? 0 : mantissa & GENMASK(shift - 1, 0); - return (((fraction * 100) >> shift) >= 50) ? sign * (float32 + 1) : sign * float32; + return (((fraction * 100) >> shift) >= 50) ? sign * (flt32_val + 1) : sign * flt32_val; } static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, @@ -172,6 +188,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, struct sfh_mag_data mag_data; struct sfh_als_data als_data; struct hpd_status hpdstatus; + struct sfh_base_info binfo; void __iomem *sensoraddr; u8 report_size = 0; @@ -184,9 +201,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, OFFSET_SENSOR_DATA_DEFAULT; memcpy_fromio(&accel_data, sensoraddr, sizeof(struct sfh_accel_data)); get_common_inputs(&acc_input.common_property, report_id); - acc_input.in_accel_x_value = float_to_int(accel_data.acceldata.x) / 100; - acc_input.in_accel_y_value = float_to_int(accel_data.acceldata.y) / 100; - acc_input.in_accel_z_value = float_to_int(accel_data.acceldata.z) / 100; + acc_input.in_accel_x_value = amd_sfh_float_to_int(accel_data.acceldata.x) / 100; + acc_input.in_accel_y_value = amd_sfh_float_to_int(accel_data.acceldata.y) / 100; + acc_input.in_accel_z_value = amd_sfh_float_to_int(accel_data.acceldata.z) / 100; memcpy(input_report, &acc_input, sizeof(acc_input)); report_size = sizeof(acc_input); break; @@ -195,9 +212,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, OFFSET_SENSOR_DATA_DEFAULT; memcpy_fromio(&gyro_data, sensoraddr, sizeof(struct sfh_gyro_data)); get_common_inputs(&gyro_input.common_property, report_id); - gyro_input.in_angel_x_value = float_to_int(gyro_data.gyrodata.x) / 1000; - gyro_input.in_angel_y_value = float_to_int(gyro_data.gyrodata.y) / 1000; - gyro_input.in_angel_z_value = float_to_int(gyro_data.gyrodata.z) / 1000; + gyro_input.in_angel_x_value = amd_sfh_float_to_int(gyro_data.gyrodata.x) / 1000; + gyro_input.in_angel_y_value = amd_sfh_float_to_int(gyro_data.gyrodata.y) / 1000; + gyro_input.in_angel_z_value = amd_sfh_float_to_int(gyro_data.gyrodata.z) / 1000; memcpy(input_report, &gyro_input, sizeof(gyro_input)); report_size = sizeof(gyro_input); break; @@ -206,9 +223,9 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, OFFSET_SENSOR_DATA_DEFAULT; memcpy_fromio(&mag_data, sensoraddr, sizeof(struct sfh_mag_data)); get_common_inputs(&magno_input.common_property, report_id); - magno_input.in_magno_x = float_to_int(mag_data.magdata.x) / 100; - magno_input.in_magno_y = float_to_int(mag_data.magdata.y) / 100; - magno_input.in_magno_z = float_to_int(mag_data.magdata.z) / 100; + magno_input.in_magno_x = amd_sfh_float_to_int(mag_data.magdata.x) / 100; + magno_input.in_magno_y = amd_sfh_float_to_int(mag_data.magdata.y) / 100; + magno_input.in_magno_z = amd_sfh_float_to_int(mag_data.magdata.z) / 100; magno_input.in_magno_accuracy = mag_data.accuracy / 100; memcpy(input_report, &magno_input, sizeof(magno_input)); report_size = sizeof(magno_input); @@ -218,13 +235,23 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, OFFSET_SENSOR_DATA_DEFAULT; memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data)); get_common_inputs(&als_input.common_property, report_id); - als_input.illuminance_value = float_to_int(als_data.lux); + als_input.illuminance_value = amd_sfh_float_to_int(als_data.lux); + + memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info)); + if (binfo.sbase.s_prop[ALS_IDX].sf.feat & 0x2) { + als_input.light_color_temp = als_data.light_color_temp; + als_input.chromaticity_x_value = + amd_sfh_float_to_int(als_data.chromaticity_x); + als_input.chromaticity_y_value = + amd_sfh_float_to_int(als_data.chromaticity_y); + } + report_size = sizeof(als_input); memcpy(input_report, &als_input, sizeof(als_input)); break; case HPD_IDX: get_common_inputs(&hpd_input.common_property, report_id); - hpdstatus.val = readl(mp2->mmio + AMD_C2P_MSG(4)); + hpdstatus.val = readl(mp2->mmio + amd_get_c2p_val(mp2, 4)); hpd_input.human_presence = hpdstatus.shpd.presence; report_size = sizeof(hpd_input); memcpy(input_report, &hpd_input, sizeof(hpd_input)); |
