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 static 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 static 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 static 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 static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
204 			   struct amd_input_data *in_data)
205 {
206 	struct amd_mp2_dev *privdata = container_of(in_data, struct amd_mp2_dev, in_data);
207 	u32 *sensor_virt_addr = in_data->sensor_virt_addr[current_index];
208 	u8 *input_report = in_data->input_report[current_index];
209 	u8 supported_input = privdata->mp2_acs & GENMASK(3, 0);
210 	struct magno_input_report magno_input;
211 	struct accel3_input_report acc_input;
212 	struct gyro_input_report gyro_input;
213 	struct hpd_input_report hpd_input;
214 	struct als_input_report als_input;
215 	struct hpd_status hpdstatus;
216 	u8 report_size = 0;
217 
218 	if (!sensor_virt_addr || !input_report)
219 		return report_size;
220 
221 	switch (sensor_idx) {
222 	case accel_idx: /* accel */
223 		get_common_inputs(&acc_input.common_property, report_id);
224 		acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
225 		acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
226 		acc_input.in_accel_z_value =  (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
227 		memcpy(input_report, &acc_input, sizeof(acc_input));
228 		report_size = sizeof(acc_input);
229 		break;
230 	case gyro_idx: /* gyro */
231 		get_common_inputs(&gyro_input.common_property, report_id);
232 		gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
233 		gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
234 		gyro_input.in_angel_z_value =  (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
235 		memcpy(input_report, &gyro_input, sizeof(gyro_input));
236 		report_size = sizeof(gyro_input);
237 		break;
238 	case mag_idx: /* Magnetometer */
239 		get_common_inputs(&magno_input.common_property, report_id);
240 		magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
241 		magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
242 		magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
243 		magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
244 		memcpy(input_report, &magno_input, sizeof(magno_input));
245 		report_size = sizeof(magno_input);
246 		break;
247 	case als_idx: /* Als */
248 		get_common_inputs(&als_input.common_property, report_id);
249 		/* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
250 		if (supported_input == V2_STATUS)
251 			als_input.illuminance_value =
252 				readl(privdata->mmio + AMD_C2P_MSG(5)) & ILLUMINANCE_MASK;
253 		else
254 			als_input.illuminance_value =
255 				(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
256 		report_size = sizeof(als_input);
257 		memcpy(input_report, &als_input, sizeof(als_input));
258 		break;
259 	case HPD_IDX: /* hpd */
260 		get_common_inputs(&hpd_input.common_property, report_id);
261 		hpdstatus.val = readl(privdata->mmio + AMD_C2P_MSG(4));
262 		hpd_input.human_presence = hpdstatus.shpd.human_presence_actual;
263 		report_size = sizeof(hpd_input);
264 		memcpy(input_report, &hpd_input, sizeof(hpd_input));
265 		break;
266 	default:
267 		break;
268 	}
269 	return report_size;
270 }
271 
amd_sfh_set_desc_ops(struct amd_mp2_ops * mp2_ops)272 void amd_sfh_set_desc_ops(struct amd_mp2_ops *mp2_ops)
273 {
274 	mp2_ops->get_rep_desc = get_report_descriptor;
275 	mp2_ops->get_feat_rep = get_feature_report;
276 	mp2_ops->get_in_rep = get_input_report;
277 	mp2_ops->get_desc_sz = get_descr_sz;
278 }
279