1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AMD MP2 1.1 descriptor interfaces
5 * Copyright (c) 2022, Advanced Micro Devices, Inc.
8 * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
11 #include <linux/hid-sensor-ids.h>
13 #include "amd_sfh_interface.h"
14 #include "../hid_descriptor/amd_sfh_hid_desc.h"
15 #include "../hid_descriptor/amd_sfh_hid_report_desc.h"
17 #define SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
18 #define SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x51
19 #define HID_DEFAULT_REPORT_INTERVAL 0x50
20 #define HID_DEFAULT_MIN_VALUE 0X7F
21 #define HID_DEFAULT_MAX_VALUE 0x80
22 #define HID_DEFAULT_SENSITIVITY 0x7F
23 #define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x01
25 #define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
26 #define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
27 #define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
29 static int get_report_desc(int sensor_idx
, u8
*rep_desc
)
32 case ACCEL_IDX
: /* accelerometer */
33 memset(rep_desc
, 0, sizeof(accel3_report_descriptor
));
34 memcpy(rep_desc
, accel3_report_descriptor
,
35 sizeof(accel3_report_descriptor
));
37 case GYRO_IDX
: /* gyroscope */
38 memset(rep_desc
, 0, sizeof(gyro3_report_descriptor
));
39 memcpy(rep_desc
, gyro3_report_descriptor
,
40 sizeof(gyro3_report_descriptor
));
42 case MAG_IDX
: /* magnetometer */
43 memset(rep_desc
, 0, sizeof(comp3_report_descriptor
));
44 memcpy(rep_desc
, comp3_report_descriptor
,
45 sizeof(comp3_report_descriptor
));
47 case ALS_IDX
: /* ambient light sensor */
48 memset(rep_desc
, 0, sizeof(als_report_descriptor
));
49 memcpy(rep_desc
, als_report_descriptor
,
50 sizeof(als_report_descriptor
));
52 case HPD_IDX
: /* HPD sensor */
53 memset(rep_desc
, 0, sizeof(hpd_report_descriptor
));
54 memcpy(rep_desc
, hpd_report_descriptor
,
55 sizeof(hpd_report_descriptor
));
61 static void get_common_features(struct common_feature_property
*common
, int report_id
)
63 common
->report_id
= report_id
;
64 common
->connection_type
= HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM
;
65 common
->report_state
= SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM
;
66 common
->power_state
= SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM
;
67 common
->sensor_state
= HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM
;
68 common
->report_interval
= HID_DEFAULT_REPORT_INTERVAL
;
71 static u8
get_feature_rep(int sensor_idx
, int report_id
, u8
*feature_report
)
73 struct magno_feature_report magno_feature
;
74 struct accel3_feature_report acc_feature
;
75 struct gyro_feature_report gyro_feature
;
76 struct hpd_feature_report hpd_feature
;
77 struct als_feature_report als_feature
;
84 case ACCEL_IDX
: /* accelerometer */
85 get_common_features(&acc_feature
.common_property
, report_id
);
86 acc_feature
.accel_change_sesnitivity
= HID_DEFAULT_SENSITIVITY
;
87 acc_feature
.accel_sensitivity_min
= HID_DEFAULT_MIN_VALUE
;
88 acc_feature
.accel_sensitivity_max
= HID_DEFAULT_MAX_VALUE
;
89 memcpy(feature_report
, &acc_feature
, sizeof(acc_feature
));
90 report_size
= sizeof(acc_feature
);
92 case GYRO_IDX
: /* gyroscope */
93 get_common_features(&gyro_feature
.common_property
, report_id
);
94 gyro_feature
.gyro_change_sesnitivity
= HID_DEFAULT_SENSITIVITY
;
95 gyro_feature
.gyro_sensitivity_min
= HID_DEFAULT_MIN_VALUE
;
96 gyro_feature
.gyro_sensitivity_max
= HID_DEFAULT_MAX_VALUE
;
97 memcpy(feature_report
, &gyro_feature
, sizeof(gyro_feature
));
98 report_size
= sizeof(gyro_feature
);
100 case MAG_IDX
: /* magnetometer */
101 get_common_features(&magno_feature
.common_property
, report_id
);
102 magno_feature
.magno_headingchange_sensitivity
= HID_DEFAULT_SENSITIVITY
;
103 magno_feature
.heading_min
= HID_DEFAULT_MIN_VALUE
;
104 magno_feature
.heading_max
= HID_DEFAULT_MAX_VALUE
;
105 magno_feature
.flux_change_sensitivity
= HID_DEFAULT_MIN_VALUE
;
106 magno_feature
.flux_min
= HID_DEFAULT_MIN_VALUE
;
107 magno_feature
.flux_max
= HID_DEFAULT_MAX_VALUE
;
108 memcpy(feature_report
, &magno_feature
, sizeof(magno_feature
));
109 report_size
= sizeof(magno_feature
);
111 case ALS_IDX
: /* ambient light sensor */
112 get_common_features(&als_feature
.common_property
, report_id
);
113 als_feature
.als_change_sesnitivity
= HID_DEFAULT_SENSITIVITY
;
114 als_feature
.als_sensitivity_min
= HID_DEFAULT_MIN_VALUE
;
115 als_feature
.als_sensitivity_max
= HID_DEFAULT_MAX_VALUE
;
116 memcpy(feature_report
, &als_feature
, sizeof(als_feature
));
117 report_size
= sizeof(als_feature
);
119 case HPD_IDX
: /* human presence detection sensor */
120 get_common_features(&hpd_feature
.common_property
, report_id
);
121 memcpy(feature_report
, &hpd_feature
, sizeof(hpd_feature
));
122 report_size
= sizeof(hpd_feature
);
128 static void get_common_inputs(struct common_input_property
*common
, int report_id
)
130 common
->report_id
= report_id
;
131 common
->sensor_state
= HID_USAGE_SENSOR_STATE_READY_ENUM
;
132 common
->event_type
= HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM
;
135 int amd_sfh_float_to_int(u32 flt32_val
)
137 int fraction
, shift
, mantissa
, sign
, exp
, zeropre
;
139 mantissa
= flt32_val
& GENMASK(22, 0);
140 sign
= (flt32_val
& BIT(31)) ? -1 : 1;
141 exp
= (flt32_val
& ~BIT(31)) >> 23;
143 if (!exp
&& !mantissa
)
147 * Calculate the exponent and fraction part of floating
148 * point representation.
153 if (exp
>= BITS_PER_TYPE(u32
))
155 zeropre
= (((BIT(23) + mantissa
) * 100) >> 23) >> exp
;
156 return zeropre
>= 50 ? sign
: 0;
160 if (abs(shift
) >= BITS_PER_TYPE(u32
))
165 flt32_val
= BIT(exp
) + (mantissa
<< shift
);
168 flt32_val
= BIT(exp
) + (mantissa
>> shift
);
171 fraction
= (shift
== 0) ? 0 : mantissa
& GENMASK(shift
- 1, 0);
173 return (((fraction
* 100) >> shift
) >= 50) ? sign
* (flt32_val
+ 1) : sign
* flt32_val
;
176 static u8
get_input_rep(u8 current_index
, int sensor_idx
, int report_id
,
177 struct amd_input_data
*in_data
)
179 struct amd_mp2_dev
*mp2
= container_of(in_data
, struct amd_mp2_dev
, in_data
);
180 u8
*input_report
= in_data
->input_report
[current_index
];
181 struct magno_input_report magno_input
;
182 struct accel3_input_report acc_input
;
183 struct gyro_input_report gyro_input
;
184 struct als_input_report als_input
;
185 struct hpd_input_report hpd_input
;
186 struct sfh_accel_data accel_data
;
187 struct sfh_gyro_data gyro_data
;
188 struct sfh_mag_data mag_data
;
189 struct sfh_als_data als_data
;
190 struct hpd_status hpdstatus
;
191 struct sfh_base_info binfo
;
192 void __iomem
*sensoraddr
;
198 switch (sensor_idx
) {
199 case ACCEL_IDX
: /* accelerometer */
200 sensoraddr
= mp2
->vsbase
+ (ACCEL_IDX
* SENSOR_DATA_MEM_SIZE_DEFAULT
) +
201 OFFSET_SENSOR_DATA_DEFAULT
;
202 memcpy_fromio(&accel_data
, sensoraddr
, sizeof(struct sfh_accel_data
));
203 get_common_inputs(&acc_input
.common_property
, report_id
);
204 acc_input
.in_accel_x_value
= amd_sfh_float_to_int(accel_data
.acceldata
.x
) / 100;
205 acc_input
.in_accel_y_value
= amd_sfh_float_to_int(accel_data
.acceldata
.y
) / 100;
206 acc_input
.in_accel_z_value
= amd_sfh_float_to_int(accel_data
.acceldata
.z
) / 100;
207 memcpy(input_report
, &acc_input
, sizeof(acc_input
));
208 report_size
= sizeof(acc_input
);
210 case GYRO_IDX
: /* gyroscope */
211 sensoraddr
= mp2
->vsbase
+ (GYRO_IDX
* SENSOR_DATA_MEM_SIZE_DEFAULT
) +
212 OFFSET_SENSOR_DATA_DEFAULT
;
213 memcpy_fromio(&gyro_data
, sensoraddr
, sizeof(struct sfh_gyro_data
));
214 get_common_inputs(&gyro_input
.common_property
, report_id
);
215 gyro_input
.in_angel_x_value
= amd_sfh_float_to_int(gyro_data
.gyrodata
.x
) / 1000;
216 gyro_input
.in_angel_y_value
= amd_sfh_float_to_int(gyro_data
.gyrodata
.y
) / 1000;
217 gyro_input
.in_angel_z_value
= amd_sfh_float_to_int(gyro_data
.gyrodata
.z
) / 1000;
218 memcpy(input_report
, &gyro_input
, sizeof(gyro_input
));
219 report_size
= sizeof(gyro_input
);
221 case MAG_IDX
: /* magnetometer */
222 sensoraddr
= mp2
->vsbase
+ (MAG_IDX
* SENSOR_DATA_MEM_SIZE_DEFAULT
) +
223 OFFSET_SENSOR_DATA_DEFAULT
;
224 memcpy_fromio(&mag_data
, sensoraddr
, sizeof(struct sfh_mag_data
));
225 get_common_inputs(&magno_input
.common_property
, report_id
);
226 magno_input
.in_magno_x
= amd_sfh_float_to_int(mag_data
.magdata
.x
) / 100;
227 magno_input
.in_magno_y
= amd_sfh_float_to_int(mag_data
.magdata
.y
) / 100;
228 magno_input
.in_magno_z
= amd_sfh_float_to_int(mag_data
.magdata
.z
) / 100;
229 magno_input
.in_magno_accuracy
= mag_data
.accuracy
/ 100;
230 memcpy(input_report
, &magno_input
, sizeof(magno_input
));
231 report_size
= sizeof(magno_input
);
234 sensoraddr
= mp2
->vsbase
+ (ALS_IDX
* SENSOR_DATA_MEM_SIZE_DEFAULT
) +
235 OFFSET_SENSOR_DATA_DEFAULT
;
236 memcpy_fromio(&als_data
, sensoraddr
, sizeof(struct sfh_als_data
));
237 get_common_inputs(&als_input
.common_property
, report_id
);
238 als_input
.illuminance_value
= amd_sfh_float_to_int(als_data
.lux
);
240 memcpy_fromio(&binfo
, mp2
->vsbase
, sizeof(struct sfh_base_info
));
241 if (binfo
.sbase
.s_prop
[ALS_IDX
].sf
.feat
& 0x2) {
242 als_input
.light_color_temp
= als_data
.light_color_temp
;
243 als_input
.chromaticity_x_value
=
244 amd_sfh_float_to_int(als_data
.chromaticity_x
);
245 als_input
.chromaticity_y_value
=
246 amd_sfh_float_to_int(als_data
.chromaticity_y
);
249 report_size
= sizeof(als_input
);
250 memcpy(input_report
, &als_input
, sizeof(als_input
));
253 get_common_inputs(&hpd_input
.common_property
, report_id
);
254 hpdstatus
.val
= readl(mp2
->mmio
+ amd_get_c2p_val(mp2
, 4));
255 hpd_input
.human_presence
= hpdstatus
.shpd
.presence
;
256 report_size
= sizeof(hpd_input
);
257 memcpy(input_report
, &hpd_input
, sizeof(hpd_input
));
263 static u32
get_desc_size(int sensor_idx
, int descriptor_name
)
265 switch (sensor_idx
) {
267 switch (descriptor_name
) {
269 return sizeof(accel3_report_descriptor
);
271 return sizeof(struct accel3_input_report
);
273 return sizeof(struct accel3_feature_report
);
277 switch (descriptor_name
) {
279 return sizeof(gyro3_report_descriptor
);
281 return sizeof(struct gyro_input_report
);
283 return sizeof(struct gyro_feature_report
);
287 switch (descriptor_name
) {
289 return sizeof(comp3_report_descriptor
);
291 return sizeof(struct magno_input_report
);
293 return sizeof(struct magno_feature_report
);
297 switch (descriptor_name
) {
299 return sizeof(als_report_descriptor
);
301 return sizeof(struct als_input_report
);
303 return sizeof(struct als_feature_report
);
307 switch (descriptor_name
) {
309 return sizeof(hpd_report_descriptor
);
311 return sizeof(struct hpd_input_report
);
313 return sizeof(struct hpd_feature_report
);
321 void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops
*mp2_ops
)
323 mp2_ops
->get_rep_desc
= get_report_desc
;
324 mp2_ops
->get_feat_rep
= get_feature_rep
;
325 mp2_ops
->get_desc_sz
= get_desc_size
;
326 mp2_ops
->get_in_rep
= get_input_rep
;