blob: 32a65ec0c39e7bf2a1d418e3736619265a23ec65 [file] [log] [blame]
/*
* Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "ssp.h"
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/iio/buffer.h>
#include <linux/iio/types.h>
/*************************************************************************/
/* SSP Kernel -> HAL input evnet function */
/*************************************************************************/
#define IIO_BUFFER_12_BYTES 20 /* 12 + timestamp 8*/
#define IIO_BUFFER_6_BYTES 14
#define IIO_BUFFER_1_BYTES 9
#define IIO_BUFFER_17_BYTES 25
#define IIO_BUFFER_23_BYTES 31
/* data header defines */
static int ssp_push_23bytes_buffer(struct iio_dev *indio_dev,
u64 t, int *q)
{
u8 buf[IIO_BUFFER_23_BYTES];
int i;
for (i = 0; i < 4; i++)
memcpy(buf + 4 * i, &q[i], sizeof(q[i]));
buf[16] = (u8)q[4];
for (i = 0; i < 3; i++)
memcpy(buf + 17 + i * 2, &q[i + 5], sizeof(s16));
memcpy(buf + 23, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffers(indio_dev, buf);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_17bytes_buffer(struct iio_dev *indio_dev,
u64 t, int *q)
{
u8 buf[IIO_BUFFER_17_BYTES];
int i;
for (i = 0; i < 4; i++)
memcpy(buf + 4 * i, &q[i], sizeof(q[i]));
buf[16] = (u8)q[5];
memcpy(buf + 17, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffers(indio_dev, buf);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_12bytes_buffer(struct iio_dev *indio_dev, u64 t,
int *q)
{
u8 buf[IIO_BUFFER_12_BYTES];
int i;
for (i = 0; i < 3; i++)
memcpy(buf + 4 * i, &q[i], sizeof(q[i]));
memcpy(buf + 12, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffers(indio_dev, buf);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_6bytes_buffer(struct iio_dev *indio_dev,
u64 t, s16 *d)
{
u8 buf[IIO_BUFFER_6_BYTES];
int i;
for (i = 0; i < 3; i++)
memcpy(buf + i * 2, &d[i], sizeof(d[i]));
memcpy(buf + 6, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffers(indio_dev, buf);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_1bytes_buffer(struct iio_dev *indio_dev,
u64 t, u8 *d)
{
u8 buf[IIO_BUFFER_1_BYTES];
memcpy(buf, d, sizeof(u8));
memcpy(buf + 1, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffers(indio_dev, buf);
mutex_unlock(&indio_dev->mlock);
return 0;
}
void report_meta_data(struct ssp_data *data, struct sensor_value *s)
{
if (s->meta_data.sensor == ACCELEROMETER_SENSOR) {
s16 accel_buf[3];
memset(accel_buf, 0xff, sizeof(s16) * 3);
ssp_push_6bytes_buffer(data->accel_indio_dev, 0, accel_buf);
} else if (s->meta_data.sensor == GAME_ROTATION_VECTOR) {
int grot_buf[5];
memset(grot_buf, 0xff, sizeof(int) * 5);
ssp_push_17bytes_buffer(data->game_rot_indio_dev, 0, grot_buf);
} else if (s->meta_data.sensor == STEP_DETECTOR) {
u8 step_buf[1] = {0xff};
ssp_push_1bytes_buffer(data->step_det_indio_dev, 0, step_buf);
} else {
input_report_rel(data->meta_input_dev, REL_DIAL, s->meta_data.what);
input_report_rel(data->meta_input_dev, REL_HWHEEL, s->meta_data.sensor + 1);
input_sync(data->meta_input_dev);
}
}
void report_acc_data(struct ssp_data *data, struct sensor_value *accdata)
{
s16 accel_buf[3];
data->buf[ACCELEROMETER_SENSOR].x = accdata->x;
data->buf[ACCELEROMETER_SENSOR].y = accdata->y;
data->buf[ACCELEROMETER_SENSOR].z = accdata->z;
accel_buf[0] = data->buf[ACCELEROMETER_SENSOR].x;
accel_buf[1] = data->buf[ACCELEROMETER_SENSOR].y;
accel_buf[2] = data->buf[ACCELEROMETER_SENSOR].z;
ssp_push_6bytes_buffer(data->accel_indio_dev, accdata->timestamp,
accel_buf);
}
void report_gyro_data(struct ssp_data *data, struct sensor_value *gyrodata)
{
int lTemp[3] = {0,};
data->buf[GYROSCOPE_SENSOR].x = gyrodata->x;
data->buf[GYROSCOPE_SENSOR].y = gyrodata->y;
data->buf[GYROSCOPE_SENSOR].z = gyrodata->z;
if (data->uGyroDps == GYROSCOPE_DPS500) {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z;
} else if (data->uGyroDps == GYROSCOPE_DPS250) {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x >> 1;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y >> 1;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z >> 1;
} else if (data->uGyroDps == GYROSCOPE_DPS2000) {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x << 2;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y << 2;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z << 2;
} else {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z;
}
ssp_push_12bytes_buffer(data->gyro_indio_dev, gyrodata->timestamp,
lTemp);
}
void report_geomagnetic_raw_data(struct ssp_data *data,
struct sensor_value *magrawdata)
{
data->buf[GEOMAGNETIC_RAW].x = magrawdata->x;
data->buf[GEOMAGNETIC_RAW].y = magrawdata->y;
data->buf[GEOMAGNETIC_RAW].z = magrawdata->z;
}
void report_mag_data(struct ssp_data *data, struct sensor_value *magdata)
{
int time_hi, time_lo;
time_lo = (int)(magdata->timestamp & 0x00000000FFFFFFFF);
time_hi = (int)((magdata->timestamp & 0xFFFFFFFF00000000) >> 32);
data->buf[GEOMAGNETIC_SENSOR].cal_x = magdata->cal_x;
data->buf[GEOMAGNETIC_SENSOR].cal_y = magdata->cal_y;
data->buf[GEOMAGNETIC_SENSOR].cal_z = magdata->cal_z;
data->buf[GEOMAGNETIC_SENSOR].accuracy = magdata->accuracy;
input_report_rel(data->mag_input_dev, REL_RX,
data->buf[GEOMAGNETIC_SENSOR].cal_x);
input_report_rel(data->mag_input_dev, REL_RY,
data->buf[GEOMAGNETIC_SENSOR].cal_y);
input_report_rel(data->mag_input_dev, REL_RZ,
data->buf[GEOMAGNETIC_SENSOR].cal_z);
input_report_rel(data->mag_input_dev, REL_HWHEEL,
data->buf[GEOMAGNETIC_SENSOR].accuracy + 1);
input_report_rel(data->mag_input_dev, REL_X, time_hi);
input_report_rel(data->mag_input_dev, REL_Y, time_lo);
input_sync(data->mag_input_dev);
}
void report_mag_uncaldata(struct ssp_data *data, struct sensor_value *magdata)
{
int time_hi, time_lo;
time_lo = (int)(magdata->timestamp & 0x00000000FFFFFFFF);
time_hi = (int)((magdata->timestamp & 0xFFFFFFFF00000000) >> 32);
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_x = magdata->uncal_x;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_y = magdata->uncal_y;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_z = magdata->uncal_z;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_x = magdata->offset_x;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_y = magdata->offset_y;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_z = magdata->offset_z;
input_report_rel(data->uncal_mag_input_dev, REL_RX,
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_x);
input_report_rel(data->uncal_mag_input_dev, REL_RY,
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_y);
input_report_rel(data->uncal_mag_input_dev, REL_RZ,
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_z);
input_report_rel(data->uncal_mag_input_dev, REL_HWHEEL,
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_x);
input_report_rel(data->uncal_mag_input_dev, REL_DIAL,
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_y);
input_report_rel(data->uncal_mag_input_dev, REL_WHEEL,
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_z);
input_report_rel(data->uncal_mag_input_dev, REL_X, time_hi);
input_report_rel(data->uncal_mag_input_dev, REL_Y, time_lo);
input_sync(data->uncal_mag_input_dev);
}
void report_uncalib_gyro_data(struct ssp_data *data,
struct sensor_value *gyrodata)
{
data->buf[GYRO_UNCALIB_SENSOR].uncal_x = gyrodata->uncal_x;
data->buf[GYRO_UNCALIB_SENSOR].uncal_y = gyrodata->uncal_y;
data->buf[GYRO_UNCALIB_SENSOR].uncal_z = gyrodata->uncal_z;
data->buf[GYRO_UNCALIB_SENSOR].offset_x = gyrodata->offset_x;
data->buf[GYRO_UNCALIB_SENSOR].offset_y = gyrodata->offset_y;
data->buf[GYRO_UNCALIB_SENSOR].offset_z = gyrodata->offset_z;
input_report_rel(data->uncalib_gyro_input_dev, REL_RX,
data->buf[GYRO_UNCALIB_SENSOR].uncal_x);
input_report_rel(data->uncalib_gyro_input_dev, REL_RY,
data->buf[GYRO_UNCALIB_SENSOR].uncal_y);
input_report_rel(data->uncalib_gyro_input_dev, REL_RZ,
data->buf[GYRO_UNCALIB_SENSOR].uncal_z);
input_report_rel(data->uncalib_gyro_input_dev, REL_HWHEEL,
data->buf[GYRO_UNCALIB_SENSOR].offset_x);
input_report_rel(data->uncalib_gyro_input_dev, REL_DIAL,
data->buf[GYRO_UNCALIB_SENSOR].offset_y);
input_report_rel(data->uncalib_gyro_input_dev, REL_WHEEL,
data->buf[GYRO_UNCALIB_SENSOR].offset_z);
input_sync(data->uncalib_gyro_input_dev);
}
void report_sig_motion_data(struct ssp_data *data,
struct sensor_value *sig_motion_data)
{
data->buf[SIG_MOTION_SENSOR].sig_motion = sig_motion_data->sig_motion;
input_report_rel(data->sig_motion_input_dev, REL_MISC,
data->buf[SIG_MOTION_SENSOR].sig_motion);
input_sync(data->sig_motion_input_dev);
}
void report_rot_data(struct ssp_data *data, struct sensor_value *rotdata)
{
int rot_buf[8];
data->buf[ROTATION_VECTOR].quat_a = rotdata->quat_a;
data->buf[ROTATION_VECTOR].quat_b = rotdata->quat_b;
data->buf[ROTATION_VECTOR].quat_c = rotdata->quat_c;
data->buf[ROTATION_VECTOR].quat_d = rotdata->quat_d;
data->buf[ROTATION_VECTOR].acc_x = rotdata->acc_x;
data->buf[ROTATION_VECTOR].acc_y = rotdata->acc_y;
data->buf[ROTATION_VECTOR].acc_z = rotdata->acc_z;
data->buf[ROTATION_VECTOR].acc_rot = rotdata->acc_rot;
rot_buf[0] = rotdata->quat_a;
rot_buf[1] = rotdata->quat_b;
rot_buf[2] = rotdata->quat_c;
rot_buf[3] = rotdata->quat_d;
rot_buf[4] = rotdata->acc_rot;
rot_buf[5] = rotdata->acc_x;
rot_buf[6] = rotdata->acc_y;
rot_buf[7] = rotdata->acc_z;
ssp_push_23bytes_buffer(data->rot_indio_dev, rotdata->timestamp,
rot_buf);
}
void report_game_rot_data(struct ssp_data *data,
struct sensor_value *grvec_data)
{
int grot_buf[5];
data->buf[GAME_ROTATION_VECTOR].quat_grv_a = grvec_data->quat_grv_a;
data->buf[GAME_ROTATION_VECTOR].quat_grv_b = grvec_data->quat_grv_b;
data->buf[GAME_ROTATION_VECTOR].quat_grv_c = grvec_data->quat_grv_c;
data->buf[GAME_ROTATION_VECTOR].quat_grv_d = grvec_data->quat_grv_d;
data->buf[GAME_ROTATION_VECTOR].acc_grv_rot = grvec_data->acc_grv_rot;
grot_buf[0] = grvec_data->quat_grv_a;
grot_buf[1] = grvec_data->quat_grv_b;
grot_buf[2] = grvec_data->quat_grv_c;
grot_buf[3] = grvec_data->quat_grv_d;
grot_buf[4] = grvec_data->acc_grv_rot;
ssp_push_17bytes_buffer(data->game_rot_indio_dev, grvec_data->timestamp,
grot_buf);
}
void report_step_det_data(struct ssp_data *data,
struct sensor_value *stepdet_data)
{
data->buf[STEP_DETECTOR].step_det = stepdet_data->step_det;
ssp_push_1bytes_buffer(data->step_det_indio_dev,
stepdet_data->timestamp, &stepdet_data->step_det);
}
void report_step_cnt_data(struct ssp_data *data,
struct sensor_value *sig_motion_data)
{
data->buf[STEP_COUNTER].step_diff = sig_motion_data->step_diff;
data->step_count_total += data->buf[STEP_COUNTER].step_diff;
input_report_rel(data->step_cnt_input_dev, REL_MISC,
data->step_count_total + 1);
input_sync(data->step_cnt_input_dev);
}
#ifdef CONFIG_SENSORS_SSP_ADPD142
void report_hrm_lib_data(struct ssp_data *data, struct sensor_value *hrmdata)
{
data->buf[BIO_HRM_LIB].hr = hrmdata->hr;
data->buf[BIO_HRM_LIB].rri = hrmdata->rri;
data->buf[BIO_HRM_LIB].snr = hrmdata->snr;
data->buf[BIO_HRM_LIB].flag = hrmdata->flag;
input_report_rel(data->hrm_lib_input_dev, REL_X,
data->buf[BIO_HRM_LIB].hr + 1);
input_report_rel(data->hrm_lib_input_dev, REL_Y,
data->buf[BIO_HRM_LIB].rri + 1);
input_report_rel(data->hrm_lib_input_dev, REL_Z,
data->buf[BIO_HRM_LIB].snr + 1);
input_report_rel(data->hrm_lib_input_dev, REL_MISC,
data->buf[BIO_HRM_LIB].flag >= 0 ?
(data->buf[BIO_HRM_LIB].flag + 1) :
data->buf[BIO_HRM_LIB].flag);
input_sync(data->hrm_lib_input_dev);
}
#endif
void report_tilt_wake_data(struct ssp_data *data, struct sensor_value *tiltdata)
{
data->buf[TILT_TO_WAKE].x = tiltdata->x;
data->buf[TILT_TO_WAKE].y = tiltdata->y;
data->buf[TILT_TO_WAKE].z = tiltdata->z;
input_report_rel(data->tilt_wake_input_dev, REL_X,
data->buf[TILT_TO_WAKE].x >= 0 ?
(data->buf[TILT_TO_WAKE].x + 1) :
data->buf[TILT_TO_WAKE].x);
input_report_rel(data->tilt_wake_input_dev, REL_Y,
data->buf[TILT_TO_WAKE].y >= 0 ?
(data->buf[TILT_TO_WAKE].y + 1) :
data->buf[TILT_TO_WAKE].y);
input_report_rel(data->tilt_wake_input_dev, REL_Z,
data->buf[TILT_TO_WAKE].z >= 0 ?
(data->buf[TILT_TO_WAKE].z + 1) :
data->buf[TILT_TO_WAKE].z);
input_sync(data->tilt_wake_input_dev);
wake_lock_timeout(&data->ssp_wake_lock, 3 * HZ);
}
int initialize_event_symlink(struct ssp_data *data)
{
int iRet = 0;
iRet = sensors_create_symlink(data->mag_input_dev);
if (iRet < 0)
goto iRet_mag_sysfs_create_link;
iRet = sensors_create_symlink(data->uncal_mag_input_dev);
if (iRet < 0)
goto iRet_uncal_mag_sysfs_create_link;
iRet = sensors_create_symlink(data->sig_motion_input_dev);
if (iRet < 0)
goto iRet_sig_motion_sysfs_create_link;
iRet = sensors_create_symlink(data->uncalib_gyro_input_dev);
if (iRet < 0)
goto iRet_uncal_gyro_sysfs_create_link;
iRet = sensors_create_symlink(data->step_cnt_input_dev);
if (iRet < 0)
goto iRet_step_cnt_sysfs_create_link;
iRet = sensors_create_symlink(data->meta_input_dev);
if (iRet < 0)
goto iRet_meta_sysfs_create_link;
#ifdef CONFIG_SENSORS_SSP_ADPD142
iRet = sensors_create_symlink(data->hrm_lib_input_dev);
if (iRet < 0)
goto iRet_hrm_lib_sysfs_create_link;
#endif
iRet = sensors_create_symlink(data->tilt_wake_input_dev);
if (iRet < 0)
goto iRet_tilt_wake_sysfs_create_link;
return SUCCESS;
iRet_tilt_wake_sysfs_create_link:
#ifdef CONFIG_SENSORS_SSP_ADPD142
sensors_remove_symlink(data->hrm_lib_input_dev);
iRet_hrm_lib_sysfs_create_link:
#endif
sensors_remove_symlink(data->meta_input_dev);
iRet_meta_sysfs_create_link:
sensors_remove_symlink(data->step_cnt_input_dev);
iRet_step_cnt_sysfs_create_link:
sensors_remove_symlink(data->uncalib_gyro_input_dev);
iRet_uncal_gyro_sysfs_create_link:
sensors_remove_symlink(data->sig_motion_input_dev);
iRet_sig_motion_sysfs_create_link:
sensors_remove_symlink(data->uncal_mag_input_dev);
iRet_uncal_mag_sysfs_create_link:
sensors_remove_symlink(data->mag_input_dev);
iRet_mag_sysfs_create_link:
pr_err("[SSP]: %s - could not create event symlink\n", __func__);
return FAIL;
}
void remove_event_symlink(struct ssp_data *data)
{
sensors_remove_symlink(data->mag_input_dev);
sensors_remove_symlink(data->uncal_mag_input_dev);
sensors_remove_symlink(data->sig_motion_input_dev);
sensors_remove_symlink(data->uncalib_gyro_input_dev);
sensors_remove_symlink(data->step_cnt_input_dev);
sensors_remove_symlink(data->meta_input_dev);
#ifdef CONFIG_SENSORS_SSP_ADPD142
sensors_remove_symlink(data->hrm_lib_input_dev);
#endif
sensors_remove_symlink(data->tilt_wake_input_dev);
}
static const struct iio_info accel_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec accel_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_6_BYTES*8,
IIO_BUFFER_6_BYTES*8, 0)
}
};
static const struct iio_info gyro_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec gyro_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_12_BYTES*8,
IIO_BUFFER_12_BYTES*8, 0)
}
};
static const struct iio_info game_rot_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec game_rot_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_17_BYTES*8,
IIO_BUFFER_17_BYTES*8, 0)
}
};
static const struct iio_info rot_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec rot_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_23_BYTES*8,
IIO_BUFFER_23_BYTES*8, 0)
}
};
static const struct iio_info step_det_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec step_det_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_1_BYTES*8,
IIO_BUFFER_1_BYTES*8, 0)
}
};
static const struct iio_info pressure_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec pressure_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_12_BYTES * 8,
IIO_BUFFER_12_BYTES * 8, 0)
}
};
int initialize_input_dev(struct ssp_data *data)
{
int iRet = 0;
/* Registering iio device - start */
data->accel_indio_dev = iio_device_alloc(0);
if (!data->accel_indio_dev)
goto err_alloc_accel;
data->accel_indio_dev->name = "accelerometer_sensor";
data->accel_indio_dev->dev.parent = &data->spi->dev;
data->accel_indio_dev->info = &accel_info;
data->accel_indio_dev->channels = accel_channels;
data->accel_indio_dev->num_channels = ARRAY_SIZE(accel_channels);
data->accel_indio_dev->modes = INDIO_DIRECT_MODE;
data->accel_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->accel_indio_dev);
if (iRet)
goto err_config_ring_accel;
iRet = iio_buffer_register(data->accel_indio_dev,
data->accel_indio_dev->channels,
data->accel_indio_dev->num_channels);
if (iRet)
goto err_register_buffer_accel;
iRet = iio_device_register(data->accel_indio_dev);
if (iRet)
goto err_register_device_accel;
data->gyro_indio_dev = iio_device_alloc(0);
if (!data->gyro_indio_dev)
goto err_alloc_gyro;
data->gyro_indio_dev->name = "gyro_sensor";
data->gyro_indio_dev->dev.parent = &data->spi->dev;
data->gyro_indio_dev->info = &gyro_info;
data->gyro_indio_dev->channels = gyro_channels;
data->gyro_indio_dev->num_channels = ARRAY_SIZE(gyro_channels);
data->gyro_indio_dev->modes = INDIO_DIRECT_MODE;
data->gyro_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->gyro_indio_dev);
if (iRet)
goto err_config_ring_gyro;
iRet = iio_buffer_register(data->gyro_indio_dev,
data->gyro_indio_dev->channels,
data->gyro_indio_dev->num_channels);
if (iRet)
goto err_register_buffer_gyro;
iRet = iio_device_register(data->gyro_indio_dev);
if (iRet)
goto err_register_device_gyro;
data->game_rot_indio_dev = iio_device_alloc(0);
if (!data->game_rot_indio_dev)
goto err_alloc_game_rot;
data->game_rot_indio_dev->name = "game_rotation_vector";
data->game_rot_indio_dev->dev.parent = &data->spi->dev;
data->game_rot_indio_dev->info = &game_rot_info;
data->game_rot_indio_dev->channels = game_rot_channels;
data->game_rot_indio_dev->num_channels = ARRAY_SIZE(game_rot_channels);
data->game_rot_indio_dev->modes = INDIO_DIRECT_MODE;
data->game_rot_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->game_rot_indio_dev);
if (iRet)
goto err_config_ring_game_rot;
iRet = iio_buffer_register(data->game_rot_indio_dev,
data->game_rot_indio_dev->channels,
data->game_rot_indio_dev->num_channels);
if (iRet)
goto err_register_buffer_game_rot;
iRet = iio_device_register(data->game_rot_indio_dev);
if (iRet)
goto err_register_device_game_rot;
data->rot_indio_dev = iio_device_alloc(0);
if (!data->rot_indio_dev)
goto err_alloc_rot;
data->rot_indio_dev->name = "rotation_vector_sensor";
data->rot_indio_dev->dev.parent = &data->spi->dev;
data->rot_indio_dev->info = &rot_info;
data->rot_indio_dev->channels = rot_channels;
data->rot_indio_dev->num_channels = ARRAY_SIZE(rot_channels);
data->rot_indio_dev->modes = INDIO_DIRECT_MODE;
data->rot_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->rot_indio_dev);
if (iRet)
goto err_config_ring_rot;
iRet = iio_buffer_register(data->rot_indio_dev,
data->rot_indio_dev->channels,
data->rot_indio_dev->num_channels);
if (iRet)
goto err_register_buffer_rot;
iRet = iio_device_register(data->rot_indio_dev);
if (iRet)
goto err_register_device_rot;
data->step_det_indio_dev = iio_device_alloc(0);
if (!data->step_det_indio_dev)
goto err_alloc_step_det;
data->step_det_indio_dev->name = "step_det_sensor";
data->step_det_indio_dev->dev.parent = &data->spi->dev;
data->step_det_indio_dev->info = &step_det_info;
data->step_det_indio_dev->channels = step_det_channels;
data->step_det_indio_dev->num_channels = ARRAY_SIZE(step_det_channels);
data->step_det_indio_dev->modes = INDIO_DIRECT_MODE;
data->step_det_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->step_det_indio_dev);
if (iRet)
goto err_config_ring_step_det;
iRet = iio_buffer_register(data->step_det_indio_dev,
data->step_det_indio_dev->channels,
data->step_det_indio_dev->num_channels);
if (iRet)
goto err_register_buffer_step_det;
iRet = iio_device_register(data->step_det_indio_dev);
if (iRet)
goto err_register_device_step_det;
data->mag_input_dev = input_allocate_device();
if (data->mag_input_dev == NULL)
goto err_initialize_mag_input_dev;
data->mag_input_dev->name = "geomagnetic_sensor";
input_set_capability(data->mag_input_dev, EV_REL, REL_RX);
input_set_capability(data->mag_input_dev, EV_REL, REL_RY);
input_set_capability(data->mag_input_dev, EV_REL, REL_RZ);
input_set_capability(data->mag_input_dev, EV_REL, REL_X); /* time_hi */
input_set_capability(data->mag_input_dev, EV_REL, REL_Y); /* time_lo */
input_set_capability(data->mag_input_dev, EV_REL, REL_HWHEEL);
iRet = input_register_device(data->mag_input_dev);
if (iRet < 0) {
input_free_device(data->mag_input_dev);
goto err_initialize_mag_input_dev;
}
input_set_drvdata(data->mag_input_dev, data);
data->uncal_mag_input_dev = input_allocate_device();
if (data->uncal_mag_input_dev == NULL)
goto err_initialize_uncal_mag_input_dev;
data->uncal_mag_input_dev->name = "uncal_geomagnetic_sensor";
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_RX);
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_RY);
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_RZ);
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_HWHEEL);
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_DIAL);
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_WHEEL);
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_X); /* time_hi */
input_set_capability(data->uncal_mag_input_dev, EV_REL, REL_Y); /* time_lo */
iRet = input_register_device(data->uncal_mag_input_dev);
if (iRet < 0) {
input_free_device(data->uncal_mag_input_dev);
goto err_initialize_uncal_mag_input_dev;
}
input_set_drvdata(data->uncal_mag_input_dev, data);
data->sig_motion_input_dev = input_allocate_device();
if (data->sig_motion_input_dev == NULL)
goto err_initialize_sig_motion_input_dev;
data->sig_motion_input_dev->name = "sig_motion_sensor";
input_set_capability(data->sig_motion_input_dev, EV_REL, REL_MISC);
iRet = input_register_device(data->sig_motion_input_dev);
if (iRet < 0) {
input_free_device(data->sig_motion_input_dev);
goto err_initialize_sig_motion_input_dev;
}
input_set_drvdata(data->sig_motion_input_dev, data);
data->uncalib_gyro_input_dev = input_allocate_device();
if (data->uncalib_gyro_input_dev == NULL)
goto err_initialize_uncal_gyro_input_dev;
data->uncalib_gyro_input_dev->name = "uncal_gyro_sensor";
input_set_capability(data->uncalib_gyro_input_dev, EV_REL, REL_RX);
input_set_capability(data->uncalib_gyro_input_dev, EV_REL, REL_RY);
input_set_capability(data->uncalib_gyro_input_dev, EV_REL, REL_RZ);
input_set_capability(data->uncalib_gyro_input_dev, EV_REL, REL_HWHEEL);
input_set_capability(data->uncalib_gyro_input_dev, EV_REL, REL_DIAL);
input_set_capability(data->uncalib_gyro_input_dev, EV_REL, REL_WHEEL);
iRet = input_register_device(data->uncalib_gyro_input_dev);
if (iRet < 0) {
input_free_device(data->uncalib_gyro_input_dev);
goto err_initialize_uncal_gyro_input_dev;
}
input_set_drvdata(data->uncalib_gyro_input_dev, data);
data->step_cnt_input_dev = input_allocate_device();
if (data->step_cnt_input_dev == NULL)
goto err_initialize_step_cnt_input_dev;
data->step_cnt_input_dev->name = "step_cnt_sensor";
input_set_capability(data->step_cnt_input_dev, EV_REL, REL_MISC);
iRet = input_register_device(data->step_cnt_input_dev);
if (iRet < 0) {
input_free_device(data->step_cnt_input_dev);
goto err_initialize_step_cnt_input_dev;
}
input_set_drvdata(data->step_cnt_input_dev, data);
data->meta_input_dev = input_allocate_device();
if (data->meta_input_dev == NULL)
goto err_initialize_meta_input_dev;
data->meta_input_dev->name = "meta_event";
input_set_capability(data->meta_input_dev, EV_REL, REL_HWHEEL);
input_set_capability(data->meta_input_dev, EV_REL, REL_DIAL);
iRet = input_register_device(data->meta_input_dev);
if (iRet < 0) {
input_free_device(data->meta_input_dev);
goto err_initialize_meta_input_dev;
}
input_set_drvdata(data->meta_input_dev, data);
#ifdef CONFIG_SENSORS_SSP_ADPD142
data->hrm_lib_input_dev = input_allocate_device();
if (data->hrm_lib_input_dev == NULL)
goto err_initialize_hrm_lib_input_dev;
data->hrm_lib_input_dev->name = "hrm_lib_sensor";
input_set_capability(data->hrm_lib_input_dev, EV_REL, REL_X);
input_set_capability(data->hrm_lib_input_dev, EV_REL, REL_Y);
input_set_capability(data->hrm_lib_input_dev, EV_REL, REL_Z);
input_set_capability(data->hrm_lib_input_dev, EV_REL, REL_MISC);
iRet = input_register_device(data->hrm_lib_input_dev);
if (iRet < 0) {
input_free_device(data->hrm_lib_input_dev);
goto err_initialize_hrm_lib_input_dev;
}
input_set_drvdata(data->hrm_lib_input_dev, data);
#endif
data->tilt_wake_input_dev = input_allocate_device();
if (data->tilt_wake_input_dev == NULL)
goto err_initialize_tilt_wake_input_dev;
data->tilt_wake_input_dev->name = "tilt_wake_sensor";
input_set_capability(data->tilt_wake_input_dev, EV_REL, REL_X);
input_set_capability(data->tilt_wake_input_dev, EV_REL, REL_Y);
input_set_capability(data->tilt_wake_input_dev, EV_REL, REL_Z);
iRet = input_register_device(data->tilt_wake_input_dev);
if (iRet < 0) {
input_free_device(data->tilt_wake_input_dev);
goto err_initialize_tilt_wake_input_dev;
}
input_set_drvdata(data->tilt_wake_input_dev, data);
return SUCCESS;
err_initialize_tilt_wake_input_dev:
pr_err("[SSP]: %s - could not allocate tilt wake input device\n",
__func__);
#ifdef CONFIG_SENSORS_SSP_ADPD142
input_unregister_device(data->hrm_lib_input_dev);
err_initialize_hrm_lib_input_dev:
pr_err("[SSP]: %s - could not allocate hrm lib input device\n",
__func__);
#endif
input_unregister_device(data->meta_input_dev);
err_initialize_meta_input_dev:
pr_err("[SSP]: %s - could not allocate meta event input device\n",
__func__);
input_unregister_device(data->step_cnt_input_dev);
err_initialize_step_cnt_input_dev:
pr_err("[SSP]: %s - could not allocate step cnt input device\n",
__func__);
input_unregister_device(data->uncalib_gyro_input_dev);
err_initialize_uncal_gyro_input_dev:
pr_err("[SSP]: %s - could not allocate uncal gyro input device\n",
__func__);
input_unregister_device(data->sig_motion_input_dev);
err_initialize_sig_motion_input_dev:
pr_err("[SSP]: %s - could not allocate sig motion input device\n",
__func__);
input_unregister_device(data->uncal_mag_input_dev);
err_initialize_uncal_mag_input_dev:
pr_err("[SSP]: %s - could not allocate uncal mag input device\n",
__func__);
input_unregister_device(data->mag_input_dev);
err_initialize_mag_input_dev:
pr_err("[SSP]: failed to allocate memory for iio pressure_sensor device\n");
iio_device_unregister(data->step_det_indio_dev);
err_register_device_step_det:
pr_err("[SSP]: failed to register step_det device\n");
iio_buffer_unregister(data->step_det_indio_dev);
err_register_buffer_step_det:
pr_err("[SSP]: failed to register step_det buffer\n");
ssp_iio_unconfigure_ring(data->step_det_indio_dev);
err_config_ring_step_det:
pr_err("[SSP]: failed to configure step_det ring buffer\n");
iio_device_free(data->step_det_indio_dev);
err_alloc_step_det:
pr_err("[SSP]: failed to allocate memory for iio step_det device\n");
iio_device_unregister(data->rot_indio_dev);
err_register_device_rot:
pr_err("[SSP]: failed to register rot device\n");
iio_buffer_unregister(data->rot_indio_dev);
err_register_buffer_rot:
pr_err("[SSP]: failed to register rot buffer\n");
ssp_iio_unconfigure_ring(data->rot_indio_dev);
err_config_ring_rot:
pr_err("[SSP]: failed to configure rot ring buffer\n");
iio_device_free(data->rot_indio_dev);
err_alloc_rot:
pr_err("[SSP]: failed to allocate memory for iio rot device\n");
iio_device_unregister(data->game_rot_indio_dev);
err_register_device_game_rot:
pr_err("[SSP]: failed to register game_rot device\n");
iio_buffer_unregister(data->game_rot_indio_dev);
err_register_buffer_game_rot:
pr_err("[SSP]: failed to register game_rot buffer\n");
ssp_iio_unconfigure_ring(data->game_rot_indio_dev);
err_config_ring_game_rot:
pr_err("[SSP]: failed to configure game_rot ring buffer\n");
iio_device_free(data->game_rot_indio_dev);
err_alloc_game_rot:
pr_err("[SSP]: failed to allocate memory for iio game_rot device\n");
iio_device_unregister(data->gyro_indio_dev);
err_register_device_gyro:
pr_err("[SSP]: failed to register gyro device\n");
iio_buffer_unregister(data->gyro_indio_dev);
err_register_buffer_gyro:
pr_err("[SSP]: failed to register gyro buffer\n");
ssp_iio_unconfigure_ring(data->gyro_indio_dev);
err_config_ring_gyro:
pr_err("[SSP]: failed to configure gyro ring buffer\n");
iio_device_free(data->gyro_indio_dev);
err_alloc_gyro:
pr_err("[SSP]: failed to allocate memory for iio gyro device\n");
iio_device_unregister(data->accel_indio_dev);
err_register_device_accel:
pr_err("[SSP]: failed to register accel device\n");
iio_buffer_unregister(data->accel_indio_dev);
err_register_buffer_accel:
pr_err("[SSP]: failed to register accel buffer\n");
ssp_iio_unconfigure_ring(data->accel_indio_dev);
err_config_ring_accel:
pr_err("[SSP]: failed to configure accel ring buffer\n");
iio_device_free(data->accel_indio_dev);
err_alloc_accel:
pr_err("[SSP]: failed to allocate memory for iio accel device\n");
return ERROR;
}
void remove_input_dev(struct ssp_data *data)
{
input_unregister_device(data->mag_input_dev);
input_unregister_device(data->uncal_mag_input_dev);
input_unregister_device(data->sig_motion_input_dev);
input_unregister_device(data->uncalib_gyro_input_dev);
input_unregister_device(data->step_cnt_input_dev);
input_unregister_device(data->meta_input_dev);
#ifdef CONFIG_SENSORS_SSP_ADPD142
input_unregister_device(data->hrm_lib_input_dev);
#endif
input_unregister_device(data->tilt_wake_input_dev);
}