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