summaryrefslogtreecommitdiff
path: root/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
diff options
context:
space:
mode:
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.c63
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));