diff --git a/Documentation/devicetree/bindings/sound/msm-cirrus-playback.txt b/Documentation/devicetree/bindings/sound/msm-cirrus-playback.txt deleted file mode 100644 index e13cadddf93c..000000000000 --- a/Documentation/devicetree/bindings/sound/msm-cirrus-playback.txt +++ /dev/null @@ -1,21 +0,0 @@ -Cirrus Logic MSM Framework Driver - -Required properties: - - - compatible : "cirrus,msm-cirrus-playback" - - - usecase-names : List of strings representing the various usecases - available on a given platform (max of 4). - - - usecase-indexes : List of usecases index representing the above - - - ff-port-id : Port index of feedforward speaker enhancement module - -Example: - -msm-cirrus-playback { - compatible = "cirrus,msm-cirrus-playback"; - usecase-names = "Playback", "Voice", "Headset", "Handsfree"; - usecase-indexes = <0 1 2 3>; - ff-port-id = "16384"; -}; diff --git a/include/sound/msm-cirrus-playback.h b/include/sound/msm-cirrus-playback.h deleted file mode 100644 index 79fe907d6be2..000000000000 --- a/include/sound/msm-cirrus-playback.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2015 Cirrus Logic, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef MSM_CIRRUS_PLAYBACK_H -#define MSM_CIRRUS_PLAYBACK_H - -#include -#include -#include -#include -#include -#include - -struct afe_custom_crus_set_config_t { - struct apr_hdr hdr; - struct afe_port_cmd_set_param_v2 param; - struct afe_port_param_data_v2 data; -} __packed; - -struct afe_custom_crus_get_config_t { - struct apr_hdr hdr; - struct afe_port_cmd_get_param_v2 param; - struct afe_port_param_data_v2 data; -} __packed; - -/* Payload struct for getting or setting one integer value from/to the DSP - * module - */ -struct crus_single_data_t { - int32_t value; -}; - -/* Payload struct for getting or setting two integer values from/to the DSP - * module - */ -struct crus_dual_data_t { - int32_t data1; - int32_t data2; -}; - -/* Payload struct for getting or setting three integer values from/to the DSP - * module - */ -struct crus_triple_data_t { - int32_t data1; - int32_t data2; - int32_t data3; -}; - -/* Payload struct for setting the RX and TX use cases */ -struct crus_rx_run_case_ctrl_t { - int32_t value; - int32_t status_l; - int32_t checksum_l; - int32_t z_l; - int32_t status_r; - int32_t checksum_r; - int32_t z_r; - int32_t atemp; -}; - -/* Payload struct for getting calibration result from DSP module */ -struct cirrus_cal_result_t { - int32_t status_l; - int32_t checksum_l; - int32_t z_l; - int32_t status_r; - int32_t checksum_r; - int32_t z_r; -}; - -#define APR_CHUNK_SIZE 256 -#define CONFIG_FILE_SIZE 128 -#define PAYLOAD_FOLLOWS_CONFIG 4 -#define MAX_TUNING_CONFIGS 4 -#define MIN_CHAN_SWAP_SAMPLES 48 -#define MAX_CHAN_SWAP_SAMPLES 9600 - -/* Payload struct for sending an external configuration string to the DSP - * module - */ -struct crus_external_config_t { - uint32_t total_size; - uint32_t chunk_size; - int32_t done; - int32_t reserved; - int32_t config; - char data[APR_CHUNK_SIZE]; -}; - -/* Payload struct for sending an external tuning transition string to the DSP - * module - */ -struct crus_delta_config_t { - uint32_t total_size; - uint32_t chunk_size; - int32_t done; - int32_t index; - int32_t reserved; - int32_t config; - char data[APR_CHUNK_SIZE]; -}; - -extern int afe_apr_send_pkt_crus(void *data, int index); -extern int crus_afe_set_callback( - int32_t (*crus_afe_callback_func)(void *payload, int size)); -void msm_crus_pb_add_controls(struct snd_soc_platform *platform); - -#endif /* _MSM_CIRRUS_PLAYBACK_H */ - diff --git a/sound/soc/codecs/Android.mk b/sound/soc/codecs/Android.mk index d70a812aef86..4a8df2c8e806 100644 --- a/sound/soc/codecs/Android.mk +++ b/sound/soc/codecs/Android.mk @@ -1,12 +1,6 @@ DLKM_DIR := motorola/kernel/modules LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) -LOCAL_MODULE := cirrus_playback.ko -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) -include $(DLKM_DIR)/AndroidKernelModule.mk - include $(CLEAR_VARS) LOCAL_MODULE := snd_soc_tfa9874.ko LOCAL_MODULE_TAGS := optional diff --git a/sound/soc/codecs/Kbuild b/sound/soc/codecs/Kbuild index 7b3b515e1c85..33d5ce390629 100644 --- a/sound/soc/codecs/Kbuild +++ b/sound/soc/codecs/Kbuild @@ -31,9 +31,6 @@ EXTRA_CFLAGS += -DTFA9874_NONDSP_STEREO EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/sound/soc/codecs/inc EXTRA_CFLAGS += -Werror -cirrus_playback-objs = msm-cirrus-playback.o -obj-m += cirrus_playback.o - snd_soc_tfa9874-objs += tfa98xx.o snd_soc_tfa9874-objs += tfa_container.o snd_soc_tfa9874-objs += tfa_dsp.o diff --git a/sound/soc/codecs/msm-cirrus-playback.c b/sound/soc/codecs/msm-cirrus-playback.c deleted file mode 100644 index 60c51d9f060f..000000000000 --- a/sound/soc/codecs/msm-cirrus-playback.c +++ /dev/null @@ -1,1051 +0,0 @@ -/* Copyright (c) 2015, 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 -* only version 2 as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define CRUS_RX_CONFIG "crus_sp_rx%d.bin" - -static struct device *crus_se_device; -static atomic_t crus_se_misc_usage_count; - -static struct crus_single_data_t crus_enable; - -static struct crus_se_ioctl_header crus_se_hdr; -static uint32_t *crus_se_get_buffer; -static atomic_t crus_se_get_param_flag; -struct mutex crus_se_get_param_lock; -struct mutex crus_se_lock; -static int cirrus_se_en; -static int cirrus_se_usecase; -static int cirrus_ff_load_conf_sel; -static int cirrus_ff_delta_sel; -static int cirrus_ff_chan_swap_sel; -static int cirrus_ff_chan_swap_dur; -static int cirrus_ff_port; - -static int crus_se_usecase_dt_count; -static const char *crus_se_usecase_dt_text[MAX_TUNING_CONFIGS]; -static u32 crus_se_usecase_dt_index[MAX_TUNING_CONFIGS] = {0, 1, 2, 3}; - -int crus_afe_callback(void *payload, int size); - -static void *crus_gen_afe_get_header(int length, int port, int module, - int param) -{ - struct afe_custom_crus_get_config_t *config = NULL; - int size = sizeof(struct afe_custom_crus_get_config_t); - int index = afe_get_port_index(port); - uint16_t payload_size = sizeof(struct afe_port_param_data_v2) + - length; - - /* Allocate memory for the message */ - config = kzalloc(size, GFP_KERNEL); - if (!config) - return NULL; - - /* Set header section */ - config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - config->hdr.pkt_size = size; - config->hdr.src_svc = APR_SVC_AFE; - config->hdr.src_domain = APR_DOMAIN_APPS; - config->hdr.src_port = 0; - config->hdr.dest_svc = APR_SVC_AFE; - config->hdr.dest_domain = APR_DOMAIN_ADSP; - config->hdr.dest_port = 0; - config->hdr.token = index; - config->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; - - /* Set param section */ - config->param.port_id = (uint16_t) port; - config->param.payload_address_lsw = 0; - config->param.payload_address_msw = 0; - config->param.mem_map_handle = 0; - config->param.module_id = (uint32_t) module; - config->param.param_id = (uint32_t) param; - /* max data size of the param_ID/module_ID combination */ - config->param.payload_size = payload_size; - - /* Set data section */ - config->data.module_id = (uint32_t) module; - config->data.param_id = (uint32_t) param; - config->data.reserved = 0; /* Must be set to 0 */ - /* actual size of the data for the module_ID/param_ID pair */ - config->data.param_size = length; - - return (void *)config; -} - -static void *crus_gen_afe_set_header(int length, int port, int module, - int param) -{ - struct afe_custom_crus_set_config_t *config = NULL; - int size = sizeof(struct afe_custom_crus_set_config_t) + length; - int index = afe_get_port_index(port); - uint16_t payload_size = sizeof(struct afe_port_param_data_v2) + - length; - - /* Allocate memory for the message */ - config = kzalloc(size, GFP_KERNEL); - if (!config) - return NULL; - - /* Set header section */ - config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - config->hdr.pkt_size = size; - config->hdr.src_svc = APR_SVC_AFE; - config->hdr.src_domain = APR_DOMAIN_APPS; - config->hdr.src_port = 0; - config->hdr.dest_svc = APR_SVC_AFE; - config->hdr.dest_domain = APR_DOMAIN_ADSP; - config->hdr.dest_port = 0; - config->hdr.token = index; - config->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; - - /* Set param section */ - config->param.port_id = (uint16_t) port; - config->param.payload_address_lsw = 0; - config->param.payload_address_msw = 0; - config->param.mem_map_handle = 0; - /* max data size of the param_ID/module_ID combination */ - config->param.payload_size = payload_size; - - /* Set data section */ - config->data.module_id = (uint32_t) module; - config->data.param_id = (uint32_t) param; - config->data.reserved = 0; /* Must be set to 0 */ - /* actual size of the data for the module_ID/param_ID pair */ - config->data.param_size = length; - - return (void *)config; -} - -static int crus_get_param(int port, int module, int param, int length, - void *data) -{ - struct afe_custom_crus_get_config_t *config = NULL; - int index = afe_get_port_index(port); - int ret = 0, count = 0; - - pr_debug("%s: port = %d module = %d param = 0x%x length = %d\n", - __func__, port, module, param, length); - - config = (struct afe_custom_crus_get_config_t *) - crus_gen_afe_get_header(length, port, module, param); - if (config == NULL) { - pr_err("%s: Memory allocation failed!\n", __func__); - return -ENOMEM; - } - - pr_debug("%s: Preparing to send apr packet\n", __func__); - - mutex_lock(&crus_se_get_param_lock); - atomic_set(&crus_se_get_param_flag, 0); - - crus_se_get_buffer = kzalloc(length + 16, GFP_KERNEL); - if (!crus_se_get_buffer) { - pr_err("%s: Memory allocation failed!\n", __func__); - mutex_unlock(&crus_se_get_param_lock); - return -ENOMEM; - } - - crus_afe_set_callback(crus_afe_callback); - - ret = afe_apr_send_pkt_crus(config, index); - if (ret) - pr_err("%s: crus get_param for port %d failed with code %d\n", - __func__, port, ret); - else - pr_debug("%s: crus get_param sent packet with param id 0x%08x to module 0x%08x.\n", - __func__, param, module); - - /* Wait for afe callback to populate data */ - while (!atomic_read(&crus_se_get_param_flag)) { - usleep_range(800, 1200); - if (count++ >= 1000) { - pr_err("%s: AFE callback timeout\n", __func__); - atomic_set(&crus_se_get_param_flag, 1); - mutex_unlock(&crus_se_get_param_lock); - return -EINVAL; - } - } - - /* Copy from dynamic buffer to return buffer */ - memcpy((u8 *)data, &crus_se_get_buffer[4], length); - - kfree(crus_se_get_buffer); - - mutex_unlock(&crus_se_get_param_lock); - - kfree(config); - return ret; -} - -static int crus_set_param(int port, int module, int param, int length, - void *data_ptr) -{ - struct afe_custom_crus_set_config_t *config = NULL; - int index = afe_get_port_index(port); - int ret = 0; - - pr_debug("%s: port = %d module = %d param = 0x%x length = %d\n", - __func__, port, module, param, length); - - config = crus_gen_afe_set_header(length, port, module, param); - if (config == NULL) { - pr_err("%s: Memory allocation failed!\n", __func__); - return -ENOMEM; - } - - memcpy((u8 *)config + sizeof(struct afe_custom_crus_set_config_t), - (u8 *) data_ptr, length); - - pr_debug("%s: Preparing to send apr packet.\n", __func__); - - ret = afe_apr_send_pkt_crus(config, index); - if (ret) { - pr_err("%s: crus set_param for port %d failed with code %d\n", - __func__, port, ret); - } else { - pr_debug("%s: crus set_param sent packet with param id 0x%08x to module 0x%08x.\n", - __func__, param, module); - } - - kfree(config); - return ret; -} - -static int crus_send_config(const char *data, int32_t length, - int32_t port, int32_t module) -{ - struct afe_custom_crus_set_config_t *config = NULL; - struct crus_external_config_t *payload = NULL; - int size = sizeof(struct crus_external_config_t); - int ret = 0; - int index = afe_get_port_index(port); - uint32_t param = 0; - int mem_size = 0; - int sent = 0; - int chars_to_send = 0; - - pr_debug("%s: called with module_id = %x, string length = %d\n", - __func__, module, length); - - /* Destination settings for message */ - if (port == cirrus_ff_port) - param = CRUS_PARAM_RX_SET_EXT_CONFIG; - else { - pr_err("%s: Received invalid port parameter %d\n", - __func__, module); - return -EINVAL; - } - - if (length > APR_CHUNK_SIZE) - mem_size = APR_CHUNK_SIZE; - else - mem_size = length; - - config = crus_gen_afe_set_header(size, port, module, param); - if (config == NULL) { - pr_err("%s: Memory allocation failed!\n", __func__); - return -ENOMEM; - } - - payload = (struct crus_external_config_t *)((u8 *)config + - sizeof(struct afe_custom_crus_set_config_t)); - payload->total_size = (uint32_t)length; - payload->reserved = 0; - payload->config = PAYLOAD_FOLLOWS_CONFIG; - /* ^ This tells the algorithm to expect array */ - /* immediately following the header */ - - /* Send config string in chunks of APR_CHUNK_SIZE bytes */ - while (sent < length) { - chars_to_send = length - sent; - if (chars_to_send > APR_CHUNK_SIZE) { - chars_to_send = APR_CHUNK_SIZE; - payload->done = 0; - } else { - payload->done = 1; - } - - /* Configure per message parameter settings */ - memcpy(payload->data, data + sent, chars_to_send); - payload->chunk_size = chars_to_send; - - - /* Send the actual message */ - pr_debug("%s: Preparing to send apr packet.\n", __func__); - ret = afe_apr_send_pkt_crus(config, index); - if (ret) - pr_err("%s: crus set_param for port %d failed with code %d\n", - __func__, port, ret); - else - pr_debug("%s: crus set_param sent packet with param id 0x%08x to module 0x%08x.\n", - __func__, param, module); - - sent += chars_to_send; - } - - kfree(config); - return ret; -} - -static int crus_send_delta(const char *data, uint32_t length) -{ - struct afe_custom_crus_set_config_t *config = NULL; - struct crus_delta_config_t *payload = NULL; - int size = sizeof(struct crus_delta_config_t); - int port = cirrus_ff_port; - int param = CRUS_PARAM_RX_SET_DELTA_CONFIG; - int module = CIRRUS_SE; - int ret = 0; - int index = afe_get_port_index(port); - int mem_size = 0; - int sent = 0; - int chars_to_send = 0; - - pr_debug("%s: called with module_id = %x, string length = %d\n", - __func__, module, length); - - if (length > APR_CHUNK_SIZE) - mem_size = APR_CHUNK_SIZE; - else - mem_size = length; - - config = crus_gen_afe_set_header(size, port, module, param); - if (config == NULL) { - pr_err("%s: Memory allocation failed!\n", __func__); - return -ENOMEM; - } - - payload = (struct crus_delta_config_t *)((u8 *)config + - sizeof(struct afe_custom_crus_set_config_t)); - payload->total_size = length; - payload->index = 0; - payload->reserved = 0; - payload->config = PAYLOAD_FOLLOWS_CONFIG; - /* ^ This tells the algorithm to expect array */ - /* immediately following the header */ - - /* Send config string in chunks of APR_CHUNK_SIZE bytes */ - while (sent < length) { - chars_to_send = length - sent; - if (chars_to_send > APR_CHUNK_SIZE) { - chars_to_send = APR_CHUNK_SIZE; - payload->done = 0; - } else { - payload->done = 1; - } - - /* Configure per message parameter settings */ - memcpy(payload->data, data + sent, chars_to_send); - payload->chunk_size = chars_to_send; - - /* Send the actual message */ - pr_debug("%s: Preparing to send apr packet.\n", __func__); - ret = afe_apr_send_pkt_crus(config, index); - if (ret) - pr_err("%s: crus set_param for port %d failed with code %d\n", - __func__, port, ret); - else - pr_debug("%s: crus set_param sent packet with param id 0x%08x to module 0x%08x.\n", - __func__, param, module); - - sent += chars_to_send; - } - - kfree(config); - return ret; -} - -int crus_afe_callback(void *payload, int size) -{ - uint32_t *payload32 = payload; - - pr_debug("Cirrus AFE CALLBACK: size = %d\n", size); - - switch (payload32[1]) { - case CIRRUS_SE: - memcpy(crus_se_get_buffer, payload32, size); - atomic_set(&crus_se_get_param_flag, 1); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int msm_crus_se_enable(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - static struct crus_single_data_t crus_id_ctrl; - const int crus_set = ucontrol->value.integer.value[0]; - - if (crus_set > 255) { - pr_err("Cirrus SE Enable: Invalid entry; Enter 0 to DISABLE, 1 to ENABLE\n"); - return -EINVAL; - } - - switch (crus_set) { - case 0: /* "Config SE Disable" */ - pr_debug("Cirrus SE Enable: Config DISABLE\n"); - crus_enable.value = 0; - cirrus_se_en = 0; - break; - case 1: /* "Config SE Enable" */ - pr_debug("Cirrus SE Enable: Config ENABLE\n"); - crus_enable.value = 1; - cirrus_se_en = 1; - break; - default: - return -EINVAL; - } - - mutex_lock(&crus_se_lock); - crus_set_param(cirrus_ff_port, CIRRUS_SE, - CIRRUS_SE_ENABLE, - sizeof(struct crus_single_data_t), - (void *)&crus_enable); - - crus_id_ctrl.value = 0; /*tx=1, rx=0*/ - crus_set_param(cirrus_ff_port, CIRRUS_SE, - CIRRUS_SE_PARAM_ID_CTRL, - sizeof(struct crus_single_data_t), - (void *)&crus_id_ctrl); - mutex_unlock(&crus_se_lock); - - return 0; -} - -static int msm_crus_se_enable_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("Starting Cirrus SE Enable Get function call\n"); - - crus_get_param(cirrus_ff_port, CIRRUS_SE, CIRRUS_SE_ENABLE, - sizeof(struct crus_single_data_t), (void *)&crus_enable); - - ucontrol->value.integer.value[0] = crus_enable.value; - - return 0; -} - -static int msm_crus_se_usecase(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int ret = 0; - struct crus_rx_run_case_ctrl_t case_ctrl; - const int crus_set = ucontrol->value.integer.value[0]; - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - uint32_t max_index = e->items; - - pr_debug("Starting Cirrus SE Usecase function call [%d,%d]\n", - crus_set, crus_se_usecase_dt_index[crus_set]); - - if (crus_set >= max_index) { - pr_err("Cirrus SE Config index out of bounds (%d)\n", crus_set); - return -EINVAL; - } - - case_ctrl.status_l = 0; - case_ctrl.status_r = 0; - case_ctrl.atemp = 0; - case_ctrl.value = crus_se_usecase_dt_index[crus_set]; - - ret = crus_set_param(cirrus_ff_port, CIRRUS_SE, - CRUS_PARAM_RX_SET_USECASE, sizeof(case_ctrl), - (void *)&case_ctrl); - - if (ret == 0) - cirrus_se_usecase = crus_se_usecase_dt_index[crus_set]; - - return 0; -} - -static int msm_crus_se_usecase_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - static struct crus_single_data_t crus_usecase; - - pr_debug("Starting Cirrus SE Usecase Get function call\n"); - - crus_get_param(cirrus_ff_port, CIRRUS_SE, CRUS_PARAM_RX_GET_USECASE, - sizeof(struct crus_single_data_t), (void *)&crus_usecase); - - pr_debug("Usecase from qdsp returned as %d\n", crus_usecase.value); - - if (crus_usecase.value < 0) { - /* QDSP/LPASS default, module isn't running */ - ucontrol->value.integer.value[0] = 0; - } else { - ucontrol->value.integer.value[0] = - crus_usecase.value - crus_se_usecase_dt_index[0]; - } - - return 0; -} - -static int msm_crus_load_config(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - const int crus_set = ucontrol->value.integer.value[0]; - char config[CONFIG_FILE_SIZE]; - const struct firmware *firmware; - - pr_debug("Starting Cirrus SE Load Config function call %d\n", crus_set); - - switch (crus_set) { - case 0: - break; - case 1: /* Load RX Config */ - cirrus_ff_load_conf_sel = crus_set; - snprintf(config, CONFIG_FILE_SIZE, CRUS_RX_CONFIG, - cirrus_se_usecase); - - if (request_firmware(&firmware, config, crus_se_device) != 0) { - pr_err("%s: Request firmware failed\n", __func__); - return -EINVAL; - } - - if (firmware->data != NULL && firmware->size > 0) { - pr_debug("%s: Sending RX config(%d)\n", - __func__, cirrus_se_usecase); - crus_send_config(firmware->data, firmware->size, - cirrus_ff_port, CIRRUS_SE); - } else { - pr_err("%s: can't read firmware data\n", __func__); - } - - release_firmware(firmware); - break; - default: - return -EINVAL; - } - - cirrus_ff_load_conf_sel = 0; - - return 0; -} - -static int msm_crus_load_config_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("Starting Cirrus SE Load Config Get function call\n"); - ucontrol->value.integer.value[0] = cirrus_ff_load_conf_sel; - - return 0; -} - -static int msm_crus_delta_config(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct crus_single_data_t data; - const int crus_set = ucontrol->value.integer.value[0]; - const struct firmware *firmware; - - pr_debug("Starting Cirrus SE Delta Config function call %d\n", - crus_set); - - switch (crus_set) { - case 0: - break; - case 1: /* Load delta config over AFE */ - cirrus_ff_delta_sel = crus_set; - - if (request_firmware(&firmware, "crus_se_delta_config.bin", - crus_se_device) != 0) { - pr_err("%s: Request firmware failed\n", __func__); - cirrus_ff_delta_sel = 0; - return -EINVAL; - } - - pr_debug("%s: Sending delta config\n", __func__); - crus_send_delta(firmware->data, firmware->size); - release_firmware(firmware); - break; - case 2: /* Run delta transition */ - cirrus_ff_delta_sel = crus_set; - data.value = 0; - crus_set_param(cirrus_ff_port, CIRRUS_SE, - CRUS_PARAM_RX_RUN_DELTA_CONFIG, - sizeof(struct crus_single_data_t), &data); - break; - default: - return -EINVAL; - } - - cirrus_ff_delta_sel = 0; - return 0; -} - -static int msm_crus_delta_config_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("Starting Cirrus SE Delta Config Get function call\n"); - ucontrol->value.integer.value[0] = cirrus_ff_delta_sel; - - return 0; -} - -static int msm_crus_chan_swap(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct crus_dual_data_t data; - const int crus_set = ucontrol->value.integer.value[0]; - - pr_debug("Starting Cirrus SE Channel Swap function call %d\n", - crus_set); - - switch (crus_set) { - case 0: /* L/R */ - data.data1 = 1; - break; - case 1: /* R/L */ - data.data1 = 2; - break; - default: - return -EINVAL; - } - - data.data2 = cirrus_ff_chan_swap_dur; - - crus_set_param(cirrus_ff_port, CIRRUS_SE, - CRUS_PARAM_RX_CHANNEL_SWAP, - sizeof(struct crus_dual_data_t), &data); - - cirrus_ff_chan_swap_sel = crus_set; - - return 0; -} - -static int msm_crus_chan_swap_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("Starting Cirrus SE Channel Swap Get function call\n"); - ucontrol->value.integer.value[0] = cirrus_ff_chan_swap_sel; - - return 0; -} - -static int msm_crus_chan_swap_dur(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int crus_set = ucontrol->value.integer.value[0]; - - pr_debug("Starting Cirrus SE Channel Swap Duration function call\n"); - - if ((crus_set < 0) || (crus_set > MAX_CHAN_SWAP_SAMPLES)) { - pr_err("%s: Value out of range (%d)\n", __func__, crus_set); - return -EINVAL; - } - - if (crus_set < MIN_CHAN_SWAP_SAMPLES) { - pr_debug("%s: Received %d, rounding up to min value %d\n", - __func__, crus_set, MIN_CHAN_SWAP_SAMPLES); - crus_set = MIN_CHAN_SWAP_SAMPLES; - } - - cirrus_ff_chan_swap_dur = crus_set; - - return 0; -} - -static int msm_crus_chan_swap_dur_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("Starting Cirrus SE Channel Swap Duration Get function call\n"); - ucontrol->value.integer.value[0] = cirrus_ff_chan_swap_dur; - - return 0; -} - -static int msm_crus_se_rx_port(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int crus_set = ucontrol->value.integer.value[0]; - - pr_debug("Starting Cirrus SE RX Port function call\n"); - - if ((crus_set < 0) || (crus_set > AFE_PORT_ID_INVALID)) { - pr_err("%s: ignore the value out of range (%d)\n", - __func__, crus_set); - return 0; - } - - pr_debug("%s: Received %d, change AFE Rx port from %d to %d\n", - __func__, crus_set, cirrus_ff_port, crus_set); - - cirrus_ff_port = crus_set; - - return 0; -} - -static int msm_crus_se_rx_port_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("Starting Cirrus SE RX Port Get function call\n"); - ucontrol->value.integer.value[0] = cirrus_ff_port; - - return 0; -} - -static int msm_crus_se_usecase_index_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int i = 0; - - pr_debug("Starting Cirrus SE Usecase Index Get function call\n"); - - for (i = 0 ; i < crus_se_usecase_dt_count; i++) { - ucontrol->value.integer.value[i] = crus_se_usecase_dt_index[i]; - } - - return 0; -} - -static const char * const crus_en_text[] = {"Disable", "Enable"}; - -static const char * const crus_conf_load_text[] = {"Idle", "Load RX"}; - -static const char * const crus_delta_text[] = {"Idle", "Load", "Run"}; - -static const char * const crus_chan_swap_text[] = {"LR", "RL"}; - -static const struct soc_enum crus_en_enum[] = { - SOC_ENUM_SINGLE_EXT(2, crus_en_text), -}; - -static struct soc_enum crus_se_usecase_enum[] = { - SOC_ENUM_SINGLE_EXT(MAX_TUNING_CONFIGS, crus_se_usecase_dt_text), -}; - -static const struct soc_enum crus_conf_load_enum[] = { - SOC_ENUM_SINGLE_EXT(2, crus_conf_load_text), -}; - -static const struct soc_enum crus_delta_enum[] = { - SOC_ENUM_SINGLE_EXT(3, crus_delta_text), -}; - -static const struct soc_enum crus_chan_swap_enum[] = { - SOC_ENUM_SINGLE_EXT(2, crus_chan_swap_text), -}; - -static const struct snd_kcontrol_new crus_mixer_controls[] = { - SOC_ENUM_EXT("Cirrus SE", crus_en_enum[0], - msm_crus_se_enable_get, msm_crus_se_enable), - SOC_ENUM_EXT("Cirrus SE Audio Mode", crus_se_usecase_enum[0], - msm_crus_se_usecase_get, msm_crus_se_usecase), - SOC_ENUM_EXT("Cirrus SE Load Config", crus_conf_load_enum[0], - msm_crus_load_config_get, msm_crus_load_config), - SOC_ENUM_EXT("Cirrus SE Delta Config", crus_delta_enum[0], - msm_crus_delta_config_get, msm_crus_delta_config), - SOC_ENUM_EXT("Cirrus SE Channel Swap", crus_chan_swap_enum[0], - msm_crus_chan_swap_get, msm_crus_chan_swap), - SOC_SINGLE_EXT("Cirrus SE Channel Swap Duration", SND_SOC_NOPM, 0, - MAX_CHAN_SWAP_SAMPLES, 0, msm_crus_chan_swap_dur_get, - msm_crus_chan_swap_dur), - SOC_SINGLE_EXT("Cirrus SE Rx Port", SND_SOC_NOPM, 0, - AFE_PORT_ID_INVALID, 0, msm_crus_se_rx_port_get, msm_crus_se_rx_port), - SOC_SINGLE_MULTI_EXT("Cirrus SE Audio Index", SND_SOC_NOPM, 0, - 0xFFFF, 0, 4, msm_crus_se_usecase_index_get, NULL), -}; - -void msm_crus_pb_add_controls(struct snd_soc_platform *platform) -{ - crus_se_device = platform->dev; - - if (crus_se_device == NULL) - pr_err("%s: platform->dev is NULL!\n", __func__); - else - pr_debug("%s: platform->dev = %lx\n", __func__, - (unsigned long)crus_se_device); - - if (crus_se_usecase_dt_count == 0) - pr_err("%s: Missing usecase config selections\n", __func__); - - crus_se_usecase_enum[0].items = crus_se_usecase_dt_count; - crus_se_usecase_enum[0].texts = crus_se_usecase_dt_text; - - snd_soc_add_platform_controls(platform, crus_mixer_controls, - ARRAY_SIZE(crus_mixer_controls)); -} -EXPORT_SYMBOL(msm_crus_pb_add_controls); - -static long crus_se_shared_ioctl(struct file *f, unsigned int cmd, - void __user *arg) -{ - int result = 0, port; - uint32_t bufsize = 0, size; - void *io_data = NULL; - - pr_debug("%s\n", __func__); - - if (copy_from_user(&size, arg, sizeof(size))) { - pr_err("%s: copy_from_user (size) failed\n", __func__); - result = -EFAULT; - goto exit; - } - - /* Copy IOCTL header from usermode */ - if (copy_from_user(&crus_se_hdr, arg, size)) { - pr_err("%s: copy_from_user (struct) failed\n", __func__); - result = -EFAULT; - goto exit; - } - - bufsize = crus_se_hdr.data_length; - io_data = kzalloc(bufsize, GFP_KERNEL); - if (!io_data) { - pr_err("%s: Memory allocation failed!\n", __func__); - return -ENOMEM; - } - - switch (cmd) { - case CRUS_SE_IOCTL_GET: - switch (crus_se_hdr.module_id) { - case CRUS_MODULE_ID_RX: - port = cirrus_ff_port; - break; - default: - pr_debug("%s: Unrecognized port ID (%d)\n", __func__, - crus_se_hdr.module_id); - port = cirrus_ff_port; - } - - crus_get_param(port, CIRRUS_SE, crus_se_hdr.param_id, - bufsize, io_data); - - result = copy_to_user(crus_se_hdr.data, io_data, bufsize); - if (result) { - pr_err("%s: copy_to_user failed (%d)\n", __func__, - result); - result = -EFAULT; - } else { - result = bufsize; - } - break; - case CRUS_SE_IOCTL_SET: - result = copy_from_user(io_data, (void *)crus_se_hdr.data, - bufsize); - if (result) { - pr_err("%s: copy_from_user failed (%d)\n", __func__, - result); - result = -EFAULT; - goto exit_io; - } - - switch (crus_se_hdr.module_id) { - case CRUS_MODULE_ID_RX: - port = cirrus_ff_port; - break; - default: - pr_debug("%s: Unrecognized port ID (%d)\n", __func__, - crus_se_hdr.module_id); - port = cirrus_ff_port; - } - - crus_set_param(port, CIRRUS_SE, crus_se_hdr.param_id, - bufsize, io_data); - break; - default: - pr_err("%s: Invalid IOCTL, command = %d!\n", __func__, cmd); - result = -EINVAL; - } - -exit_io: - kfree(io_data); -exit: - return result; -} - -static long crus_se_ioctl(struct file *f, - unsigned int cmd, unsigned long arg) -{ - pr_debug("%s\n", __func__); - - return crus_se_shared_ioctl(f, cmd, (void __user *)arg); -} - -#ifdef CONFIG_COMPAT -static long crus_se_compat_ioctl(struct file *f, - unsigned int cmd, unsigned long arg) -{ - unsigned int cmd64; - - pr_debug("%s\n", __func__); - - switch (cmd) { - case CRUS_SE_IOCTL_GET32: - cmd64 = CRUS_SE_IOCTL_GET; - break; - case CRUS_SE_IOCTL_SET32: - cmd64 = CRUS_SE_IOCTL_SET; - break; - default: - pr_err("%s: Invalid IOCTL, command = %d!\n", __func__, cmd); - return -EINVAL; - } - - return crus_se_shared_ioctl(f, cmd64, compat_ptr(arg)); -} -#else -#define crus_se_compat_ioctl NULL -#endif - -static int crus_se_open(struct inode *inode, struct file *f) -{ - int result = 0; - - pr_debug("%s\n", __func__); - - atomic_inc(&crus_se_misc_usage_count); - return result; -} - -static int crus_se_release(struct inode *inode, struct file *f) -{ - int result = 0; - - pr_debug("%s\n", __func__); - - atomic_dec(&crus_se_misc_usage_count); - pr_debug("%s: ref count %d!\n", __func__, - atomic_read(&crus_se_misc_usage_count)); - - return result; -} - -static int msm_cirrus_playback_probe(struct platform_device *pdev) -{ - int i, rc = 0; - u32 ff_port_id; - int num_entries = 0; - - pr_info("CRUS_SE: initializing platform device\n"); - - crus_se_usecase_dt_count = of_property_count_strings(pdev->dev.of_node, - "usecase-names"); - if (crus_se_usecase_dt_count <= 0) { - dev_dbg(&pdev->dev, "Usecase names not found\n"); - crus_se_usecase_dt_count = 0; - return 0; - } - - if ((crus_se_usecase_dt_count > 0) && - (crus_se_usecase_dt_count <= MAX_TUNING_CONFIGS)) - of_property_read_string_array(pdev->dev.of_node, - "usecase-names", - crus_se_usecase_dt_text, - crus_se_usecase_dt_count); - else if (crus_se_usecase_dt_count > MAX_TUNING_CONFIGS) { - dev_err(&pdev->dev, "Max of %d usecase configs allowed\n", - MAX_TUNING_CONFIGS); - return -EINVAL; - } - - num_entries = of_property_count_u32_elems(pdev->dev.of_node, - "usecase-indexes"); - if (num_entries > 0) { - of_property_read_u32_array(pdev->dev.of_node, - "usecase-indexes", - crus_se_usecase_dt_index, - crus_se_usecase_dt_count); - } - - for (i = 0; i < crus_se_usecase_dt_count; i++) { - pr_info("CRUS_SE: usecase[%u] = %s\n", - crus_se_usecase_dt_index[i], - crus_se_usecase_dt_text[i]); - } - - rc = of_property_read_u32_index(pdev->dev.of_node, - "afe-port-id", 0, &ff_port_id); - if (rc >= 0) { - cirrus_ff_port = ff_port_id; - } else { - cirrus_ff_port = AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX; - } - pr_info("CRUS_SE: cirrus_ff_port = 0x%x", cirrus_ff_port); - - return 0; -} - -static const struct of_device_id msm_cirrus_playback_dt_match[] = { - {.compatible = "cirrus,msm-cirrus-playback"}, - {} -}; -MODULE_DEVICE_TABLE(of, msm_cirrus_playback_dt_match); - -static struct platform_driver msm_cirrus_playback_driver = { - .driver = { - .name = "msm-cirrus-playback", - .owner = THIS_MODULE, - .of_match_table = msm_cirrus_playback_dt_match, - }, - .probe = msm_cirrus_playback_probe, -}; - -static const struct file_operations crus_se_fops = { - .owner = THIS_MODULE, - .open = crus_se_open, - .release = crus_se_release, - .unlocked_ioctl = crus_se_ioctl, - .compat_ioctl = crus_se_compat_ioctl, -}; - -struct miscdevice crus_se_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = "msm_cirrus_playback", - .fops = &crus_se_fops, -}; - -static int __init crus_se_init(void) -{ - pr_info("CRUS_SE_INIT: initializing misc device\n"); - atomic_set(&crus_se_get_param_flag, 0); - atomic_set(&crus_se_misc_usage_count, 0); - mutex_init(&crus_se_get_param_lock); - mutex_init(&crus_se_lock); - - misc_register(&crus_se_misc); - - return platform_driver_register(&msm_cirrus_playback_driver); -} -module_init(crus_se_init); - -static void __exit crus_se_exit(void) -{ - mutex_destroy(&crus_se_get_param_lock); - mutex_destroy(&crus_se_lock); - - platform_driver_unregister(&msm_cirrus_playback_driver); -} -module_exit(crus_se_exit); - -MODULE_DESCRIPTION("ASoC cirrus-playback driver"); -MODULE_LICENSE("GPL");