From bdede7a49d6b7cba931a6e847670885152ddfb8a Mon Sep 17 00:00:00 2001 From: Aravind Kumar Date: Tue, 8 Apr 2014 11:42:05 +0530 Subject: [PATCH] ASoC: qcom: qdsp6v2: update the audio native drivers to 64bit Add support for compat ioctls in audio native drivers. Change-Id: I1e84777ee8775b91f2daddc99da327bb3b08cb15 Signed-off-by: Aravind Kumar --- drivers/misc/qcom/qdsp6v2/aac_in.c | 366 ++++++++-- drivers/misc/qcom/qdsp6v2/amrnb_in.c | 154 +++- drivers/misc/qcom/qdsp6v2/amrwb_in.c | 148 +++- drivers/misc/qcom/qdsp6v2/audio_aac.c | 242 +++++-- drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c | 159 ++++- drivers/misc/qcom/qdsp6v2/audio_multi_aac.c | 290 ++++++-- drivers/misc/qcom/qdsp6v2/audio_utils.c | 387 ++++++++-- drivers/misc/qcom/qdsp6v2/audio_utils.h | 15 +- drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 751 +++++++++++++++++--- drivers/misc/qcom/qdsp6v2/audio_utils_aio.h | 6 +- drivers/misc/qcom/qdsp6v2/audio_wma.c | 121 +++- drivers/misc/qcom/qdsp6v2/audio_wmapro.c | 147 +++- drivers/misc/qcom/qdsp6v2/evrc_in.c | 158 +++- drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c | 6 +- drivers/misc/qcom/qdsp6v2/qcelp_in.c | 156 +++- include/uapi/linux/msm_audio.h | 24 +- include/uapi/linux/msm_audio_aac.h | 10 +- include/uapi/linux/msm_audio_wmapro.h | 4 +- 18 files changed, 2690 insertions(+), 454 deletions(-) diff --git a/drivers/misc/qcom/qdsp6v2/aac_in.c b/drivers/misc/qcom/qdsp6v2/aac_in.c index 5090544f5bee..38db0381c50e 100644 --- a/drivers/misc/qcom/qdsp6v2/aac_in.c +++ b/drivers/misc/qcom/qdsp6v2/aac_in.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include "audio_utils.h" @@ -33,9 +34,7 @@ #define AAC_FORMAT_ADTS 65535 -/* ------------------- device --------------------- */ -static long aac_in_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long aac_in_ioctl_shared(struct file *file, unsigned int cmd, void *arg) { struct q6audio_in *audio = file->private_data; int rc = 0; @@ -150,52 +149,61 @@ static long aac_in_ioctl(struct file *file, break; } case AUDIO_GET_AAC_ENC_CONFIG: { - struct msm_audio_aac_enc_config cfg; + struct msm_audio_aac_enc_config *cfg; struct msm_audio_aac_enc_config *enc_cfg; - memset(&cfg, 0, sizeof(cfg)); + + cfg = (struct msm_audio_aac_enc_config *)arg; + if (cfg == NULL) { + pr_err("%s: NULL config pointer for %s\n", + __func__, "AUDIO_GET_AAC_CONFIG"); + rc = -EINVAL; + break; + } + memset(cfg, 0, sizeof(*cfg)); enc_cfg = audio->enc_cfg; if (enc_cfg->channels == CH_MODE_MONO) - cfg.channels = 1; + cfg->channels = 1; else - cfg.channels = 2; - cfg.sample_rate = enc_cfg->sample_rate; - cfg.bit_rate = enc_cfg->bit_rate; + cfg->channels = 2; + cfg->sample_rate = enc_cfg->sample_rate; + cfg->bit_rate = enc_cfg->bit_rate; switch (enc_cfg->stream_format) { case 0x00: - cfg.stream_format = AUDIO_AAC_FORMAT_ADTS; + cfg->stream_format = AUDIO_AAC_FORMAT_ADTS; break; case 0x01: - cfg.stream_format = AUDIO_AAC_FORMAT_LOAS; + cfg->stream_format = AUDIO_AAC_FORMAT_LOAS; break; case 0x02: - cfg.stream_format = AUDIO_AAC_FORMAT_ADIF; + cfg->stream_format = AUDIO_AAC_FORMAT_ADIF; break; default: case 0x03: - cfg.stream_format = AUDIO_AAC_FORMAT_RAW; + cfg->stream_format = AUDIO_AAC_FORMAT_RAW; } - pr_debug("%s:session id %d: Get-aac-cfg: format=%d sr=%d" "bitrate=%d\n", __func__, audio->ac->session, - cfg.stream_format, cfg.sample_rate, cfg.bit_rate); - if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) - rc = -EFAULT; + cfg->stream_format, cfg->sample_rate, cfg->bit_rate); break; } case AUDIO_SET_AAC_ENC_CONFIG: { - struct msm_audio_aac_enc_config cfg; + struct msm_audio_aac_enc_config *cfg; struct msm_audio_aac_enc_config *enc_cfg; uint32_t min_bitrate, max_bitrate; - enc_cfg = audio->enc_cfg; - if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { - rc = -EFAULT; + + cfg = (struct msm_audio_aac_enc_config *)arg; + if (cfg == NULL) { + pr_err("%s: NULL config pointer for %s\n", + "AUDIO_SET_AAC_ENC_CONFIG", __func__); + rc = -EINVAL; break; } + enc_cfg = audio->enc_cfg; pr_debug("%s:session id %d: Set-aac-cfg: stream=%d\n", __func__, - audio->ac->session, cfg.stream_format); + audio->ac->session, cfg->stream_format); - switch (cfg.stream_format) { + switch (cfg->stream_format) { case AUDIO_AAC_FORMAT_ADTS: enc_cfg->stream_format = 0x00; break; @@ -211,46 +219,47 @@ static long aac_in_ioctl(struct file *file, default: pr_err("%s:session id %d: unsupported AAC format %d\n", __func__, audio->ac->session, - cfg.stream_format); + cfg->stream_format); rc = -EINVAL; break; } - if (cfg.channels == 1) { - cfg.channels = CH_MODE_MONO; - } else if (cfg.channels == 2) { - cfg.channels = CH_MODE_STEREO; + if (cfg->channels == 1) { + cfg->channels = CH_MODE_MONO; + } else if (cfg->channels == 2) { + cfg->channels = CH_MODE_STEREO; } else { rc = -EINVAL; break; } - if ((cfg.sample_rate < 8000) || (cfg.sample_rate > 48000)) { - pr_err("%s: ERROR in setting samplerate = %d\n", - __func__, cfg.sample_rate); + + min_bitrate = ((cfg->sample_rate)*(cfg->channels))/2; + if (min_bitrate < 24000) + min_bitrate = 24000; + max_bitrate = 6*(cfg->sample_rate)*(cfg->channels); + if (max_bitrate > 192000) + max_bitrate = 192000; + if ((cfg->bit_rate < min_bitrate) || + (cfg->bit_rate > max_bitrate)) { + pr_err("%s: bitrate permissible: max=%d, min=%d\n", + __func__, max_bitrate, min_bitrate); + pr_err("%s: ERROR in setting bitrate = %d\n", + __func__, cfg->bit_rate); rc = -EINVAL; break; } /* For aac-lc, min_bit_rate = min(24Kbps, 0.5*SR*num_chan); max_bi_rate = min(192Kbps, 6*SR*num_chan); min_sample_rate = 8000Hz, max_rate=48000 */ - min_bitrate = ((cfg.sample_rate)*(cfg.channels))/2; - if (min_bitrate < 24000) - min_bitrate = 24000; - max_bitrate = 6*(cfg.sample_rate)*(cfg.channels); - if (max_bitrate > 192000) - max_bitrate = 192000; - if ((cfg.bit_rate < min_bitrate) || - (cfg.bit_rate > max_bitrate)) { - pr_err("%s: bitrate permissible: max=%d, min=%d\n", - __func__, max_bitrate, min_bitrate); + if ((cfg->bit_rate < 24000) || (cfg->bit_rate > 192000)) { pr_err("%s: ERROR in setting bitrate = %d\n", - __func__, cfg.bit_rate); + __func__, cfg->bit_rate); rc = -EINVAL; break; } - enc_cfg->sample_rate = cfg.sample_rate; - enc_cfg->channels = cfg.channels; - enc_cfg->bit_rate = cfg.bit_rate; + enc_cfg->sample_rate = cfg->sample_rate; + enc_cfg->channels = cfg->channels; + enc_cfg->bit_rate = cfg->bit_rate; pr_debug("%s:session id %d: Set-aac-cfg:SR= 0x%x ch=0x%x" "bitrate=0x%x, format(adts/raw) = %d\n", __func__, audio->ac->session, enc_cfg->sample_rate, @@ -258,32 +267,25 @@ static long aac_in_ioctl(struct file *file, enc_cfg->stream_format); break; } - case AUDIO_GET_AAC_CONFIG: { - if (copy_to_user((void *)arg, &audio->codec_cfg, - sizeof(struct msm_audio_aac_config))) { - rc = -EFAULT; - break; - } - break; - } case AUDIO_SET_AAC_CONFIG: { - struct msm_audio_aac_config aac_cfg; + struct msm_audio_aac_config *aac_cfg; struct msm_audio_aac_config *audio_aac_cfg; struct msm_audio_aac_enc_config *enc_cfg; enc_cfg = audio->enc_cfg; audio_aac_cfg = audio->codec_cfg; + aac_cfg = (struct msm_audio_aac_config *)arg; - if (copy_from_user(&aac_cfg, (void *)arg, - sizeof(struct msm_audio_aac_config))) { - rc = -EFAULT; + if (aac_cfg == NULL) { + pr_err("%s: NULL config pointer %s\n", + __func__, "AUDIO_SET_AAC_CONFIG"); + rc = -EINVAL; break; } - pr_debug("%s:session id %d: AUDIO_SET_AAC_CONFIG: sbr_flag = %d" - " sbr_ps_flag = %d\n", __func__, - audio->ac->session, aac_cfg.sbr_on_flag, - aac_cfg.sbr_ps_on_flag); - audio_aac_cfg->sbr_on_flag = aac_cfg.sbr_on_flag; - audio_aac_cfg->sbr_ps_on_flag = aac_cfg.sbr_ps_on_flag; + pr_debug("%s:session id %d: AUDIO_SET_AAC_CONFIG: sbr_flag = %d sbr_ps_flag = %d\n", + __func__, audio->ac->session, aac_cfg->sbr_on_flag, + aac_cfg->sbr_ps_on_flag); + audio_aac_cfg->sbr_on_flag = aac_cfg->sbr_on_flag; + audio_aac_cfg->sbr_ps_on_flag = aac_cfg->sbr_ps_on_flag; if ((audio_aac_cfg->sbr_on_flag == 1) || (audio_aac_cfg->sbr_ps_on_flag == 1)) { if (enc_cfg->sample_rate < 24000) { @@ -296,11 +298,247 @@ static long aac_in_ioctl(struct file *file, break; } default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); rc = -EINVAL; } return rc; } +static long aac_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = aac_in_ioctl_shared(file, cmd, NULL); + break; + } + case AUDIO_GET_AAC_ENC_CONFIG: { + struct msm_audio_aac_enc_config cfg; + rc = aac_in_ioctl_shared(file, cmd, &cfg); + if (rc) { + pr_err("%s:AUDIO_GET_AAC_ENC_CONFIG failed. rc=%d\n", + __func__, rc); + break; + } + if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_ENC_CONFIG failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_AAC_ENC_CONFIG: { + struct msm_audio_aac_enc_config cfg; + if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_ENC_CONFIG failed\n", + __func__); + rc = -EFAULT; + break; + } + rc = aac_in_ioctl_shared(file, cmd, &cfg); + if (rc) + pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG failed. rc=%d\n", + __func__, rc); + break; + } + case AUDIO_GET_AAC_CONFIG: { + if (copy_to_user((void *)arg, &audio->codec_cfg, + sizeof(struct msm_audio_aac_config))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG failed\n", + __func__); + rc = -EFAULT; + break; + } + break; + } + case AUDIO_SET_AAC_CONFIG: { + struct msm_audio_aac_config aac_cfg; + if (copy_from_user(&aac_cfg, (void *)arg, + sizeof(struct msm_audio_aac_config))) { + pr_err("%s: copy_to_user for AUDIO_SET_CONFIG failed\n", + __func__); + rc = -EFAULT; + break; + } + rc = aac_in_ioctl_shared(file, cmd, &aac_cfg); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. rc=%d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd=%d\n", __func__, cmd); + rc = -EINVAL; + } + return rc; +} + +#ifdef CONFIG_COMPAT +struct msm_audio_aac_enc_config32 { + u32 channels; + u32 sample_rate; + u32 bit_rate; + u32 stream_format; +}; + +struct msm_audio_aac_config32 { + s16 format; + u16 audio_object; + u16 ep_config; /* 0 ~ 3 useful only obj = ERLC */ + u16 aac_section_data_resilience_flag; + u16 aac_scalefactor_data_resilience_flag; + u16 aac_spectral_data_resilience_flag; + u16 sbr_on_flag; + u16 sbr_ps_on_flag; + u16 dual_mono_mode; + u16 channel_configuration; + u16 sample_rate; +}; + +enum { + AUDIO_SET_AAC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config32), + AUDIO_GET_AAC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config32), + AUDIO_SET_AAC_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config32), + AUDIO_GET_AAC_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config32) +}; + +static long aac_in_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = aac_in_ioctl_shared(file, cmd, NULL); + break; + } + case AUDIO_GET_AAC_ENC_CONFIG_32: { + struct msm_audio_aac_enc_config cfg; + struct msm_audio_aac_enc_config32 cfg_32; + + cmd = AUDIO_GET_AAC_ENC_CONFIG; + rc = aac_in_ioctl_shared(file, cmd, &cfg); + if (rc) { + pr_err("%s:AUDIO_GET_AAC_ENC_CONFIG_32 failed. Rc= %d\n", + __func__, rc); + break; + } + cfg_32.channels = cfg.channels; + cfg_32.sample_rate = cfg.sample_rate; + cfg_32.bit_rate = cfg.bit_rate; + cfg_32.stream_format = cfg.stream_format; + if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_AAC_ENC_CONFIG_32: { + struct msm_audio_aac_enc_config cfg; + struct msm_audio_aac_enc_config32 cfg_32; + if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_GET_AAC_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cfg.channels = cfg_32.channels; + cfg.sample_rate = cfg_32.sample_rate; + cfg.bit_rate = cfg_32.bit_rate; + cfg.stream_format = cfg_32.stream_format; + /* The command should be converted from 32 bit to normal + * before the shared ioctl is called as shared ioctl + * can process only normal commands */ + cmd = AUDIO_SET_AAC_ENC_CONFIG; + rc = aac_in_ioctl_shared(file, cmd, &cfg); + if (rc) + pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG_32 failed. rc=%d\n", + __func__, rc); + break; + } + case AUDIO_GET_AAC_CONFIG_32: { + struct msm_audio_aac_config *aac_config; + struct msm_audio_aac_config32 aac_config_32; + + aac_config = (struct msm_audio_aac_config *)audio->codec_cfg; + aac_config_32.format = aac_config->format; + aac_config_32.audio_object = aac_config->audio_object; + aac_config_32.ep_config = aac_config->ep_config; + aac_config_32.aac_section_data_resilience_flag = + aac_config->aac_section_data_resilience_flag; + aac_config_32.aac_scalefactor_data_resilience_flag = + aac_config->aac_scalefactor_data_resilience_flag; + aac_config_32.aac_spectral_data_resilience_flag = + aac_config->aac_spectral_data_resilience_flag; + aac_config_32.sbr_on_flag = aac_config->sbr_on_flag; + aac_config_32.sbr_ps_on_flag = aac_config->sbr_ps_on_flag; + aac_config_32.dual_mono_mode = aac_config->dual_mono_mode; + aac_config_32.channel_configuration = + aac_config->channel_configuration; + aac_config_32.sample_rate = aac_config->sample_rate; + + if (copy_to_user((void *)arg, &aac_config_32, + sizeof(aac_config_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + break; + } + case AUDIO_SET_AAC_CONFIG_32: { + struct msm_audio_aac_config aac_cfg; + struct msm_audio_aac_config32 aac_cfg_32; + if (copy_from_user(&aac_cfg_32, (void *)arg, + sizeof(aac_cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + aac_cfg.format = aac_cfg_32.format; + aac_cfg.audio_object = aac_cfg_32.audio_object; + aac_cfg.ep_config = aac_cfg_32.ep_config; + aac_cfg.aac_section_data_resilience_flag = + aac_cfg_32.aac_section_data_resilience_flag; + aac_cfg.aac_scalefactor_data_resilience_flag = + aac_cfg_32.aac_scalefactor_data_resilience_flag; + aac_cfg.aac_spectral_data_resilience_flag = + aac_cfg_32.aac_spectral_data_resilience_flag; + aac_cfg.sbr_on_flag = aac_cfg_32.sbr_on_flag; + aac_cfg.sbr_ps_on_flag = aac_cfg_32.sbr_ps_on_flag; + aac_cfg.dual_mono_mode = aac_cfg_32.dual_mono_mode; + aac_cfg.channel_configuration = + aac_cfg_32.channel_configuration; + aac_cfg.sample_rate = aac_cfg_32.sample_rate; + + cmd = AUDIO_SET_AAC_CONFIG; + rc = aac_in_ioctl_shared(file, cmd, &aac_cfg); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d\n", __func__, cmd); + rc = -EINVAL; + } + return rc; +} +#else +#define aac_in_compat_ioctl NULL +#endif + static int aac_in_open(struct inode *inode, struct file *file) { struct q6audio_in *audio = NULL; @@ -426,6 +664,7 @@ static int aac_in_open(struct inode *inode, struct file *file) audio->opened = 1; atomic_set(&audio->in_count, PCM_BUF_COUNT); atomic_set(&audio->out_count, 0x00); + audio->enc_compat_ioctl = aac_in_compat_ioctl; audio->enc_ioctl = aac_in_ioctl; file->private_data = audio; @@ -446,6 +685,7 @@ static const struct file_operations audio_in_fops = { .read = audio_in_read, .write = audio_in_write, .unlocked_ioctl = audio_in_ioctl, + .compat_ioctl = audio_in_compat_ioctl }; struct miscdevice audio_aac_in_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/amrnb_in.c b/drivers/misc/qcom/qdsp6v2/amrnb_in.c index 91c588c064d5..eb92137f0671 100644 --- a/drivers/misc/qcom/qdsp6v2/amrnb_in.c +++ b/drivers/misc/qcom/qdsp6v2/amrnb_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2012, 2014 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include "audio_utils.h" @@ -30,9 +31,8 @@ /* Maximum 10 frames in buffer with meta */ #define FRAME_SIZE (1 + ((32+sizeof(struct meta_out_dsp)) * 10)) -/* ------------------- device --------------------- */ -static long amrnb_in_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long amrnb_in_ioctl_shared(struct file *file, + unsigned int cmd, void *arg) { struct q6audio_in *audio = file->private_data; int rc = 0; @@ -108,23 +108,21 @@ static long amrnb_in_ioctl(struct file *file, } break; } - case AUDIO_GET_AMRNB_ENC_CONFIG_V2: { - if (copy_to_user((void *)arg, audio->enc_cfg, - sizeof(struct msm_audio_amrnb_enc_config_v2))) - rc = -EFAULT; - break; - } case AUDIO_SET_AMRNB_ENC_CONFIG_V2: { - struct msm_audio_amrnb_enc_config_v2 cfg; + struct msm_audio_amrnb_enc_config_v2 *cfg; struct msm_audio_amrnb_enc_config_v2 *enc_cfg; - enc_cfg = audio->enc_cfg; - if (copy_from_user(&cfg, (void *) arg, - sizeof(struct msm_audio_amrnb_enc_config_v2))) { - rc = -EFAULT; + cfg = (struct msm_audio_amrnb_enc_config_v2 *)arg; + if (cfg == NULL) { + pr_err("%s: NULL config pointer for %s\n", + __func__, + "AUDIO_SET_AMRNB_ENC_CONFIG_V2"); + rc = -EINVAL; break; } - if (cfg.band_mode > 8 || - cfg.band_mode < 1) { + + enc_cfg = audio->enc_cfg; + if (cfg->band_mode > 8 || + cfg->band_mode < 1) { pr_err("%s:session id %d: invalid band mode\n", __func__, audio->ac->session); rc = -EINVAL; @@ -133,8 +131,8 @@ static long amrnb_in_ioctl(struct file *file, /* AMR NB encoder accepts values between 0-7 while openmax provides value between 1-8 as per spec */ - enc_cfg->band_mode = (cfg.band_mode - 1); - enc_cfg->dtx_enable = (cfg.dtx_enable ? 1 : 0); + enc_cfg->band_mode = (cfg->band_mode - 1); + enc_cfg->dtx_enable = (cfg->dtx_enable ? 1 : 0); enc_cfg->frame_format = 0; pr_debug("%s:session id %d: band_mode = 0x%x dtx_enable=0x%x\n", __func__, audio->ac->session, @@ -142,11 +140,127 @@ static long amrnb_in_ioctl(struct file *file, break; } default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); rc = -EINVAL; } return rc; } +static long amrnb_in_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = amrnb_in_ioctl_shared(file, cmd, NULL); + break; + } + case AUDIO_GET_AMRNB_ENC_CONFIG_V2: { + if (copy_to_user((void *)arg, audio->enc_cfg, + sizeof(struct msm_audio_amrnb_enc_config_v2))) { + pr_err("%s: copy_to_user for AUDIO_GET_AMRNB_ENC_CONFIG_V2 failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_AMRNB_ENC_CONFIG_V2: { + struct msm_audio_amrnb_enc_config_v2 cfg; + if (copy_from_user(&cfg, (void *) arg, + sizeof(cfg))) { + pr_err("%s: copy_from_user for AUDIO_SET_AMRNB_ENC_CONFIG_V2 failed\n", + __func__); + rc = -EFAULT; + break; + } + rc = amrnb_in_ioctl_shared(file, cmd, &cfg); + if (rc) + pr_err("%s: AUDIO_SET_AMRNB_ENC_CONFIG_V2 failed. rc=%d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd=%d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} + +#ifdef CONFIG_COMPAT +struct msm_audio_amrnb_enc_config_v2_32 { + u32 band_mode; + u32 dtx_enable; + u32 frame_format; +}; + +enum { + AUDIO_GET_AMRNB_ENC_CONFIG_V2_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+2), + struct msm_audio_amrnb_enc_config_v2_32), + AUDIO_SET_AMRNB_ENC_CONFIG_V2_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+3), + struct msm_audio_amrnb_enc_config_v2_32) +}; + +static long amrnb_in_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = amrnb_in_ioctl_shared(file, cmd, NULL); + break; + } + case AUDIO_GET_AMRNB_ENC_CONFIG_V2_32: { + struct msm_audio_amrnb_enc_config_v2 *amrnb_config; + struct msm_audio_amrnb_enc_config_v2_32 amrnb_config_32; + + amrnb_config = + (struct msm_audio_amrnb_enc_config_v2 *)audio->enc_cfg; + amrnb_config_32.band_mode = amrnb_config->band_mode; + amrnb_config_32.dtx_enable = amrnb_config->dtx_enable; + amrnb_config_32.frame_format = amrnb_config->frame_format; + + if (copy_to_user((void *)arg, &amrnb_config_32, + sizeof(amrnb_config_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_AMRNB_ENC_CONFIG_V2_32 failed", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_AMRNB_ENC_CONFIG_V2_32: { + struct msm_audio_amrnb_enc_config_v2_32 cfg_32; + if (copy_from_user(&cfg_32, (void *) arg, + sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_AMRNB_ENC_CONFIG_V2_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cmd = AUDIO_SET_AMRNB_ENC_CONFIG_V2; + rc = amrnb_in_ioctl_shared(file, cmd, &cfg_32); + if (rc) + pr_err("%s:AUDIO_SET_AMRNB_ENC_CONFIG_V2 failed rc= %d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} +#else +#define amrnb_in_compat_ioctl NULL +#endif + static int amrnb_in_open(struct inode *inode, struct file *file) { struct q6audio_in *audio = NULL; @@ -250,6 +364,7 @@ static int amrnb_in_open(struct inode *inode, struct file *file) audio->opened = 1; atomic_set(&audio->in_count, PCM_BUF_COUNT); atomic_set(&audio->out_count, 0x00); + audio->enc_compat_ioctl = amrnb_in_compat_ioctl; audio->enc_ioctl = amrnb_in_ioctl; file->private_data = audio; @@ -269,6 +384,7 @@ static const struct file_operations audio_in_fops = { .read = audio_in_read, .write = audio_in_write, .unlocked_ioctl = audio_in_ioctl, + .compat_ioctl = audio_in_compat_ioctl }; struct miscdevice audio_amrnb_in_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/amrwb_in.c b/drivers/misc/qcom/qdsp6v2/amrwb_in.c index ea3fe5b84068..4cea3dc63389 100644 --- a/drivers/misc/qcom/qdsp6v2/amrwb_in.c +++ b/drivers/misc/qcom/qdsp6v2/amrwb_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include "audio_utils.h" @@ -29,9 +30,8 @@ /* Maximum 10 frames in buffer with meta */ #define FRAME_SIZE (1 + ((61+sizeof(struct meta_out_dsp)) * 10)) -/* ------------------- device --------------------- */ -static long amrwb_in_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long amrwb_in_ioctl_shared(struct file *file, + unsigned int cmd, void *arg) { struct q6audio_in *audio = file->private_data; int rc = 0; @@ -105,22 +105,19 @@ static long amrwb_in_ioctl(struct file *file, } break; } - case AUDIO_GET_AMRWB_ENC_CONFIG: { - if (copy_to_user((void *)arg, audio->enc_cfg, - sizeof(struct msm_audio_amrwb_enc_config))) - rc = -EFAULT; - break; - } case AUDIO_SET_AMRWB_ENC_CONFIG: { - struct msm_audio_amrwb_enc_config cfg; + struct msm_audio_amrwb_enc_config *cfg; struct msm_audio_amrwb_enc_config *enc_cfg; enc_cfg = audio->enc_cfg; - if (copy_from_user(&cfg, (void *) arg, - sizeof(struct msm_audio_amrwb_enc_config))) { - rc = -EFAULT; + cfg = (struct msm_audio_amrwb_enc_config *)arg; + if (cfg == NULL) { + pr_err("%s: NULL config pointer for %s\n", + __func__, "AUDIO_SET_AMRWB_ENC_CONFIG"); + rc = -EINVAL; break; } - if (cfg.band_mode > 8) { + + if (cfg->band_mode > 8) { pr_err("%s:session id %d: invalid band mode\n", __func__, audio->ac->session); rc = -EINVAL; @@ -129,8 +126,8 @@ static long amrwb_in_ioctl(struct file *file, /* ToDo: AMR WB encoder accepts values between 0-8 while openmax provides value between 9-17 as per spec */ - enc_cfg->band_mode = cfg.band_mode; - enc_cfg->dtx_enable = (cfg.dtx_enable ? 1 : 0); + enc_cfg->band_mode = cfg->band_mode; + enc_cfg->dtx_enable = (cfg->dtx_enable ? 1 : 0); /* Currently DSP does not support different frameformat */ enc_cfg->frame_format = 0; pr_debug("%s:session id %d: band_mode = 0x%x dtx_enable=0x%x\n", @@ -139,11 +136,126 @@ static long amrwb_in_ioctl(struct file *file, break; } default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); rc = -EINVAL; } return rc; } +static long amrwb_in_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = amrwb_in_ioctl_shared(file, cmd, NULL); + break; + } + case AUDIO_GET_AMRWB_ENC_CONFIG: { + if (copy_to_user((void *)arg, audio->enc_cfg, + sizeof(struct msm_audio_amrwb_enc_config))) + pr_err("%s: copy_to_user for AUDIO_GET_AMRWB_ENC_CONFIG failed\n", + __func__); + rc = -EFAULT; + break; + } + case AUDIO_SET_AMRWB_ENC_CONFIG: { + struct msm_audio_amrwb_enc_config cfg; + if (copy_from_user(&cfg, (void *) arg, + sizeof(cfg))) { + pr_err("%s: copy_from_user for AUDIO_SET_AMRWB_ENC_CONFIG failed\n", + __func__); + rc = -EFAULT; + break; + } + rc = amrwb_in_ioctl_shared(file, cmd, &cfg); + if (rc) + pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG failed. rc=%d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} + +#ifdef CONFIG_COMPAT +struct msm_audio_amrwb_enc_config_32 { + u32 band_mode; + u32 dtx_enable; + u32 frame_format; +}; + +enum { + AUDIO_GET_AMRWB_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+0), + struct msm_audio_amrwb_enc_config_32), + AUDIO_SET_AMRWB_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+1), + struct msm_audio_amrwb_enc_config_32) +}; + +static long amrwb_in_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = amrwb_in_ioctl_shared(file, cmd, NULL); + break; + } + case AUDIO_GET_AMRWB_ENC_CONFIG_32: { + struct msm_audio_amrwb_enc_config *amrwb_config; + struct msm_audio_amrwb_enc_config_32 amrwb_config_32; + + amrwb_config = + (struct msm_audio_amrwb_enc_config *)audio->enc_cfg; + amrwb_config_32.band_mode = amrwb_config->band_mode; + amrwb_config_32.dtx_enable = amrwb_config->dtx_enable; + amrwb_config_32.frame_format = amrwb_config->frame_format; + + if (copy_to_user((void *)arg, &amrwb_config_32, + sizeof(struct msm_audio_amrwb_enc_config_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_AMRWB_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_AMRWB_ENC_CONFIG_32: { + struct msm_audio_amrwb_enc_config cfg_32; + if (copy_from_user(&cfg_32, (void *) arg, + sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_AMRWB_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cmd = AUDIO_SET_AMRWB_ENC_CONFIG; + rc = amrwb_in_ioctl_shared(file, cmd, &cfg_32); + if (rc) + pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG failed. rc=%d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} +#else +#define amrwb_in_compat_ioctl NULL +#endif + static int amrwb_in_open(struct inode *inode, struct file *file) { struct q6audio_in *audio = NULL; @@ -247,6 +359,7 @@ static int amrwb_in_open(struct inode *inode, struct file *file) audio->opened = 1; atomic_set(&audio->in_count, PCM_BUF_COUNT); atomic_set(&audio->out_count, 0x00); + audio->enc_compat_ioctl = amrwb_in_compat_ioctl; audio->enc_ioctl = amrwb_in_ioctl; file->private_data = audio; @@ -266,6 +379,7 @@ static const struct file_operations audio_in_fops = { .read = audio_in_read, .write = audio_in_write, .unlocked_ioctl = audio_in_ioctl, + .compat_ioctl = audio_in_compat_ioctl }; struct miscdevice audio_amrwb_in_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/audio_aac.c b/drivers/misc/qcom/qdsp6v2/audio_aac.c index caeb79d22880..c3cf3e4d09af 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_aac.c +++ b/drivers/misc/qcom/qdsp6v2/audio_aac.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -16,6 +16,7 @@ */ #include +#include #include "audio_utils_aio.h" #define AUDIO_AAC_DUAL_MONO_INVALID -1 @@ -28,7 +29,8 @@ static const struct file_operations audio_aac_debug_fops = { }; #endif -static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long audio_ioctl_shared(struct file *file, unsigned int cmd, + void *arg) { struct q6audio_aio *audio = file->private_data; int rc = 0; @@ -122,75 +124,220 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) audio->stopped = 0; break; } + case AUDIO_SET_AAC_CONFIG: { + struct msm_audio_aac_config *aac_config; + uint16_t sce_left = 1, sce_right = 2; + + pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__); + aac_config = (struct msm_audio_aac_config *)arg; + if (aac_config == NULL) { + pr_err("%s: Invalid config pointer\n", __func__); + rc = -EINVAL; + break; + } + memcpy(audio->codec_cfg, aac_config, + sizeof(struct msm_audio_aac_config)); + /* PL_PR is 0 only need to check PL_SR */ + if (aac_config->dual_mono_mode > + AUDIO_AAC_DUAL_MONO_PL_SR) { + pr_err("%s:Invalid dual_mono mode =%d\n", __func__, + aac_config->dual_mono_mode); + } else { + /* convert the data from user into sce_left + * and sce_right based on the definitions + */ + pr_debug("%s: modify dual_mono mode =%d\n", __func__, + aac_config->dual_mono_mode); + switch (aac_config->dual_mono_mode) { + case AUDIO_AAC_DUAL_MONO_PL_PR: + sce_left = 1; + sce_right = 1; + break; + case AUDIO_AAC_DUAL_MONO_SL_SR: + sce_left = 2; + sce_right = 2; + break; + case AUDIO_AAC_DUAL_MONO_SL_PR: + sce_left = 2; + sce_right = 1; + break; + case AUDIO_AAC_DUAL_MONO_PL_SR: + default: + sce_left = 1; + sce_right = 2; + break; + } + rc = q6asm_cfg_dual_mono_aac(audio->ac, + sce_left, sce_right); + if (rc < 0) + pr_err("%s:asm cmd dualmono failed rc=%d\n", + __func__, rc); + } + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + break; + } + return rc; +} + +static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } case AUDIO_GET_AAC_CONFIG: { if (copy_to_user((void *)arg, audio->codec_cfg, sizeof(struct msm_audio_aac_config))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG failed\n", + __func__); rc = -EFAULT; break; } break; } case AUDIO_SET_AAC_CONFIG: { - struct msm_audio_aac_config *aac_config; + struct msm_audio_aac_config aac_config; pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__); - if (copy_from_user(audio->codec_cfg, (void *)arg, - sizeof(struct msm_audio_aac_config))) { + if (copy_from_user(&aac_config, (void *)arg, + sizeof(aac_config))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG failed\n", + __func__); rc = -EFAULT; break; - } else { - uint16_t sce_left = 1, sce_right = 2; - aac_config = audio->codec_cfg; - /* PL_PR is 0 only need to check PL_SR */ - if (aac_config->dual_mono_mode > - AUDIO_AAC_DUAL_MONO_PL_SR) { - pr_err("%s:AUDIO_SET_AAC_CONFIG: Invalid" - "dual_mono mode =%d\n", __func__, - aac_config->dual_mono_mode); - } else { - /* convert the data from user into sce_left - * and sce_right based on the definitions - */ - pr_debug("%s: AUDIO_SET_AAC_CONFIG: modify" - "dual_mono mode =%d\n", __func__, - aac_config->dual_mono_mode); - switch (aac_config->dual_mono_mode) { - case AUDIO_AAC_DUAL_MONO_PL_PR: - sce_left = 1; - sce_right = 1; - break; - case AUDIO_AAC_DUAL_MONO_SL_SR: - sce_left = 2; - sce_right = 2; - break; - case AUDIO_AAC_DUAL_MONO_SL_PR: - sce_left = 2; - sce_right = 1; - break; - case AUDIO_AAC_DUAL_MONO_PL_SR: - default: - sce_left = 1; - sce_right = 2; - break; - } - rc = q6asm_cfg_dual_mono_aac(audio->ac, - sce_left, sce_right); - if (rc < 0) - pr_err("%s: asm cmd dualmono failed" - " rc=%d\n", __func__, rc); - } } + rc = audio_ioctl_shared(file, cmd, &aac_config); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n", + __func__, rc); break; } - default: + default: { pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); rc = audio->codec_ioctl(file, cmd, arg); if (rc) pr_err("%s[%p]:Failed in utils_ioctl: %d\n", __func__, audio, rc); } + } return rc; } +#ifdef CONFIG_COMPAT +struct msm_audio_aac_config32 { + s16 format; + u16 audio_object; + u16 ep_config; /* 0 ~ 3 useful only obj = ERLC */ + u16 aac_section_data_resilience_flag; + u16 aac_scalefactor_data_resilience_flag; + u16 aac_spectral_data_resilience_flag; + u16 sbr_on_flag; + u16 sbr_ps_on_flag; + u16 dual_mono_mode; + u16 channel_configuration; + u16 sample_rate; +}; + +enum { + AUDIO_SET_AAC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config32), + AUDIO_GET_AAC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config32) +}; + +static long audio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } + case AUDIO_GET_AAC_CONFIG_32: { + struct msm_audio_aac_config *aac_config; + struct msm_audio_aac_config32 aac_config_32; + + aac_config = (struct msm_audio_aac_config *)audio->codec_cfg; + aac_config_32.format = aac_config->format; + aac_config_32.audio_object = aac_config->audio_object; + aac_config_32.ep_config = aac_config->ep_config; + aac_config_32.aac_section_data_resilience_flag = + aac_config->aac_section_data_resilience_flag; + aac_config_32.aac_scalefactor_data_resilience_flag = + aac_config->aac_scalefactor_data_resilience_flag; + aac_config_32.aac_spectral_data_resilience_flag = + aac_config->aac_spectral_data_resilience_flag; + aac_config_32.sbr_on_flag = aac_config->sbr_on_flag; + aac_config_32.sbr_ps_on_flag = aac_config->sbr_ps_on_flag; + aac_config_32.dual_mono_mode = aac_config->dual_mono_mode; + aac_config_32.channel_configuration = + aac_config->channel_configuration; + aac_config_32.sample_rate = aac_config->sample_rate; + + if (copy_to_user((void *)arg, &aac_config_32, + sizeof(aac_config_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + break; + } + case AUDIO_SET_AAC_CONFIG_32: { + struct msm_audio_aac_config aac_config; + struct msm_audio_aac_config32 aac_config_32; + pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__); + if (copy_from_user(&aac_config_32, (void *)arg, + sizeof(aac_config_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + aac_config.format = aac_config_32.format; + aac_config.audio_object = aac_config_32.audio_object; + aac_config.ep_config = aac_config_32.ep_config; + aac_config.aac_section_data_resilience_flag = + aac_config_32.aac_section_data_resilience_flag; + aac_config.aac_scalefactor_data_resilience_flag = + aac_config_32.aac_scalefactor_data_resilience_flag; + aac_config.aac_spectral_data_resilience_flag = + aac_config_32.aac_spectral_data_resilience_flag; + aac_config.sbr_on_flag = aac_config_32.sbr_on_flag; + aac_config.sbr_ps_on_flag = aac_config_32.sbr_ps_on_flag; + aac_config.dual_mono_mode = aac_config_32.dual_mono_mode; + aac_config.channel_configuration = + aac_config_32.channel_configuration; + aac_config.sample_rate = aac_config_32.sample_rate; + + cmd = AUDIO_SET_AAC_CONFIG; + rc = audio_ioctl_shared(file, cmd, &aac_config); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n", + __func__, rc); + break; + } + default: { + pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); + rc = audio->codec_compat_ioctl(file, cmd, arg); + if (rc) + pr_err("%s[%p]:Failed in utils_ioctl: %d\n", + __func__, audio, rc); + } + } + return rc; +} +#else +#define audio_compat_ioctl NULL +#endif + static int audio_open(struct inode *inode, struct file *file) { struct q6audio_aio *audio = NULL; @@ -293,6 +440,7 @@ static const struct file_operations audio_aac_fops = { .release = audio_aio_release, .unlocked_ioctl = audio_ioctl, .fsync = audio_aio_fsync, + .compat_ioctl = audio_compat_ioctl }; struct miscdevice audio_aac_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c index 544bf9ca8a25..84568cb5a047 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c +++ b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -15,6 +15,7 @@ * */ #include +#include #include "audio_utils_aio.h" #ifdef CONFIG_DEBUG_FS @@ -41,7 +42,8 @@ static void config_debug_fs(struct q6audio_aio *audio) } #endif -static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long audio_ioctl_shared(struct file *file, unsigned int cmd, + void *arg) { struct asm_amrwbplus_cfg q6_amrwbplus_cfg; struct msm_audio_amrwbplus_config_v2 *amrwbplus_drv_config; @@ -103,16 +105,37 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) audio->stopped = 0; break; } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + break; + } + return rc; +} + +static long audio_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } case AUDIO_GET_AMRWBPLUS_CONFIG_V2: { if ((audio) && (arg) && (audio->codec_cfg)) { if (copy_to_user((void *)arg, audio->codec_cfg, sizeof(struct msm_audio_amrwbplus_config_v2))) { rc = -EFAULT; - pr_err("wb+ config get copy_to_user failed"); + pr_err("%s: copy_to_user for AUDIO_GET_AMRWBPLUS_CONFIG_V2 failed\n", + __func__); break; } } else { - pr_err("wb+ config v2 invalid parameters.."); + pr_err("%s: wb+ config v2 invalid parameters\n" + , __func__); rc = -EFAULT; break; } @@ -121,24 +144,143 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case AUDIO_SET_AMRWBPLUS_CONFIG_V2: { if ((audio) && (arg) && (audio->codec_cfg)) { if (copy_from_user(audio->codec_cfg, (void *)arg, - sizeof(struct msm_audio_amrwbplus_config_v2))) { + sizeof(struct msm_audio_amrwbplus_config_v2))) { rc = -EFAULT; - pr_err("wb+ config set copy_to_user_failed"); + pr_err("%s: copy_from_user for AUDIO_SET_AMRWBPLUS_CONFIG_V2 failed\n", + __func__); break; } } else { - pr_err("wb+ config invalid parameters.."); + pr_err("%s: wb+ config invalid parameters\n", + __func__); rc = -EFAULT; break; } break; } - default: + default: { pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); rc = audio->codec_ioctl(file, cmd, arg); + break; + } } return rc; } +#ifdef CONFIG_COMPAT +struct msm_audio_amrwbplus_config_v2_32 { + u32 size_bytes; + u32 version; + u32 num_channels; + u32 amr_band_mode; + u32 amr_dtx_mode; + u32 amr_frame_fmt; + u32 amr_lsf_idx; +}; + +enum { + AUDIO_GET_AMRWBPLUS_CONFIG_V2_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+2), + struct msm_audio_amrwbplus_config_v2_32), + AUDIO_SET_AMRWBPLUS_CONFIG_V2_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+3), + struct msm_audio_amrwbplus_config_v2_32) +}; + +static long audio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } + case AUDIO_GET_AMRWBPLUS_CONFIG_V2_32: { + if (audio && arg && (audio->codec_cfg)) { + struct msm_audio_amrwbplus_config_v2 *amrwbplus_config; + struct msm_audio_amrwbplus_config_v2_32 + amrwbplus_config_32; + amrwbplus_config = + (struct msm_audio_amrwbplus_config_v2 *) + audio->codec_cfg; + amrwbplus_config_32.size_bytes = + amrwbplus_config->size_bytes; + amrwbplus_config_32.version = + amrwbplus_config->version; + amrwbplus_config_32.num_channels = + amrwbplus_config->num_channels; + amrwbplus_config_32.amr_band_mode = + amrwbplus_config->amr_band_mode; + amrwbplus_config_32.amr_dtx_mode = + amrwbplus_config->amr_dtx_mode; + amrwbplus_config_32.amr_frame_fmt = + amrwbplus_config->amr_frame_fmt; + amrwbplus_config_32.amr_lsf_idx = + amrwbplus_config->amr_lsf_idx; + + if (copy_to_user((void *)arg, &amrwbplus_config_32, + sizeof(amrwbplus_config_32))) { + rc = -EFAULT; + pr_err("%s: copy_to_user for AUDIO_GET_AMRWBPLUS_CONFIG_V2_32 failed\n" + , __func__); + } + } else { + pr_err("%s: wb+ Get config v2 invalid parameters\n" + , __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_AMRWBPLUS_CONFIG_V2_32: { + if ((audio) && (arg) && (audio->codec_cfg)) { + struct msm_audio_amrwbplus_config_v2 *amrwbplus_config; + struct msm_audio_amrwbplus_config_v2_32 + amrwbplus_config_32; + + if (copy_from_user(&amrwbplus_config_32, (void *)arg, + sizeof(struct msm_audio_amrwbplus_config_v2_32))) { + rc = -EFAULT; + pr_err("%s: copy_from_user for AUDIO_SET_AMRWBPLUS_CONFIG_V2_32 failed\n" + , __func__); + break; + } + amrwbplus_config = + (struct msm_audio_amrwbplus_config_v2 *) + audio->codec_cfg; + amrwbplus_config->size_bytes = + amrwbplus_config_32.size_bytes; + amrwbplus_config->version = + amrwbplus_config_32.version; + amrwbplus_config->num_channels = + amrwbplus_config_32.num_channels; + amrwbplus_config->amr_band_mode = + amrwbplus_config_32.amr_band_mode; + amrwbplus_config->amr_dtx_mode = + amrwbplus_config_32.amr_dtx_mode; + amrwbplus_config->amr_frame_fmt = + amrwbplus_config_32.amr_frame_fmt; + amrwbplus_config->amr_lsf_idx = + amrwbplus_config_32.amr_lsf_idx; + } else { + pr_err("%s: wb+ config invalid parameters\n", + __func__); + rc = -EFAULT; + } + break; + } + default: { + pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); + rc = audio->codec_compat_ioctl(file, cmd, arg); + break; + } + } + return rc; +} +#else +#define audio_compat_ioctl NULL +#endif static int audio_open(struct inode *inode, struct file *file) { @@ -222,6 +364,7 @@ static const struct file_operations audio_amrwbplus_fops = { .release = audio_aio_release, .unlocked_ioctl = audio_ioctl, .fsync = audio_aio_fsync, + .compat_ioctl = audio_compat_ioctl }; struct miscdevice audio_amrwbplus_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c index 4511222c931e..2a6d357b8a32 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c +++ b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c @@ -16,6 +16,7 @@ */ #include +#include #include #include "audio_utils_aio.h" @@ -32,7 +33,8 @@ static const struct file_operations audio_aac_debug_fops = { }; #endif -static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long audio_ioctl_shared(struct file *file, unsigned int cmd, + void *arg) { struct q6audio_aio *audio = file->private_data; int rc = 0; @@ -131,86 +133,263 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) audio->stopped = 0; break; } + case AUDIO_SET_AAC_CONFIG: { + struct msm_audio_aac_config *aac_config; + uint16_t sce_left = 1, sce_right = 2; + + if (arg == NULL) { + pr_err("%s: NULL config pointer\n", __func__); + rc = -EINVAL; + break; + } + memcpy(audio->codec_cfg, arg, + sizeof(struct msm_audio_aac_config)); + aac_config = audio->codec_cfg; + if (aac_config->dual_mono_mode > + AUDIO_AAC_DUAL_MONO_PL_SR) { + pr_err("%s:AUDIO_SET_AAC_CONFIG: Invalid dual_mono mode =%d\n", + __func__, aac_config->dual_mono_mode); + } else { + /* convert the data from user into sce_left + * and sce_right based on the definitions + */ + pr_debug("%s: AUDIO_SET_AAC_CONFIG: modify dual_mono mode =%d\n", + __func__, aac_config->dual_mono_mode); + switch (aac_config->dual_mono_mode) { + case AUDIO_AAC_DUAL_MONO_PL_PR: + sce_left = 1; + sce_right = 1; + break; + case AUDIO_AAC_DUAL_MONO_SL_SR: + sce_left = 2; + sce_right = 2; + break; + case AUDIO_AAC_DUAL_MONO_SL_PR: + sce_left = 2; + sce_right = 1; + break; + case AUDIO_AAC_DUAL_MONO_PL_SR: + default: + sce_left = 1; + sce_right = 2; + break; + } + rc = q6asm_cfg_dual_mono_aac(audio->ac, + sce_left, sce_right); + if (rc < 0) + pr_err("%s: asm cmd dualmono failed rc=%d\n", + __func__, rc); + } break; + break; + } + case AUDIO_SET_AAC_MIX_CONFIG: { + u32 *mix_coeff = (u32 *)arg; + if (!arg) { + pr_err("%s: Invalid param for %s\n", + __func__, "AUDIO_SET_AAC_MIX_CONFIG"); + rc = -EINVAL; + break; + } + pr_debug("%s, AUDIO_SET_AAC_MIX_CONFIG", __func__); + pr_debug("%s, value of coeff = %d", + __func__, *mix_coeff); + q6asm_cfg_aac_sel_mix_coef(audio->ac, *mix_coeff); + if (rc < 0) + pr_err("%s asm aac_sel_mix_coef failed rc=%d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + break; + } + return rc; +} + +static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } case AUDIO_GET_AAC_CONFIG: { if (copy_to_user((void *)arg, audio->codec_cfg, sizeof(struct msm_audio_aac_config))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG failed\n" + , __func__); rc = -EFAULT; break; } break; } case AUDIO_SET_AAC_CONFIG: { - struct msm_audio_aac_config *aac_config; - if (copy_from_user(audio->codec_cfg, (void *)arg, - sizeof(struct msm_audio_aac_config))) { + struct msm_audio_aac_config aac_config; + if (copy_from_user(&aac_config, (void *)arg, + sizeof(aac_config))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG failed\n" + , __func__); rc = -EFAULT; - } else { - uint16_t sce_left = 1, sce_right = 2; - aac_config = audio->codec_cfg; - if (aac_config->dual_mono_mode > - AUDIO_AAC_DUAL_MONO_PL_SR) { - pr_err("%s:AUDIO_SET_AAC_CONFIG: Invalid dual_mono mode =%d\n", - __func__, aac_config->dual_mono_mode); - } else { - /* convert the data from user into sce_left - * and sce_right based on the definitions - */ - pr_debug("%s: AUDIO_SET_AAC_CONFIG: modify dual_mono mode =%d\n", - __func__, aac_config->dual_mono_mode); - switch (aac_config->dual_mono_mode) { - case AUDIO_AAC_DUAL_MONO_PL_PR: - sce_left = 1; - sce_right = 1; - break; - case AUDIO_AAC_DUAL_MONO_SL_SR: - sce_left = 2; - sce_right = 2; - break; - case AUDIO_AAC_DUAL_MONO_SL_PR: - sce_left = 2; - sce_right = 1; - break; - case AUDIO_AAC_DUAL_MONO_PL_SR: - default: - sce_left = 1; - sce_right = 2; - break; - } - rc = q6asm_cfg_dual_mono_aac(audio->ac, - sce_left, sce_right); - if (rc < 0) - pr_err("%s: asm cmd dualmono failed rc=%d\n", - __func__, rc); - } break; } + rc = audio_ioctl_shared(file, cmd, &aac_config); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n", + __func__, rc); break; } case AUDIO_SET_AAC_MIX_CONFIG: { + u32 mix_config; pr_debug("%s, AUDIO_SET_AAC_MIX_CONFIG", __func__); - if (copy_from_user(audio->codec_cfg, (void *)arg, - sizeof(unsigned long))) { + if (copy_from_user(&mix_config, (void *)arg, + sizeof(u32))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_MIX_CONFIG failed\n", + __func__); rc = -EFAULT; break; - } else { - unsigned long *mix_coeff = - (unsigned long *)audio->codec_cfg; - pr_debug("%s, value of coeff = %lu", - __func__, *mix_coeff); - q6asm_cfg_aac_sel_mix_coef(audio->ac, *mix_coeff); - if (rc < 0) - pr_err("%s asm aac_sel_mix_coef failed rc=%d\n", - __func__, rc); - break; } + rc = audio_ioctl_shared(file, cmd, &mix_config); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n", + __func__, rc); break; } - default: + default: { pr_debug("Calling utils ioctl\n"); rc = audio->codec_ioctl(file, cmd, arg); } + } return rc; } +#ifdef CONFIG_COMPAT +struct msm_audio_aac_config32 { + s16 format; + u16 audio_object; + u16 ep_config; /* 0 ~ 3 useful only obj = ERLC */ + u16 aac_section_data_resilience_flag; + u16 aac_scalefactor_data_resilience_flag; + u16 aac_spectral_data_resilience_flag; + u16 sbr_on_flag; + u16 sbr_ps_on_flag; + u16 dual_mono_mode; + u16 channel_configuration; + u16 sample_rate; +}; + +enum { + AUDIO_SET_AAC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config32), + AUDIO_GET_AAC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config32), +}; + +static long audio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } + case AUDIO_GET_AAC_CONFIG_32: { + struct msm_audio_aac_config *aac_config; + struct msm_audio_aac_config32 aac_config_32; + + aac_config = (struct msm_audio_aac_config *)audio->codec_cfg; + aac_config_32.format = aac_config->format; + aac_config_32.audio_object = aac_config->audio_object; + aac_config_32.ep_config = aac_config->ep_config; + aac_config_32.aac_section_data_resilience_flag = + aac_config->aac_section_data_resilience_flag; + aac_config_32.aac_scalefactor_data_resilience_flag = + aac_config->aac_scalefactor_data_resilience_flag; + aac_config_32.aac_spectral_data_resilience_flag = + aac_config->aac_spectral_data_resilience_flag; + aac_config_32.sbr_on_flag = aac_config->sbr_on_flag; + aac_config_32.sbr_ps_on_flag = aac_config->sbr_ps_on_flag; + aac_config_32.dual_mono_mode = aac_config->dual_mono_mode; + aac_config_32.channel_configuration = + aac_config->channel_configuration; + aac_config_32.sample_rate = aac_config->sample_rate; + + if (copy_to_user((void *)arg, &aac_config_32, + sizeof(aac_config_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + break; + } + case AUDIO_SET_AAC_CONFIG_32: { + struct msm_audio_aac_config aac_config; + struct msm_audio_aac_config32 aac_config_32; + pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__); + + if (copy_from_user(&aac_config_32, (void *)arg, + sizeof(aac_config_32))) { + pr_err( + "%s: copy_from_user for AUDIO_SET_AAC_CONFIG_32 failed", + __func__); + rc = -EFAULT; + break; + } + aac_config.format = aac_config_32.format; + aac_config.audio_object = aac_config_32.audio_object; + aac_config.ep_config = aac_config_32.ep_config; + aac_config.aac_section_data_resilience_flag = + aac_config_32.aac_section_data_resilience_flag; + aac_config.aac_scalefactor_data_resilience_flag = + aac_config_32.aac_scalefactor_data_resilience_flag; + aac_config.aac_spectral_data_resilience_flag = + aac_config_32.aac_spectral_data_resilience_flag; + aac_config.sbr_on_flag = aac_config_32.sbr_on_flag; + aac_config.sbr_ps_on_flag = aac_config_32.sbr_ps_on_flag; + aac_config.dual_mono_mode = aac_config_32.dual_mono_mode; + aac_config.channel_configuration = + aac_config_32.channel_configuration; + aac_config.sample_rate = aac_config_32.sample_rate; + + cmd = AUDIO_SET_AAC_CONFIG; + rc = audio_ioctl_shared(file, cmd, &aac_config); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. rc= %d\n", + __func__, rc); + break; + } + case AUDIO_SET_AAC_MIX_CONFIG: { + u32 mix_config; + pr_debug("%s, AUDIO_SET_AAC_MIX_CONFIG\n", __func__); + if (copy_from_user(&mix_config, (void *)arg, + sizeof(u32))) { + pr_err("%s: copy_from_user for AUDIO_SET_AAC_MIX_CONFIG failed\n" + , __func__); + rc = -EFAULT; + break; + } + rc = audio_ioctl_shared(file, cmd, &mix_config); + if (rc) + pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n", + __func__, rc); + break; + } + default: { + pr_debug("Calling utils ioctl\n"); + rc = audio->codec_compat_ioctl(file, cmd, arg); + } + } + return rc; +} +#else +#define audio_compat_ioctl NULL +#endif static int audio_open(struct inode *inode, struct file *file) { @@ -312,6 +491,7 @@ static const struct file_operations audio_aac_fops = { .release = audio_aio_release, .unlocked_ioctl = audio_ioctl, .fsync = audio_aio_fsync, + .compat_ioctl = audio_compat_ioctl }; struct miscdevice audio_multiaac_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils.c b/drivers/misc/qcom/qdsp6v2/audio_utils.c index 767579456176..88f46ba0148f 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "audio_utils.h" @@ -188,7 +189,95 @@ int audio_in_buf_alloc(struct q6audio_in *audio) return rc; } + +int audio_in_set_config(struct file *file, + struct msm_audio_config *cfg) +{ + int rc = 0; + struct q6audio_in *audio = file->private_data; + + if (audio->feedback != NON_TUNNEL_MODE) { + pr_err("%s:session id %d: Not sufficient permission to change the record mode\n", + __func__, audio->ac->session); + rc = -EACCES; + goto ret; + } + if ((cfg->buffer_count > PCM_BUF_COUNT) || + (cfg->buffer_count == 1)) + cfg->buffer_count = PCM_BUF_COUNT; + + audio->pcm_cfg.buffer_count = cfg->buffer_count; + audio->pcm_cfg.buffer_size = cfg->buffer_size; + audio->pcm_cfg.channel_count = cfg->channel_count; + audio->pcm_cfg.sample_rate = cfg->sample_rate; + if (audio->opened && audio->feedback == NON_TUNNEL_MODE) { + rc = q6asm_audio_client_buf_alloc(IN, audio->ac, + ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size), + audio->pcm_cfg.buffer_count); + if (rc < 0) { + pr_err("%s:session id %d: Buffer Alloc failed\n", + __func__, audio->ac->session); + rc = -ENOMEM; + goto ret; + } + } + audio->buf_alloc |= BUF_ALLOC_IN; + rc = 0; + pr_debug("%s:session id %d: AUDIO_SET_CONFIG %d %d\n", __func__, + audio->ac->session, audio->pcm_cfg.buffer_count, + audio->pcm_cfg.buffer_size); +ret: + return rc; +} /* ------------------- device --------------------- */ +static long audio_in_ioctl_shared(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_FLUSH: { + /* Make sure we're stopped and we wake any threads + * that might be blocked holding the read_lock. + * While audio->stopped read threads will always + * exit immediately. + */ + rc = audio_in_flush(audio); + if (rc < 0) + pr_err("%s:session id %d: Flush Fail rc=%d\n", + __func__, audio->ac->session, rc); + else { /* Register back the flushed read buffer with DSP */ + int cnt = 0; + while (cnt++ < audio->str_cfg.buffer_count) + q6asm_read(audio->ac); /* Push buffer to DSP */ + pr_debug("register the read buffer\n"); + } + break; + } + case AUDIO_PAUSE: { + pr_debug("%s:session id %d: AUDIO_PAUSE\n", __func__, + audio->ac->session); + if (audio->enabled) + audio_in_pause(audio); + break; + } + case AUDIO_GET_SESSION_ID: { + if (copy_to_user((void *) arg, &audio->ac->session, + sizeof(u16))) { + pr_err("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n", + __func__); + rc = -EFAULT; + } + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} + long audio_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -207,31 +296,11 @@ long audio_in_ioctl(struct file *file, mutex_lock(&audio->lock); switch (cmd) { - case AUDIO_FLUSH: { - /* Make sure we're stopped and we wake any threads - * that might be blocked holding the read_lock. - * While audio->stopped read threads will always - * exit immediately. - */ - rc = audio_in_flush(audio); - if (rc < 0) - pr_err("%s:session id %d: Flush Fail rc=%d\n", - __func__, audio->ac->session, rc); - else { /* Register back the flushed read buffer with DSP */ - int cnt = 0; - while (cnt++ < audio->str_cfg.buffer_count) - q6asm_read(audio->ac); /* Push buffer to DSP */ - pr_debug("register the read buffer\n"); - } + case AUDIO_FLUSH: + case AUDIO_PAUSE: + case AUDIO_GET_SESSION_ID: + rc = audio_in_ioctl_shared(file, cmd, arg); break; - } - case AUDIO_PAUSE: { - pr_debug("%s:session id %d: AUDIO_PAUSE\n", __func__, - audio->ac->session); - if (audio->enabled) - audio_in_pause(audio); - break; - } case AUDIO_GET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; memset(&cfg, 0, sizeof(cfg)); @@ -247,6 +316,8 @@ long audio_in_ioctl(struct file *file, case AUDIO_SET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { + pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG failed\n" + , __func__); rc = -EFAULT; break; } @@ -264,11 +335,11 @@ long audio_in_ioctl(struct file *file, rc = q6asm_audio_client_buf_alloc(OUT, audio->ac, ALIGN_BUF_SIZE(audio->str_cfg.buffer_size), audio->str_cfg.buffer_count); - if (rc < 0) { - pr_err("%s: session id %d: Buffer Alloc failed rc=%d\n", - __func__, audio->ac->session, rc); - rc = -ENOMEM; - break; + if (rc < 0) { + pr_err("%s: session id %d: Buffer Alloc failed rc=%d\n", + __func__, audio->ac->session, rc); + rc = -ENOMEM; + break; } } audio->buf_alloc |= BUF_ALLOC_OUT; @@ -279,13 +350,6 @@ long audio_in_ioctl(struct file *file, audio->str_cfg.buffer_count); break; } - case AUDIO_GET_SESSION_ID: { - if (copy_to_user((void *) arg, &audio->ac->session, - sizeof(unsigned short))) { - rc = -EFAULT; - } - break; - } case AUDIO_SET_BUF_CFG: { struct msm_audio_buf_cfg cfg; if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { @@ -333,40 +397,12 @@ long audio_in_ioctl(struct file *file, case AUDIO_SET_CONFIG: { struct msm_audio_config cfg; if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { + pr_err("%s: copy_from_user for AUDIO_SET_CONFIG failed\n", + __func__); rc = -EFAULT; break; } - if (audio->feedback != NON_TUNNEL_MODE) { - pr_err("%s:session id %d: Not sufficient permission to change the record mode\n", - __func__, - audio->ac->session); - rc = -EACCES; - break; - } - if ((cfg.buffer_count > PCM_BUF_COUNT) || - (cfg.buffer_count == 1)) - cfg.buffer_count = PCM_BUF_COUNT; - - audio->pcm_cfg.buffer_count = cfg.buffer_count; - audio->pcm_cfg.buffer_size = cfg.buffer_size; - audio->pcm_cfg.channel_count = cfg.channel_count; - audio->pcm_cfg.sample_rate = cfg.sample_rate; - if (audio->opened && audio->feedback == NON_TUNNEL_MODE) { - rc = q6asm_audio_client_buf_alloc(IN, audio->ac, - ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size), - audio->pcm_cfg.buffer_count); - if (rc < 0) { - pr_err("%s:session id %d: Buffer Alloc failed\n", - __func__, audio->ac->session); - rc = -ENOMEM; - break; - } - } - audio->buf_alloc |= BUF_ALLOC_IN; - rc = 0; - pr_debug("%s:session id %d: AUDIO_SET_CONFIG %d %d\n", __func__, - audio->ac->session, audio->pcm_cfg.buffer_count, - audio->pcm_cfg.buffer_size); + rc = audio_in_set_config(file, &cfg); break; } default: @@ -377,6 +413,223 @@ long audio_in_ioctl(struct file *file, return rc; } +#ifdef CONFIG_COMPAT +struct msm_audio_stats32 { + u32 byte_count; + u32 sample_count; + u32 unused[2]; +}; + +struct msm_audio_stream_config32 { + u32 buffer_size; + u32 buffer_count; +}; + +struct msm_audio_config32 { + u32 buffer_size; + u32 buffer_count; + u32 channel_count; + u32 sample_rate; + u32 type; + u32 meta_field; + u32 bits; + u32 unused[3]; +}; + +struct msm_audio_buf_cfg32 { + u32 meta_info_enable; + u32 frames_per_buf; +}; + +enum { + AUDIO_GET_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 3, + struct msm_audio_config32), + AUDIO_SET_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 4, + struct msm_audio_config32), + AUDIO_GET_STATS_32 = _IOR(AUDIO_IOCTL_MAGIC, 5, + struct msm_audio_stats32), + AUDIO_SET_STREAM_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 80, + struct msm_audio_stream_config32), + AUDIO_GET_STREAM_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 81, + struct msm_audio_stream_config32), + AUDIO_SET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 94, + struct msm_audio_buf_cfg32), + AUDIO_GET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 93, + struct msm_audio_buf_cfg32), +}; + +long audio_in_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + if (cmd == AUDIO_GET_STATS_32) { + struct msm_audio_stats32 stats_32; + memset(&stats_32, 0, sizeof(stats_32)); + stats_32.byte_count = atomic_read(&audio->in_bytes); + stats_32.sample_count = atomic_read(&audio->in_samples); + if (copy_to_user((void *) arg, &stats_32, sizeof(stats_32))) { + pr_err("%s: copy_to_user failed for AUDIO_GET_STATS_32\n", + __func__); + return -EFAULT; + } + return rc; + } + + mutex_lock(&audio->lock); + switch (cmd) { + case AUDIO_FLUSH: + case AUDIO_PAUSE: + case AUDIO_GET_SESSION_ID: + rc = audio_in_ioctl_shared(file, cmd, arg); + break; + case AUDIO_GET_STREAM_CONFIG_32: { + struct msm_audio_stream_config32 cfg_32; + memset(&cfg_32, 0, sizeof(cfg_32)); + cfg_32.buffer_size = audio->str_cfg.buffer_size; + cfg_32.buffer_count = audio->str_cfg.buffer_count; + if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) { + pr_err("%s: Copy to user failed\n", __func__); + rc = -EFAULT; + } + pr_debug("%s:session id %d: AUDIO_GET_STREAM_CONFIG %d %d\n", + __func__, audio->ac->session, + cfg_32.buffer_size, + cfg_32.buffer_count); + break; + } + case AUDIO_SET_STREAM_CONFIG_32: { + struct msm_audio_stream_config32 cfg_32; + struct msm_audio_stream_config cfg; + if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cfg.buffer_size = cfg_32.buffer_size; + cfg.buffer_count = cfg_32.buffer_count; + /* Minimum single frame size, + * but with in maximum frames number */ + if ((cfg.buffer_size < (audio->min_frame_size + + sizeof(struct meta_out_dsp))) || + (cfg.buffer_count < FRAME_NUM)) { + rc = -EINVAL; + break; + } + audio->str_cfg.buffer_size = cfg.buffer_size; + audio->str_cfg.buffer_count = cfg.buffer_count; + if (audio->opened) { + rc = q6asm_audio_client_buf_alloc(OUT, audio->ac, + ALIGN_BUF_SIZE(audio->str_cfg.buffer_size), + audio->str_cfg.buffer_count); + if (rc < 0) { + pr_err("%s: session id %d:\n", + __func__, audio->ac->session); + pr_err("Buffer Alloc failed rc=%d\n", rc); + rc = -ENOMEM; + break; + } + } + audio->buf_alloc |= BUF_ALLOC_OUT; + pr_debug("%s:session id %d: AUDIO_SET_STREAM_CONFIG %d %d\n", + __func__, audio->ac->session, + audio->str_cfg.buffer_size, + audio->str_cfg.buffer_count); + break; + } + case AUDIO_SET_BUF_CFG_32: { + struct msm_audio_buf_cfg32 cfg_32; + struct msm_audio_buf_cfg cfg; + if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_BUG_CFG_32 failed", + __func__); + rc = -EFAULT; + break; + } + cfg.meta_info_enable = cfg_32.meta_info_enable; + cfg.frames_per_buf = cfg_32.frames_per_buf; + + if ((audio->feedback == NON_TUNNEL_MODE) && + !cfg.meta_info_enable) { + rc = -EFAULT; + break; + } + + /* Restrict the num of frames per buf to coincide with + * default buf size */ + if (cfg.frames_per_buf > audio->max_frames_per_buf) { + rc = -EFAULT; + break; + } + audio->buf_cfg.meta_info_enable = cfg.meta_info_enable; + audio->buf_cfg.frames_per_buf = cfg.frames_per_buf; + pr_debug("%s:session id %d: Set-buf-cfg: meta[%d] framesperbuf[%d]\n", + __func__, audio->ac->session, cfg.meta_info_enable, + cfg.frames_per_buf); + break; + } + case AUDIO_GET_BUF_CFG_32: { + struct msm_audio_buf_cfg32 cfg_32; + pr_debug("%s:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n", + __func__, + audio->ac->session, audio->buf_cfg.meta_info_enable, + audio->buf_cfg.frames_per_buf); + cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable; + cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf; + + if (copy_to_user((void *)arg, &cfg_32, + sizeof(struct msm_audio_buf_cfg32))) { + pr_err("%s: Copy to user failed\n", __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_GET_CONFIG_32: { + struct msm_audio_config32 cfg_32; + cfg_32.buffer_size = audio->pcm_cfg.buffer_size; + cfg_32.buffer_count = audio->pcm_cfg.buffer_count; + cfg_32.channel_count = audio->pcm_cfg.channel_count; + cfg_32.sample_rate = audio->pcm_cfg.sample_rate; + cfg_32.type = audio->pcm_cfg.type; + cfg_32.meta_field = audio->pcm_cfg.meta_field; + cfg_32.bits = audio->pcm_cfg.bits; + + if (copy_to_user((void *)arg, &cfg_32, + sizeof(struct msm_audio_config32))) { + pr_err("%s: Copy to user failed\n", __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_CONFIG_32: { + struct msm_audio_config32 cfg_32; + struct msm_audio_config cfg; + if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cfg.buffer_size = cfg_32.buffer_size; + cfg.buffer_count = cfg_32.buffer_count; + cfg.channel_count = cfg_32.channel_count; + cfg.sample_rate = cfg_32.sample_rate; + cfg.type = cfg_32.type; + cfg.meta_field = cfg_32.meta_field; + cfg.bits = cfg_32.bits; + rc = audio_in_set_config(file, &cfg); + } + default: + /* call codec specific ioctl */ + rc = audio->enc_compat_ioctl(file, cmd, arg); + } + mutex_unlock(&audio->lock); + return rc; +} +#endif + ssize_t audio_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos) diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils.h b/drivers/misc/qcom/qdsp6v2/audio_utils.h index 7209724f484d..de1b7399ec2e 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils.h +++ b/drivers/misc/qcom/qdsp6v2/audio_utils.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -11,6 +11,7 @@ * */ #include +#include #include "q6audio_common.h" #define FRAME_NUM (8) @@ -28,8 +29,8 @@ #define ALIGN_BUF_SIZE(size) ((size + 4095) & (~4095)) struct timestamp { - unsigned long lowpart; - unsigned long highpart; + u32 lowpart; + u32 highpart; } __packed; struct meta_in { @@ -89,6 +90,7 @@ struct q6audio_in { uint16_t min_frame_size; uint16_t max_frames_per_buf; long (*enc_ioctl)(struct file *, unsigned int, unsigned long); + long (*enc_compat_ioctl)(struct file *, unsigned int, unsigned long); }; int audio_in_enable(struct q6audio_in *audio); @@ -96,9 +98,16 @@ int audio_in_disable(struct q6audio_in *audio); int audio_in_buf_alloc(struct q6audio_in *audio); long audio_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +long audio_in_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg); +#else +#define audio_in_compat_ioctl NULL +#endif ssize_t audio_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos); ssize_t audio_in_write(struct file *file, const char __user *buf, size_t count, loff_t *pos); int audio_in_release(struct inode *inode, struct file *file); +int audio_in_set_config(struct file *file, struct msm_audio_config *cfg); diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c index d513d41256ef..bf952677f3bf 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "audio_utils_aio.h" #ifdef CONFIG_USE_DEV_CTRL_VOLUME #include @@ -70,6 +71,14 @@ ssize_t audio_aio_debug_read(struct file *file, char __user *buf, } #endif +static long audio_aio_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +#ifdef CONFIG_COMPAT +static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +#else +#define audio_aio_compat_ioctl NULL +#endif int insert_eos_buf(struct q6audio_aio *audio, struct audio_aio_buffer_node *buf_node) { @@ -140,11 +149,11 @@ static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr, return *region ? 0 : -1; } -static unsigned long audio_aio_ion_fixup(struct q6audio_aio *audio, void *addr, +static phys_addr_t audio_aio_ion_fixup(struct q6audio_aio *audio, void *addr, unsigned long len, int ref_up, void **kvaddr) { struct audio_aio_ion_region *region; - unsigned long paddr; + phys_addr_t paddr; int ret; ret = audio_aio_ion_lookup_vaddr(audio, addr, len, ®ion); @@ -675,19 +684,15 @@ static int audio_aio_events_pending(struct q6audio_aio *audio) return empty || audio->event_abort; } -static long audio_aio_process_event_req(struct q6audio_aio *audio, - void __user *arg) +static long audio_aio_process_event_req_common(struct q6audio_aio *audio, + struct msm_audio_event *usr_evt) { long rc; - struct msm_audio_event usr_evt; struct audio_aio_event *drv_evt = NULL; int timeout; unsigned long flags; - if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event))) - return -EFAULT; - - timeout = (int)usr_evt.timeout_ms; + timeout = usr_evt->timeout_ms; if (timeout > 0) { rc = wait_event_interruptible_timeout(audio->event_wait, @@ -718,8 +723,8 @@ static long audio_aio_process_event_req(struct q6audio_aio *audio, list_del(&drv_evt->list); } if (drv_evt) { - usr_evt.event_type = drv_evt->event_type; - usr_evt.event_payload = drv_evt->payload; + usr_evt->event_type = drv_evt->event_type; + usr_evt->event_payload = drv_evt->payload; list_add_tail(&drv_evt->list, &audio->free_event_queue); } else { pr_err("%s[%p]:Unexpected path\n", __func__, audio); @@ -753,12 +758,134 @@ static long audio_aio_process_event_req(struct q6audio_aio *audio, audio_aio_flush(audio); } - if (copy_to_user(arg, &usr_evt, sizeof(usr_evt))) - rc = -EFAULT; - return rc; } +static long audio_aio_process_event_req(struct q6audio_aio *audio, + void __user *arg) +{ + long rc; + struct msm_audio_event usr_evt; + + if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event))) { + pr_err("%s: copy_from_user failed\n", __func__); + return -EFAULT; + } + + rc = audio_aio_process_event_req_common(audio, &usr_evt); + + if (copy_to_user(arg, &usr_evt, sizeof(usr_evt))) { + pr_err("%s: copy_to_user failed\n", __func__); + rc = -EFAULT; + } + return rc; +} + +#ifdef CONFIG_COMPAT + +struct msm_audio_aio_buf32 { + compat_uptr_t buf_addr; + u32 buf_len; + u32 data_len; + compat_uptr_t private_data; + u16 mfield_sz; /*only useful for data has meta field */ +}; + +struct msm_audio_bitstream_info32 { + u32 codec_type; + u32 chan_info; + u32 sample_rate; + u32 bit_stream_info; + u32 bit_rate; + u32 unused[3]; +}; + +struct msm_audio_bitstream_error_info32 { + u32 dec_id; + u32 err_msg_indicator; + u32 err_type; +}; + +union msm_audio_event_payload32 { + struct msm_audio_aio_buf32 aio_buf; + struct msm_audio_bitstream_info32 stream_info; + struct msm_audio_bitstream_error_info32 error_info; + s32 reserved; +}; + +struct msm_audio_event32 { + s32 event_type; + s32 timeout_ms; + union msm_audio_event_payload32 event_payload; +}; + +static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, + void __user *arg) +{ + long rc; + struct msm_audio_event32 usr_evt_32; + struct msm_audio_event usr_evt; + + if (copy_from_user(&usr_evt_32, arg, + sizeof(struct msm_audio_event32))) { + pr_err("%s: copy_from_user failed\n", __func__); + return -EFAULT; + } + usr_evt.timeout_ms = usr_evt_32.timeout_ms; + + rc = audio_aio_process_event_req_common(audio, &usr_evt); + + usr_evt_32.event_type = usr_evt.event_type; + switch (usr_evt_32.event_type) { + case AUDIO_EVENT_SUSPEND: + case AUDIO_EVENT_RESUME: + case AUDIO_EVENT_WRITE_DONE: + case AUDIO_EVENT_READ_DONE: + usr_evt_32.event_payload.aio_buf.buf_addr = + ptr_to_compat(usr_evt.event_payload.aio_buf.buf_addr); + usr_evt_32.event_payload.aio_buf.buf_len = + usr_evt.event_payload.aio_buf.buf_len; + usr_evt_32.event_payload.aio_buf.data_len = + usr_evt.event_payload.aio_buf.data_len; + usr_evt_32.event_payload.aio_buf.private_data = + ptr_to_compat(usr_evt.event_payload.aio_buf.private_data); + usr_evt_32.event_payload.aio_buf.mfield_sz = + usr_evt.event_payload.aio_buf.mfield_sz; + break; + case AUDIO_EVENT_STREAM_INFO: + usr_evt_32.event_payload.stream_info.codec_type = + usr_evt.event_payload.stream_info.codec_type; + usr_evt_32.event_payload.stream_info.chan_info = + usr_evt.event_payload.stream_info.chan_info; + usr_evt_32.event_payload.stream_info.sample_rate = + usr_evt.event_payload.stream_info.sample_rate; + usr_evt_32.event_payload.stream_info.bit_stream_info = + usr_evt.event_payload.stream_info.bit_stream_info; + usr_evt_32.event_payload.stream_info.bit_rate = + usr_evt.event_payload.stream_info.bit_rate; + break; + case AUDIO_EVENT_BITSTREAM_ERROR_INFO: + usr_evt_32.event_payload.error_info.dec_id = + usr_evt.event_payload.error_info.dec_id; + usr_evt_32.event_payload.error_info.err_msg_indicator = + usr_evt.event_payload.error_info.err_msg_indicator; + usr_evt_32.event_payload.error_info.err_type = + usr_evt.event_payload.error_info.err_type; + break; + default: + pr_err("%s: unknown audio event type = %d", + __func__, usr_evt_32.event_type); + rc = -EINVAL; + return rc; + } + if (copy_to_user(arg, &usr_evt_32, sizeof(usr_evt_32))) { + pr_err("%s: copy_to_user failed\n", __func__); + rc = -EFAULT; + } + return rc; +} +#endif + static int audio_aio_ion_check(struct q6audio_aio *audio, void *vaddr, unsigned long len) { @@ -984,22 +1111,10 @@ static void audio_aio_async_read(struct q6audio_aio *audio, pr_err("%s[%p]:failed\n", __func__, audio); } -static int audio_aio_buf_add(struct q6audio_aio *audio, unsigned dir, - void __user *arg) +static int audio_aio_buf_add_shared(struct q6audio_aio *audio, u32 dir, + struct audio_aio_buffer_node *buf_node) { unsigned long flags; - struct audio_aio_buffer_node *buf_node; - - - buf_node = kzalloc(sizeof(*buf_node), GFP_KERNEL); - - if (!buf_node) - return -ENOMEM; - - if (copy_from_user(&buf_node->buf, arg, sizeof(buf_node->buf))) { - kfree(buf_node); - return -EFAULT; - } pr_debug("%s[%p]:node %p dir %x buf_addr %p buf_len %d data_len %d\n", __func__, audio, buf_node, dir, buf_node->buf.buf_addr, @@ -1081,6 +1196,57 @@ static int audio_aio_buf_add(struct q6audio_aio *audio, unsigned dir, } return 0; } +#ifdef CONFIG_COMPAT +static int audio_aio_buf_add_compat(struct q6audio_aio *audio, u32 dir, + void __user *arg) +{ + struct audio_aio_buffer_node *buf_node; + struct msm_audio_aio_buf32 aio_buf_32; + + buf_node = kzalloc(sizeof(*buf_node), GFP_KERNEL); + + if (!buf_node) { + pr_err("%s: Buffer node alloc failed\n", __func__); + return -ENOMEM; + } + + + if (copy_from_user(&aio_buf_32, arg, sizeof(aio_buf_32))) { + kfree(buf_node); + pr_err("%s: copy_from_user failed\n", __func__); + return -EFAULT; + } + + buf_node->buf.buf_addr = compat_ptr(aio_buf_32.buf_addr); + buf_node->buf.buf_len = aio_buf_32.buf_len; + buf_node->buf.data_len = aio_buf_32.data_len; + buf_node->buf.private_data = compat_ptr(aio_buf_32.private_data); + buf_node->buf.mfield_sz = aio_buf_32.mfield_sz; + + return audio_aio_buf_add_shared(audio, dir, buf_node); +} +#endif + +static int audio_aio_buf_add(struct q6audio_aio *audio, u32 dir, + void __user *arg) +{ + struct audio_aio_buffer_node *buf_node; + + buf_node = kzalloc(sizeof(*buf_node), GFP_KERNEL); + + if (!buf_node) { + pr_err("%s: Buffer node alloc failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(&buf_node->buf, arg, sizeof(buf_node->buf))) { + kfree(buf_node); + pr_err("%s: copy_from_user failed\n", __func__); + return -EFAULT; + } + + return audio_aio_buf_add_shared(audio, dir, buf_node); +} void audio_aio_ioport_reset(struct q6audio_aio *audio) { @@ -1149,7 +1315,7 @@ int audio_aio_open(struct q6audio_aio *audio, struct file *file) audio->opened = 1; file->private_data = audio; audio->codec_ioctl = audio_aio_ioctl; - + audio->codec_compat_ioctl = audio_aio_compat_ioctl; for (i = 0; i < AUDIO_EVENT_NUM; i++) { e_node = kmalloc(sizeof(struct audio_aio_event), GFP_KERNEL); if (e_node) @@ -1189,66 +1355,18 @@ fail: return rc; } -long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long audio_aio_shared_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct q6audio_aio *audio = file->private_data; int rc = 0; switch (cmd) { - case AUDIO_GET_STATS: { - struct msm_audio_stats stats; - uint64_t timestamp; - memset(&stats, 0, sizeof(struct msm_audio_stats)); - stats.byte_count = atomic_read(&audio->in_bytes); - stats.sample_count = atomic_read(&audio->in_samples); - rc = q6asm_get_session_time(audio->ac, ×tamp); - if (rc >= 0) - memcpy(&stats.unused[0], ×tamp, sizeof(timestamp)); - else - pr_debug("Error while getting timestamp\n"); - if (copy_to_user((void *)arg, &stats, sizeof(stats))) - rc = -EFAULT; - break; - } - case AUDIO_GET_EVENT: { - pr_debug("%s[%p]:AUDIO_GET_EVENT\n", __func__, audio); - if (mutex_trylock(&audio->get_event_lock)) { - rc = audio_aio_process_event_req(audio, - (void __user *)arg); - mutex_unlock(&audio->get_event_lock); - } else - rc = -EBUSY; - break; - } case AUDIO_ABORT_GET_EVENT: { audio->event_abort = 1; wake_up(&audio->event_wait); break; } - case AUDIO_ASYNC_WRITE: { - mutex_lock(&audio->write_lock); - if (audio->drv_status & ADRV_STATUS_FSYNC) - rc = -EBUSY; - else { - if (audio->enabled) - rc = audio_aio_buf_add(audio, 1, - (void __user *)arg); - else - rc = -EPERM; - } - mutex_unlock(&audio->write_lock); - break; - } - case AUDIO_ASYNC_READ: { - mutex_lock(&audio->read_lock); - if ((audio->feedback) && (audio->enabled)) - rc = audio_aio_buf_add(audio, 0, - (void __user *)arg); - else - rc = -EPERM; - mutex_unlock(&audio->read_lock); - break; - } case AUDIO_OUTPORT_FLUSH: { pr_debug("%s[%p]:AUDIO_OUTPORT_FLUSH\n", __func__, audio); mutex_lock(&audio->read_lock); @@ -1342,28 +1460,93 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_unlock(&audio->lock); break; } - case AUDIO_REGISTER_ION: { - struct msm_audio_ion_info info; - pr_debug("%s[%p]:AUDIO_REGISTER_ION\n", __func__, audio); + case AUDIO_GET_SESSION_ID: { mutex_lock(&audio->lock); - if (copy_from_user(&info, (void *)arg, sizeof(info))) + if (copy_to_user((void *)arg, &audio->ac->session, + sizeof(u16))) { + pr_err("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n", + __func__); rc = -EFAULT; - else - rc = audio_aio_ion_add(audio, &info); + } mutex_unlock(&audio->lock); break; } - case AUDIO_DEREGISTER_ION: { - struct msm_audio_ion_info info; - mutex_lock(&audio->lock); - pr_debug("%s[%p]:AUDIO_DEREGISTER_ION\n", __func__, audio); - if (copy_from_user(&info, (void *)arg, sizeof(info))) - rc = -EFAULT; + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; + + +} + +static long audio_aio_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_ABORT_GET_EVENT: + case AUDIO_OUTPORT_FLUSH: + case AUDIO_STOP: + case AUDIO_PAUSE: + case AUDIO_FLUSH: + rc = audio_aio_shared_ioctl(file, cmd, arg); + break; + case AUDIO_GET_STATS: { + struct msm_audio_stats stats; + uint64_t timestamp; + memset(&stats, 0, sizeof(struct msm_audio_stats)); + stats.byte_count = atomic_read(&audio->in_bytes); + stats.sample_count = atomic_read(&audio->in_samples); + rc = q6asm_get_session_time(audio->ac, ×tamp); + if (rc >= 0) + memcpy(&stats.unused[0], ×tamp, sizeof(timestamp)); else - rc = audio_aio_ion_remove(audio, &info); - mutex_unlock(&audio->lock); + pr_debug("Error while getting timestamp\n"); + if (copy_to_user((void *)arg, &stats, sizeof(stats))) { + pr_err("%s: copy_frm_user for AUDIO_GET_STATS failed\n", + __func__); + rc = -EFAULT; + } break; } + case AUDIO_GET_EVENT: { + pr_debug("%s[%p]:AUDIO_GET_EVENT\n", __func__, audio); + if (mutex_trylock(&audio->get_event_lock)) { + rc = audio_aio_process_event_req(audio, + (void __user *)arg); + mutex_unlock(&audio->get_event_lock); + } else + rc = -EBUSY; + break; + } + case AUDIO_ASYNC_WRITE: { + mutex_lock(&audio->write_lock); + if (audio->drv_status & ADRV_STATUS_FSYNC) + rc = -EBUSY; + else { + if (audio->enabled) + rc = audio_aio_buf_add(audio, 1, + (void __user *)arg); + else + rc = -EPERM; + } + mutex_unlock(&audio->write_lock); + break; + } + case AUDIO_ASYNC_READ: { + mutex_lock(&audio->read_lock); + if ((audio->feedback) && (audio->enabled)) + rc = audio_aio_buf_add(audio, 0, + (void __user *)arg); + else + rc = -EPERM; + mutex_unlock(&audio->read_lock); + break; + } + case AUDIO_GET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; mutex_lock(&audio->lock); @@ -1372,8 +1555,12 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) cfg.buffer_count = audio->str_cfg.buffer_count; pr_debug("%s[%p]:GET STREAM CFG %d %d\n", __func__, audio, cfg.buffer_size, cfg.buffer_count); - if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) + if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) { + pr_err( + "%s: copy_to_user for AUDIO_GET_STREAM_CONFIG failed\n", + __func__); rc = -EFAULT; + } mutex_unlock(&audio->lock); break; } @@ -1382,6 +1569,9 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_debug("%s[%p]:SET STREAM CONFIG\n", __func__, audio); mutex_lock(&audio->lock); if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { + pr_err( + "%s: copy_from_user for AUDIO_SET_STREAM_CONFIG failed\n", + __func__); rc = -EFAULT; mutex_unlock(&audio->lock); break; @@ -1395,8 +1585,12 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case AUDIO_GET_CONFIG: { struct msm_audio_config cfg; mutex_lock(&audio->lock); - if (copy_to_user((void *)arg, &audio->pcm_cfg, sizeof(cfg))) + if (copy_to_user((void *)arg, &audio->pcm_cfg, sizeof(cfg))) { + pr_err( + "%s: copy_to_user for AUDIO_GET_CONFIG failed\n", + __func__); rc = -EFAULT; + } mutex_unlock(&audio->lock); break; } @@ -1405,6 +1599,9 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_err("%s[%p]:AUDIO_SET_CONFIG\n", __func__, audio); mutex_lock(&audio->lock); if (copy_from_user(&config, (void *)arg, sizeof(config))) { + pr_err( + "%s: copy_from_user for AUDIO_SET_CONFIG failed\n", + __func__); rc = -EFAULT; mutex_unlock(&audio->lock); break; @@ -1435,6 +1632,9 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct msm_audio_buf_cfg cfg; mutex_lock(&audio->lock); if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { + pr_err( + "%s: copy_from_user for AUDIO_GET_BUF CONFIG failed\n", + __func__); rc = -EFAULT; mutex_unlock(&audio->lock); break; @@ -1461,22 +1661,365 @@ long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_lock(&audio->lock); if (copy_to_user((void *)arg, &audio->buf_cfg, - sizeof(struct msm_audio_buf_cfg))) - rc = -EFAULT; - mutex_unlock(&audio->lock); - break; - } - case AUDIO_GET_SESSION_ID: { - mutex_lock(&audio->lock); - if (copy_to_user((void *)arg, &audio->ac->session, - sizeof(unsigned short))) { + sizeof(struct msm_audio_buf_cfg))) { + pr_err( + "%s: copy_to_user for AUDIO_GET_BUF_CONFIG failed\n", + __func__); rc = -EFAULT; } mutex_unlock(&audio->lock); break; } + case AUDIO_REGISTER_ION: { + struct msm_audio_ion_info info; + pr_debug("%s[%p]:AUDIO_REGISTER_ION\n", __func__, audio); + mutex_lock(&audio->lock); + if (copy_from_user(&info, (void *)arg, sizeof(info))) { + pr_err( + "%s: copy_from_user for AUDIO_REGISTER_ION failed\n", + __func__); + rc = -EFAULT; + } else { + rc = audio_aio_ion_add(audio, &info); + } + mutex_unlock(&audio->lock); + break; + } + case AUDIO_DEREGISTER_ION: { + struct msm_audio_ion_info info; + mutex_lock(&audio->lock); + pr_debug("%s[%p]:AUDIO_DEREGISTER_ION\n", __func__, audio); + if (copy_from_user(&info, (void *)arg, sizeof(info))) { + pr_err( + "%s: copy_from_user for AUDIO_DEREGISTER_ION failed\n", + __func__); + rc = -EFAULT; + } else { + rc = audio_aio_ion_remove(audio, &info); + } + mutex_unlock(&audio->lock); + break; + } default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); rc = -EINVAL; } return rc; } + +#ifdef CONFIG_COMPAT +struct msm_audio_stream_config32 { + u32 buffer_size; + u32 buffer_count; +}; + +struct msm_audio_stats32 { + u32 byte_count; + u32 sample_count; + u32 unused[2]; +}; + +struct msm_audio_config32 { + u32 buffer_size; + u32 buffer_count; + u32 channel_count; + u32 sample_rate; + u32 type; + u32 meta_field; + u32 bits; + u32 unused[3]; +}; + +struct msm_audio_buf_cfg32 { + u32 meta_info_enable; + u32 frames_per_buf; +}; + +struct msm_audio_ion_info32 { + int fd; + compat_uptr_t vaddr; +}; + +enum { + AUDIO_GET_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 3, + struct msm_audio_config32), + AUDIO_SET_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 4, + struct msm_audio_config32), + AUDIO_GET_STATS_32 = _IOR(AUDIO_IOCTL_MAGIC, 5, + struct msm_audio_stats32), + AUDIO_GET_EVENT_32 = _IOR(AUDIO_IOCTL_MAGIC, 13, + struct msm_audio_event32), + AUDIO_ASYNC_WRITE_32 = _IOW(AUDIO_IOCTL_MAGIC, 17, + struct msm_audio_aio_buf32), + AUDIO_ASYNC_READ_32 = _IOW(AUDIO_IOCTL_MAGIC, 18, + struct msm_audio_aio_buf32), + AUDIO_SET_STREAM_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 80, + struct msm_audio_stream_config32), + AUDIO_GET_STREAM_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 81, + struct msm_audio_stream_config32), + AUDIO_GET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 93, + struct msm_audio_buf_cfg32), + AUDIO_SET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 94, + struct msm_audio_buf_cfg32), + AUDIO_REGISTER_ION_32 = _IOW(AUDIO_IOCTL_MAGIC, 97, + struct msm_audio_ion_info32), + AUDIO_DEREGISTER_ION_32 = _IOW(AUDIO_IOCTL_MAGIC, 98, + struct msm_audio_ion_info32), +}; + +static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_ABORT_GET_EVENT: + case AUDIO_OUTPORT_FLUSH: + case AUDIO_STOP: + case AUDIO_PAUSE: + case AUDIO_FLUSH: + rc = audio_aio_shared_ioctl(file, cmd, arg); + break; + case AUDIO_GET_STATS_32: { + struct msm_audio_stats32 stats; + uint64_t timestamp; + memset(&stats, 0, sizeof(struct msm_audio_stats32)); + stats.byte_count = atomic_read(&audio->in_bytes); + stats.sample_count = atomic_read(&audio->in_samples); + rc = q6asm_get_session_time(audio->ac, ×tamp); + if (rc >= 0) + memcpy(&stats.unused[0], ×tamp, sizeof(timestamp)); + else + pr_debug("Error while getting timestamp\n"); + if (copy_to_user((void *)arg, &stats, sizeof(stats))) { + pr_err( + "%s: copy_to_user for AUDIO_GET_STATS_32 failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_GET_EVENT_32: { + pr_debug("%s[%p]:AUDIO_GET_EVENT\n", __func__, audio); + if (mutex_trylock(&audio->get_event_lock)) { + rc = audio_aio_process_event_req_compat(audio, + (void __user *)arg); + mutex_unlock(&audio->get_event_lock); + } else + rc = -EBUSY; + break; + } + case AUDIO_ASYNC_WRITE_32: { + mutex_lock(&audio->write_lock); + if (audio->drv_status & ADRV_STATUS_FSYNC) + rc = -EBUSY; + else { + if (audio->enabled) + rc = audio_aio_buf_add_compat(audio, 1, + (void __user *)arg); + else + rc = -EPERM; + } + mutex_unlock(&audio->write_lock); + break; + } + case AUDIO_ASYNC_READ_32: { + mutex_lock(&audio->read_lock); + if ((audio->feedback) && (audio->enabled)) + rc = audio_aio_buf_add_compat(audio, 0, + (void __user *)arg); + else + rc = -EPERM; + mutex_unlock(&audio->read_lock); + break; + } + + case AUDIO_GET_STREAM_CONFIG_32: { + struct msm_audio_stream_config32 cfg; + mutex_lock(&audio->lock); + memset(&cfg, 0, sizeof(cfg)); + cfg.buffer_size = audio->str_cfg.buffer_size; + cfg.buffer_count = audio->str_cfg.buffer_count; + pr_debug("%s[%p]:GET STREAM CFG %d %d\n", + __func__, audio, cfg.buffer_size, cfg.buffer_count); + if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) { + pr_err("%s: copy_to_user for AUDIO_GET_STREAM_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + } + mutex_unlock(&audio->lock); + break; + } + case AUDIO_SET_STREAM_CONFIG_32: { + struct msm_audio_stream_config32 cfg_32; + struct msm_audio_stream_config cfg; + pr_debug("%s[%p]:SET STREAM CONFIG\n", __func__, audio); + mutex_lock(&audio->lock); + if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + mutex_unlock(&audio->lock); + break; + } + cfg.buffer_size = cfg_32.buffer_size; + cfg.buffer_count = cfg_32.buffer_count; + + audio->str_cfg.buffer_size = FRAME_SIZE; + audio->str_cfg.buffer_count = FRAME_NUM; + rc = 0; + mutex_unlock(&audio->lock); + break; + } + case AUDIO_GET_CONFIG_32: { + struct msm_audio_config32 cfg_32; + mutex_lock(&audio->lock); + cfg_32.buffer_size = audio->pcm_cfg.buffer_size; + cfg_32.buffer_count = audio->pcm_cfg.buffer_count; + cfg_32.channel_count = audio->pcm_cfg.channel_count; + cfg_32.sample_rate = audio->pcm_cfg.sample_rate; + cfg_32.type = audio->pcm_cfg.type; + cfg_32.meta_field = audio->pcm_cfg.meta_field; + cfg_32.bits = audio->pcm_cfg.bits; + + if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + } + mutex_unlock(&audio->lock); + break; + } + case AUDIO_SET_CONFIG_32: { + struct msm_audio_config config; + struct msm_audio_config32 config_32; + mutex_lock(&audio->lock); + + if (audio->feedback != NON_TUNNEL_MODE) { + pr_err("%s[%p]:Not sufficient permission to change the playback mode\n", + __func__, audio); + rc = -EACCES; + mutex_unlock(&audio->lock); + break; + } + pr_err("%s[%p]:AUDIO_SET_CONFIG\n", __func__, audio); + if (copy_from_user(&config_32, (void *)arg, + sizeof(config_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + mutex_unlock(&audio->lock); + break; + } + config.buffer_size = config_32.buffer_size; + config.buffer_count = config_32.buffer_count; + config.channel_count = config_32.channel_count; + config.sample_rate = config_32.sample_rate; + config.type = config_32.type; + config.meta_field = config_32.meta_field; + config.bits = config_32.bits; + + if ((config.buffer_count > PCM_BUF_COUNT) || + (config.buffer_count == 1)) + config.buffer_count = PCM_BUF_COUNT; + + if (config.buffer_size < PCM_BUFSZ_MIN) + config.buffer_size = PCM_BUFSZ_MIN; + + audio->pcm_cfg.buffer_count = config.buffer_count; + audio->pcm_cfg.buffer_size = config.buffer_size; + audio->pcm_cfg.channel_count = config.channel_count; + audio->pcm_cfg.sample_rate = config.sample_rate; + rc = 0; + mutex_unlock(&audio->lock); + break; + } + case AUDIO_SET_BUF_CFG_32: { + struct msm_audio_buf_cfg cfg; + struct msm_audio_buf_cfg32 cfg_32; + mutex_lock(&audio->lock); + if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { + pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + mutex_unlock(&audio->lock); + break; + } + cfg.meta_info_enable = cfg_32.meta_info_enable; + cfg.frames_per_buf = cfg_32.frames_per_buf; + + if ((audio->feedback == NON_TUNNEL_MODE) && + !cfg.meta_info_enable) { + rc = -EFAULT; + mutex_unlock(&audio->lock); + break; + } + + audio->buf_cfg.meta_info_enable = cfg.meta_info_enable; + pr_debug("%s[%p]:session id %d: Set-buf-cfg: meta[%d]", + __func__, audio, + audio->ac->session, cfg.meta_info_enable); + mutex_unlock(&audio->lock); + break; + } + case AUDIO_GET_BUF_CFG_32: { + struct msm_audio_buf_cfg32 cfg_32; + pr_debug("%s[%p]:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n", + __func__, audio, + audio->ac->session, audio->buf_cfg.meta_info_enable, + audio->buf_cfg.frames_per_buf); + + mutex_lock(&audio->lock); + cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable; + cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf; + if (copy_to_user((void *)arg, &cfg_32, + sizeof(struct msm_audio_buf_cfg32))) { + pr_err("%s: copy_to_user for AUDIO_GET_BUF_CFG_32 failed\n", + __func__); + rc = -EFAULT; + } + mutex_unlock(&audio->lock); + break; + } + case AUDIO_REGISTER_ION_32: { + struct msm_audio_ion_info32 info_32; + struct msm_audio_ion_info info; + pr_debug("%s[%p]:AUDIO_REGISTER_ION\n", __func__, audio); + mutex_lock(&audio->lock); + if (copy_from_user(&info_32, (void *)arg, sizeof(info_32))) { + pr_err("%s: copy_from_user for AUDIO_REGISTER_ION_32 failed\n", + __func__); + rc = -EFAULT; + } else { + info.fd = info_32.fd; + info.vaddr = compat_ptr(info_32.vaddr); + rc = audio_aio_ion_add(audio, &info); + } + mutex_unlock(&audio->lock); + break; + } + case AUDIO_DEREGISTER_ION_32: { + struct msm_audio_ion_info32 info_32; + struct msm_audio_ion_info info; + mutex_lock(&audio->lock); + pr_debug("%s[%p]:AUDIO_DEREGISTER_ION\n", __func__, audio); + if (copy_from_user(&info_32, (void *)arg, sizeof(info_32))) { + pr_err("%s: copy_from_user for AUDIO_DEREGISTER_ION_32 failed\n", + __func__); + rc = -EFAULT; + } else { + info.fd = info_32.fd; + info.vaddr = compat_ptr(info_32.vaddr); + rc = audio_aio_ion_remove(audio, &info); + } + mutex_unlock(&audio->lock); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} +#endif diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.h b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.h index ae9deba7f127..3cea26ba0a75 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.h +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.h @@ -71,8 +71,8 @@ }) struct timestamp { - unsigned long lowpart; - unsigned long highpart; + u32 lowpart; + u32 highpart; } __packed; struct meta_out_dsp { @@ -189,6 +189,7 @@ struct q6audio_aio { int rflush; /* Read flush */ int wflush; /* Write flush */ long (*codec_ioctl)(struct file *, unsigned int, unsigned long); + long (*codec_compat_ioctl)(struct file *, unsigned int, unsigned long); }; void audio_aio_async_write_ack(struct q6audio_aio *audio, uint32_t token, @@ -208,7 +209,6 @@ int audio_aio_enable(struct q6audio_aio *audio); void audio_aio_post_event(struct q6audio_aio *audio, int type, union msm_audio_event_payload payload); int audio_aio_release(struct inode *inode, struct file *file); -long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int audio_aio_fsync(struct file *file, loff_t start, loff_t end, int datasync); void audio_aio_async_out_flush(struct q6audio_aio *audio); void audio_aio_async_in_flush(struct q6audio_aio *audio); diff --git a/drivers/misc/qcom/qdsp6v2/audio_wma.c b/drivers/misc/qcom/qdsp6v2/audio_wma.c index 5e3de8609803..93f6a85b4235 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_wma.c +++ b/drivers/misc/qcom/qdsp6v2/audio_wma.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -17,6 +17,7 @@ #include #include +#include #include "audio_utils_aio.h" #ifdef CONFIG_DEBUG_FS @@ -26,7 +27,8 @@ static const struct file_operations audio_wma_debug_fops = { }; #endif -static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long audio_ioctl_shared(struct file *file, unsigned int cmd, + void *arg) { struct q6audio_aio *audio = file->private_data; int rc = 0; @@ -78,9 +80,27 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) audio->stopped = 0; break; } + default: + break; + } + return rc; +} + +static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } case AUDIO_GET_WMA_CONFIG_V2: { if (copy_to_user((void *)arg, audio->codec_cfg, sizeof(struct msm_audio_wma_config_v2))) { + pr_err("%s:copy_to_user for AUDIO_SET_WMA_CONFIG_V2 failed\n", + __func__); rc = -EFAULT; break; } @@ -89,20 +109,114 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case AUDIO_SET_WMA_CONFIG_V2: { if (copy_from_user(audio->codec_cfg, (void *)arg, sizeof(struct msm_audio_wma_config_v2))) { + pr_err("%s:copy_from_user for AUDIO_SET_WMA_CONFIG_V2 failed\n", + __func__); rc = -EFAULT; break; } break; } - default: + default: { pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); rc = audio->codec_ioctl(file, cmd, arg); if (rc) pr_err("Failed in utils_ioctl: %d\n", rc); + break; + } } return rc; } +#ifdef CONFIG_COMPAT +struct msm_audio_wma_config_v2_32 { + u16 format_tag; + u16 numchannels; + u32 samplingrate; + u32 avgbytespersecond; + u16 block_align; + u16 validbitspersample; + u32 channelmask; + u16 encodeopt; +}; + +enum { + AUDIO_GET_WMA_CONFIG_V2_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+2), struct msm_audio_wma_config_v2_32), + AUDIO_SET_WMA_CONFIG_V2_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_wma_config_v2_32) +}; + +static long audio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } + case AUDIO_GET_WMA_CONFIG_V2_32: { + struct msm_audio_wma_config_v2 *wma_config; + struct msm_audio_wma_config_v2_32 wma_config_32; + + wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg; + wma_config_32.format_tag = wma_config->format_tag; + wma_config_32.numchannels = wma_config->numchannels; + wma_config_32.samplingrate = wma_config->samplingrate; + wma_config_32.avgbytespersecond = wma_config->avgbytespersecond; + wma_config_32.block_align = wma_config->block_align; + wma_config_32.validbitspersample = + wma_config->validbitspersample; + wma_config_32.channelmask = wma_config->channelmask; + wma_config_32.encodeopt = wma_config->encodeopt; + if (copy_to_user((void *)arg, &wma_config_32, + sizeof(wma_config_32))) { + pr_err("%s: copy_to_user for GET_WMA_CONFIG_V2_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + break; + } + case AUDIO_SET_WMA_CONFIG_V2_32: { + struct msm_audio_wma_config_v2 *wma_config; + struct msm_audio_wma_config_v2_32 wma_config_32; + + if (copy_from_user(&wma_config_32, (void *)arg, + sizeof(wma_config_32))) { + pr_err("%s: copy_from_user for SET_WMA_CONFIG_V2_32 failed\n" + , __func__); + rc = -EFAULT; + break; + } + wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg; + wma_config->format_tag = wma_config_32.format_tag; + wma_config->numchannels = wma_config_32.numchannels; + wma_config->samplingrate = wma_config_32.samplingrate; + wma_config->avgbytespersecond = wma_config_32.avgbytespersecond; + wma_config->block_align = wma_config_32.block_align; + wma_config->validbitspersample = + wma_config_32.validbitspersample; + wma_config->channelmask = wma_config_32.channelmask; + wma_config->encodeopt = wma_config_32.encodeopt; + break; + } + default: { + pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); + rc = audio->codec_compat_ioctl(file, cmd, arg); + if (rc) + pr_err("Failed in utils_ioctl: %d\n", rc); + break; + } + } + return rc; +} +#else +#define audio_compat_ioctl NULL +#endif + static int audio_open(struct inode *inode, struct file *file) { struct q6audio_aio *audio = NULL; @@ -198,6 +312,7 @@ static const struct file_operations audio_wma_fops = { .release = audio_aio_release, .unlocked_ioctl = audio_ioctl, .fsync = audio_aio_fsync, + .compat_ioctl = audio_compat_ioctl }; struct miscdevice audio_wma_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c index ce49cac47fa5..47c044c77f3d 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c +++ b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -17,6 +17,7 @@ #include #include +#include #include "audio_utils_aio.h" #ifdef CONFIG_DEBUG_FS @@ -26,7 +27,8 @@ static const struct file_operations audio_wmapro_debug_fops = { }; #endif -static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long audio_ioctl_shared(struct file *file, unsigned int cmd, + void *arg) { struct q6audio_aio *audio = file->private_data; int rc = 0; @@ -97,8 +99,7 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) wmapro_config->validbitspersample; } else { pr_err("%s:AUDIO_START failed: bitspersample = %d\n", - __func__, - wmapro_config->validbitspersample); + __func__, wmapro_config->validbitspersample); rc = -EINVAL; break; } @@ -137,9 +138,25 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) audio->stopped = 0; break; } + default: + pr_err("%s: Unkown ioctl cmd %d\n", __func__, cmd); + rc = -EINVAL; + break; + } + return rc; +} + +static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { case AUDIO_GET_WMAPRO_CONFIG: { if (copy_to_user((void *)arg, audio->codec_cfg, sizeof(struct msm_audio_wmapro_config))) { + pr_err("%s: copy_to_user for AUDIO_GET_WMAPRO_CONFIG failed\n", + __func__); rc = -EFAULT; } break; @@ -147,20 +164,139 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case AUDIO_SET_WMAPRO_CONFIG: { if (copy_from_user(audio->codec_cfg, (void *)arg, sizeof(struct msm_audio_wmapro_config))) { + pr_err("%s: copy_from_user for AUDIO_SET_WMAPRO_CONFIG_V2 failed\n", + __func__); rc = -EFAULT; break; } break; } - default: + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } + default: { pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); rc = audio->codec_ioctl(file, cmd, arg); if (rc) pr_err("Failed in utils_ioctl: %d\n", rc); + break; + } } return rc; } +#ifdef CONFIG_COMPAT + +struct msm_audio_wmapro_config32 { + u16 armdatareqthr; + u8 validbitspersample; + u8 numchannels; + u16 formattag; + u16 samplingrate; + u16 avgbytespersecond; + u16 asfpacketlength; + u16 channelmask; + u16 encodeopt; + u16 advancedencodeopt; + u32 advancedencodeopt2; +}; + +enum { + AUDIO_GET_WMAPRO_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_wmapro_config32), + AUDIO_SET_WMAPRO_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_wmapro_config32) +}; + +static long audio_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct q6audio_aio *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_GET_WMAPRO_CONFIG_32: { + struct msm_audio_wmapro_config *wmapro_config; + struct msm_audio_wmapro_config32 wmapro_config_32; + + wmapro_config = + (struct msm_audio_wmapro_config *)audio->codec_cfg; + wmapro_config_32.armdatareqthr = wmapro_config->armdatareqthr; + wmapro_config_32.validbitspersample = + wmapro_config->validbitspersample; + wmapro_config_32.numchannels = wmapro_config->numchannels; + wmapro_config_32.formattag = wmapro_config->formattag; + wmapro_config_32.samplingrate = wmapro_config->samplingrate; + wmapro_config_32.avgbytespersecond = + wmapro_config->avgbytespersecond; + wmapro_config_32.asfpacketlength = + wmapro_config->asfpacketlength; + wmapro_config_32.channelmask = wmapro_config->channelmask; + wmapro_config_32.encodeopt = wmapro_config->encodeopt; + wmapro_config_32.advancedencodeopt = + wmapro_config->advancedencodeopt; + wmapro_config_32.advancedencodeopt2 = + wmapro_config->advancedencodeopt2; + + if (copy_to_user((void *)arg, &wmapro_config_32, + sizeof(struct msm_audio_wmapro_config32))) { + pr_err("%s: copy_to_user for AUDIO_GET_WMAPRO_CONFIG_V2_32 failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_WMAPRO_CONFIG_32: { + struct msm_audio_wmapro_config *wmapro_config; + struct msm_audio_wmapro_config32 wmapro_config_32; + + if (copy_from_user(&wmapro_config_32, (void *)arg, + sizeof(struct msm_audio_wmapro_config32))) { + pr_err( + "%s: copy_from_user for AUDIO_SET_WMAPRO_CONFG_V2_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + wmapro_config = + (struct msm_audio_wmapro_config *)audio->codec_cfg; + wmapro_config->armdatareqthr = wmapro_config_32.armdatareqthr; + wmapro_config->validbitspersample = + wmapro_config_32.validbitspersample; + wmapro_config->numchannels = wmapro_config_32.numchannels; + wmapro_config->formattag = wmapro_config_32.formattag; + wmapro_config->samplingrate = wmapro_config_32.samplingrate; + wmapro_config->avgbytespersecond = + wmapro_config_32.avgbytespersecond; + wmapro_config->asfpacketlength = + wmapro_config_32.asfpacketlength; + wmapro_config->channelmask = wmapro_config_32.channelmask; + wmapro_config->encodeopt = wmapro_config_32.encodeopt; + wmapro_config->advancedencodeopt = + wmapro_config_32.advancedencodeopt; + wmapro_config->advancedencodeopt2 = + wmapro_config_32.advancedencodeopt2; + break; + } + case AUDIO_START: { + rc = audio_ioctl_shared(file, cmd, (void *)arg); + break; + } + default: { + pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio); + rc = audio->codec_compat_ioctl(file, cmd, arg); + if (rc) + pr_err("Failed in utils_ioctl: %d\n", rc); + break; + } + } + return rc; +} +#else +#define audio_compat_ioctl NULL +#endif + static int audio_open(struct inode *inode, struct file *file) { struct q6audio_aio *audio = NULL; @@ -257,6 +393,7 @@ static const struct file_operations audio_wmapro_fops = { .release = audio_aio_release, .unlocked_ioctl = audio_ioctl, .fsync = audio_aio_fsync, + .compat_ioctl = audio_compat_ioctl }; struct miscdevice audio_wmapro_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/evrc_in.c b/drivers/misc/qcom/qdsp6v2/evrc_in.c index a7852662d546..1b8f8ad451db 100644 --- a/drivers/misc/qcom/qdsp6v2/evrc_in.c +++ b/drivers/misc/qcom/qdsp6v2/evrc_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "audio_utils.h" @@ -30,8 +31,7 @@ /* Maximum 10 frames in buffer with meta */ #define FRAME_SIZE (1 + ((23+sizeof(struct meta_out_dsp)) * 10)) -/* ------------------- device --------------------- */ -static long evrc_in_ioctl(struct file *file, +static long evrc_in_ioctl_shared(struct file *file, unsigned int cmd, unsigned long arg) { struct q6audio_in *audio = file->private_data; @@ -108,41 +108,36 @@ static long evrc_in_ioctl(struct file *file, } break; } - case AUDIO_GET_EVRC_ENC_CONFIG: { - if (copy_to_user((void *)arg, audio->enc_cfg, - sizeof(struct msm_audio_evrc_enc_config))) - rc = -EFAULT; - break; - } case AUDIO_SET_EVRC_ENC_CONFIG: { - struct msm_audio_evrc_enc_config cfg; + struct msm_audio_evrc_enc_config *cfg; struct msm_audio_evrc_enc_config *enc_cfg; enc_cfg = audio->enc_cfg; - if (copy_from_user(&cfg, (void *) arg, - sizeof(struct msm_audio_evrc_enc_config))) { - rc = -EFAULT; + cfg = (struct msm_audio_evrc_enc_config *)arg; + if (cfg == NULL) { + pr_err("%s: NULL config pointer for %s\n", + __func__, "AUDIO_SET_EVRC_ENC_CONFIG"); + rc = -EINVAL; break; } - - if (cfg.min_bit_rate > 4 || - cfg.min_bit_rate < 1 || - (cfg.min_bit_rate == 2)) { + if (cfg->min_bit_rate > 4 || + cfg->min_bit_rate < 1 || + (cfg->min_bit_rate == 2)) { pr_err("%s:session id %d: invalid min bitrate\n", __func__, audio->ac->session); rc = -EINVAL; break; } - if (cfg.max_bit_rate > 4 || - cfg.max_bit_rate < 1 || - (cfg.max_bit_rate == 2)) { + if (cfg->max_bit_rate > 4 || + cfg->max_bit_rate < 1 || + (cfg->max_bit_rate == 2)) { pr_err("%s:session id %d: invalid max bitrate\n", __func__, audio->ac->session); rc = -EINVAL; break; } - enc_cfg->min_bit_rate = cfg.min_bit_rate; - enc_cfg->max_bit_rate = cfg.max_bit_rate; + enc_cfg->min_bit_rate = cfg->min_bit_rate; + enc_cfg->max_bit_rate = cfg->max_bit_rate; pr_debug("%s:session id %d: min_bit_rate= 0x%x max_bit_rate=0x%x\n", __func__, audio->ac->session, enc_cfg->min_bit_rate, @@ -150,11 +145,128 @@ static long evrc_in_ioctl(struct file *file, break; } default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); rc = -EINVAL; } return rc; } +static long evrc_in_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = evrc_in_ioctl_shared(file, cmd, arg); + break; + } + case AUDIO_GET_EVRC_ENC_CONFIG: { + if (copy_to_user((void *)arg, audio->enc_cfg, + sizeof(struct msm_audio_evrc_enc_config))) { + pr_err("%s: copy_to_user for AUDIO_GET_EVRC_ENC_CONFIG failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_EVRC_ENC_CONFIG: { + struct msm_audio_evrc_enc_config cfg; + if (copy_from_user(&cfg, (void *) arg, + sizeof(struct msm_audio_evrc_enc_config))) { + pr_err("%s: copy_from_user for AUDIO_SET_EVRC_ENC_CONFIG failed\n", + __func__); + rc = -EFAULT; + break; + } + rc = evrc_in_ioctl_shared(file, cmd, (unsigned long)&cfg); + if (rc) + pr_err("%s:AUDIO_SET_EVRC_ENC_CONFIG failed. rc= %d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} + +#ifdef CONFIG_COMPAT +struct msm_audio_evrc_enc_config32 { + u32 cdma_rate; + u32 min_bit_rate; + u32 max_bit_rate; +}; + +enum { + AUDIO_SET_EVRC_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + 2, struct msm_audio_evrc_enc_config32), + AUDIO_GET_EVRC_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + 3, struct msm_audio_evrc_enc_config32) +}; + +static long evrc_in_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = evrc_in_ioctl_shared(file, cmd, arg); + break; + } + case AUDIO_GET_EVRC_ENC_CONFIG_32: { + struct msm_audio_evrc_enc_config32 cfg_32; + struct msm_audio_evrc_enc_config *enc_cfg; + + enc_cfg = audio->enc_cfg; + cfg_32.cdma_rate = enc_cfg->cdma_rate; + cfg_32.min_bit_rate = enc_cfg->min_bit_rate; + cfg_32.max_bit_rate = enc_cfg->max_bit_rate; + + if (copy_to_user((void *)arg, &cfg_32, + sizeof(cfg_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_EVRC_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_EVRC_ENC_CONFIG_32: { + struct msm_audio_evrc_enc_config cfg; + struct msm_audio_evrc_enc_config32 cfg_32; + if (copy_from_user(&cfg_32, (void *) arg, + sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_EVRC_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cfg.cdma_rate = cfg_32.cdma_rate; + cfg.min_bit_rate = cfg_32.min_bit_rate; + cfg.max_bit_rate = cfg_32.max_bit_rate; + cmd = AUDIO_SET_EVRC_ENC_CONFIG; + rc = evrc_in_ioctl_shared(file, cmd, (unsigned long)&cfg); + if (rc) + pr_err("%s:AUDIO_SET_EVRC_ENC_CONFIG failed. rc= %d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} +#else +#define evrc_in_compat_ioctl NULL +#endif + static int evrc_in_open(struct inode *inode, struct file *file) { struct q6audio_in *audio = NULL; @@ -258,6 +370,7 @@ static int evrc_in_open(struct inode *inode, struct file *file) audio->opened = 1; atomic_set(&audio->in_count, PCM_BUF_COUNT); atomic_set(&audio->out_count, 0x00); + audio->enc_compat_ioctl = evrc_in_compat_ioctl; audio->enc_ioctl = evrc_in_ioctl; file->private_data = audio; @@ -277,6 +390,7 @@ static const struct file_operations audio_in_fops = { .read = audio_in_read, .write = audio_in_write, .unlocked_ioctl = audio_in_ioctl, + .compat_ioctl = audio_in_compat_ioctl }; struct miscdevice audio_evrc_in_misc = { diff --git a/drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c b/drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c index 21040b15e1ce..d8ae60d392a6 100644 --- a/drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c +++ b/drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -129,7 +129,7 @@ void extract_meta_out_info(struct q6audio_aio *audio, else memset(&buf_node->meta_info.meta_in, 0, sizeof(struct dec_meta_in)); - pr_debug("%s[%p]:i/p: msw_ts 0x%lx lsw_ts 0x%lx nflags 0x%8x\n", + pr_debug("%s[%p]:i/p: msw_ts 0x%d lsw_ts 0x%d nflags 0x%8x\n", __func__, audio, buf_node->meta_info.meta_in.ntimestamp.highpart, buf_node->meta_info.meta_in.ntimestamp.lowpart, @@ -144,7 +144,7 @@ void extract_meta_out_info(struct q6audio_aio *audio, meta_data->meta_out_dsp[0].lsw_ts; meta_data->meta_out_dsp[0].lsw_ts = temp; - pr_debug("%s[%p]:o/p: msw_ts 0x%8x lsw_ts 0x%8x nflags 0x%8x, num_frames = %d\n", + pr_debug("%s[%p]:o/p: msw_ts 0x%d lsw_ts 0x%d nflags 0x%8x, num_frames = %d\n", __func__, audio, ((struct dec_meta_out *)buf_node->kvaddr)->\ meta_out_dsp[0].msw_ts, diff --git a/drivers/misc/qcom/qdsp6v2/qcelp_in.c b/drivers/misc/qcom/qdsp6v2/qcelp_in.c index 3a5411ed2625..6dbb90d2a24e 100644 --- a/drivers/misc/qcom/qdsp6v2/qcelp_in.c +++ b/drivers/misc/qcom/qdsp6v2/qcelp_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "audio_utils.h" @@ -30,8 +31,7 @@ /* Maximum 10 frames in buffer with meta */ #define FRAME_SIZE (1 + ((35+sizeof(struct meta_out_dsp)) * 10)) -/* ------------------- device --------------------- */ -static long qcelp_in_ioctl(struct file *file, +static long qcelp_in_ioctl_shared(struct file *file, unsigned int cmd, unsigned long arg) { struct q6audio_in *audio = file->private_data; @@ -109,38 +109,34 @@ static long qcelp_in_ioctl(struct file *file, } break; } - case AUDIO_GET_QCELP_ENC_CONFIG: { - if (copy_to_user((void *)arg, audio->enc_cfg, - sizeof(struct msm_audio_qcelp_enc_config))) - rc = -EFAULT; - break; - } case AUDIO_SET_QCELP_ENC_CONFIG: { - struct msm_audio_qcelp_enc_config cfg; + struct msm_audio_qcelp_enc_config *cfg; struct msm_audio_qcelp_enc_config *enc_cfg; enc_cfg = audio->enc_cfg; - if (copy_from_user(&cfg, (void *) arg, - sizeof(struct msm_audio_qcelp_enc_config))) { - rc = -EFAULT; + + cfg = (struct msm_audio_qcelp_enc_config *)arg; + if (cfg == NULL) { + pr_err("%s: NULL config pointer\n", __func__); + rc = -EINVAL; break; } - - if (cfg.min_bit_rate > 4 || - cfg.min_bit_rate < 1) { + if (cfg->min_bit_rate > 4 || + cfg->min_bit_rate < 1) { pr_err("%s:session id %d: invalid min bitrate\n", __func__, audio->ac->session); rc = -EINVAL; break; } - if (cfg.max_bit_rate > 4 || - cfg.max_bit_rate < 1) { + if (cfg->max_bit_rate > 4 || + cfg->max_bit_rate < 1) { pr_err("%s:session id %d: invalid max bitrate\n", __func__, audio->ac->session); rc = -EINVAL; break; } - enc_cfg->min_bit_rate = cfg.min_bit_rate; - enc_cfg->max_bit_rate = cfg.max_bit_rate; + enc_cfg->cdma_rate = cfg->cdma_rate; + enc_cfg->min_bit_rate = cfg->min_bit_rate; + enc_cfg->max_bit_rate = cfg->max_bit_rate; pr_debug("%s:session id %d: min_bit_rate= 0x%x max_bit_rate=0x%x\n", __func__, audio->ac->session, enc_cfg->min_bit_rate, @@ -148,11 +144,129 @@ static long qcelp_in_ioctl(struct file *file, break; } default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); rc = -EINVAL; } return rc; } +static long qcelp_in_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = qcelp_in_ioctl_shared(file, cmd, arg); + break; + } + case AUDIO_GET_QCELP_ENC_CONFIG: { + if (copy_to_user((void *)arg, audio->enc_cfg, + sizeof(struct msm_audio_qcelp_enc_config))) { + pr_err( + "%s: copy_to_user for AUDIO_GET_QCELP_ENC_CONFIG failed", + __func__); + rc = -EFAULT; + } + break; + } + case AUDIO_SET_QCELP_ENC_CONFIG: { + struct msm_audio_qcelp_enc_config cfg; + if (copy_from_user(&cfg, (void *) arg, + sizeof(cfg))) { + pr_err( + "%s: copy_from_user for AUDIO_SET_QCELP_ENC_CONFIG failed", + __func__); + rc = -EFAULT; + break; + } + rc = qcelp_in_ioctl_shared(file, cmd, (unsigned long)&cfg); + if (rc) + pr_err("%s:AUDIO_SET_QCELP_ENC_CONFIG failed. Rc= %d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} + +#ifdef CONFIG_COMPAT +struct msm_audio_qcelp_enc_config32 { + u32 cdma_rate; + u32 min_bit_rate; + u32 max_bit_rate; +}; + +enum { + AUDIO_SET_QCELP_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, + 0, struct msm_audio_qcelp_enc_config32), + AUDIO_GET_QCELP_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, + 1, struct msm_audio_qcelp_enc_config32) +}; + +static long qcelp_in_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct q6audio_in *audio = file->private_data; + int rc = 0; + + switch (cmd) { + case AUDIO_START: + case AUDIO_STOP: { + rc = qcelp_in_ioctl_shared(file, cmd, arg); + break; + } + case AUDIO_GET_QCELP_ENC_CONFIG_32: { + struct msm_audio_qcelp_enc_config32 cfg_32; + struct msm_audio_qcelp_enc_config *enc_cfg; + + enc_cfg = (struct msm_audio_qcelp_enc_config *)audio->enc_cfg; + cfg_32.cdma_rate = enc_cfg->cdma_rate; + cfg_32.min_bit_rate = enc_cfg->min_bit_rate; + cfg_32.max_bit_rate = enc_cfg->max_bit_rate; + if (copy_to_user((void *)arg, &cfg_32, + sizeof(cfg_32))) { + pr_err("%s: copy_to_user for AUDIO_GET_QCELP_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; +} + break; + } + case AUDIO_SET_QCELP_ENC_CONFIG_32: { + struct msm_audio_qcelp_enc_config32 cfg_32; + struct msm_audio_qcelp_enc_config cfg; + if (copy_from_user(&cfg_32, (void *) arg, + sizeof(cfg_32))) { + pr_err("%s: copy_from_user for AUDIO_SET_QCELP_ENC_CONFIG_32 failed\n", + __func__); + rc = -EFAULT; + break; + } + cfg.cdma_rate = cfg_32.cdma_rate; + cfg.min_bit_rate = cfg_32.min_bit_rate; + cfg.max_bit_rate = cfg_32.max_bit_rate; + cmd = AUDIO_SET_QCELP_ENC_CONFIG; + rc = qcelp_in_ioctl_shared(file, cmd, (unsigned long)&cfg); + if (rc) + pr_err("%s:AUDIO_SET_QCELP_ENC_CONFIG failed. rc= %d\n", + __func__, rc); + break; + } + default: + pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd); + rc = -EINVAL; + } + return rc; +} +#else +#define qcelp_in_compat_ioctl NULL +#endif + static int qcelp_in_open(struct inode *inode, struct file *file) { struct q6audio_in *audio = NULL; @@ -256,6 +370,7 @@ static int qcelp_in_open(struct inode *inode, struct file *file) audio->opened = 1; atomic_set(&audio->in_count, PCM_BUF_COUNT); atomic_set(&audio->out_count, 0x00); + audio->enc_compat_ioctl = qcelp_in_compat_ioctl; audio->enc_ioctl = qcelp_in_ioctl; file->private_data = audio; @@ -275,6 +390,7 @@ static const struct file_operations audio_in_fops = { .read = audio_in_read, .write = audio_in_write, .unlocked_ioctl = audio_in_ioctl, + .compat_ioctl = audio_in_compat_ioctl }; struct miscdevice audio_qcelp_in_misc = { diff --git a/include/uapi/linux/msm_audio.h b/include/uapi/linux/msm_audio.h index af780643e130..1f17371a0ea2 100644 --- a/include/uapi/linux/msm_audio.h +++ b/include/uapi/linux/msm_audio.h @@ -27,9 +27,12 @@ #define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned) #define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned) #define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned) -#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned) -#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned) -#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned) +#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, \ + struct msm_audio_config) +#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, \ + struct msm_audio_config) +#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, \ + struct msm_audio_stats) #define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned) #define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned) #define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned) @@ -37,12 +40,15 @@ #define AUDIO_SET_VOLUME _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned) #define AUDIO_PAUSE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned) #define AUDIO_PLAY_DTMF _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned) -#define AUDIO_GET_EVENT _IOR(AUDIO_IOCTL_MAGIC, 13, unsigned) +#define AUDIO_GET_EVENT _IOR(AUDIO_IOCTL_MAGIC, 13, \ + struct msm_audio_event) #define AUDIO_ABORT_GET_EVENT _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned) #define AUDIO_REGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 15, unsigned) #define AUDIO_DEREGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 16, unsigned) -#define AUDIO_ASYNC_WRITE _IOW(AUDIO_IOCTL_MAGIC, 17, unsigned) -#define AUDIO_ASYNC_READ _IOW(AUDIO_IOCTL_MAGIC, 18, unsigned) +#define AUDIO_ASYNC_WRITE _IOW(AUDIO_IOCTL_MAGIC, 17, \ + struct msm_audio_aio_buf) +#define AUDIO_ASYNC_READ _IOW(AUDIO_IOCTL_MAGIC, 18, \ + struct msm_audio_aio_buf) #define AUDIO_SET_INCALL _IOW(AUDIO_IOCTL_MAGIC, 19, struct msm_voicerec_mode) #define AUDIO_GET_NUM_SND_DEVICE _IOR(AUDIO_IOCTL_MAGIC, 20, unsigned) #define AUDIO_GET_SND_DEVICES _IOWR(AUDIO_IOCTL_MAGIC, 21, \ @@ -94,8 +100,10 @@ #define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96, \ struct msm_acdb_cmd_device) -#define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 97, unsigned) -#define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 98, unsigned) +#define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 97, \ + struct msm_audio_ion_info) +#define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 98, \ + struct msm_audio_ion_info) #define AUDIO_MAX_COMMON_IOCTL_NUM 100 diff --git a/include/uapi/linux/msm_audio_aac.h b/include/uapi/linux/msm_audio_aac.h index 87f7ec09970e..fadeb74c2ea7 100644 --- a/include/uapi/linux/msm_audio_aac.h +++ b/include/uapi/linux/msm_audio_aac.h @@ -4,18 +4,18 @@ #include #define AUDIO_SET_AAC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \ - (AUDIO_MAX_COMMON_IOCTL_NUM+0), unsigned) + (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config) #define AUDIO_GET_AAC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \ - (AUDIO_MAX_COMMON_IOCTL_NUM+1), unsigned) + (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config) #define AUDIO_SET_AAC_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \ - (AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config) + (AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config) #define AUDIO_GET_AAC_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \ - (AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config) + (AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config) #define AUDIO_SET_AAC_MIX_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \ -(AUDIO_MAX_COMMON_IOCTL_NUM+5), unsigned) + (AUDIO_MAX_COMMON_IOCTL_NUM+5), uint32_t) #define AUDIO_AAC_FORMAT_ADTS -1 #define AUDIO_AAC_FORMAT_RAW 0x0000 diff --git a/include/uapi/linux/msm_audio_wmapro.h b/include/uapi/linux/msm_audio_wmapro.h index b07edb7ce250..195394e7cbc3 100644 --- a/include/uapi/linux/msm_audio_wmapro.h +++ b/include/uapi/linux/msm_audio_wmapro.h @@ -2,9 +2,9 @@ #define _UAPI_MSM_AUDIO_WMAPRO_H #define AUDIO_GET_WMAPRO_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \ - (AUDIO_MAX_COMMON_IOCTL_NUM+0), unsigned) + (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_wmapro_config) #define AUDIO_SET_WMAPRO_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \ - (AUDIO_MAX_COMMON_IOCTL_NUM+1), unsigned) + (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_wmapro_config) struct msm_audio_wmapro_config { unsigned short armdatareqthr;