1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  AMD SFH Report Descriptor generator
4  *  Copyright 2020-2021 Advanced Micro Devices, Inc.
5  *  Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
6  *	     Sandeep Singh <sandeep.singh@amd.com>
7  *	     Basavaraj Natikar <Basavaraj.Natikar@amd.com>
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include <linux/slab.h>
13 #include "amd_sfh_pcie.h"
14 #include "amd_sfh_hid_desc.h"
15 #include "amd_sfh_hid_report_desc.h"
16 #include "amd_sfh_hid.h"
17 
18 #define	AMD_SFH_FW_MULTIPLIER (1000)
19 #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM	0x41
20 #define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM	0x51
21 #define HID_DEFAULT_REPORT_INTERVAL				0x50
22 #define HID_DEFAULT_MIN_VALUE					0X7F
23 #define HID_DEFAULT_MAX_VALUE					0x80
24 #define HID_DEFAULT_SENSITIVITY					0x7F
25 #define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM  0x01
26 /* state enums */
27 #define HID_USAGE_SENSOR_STATE_READY_ENUM                             0x02
28 #define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM                      0x05
29 #define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM                      0x04
30 
31 int get_report_descriptor(int sensor_idx, u8 *rep_desc)
32 {
33 	switch (sensor_idx) {
34 	case accel_idx: /* accel */
35 		memset(rep_desc, 0, sizeof(accel3_report_descriptor));
36 		memcpy(rep_desc, accel3_report_descriptor,
37 		       sizeof(accel3_report_descriptor));
38 		break;
39 	case gyro_idx: /* gyro */
40 		memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
41 		memcpy(rep_desc, gyro3_report_descriptor,
42 		       sizeof(gyro3_report_descriptor));
43 		break;
44 	case mag_idx: /* Magnetometer */
45 		memset(rep_desc, 0, sizeof(comp3_report_descriptor));
46 		memcpy(rep_desc, comp3_report_descriptor,
47 		       sizeof(comp3_report_descriptor));
48 		break;
49 	case als_idx: /* ambient light sensor */
50 		memset(rep_desc, 0, sizeof(als_report_descriptor));
51 		memcpy(rep_desc, als_report_descriptor,
52 		       sizeof(als_report_descriptor));
53 		break;
54 	case HPD_IDX: /* HPD sensor */
55 		memset(rep_desc, 0, sizeof(hpd_report_descriptor));
56 		memcpy(rep_desc, hpd_report_descriptor,
57 		       sizeof(hpd_report_descriptor));
58 		break;
59 	default:
60 		break;
61 	}
62 	return 0;
63 }
64 
65 u32 get_descr_sz(int sensor_idx, int descriptor_name)
66 {
67 	switch (sensor_idx) {
68 	case accel_idx:
69 		switch (descriptor_name) {
70 		case descr_size:
71 			return sizeof(accel3_report_descriptor);
72 		case input_size:
73 			return sizeof(struct accel3_input_report);
74 		case feature_size:
75 			return sizeof(struct accel3_feature_report);
76 		}
77 		break;
78 	case gyro_idx:
79 		switch (descriptor_name) {
80 		case descr_size:
81 			return sizeof(gyro3_report_descriptor);
82 		case input_size:
83 			return sizeof(struct gyro_input_report);
84 		case feature_size:
85 			return sizeof(struct gyro_feature_report);
86 		}
87 		break;
88 	case mag_idx:
89 		switch (descriptor_name) {
90 		case descr_size:
91 			return sizeof(comp3_report_descriptor);
92 		case input_size:
93 			return sizeof(struct magno_input_report);
94 		case feature_size:
95 			return sizeof(struct magno_feature_report);
96 		}
97 		break;
98 	case als_idx:
99 		switch (descriptor_name) {
100 		case descr_size:
101 			return sizeof(als_report_descriptor);
102 		case input_size:
103 			return sizeof(struct als_input_report);
104 		case feature_size:
105 			return sizeof(struct als_feature_report);
106 		}
107 		break;
108 	case HPD_IDX:
109 		switch (descriptor_name) {
110 		case descr_size:
111 			return sizeof(hpd_report_descriptor);
112 		case input_size:
113 			return sizeof(struct hpd_input_report);
114 		case feature_size:
115 			return sizeof(struct hpd_feature_report);
116 		}
117 		break;
118 
119 	default:
120 		break;
121 	}
122 	return 0;
123 }
124 
125 static void get_common_features(struct common_feature_property *common, int report_id)
126 {
127 	common->report_id = report_id;
128 	common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
129 	common->report_state = HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
130 	common->power_state = HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
131 	common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
132 	common->report_interval =  HID_DEFAULT_REPORT_INTERVAL;
133 }
134 
135 u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
136 {
137 	struct accel3_feature_report acc_feature;
138 	struct gyro_feature_report gyro_feature;
139 	struct magno_feature_report magno_feature;
140 	struct hpd_feature_report hpd_feature;
141 	struct als_feature_report als_feature;
142 	u8 report_size = 0;
143 
144 	if (!feature_report)
145 		return report_size;
146 
147 	switch (sensor_idx) {
148 	case accel_idx: /* accel */
149 		get_common_features(&acc_feature.common_property, report_id);
150 		acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
151 		acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
152 		acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
153 		memcpy(feature_report, &acc_feature, sizeof(acc_feature));
154 		report_size = sizeof(acc_feature);
155 		break;
156 	case gyro_idx: /* gyro */
157 		get_common_features(&gyro_feature.common_property, report_id);
158 		gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
159 		gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
160 		gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
161 		memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
162 		report_size = sizeof(gyro_feature);
163 		break;
164 	case mag_idx: /* Magnetometer */
165 		get_common_features(&magno_feature.common_property, report_id);
166 		magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
167 		magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
168 		magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
169 		magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
170 		magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
171 		magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
172 		memcpy(feature_report, &magno_feature, sizeof(magno_feature));
173 		report_size = sizeof(magno_feature);
174 		break;
175 	case als_idx:  /* ambient light sensor */
176 		get_common_features(&als_feature.common_property, report_id);
177 		als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
178 		als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
179 		als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
180 		memcpy(feature_report, &als_feature, sizeof(als_feature));
181 		report_size = sizeof(als_feature);
182 		break;
183 	case HPD_IDX:  /* human presence detection sensor */
184 		get_common_features(&hpd_feature.common_property, report_id);
185 		memcpy(feature_report, &hpd_feature, sizeof(hpd_feature));
186 		report_size = sizeof(hpd_feature);
187 		break;
188 
189 	default:
190 		break;
191 	}
192 	return report_size;
193 }
194 
195 static void get_common_inputs(struct common_input_property *common, int report_id)
196 {
197 	common->report_id = report_id;
198 	common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
199 	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
200 }
201 
202 u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_input_data *in_data)
203 {
204 	struct amd_mp2_dev *privdata = container_of(in_data, struct amd_mp2_dev, in_data);
205 	u32 *sensor_virt_addr = in_data->sensor_virt_addr[current_index];
206 	u8 *input_report = in_data->input_report[current_index];
207 	u8 supported_input = privdata->mp2_acs & GENMASK(3, 0);
208 	struct magno_input_report magno_input;
209 	struct accel3_input_report acc_input;
210 	struct gyro_input_report gyro_input;
211 	struct hpd_input_report hpd_input;
212 	struct als_input_report als_input;
213 	struct hpd_status hpdstatus;
214 	u8 report_size = 0;
215 
216 	if (!sensor_virt_addr || !input_report)
217 		return report_size;
218 
219 	switch (sensor_idx) {
220 	case accel_idx: /* accel */
221 		get_common_inputs(&acc_input.common_property, report_id);
222 		acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
223 		acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
224 		acc_input.in_accel_z_value =  (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
225 		memcpy(input_report, &acc_input, sizeof(acc_input));
226 		report_size = sizeof(acc_input);
227 		break;
228 	case gyro_idx: /* gyro */
229 		get_common_inputs(&gyro_input.common_property, report_id);
230 		gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
231 		gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
232 		gyro_input.in_angel_z_value =  (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
233 		memcpy(input_report, &gyro_input, sizeof(gyro_input));
234 		report_size = sizeof(gyro_input);
235 		break;
236 	case mag_idx: /* Magnetometer */
237 		get_common_inputs(&magno_input.common_property, report_id);
238 		magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
239 		magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
240 		magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
241 		magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
242 		memcpy(input_report, &magno_input, sizeof(magno_input));
243 		report_size = sizeof(magno_input);
244 		break;
245 	case als_idx: /* Als */
246 		get_common_inputs(&als_input.common_property, report_id);
247 		/* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
248 		if (supported_input == V2_STATUS)
249 			als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5));
250 		else
251 			als_input.illuminance_value =
252 				(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
253 		report_size = sizeof(als_input);
254 		memcpy(input_report, &als_input, sizeof(als_input));
255 		break;
256 	case HPD_IDX: /* hpd */
257 		get_common_inputs(&hpd_input.common_property, report_id);
258 		hpdstatus.val = readl(privdata->mmio + AMD_C2P_MSG(4));
259 		hpd_input.human_presence = hpdstatus.shpd.human_presence_actual;
260 		report_size = sizeof(hpd_input);
261 		memcpy(input_report, &hpd_input, sizeof(hpd_input));
262 		break;
263 	default:
264 		break;
265 	}
266 	return report_size;
267 }
268