audio: dsp: Import elliptic
From branch: redwood-s-oss Change-Id: I797a2a9e9bbde8f9bf750b7429977747c31bd8a6
This commit is contained in:
parent
257a07db14
commit
17ca3415dc
458
techpack/audio/dsp/apr_elliptic.c
Executable file
458
techpack/audio/dsp/apr_elliptic.c
Executable file
@ -0,0 +1,458 @@
|
||||
/**
|
||||
* Elliptic Labs
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <sound/asound.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/control.h>
|
||||
#include "../asoc/msm-pcm-routing-v2.h"
|
||||
#include <dsp/q6audio-v2.h>
|
||||
#include <dsp/q6common.h>
|
||||
#include <dsp/apr_audio-v2.h>
|
||||
#include <dsp/apr_elliptic.h>
|
||||
#include <elliptic/elliptic_mixer_controls.h>
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
enum {
|
||||
HALL_SLIDER_UP = 4,
|
||||
HALL_SLIDER_DOWN = 5,
|
||||
HALL_SLIDING = 6,
|
||||
};
|
||||
|
||||
enum driver_sensor_type {
|
||||
DRIVER_SENSOR_HALL = 35,
|
||||
};
|
||||
|
||||
struct driver_sensor_event {
|
||||
enum driver_sensor_type type;
|
||||
union {
|
||||
int32_t event;
|
||||
int32_t reserved[2];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int afe_set_parameter(int port,
|
||||
int param_id,
|
||||
int module_id,
|
||||
struct afe_ultrasound_set_params_t *prot_config,
|
||||
uint32_t length)
|
||||
{
|
||||
struct afe_port_cmd_set_param_v2 *set_param_v2 = NULL;
|
||||
uint32_t set_param_v2_size = sizeof(struct afe_port_cmd_set_param_v2);
|
||||
struct afe_port_cmd_set_param_v3 *set_param_v3 = NULL;
|
||||
uint32_t set_param_v3_size = sizeof(struct afe_port_cmd_set_param_v3);
|
||||
struct param_hdr_v3 param_hdr = {0};
|
||||
u16 port_id = 0;
|
||||
int index = 0;
|
||||
u8 *packed_param_data = NULL;
|
||||
int packed_data_size = sizeof(union param_hdrs) + length;
|
||||
int ret = 0;
|
||||
|
||||
pr_debug("[ELUS]: inside %s\n", __func__);
|
||||
|
||||
port_id = q6audio_get_port_id(port);
|
||||
ret = q6audio_validate_port(port_id);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Not a valid port id = 0x%x ret %d\n", __func__,
|
||||
port_id, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
index = q6audio_get_port_index(port);
|
||||
|
||||
param_hdr.module_id = module_id;
|
||||
param_hdr.instance_id = INSTANCE_ID_0;
|
||||
param_hdr.param_id = param_id;
|
||||
param_hdr.param_size = length;
|
||||
pr_debug("[ELUS]: param_size %d\n", length);
|
||||
|
||||
packed_param_data = kzalloc(packed_data_size, GFP_KERNEL);
|
||||
if (packed_param_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = q6common_pack_pp_params(packed_param_data, ¶m_hdr, (u8 *)prot_config,
|
||||
&packed_data_size);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to pack param header and data, error %d\n",
|
||||
__func__, ret);
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
if (q6common_is_instance_id_supported()) {
|
||||
set_param_v3_size += packed_data_size;
|
||||
set_param_v3 = kzalloc(set_param_v3_size, GFP_KERNEL);
|
||||
if (set_param_v3 == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
set_param_v3->apr_hdr.hdr_field =
|
||||
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
|
||||
APR_PKT_VER);
|
||||
set_param_v3->apr_hdr.pkt_size = sizeof(struct afe_port_cmd_set_param_v3) +
|
||||
packed_data_size;
|
||||
set_param_v3->apr_hdr.src_port = 0;
|
||||
set_param_v3->apr_hdr.dest_port = 0;
|
||||
set_param_v3->apr_hdr.token = index;
|
||||
set_param_v3->apr_hdr.opcode = AFE_PORT_CMD_SET_PARAM_V3;
|
||||
set_param_v3->port_id = port_id;
|
||||
set_param_v3->payload_size = packed_data_size;
|
||||
memcpy(&set_param_v3->param_data, packed_param_data,
|
||||
packed_data_size);
|
||||
|
||||
mutex_lock(elus_afe.ptr_afe_apr_lock);
|
||||
atomic_set(elus_afe.ptr_state, 1);
|
||||
atomic_set(elus_afe.ptr_status, 0);
|
||||
ret = apr_send_pkt(*elus_afe.ptr_apr, (uint32_t *) set_param_v3);
|
||||
} else {
|
||||
set_param_v2_size += packed_data_size;
|
||||
set_param_v2 = kzalloc(set_param_v2_size, GFP_KERNEL);
|
||||
if (set_param_v2 == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
set_param_v2->apr_hdr.hdr_field =
|
||||
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
|
||||
APR_PKT_VER);
|
||||
set_param_v2->apr_hdr.pkt_size = sizeof(struct afe_port_cmd_set_param_v2) +
|
||||
packed_data_size;
|
||||
set_param_v2->apr_hdr.src_port = 0;
|
||||
set_param_v2->apr_hdr.dest_port = 0;
|
||||
set_param_v2->apr_hdr.token = index;
|
||||
set_param_v2->apr_hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
|
||||
set_param_v2->port_id = port_id;
|
||||
set_param_v2->payload_size = packed_data_size;
|
||||
memcpy(&set_param_v2->param_data, packed_param_data,
|
||||
packed_data_size);
|
||||
|
||||
mutex_lock(elus_afe.ptr_afe_apr_lock);
|
||||
atomic_set(elus_afe.ptr_state, 1);
|
||||
atomic_set(elus_afe.ptr_status, 0);
|
||||
ret = apr_send_pkt(*elus_afe.ptr_apr, (uint32_t *) set_param_v2);
|
||||
}
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Setting param for port %d param[0x%x]failed\n",
|
||||
__func__, port, param_id);
|
||||
goto fail_cmd_lock;
|
||||
}
|
||||
ret = wait_event_timeout(elus_afe.ptr_wait[index],
|
||||
(atomic_read(elus_afe.ptr_state) == 0),
|
||||
msecs_to_jiffies(elus_afe.timeout_ms));
|
||||
if (!ret) {
|
||||
pr_err("%s: wait_event timeout\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto fail_cmd_lock;
|
||||
}
|
||||
if (atomic_read(elus_afe.ptr_status) != 0) {
|
||||
pr_err("%s: set param cmd failed\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto fail_cmd_lock;
|
||||
}
|
||||
ret = 0;
|
||||
fail_cmd_lock:
|
||||
mutex_unlock(elus_afe.ptr_afe_apr_lock);
|
||||
fail_cmd:
|
||||
pr_debug("%s param_id %x status %d\n", __func__, param_id, ret);
|
||||
kfree(set_param_v2);
|
||||
kfree(set_param_v3);
|
||||
kfree(packed_param_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t ultrasound_apr_set_parameter(int32_t port_id, uint32_t param_id,
|
||||
u8 *user_params, int32_t length) {
|
||||
|
||||
int32_t ret = 0;
|
||||
uint32_t module_id = 0;
|
||||
|
||||
if (port_id == ELLIPTIC_PORT_ID)
|
||||
module_id = ELLIPTIC_ULTRASOUND_MODULE_TX;
|
||||
else
|
||||
module_id = ELLIPTIC_ULTRASOUND_MODULE_RX;
|
||||
|
||||
ret = afe_set_parameter(port_id,
|
||||
param_id, module_id,
|
||||
(struct afe_ultrasound_set_params_t *)user_params,
|
||||
length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_version_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_VERSION_INFO_SIZE) {
|
||||
pr_debug("[ELUS]: elliptic_version copied to local AP cache");
|
||||
data_block =
|
||||
elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_VERSION_INFO);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_VERSION_INFO_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_branch_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_BRANCH_INFO_SIZE) {
|
||||
pr_debug("[ELUS]: elliptic_branch copied to local AP cache");
|
||||
data_block =
|
||||
elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_BRANCH_INFO);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_BRANCH_INFO_MAX_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_tag_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_TAG_INFO_SIZE) {
|
||||
pr_debug("[ELUS]: elliptic_tag copied to local AP cache");
|
||||
data_block =
|
||||
elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_TAG_INFO);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_TAG_INFO_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_calibration_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_CALIBRATION_DATA_SIZE) {
|
||||
pr_debug("[ELUS]: calibration_data copied to local AP cache");
|
||||
|
||||
data_block = elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_CALIBRATION_DATA);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_CALIBRATION_DATA_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
elliptic_set_calibration_data((u8 *)&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_calibration_v2_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_CALIBRATION_V2_DATA_SIZE) {
|
||||
pr_debug("[ELUS]: calibration_data copied to local AP cache");
|
||||
|
||||
data_block = elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_CALIBRATION_V2_DATA);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_CALIBRATION_V2_DATA_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
elliptic_set_calibration_data((u8 *)&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_ml_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_ML_DATA_SIZE) {
|
||||
pr_debug("[ELUS]: ml_data copied to local AP cache");
|
||||
|
||||
data_block = elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_ML_DATA);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_ML_DATA_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_diagnostics_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
struct elliptic_shared_data_block *data_block = NULL;
|
||||
size_t copy_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
pr_err("[ELUS]: %s() size:%d\n", __func__, payload_size);
|
||||
|
||||
if (payload_size >= ELLIPTIC_DIAGNOSTICS_DATA_SIZE) {
|
||||
pr_debug("[ELUS]: diagnostics_data copied to local AP cache");
|
||||
|
||||
data_block = elliptic_get_shared_obj(
|
||||
ELLIPTIC_OBJ_ID_DIAGNOSTICS_DATA);
|
||||
copy_size = min_t(size_t, data_block->size,
|
||||
(size_t)ELLIPTIC_DIAGNOSTICS_DATA_SIZE);
|
||||
|
||||
memcpy((u8 *)data_block->buffer,
|
||||
&payload[3], copy_size);
|
||||
ret = (int32_t)copy_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t process_sensorhub_msg(uint32_t *payload, uint32_t payload_size)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
pr_err("[ELUS]: %s, paramId:%u, size:%d\n",
|
||||
__func__, payload[1], payload_size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t elliptic_process_apr_payload(uint32_t *payload)
|
||||
{
|
||||
uint32_t payload_size = 0;
|
||||
int32_t ret = -1;
|
||||
|
||||
if (payload[0] == ELLIPTIC_ULTRASOUND_MODULE_TX) {
|
||||
/* payload format
|
||||
* payload[0] = Module ID
|
||||
* payload[1] = Param ID
|
||||
* payload[2] = LSB - payload size
|
||||
* MSB - reserved(TBD)
|
||||
* payload[3] = US data payload starts from here
|
||||
*/
|
||||
payload_size = payload[2] & 0xFFFF;
|
||||
|
||||
switch (payload[1]) {
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_ENGINE_VERSION:
|
||||
ret = process_version_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_BUILD_BRANCH:
|
||||
ret = process_branch_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_TAG:
|
||||
ret = process_tag_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_CALIBRATION_DATA:
|
||||
ret = process_calibration_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_CALIBRATION_V2_DATA:
|
||||
ret = process_calibration_v2_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_ML_DATA:
|
||||
ret = process_ml_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_DIAGNOSTICS_DATA:
|
||||
ret = process_diagnostics_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_SENSORHUB:
|
||||
ret = process_sensorhub_msg(payload, payload_size);
|
||||
break;
|
||||
case ELLIPTIC_ULTRASOUND_PARAM_ID_ENGINE_DATA:
|
||||
ret = elliptic_data_push(
|
||||
ELLIPTIC_ALL_DEVICES,
|
||||
(const char *)&payload[3],
|
||||
(size_t)payload_size,
|
||||
ELLIPTIC_DATA_PUSH_FROM_KERNEL);
|
||||
|
||||
if (ret != 0) {
|
||||
pr_err("[ELUS] : failed to push apr payload to elliptic device");
|
||||
return ret;
|
||||
}
|
||||
ret = payload_size;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
pr_err("[ELUS] : elliptic_process_apr_payload, Illegal paramId:%u", payload[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
pr_debug("[ELUS]: Invalid Ultrasound Module ID %d\n",
|
||||
payload[0]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int elliptic_set_hall_state(int state)
|
||||
{
|
||||
struct driver_sensor_event dse;
|
||||
int ret = -1;
|
||||
|
||||
dse.type = DRIVER_SENSOR_HALL;
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
dse.event = HALL_SLIDER_UP;
|
||||
break;
|
||||
case 1:
|
||||
dse.event = HALL_SLIDER_DOWN;
|
||||
break;
|
||||
case 2:
|
||||
dse.event = HALL_SLIDING;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s Invalid HALL state:%d\n", __func__, state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = afe_set_parameter(ELLIPTIC_PORT_ID,
|
||||
2, ELLIPTIC_ULTRASOUND_MODULE_TX,
|
||||
(struct afe_ultrasound_set_params_t *)&dse,
|
||||
sizeof(dse));
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(elliptic_set_hall_state);
|
28
techpack/audio/dsp/elliptic/Makefile
Executable file
28
techpack/audio/dsp/elliptic/Makefile
Executable file
@ -0,0 +1,28 @@
|
||||
ccflags-y := -I$(src) -Wall -Werror
|
||||
IO_MODULE := msm
|
||||
|
||||
# EXTRA_CFLAGS += -DDEBUG
|
||||
|
||||
# Need to add include paths:
|
||||
LINUXINCLUDE += \
|
||||
-I$(srctree)techpack/audio/include/dsp
|
||||
-I$(srctree)techpack/audio/include/uapi
|
||||
-I$(srctree)techpack/aduio/include
|
||||
|
||||
obj-y += elliptic.o
|
||||
obj-y += elliptic_mixer_controls.o
|
||||
obj-y += io_modules/$(IO_MODULE)/elliptic_data_$(IO_MODULE)_io.o
|
||||
obj-y += io_modules/userspace/elliptic_data_userspace_io.o
|
||||
obj-y += io_modules/userspace/elliptic_data_userspace_ctrl.o
|
||||
obj-y += elliptic_sysfs.o
|
||||
|
||||
# elliptic_driver-y := elliptic.o
|
||||
# elliptic_driver-y += io_modules/$(IO_MODULE)/elliptic_data_io.o
|
||||
# elliptic_driver-y += mixer_controls/$(MIXER_MODULE)/elliptic_mixer_controls.o
|
||||
# elliptic_driver-y += elliptic_sysfs.o
|
||||
|
||||
# .PHONY: clean
|
||||
# all:
|
||||
# make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
|
||||
# clean:
|
||||
# rm *.o *.ko
|
808
techpack/audio/dsp/elliptic/elliptic.c
Executable file
808
techpack/audio/dsp/elliptic/elliptic.c
Executable file
@ -0,0 +1,808 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs
|
||||
*
|
||||
*/
|
||||
/* #define DEBUG */
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
/* includes the file structure, that is, file open read close */
|
||||
#include <linux/fs.h>
|
||||
|
||||
/* include the character device, makes cdev avilable */
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
/* includes copy_user vice versa */
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/kobject.h>
|
||||
|
||||
#include <elliptic/elliptic_sysfs.h>
|
||||
#include <elliptic/elliptic_device.h>
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
#include <elliptic/elliptic_mixer_controls.h>
|
||||
#include <dsp/apr_elliptic.h>
|
||||
|
||||
|
||||
/* Alternative mechanism to load calibration data.
|
||||
* Read calibration data during driver initialization
|
||||
* and send message to the DSP
|
||||
*
|
||||
* #define ELLIPTIC_LOAD_CALIBRATION_DATA_FROM_FILESYSTEM 1
|
||||
*/
|
||||
#ifdef ELLIPTIC_LOAD_CALIBRATION_DATA_FROM_FILESYSTEM
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <asm/uaccess.h>
|
||||
#endif
|
||||
|
||||
static struct elliptic_device *elliptic_devices;
|
||||
|
||||
/* Global variable for the device class*/
|
||||
struct class *elliptic_class;
|
||||
|
||||
typedef uint32_t el_fifo_size_t;
|
||||
|
||||
/* Major number provided by the kernel*/
|
||||
static dev_t elliptic_major;
|
||||
|
||||
static struct wakeup_source *wake_source;
|
||||
|
||||
|
||||
void elliptic_data_cancel(struct elliptic_data *elliptic_data)
|
||||
{
|
||||
atomic_set(&elliptic_data->abort_io, 1);
|
||||
wake_up_interruptible(&elliptic_data->fifo_isr_not_empty);
|
||||
}
|
||||
|
||||
void elliptic_data_reset_debug_counters(struct elliptic_data *elliptic_data)
|
||||
{
|
||||
elliptic_data->isr_fifo_discard = 0;
|
||||
}
|
||||
|
||||
void elliptic_data_print_debug_counters(struct elliptic_data *elliptic_data)
|
||||
{
|
||||
if (elliptic_data->isr_fifo_discard > 0) {
|
||||
EL_PRINT_E("isr fifo discarded %u frames",
|
||||
elliptic_data->isr_fifo_discard);
|
||||
}
|
||||
|
||||
if (elliptic_data->userspace_read_total !=
|
||||
elliptic_data->isr_write_total) {
|
||||
EL_PRINT_I("user space reads / isr writes : %u / %u",
|
||||
elliptic_data->userspace_read_total,
|
||||
elliptic_data->isr_write_total);
|
||||
}
|
||||
|
||||
EL_PRINT_I("total isr fifo discarded frame count : %u",
|
||||
elliptic_data->isr_fifo_discard_total);
|
||||
}
|
||||
|
||||
void elliptic_data_update_debug_counters(struct elliptic_data
|
||||
*elliptic_data)
|
||||
{
|
||||
elliptic_data->isr_fifo_discard_total +=
|
||||
elliptic_data->isr_fifo_discard;
|
||||
}
|
||||
|
||||
|
||||
/* spin lock for isr must be held prior to calling */
|
||||
static void elliptic_data_flush_isr_fifo(struct elliptic_data
|
||||
*elliptic_data)
|
||||
{
|
||||
kfifo_reset(&elliptic_data->fifo_isr);
|
||||
}
|
||||
|
||||
/* spin lock for isr must be held prior to calling */
|
||||
static void elliptic_data_isr_fifo_pop(struct elliptic_data
|
||||
*elliptic_data, size_t size)
|
||||
{
|
||||
unsigned int fifo_result;
|
||||
static uint8_t temp_buffer[ELLIPTIC_MSG_BUF_SIZE];
|
||||
|
||||
if (size > ELLIPTIC_MSG_BUF_SIZE)
|
||||
EL_PRINT_E("pop size %zu too large", size);
|
||||
|
||||
fifo_result = kfifo_out(&elliptic_data->fifo_isr,
|
||||
temp_buffer, size);
|
||||
|
||||
if (size != fifo_result)
|
||||
EL_PRINT_E("failed to pop element");
|
||||
}
|
||||
|
||||
|
||||
int elliptic_notify_gain_change_msg(int component_id, int gaindb)
|
||||
{
|
||||
int32_t msg[3] = {ESCPT_COMPONENT_GAIN_CHANGE, component_id, gaindb};
|
||||
|
||||
return elliptic_data_write(
|
||||
ELLIPTIC_ULTRASOUND_SET_PARAMS,
|
||||
(const char *)msg, sizeof(msg));
|
||||
}
|
||||
|
||||
static int major;
|
||||
|
||||
/* inode refers to the actual file on disk */
|
||||
static int device_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
unsigned int major;
|
||||
unsigned int minor;
|
||||
struct elliptic_device *dev;
|
||||
struct elliptic_data *elliptic_data;
|
||||
unsigned long flags;
|
||||
|
||||
major = imajor(inode);
|
||||
minor = iminor(inode);
|
||||
|
||||
if (major != elliptic_major || minor < 0
|
||||
|| minor >= ELLIPTIC_NUM_DEVICES) {
|
||||
EL_PRINT_W("no device found with minor=%d and major=%d",
|
||||
major, minor);
|
||||
return -ENODEV; /* No such device */
|
||||
}
|
||||
|
||||
dev = NULL;
|
||||
dev = &elliptic_devices[minor];
|
||||
filp->private_data = dev;
|
||||
|
||||
if (inode->i_cdev != &dev->cdev) {
|
||||
EL_PRINT_W("dev pointer mismatch");
|
||||
return -ENODEV; /* No such device */
|
||||
}
|
||||
|
||||
if (down_interruptible(&dev->sem) != 0) {
|
||||
EL_PRINT_E("the device has been opened, unable to open lock");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
elliptic_data = &dev->el_data;
|
||||
spin_lock_irqsave(&elliptic_data->fifo_isr_spinlock, flags);
|
||||
elliptic_data_flush_isr_fifo(elliptic_data);
|
||||
spin_unlock_irqrestore(&elliptic_data->fifo_isr_spinlock, flags);
|
||||
|
||||
|
||||
atomic_set(&elliptic_data->abort_io, 0);
|
||||
elliptic_data_reset_debug_counters(elliptic_data);
|
||||
|
||||
EL_PRINT_I("Opened device elliptic%u", minor);
|
||||
dev->opened = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int elliptic_data_initialize(struct elliptic_data
|
||||
*elliptic_data, size_t queue_size,
|
||||
unsigned int wakeup_timeout, int id)
|
||||
{
|
||||
int is_power_of_two;
|
||||
|
||||
is_power_of_two = (queue_size != 0) && !(queue_size & (queue_size - 1));
|
||||
|
||||
if (is_power_of_two != 1) {
|
||||
EL_PRINT_E("non power of 2 fifo size");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (kfifo_alloc(&elliptic_data->fifo_isr,
|
||||
queue_size, GFP_KERNEL) != 0) {
|
||||
EL_PRINT_E("failed to allocate fifo isr");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
atomic_set(&elliptic_data->abort_io, 0);
|
||||
spin_lock_init(&elliptic_data->fifo_isr_spinlock);
|
||||
|
||||
elliptic_data->wakeup_timeout = wakeup_timeout;
|
||||
|
||||
mutex_init(&elliptic_data->user_buffer_lock);
|
||||
init_waitqueue_head(&elliptic_data->fifo_isr_not_empty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elliptic_data_cleanup(struct elliptic_data *elliptic_data)
|
||||
{
|
||||
spin_unlock(&elliptic_data->fifo_isr_spinlock);
|
||||
kfifo_free(&elliptic_data->fifo_isr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t elliptic_data_pop(struct elliptic_data
|
||||
*elliptic_data, char __user *user_buffer, size_t buffer_size)
|
||||
{
|
||||
int result;
|
||||
unsigned long num_copied;
|
||||
unsigned int fifo_result;
|
||||
unsigned long flags;
|
||||
|
||||
if (buffer_size < ELLIPTIC_MSG_BUF_SIZE) {
|
||||
EL_PRINT_E("buffer_size : %lu smaller than %lu",
|
||||
buffer_size, (size_t)ELLIPTIC_MSG_BUF_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = wait_event_interruptible(elliptic_data->fifo_isr_not_empty,
|
||||
(kfifo_is_empty(&elliptic_data->fifo_isr) == 0)
|
||||
|| (atomic_read(&elliptic_data->abort_io) == 1));
|
||||
|
||||
if (atomic_read(&elliptic_data->abort_io) == 1) {
|
||||
atomic_set(&elliptic_data->abort_io, 0);
|
||||
EL_PRINT_D("pop cancelled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
spin_lock_irqsave(&elliptic_data->fifo_isr_spinlock, flags);
|
||||
|
||||
fifo_result = kfifo_out(&elliptic_data->fifo_isr,
|
||||
elliptic_data->isr_swap_buffer, ELLIPTIC_MSG_BUF_SIZE);
|
||||
|
||||
spin_unlock_irqrestore(&elliptic_data->fifo_isr_spinlock,
|
||||
flags);
|
||||
|
||||
if (fifo_result == 0) {
|
||||
EL_PRINT_E("failed to copy: fifo isr -> swap buffer %u",
|
||||
fifo_result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&elliptic_data->user_buffer_lock);
|
||||
|
||||
num_copied = copy_to_user(user_buffer,
|
||||
elliptic_data->isr_swap_buffer,
|
||||
ELLIPTIC_MSG_BUF_SIZE);
|
||||
|
||||
mutex_unlock(&elliptic_data->user_buffer_lock);
|
||||
|
||||
if (num_copied != 0) {
|
||||
EL_PRINT_E("failed copy to user");
|
||||
return 0;
|
||||
}
|
||||
++elliptic_data->userspace_read_total;
|
||||
} else {
|
||||
if (-ERESTARTSYS == result)
|
||||
EL_PRINT_I("wait interrupted");
|
||||
else
|
||||
EL_PRINT_E("wait error = %d", result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)ELLIPTIC_MSG_BUF_SIZE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* push data to specific device or all devices */
|
||||
int elliptic_data_push(int deviceid,
|
||||
const char *buffer,
|
||||
size_t buffer_size,
|
||||
elliptic_data_push_t data_source)
|
||||
{
|
||||
size_t available_space;
|
||||
size_t space_required;
|
||||
size_t zeros_to_pad;
|
||||
unsigned int copied_from_user;
|
||||
int copy_from_user_result;
|
||||
int err;
|
||||
int i;
|
||||
int i_max;
|
||||
|
||||
unsigned long flags;
|
||||
struct elliptic_device *device;
|
||||
struct elliptic_data *elliptic_data;
|
||||
unsigned int fifo_result;
|
||||
static uint8_t zero_pad_buffer[ELLIPTIC_MSG_BUF_SIZE];
|
||||
|
||||
err = 0;
|
||||
fifo_result = 0;
|
||||
copied_from_user = 0;
|
||||
copy_from_user_result = 0;
|
||||
if (buffer_size > ELLIPTIC_MSG_BUF_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
zeros_to_pad = ELLIPTIC_MSG_BUF_SIZE - buffer_size;
|
||||
|
||||
i = 0;
|
||||
i_max = ELLIPTIC_NUM_DEVICES;
|
||||
|
||||
if (deviceid != ELLIPTIC_ALL_DEVICES) {
|
||||
/* Copy to specific device */
|
||||
i = deviceid;
|
||||
i_max = i + 1;
|
||||
}
|
||||
|
||||
for (; i < i_max; ++i) {
|
||||
device = &elliptic_devices[i];
|
||||
elliptic_data = &device->el_data;
|
||||
|
||||
if ((!device->opened))
|
||||
continue;
|
||||
|
||||
available_space = kfifo_avail(&elliptic_data->fifo_isr);
|
||||
space_required = ELLIPTIC_MSG_BUF_SIZE;
|
||||
|
||||
spin_lock_irqsave(&elliptic_data->fifo_isr_spinlock, flags);
|
||||
|
||||
if (available_space < space_required) {
|
||||
|
||||
++elliptic_data->isr_fifo_discard;
|
||||
elliptic_data_isr_fifo_pop(elliptic_data,
|
||||
ELLIPTIC_MSG_BUF_SIZE);
|
||||
}
|
||||
|
||||
if (data_source == ELLIPTIC_DATA_PUSH_FROM_KERNEL) {
|
||||
fifo_result = kfifo_in(&elliptic_data->fifo_isr,
|
||||
buffer, buffer_size);
|
||||
|
||||
if (fifo_result == 0) {
|
||||
spin_unlock_irqrestore(
|
||||
&elliptic_data->fifo_isr_spinlock,
|
||||
flags);
|
||||
continue;
|
||||
}
|
||||
} else if (data_source == ELLIPTIC_DATA_PUSH_FROM_USERSPACE) {
|
||||
copy_from_user_result = kfifo_from_user(
|
||||
&elliptic_data->fifo_isr, buffer,
|
||||
buffer_size, &copied_from_user);
|
||||
|
||||
if (-EFAULT == copy_from_user_result) {
|
||||
spin_unlock_irqrestore(
|
||||
&elliptic_data->fifo_isr_spinlock,
|
||||
flags);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (zeros_to_pad > 0) {
|
||||
fifo_result = kfifo_in(
|
||||
&elliptic_data->fifo_isr, zero_pad_buffer,
|
||||
zeros_to_pad);
|
||||
|
||||
if (fifo_result == 0) {
|
||||
elliptic_data_isr_fifo_pop(elliptic_data,
|
||||
buffer_size);
|
||||
|
||||
spin_unlock_irqrestore(
|
||||
&elliptic_data->fifo_isr_spinlock,
|
||||
flags);
|
||||
|
||||
++elliptic_data->isr_fifo_discard;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
++elliptic_data->isr_write_total;
|
||||
spin_unlock_irqrestore(
|
||||
&elliptic_data->fifo_isr_spinlock, flags);
|
||||
wake_up_interruptible(&elliptic_data->fifo_isr_not_empty);
|
||||
__pm_wakeup_event(wake_source, elliptic_data->wakeup_timeout);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int elliptic_open_port(int portid)
|
||||
{
|
||||
return elliptic_io_open_port(portid);
|
||||
}
|
||||
|
||||
int elliptic_close_port(int portid)
|
||||
{
|
||||
return elliptic_io_close_port(portid);
|
||||
}
|
||||
|
||||
|
||||
int32_t elliptic_data_write(uint32_t message_id,
|
||||
const char *data, size_t data_size)
|
||||
{
|
||||
int32_t err_dsp;
|
||||
/* int32_t err_us; */
|
||||
|
||||
err_dsp = 0;
|
||||
err_dsp = elliptic_data_io_write(message_id, data, data_size);
|
||||
if (err_dsp)
|
||||
EL_PRINT_E("Failed write to DSP");
|
||||
return err_dsp;
|
||||
|
||||
/*
|
||||
* err_us = 0;
|
||||
* err_us = elliptic_userspace_ctrl_write(message_id, data, data_size);
|
||||
* if(err_us){
|
||||
* EL_PRINT_E("Failed write to user space");
|
||||
*}
|
||||
*
|
||||
*return (err_dsp | err_us);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Number of bytes read.
|
||||
*/
|
||||
static ssize_t device_read(struct file *fp, char __user *buff,
|
||||
size_t length, loff_t *ppos)
|
||||
{
|
||||
ssize_t bytes_read = 0;
|
||||
struct elliptic_device *elliptic_device;
|
||||
struct elliptic_data *elliptic_data;
|
||||
|
||||
elliptic_device = (struct elliptic_device *)fp->private_data;
|
||||
elliptic_data = (struct elliptic_data *)&elliptic_device->el_data;
|
||||
|
||||
bytes_read = elliptic_data_pop(elliptic_data, buff, length);
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return number of bytes actually written
|
||||
*/
|
||||
static ssize_t device_write(struct file *fp, const char *buff,
|
||||
size_t length, loff_t *ppos)
|
||||
{
|
||||
ssize_t ret_val;
|
||||
|
||||
ret_val = 0;
|
||||
if ((buff != NULL) && (length != 0))
|
||||
ret_val = elliptic_data_io_write(ELLIPTIC_ULTRASOUND_SET_PARAMS,
|
||||
buff, length);
|
||||
|
||||
return ret_val >= 0 ? (ssize_t)length : 0;
|
||||
}
|
||||
|
||||
|
||||
static long device_ioctl(struct file *fp, unsigned int number,
|
||||
unsigned long param)
|
||||
{
|
||||
struct elliptic_device *device;
|
||||
struct elliptic_data *elliptic_data;
|
||||
int err;
|
||||
unsigned int mirror_tag, mirror_payload_size;
|
||||
unsigned char *data_ptr;
|
||||
|
||||
device = (struct elliptic_device *)(fp->private_data);
|
||||
elliptic_data = &device->el_data;
|
||||
|
||||
switch (number) {
|
||||
case IOCTL_ELLIPTIC_DATA_IO_CANCEL:
|
||||
EL_PRINT_D("IOCTL_ELLIPTIC_CANCEL_READ %ld",
|
||||
param);
|
||||
elliptic_data_cancel(elliptic_data);
|
||||
break;
|
||||
|
||||
case IOCTL_ELLIPTIC_DATA_IO_MIRROR:
|
||||
data_ptr = (unsigned char *)param;
|
||||
mirror_tag = *(unsigned int *)data_ptr;
|
||||
mirror_payload_size = *((unsigned int *)data_ptr + 1);
|
||||
|
||||
if ((mirror_tag == MIRROR_TAG) &&
|
||||
(mirror_payload_size != 0) &&
|
||||
(mirror_payload_size <=
|
||||
(ELLIPTIC_SET_PARAMS_SIZE * 4))) {
|
||||
|
||||
err = elliptic_data_io_write(
|
||||
ELLIPTIC_ULTRASOUND_SET_PARAMS,
|
||||
(data_ptr + 8), mirror_payload_size);
|
||||
|
||||
if (err != 0) {
|
||||
EL_PRINT_E("elliptic_data_io_write failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
} else {
|
||||
EL_PRINT_E("TAG or Length is not valid");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
EL_PRINT_W("UNKNOWN IOCTL number=%d", number);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int device_poll(struct file *file,
|
||||
struct poll_table_struct *poll_table)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
struct elliptic_device *device;
|
||||
struct elliptic_data *elliptic_data;
|
||||
|
||||
mask = 0;
|
||||
device = (struct elliptic_device *)file->private_data;
|
||||
elliptic_data = (struct elliptic_data *)&device->el_data;
|
||||
|
||||
poll_wait(file, &elliptic_data->fifo_isr_not_empty, poll_table);
|
||||
|
||||
if (!kfifo_is_empty(&elliptic_data->fifo_isr))
|
||||
mask = POLLIN | POLLRDNORM;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
static int device_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct elliptic_device *device;
|
||||
struct elliptic_data *elliptic_data;
|
||||
unsigned int minor;
|
||||
|
||||
device = filp->private_data;
|
||||
elliptic_data = &device->el_data;
|
||||
minor = iminor(inode);
|
||||
if (device == NULL) {
|
||||
EL_PRINT_E("device not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
device->opened = 0;
|
||||
elliptic_data_update_debug_counters(elliptic_data);
|
||||
elliptic_data_print_debug_counters(elliptic_data);
|
||||
elliptic_data_cancel(elliptic_data);
|
||||
up(&device->sem);
|
||||
|
||||
EL_PRINT_I("Closed device elliptic%u", minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* defines the file operations provided by the driver */
|
||||
static const struct file_operations elliptic_fops = {
|
||||
.owner = THIS_MODULE, /* prevents unloading when operations are in use*/
|
||||
.open = device_open, /*to open the device*/
|
||||
.write = device_write, /*to write to the device*/
|
||||
.read = device_read, /*to read the device*/
|
||||
.poll = device_poll,
|
||||
.unlocked_ioctl = device_ioctl, /* IOCTL calls */
|
||||
.release = device_close, /*to close the device*/
|
||||
};
|
||||
|
||||
|
||||
static int elliptic_device_initialize(struct elliptic_device
|
||||
*elliptic_device, int minor, struct class *class)
|
||||
{
|
||||
int err;
|
||||
dev_t device_number;
|
||||
struct device *device;
|
||||
|
||||
BUG_ON(elliptic_device == NULL || class == NULL);
|
||||
|
||||
err = 0;
|
||||
device = NULL;
|
||||
device_number = MKDEV(elliptic_major, minor);
|
||||
/* Memory is to be allocated when the device is opened the first time */
|
||||
sema_init(&elliptic_device->sem, 1);
|
||||
cdev_init(&elliptic_device->cdev, &elliptic_fops);
|
||||
elliptic_device->cdev.owner = THIS_MODULE;
|
||||
|
||||
err = cdev_add(&elliptic_device->cdev, device_number, 1);
|
||||
|
||||
if (err) {
|
||||
EL_PRINT_E("error %d while trying to add %s%d",
|
||||
err, ELLIPTIC_DEVICENAME, minor);
|
||||
return err;
|
||||
}
|
||||
|
||||
device = device_create(class, NULL, device_number,
|
||||
NULL, ELLIPTIC_DEVICENAME "%d", minor);
|
||||
|
||||
if (IS_ERR(device)) {
|
||||
err = PTR_ERR(device);
|
||||
EL_PRINT_E("error %d while trying to create %s%d",
|
||||
err, ELLIPTIC_DEVICENAME, minor);
|
||||
cdev_del(&elliptic_device->cdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
EL_PRINT_E("failed device initialize");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void elliptic_device_cleanup(struct elliptic_device *dev, int minor,
|
||||
struct class *class)
|
||||
|
||||
{
|
||||
BUG_ON(dev == NULL || class == NULL);
|
||||
device_destroy(class, MKDEV(elliptic_major, minor));
|
||||
cdev_del(&dev->cdev);
|
||||
up(&dev->sem);
|
||||
}
|
||||
|
||||
static void elliptic_driver_cleanup(int devices_to_destroy)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (elliptic_devices) {
|
||||
elliptic_data_io_cleanup();
|
||||
|
||||
for (i = 0; i < devices_to_destroy; ++i) {
|
||||
elliptic_data_cleanup(&elliptic_devices[i].el_data);
|
||||
elliptic_device_cleanup(
|
||||
&elliptic_devices[i], i, elliptic_class);
|
||||
}
|
||||
|
||||
kfree(elliptic_devices);
|
||||
}
|
||||
|
||||
if (elliptic_class)
|
||||
class_destroy(elliptic_class);
|
||||
|
||||
unregister_chrdev_region(
|
||||
MKDEV(elliptic_major, 0), ELLIPTIC_NUM_DEVICES);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ELLIPTIC_LOAD_CALIBRATION_DATA_FROM_FILESYSTEM
|
||||
|
||||
#define ELLIPTIC_CALIBRATION_MAX_DATA_SIZE (ELLIPTIC_CALIBRATION_V2_DATA_SIZE + ELLIPTIC_CALIBRATION_DATA_SIZE)
|
||||
static unsigned char calibration_data[ELLIPTIC_CALIBRATION_MAX_DATA_SIZE];
|
||||
static char *calibration_filename = "/persist/audio/elliptic_calibration";
|
||||
|
||||
/* function to load the calibration from a file (if possible) */
|
||||
static size_t load_calibration_data(char *filename)
|
||||
{
|
||||
size_t ret = 0;
|
||||
int fd;
|
||||
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
fd = sys_open(filename, O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
size_t bytes_read = sys_read(fd, calibration_data, ELLIPTIC_CALIBRATION_MAX_DATA_SIZE);
|
||||
|
||||
if (bytes_read == ELLIPTIC_CALIBRATION_DATA_SIZE ||
|
||||
bytes_read == ELLIPTIC_CALIBRATION_V2_DATA_SIZE) {
|
||||
ret = bytes_read;
|
||||
}
|
||||
sys_close(fd);
|
||||
}
|
||||
set_fs(old_fs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t elliptic_send_calibration_to_engine(size_t calib_data_size)
|
||||
{
|
||||
elliptic_set_calibration_data(calibration_data, calib_data_size);
|
||||
return elliptic_data_write(
|
||||
ELLIPTIC_ULTRASOUND_SET_PARAMS,
|
||||
(const char *)calibration_data, calib_data_size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int __init elliptic_driver_init(void)
|
||||
{
|
||||
int err;
|
||||
int i;
|
||||
int devices_to_destroy;
|
||||
dev_t device_number = MKDEV(major, 0);
|
||||
|
||||
if (major) {
|
||||
err = register_chrdev_region(device_number, ELLIPTIC_NUM_DEVICES,
|
||||
ELLIPTIC_DEVICENAME);
|
||||
} else {
|
||||
err = alloc_chrdev_region(&device_number, 0, ELLIPTIC_NUM_DEVICES,
|
||||
ELLIPTIC_DEVICENAME);
|
||||
major = MAJOR(device_number);
|
||||
}
|
||||
|
||||
devices_to_destroy = 0;
|
||||
|
||||
if (err < 0) {
|
||||
EL_PRINT_E("Failed to allocate cdev region");
|
||||
return err;
|
||||
}
|
||||
|
||||
elliptic_major = MAJOR(device_number);
|
||||
elliptic_class = class_create(THIS_MODULE, "chardev");
|
||||
|
||||
if (elliptic_class == NULL) {
|
||||
EL_PRINT_E("Class creation failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
elliptic_devices = (struct elliptic_device *)
|
||||
kzalloc(sizeof(struct elliptic_device) * ELLIPTIC_NUM_DEVICES,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (elliptic_devices == NULL) {
|
||||
err = -ENOMEM;
|
||||
EL_PRINT_E("elliptic_devices creation failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < ELLIPTIC_NUM_DEVICES; ++i) {
|
||||
if (elliptic_device_initialize(&elliptic_devices[i], i,
|
||||
elliptic_class)) {
|
||||
devices_to_destroy = i;
|
||||
EL_PRINT_E("elliptic device initialize failed %d", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (elliptic_data_initialize(&elliptic_devices[i].el_data,
|
||||
ELLIPTIC_DATA_FIFO_SIZE, ELLIPTIC_WAKEUP_TIMEOUT, i)) {
|
||||
EL_PRINT_E("elliptic data initialize failed failed %d", i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (elliptic_initialize_sysfs())
|
||||
goto fail;
|
||||
|
||||
if (elliptic_data_io_initialize())
|
||||
goto fail;
|
||||
|
||||
if (elliptic_userspace_io_driver_init())
|
||||
goto fail;
|
||||
|
||||
|
||||
if (elliptic_userspace_ctrl_driver_init())
|
||||
goto fail;
|
||||
|
||||
wake_source = wakeup_source_register(NULL, "elliptic_wake_source");
|
||||
if (wake_source == NULL) {
|
||||
EL_PRINT_E("wake_source register failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef ELLIPTIC_LOAD_CALIBRATION_DATA_FROM_FILESYSTEM
|
||||
/* Code to send calibration to engine */
|
||||
{
|
||||
size_t calib_data_size = load_calibration_data(calibration_filename);
|
||||
if (calib_data_size > 0)
|
||||
elliptic_send_calibration_to_engine(calib_data_size);
|
||||
}
|
||||
#endif
|
||||
EL_PRINT_I("elliptic_class creation name %s", elliptic_class->name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
elliptic_driver_cleanup(devices_to_destroy);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void elliptic_driver_exit(void)
|
||||
{
|
||||
wakeup_source_unregister(wake_source);
|
||||
|
||||
elliptic_cleanup_sysfs();
|
||||
elliptic_driver_cleanup(ELLIPTIC_NUM_DEVICES);
|
||||
elliptic_userspace_io_driver_exit();
|
||||
elliptic_userspace_ctrl_driver_exit();
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Elliptic Labs");
|
||||
MODULE_DESCRIPTION("Providing Interface to UPS data");
|
||||
MODULE_LICENSE("GPL");
|
1351
techpack/audio/dsp/elliptic/elliptic_mixer_controls.c
Executable file
1351
techpack/audio/dsp/elliptic/elliptic_mixer_controls.c
Executable file
File diff suppressed because it is too large
Load Diff
654
techpack/audio/dsp/elliptic/elliptic_sysfs.c
Executable file
654
techpack/audio/dsp/elliptic/elliptic_sysfs.c
Executable file
@ -0,0 +1,654 @@
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <elliptic/elliptic_device.h>
|
||||
#include <elliptic/elliptic_sysfs.h>
|
||||
#include "elliptic_version.h"
|
||||
#include <elliptic/elliptic_mixer_controls.h>
|
||||
|
||||
|
||||
#define ELLIPTIC_DIAGNOSTICS_DATA_SECTION_COUNT 16
|
||||
#define ELLIPTIC_CALIBRATION_MAX_DISPLAY_COUNT 96
|
||||
#define ELLIPTIC_ML_DISPLAY_COUNT 16
|
||||
|
||||
#define elliptic_attr(_name) \
|
||||
static struct kobj_attribute _name##_attr = { \
|
||||
.attr = { \
|
||||
.name = __stringify(_name), \
|
||||
.mode = 0644, \
|
||||
}, \
|
||||
.show = _name##_show, \
|
||||
.store = _name##_store, \
|
||||
}
|
||||
|
||||
#define elliptic_attr_ro(_name) \
|
||||
static struct kobj_attribute _name##_attr = { \
|
||||
.attr = { \
|
||||
.name = __stringify(_name), \
|
||||
.mode = S_IRUGO, \
|
||||
}, \
|
||||
.show = _name##_show, \
|
||||
}
|
||||
|
||||
static int kobject_create_and_add_failed;
|
||||
static int sysfs_create_group_failed;
|
||||
|
||||
extern struct elliptic_system_configuration_parameters_cache
|
||||
elliptic_system_configuration_cache;
|
||||
|
||||
static ssize_t calibration_store(struct kobject *dev,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count) {
|
||||
|
||||
ssize_t result;
|
||||
|
||||
struct elliptic_shared_data_block *calibration_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_CALIBRATION_DATA);
|
||||
|
||||
if (calibration_obj == NULL) {
|
||||
EL_PRINT_E("calibration_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (count > calibration_obj->size) {
|
||||
EL_PRINT_E("write length %zu larger than buffer", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(calibration_obj->buffer, buf, count);
|
||||
result = (ssize_t)count;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t calibration_v2_store(struct kobject *dev,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count) {
|
||||
|
||||
ssize_t result;
|
||||
|
||||
struct elliptic_shared_data_block *calibration_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_CALIBRATION_V2_DATA);
|
||||
|
||||
if (calibration_obj == NULL) {
|
||||
EL_PRINT_E("calibration_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (count > calibration_obj->size) {
|
||||
EL_PRINT_E("write length %zu larger than buffer", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(calibration_obj->buffer, buf, count);
|
||||
result = (ssize_t)count;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t diagnostics_store(struct kobject *dev,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count) {
|
||||
|
||||
ssize_t result;
|
||||
|
||||
struct elliptic_shared_data_block *diagnostics_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_DIAGNOSTICS_DATA);
|
||||
|
||||
if (diagnostics_obj == NULL) {
|
||||
EL_PRINT_E("diagnostics_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (count > diagnostics_obj->size) {
|
||||
EL_PRINT_E("write length %zu larger than buffer", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(diagnostics_obj->buffer, buf, count);
|
||||
result = (ssize_t)count;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t ml_store(struct kobject *dev,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count) {
|
||||
|
||||
ssize_t result;
|
||||
|
||||
struct elliptic_shared_data_block *ml_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_ML_DATA);
|
||||
|
||||
if (ml_obj == NULL) {
|
||||
EL_PRINT_E("ml_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (count > ml_obj->size) {
|
||||
EL_PRINT_E("write length %zu larger than buffer", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ml_obj->buffer, buf, count);
|
||||
result = (ssize_t)count;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t calibration_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
ssize_t result;
|
||||
int length = 0;
|
||||
int i;
|
||||
uint8_t *caldata;
|
||||
|
||||
struct elliptic_shared_data_block *calibration_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_CALIBRATION_DATA);
|
||||
|
||||
if (kobject_create_and_add_failed)
|
||||
EL_PRINT_E("kobject_create_and_add_failed");
|
||||
|
||||
if (sysfs_create_group_failed)
|
||||
EL_PRINT_E("sysfs_create_group_failed");
|
||||
|
||||
if (calibration_obj == NULL) {
|
||||
EL_PRINT_E("calibration_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (calibration_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("calibration_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
caldata = (uint8_t *)calibration_obj->buffer;
|
||||
length = 0;
|
||||
if (pretty) {
|
||||
if (caldata[0] == 0xDE &&
|
||||
caldata[1] == 0xAD) {
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"Calibration Data: not loaded");
|
||||
} else {
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"Calibration Data: ");
|
||||
for (i = 0; i < calibration_obj->size; ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"0x%02x ", caldata[i]);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < calibration_obj->size; ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"0x%02x ", caldata[i]);
|
||||
}
|
||||
length += snprintf(buf + length, PAGE_SIZE - length, "\n\n");
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t calibration_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return calibration_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t calibration_v2_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
ssize_t result;
|
||||
int length = 0;
|
||||
int i;
|
||||
uint8_t *caldata;
|
||||
|
||||
struct elliptic_shared_data_block *calibration_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_CALIBRATION_V2_DATA);
|
||||
|
||||
if (kobject_create_and_add_failed)
|
||||
EL_PRINT_E("kobject_create_and_add_failed");
|
||||
|
||||
if (sysfs_create_group_failed)
|
||||
EL_PRINT_E("sysfs_create_group_failed");
|
||||
|
||||
if (calibration_obj == NULL) {
|
||||
EL_PRINT_E("calibration_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (calibration_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("calibration_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
caldata = (uint8_t *)calibration_obj->buffer;
|
||||
length = 0;
|
||||
if (pretty) {
|
||||
if (caldata[0] == 0xDE &&
|
||||
caldata[1] == 0xAD) {
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"Calibration Ext Data: not loaded");
|
||||
} else {
|
||||
int j = (ELLIPTIC_CALIBRATION_V2_DATA_SIZE>>2) - 1;
|
||||
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"Calibration Ext Data: ");
|
||||
for (i = 0; i < ELLIPTIC_CALIBRATION_MAX_DISPLAY_COUNT; ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"0x%02x ", caldata[i]);
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"\nTruncated at %d",
|
||||
ELLIPTIC_CALIBRATION_MAX_DISPLAY_COUNT);
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"\nmisc: %u %u %u %u %u %u %u %u\n",
|
||||
caldata[j-7], caldata[j-6], caldata[j-5],
|
||||
caldata[j-4], caldata[j-3], caldata[j-2],
|
||||
caldata[j-1], caldata[j]);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < calibration_obj->size; ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"0x%02x ", caldata[i]);
|
||||
}
|
||||
length += snprintf(buf + length, PAGE_SIZE - length, "\n\n");
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t calibration_v2_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return calibration_v2_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t diagnostics_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
ssize_t result;
|
||||
int length = 0;
|
||||
uint32_t *data32;
|
||||
int i;
|
||||
|
||||
struct elliptic_shared_data_block *diagnostics_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_DIAGNOSTICS_DATA);
|
||||
|
||||
if (kobject_create_and_add_failed)
|
||||
EL_PRINT_E("kobject_create_and_add_failed");
|
||||
|
||||
if (sysfs_create_group_failed)
|
||||
EL_PRINT_E("sysfs_create_group_failed");
|
||||
|
||||
if (diagnostics_obj == NULL) {
|
||||
EL_PRINT_E("diagnostics_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (diagnostics_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("diagnostics_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
length = 0;
|
||||
data32 = (uint32_t *)diagnostics_obj->buffer;
|
||||
|
||||
if (pretty) {
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"Diagnostics:\n counters:\n");
|
||||
for (i = 0; i < ELLIPTIC_DIAGNOSTICS_DATA_SECTION_COUNT; i++)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length, " %u %u %u %u\n",
|
||||
data32[4*i], data32[4*i+1], data32[4*i+2], data32[4*i+3]);
|
||||
} else {
|
||||
for (i = 0; i < (diagnostics_obj->size >> 4); ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length, " %u %u %u %u\n",
|
||||
data32[4*i], data32[4*i+1], data32[4*i+2], data32[4*i+3]);
|
||||
}
|
||||
length += snprintf(buf + length, PAGE_SIZE - length, "\n\n");
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t diagnostics_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return diagnostics_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t ml_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
ssize_t result;
|
||||
int length = 0;
|
||||
int i;
|
||||
uint32_t *mldata;
|
||||
|
||||
struct elliptic_shared_data_block *ml_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_ML_DATA);
|
||||
|
||||
if (kobject_create_and_add_failed)
|
||||
EL_PRINT_E("kobject_create_and_add_failed");
|
||||
|
||||
if (sysfs_create_group_failed)
|
||||
EL_PRINT_E("sysfs_create_group_failed");
|
||||
|
||||
if (ml_obj == NULL) {
|
||||
EL_PRINT_E("ml_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ml_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("ml_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mldata = (uint32_t *)ml_obj->buffer;
|
||||
length = 0;
|
||||
if (pretty) {
|
||||
if (mldata[0] == 0x0 &&
|
||||
mldata[1] == 0x0) {
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"ML Data: not loaded");
|
||||
} else {
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"ML Data: ");
|
||||
for (i = 0; i < ELLIPTIC_ML_DISPLAY_COUNT; ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"0x%08x ", mldata[i]);
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"\nTruncated at %d",
|
||||
ELLIPTIC_ML_DISPLAY_COUNT);
|
||||
}
|
||||
} else {
|
||||
int values = ml_obj->size >> 2;
|
||||
|
||||
for (i = 0; i < values; ++i)
|
||||
length += snprintf(buf + length, PAGE_SIZE - length,
|
||||
"0x%08x ", mldata[i]);
|
||||
}
|
||||
length += snprintf(buf + length, PAGE_SIZE - length, "\n\n");
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t ml_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return ml_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t version_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
ssize_t result;
|
||||
struct elliptic_engine_version_info *version_info;
|
||||
int length;
|
||||
|
||||
struct elliptic_shared_data_block *version_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_VERSION_INFO);
|
||||
|
||||
if (kobject_create_and_add_failed)
|
||||
EL_PRINT_E("kobject_create_and_add_failed");
|
||||
|
||||
if (sysfs_create_group_failed)
|
||||
EL_PRINT_E("sysfs_create_group_failed");
|
||||
|
||||
if (version_obj == NULL) {
|
||||
EL_PRINT_E("version_obj is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (version_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("version_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
version_info = (struct elliptic_engine_version_info *)
|
||||
version_obj->buffer;
|
||||
|
||||
if (pretty) {
|
||||
if (version_info->major == 0xDE &&
|
||||
version_info->minor == 0xAD) {
|
||||
length = snprintf(buf, PAGE_SIZE, "Version: unknown\n");
|
||||
} else {
|
||||
length = snprintf(buf, PAGE_SIZE, "Version: %d.%d.%d.%d\n",
|
||||
version_info->major, version_info->minor,
|
||||
version_info->build, version_info->revision);
|
||||
}
|
||||
} else {
|
||||
length = snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
|
||||
version_info->major, version_info->minor,
|
||||
version_info->build, version_info->revision);
|
||||
}
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t version_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return version_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t branch_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
struct elliptic_shared_data_block *branch_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_BRANCH_INFO);
|
||||
|
||||
if (branch_obj == NULL) {
|
||||
EL_PRINT_E("branch_obj not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (branch_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("branch_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pretty) {
|
||||
length = snprintf(buf, PAGE_SIZE - 1, "Branch: %s\n",
|
||||
(const char *)(branch_obj->buffer));
|
||||
} else {
|
||||
length = snprintf(buf, PAGE_SIZE - 1, "%s\n",
|
||||
(const char *)(branch_obj->buffer));
|
||||
}
|
||||
|
||||
return (ssize_t)length;
|
||||
}
|
||||
|
||||
static ssize_t branch_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return branch_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t tag_show_core(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf, int pretty)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
struct elliptic_shared_data_block *tag_obj =
|
||||
elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_TAG_INFO);
|
||||
|
||||
if (tag_obj == NULL) {
|
||||
EL_PRINT_E("tag_obj not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag_obj->size > PAGE_SIZE) {
|
||||
EL_PRINT_E("tag_obj->size > PAGE_SIZE");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pretty) {
|
||||
length = snprintf(buf, PAGE_SIZE - 1, "Tag: %s\n",
|
||||
(const char *)(tag_obj->buffer));
|
||||
} else {
|
||||
length = snprintf(buf, PAGE_SIZE - 1, "%s\n",
|
||||
(const char *)(tag_obj->buffer));
|
||||
}
|
||||
|
||||
return (ssize_t)length;
|
||||
}
|
||||
|
||||
static ssize_t tag_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return tag_show_core(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t cache_show(char *buf, int pretty)
|
||||
{
|
||||
struct elliptic_system_configuration_parameters_cache *cache =
|
||||
&elliptic_system_configuration_cache;
|
||||
|
||||
int length = 0;
|
||||
|
||||
length = snprintf(buf, PAGE_SIZE - 1, "Cache:\n");
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " mi:%d\n",
|
||||
cache->microphone_index);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " om:%d\n",
|
||||
cache->operation_mode);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " omf:%d\n",
|
||||
cache->operation_mode_flags);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " cs:%d\n",
|
||||
cache->calibration_state);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " cp:%d\n",
|
||||
cache->calibration_profile);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " ug:%d\n",
|
||||
cache->ultrasound_gain);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " ll:%d\n",
|
||||
cache->log_level);
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, " es:%d\n",
|
||||
cache->engine_suspend);
|
||||
|
||||
return (ssize_t)length;
|
||||
}
|
||||
|
||||
static ssize_t opmode_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int length = 0;
|
||||
ssize_t result;
|
||||
|
||||
struct elliptic_system_configuration_parameters_cache *cache =
|
||||
&elliptic_system_configuration_cache;
|
||||
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, "%d\n",
|
||||
cache->operation_mode);
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t opmode_flags_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int length = 0;
|
||||
ssize_t result;
|
||||
struct elliptic_system_configuration_parameters_cache *cache =
|
||||
&elliptic_system_configuration_cache;
|
||||
|
||||
length += snprintf(buf + length, PAGE_SIZE - 1, "%d\n",
|
||||
cache->operation_mode_flags);
|
||||
result = (ssize_t)length;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t driver_version_show(char *buf)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
length = snprintf(buf, PAGE_SIZE, "Driver version: %s-%s (%s)\n",
|
||||
build_name, build_number, build_source_version);
|
||||
|
||||
return (ssize_t)length;
|
||||
}
|
||||
|
||||
static ssize_t state_show(struct kobject *dev,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
length += driver_version_show(buf + length);
|
||||
length += version_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += branch_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += tag_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += calibration_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += calibration_v2_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += diagnostics_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += ml_show_core(dev, attr, buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
length += cache_show(buf + length, 1);
|
||||
if (length > PAGE_SIZE)
|
||||
return (ssize_t)0;
|
||||
return (ssize_t)length;
|
||||
}
|
||||
|
||||
elliptic_attr(calibration);
|
||||
elliptic_attr(calibration_v2);
|
||||
elliptic_attr(diagnostics);
|
||||
elliptic_attr(ml);
|
||||
elliptic_attr_ro(version);
|
||||
elliptic_attr_ro(branch);
|
||||
elliptic_attr_ro(state);
|
||||
elliptic_attr_ro(tag);
|
||||
elliptic_attr_ro(opmode);
|
||||
elliptic_attr_ro(opmode_flags);
|
||||
|
||||
static struct attribute *elliptic_attrs[] = {
|
||||
&calibration_attr.attr,
|
||||
&version_attr.attr,
|
||||
&branch_attr.attr,
|
||||
&calibration_v2_attr.attr,
|
||||
&diagnostics_attr.attr,
|
||||
&state_attr.attr,
|
||||
&tag_attr.attr,
|
||||
&ml_attr.attr,
|
||||
&opmode_attr.attr,
|
||||
&opmode_flags_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group elliptic_attr_group = {
|
||||
.name = ELLIPTIC_SYSFS_ENGINE_FOLDER,
|
||||
.attrs = elliptic_attrs,
|
||||
};
|
||||
|
||||
static struct kobject *elliptic_sysfs_kobj;
|
||||
|
||||
int elliptic_initialize_sysfs(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
elliptic_sysfs_kobj = kobject_create_and_add(ELLIPTIC_SYSFS_ROOT_FOLDER,
|
||||
kernel_kobj->parent);
|
||||
|
||||
if (!elliptic_sysfs_kobj) {
|
||||
kobject_create_and_add_failed = 1;
|
||||
EL_PRINT_E("failed to create kobj");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = sysfs_create_group(elliptic_sysfs_kobj, &elliptic_attr_group);
|
||||
|
||||
if (err) {
|
||||
sysfs_create_group_failed = 1;
|
||||
EL_PRINT_E("failed to create sysfs group");
|
||||
kobject_put(elliptic_sysfs_kobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void elliptic_cleanup_sysfs(void)
|
||||
{
|
||||
kobject_put(elliptic_sysfs_kobj);
|
||||
}
|
8
techpack/audio/dsp/elliptic/elliptic_version.h
Executable file
8
techpack/audio/dsp/elliptic/elliptic_version.h
Executable file
@ -0,0 +1,8 @@
|
||||
#ifndef ELLIPTIC_VERSION_H
|
||||
#define ELLIPTIC_VERSION_H
|
||||
|
||||
#define build_name "Elliptic.LinuxKernelDriver.VendorDLKM.master"
|
||||
#define build_number "20181016.1"
|
||||
#define build_source_version "e5e26691554bba9b1438ec3d7e0cc55dfb296bb8"
|
||||
|
||||
#endif //ELLIPTIC_VERSION_H
|
2
techpack/audio/dsp/elliptic/io_modules/Makefile
Executable file
2
techpack/audio/dsp/elliptic/io_modules/Makefile
Executable file
@ -0,0 +1,2 @@
|
||||
# TODO: add config parameter for which io module to build
|
||||
#obj-y += userspace/
|
108
techpack/audio/dsp/elliptic/io_modules/msm/elliptic_data_msm_io.c
Executable file
108
techpack/audio/dsp/elliptic/io_modules/msm/elliptic_data_msm_io.c
Executable file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
/* includes the file structure, that is, file open read close */
|
||||
#include <linux/fs.h>
|
||||
|
||||
/* include the character device, makes cdev avilable */
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
/* includes copy_user vice versa */
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
#include <elliptic/elliptic_device.h>
|
||||
|
||||
#include <dsp/apr_elliptic.h>
|
||||
#include <dsp/q6afe-v2.h>
|
||||
|
||||
#define IO_PING_PONG_BUFFER_SIZE 512
|
||||
#define AFE_MSM_RX_PSEUDOPORT_ID 0x8001
|
||||
#define AFE_MSM_TX_PSEUDOPORT_ID 0x8002
|
||||
|
||||
struct elliptic_msm_io_device {
|
||||
};
|
||||
|
||||
/* static struct elliptic_msm_io_device io_device;*/
|
||||
|
||||
|
||||
int elliptic_data_io_initialize(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elliptic_data_io_cleanup(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int elliptic_io_open_port(int portid)
|
||||
{
|
||||
if (portid == ULTRASOUND_RX_PORT_ID)
|
||||
return afe_start_pseudo_port(AFE_MSM_RX_PSEUDOPORT_ID);
|
||||
else
|
||||
return afe_start_pseudo_port(AFE_MSM_TX_PSEUDOPORT_ID);
|
||||
}
|
||||
|
||||
int elliptic_io_close_port(int portid)
|
||||
{
|
||||
if (portid == ULTRASOUND_RX_PORT_ID)
|
||||
return afe_stop_pseudo_port(AFE_MSM_RX_PSEUDOPORT_ID);
|
||||
else
|
||||
return afe_stop_pseudo_port(AFE_MSM_TX_PSEUDOPORT_ID);
|
||||
}
|
||||
|
||||
int32_t elliptic_data_io_write(uint32_t message_id, const char *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t result = 0;
|
||||
|
||||
/* msm_pcm_routing_acquire_lock(); */
|
||||
|
||||
result = ultrasound_apr_set_parameter(ELLIPTIC_PORT_ID,
|
||||
message_id, (u8 *)data,
|
||||
(int32_t)data_size);
|
||||
|
||||
/* msm_pcm_routing_release_lock();*/
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t elliptic_data_io_transact(uint32_t message_id, const char *data,
|
||||
size_t data_size, char *output_data, size_t output_data_size)
|
||||
{
|
||||
pr_err("%s : unimplemented\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
2
techpack/audio/dsp/elliptic/io_modules/userspace/Makefile
Executable file
2
techpack/audio/dsp/elliptic/io_modules/userspace/Makefile
Executable file
@ -0,0 +1,2 @@
|
||||
# TODO: add config parameter for which io module to build
|
||||
#obj-y += elliptic_data_io.o
|
271
techpack/audio/dsp/elliptic/io_modules/userspace/elliptic_data_userspace_ctrl.c
Executable file
271
techpack/audio/dsp/elliptic/io_modules/userspace/elliptic_data_userspace_ctrl.c
Executable file
@ -0,0 +1,271 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
/* includes the file structure, that is, file open read close */
|
||||
#include <linux/fs.h>
|
||||
|
||||
/* include the character device, makes cdev avilable */
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
/* includes copy_user vice versa */
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
#include <elliptic/elliptic_device.h>
|
||||
|
||||
|
||||
static dev_t elliptic_userspace_ctrl_major;
|
||||
#define USERSPACE_CTRL_IO_DEVICE_NAME "elliptic_us_ctrl_io"
|
||||
struct elliptic_userspace_ctrl_device {
|
||||
struct cdev cdev;
|
||||
struct semaphore sem;
|
||||
int ping_pong_idx;
|
||||
size_t ping_pong_buffer_size[2];
|
||||
uint8_t ping_pong_buffer[2][ELLIPTIC_MSG_BUF_SIZE];
|
||||
wait_queue_head_t data_available;
|
||||
struct mutex data_lock;
|
||||
atomic_t data_state;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct elliptic_userspace_ctrl_device ctrl_device;
|
||||
|
||||
static uint8_t *get_ping_buffer(struct elliptic_userspace_ctrl_device *dev,
|
||||
/*out parameter*/ size_t *data_size)
|
||||
{
|
||||
if (data_size != NULL)
|
||||
*data_size = dev->ping_pong_buffer_size[dev->ping_pong_idx];
|
||||
|
||||
return dev->ping_pong_buffer[dev->ping_pong_idx];
|
||||
}
|
||||
|
||||
static uint8_t *get_pong_buffer(struct elliptic_userspace_ctrl_device *dev,
|
||||
/*out parameter*/ size_t *data_size)
|
||||
{
|
||||
if (data_size != NULL)
|
||||
*data_size = dev->ping_pong_buffer_size[1 - dev->ping_pong_idx];
|
||||
|
||||
return dev->ping_pong_buffer[1 - dev->ping_pong_idx];
|
||||
}
|
||||
|
||||
|
||||
static void set_pong_buffer_size(struct elliptic_userspace_ctrl_device *dev,
|
||||
size_t data_size)
|
||||
{
|
||||
dev->ping_pong_buffer_size[1 - dev->ping_pong_idx] = data_size;
|
||||
}
|
||||
|
||||
static void swap_ping_pong(struct elliptic_userspace_ctrl_device *dev)
|
||||
{
|
||||
dev->ping_pong_idx = 1 - dev->ping_pong_idx;
|
||||
}
|
||||
|
||||
static int device_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (inode->i_cdev != &ctrl_device.cdev) {
|
||||
pr_warn("elliptic : dev pointer mismatch\n");
|
||||
return -ENODEV; /* No such device */
|
||||
}
|
||||
|
||||
if (down_interruptible(&ctrl_device.sem) != 0)
|
||||
return -EEXIST;
|
||||
EL_PRINT_I("Opened device %s", USERSPACE_CTRL_IO_DEVICE_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t device_read(struct file *fp, char __user *buff,
|
||||
size_t user_buf_length, loff_t *ppos)
|
||||
{
|
||||
size_t bytes_read;
|
||||
unsigned long copy_result;
|
||||
uint8_t *ping_buffer;
|
||||
int result;
|
||||
|
||||
if (user_buf_length < ELLIPTIC_MSG_BUF_SIZE)
|
||||
EL_PRINT_E("user space buffer user_buf_length too small : %zu",
|
||||
user_buf_length);
|
||||
|
||||
bytes_read = 0;
|
||||
copy_result = 0;
|
||||
ping_buffer = NULL;
|
||||
|
||||
result = wait_event_interruptible(ctrl_device.data_available,
|
||||
atomic_read(&ctrl_device.data_state) != 0);
|
||||
if (result == 0) {
|
||||
const int state = atomic_read(&ctrl_device.data_state);
|
||||
|
||||
if (state > 0) {
|
||||
result = mutex_lock_interruptible(
|
||||
&ctrl_device.data_lock);
|
||||
if (result == 0) {
|
||||
swap_ping_pong(&ctrl_device);
|
||||
|
||||
ping_buffer = get_ping_buffer(
|
||||
&ctrl_device, &bytes_read);
|
||||
|
||||
if (bytes_read > user_buf_length) {
|
||||
EL_PRINT_E(
|
||||
"ping buffer size %zu larger than user buffer",
|
||||
bytes_read);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
copy_result = copy_to_user(buff, ping_buffer,
|
||||
bytes_read);
|
||||
if (copy_result > 0) {
|
||||
EL_PRINT_E("Failed copy to user");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
atomic_set(&ctrl_device.data_state, 0);
|
||||
|
||||
mutex_unlock(&ctrl_device.data_lock);
|
||||
} else if (result == -EINTR) {
|
||||
EL_PRINT_E("lock interrupted");
|
||||
} else {
|
||||
EL_PRINT_E("lock error = %d", result);
|
||||
}
|
||||
} else {
|
||||
EL_PRINT_W("state = %d", state);
|
||||
atomic_set(&ctrl_device.data_state, 0);
|
||||
}
|
||||
} else if (result == -ERESTARTSYS) {
|
||||
EL_PRINT_E("interrupted");
|
||||
} else {
|
||||
EL_PRINT_E("wait_event error = %d", result);
|
||||
}
|
||||
return bytes_read;
|
||||
fail:
|
||||
atomic_set(&ctrl_device.data_state, 0);
|
||||
mutex_unlock(&ctrl_device.data_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int device_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
up(&ctrl_device.sem);
|
||||
EL_PRINT_I("Closed device %s", USERSPACE_CTRL_IO_DEVICE_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations
|
||||
elliptic_userspace_ctrl_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = device_open,
|
||||
.read = device_read,
|
||||
.release = device_close,
|
||||
};
|
||||
|
||||
int elliptic_userspace_ctrl_driver_init(void)
|
||||
{
|
||||
struct device *device;
|
||||
dev_t device_number;
|
||||
int err;
|
||||
|
||||
err = alloc_chrdev_region(
|
||||
&device_number, 0, 1, USERSPACE_CTRL_IO_DEVICE_NAME);
|
||||
|
||||
if (err < 0) {
|
||||
pr_err("failed to allocate chrdev region\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
elliptic_userspace_ctrl_major = MAJOR(device_number);
|
||||
|
||||
device_number = MKDEV(elliptic_userspace_ctrl_major, 0);
|
||||
device = device_create(
|
||||
elliptic_class, NULL, device_number,
|
||||
NULL, USERSPACE_CTRL_IO_DEVICE_NAME);
|
||||
|
||||
if (IS_ERR(device)) {
|
||||
unregister_chrdev(
|
||||
elliptic_userspace_ctrl_major,
|
||||
USERSPACE_CTRL_IO_DEVICE_NAME);
|
||||
EL_PRINT_E("Failed to create the device\n");
|
||||
return PTR_ERR(device);
|
||||
}
|
||||
|
||||
cdev_init(&ctrl_device.cdev, &elliptic_userspace_ctrl_fops);
|
||||
ctrl_device.cdev.owner = THIS_MODULE;
|
||||
err = cdev_add(&ctrl_device.cdev, device_number, 1);
|
||||
if (err) {
|
||||
EL_PRINT_W("error %d while trying to add %s%d",
|
||||
err, ELLIPTIC_DEVICENAME, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
sema_init(&ctrl_device.sem, 1);
|
||||
mutex_init(&ctrl_device.data_lock);
|
||||
init_waitqueue_head(&ctrl_device.data_available);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void elliptic_userspace_ctrl_driver_exit(void)
|
||||
{
|
||||
BUG_ON(elliptic_class == NULL);
|
||||
device_destroy(elliptic_class, MKDEV(elliptic_userspace_ctrl_major, 0));
|
||||
cdev_del(&ctrl_device.cdev);
|
||||
unregister_chrdev(elliptic_userspace_ctrl_major,
|
||||
USERSPACE_CTRL_IO_DEVICE_NAME);
|
||||
up(&ctrl_device.sem);
|
||||
}
|
||||
|
||||
int32_t elliptic_userspace_ctrl_write(uint32_t message_id,
|
||||
const char *data, size_t data_size){
|
||||
uint8_t *pong_buffer;
|
||||
|
||||
if (data_size > ELLIPTIC_MSG_BUF_SIZE) {
|
||||
EL_PRINT_E("data size : %zu larger than buf size : %zu",
|
||||
data_size, (size_t)ELLIPTIC_MSG_BUF_SIZE);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&ctrl_device.data_lock);
|
||||
|
||||
pong_buffer = get_pong_buffer(&ctrl_device, NULL);
|
||||
set_pong_buffer_size(&ctrl_device, data_size);
|
||||
|
||||
memcpy(pong_buffer, data, data_size);
|
||||
wake_up_interruptible(&ctrl_device.data_available);
|
||||
atomic_set(&ctrl_device.data_state, 1);
|
||||
mutex_unlock(&ctrl_device.data_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
149
techpack/audio/dsp/elliptic/io_modules/userspace/elliptic_data_userspace_io.c
Executable file
149
techpack/audio/dsp/elliptic/io_modules/userspace/elliptic_data_userspace_io.c
Executable file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
/* includes the file structure, that is, file open read close */
|
||||
#include <linux/fs.h>
|
||||
|
||||
/* include the character device, makes cdev avilable */
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
/* includes copy_user vice versa */
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
#include <elliptic/elliptic_device.h>
|
||||
|
||||
|
||||
static dev_t elliptic_userspace_major;
|
||||
#define USERSPACE_IO_DEVICE_NAME "elliptic_us_io"
|
||||
struct elliptic_userspace_device {
|
||||
struct cdev cdev;
|
||||
struct semaphore sem;
|
||||
};
|
||||
|
||||
static struct elliptic_userspace_device io_device;
|
||||
|
||||
static int device_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (inode->i_cdev != &io_device.cdev) {
|
||||
pr_warn("elliptic : dev pointer mismatch\n");
|
||||
return -ENODEV; /* No such device */
|
||||
}
|
||||
|
||||
if (down_interruptible(&io_device.sem) != 0)
|
||||
return -EEXIST;
|
||||
EL_PRINT_I("Opened device %s", USERSPACE_IO_DEVICE_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t device_write(struct file *fp, const char __user *buff,
|
||||
size_t length, loff_t *ppos)
|
||||
{
|
||||
int push_result;
|
||||
|
||||
push_result = elliptic_data_push(
|
||||
ELLIPTIC_ALL_DEVICES, buff, length, ELLIPTIC_DATA_PUSH_FROM_USERSPACE);
|
||||
|
||||
return push_result == 0 ? (ssize_t)length : (ssize_t)(-1);
|
||||
}
|
||||
|
||||
static int device_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
up(&io_device.sem);
|
||||
EL_PRINT_I("Closed device %s", USERSPACE_IO_DEVICE_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations
|
||||
elliptic_userspace_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = device_open,
|
||||
.write = device_write,
|
||||
.release = device_close,
|
||||
};
|
||||
|
||||
int elliptic_userspace_io_driver_init(void)
|
||||
{
|
||||
struct device *device;
|
||||
dev_t device_number;
|
||||
int err;
|
||||
|
||||
err = alloc_chrdev_region(
|
||||
&device_number, 0, 1, USERSPACE_IO_DEVICE_NAME);
|
||||
|
||||
if (err < 0) {
|
||||
pr_err("failed to allocate chrdev region\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
elliptic_userspace_major = MAJOR(device_number);
|
||||
|
||||
device_number = MKDEV(elliptic_userspace_major, 0);
|
||||
device = device_create(
|
||||
elliptic_class, NULL, device_number,
|
||||
NULL, USERSPACE_IO_DEVICE_NAME);
|
||||
|
||||
if (IS_ERR(device)) {
|
||||
unregister_chrdev(
|
||||
elliptic_userspace_major, USERSPACE_IO_DEVICE_NAME);
|
||||
pr_err("Failed to create the device\n");
|
||||
return PTR_ERR(device);
|
||||
}
|
||||
|
||||
cdev_init(&io_device.cdev, &elliptic_userspace_fops);
|
||||
io_device.cdev.owner = THIS_MODULE;
|
||||
err = cdev_add(&io_device.cdev, device_number, 1);
|
||||
if (err) {
|
||||
EL_PRINT_W("error %d while trying to add %s%d",
|
||||
err, ELLIPTIC_DEVICENAME, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
sema_init(&io_device.sem, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void elliptic_userspace_io_driver_exit(void)
|
||||
{
|
||||
BUG_ON(elliptic_class == NULL);
|
||||
device_destroy(elliptic_class, MKDEV(elliptic_userspace_major, 0));
|
||||
cdev_del(&io_device.cdev);
|
||||
unregister_chrdev(elliptic_userspace_major, USERSPACE_IO_DEVICE_NAME);
|
||||
up(&io_device.sem);
|
||||
}
|
||||
|
||||
|
2
techpack/audio/dsp/elliptic/io_modules/userspace_test/Makefile
Executable file
2
techpack/audio/dsp/elliptic/io_modules/userspace_test/Makefile
Executable file
@ -0,0 +1,2 @@
|
||||
# TODO: add config parameter for which io module to build
|
||||
#obj-y += elliptic_data_io.o
|
123
techpack/audio/dsp/elliptic/io_modules/userspace_test/elliptic_data_io.c
Executable file
123
techpack/audio/dsp/elliptic/io_modules/userspace_test/elliptic_data_io.c
Executable file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
#include <elliptic/elliptic_device.h>
|
||||
|
||||
|
||||
#define USE_IRQ 11
|
||||
|
||||
static struct task_struct *simulating_task;
|
||||
static atomic_t cancel;
|
||||
|
||||
struct elliptic_data_io_state {
|
||||
};
|
||||
#define BUFFER_SIZE 128
|
||||
|
||||
static int32_t output_buffer[BUFFER_SIZE];
|
||||
|
||||
irqreturn_t irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = elliptic_data_push(ELLIPTIC_ALL_DEVICES,
|
||||
(const char *)output_buffer, BUFFER_SIZE * sizeof(int32_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void fill_buffer(int32_t *buffer, size_t len, int32_t value)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
buffer[i] = value;
|
||||
}
|
||||
|
||||
|
||||
int simulating_thread(void *context)
|
||||
{
|
||||
static int32_t count;
|
||||
int result;
|
||||
|
||||
count = 0;
|
||||
msleep(100);
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
while (atomic_read(&cancel) == 0) {
|
||||
if (kthread_should_stop())
|
||||
do_exit(0);
|
||||
|
||||
fill_buffer(output_buffer, BUFFER_SIZE, count);
|
||||
|
||||
++count;
|
||||
if (result != 0) {
|
||||
pr_warn("failed to push data\n");
|
||||
}
|
||||
asm("int $0x3B"); /* Corresponding to irq 11 */
|
||||
msleep(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t elliptic_data_io_write(uint32_t message_id, const char *data,
|
||||
size_t data_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t elliptic_data_io_transact(uint32_t message_id, const char *data,
|
||||
size_t data_size, char *output_data, size_t output_data_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void elliptic_data_io_cancel(struct elliptic_data *elliptic_data)
|
||||
{
|
||||
atomic_set(&elliptic_data->abort_io, 1);
|
||||
wake_up_interruptible(&elliptic_data->fifo_isr_not_empty);
|
||||
}
|
||||
|
||||
|
||||
int elliptic_data_io_initialize(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
atomic_set(&cancel, 0);
|
||||
simulating_task = kthread_run(&simulating_thread, NULL,
|
||||
"el_simulating_thread");
|
||||
|
||||
|
||||
if (request_irq(USE_IRQ, irq_handler, IRQF_SHARED, "my_device",
|
||||
(void *)(irq_handler))) {
|
||||
pr_debug("my_device: cannot register IRQ ");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elliptic_data_io_cleanup(void)
|
||||
{
|
||||
free_irq(USE_IRQ, (void *)(irq_handler));
|
||||
kthread_stop(simulating_task);
|
||||
atomic_set(&cancel, 1);
|
||||
msleep(200);
|
||||
return 0;
|
||||
}
|
42
techpack/audio/include/dsp/apr_elliptic.h
Executable file
42
techpack/audio/include/dsp/apr_elliptic.h
Executable file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <dsp/apr_audio-v2.h>
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define ELLIPTIC_SET_PARAMS_SIZE 114
|
||||
#define ELLIPTIC_ULTRASOUND_MODULE_TX 0x0F010201
|
||||
#define ELLIPTIC_ULTRASOUND_MODULE_RX 0x0FF10202
|
||||
#define ULTRASOUND_OPCODE 0x0FF10204
|
||||
|
||||
/* This need to be updated for all platforms */
|
||||
#define ELLIPTIC_PORT_ID AFE_PORT_ID_TX_CODEC_DMA_TX_4
|
||||
|
||||
/** Sequence of Elliptic Labs Ultrasound module parameters */
|
||||
struct afe_ultrasound_set_params_t {
|
||||
uint32_t payload[ELLIPTIC_SET_PARAMS_SIZE];
|
||||
} __packed;
|
||||
|
||||
/** Sequence of Elliptic Labs Ultrasound module parameters */
|
||||
|
||||
/** Elliptic APR public */
|
||||
|
||||
int32_t ultrasound_apr_set_parameter(int32_t port_id, uint32_t param_id,
|
||||
u8 *user_params, int32_t length);
|
||||
|
||||
int32_t elliptic_process_apr_payload(uint32_t *payload);
|
||||
|
||||
int elliptic_notify_gain_change_msg(int component_id, int gaindb);
|
||||
|
||||
typedef struct afe_ultrasound_state {
|
||||
atomic_t us_apr_state;
|
||||
void **ptr_apr;
|
||||
atomic_t *ptr_status;
|
||||
atomic_t *ptr_state;
|
||||
wait_queue_head_t *ptr_wait;
|
||||
struct mutex *ptr_afe_apr_lock;
|
||||
int timeout_ms;
|
||||
} afe_ultrasound_state_t;
|
||||
|
||||
extern afe_ultrasound_state_t elus_afe;
|
155
techpack/audio/include/elliptic/elliptic_data_io.h
Executable file
155
techpack/audio/include/elliptic/elliptic_data_io.h
Executable file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs 2015-2016
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define ELLIPTIC_DATA_IO_AP_TO_DSP 0
|
||||
#define ELLIPTIC_DATA_IO_DSP_TO_AP 1
|
||||
|
||||
#define ELLIPTIC_DATA_IO_READ_OK 0
|
||||
#define ELLIPTIC_DATA_IO_READ_BUSY 1
|
||||
#define ELLIPTIC_DATA_IO_READ_CANCEL 2
|
||||
|
||||
#define ELLIPTIC_MSG_BUF_SIZE 512
|
||||
|
||||
/* wake source timeout in ms*/
|
||||
#define ELLIPTIC_WAKEUP_TIMEOUT 250
|
||||
|
||||
#define ELLIPTIC_DATA_FIFO_SIZE (PAGE_SIZE)
|
||||
|
||||
#define ULTRASOUND_RX_PORT_ID 0
|
||||
#define ULTRASOUND_TX_PORT_ID 1
|
||||
|
||||
/* Elliptic Labs UltraSound Module */
|
||||
#define ELLIPTIC_ULTRASOUND_DISABLE 0
|
||||
#define ELLIPTIC_ULTRASOUND_ENABLE 1
|
||||
#define ELLIPTIC_ULTRASOUND_SET_PARAMS 2
|
||||
#define ELLIPTIC_ULTRASOUND_GET_PARAMS 3
|
||||
#define ELLIPTIC_ULTRASOUND_RAMP_DOWN 4
|
||||
|
||||
/** Param ID definition */
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_ENGINE_DATA 3
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_CALIBRATION_DATA 11
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_ENGINE_VERSION 12
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_BUILD_BRANCH 14
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_CALIBRATION_V2_DATA 15
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_SENSORHUB 16
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_DIAGNOSTICS_DATA 17
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_TAG 18
|
||||
#define ELLIPTIC_ULTRASOUND_PARAM_ID_ML_DATA 19
|
||||
|
||||
#define ELLIPTIC_DATA_READ_BUSY 0
|
||||
#define ELLIPTIC_DATA_READ_OK 1
|
||||
#define ELLIPTIC_DATA_READ_CANCEL 2
|
||||
|
||||
#define ELLIPTIC_ALL_DEVICES -1
|
||||
#define ELLIPTIC_DEVICE_0 0
|
||||
#define ELLIPTIC_DEVICE_1 1
|
||||
|
||||
enum elliptic_message_id {
|
||||
ELLIPTIC_MESSAGE_PAYLOAD, /* Input to AP*/
|
||||
ELLIPTIC_MESSAGE_RAW, /* Output from AP*/
|
||||
ELLIPTIC_MESSAGE_CALIBRATION,
|
||||
ELLIPTIC_MESSAGE_CALIBRATION_V2,
|
||||
ELLIPTIC_MESSAGE_DIAGNOSTICS,
|
||||
ELLIPTIC_MAX_MESSAGE_IDS
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ELLIPTIC_DATA_PUSH_FROM_KERNEL,
|
||||
ELLIPTIC_DATA_PUSH_FROM_USERSPACE
|
||||
} elliptic_data_push_t;
|
||||
|
||||
struct elliptic_data {
|
||||
/* wake lock timeout */
|
||||
unsigned int wakeup_timeout;
|
||||
|
||||
/* members for top half interrupt handling */
|
||||
struct kfifo fifo_isr;
|
||||
spinlock_t fifo_isr_spinlock;
|
||||
wait_queue_head_t fifo_isr_not_empty;
|
||||
struct mutex user_buffer_lock;
|
||||
|
||||
/* buffer to swap data from isr fifo to userspace */
|
||||
uint8_t isr_swap_buffer[ELLIPTIC_MSG_BUF_SIZE];
|
||||
|
||||
atomic_t abort_io;
|
||||
|
||||
/* debug counters, reset between open/close */
|
||||
uint32_t isr_fifo_discard;
|
||||
|
||||
/* debug counters, persistent */
|
||||
uint32_t isr_fifo_discard_total;
|
||||
uint32_t userspace_read_total;
|
||||
uint32_t isr_write_total;
|
||||
|
||||
};
|
||||
|
||||
/* Elliptic IO module API (implemented by IO module)*/
|
||||
|
||||
int elliptic_data_io_initialize(void);
|
||||
int elliptic_data_io_cleanup(void);
|
||||
|
||||
int32_t elliptic_data_io_write(uint32_t message_id, const char *data,
|
||||
size_t data_size);
|
||||
|
||||
int32_t elliptic_data_io_transact(uint32_t message_id, const char *data,
|
||||
size_t data_size, char *output_data, size_t output_data_size);
|
||||
|
||||
|
||||
/* Elliptic driver API (implemented by main driver)*/
|
||||
int elliptic_data_initialize(struct elliptic_data *,
|
||||
size_t max_queue_size, unsigned int wakeup_timeout, int id);
|
||||
|
||||
int elliptic_data_cleanup(struct elliptic_data *);
|
||||
|
||||
void elliptic_data_reset_debug_counters(struct elliptic_data *);
|
||||
void elliptic_data_update_debug_counters(struct elliptic_data *);
|
||||
void elliptic_data_print_debug_counters(struct elliptic_data *);
|
||||
|
||||
/* Called from elliptic device read */
|
||||
size_t elliptic_data_pop(struct elliptic_data *,
|
||||
char __user *buffer, size_t buffer_size);
|
||||
|
||||
/* Used for cancelling a blocking read */
|
||||
void elliptic_data_cancel(struct elliptic_data *);
|
||||
|
||||
/* Called from IO module*/
|
||||
int elliptic_data_push(int deviceid, const char *buffer, size_t buffer_size, elliptic_data_push_t);
|
||||
|
||||
/* Writes to io module and user space control */
|
||||
int32_t elliptic_data_write(uint32_t message_id,
|
||||
const char *data, size_t data_size);
|
||||
|
||||
/* Opens port */
|
||||
int elliptic_open_port(int portid);
|
||||
|
||||
/* Closes port */
|
||||
int elliptic_close_port(int portid);
|
||||
|
||||
/* Opens port */
|
||||
int elliptic_io_open_port(int portid);
|
||||
|
||||
/* Closes port */
|
||||
int elliptic_io_close_port(int portid);
|
||||
|
||||
/* Create device node for userspace io driver*/
|
||||
int elliptic_userspace_io_driver_init(void);
|
||||
void elliptic_userspace_io_driver_exit(void);
|
||||
|
||||
/* Create device node for userspace io driver*/
|
||||
int elliptic_userspace_ctrl_driver_init(void);
|
||||
void elliptic_userspace_ctrl_driver_exit(void);
|
||||
int32_t elliptic_userspace_ctrl_write(uint32_t message_id,
|
||||
const char *data, size_t data_size);
|
||||
|
55
techpack/audio/include/elliptic/elliptic_device.h
Executable file
55
techpack/audio/include/elliptic/elliptic_device.h
Executable file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright Elliptic Labs
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <elliptic/elliptic_data_io.h>
|
||||
|
||||
#define ELLIPTIC_DEVICENAME "elliptic"
|
||||
#define ELLIPTIC_NUM_DEVICES 2
|
||||
|
||||
#define IOCTL_ELLIPTIC_APP 197
|
||||
#define MIRROR_TAG 0x3D0A4842
|
||||
|
||||
#define IOCTL_ELLIPTIC_DATA_IO_CANCEL \
|
||||
_IO(IOCTL_ELLIPTIC_APP, 2)
|
||||
|
||||
#define IOCTL_ELLIPTIC_ACTIVATE_ENGINE \
|
||||
_IOW(IOCTL_ELLIPTIC_APP, 3, int)
|
||||
|
||||
#define IOCTL_ELLIPTIC_SET_RAMP_DOWN \
|
||||
_IO(IOCTL_ELLIPTIC_APP, 4)
|
||||
|
||||
#define IOCTL_ELLIPTIC_SYSTEM_CONFIGURATION \
|
||||
_IOW(IOCTL_ELLIPTIC_APP, 5, int)
|
||||
|
||||
#define IOCTL_ELLIPTIC_DATA_IO_MIRROR \
|
||||
_IOW(IOCTL_ELLIPTIC_APP, 117, unsigned char *)
|
||||
|
||||
struct elliptic_device {
|
||||
int opened;
|
||||
struct cdev cdev;
|
||||
struct semaphore sem;
|
||||
struct device *device;
|
||||
struct elliptic_data el_data;
|
||||
};
|
||||
|
||||
extern struct class *elliptic_class;
|
||||
|
||||
#define EL_PRINT_E(string, arg...) \
|
||||
pr_err("[ELUS] : (%s) : " string "\n", __func__, ##arg)
|
||||
|
||||
#define EL_PRINT_W(string, arg...) \
|
||||
pr_warn("[ELUS] : (%s) : " string "\n", __func__, ##arg)
|
||||
|
||||
#define EL_PRINT_I(string, arg...) \
|
||||
pr_info("[ELUS] : (%s) : " string "\n", __func__, ##arg)
|
||||
|
||||
#define EL_PRINT_D(string, arg...) \
|
||||
pr_debug("[ELUS] : (%s) : " string "\n", __func__, ##arg)
|
||||
|
190
techpack/audio/include/elliptic/elliptic_mixer_controls.h
Executable file
190
techpack/audio/include/elliptic/elliptic_mixer_controls.h
Executable file
@ -0,0 +1,190 @@
|
||||
#pragma once
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
#define ELLIPTIC_OBJ_ID_CALIBRATION_DATA 1
|
||||
#define ELLIPTIC_OBJ_ID_VERSION_INFO 2
|
||||
#define ELLIPTIC_OBJ_ID_BRANCH_INFO 3
|
||||
#define ELLIPTIC_OBJ_ID_CALIBRATION_V2_DATA 4
|
||||
#define ELLIPTIC_OBJ_ID_DIAGNOSTICS_DATA 5
|
||||
#define ELLIPTIC_OBJ_ID_TAG_INFO 6
|
||||
#define ELLIPTIC_OBJ_ID_ML_DATA 7
|
||||
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_SIZE 96
|
||||
#define ELLIPTIC_CALIBRATION_DATA_SIZE 64
|
||||
#define ELLIPTIC_CALIBRATION_V2_DATA_SIZE 448
|
||||
#define ELLIPTIC_DIAGNOSTICS_DATA_SIZE 448
|
||||
#define ELLIPTIC_DIAGNOSTICS_U32_DATA_VALUES (ELLIPTIC_DIAGNOSTICS_DATA_SIZE>>2)
|
||||
#define ELLIPTIC_SENSOR_DATA_SIZE 68
|
||||
#define ELLIPTIC_SENSOR_U32_DATA_VALUES (ELLIPTIC_SENSOR_DATA_SIZE>>2)
|
||||
#define ELLIPTIC_VERSION_INFO_SIZE 16
|
||||
#define ELLIPTIC_BRANCH_INFO_SIZE 32
|
||||
#define ELLIPTIC_BRANCH_INFO_MAX_SIZE 128
|
||||
#define ELLIPTIC_TAG_INFO_SIZE 32
|
||||
#define ELLIPTIC_ML_DATA_SIZE 432
|
||||
|
||||
#define ELLIPTIC_ULTRASOUND_DISABLE 0
|
||||
#define ELLIPTIC_ULTRASOUND_ENABLE 1
|
||||
#define ELLIPTIC_ULTRASOUND_SET_PARAMS 2
|
||||
#define ELLIPTIC_ULTRASOUND_GET_PARAMS 3
|
||||
#define ELLIPTIC_ULTRASOUND_RAMP_DOWN 4
|
||||
|
||||
/** register */
|
||||
#define ELLIPTIC_CALIBRATION 1
|
||||
/** bits */
|
||||
#define ELLIPTIC_CALIBRATION_STATE 0
|
||||
#define ELLIPTIC_CALIBRATION_PROFILE 1
|
||||
#define ELLIPTIC_ULTRASOUND_GAIN 2
|
||||
|
||||
/** custom settings */
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_COUNT 16
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_MAX_VALUE 0x7FFFFFFF
|
||||
|
||||
|
||||
/** register */
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION 0
|
||||
/** bits */
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_LATENCY 0
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_SENSITIVITY 1
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_SPEAKER_SCALING 2
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_MICROPHONE_INDEX 3
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_OPERATION_MODE 4
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_OPERATION_MODE_FLAGS 5
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_LOG_LEVEL 6
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_0 7
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_1 8
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_2 9
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_3 10
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_4 11
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_5 12
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_6 13
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_7 14
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_8 15
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_9 16
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_10 17
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_11 18
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_12 19
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_13 20
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_14 21
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_15 22
|
||||
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_SUSPEND 23
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_INPUT_ENABLED 24
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_OUTPUT_ENABLED 25
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_EXTERNAL_EVENT 26
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CALIBRATION_METHOD 27
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_DEBUG_MODE 28
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_NUMBER_OF_RUNS 29
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CONTEXT 30
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_CAPTURE 31
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_INPUT_CHANNELS 32
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_REPORT_NONE 33
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_RE_SEND 34
|
||||
#define ELLIPTIC_SYSTEM_CONFIGURATION_MAX_CONTEXT_VALUE 0x7FFFFFFF
|
||||
|
||||
|
||||
struct elliptic_engine_version_info {
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t build;
|
||||
uint32_t revision;
|
||||
};
|
||||
|
||||
struct elliptic_shared_data_block {
|
||||
uint32_t object_id;
|
||||
size_t size;
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
struct elliptic_shared_data_block *elliptic_get_shared_obj(uint32_t
|
||||
object_id);
|
||||
|
||||
extern unsigned int elliptic_add_component_controls(void *platform);
|
||||
|
||||
void elliptic_set_calibration_data(uint8_t *calib_data, size_t size);
|
||||
|
||||
enum elliptic_system_configuration_parameter_type {
|
||||
|
||||
ESCPT_SPEAKER_SCALING = 1,
|
||||
ESCPT_CHANNEL_SENSITIVITY,
|
||||
ESCPT_LATENCY,
|
||||
ESCPT_MICROPHONE_INDEX,
|
||||
ESCPT_OPERATION_MODE,
|
||||
ESCPT_OPERATION_MODE_FLAGS,
|
||||
ESCPT_COMPONENT_GAIN_CHANGE,
|
||||
ESCPT_CALIBRATION_STATE,
|
||||
ESCPT_ENGINE_VERSION,
|
||||
ESCPT_CALIBRATION_PROFILE,
|
||||
ESCPT_ULTRASOUND_GAIN,
|
||||
ESCPT_LOG_LEVEL,
|
||||
ESCPT_BUILD_BRANCH,
|
||||
ESCPT_FSELECTION,
|
||||
ESCPT_ENGINE_DIAGNOSTICS,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_0,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_1,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_2,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_3,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_4,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_5,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_6,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_7,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_8,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_9,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_10,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_11,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_12,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_13,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_14,
|
||||
ESCPT_ENGINE_CUSTOM_SETTING_15,
|
||||
ESCPT_SUSPEND, // 32
|
||||
ESCPT_INPUT_ENABLED,
|
||||
ESCPT_OUTPUT_ENABLED,
|
||||
ESCPT_EXTERNAL_EVENT,
|
||||
ESCPT_ENGINE_TAG, //36
|
||||
ESCPT_CALIBRATION_METHOD,
|
||||
ESCPT_DEBUG_MODE,
|
||||
ESCPT_NUMBER_OF_RUNS,
|
||||
ESCPT_CONTEXT,
|
||||
ESCPT_CAPTURE,
|
||||
ESCPT_INPUT_CHANNELS,
|
||||
ESCPT_RE_SEND=255,
|
||||
};
|
||||
|
||||
struct elliptic_system_configuration_parameters_cache {
|
||||
int32_t speaker_scaling[2];
|
||||
int32_t sensitivity;
|
||||
int32_t latency;
|
||||
int32_t microphone_index;
|
||||
int32_t operation_mode;
|
||||
int32_t operation_mode_flags;
|
||||
int32_t component_gain_change;
|
||||
int32_t calibration_state;
|
||||
int32_t engine_version;
|
||||
int32_t calibration_profile;
|
||||
int32_t ultrasound_gain;
|
||||
int32_t log_level;
|
||||
int32_t custom_settings[ELLIPTIC_SYSTEM_CONFIGURATION_CUSTOM_SETTING_COUNT];
|
||||
int32_t engine_suspend;
|
||||
int32_t input_enabled;
|
||||
int32_t output_enabled;
|
||||
int32_t external_event;
|
||||
int32_t calibration_method;
|
||||
int32_t debug_mode;
|
||||
int32_t number_of_runs;
|
||||
int32_t context;
|
||||
int32_t capture;
|
||||
int32_t input_channels;
|
||||
int32_t re_send;
|
||||
};
|
||||
|
||||
|
||||
int elliptic_trigger_version_msg(void);
|
||||
|
||||
int elliptic_trigger_branch_msg(void);
|
||||
|
||||
int elliptic_trigger_tag_msg(void);
|
||||
|
||||
int elliptic_trigger_diagnostics_msg(void);
|
15
techpack/audio/include/elliptic/elliptic_sysfs.h
Executable file
15
techpack/audio/include/elliptic/elliptic_sysfs.h
Executable file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#define ELLIPTIC_SYSFS_ENGINE_FOLDER "engine"
|
||||
#define ELLIPTIC_SYSFS_ROOT_FOLDER "elliptic"
|
||||
#define ELLIPTIC_SYSFS_CALIBRATION_FILENAME "calibration"
|
||||
#define ELLIPTIC_SYSFS_VERSION_FILENAME "version"
|
||||
#define ELLIPTIC_SYSFS_CALIBRATION_V2_FILENAME "calibration_v2"
|
||||
#define ELLIPTIC_SYSFS_STATE_FILENAME "state"
|
||||
#define ELLIPTIC_SYSFS_TAG_FILENAME "tag"
|
||||
#define ELLIPTIC_SYSFS_OPMODE_FILENAME "opmode"
|
||||
#define ELLIPTIC_SYSFS_OPMODE_FLAGS_FILENAME "opmode_flags"
|
||||
|
||||
|
||||
int elliptic_initialize_sysfs(void);
|
||||
void elliptic_cleanup_sysfs(void);
|
Loading…
Reference in New Issue
Block a user