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
32static 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
67static 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
128static 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
138static 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
199static 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
206static 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
261		if (sensor_idx == ACS_IDX) {
262			als_input.light_color_temp = sensor_virt_addr[1];
263			als_input.chromaticity_x_value = sensor_virt_addr[2];
264			als_input.chromaticity_y_value = sensor_virt_addr[3];
265		}
266
267		report_size = sizeof(als_input);
268		memcpy(input_report, &als_input, sizeof(als_input));
269		break;
270	case HPD_IDX: /* hpd */
271		get_common_inputs(&hpd_input.common_property, report_id);
272		hpdstatus.val = readl(privdata->mmio + AMD_C2P_MSG(4));
273		hpd_input.human_presence = hpdstatus.shpd.human_presence_actual;
274		report_size = sizeof(hpd_input);
275		memcpy(input_report, &hpd_input, sizeof(hpd_input));
276		break;
277	default:
278		break;
279	}
280	return report_size;
281}
282
283void amd_sfh_set_desc_ops(struct amd_mp2_ops *mp2_ops)
284{
285	mp2_ops->get_rep_desc = get_report_descriptor;
286	mp2_ops->get_feat_rep = get_feature_report;
287	mp2_ops->get_in_rep = get_input_report;
288	mp2_ops->get_desc_sz = get_descr_sz;
289}
290