Path: blob/master/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
26285 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* AMD MP2 1.1 descriptor interfaces3*4* Copyright (c) 2022, Advanced Micro Devices, Inc.5* All Rights Reserved.6*7* Author: Basavaraj Natikar <[email protected]>8*/910#include <linux/hid-sensor-ids.h>1112#include "amd_sfh_interface.h"13#include "../hid_descriptor/amd_sfh_hid_desc.h"14#include "../hid_descriptor/amd_sfh_hid_report_desc.h"1516#define SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x4117#define SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x5118#define HID_DEFAULT_REPORT_INTERVAL 0x5019#define HID_DEFAULT_MIN_VALUE 0X7F20#define HID_DEFAULT_MAX_VALUE 0x8021#define HID_DEFAULT_SENSITIVITY 0x7F22#define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x0123/* state enums */24#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x0225#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x0526#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x042728static int get_report_desc(int sensor_idx, u8 *rep_desc)29{30switch (sensor_idx) {31case ACCEL_IDX: /* accelerometer */32memset(rep_desc, 0, sizeof(accel3_report_descriptor));33memcpy(rep_desc, accel3_report_descriptor,34sizeof(accel3_report_descriptor));35break;36case GYRO_IDX: /* gyroscope */37memset(rep_desc, 0, sizeof(gyro3_report_descriptor));38memcpy(rep_desc, gyro3_report_descriptor,39sizeof(gyro3_report_descriptor));40break;41case MAG_IDX: /* magnetometer */42memset(rep_desc, 0, sizeof(comp3_report_descriptor));43memcpy(rep_desc, comp3_report_descriptor,44sizeof(comp3_report_descriptor));45break;46case ALS_IDX: /* ambient light sensor */47memset(rep_desc, 0, sizeof(als_report_descriptor));48memcpy(rep_desc, als_report_descriptor,49sizeof(als_report_descriptor));50break;51case HPD_IDX: /* HPD sensor */52memset(rep_desc, 0, sizeof(hpd_report_descriptor));53memcpy(rep_desc, hpd_report_descriptor,54sizeof(hpd_report_descriptor));55break;56}57return 0;58}5960static void get_common_features(struct common_feature_property *common, int report_id)61{62common->report_id = report_id;63common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;64common->report_state = SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;65common->power_state = SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;66common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;67common->report_interval = HID_DEFAULT_REPORT_INTERVAL;68}6970static u8 get_feature_rep(int sensor_idx, int report_id, u8 *feature_report)71{72struct magno_feature_report magno_feature;73struct accel3_feature_report acc_feature;74struct gyro_feature_report gyro_feature;75struct hpd_feature_report hpd_feature;76struct als_feature_report als_feature;77u8 report_size = 0;7879if (!feature_report)80return report_size;8182switch (sensor_idx) {83case ACCEL_IDX: /* accelerometer */84get_common_features(&acc_feature.common_property, report_id);85acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;86acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;87acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;88memcpy(feature_report, &acc_feature, sizeof(acc_feature));89report_size = sizeof(acc_feature);90break;91case GYRO_IDX: /* gyroscope */92get_common_features(&gyro_feature.common_property, report_id);93gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;94gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;95gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;96memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));97report_size = sizeof(gyro_feature);98break;99case MAG_IDX: /* magnetometer */100get_common_features(&magno_feature.common_property, report_id);101magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;102magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;103magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;104magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;105magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;106magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;107memcpy(feature_report, &magno_feature, sizeof(magno_feature));108report_size = sizeof(magno_feature);109break;110case ALS_IDX: /* ambient light sensor */111get_common_features(&als_feature.common_property, report_id);112als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;113als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;114als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;115memcpy(feature_report, &als_feature, sizeof(als_feature));116report_size = sizeof(als_feature);117break;118case HPD_IDX: /* human presence detection sensor */119get_common_features(&hpd_feature.common_property, report_id);120memcpy(feature_report, &hpd_feature, sizeof(hpd_feature));121report_size = sizeof(hpd_feature);122break;123}124return report_size;125}126127static void get_common_inputs(struct common_input_property *common, int report_id)128{129common->report_id = report_id;130common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;131common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;132}133134int amd_sfh_float_to_int(u32 flt32_val)135{136int fraction, shift, mantissa, sign, exp, zeropre;137138mantissa = flt32_val & GENMASK(22, 0);139sign = (flt32_val & BIT(31)) ? -1 : 1;140exp = (flt32_val & ~BIT(31)) >> 23;141142if (!exp && !mantissa)143return 0;144145/*146* Calculate the exponent and fraction part of floating147* point representation.148*/149exp -= 127;150if (exp < 0) {151exp = -exp;152if (exp >= BITS_PER_TYPE(u32))153return 0;154zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp;155return zeropre >= 50 ? sign : 0;156}157158shift = 23 - exp;159if (abs(shift) >= BITS_PER_TYPE(u32))160return 0;161162if (shift < 0) {163shift = -shift;164flt32_val = BIT(exp) + (mantissa << shift);165shift = 0;166} else {167flt32_val = BIT(exp) + (mantissa >> shift);168}169170fraction = (shift == 0) ? 0 : mantissa & GENMASK(shift - 1, 0);171172return (((fraction * 100) >> shift) >= 50) ? sign * (flt32_val + 1) : sign * flt32_val;173}174175static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,176struct amd_input_data *in_data)177{178struct amd_mp2_dev *mp2 = container_of(in_data, struct amd_mp2_dev, in_data);179u8 *input_report = in_data->input_report[current_index];180struct magno_input_report magno_input;181struct accel3_input_report acc_input;182struct gyro_input_report gyro_input;183struct als_input_report als_input;184struct hpd_input_report hpd_input;185struct sfh_accel_data accel_data;186struct sfh_gyro_data gyro_data;187struct sfh_mag_data mag_data;188struct sfh_als_data als_data;189struct hpd_status hpdstatus;190struct sfh_base_info binfo;191void __iomem *sensoraddr;192u8 report_size = 0;193194if (!input_report)195return report_size;196197switch (sensor_idx) {198case ACCEL_IDX: /* accelerometer */199sensoraddr = mp2->vsbase + (ACCEL_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +200OFFSET_SENSOR_DATA_DEFAULT;201memcpy_fromio(&accel_data, sensoraddr, sizeof(struct sfh_accel_data));202get_common_inputs(&acc_input.common_property, report_id);203acc_input.in_accel_x_value = amd_sfh_float_to_int(accel_data.acceldata.x) / 100;204acc_input.in_accel_y_value = amd_sfh_float_to_int(accel_data.acceldata.y) / 100;205acc_input.in_accel_z_value = amd_sfh_float_to_int(accel_data.acceldata.z) / 100;206memcpy(input_report, &acc_input, sizeof(acc_input));207report_size = sizeof(acc_input);208break;209case GYRO_IDX: /* gyroscope */210sensoraddr = mp2->vsbase + (GYRO_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +211OFFSET_SENSOR_DATA_DEFAULT;212memcpy_fromio(&gyro_data, sensoraddr, sizeof(struct sfh_gyro_data));213get_common_inputs(&gyro_input.common_property, report_id);214gyro_input.in_angel_x_value = amd_sfh_float_to_int(gyro_data.gyrodata.x) / 1000;215gyro_input.in_angel_y_value = amd_sfh_float_to_int(gyro_data.gyrodata.y) / 1000;216gyro_input.in_angel_z_value = amd_sfh_float_to_int(gyro_data.gyrodata.z) / 1000;217memcpy(input_report, &gyro_input, sizeof(gyro_input));218report_size = sizeof(gyro_input);219break;220case MAG_IDX: /* magnetometer */221sensoraddr = mp2->vsbase + (MAG_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +222OFFSET_SENSOR_DATA_DEFAULT;223memcpy_fromio(&mag_data, sensoraddr, sizeof(struct sfh_mag_data));224get_common_inputs(&magno_input.common_property, report_id);225magno_input.in_magno_x = amd_sfh_float_to_int(mag_data.magdata.x) / 100;226magno_input.in_magno_y = amd_sfh_float_to_int(mag_data.magdata.y) / 100;227magno_input.in_magno_z = amd_sfh_float_to_int(mag_data.magdata.z) / 100;228magno_input.in_magno_accuracy = mag_data.accuracy / 100;229memcpy(input_report, &magno_input, sizeof(magno_input));230report_size = sizeof(magno_input);231break;232case ALS_IDX:233sensoraddr = mp2->vsbase + (ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +234OFFSET_SENSOR_DATA_DEFAULT;235memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));236get_common_inputs(&als_input.common_property, report_id);237als_input.illuminance_value = amd_sfh_float_to_int(als_data.lux);238239memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));240if (binfo.sbase.s_prop[ALS_IDX].sf.feat & 0x2) {241als_input.light_color_temp = als_data.light_color_temp;242als_input.chromaticity_x_value =243amd_sfh_float_to_int(als_data.chromaticity_x);244als_input.chromaticity_y_value =245amd_sfh_float_to_int(als_data.chromaticity_y);246}247248report_size = sizeof(als_input);249memcpy(input_report, &als_input, sizeof(als_input));250break;251case HPD_IDX:252get_common_inputs(&hpd_input.common_property, report_id);253hpdstatus.val = readl(mp2->mmio + amd_get_c2p_val(mp2, 4));254hpd_input.human_presence = hpdstatus.shpd.presence;255report_size = sizeof(hpd_input);256memcpy(input_report, &hpd_input, sizeof(hpd_input));257break;258}259return report_size;260}261262static u32 get_desc_size(int sensor_idx, int descriptor_name)263{264switch (sensor_idx) {265case ACCEL_IDX:266switch (descriptor_name) {267case descr_size:268return sizeof(accel3_report_descriptor);269case input_size:270return sizeof(struct accel3_input_report);271case feature_size:272return sizeof(struct accel3_feature_report);273}274break;275case GYRO_IDX:276switch (descriptor_name) {277case descr_size:278return sizeof(gyro3_report_descriptor);279case input_size:280return sizeof(struct gyro_input_report);281case feature_size:282return sizeof(struct gyro_feature_report);283}284break;285case MAG_IDX:286switch (descriptor_name) {287case descr_size:288return sizeof(comp3_report_descriptor);289case input_size:290return sizeof(struct magno_input_report);291case feature_size:292return sizeof(struct magno_feature_report);293}294break;295case ALS_IDX:296switch (descriptor_name) {297case descr_size:298return sizeof(als_report_descriptor);299case input_size:300return sizeof(struct als_input_report);301case feature_size:302return sizeof(struct als_feature_report);303}304break;305case HPD_IDX:306switch (descriptor_name) {307case descr_size:308return sizeof(hpd_report_descriptor);309case input_size:310return sizeof(struct hpd_input_report);311case feature_size:312return sizeof(struct hpd_feature_report);313}314break;315}316317return 0;318}319320void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops)321{322mp2_ops->get_rep_desc = get_report_desc;323mp2_ops->get_feat_rep = get_feature_rep;324mp2_ops->get_desc_sz = get_desc_size;325mp2_ops->get_in_rep = get_input_rep;326}327328329