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