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