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