1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  AMD SFH Report Descriptor generator
4  *  Copyright 2020 Advanced Micro Devices, Inc.
5  *  Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
6  *	     Sandeep Singh <sandeep.singh@amd.com>
7  */
8 
9 #include <linux/kernel.h>
10 #include <linux/string.h>
11 #include <linux/slab.h>
12 #include "amd_sfh_pcie.h"
13 #include "amd_sfh_hid_desc.h"
14 #include "amd_sfh_hid_report_desc.h"
15 
16 #define	AMD_SFH_FW_MULTIPLIER (1000)
17 #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM	0x41
18 #define HID_USAGE_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
24 /* state enums */
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
28 
29 int get_report_descriptor(int sensor_idx, u8 *rep_desc)
30 {
31 	switch (sensor_idx) {
32 	case accel_idx: /* accel */
33 		memset(rep_desc, 0, sizeof(accel3_report_descriptor));
34 		memcpy(rep_desc, accel3_report_descriptor,
35 		       sizeof(accel3_report_descriptor));
36 		break;
37 	case gyro_idx: /* gyro */
38 		memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
39 		memcpy(rep_desc, gyro3_report_descriptor,
40 		       sizeof(gyro3_report_descriptor));
41 		break;
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));
46 		break;
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));
51 		break;
52 	default:
53 		break;
54 	}
55 	return 0;
56 }
57 
58 u32 get_descr_sz(int sensor_idx, int descriptor_name)
59 {
60 	switch (sensor_idx) {
61 	case accel_idx:
62 		switch (descriptor_name) {
63 		case descr_size:
64 			return sizeof(accel3_report_descriptor);
65 		case input_size:
66 			return sizeof(struct accel3_input_report);
67 		case feature_size:
68 			return sizeof(struct accel3_feature_report);
69 		}
70 		break;
71 	case gyro_idx:
72 		switch (descriptor_name) {
73 		case descr_size:
74 			return sizeof(gyro3_report_descriptor);
75 		case input_size:
76 			return sizeof(struct gyro_input_report);
77 		case feature_size:
78 			return sizeof(struct gyro_feature_report);
79 		}
80 		break;
81 	case mag_idx:
82 		switch (descriptor_name) {
83 		case descr_size:
84 			return sizeof(comp3_report_descriptor);
85 		case input_size:
86 			return sizeof(struct magno_input_report);
87 		case feature_size:
88 			return sizeof(struct magno_feature_report);
89 		}
90 		break;
91 	case als_idx:
92 		switch (descriptor_name) {
93 		case descr_size:
94 			return sizeof(als_report_descriptor);
95 		case input_size:
96 			return sizeof(struct als_input_report);
97 		case feature_size:
98 			return sizeof(struct als_feature_report);
99 		}
100 		break;
101 	default:
102 		break;
103 	}
104 	return 0;
105 }
106 
107 static void get_common_features(struct common_feature_property *common, int report_id)
108 {
109 	common->report_id = report_id;
110 	common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
111 	common->report_state = HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
112 	common->power_state = HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
113 	common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
114 	common->report_interval =  HID_DEFAULT_REPORT_INTERVAL;
115 }
116 
117 u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
118 {
119 	struct accel3_feature_report acc_feature;
120 	struct gyro_feature_report gyro_feature;
121 	struct magno_feature_report magno_feature;
122 	struct als_feature_report als_feature;
123 	u8 report_size = 0;
124 
125 	if (!feature_report)
126 		return report_size;
127 
128 	switch (sensor_idx) {
129 	case accel_idx: /* accel */
130 		get_common_features(&acc_feature.common_property, report_id);
131 		acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
132 		acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
133 		acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
134 		memcpy(feature_report, &acc_feature, sizeof(acc_feature));
135 		report_size = sizeof(acc_feature);
136 		break;
137 	case gyro_idx: /* gyro */
138 		get_common_features(&gyro_feature.common_property, report_id);
139 		gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
140 		gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
141 		gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
142 		memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
143 		report_size = sizeof(gyro_feature);
144 		break;
145 	case mag_idx: /* Magnetometer */
146 		get_common_features(&magno_feature.common_property, report_id);
147 		magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
148 		magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
149 		magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
150 		magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
151 		magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
152 		magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
153 		memcpy(feature_report, &magno_feature, sizeof(magno_feature));
154 		report_size = sizeof(magno_feature);
155 		break;
156 	case als_idx:  /* ambient light sensor */
157 		get_common_features(&als_feature.common_property, report_id);
158 		als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
159 		als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
160 		als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
161 		memcpy(feature_report, &als_feature, sizeof(als_feature));
162 		report_size = sizeof(als_feature);
163 		break;
164 	default:
165 		break;
166 	}
167 	return report_size;
168 }
169 
170 static void get_common_inputs(struct common_input_property *common, int report_id)
171 {
172 	common->report_id = report_id;
173 	common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
174 	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
175 }
176 
177 u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr)
178 {
179 	struct accel3_input_report acc_input;
180 	struct gyro_input_report gyro_input;
181 	struct magno_input_report magno_input;
182 	struct als_input_report als_input;
183 	u8 report_size = 0;
184 
185 	if (!sensor_virt_addr || !input_report)
186 		return report_size;
187 
188 	switch (sensor_idx) {
189 	case accel_idx: /* accel */
190 		get_common_inputs(&acc_input.common_property, report_id);
191 		acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
192 		acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
193 		acc_input.in_accel_z_value =  (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
194 		memcpy(input_report, &acc_input, sizeof(acc_input));
195 		report_size = sizeof(acc_input);
196 		break;
197 	case gyro_idx: /* gyro */
198 		get_common_inputs(&gyro_input.common_property, report_id);
199 		gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
200 		gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
201 		gyro_input.in_angel_z_value =  (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
202 		memcpy(input_report, &gyro_input, sizeof(gyro_input));
203 		report_size = sizeof(gyro_input);
204 		break;
205 	case mag_idx: /* Magnetometer */
206 		get_common_inputs(&magno_input.common_property, report_id);
207 		magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
208 		magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
209 		magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
210 		magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
211 		memcpy(input_report, &magno_input, sizeof(magno_input));
212 		report_size = sizeof(magno_input);
213 		break;
214 	case als_idx: /* Als */
215 		get_common_inputs(&als_input.common_property, report_id);
216 		als_input.illuminance_value =  (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
217 		report_size = sizeof(als_input);
218 		memcpy(input_report, &als_input, sizeof(als_input));
219 		break;
220 	default:
221 		break;
222 	}
223 	return report_size;
224 }
225