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