You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
5.2 KiB
193 lines
5.2 KiB
/*
|
|
** =============================================================================
|
|
** Copyright (c) 2017 Texas Instruments Inc.
|
|
**
|
|
** This program is free software; you can redistribute it and/or modify it under
|
|
** the terms of the GNU General Public License as published by the Free Software
|
|
** Foundation; version 2.
|
|
**
|
|
** This program is distributed in the hope that it will be useful, but WITHOUT
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
**
|
|
** File:
|
|
** tas25xx-calib.c
|
|
**
|
|
** Description:
|
|
** misc driver for interfacing for Texas Instruments TAS2560 algorithm
|
|
**
|
|
** =============================================================================
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "%s: " fmt, __func__
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/version.h>
|
|
#include <linux/device.h>
|
|
#include <linux/string.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/semaphore.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/miscdevice.h>
|
|
#include <dsp/smart_amp.h>
|
|
|
|
/* Holds the Packet data required for processing */
|
|
struct tas_dsp_pkt {
|
|
u8 slave_id;
|
|
u8 book;
|
|
u8 page;
|
|
u8 offset;
|
|
u8 data[TAS_PAYLOAD_SIZE * 4];
|
|
};
|
|
|
|
static int smartamp_params_ctrl(uint8_t *input, u8 dir, u8 count)
|
|
{
|
|
u32 length = count / 4;
|
|
u32 paramid = 0;
|
|
u32 index;
|
|
int ret = 0;
|
|
int special_index = 0;
|
|
struct tas_dsp_pkt *ppacket;
|
|
|
|
ppacket = (struct tas_dsp_pkt*)kmalloc (sizeof(struct tas_dsp_pkt), GFP_KERNEL);
|
|
if (!ppacket) {
|
|
pr_err ("[TI-SmartPA:%s] pperror kmalloc failed!", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memset(ppacket, 0, sizeof(struct tas_dsp_pkt));
|
|
ret = copy_from_user (ppacket, input, sizeof(struct tas_dsp_pkt));
|
|
if (ret){
|
|
pr_err("[TI-SmartPA:%s] Error copying from user\n", __func__);
|
|
kfree (ppacket);
|
|
return -EFAULT;
|
|
}
|
|
|
|
index = (ppacket->page - 1) * 30 + (ppacket->offset - 8) / 4;
|
|
special_index = TAS_SA_IS_SPL_IDX(index);
|
|
pr_info("[TI-SmartPA:%s] index = %d", __func__, index);
|
|
if (special_index == 0) {
|
|
if (index > MAX_DSP_PARAM_INDEX) {
|
|
pr_err("[TI-SmartPA:%s] invalid index !\n", __func__);
|
|
kfree(ppacket);
|
|
return -1;
|
|
}
|
|
}
|
|
pr_info("[TI-SmartPA:%s] Valid Index. special = %s\n", __func__, special_index ? "Yes" : "No");
|
|
|
|
/* speakers are differentiated by slave ids */
|
|
if (ppacket->slave_id == SLAVE1 )
|
|
{
|
|
paramid = (paramid | (index ) | (length << 16) | (1 << 24));
|
|
pr_info("[TI-SmartPA:%s] Rcvd Slave id for slave 1, %x\n", __func__, ppacket->slave_id);
|
|
}else if (ppacket->slave_id == SLAVE2 )
|
|
{
|
|
paramid = (paramid | (index ) | (length << 16) | (2 << 24));
|
|
pr_info("[TI-SmartPA:%s] Rcvd Slave id for slave 2, %x\n", __func__, ppacket->slave_id);
|
|
}else{
|
|
pr_err("[TI-SmartPA:%s] Wrong slaveid = %x\n", __func__, ppacket->slave_id);
|
|
}
|
|
|
|
/*
|
|
* Note: In any case calculated paramid should not match with
|
|
* AFE_PARAM_ID_ENABLE and AFE_PARAM_ID_SMARTAMP_DEFAULT
|
|
*/
|
|
if (paramid == CAPI_V2_TAS_TX_ENABLE ||
|
|
paramid == CAPI_V2_TAS_TX_CFG ||
|
|
paramid == CAPI_V2_TAS_RX_ENABLE ||
|
|
paramid == CAPI_V2_TAS_RX_CFG )
|
|
{
|
|
pr_err("[TI-SmartPA:%s] %s Slave 0x%x params failed, paramid mismatch\n", __func__,
|
|
dir == TAS_GET_PARAM ? "get" : "set", ppacket->slave_id);
|
|
kfree(ppacket);
|
|
return -1;
|
|
}
|
|
|
|
ret = afe_smartamp_algo_ctrl(ppacket->data, paramid,
|
|
dir, length * 4, AFE_SMARTAMP_MODULE_RX);
|
|
if (ret)
|
|
pr_err("[TI-SmartPA:%s] %s Slave 0x%x params failed from afe, ret=%x\n", __func__,
|
|
dir == TAS_GET_PARAM ? "get" : "set", ppacket->slave_id, ret);
|
|
else
|
|
pr_info("[TI-SmartPA:%s] Algo control returned %d\n", __func__, ret);
|
|
|
|
if (dir == TAS_GET_PARAM) {
|
|
ret = copy_to_user(input, ppacket, sizeof(struct tas_dsp_pkt));
|
|
if (ret) {
|
|
pr_err("[TI-SmartPA:%s] Error copying to user after DSP", __func__);
|
|
ret = -EFAULT;
|
|
}
|
|
}
|
|
|
|
kfree(ppacket);
|
|
return ret;
|
|
}
|
|
|
|
static int tas_calib_open(struct inode *inode, struct file *fd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tas_calib_write(struct file *file,
|
|
const char __user *buffer, size_t count, loff_t *offp)
|
|
{
|
|
int rc = 0;
|
|
rc = smartamp_params_ctrl((uint8_t *)buffer, TAS_SET_PARAM, count);
|
|
return rc;
|
|
}
|
|
|
|
static ssize_t tas_calib_read(struct file *file, char __user *buffer,
|
|
size_t count, loff_t *ptr)
|
|
{
|
|
int rc;
|
|
rc = smartamp_params_ctrl((uint8_t *)buffer, TAS_GET_PARAM, count);
|
|
if (rc < 0)
|
|
count = rc;
|
|
return count;
|
|
}
|
|
|
|
static long tas_calib_ioctl(struct file *filp, uint cmd, ulong arg)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int tas_calib_release(struct inode *inode, struct file *fd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
const struct file_operations tas_calib_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tas_calib_open,
|
|
.write = tas_calib_write,
|
|
.read = tas_calib_read,
|
|
.release = tas_calib_release,
|
|
.unlocked_ioctl = tas_calib_ioctl,
|
|
};
|
|
|
|
static struct miscdevice tas_calib_misc = {
|
|
.minor = MISC_DYNAMIC_MINOR,
|
|
.name = "tas_calib",
|
|
.fops = &tas_calib_fops,
|
|
};
|
|
|
|
int tas_calib_init(void)
|
|
{
|
|
int rc;
|
|
pr_err("[TI-SmartPA:%s]",__func__);
|
|
rc = misc_register(&tas_calib_misc);
|
|
if (rc)
|
|
pr_err("[TI-SmartPA:%s] register calib misc failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
void tas_calib_exit(void)
|
|
{
|
|
misc_deregister(&tas_calib_misc);
|
|
}
|
|
|
|
MODULE_AUTHOR("Texas Instruments Inc.");
|
|
MODULE_DESCRIPTION("TAS25XX Misc driver");
|
|
MODULE_LICENSE("GPL v2");
|
|
|