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