mirror of
https://github.com/torvalds/linux
synced 2024-10-28 06:09:03 +00:00
Staging: sst: add ioctls for post processing algorithm interface
This patch adds two new ioctls to intel_sst_ctrl device. This i/f can be used by application to send algorithm parameters Signed-off-by: Vinod Koul <vinod.koul@intel.com> [This will need further discussion in the context of the final ALSA interface but is fine for staging, ie anyone who relies on it should expect changes Also fixed a missing kmalloc fail check] Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
79a35ad573
commit
62877913ba
|
@ -306,19 +306,19 @@ static int __devinit intel_sst_probe(struct pci_dev *pci,
|
|||
goto do_unmap_dram;
|
||||
pr_debug("Registered IRQ 0x%x\n", pci->irq);
|
||||
|
||||
/*Register LPE Control as misc driver*/
|
||||
ret = misc_register(&lpe_ctrl);
|
||||
if (ret) {
|
||||
pr_err("couldn't register control device\n");
|
||||
goto do_free_irq;
|
||||
}
|
||||
|
||||
if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
|
||||
ret = misc_register(&lpe_dev);
|
||||
if (ret) {
|
||||
pr_err("couldn't register LPE device\n");
|
||||
goto do_free_irq;
|
||||
}
|
||||
|
||||
/*Register LPE Control as misc driver*/
|
||||
ret = misc_register(&lpe_ctrl);
|
||||
if (ret) {
|
||||
pr_err("couldn't register misc driver\n");
|
||||
goto do_free_irq;
|
||||
}
|
||||
pr_err("couldn't register misc driver\n");
|
||||
goto do_free_misc;
|
||||
}
|
||||
}
|
||||
sst_drv_ctx->lpe_stalled = 0;
|
||||
pm_runtime_set_active(&pci->dev);
|
||||
|
@ -327,6 +327,8 @@ static int __devinit intel_sst_probe(struct pci_dev *pci,
|
|||
pr_debug("...successfully done!!!\n");
|
||||
return ret;
|
||||
|
||||
do_free_misc:
|
||||
misc_deregister(&lpe_ctrl);
|
||||
do_free_irq:
|
||||
free_irq(pci->irq, sst_drv_ctx);
|
||||
do_unmap_dram:
|
||||
|
@ -371,10 +373,9 @@ static void __devexit intel_sst_remove(struct pci_dev *pci)
|
|||
mutex_lock(&sst_drv_ctx->sst_lock);
|
||||
sst_drv_ctx->sst_state = SST_UN_INIT;
|
||||
mutex_unlock(&sst_drv_ctx->sst_lock);
|
||||
if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
|
||||
misc_deregister(&lpe_ctrl);
|
||||
if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
|
||||
misc_deregister(&lpe_dev);
|
||||
misc_deregister(&lpe_ctrl);
|
||||
}
|
||||
free_irq(pci->irq, sst_drv_ctx);
|
||||
iounmap(sst_drv_ctx->dram);
|
||||
iounmap(sst_drv_ctx->iram);
|
||||
|
|
|
@ -827,6 +827,141 @@ static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sst_create_algo_ipc - create ipc msg for algorithm parameters
|
||||
*
|
||||
* @algo_params: Algorithm parameters
|
||||
* @msg: post msg pointer
|
||||
*
|
||||
* This function is called to create ipc msg
|
||||
*/
|
||||
int sst_create_algo_ipc(struct snd_ppp_params *algo_params,
|
||||
struct ipc_post **msg)
|
||||
{
|
||||
if (sst_create_large_msg(msg))
|
||||
return -ENOMEM;
|
||||
sst_fill_header(&(*msg)->header,
|
||||
IPC_IA_ALG_PARAMS, 1, algo_params->str_id);
|
||||
(*msg)->header.part.data = sizeof(u32) +
|
||||
sizeof(*algo_params) + algo_params->size;
|
||||
memcpy((*msg)->mailbox_data, &(*msg)->header, sizeof(u32));
|
||||
memcpy((*msg)->mailbox_data + sizeof(u32),
|
||||
algo_params, sizeof(*algo_params));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* sst_send_algo_ipc - send ipc msg for algorithm parameters
|
||||
*
|
||||
* @msg: post msg pointer
|
||||
*
|
||||
* This function is called to send ipc msg
|
||||
*/
|
||||
int sst_send_algo_ipc(struct ipc_post **msg)
|
||||
{
|
||||
sst_drv_ctx->ppp_params_blk.condition = false;
|
||||
sst_drv_ctx->ppp_params_blk.ret_code = 0;
|
||||
sst_drv_ctx->ppp_params_blk.on = true;
|
||||
sst_drv_ctx->ppp_params_blk.data = NULL;
|
||||
spin_lock(&sst_drv_ctx->list_spin_lock);
|
||||
list_add_tail(&(*msg)->node, &sst_drv_ctx->ipc_dispatch_list);
|
||||
spin_unlock(&sst_drv_ctx->list_spin_lock);
|
||||
sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
|
||||
return sst_wait_interruptible_timeout(sst_drv_ctx,
|
||||
&sst_drv_ctx->ppp_params_blk, SST_BLOCK_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_sst_ioctl_dsp - recieves the device ioctl's
|
||||
*
|
||||
* @cmd:Ioctl cmd
|
||||
* @arg:data
|
||||
*
|
||||
* This function is called when a user space component
|
||||
* sends a DSP Ioctl to SST driver
|
||||
*/
|
||||
long intel_sst_ioctl_dsp(unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int retval = 0;
|
||||
struct snd_ppp_params algo_params;
|
||||
struct snd_ppp_params *algo_params_copied;
|
||||
struct ipc_post *msg;
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case _IOC_NR(SNDRV_SST_SET_ALGO):
|
||||
if (copy_from_user(&algo_params, (void __user *)arg,
|
||||
sizeof(algo_params)))
|
||||
return -EFAULT;
|
||||
if (algo_params.size > SST_MAILBOX_SIZE)
|
||||
return -EMSGSIZE;
|
||||
|
||||
pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
|
||||
algo_params.algo_id, algo_params.str_id,
|
||||
algo_params.enable, algo_params.size);
|
||||
retval = sst_create_algo_ipc(&algo_params, &msg);
|
||||
if (retval)
|
||||
break;
|
||||
algo_params.reserved = 0;
|
||||
if (copy_from_user(msg->mailbox_data + sizeof(algo_params),
|
||||
algo_params.params, algo_params.size))
|
||||
return -EFAULT;
|
||||
|
||||
retval = sst_send_algo_ipc(&msg);
|
||||
if (retval) {
|
||||
pr_debug("Error in sst_set_algo = %d\n", retval);
|
||||
retval = -EIO;
|
||||
}
|
||||
break;
|
||||
|
||||
case _IOC_NR(SNDRV_SST_GET_ALGO):
|
||||
if (copy_from_user(&algo_params, (void __user *)arg,
|
||||
sizeof(algo_params)))
|
||||
return -EFAULT;
|
||||
pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
|
||||
algo_params.algo_id, algo_params.str_id,
|
||||
algo_params.enable, algo_params.size);
|
||||
retval = sst_create_algo_ipc(&algo_params, &msg);
|
||||
if (retval)
|
||||
break;
|
||||
algo_params.reserved = 1;
|
||||
retval = sst_send_algo_ipc(&msg);
|
||||
if (retval) {
|
||||
pr_debug("Error in sst_get_algo = %d\n", retval);
|
||||
retval = -EIO;
|
||||
break;
|
||||
}
|
||||
algo_params_copied = (struct snd_ppp_params *)
|
||||
sst_drv_ctx->ppp_params_blk.data;
|
||||
if (algo_params_copied->size > algo_params.size) {
|
||||
pr_debug("mem insufficient to copy\n");
|
||||
retval = -EMSGSIZE;
|
||||
goto free_mem;
|
||||
} else {
|
||||
char __user *tmp;
|
||||
|
||||
if (copy_to_user(algo_params.params,
|
||||
algo_params_copied->params,
|
||||
algo_params_copied->size)) {
|
||||
retval = -EFAULT;
|
||||
goto free_mem;
|
||||
}
|
||||
tmp = (char __user *)arg + offsetof(
|
||||
struct snd_ppp_params, size);
|
||||
if (copy_to_user(tmp, &algo_params_copied->size,
|
||||
sizeof(__u32))) {
|
||||
retval = -EFAULT;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
}
|
||||
free_mem:
|
||||
kfree(algo_params_copied->params);
|
||||
kfree(algo_params_copied);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_sst_ioctl - receives the device ioctl's
|
||||
* @file_ptr:pointer to file
|
||||
|
@ -1270,6 +1405,14 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
|
|||
kfree(fw_info);
|
||||
break;
|
||||
}
|
||||
case _IOC_NR(SNDRV_SST_GET_ALGO):
|
||||
case _IOC_NR(SNDRV_SST_SET_ALGO):
|
||||
if (minor != AM_MODULE) {
|
||||
retval = -EBADRQC;
|
||||
break;
|
||||
}
|
||||
retval = intel_sst_ioctl_dsp(cmd, arg);
|
||||
break;
|
||||
default:
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
|
|
@ -392,7 +392,7 @@ struct intel_sst_drv {
|
|||
|
||||
struct stream_info streams[MAX_NUM_STREAMS];
|
||||
struct stream_alloc_block alloc_block[MAX_ACTIVE_STREAM];
|
||||
struct sst_block tgt_dev_blk, fw_info_blk,
|
||||
struct sst_block tgt_dev_blk, fw_info_blk, ppp_params_blk,
|
||||
vol_info_blk, mute_info_blk, hs_info_blk;
|
||||
struct mutex list_lock;/* mutex for IPC list locking */
|
||||
spinlock_t list_spin_lock; /* mutex for IPC list locking */
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
#define IPC_IA_CAPT_VOICE 0x17
|
||||
#define IPC_IA_DECODE_FRAMES 0x18
|
||||
|
||||
#define IPC_IA_ALG_PARAMS 0x1A
|
||||
|
||||
/* I2L Stream config/control msgs */
|
||||
#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
|
||||
#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
|
||||
|
|
|
@ -190,21 +190,15 @@ struct snd_prp_params {
|
|||
__u32 reserved; /* No pre-processing defined yet */
|
||||
};
|
||||
|
||||
struct snd_params_block {
|
||||
__u32 type; /*Type of the parameter*/
|
||||
__u32 size; /*size of the parameters in the block*/
|
||||
__u8 params[0]; /*Parameters of the algorithm*/
|
||||
};
|
||||
|
||||
/* Pre and post processing params structure */
|
||||
struct snd_ppp_params {
|
||||
enum sst_algo_types algo_id;/* Post/Pre processing algorithm ID */
|
||||
__u8 algo_id;/* Post/Pre processing algorithm ID */
|
||||
__u8 str_id; /*Only 5 bits used 0 - 31 are valid*/
|
||||
__u8 enable; /* 0= disable, 1= enable*/
|
||||
__u8 reserved;
|
||||
__u32 size; /*Size of parameters for all blocks*/
|
||||
struct snd_params_block params[0];
|
||||
};
|
||||
void *params;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct snd_sst_postproc_info {
|
||||
__u32 src_min; /* Supported SRC Min sampling freq */
|
||||
|
@ -431,5 +425,8 @@ struct snd_sst_dbufs {
|
|||
#define SNDRV_SST_FW_INFO _IOR('L', 0x20, struct snd_sst_fw_info *)
|
||||
#define SNDRV_SST_SET_TARGET_DEVICE _IOW('L', 0x21, \
|
||||
struct snd_sst_target_device *)
|
||||
/*DSP Ioctls on /dev/intel_sst_ctrl only*/
|
||||
#define SNDRV_SST_SET_ALGO _IOW('L', 0x30, struct snd_ppp_params *)
|
||||
#define SNDRV_SST_GET_ALGO _IOWR('L', 0x31, struct snd_ppp_params *)
|
||||
|
||||
#endif /* __INTEL_SST_IOCTL_H__ */
|
||||
|
|
|
@ -336,6 +336,55 @@ void sst_process_reply(struct work_struct *work)
|
|||
wake_up(&sst_drv_ctx->wait_queue);
|
||||
}
|
||||
break;
|
||||
case IPC_IA_ALG_PARAMS: {
|
||||
pr_debug("sst:IPC_ALG_PARAMS response %x\n", msg->header.full);
|
||||
pr_debug("sst: data value %x\n", msg->header.part.data);
|
||||
pr_debug("sst: large value %x\n", msg->header.part.large);
|
||||
|
||||
if (!msg->header.part.large) {
|
||||
if (!msg->header.part.data) {
|
||||
pr_debug("sst: alg set success\n");
|
||||
sst_drv_ctx->ppp_params_blk.ret_code = 0;
|
||||
} else {
|
||||
pr_debug("sst: alg set failed\n");
|
||||
sst_drv_ctx->ppp_params_blk.ret_code =
|
||||
-msg->header.part.data;
|
||||
}
|
||||
|
||||
} else if (msg->header.part.data) {
|
||||
struct snd_ppp_params *mailbox_params, *get_params;
|
||||
char *params;
|
||||
|
||||
pr_debug("sst: alg get success\n");
|
||||
mailbox_params = (struct snd_ppp_params *)msg->mailbox;
|
||||
get_params = kzalloc(sizeof(*get_params), GFP_KERNEL);
|
||||
if (get_params == NULL) {
|
||||
pr_err("sst: out of memory for ALG PARAMS");
|
||||
break;
|
||||
}
|
||||
memcpy_fromio(get_params, mailbox_params,
|
||||
sizeof(*get_params));
|
||||
get_params->params = kzalloc(mailbox_params->size,
|
||||
GFP_KERNEL);
|
||||
if (get_params->params == NULL) {
|
||||
kfree(get_params);
|
||||
pr_err("sst: out of memory for ALG PARAMS block");
|
||||
break;
|
||||
}
|
||||
params = msg->mailbox;
|
||||
params = params + sizeof(*mailbox_params) - sizeof(u32);
|
||||
memcpy_fromio(get_params->params, params,
|
||||
get_params->size);
|
||||
sst_drv_ctx->ppp_params_blk.ret_code = 0;
|
||||
sst_drv_ctx->ppp_params_blk.data = get_params;
|
||||
}
|
||||
|
||||
if (sst_drv_ctx->ppp_params_blk.on == true) {
|
||||
sst_drv_ctx->ppp_params_blk.condition = true;
|
||||
wake_up(&sst_drv_ctx->wait_queue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPC_IA_GET_FW_INFO: {
|
||||
struct snd_sst_fw_info *fw_info =
|
||||
(struct snd_sst_fw_info *)msg->mailbox;
|
||||
|
|
Loading…
Reference in a new issue