Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e3a8b44 authored by Karol Wrona's avatar Karol Wrona Committed by Jonathan Cameron
Browse files

iio: common: ssp_sensors: Add sensorhub iio commons



This patch adds common library for sensorhub iio drivers.

Signed-off-by: default avatarKarol Wrona <k.wrona@samsung.com>
Acked-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent f04df4eb
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -3,6 +3,16 @@
#
menu "SSP Sensor Common"

config IIO_SSP_SENSORS_COMMONS
	tristate "Commons for all SSP Sensor IIO drivers"
	depends on IIO_SSP_SENSORHUB
	select IIO_BUFFER
	select IIO_KFIFO_BUF
	help
	  Say yes here to build commons for SSP sensors.
	  To compile this as a module, choose M here: the module
	  will be called ssp_iio.

config IIO_SSP_SENSORHUB
	tristate "Samsung Sensorhub driver"
	depends on SPI
+2 −0
Original line number Diff line number Diff line
@@ -4,3 +4,5 @@

sensorhub-objs				:= ssp_dev.o ssp_spi.o
obj-$(CONFIG_IIO_SSP_SENSORHUB)		+= sensorhub.o

obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) 	+= ssp_iio.o
+107 −0
Original line number Diff line number Diff line
/*
 *  Copyright (C) 2014, 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 <linux/iio/common/ssp_sensors.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/module.h>
#include <linux/slab.h>
#include "ssp_iio_sensor.h"

/**
 * ssp_common_buffer_postenable() - generic postenable callback for ssp buffer
 *
 * @indio_dev:		iio device
 *
 * Returns 0 or negative value in case of error
 */
int ssp_common_buffer_postenable(struct iio_dev *indio_dev)
{
	struct ssp_sensor_data *spd = iio_priv(indio_dev);
	struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);

	/* the allocation is made in post because scan size is known in this
	 * moment
	 * */
	spd->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL | GFP_DMA);
	if (!spd->buffer)
		return -ENOMEM;

	return ssp_enable_sensor(data, spd->type,
				 ssp_get_sensor_delay(data, spd->type));
}
EXPORT_SYMBOL(ssp_common_buffer_postenable);

/**
 * ssp_common_buffer_postdisable() - generic postdisable callback for ssp buffer
 *
 * @indio_dev:		iio device
 *
 * Returns 0 or negative value in case of error
 */
int ssp_common_buffer_postdisable(struct iio_dev *indio_dev)
{
	int ret;
	struct ssp_sensor_data *spd = iio_priv(indio_dev);
	struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);

	ret = ssp_disable_sensor(data, spd->type);
	if (ret < 0)
		return ret;

	kfree(spd->buffer);

	return ret;
}
EXPORT_SYMBOL(ssp_common_buffer_postdisable);

/**
 * ssp_common_process_data() - Common process data callback for ssp sensors
 *
 * @indio_dev:		iio device
 * @buf:		source buffer
 * @len:		sensor data length
 * @timestamp:		system timestamp
 *
 * Returns 0 or negative value in case of error
 */
int ssp_common_process_data(struct iio_dev *indio_dev, void *buf,
			    unsigned int len, int64_t timestamp)
{
	__le32 time;
	int64_t calculated_time;
	struct ssp_sensor_data *spd = iio_priv(indio_dev);

	if (indio_dev->scan_bytes == 0)
		return 0;

	/*
	 * it always sends full set of samples, remember about available masks
	 */
	memcpy(spd->buffer, buf, len);

	if (indio_dev->scan_timestamp) {
		memcpy(&time, &((char *)buf)[len], SSP_TIME_SIZE);
		calculated_time =
			timestamp + (int64_t)le32_to_cpu(time) * 1000000;
	}

	return iio_push_to_buffers_with_timestamp(indio_dev, spd->buffer,
						  calculated_time);
}
EXPORT_SYMBOL(ssp_common_process_data);

MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
MODULE_DESCRIPTION("Samsung sensorhub commons");
MODULE_LICENSE("GPL");
+70 −0
Original line number Diff line number Diff line
#ifndef __SSP_IIO_SENSOR_H__
#define __SSP_IIO_SENSOR_H__

#define SSP_CHANNEL_AG(_type, _mod, _index) \
{ \
		.type = _type,\
		.modified = 1,\
		.channel2 = _mod,\
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
		.scan_index = _index,\
		.scan_type = {\
			.sign = 's',\
			.realbits = 16,\
			.storagebits = 16,\
			.shift = 0,\
			.endianness = IIO_LE,\
		},\
}

/* It is defined here as it is a mixed timestamp */
#define SSP_CHAN_TIMESTAMP(_si) {					\
	.type = IIO_TIMESTAMP,						\
	.channel = -1,							\
	.scan_index = _si,						\
	.scan_type = {							\
		.sign = 's',						\
		.realbits = 64,						\
		.storagebits = 64,					\
		},							\
}

#define SSP_MS_PER_S			1000
#define SSP_INVERTED_SCALING_FACTOR	1000000ULL

#define SSP_FACTOR_WITH_MS \
	(SSP_INVERTED_SCALING_FACTOR * SSP_MS_PER_S)

int ssp_common_buffer_postenable(struct iio_dev *indio_dev);

int ssp_common_buffer_postdisable(struct iio_dev *indio_dev);

int ssp_common_process_data(struct iio_dev *indio_dev, void *buf,
			    unsigned int len, int64_t timestamp);

/* Converts time in ms to frequency */
static inline void ssp_convert_to_freq(u32 time, int *integer_part,
				       int *fractional)
{
	if (time == 0) {
		*fractional = 0;
		*integer_part = 0;
		return;
	}

	*integer_part = SSP_FACTOR_WITH_MS / time;
	*fractional = do_div(*integer_part, SSP_INVERTED_SCALING_FACTOR);
}

/* Converts frequency to time in ms */
static inline int ssp_convert_to_time(int integer_part, int fractional)
{
	u64 value;

	value = integer_part * SSP_INVERTED_SCALING_FACTOR + fractional;
	if (value == 0)
		return 0;

	return div_u64(SSP_FACTOR_WITH_MS, value);
}
#endif /* __SSP_IIO_SENSOR_H__ */