Revert "Import S928BXXS4AXJB audio-kernel changes"
This reverts commit 3563ee22f6
.
This commit is contained in:
parent
3563ee22f6
commit
8ae7e1dcff
@ -569,19 +569,7 @@ LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
endif
|
||||
ifeq ($(PROJECT_NAME),$(filter $(PROJECT_NAME),q6q b6q q6aq))
|
||||
##########################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(AUDIO_SRC_FILES)
|
||||
LOCAL_MODULE := tas25xx_dlkm.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := asoc/codecs/tas25xx/tas25xx_dlkm.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
endif
|
||||
###########################################################
|
||||
|
||||
endif # DLKM check
|
||||
endif # supported target check
|
||||
endif
|
||||
|
@ -40,8 +40,6 @@ LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd939x/wcd939x_slave_dlkm.ko
|
||||
LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9378/wcd9378_dlkm.ko
|
||||
LOCAL_MODULE_KO_DIRS += asoc/codecs/wcd9378/wcd9378_slave_dlkm.ko
|
||||
LOCAL_MODULE_KO_DIRS += asoc/codecs/hdmi_dlkm.ko
|
||||
ifeq ($(PROJECT_NAME),$(filter $(PROJECT_NAME),q6q b6q q6aq))
|
||||
LOCAL_MODULE_KO_DIRS += asoc/codecs/tas25xx/tas25xx_dlkm.ko
|
||||
endif
|
||||
|
||||
ifeq ($(call is-board-platform-in-list,pitti),true)
|
||||
|
@ -285,11 +285,6 @@ ifeq ($(KERNEL_BUILD), 1)
|
||||
obj-y += rouleur/
|
||||
obj-y += ./
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SND_SOC_TAS25XX
|
||||
obj-y += tas25xx/
|
||||
endif
|
||||
|
||||
# Module information used by KBuild framework
|
||||
obj-$(CONFIG_WCD9XXX_CODEC_CORE) += wcd_core_dlkm.o
|
||||
obj-$(CONFIG_WCD9XXX_CODEC_CORE_V2) += wcd_core_dlkm.o
|
||||
|
@ -17,9 +17,6 @@
|
||||
#include "lpass-cdc.h"
|
||||
#include "lpass-cdc-registers.h"
|
||||
#include "lpass-cdc-clk-rsc.h"
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
|
||||
#include <sound/samsung/snd_debug_proc.h>
|
||||
#endif
|
||||
|
||||
#define AUTO_SUSPEND_DELAY 50 /* delay in msec */
|
||||
#define LPASS_CDC_TX_MACRO_MAX_OFFSET 0x1000
|
||||
@ -107,19 +104,6 @@ enum {
|
||||
VA_MCLK,
|
||||
};
|
||||
|
||||
/* Based on 9.6MHZ MCLK Freq */
|
||||
enum {
|
||||
CLK_DISABLED = 0,
|
||||
CLK_2P4MHZ,
|
||||
CLK_0P6MHZ,
|
||||
};
|
||||
|
||||
static int dmic_clk_rate_div[] = {
|
||||
[CLK_DISABLED] = 0,
|
||||
[CLK_2P4MHZ] = LPASS_CDC_TX_MACRO_CLK_DIV_4,
|
||||
[CLK_0P6MHZ] = LPASS_CDC_TX_MACRO_CLK_DIV_16,
|
||||
};
|
||||
|
||||
struct lpass_cdc_tx_macro_reg_mask_val {
|
||||
u16 reg;
|
||||
u8 mask;
|
||||
@ -165,15 +149,8 @@ struct lpass_cdc_tx_macro_priv {
|
||||
int pcm_rate[NUM_DECIMATORS];
|
||||
bool swr_dmic_enable;
|
||||
int wlock_holders;
|
||||
u32 dmic_rate_override;
|
||||
};
|
||||
|
||||
static const char* const dmic_rate_override_text[] = {
|
||||
"DISABLED", "CLK_2P4MHZ", "CLK_0P6MHZ"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(dmic_rate_enum, dmic_rate_override_text);
|
||||
|
||||
static int lpass_cdc_tx_macro_wake_enable(struct lpass_cdc_tx_macro_priv *tx_priv,
|
||||
bool wake_enable)
|
||||
{
|
||||
@ -225,48 +202,12 @@ static bool lpass_cdc_tx_macro_get_data(struct snd_soc_component *component,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lpass_cdc_dmic_rate_override_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_kcontrol_component(kcontrol);
|
||||
struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
|
||||
struct device *tx_dev = NULL;
|
||||
|
||||
if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
ucontrol->value.enumerated.item[0] = tx_priv->dmic_rate_override;
|
||||
dev_dbg(component->dev, "%s: dmic rate: %d\n",
|
||||
__func__, tx_priv->dmic_rate_override);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpass_cdc_dmic_rate_override_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_kcontrol_component(kcontrol);
|
||||
struct lpass_cdc_tx_macro_priv *tx_priv = NULL;
|
||||
struct device *tx_dev = NULL;
|
||||
|
||||
if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
tx_priv->dmic_rate_override = ucontrol->value.enumerated.item[0];
|
||||
dev_dbg(component->dev, "%s: dmic rate: %d\n",
|
||||
__func__, tx_priv->dmic_rate_override);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpass_cdc_tx_macro_mclk_enable(
|
||||
struct lpass_cdc_tx_macro_priv *tx_priv,
|
||||
bool mclk_enable)
|
||||
{
|
||||
struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL);
|
||||
int ret = 0, rc = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (regmap == NULL) {
|
||||
dev_err_ratelimited(tx_priv->dev, "%s: regmap is NULL\n", __func__);
|
||||
@ -291,34 +232,16 @@ static int lpass_cdc_tx_macro_mclk_enable(
|
||||
lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev,
|
||||
true);
|
||||
regcache_mark_dirty(regmap);
|
||||
|
||||
ret = regcache_sync_region(regmap,
|
||||
regcache_sync_region(regmap,
|
||||
TX_START_OFFSET,
|
||||
TX_MAX_OFFSET);
|
||||
if (ret < 0) {
|
||||
dev_err_ratelimited(tx_priv->dev,
|
||||
"%s: regcache_sync_region failed\n",
|
||||
__func__);
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
|
||||
sdp_info_print("%s: regcache_sync_region failed\n",
|
||||
__func__);
|
||||
#endif
|
||||
lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev,
|
||||
false);
|
||||
lpass_cdc_clk_rsc_request_clock(tx_priv->dev,
|
||||
TX_CORE_CLK,
|
||||
TX_CORE_CLK,
|
||||
false);
|
||||
goto exit;
|
||||
}
|
||||
if (tx_priv->tx_mclk_users == 0) {
|
||||
rc = (rc | regmap_update_bits(regmap,
|
||||
regmap_update_bits(regmap,
|
||||
LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
|
||||
0x01, 0x01));
|
||||
|
||||
rc = (rc | regmap_update_bits(regmap,
|
||||
0x01, 0x01);
|
||||
regmap_update_bits(regmap,
|
||||
LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
|
||||
0x01, 0x01));
|
||||
0x01, 0x01);
|
||||
}
|
||||
tx_priv->tx_mclk_users++;
|
||||
} else {
|
||||
@ -330,26 +253,17 @@ static int lpass_cdc_tx_macro_mclk_enable(
|
||||
}
|
||||
tx_priv->tx_mclk_users--;
|
||||
if (tx_priv->tx_mclk_users == 0) {
|
||||
rc = (rc | regmap_update_bits(regmap,
|
||||
regmap_update_bits(regmap,
|
||||
LPASS_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
|
||||
0x01, 0x00));
|
||||
rc = (rc | regmap_update_bits(regmap,
|
||||
0x01, 0x00);
|
||||
regmap_update_bits(regmap,
|
||||
LPASS_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
|
||||
0x01, 0x00));
|
||||
0x01, 0x00);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
dev_err_ratelimited(tx_priv->dev, "%s: register writes failed\n",
|
||||
__func__);
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
|
||||
sdp_info_print("%s: register writes failed\n",
|
||||
__func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
lpass_cdc_clk_rsc_fs_gen_request(tx_priv->dev,
|
||||
false);
|
||||
ret = lpass_cdc_clk_rsc_request_clock(tx_priv->dev,
|
||||
lpass_cdc_clk_rsc_request_clock(tx_priv->dev,
|
||||
TX_CORE_CLK,
|
||||
TX_CORE_CLK,
|
||||
false);
|
||||
@ -1955,9 +1869,6 @@ static const struct snd_kcontrol_new lpass_cdc_tx_macro_snd_controls[] = {
|
||||
|
||||
SOC_ENUM_EXT("BCS CH_SEL", bcs_ch_sel_mux_enum,
|
||||
lpass_cdc_tx_macro_get_bcs_ch_sel, lpass_cdc_tx_macro_put_bcs_ch_sel),
|
||||
|
||||
SOC_ENUM_EXT("DMIC_RATE OVERRIDE", dmic_rate_enum,
|
||||
lpass_cdc_dmic_rate_override_get, lpass_cdc_dmic_rate_override_put),
|
||||
};
|
||||
|
||||
static int lpass_cdc_tx_macro_clk_div_get(struct snd_soc_component *component)
|
||||
@ -1968,9 +1879,6 @@ static int lpass_cdc_tx_macro_clk_div_get(struct snd_soc_component *component)
|
||||
if (!lpass_cdc_tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
if (tx_priv->dmic_rate_override)
|
||||
return dmic_clk_rate_div[tx_priv->dmic_rate_override];
|
||||
|
||||
return (int)tx_priv->dmic_clk_div;
|
||||
}
|
||||
|
||||
@ -2027,9 +1935,6 @@ undefined_rate:
|
||||
static const struct lpass_cdc_tx_macro_reg_mask_val
|
||||
lpass_cdc_tx_macro_reg_init[] = {
|
||||
{LPASS_CDC_TX0_TX_PATH_SEC7, 0x3F, 0x0A},
|
||||
{LPASS_CDC_TX0_TX_PATH_CFG1, 0x0F, 0x0A},
|
||||
{LPASS_CDC_TX1_TX_PATH_CFG1, 0x0F, 0x0A},
|
||||
{LPASS_CDC_TX2_TX_PATH_CFG1, 0x0F, 0x0A},
|
||||
};
|
||||
|
||||
static int lpass_cdc_tx_macro_init(struct snd_soc_component *component)
|
||||
|
@ -1,87 +0,0 @@
|
||||
ifeq ($(MODNAME),)
|
||||
KERNEL_BUILD := 1
|
||||
else
|
||||
KERNEL_BUILD := 0
|
||||
endif
|
||||
|
||||
ifeq ($(KERNEL_BUILD), 1)
|
||||
AUDIO_BLD_DIR := $(srctree)
|
||||
AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(KERNEL_BUILD), 0)
|
||||
ifeq ($(CONFIG_ARCH_WAIPIO), y)
|
||||
include $(AUDIO_ROOT)/config/waipioauto.conf
|
||||
INCS += -include $(AUDIO_ROOT)/config/waipioautoconf.h
|
||||
endif
|
||||
endif
|
||||
|
||||
############ COMMON ############
|
||||
COMMON_DIR := include
|
||||
COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR)
|
||||
|
||||
ifdef CONFIG_SND_SOC_TAS25XX
|
||||
TAS25XX_OBJS += src/tas25xx-codec.o
|
||||
TAS25XX_OBJS += src/tas25xx-regmap.o
|
||||
TAS25XX_OBJS += src/tas25xx.o
|
||||
TAS25XX_OBJS += src/tas25xx-logic.o
|
||||
TAS25XX_OBJS += src/tas25xx-regbin-parser.o
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(CONFIG_TAS25XX_ALGO),)
|
||||
TAS25XX_OBJS += algo/src/tas25xx-algo-intf.o
|
||||
TAS25XX_OBJS += algo/src/tas25xx-calib.o
|
||||
TAS25XX_OBJS += algo/src/tas25xx-algo-common.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PLATFORM_MTK),)
|
||||
TAS25XX_OBJS += algo/platform/mtk/tas25xx-mtk-wrapper.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TAS25XX_MISC),)
|
||||
TAS25XX_OBJS += src/tas25xx-misc.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PLATFORM_QCOM),)
|
||||
TAS25XX_OBJS += algo/platform/qcom/tas25xx-algo-qdsp-intf.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TISA_KBIN_INTF),)
|
||||
TAS25XX_OBJS += algo/src/tas25xx-algo-kbin-intf.o
|
||||
TAS25XX_OBJS += algo/src/tas25xx-algo-bin-utils.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TAS25XX_CALIB_VAL_BIG),)
|
||||
TAS25XX_OBJS += algo/src/tas25xx-calib-validation.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TISA_SYSFS_INTF),)
|
||||
TAS25XX_OBJS += algo/src/tas25xx-sysfs-debugfs-utils.o
|
||||
TAS25XX_OBJS += algo/src/smartpa-debug-common.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TISA_BIN_INTF),)
|
||||
TAS25XX_OBJS += algo/src/tas25xx-algo-bin-intf.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PLATFORM_EXYNOS),)
|
||||
TAS25XX_OBJS += algo/platform/exynos/tas25xx-algo-exynos-dsp-intf.o
|
||||
TAS25XX_OBJS += algo/platform/exynos/skinprot-sysfs-cb.o
|
||||
endif
|
||||
|
||||
LINUX_INC += -Iinclude/linux
|
||||
TAS25XX_INC = -I$(AUDIO_ROOT)/asoc/codecs/tas25xx
|
||||
TAS25XX_INC += -I$(AUDIO_ROOT)/asoc/codecs/tas25xx/inc
|
||||
INCS += $(COMMON_INC) $(TAS25XX_INC)
|
||||
EXTRA_CFLAGS += $(INCS)
|
||||
|
||||
|
||||
# Module information used by KBuild framework
|
||||
obj-$(CONFIG_SND_SOC_TAS25XX) += tas25xx_dlkm.o
|
||||
tas25xx_dlkm-y := $(TAS25XX_OBJS)
|
||||
|
||||
# inject some build related information
|
||||
DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"
|
||||
|
@ -1,107 +0,0 @@
|
||||
|
||||
menuconfig SND_SOC_TAS25XX
|
||||
tristate "Texas Instruments TAS25XX SmartAmp(R)"
|
||||
help
|
||||
Enable the support for TAS driver.
|
||||
|
||||
This is the main config under which various
|
||||
other configuration can be enabled based on
|
||||
the below configurations.
|
||||
|
||||
if SND_SOC_TAS25XX
|
||||
config PLATFORM_EXYNOS
|
||||
bool "Exynos platform support"
|
||||
depends on SND_SOC_TAS25XX
|
||||
default n
|
||||
help
|
||||
Enable support for Exynos platform.
|
||||
|
||||
This enables the platform specific interface
|
||||
which acts as abstraction layer to the algorithm
|
||||
for Exynos platform.
|
||||
|
||||
config PLATFORM_MTK
|
||||
bool "MTK platform support"
|
||||
depends on SND_SOC_TAS25XX
|
||||
default n
|
||||
help
|
||||
Enable support for MTK platform.
|
||||
|
||||
This enables the platform specific interface
|
||||
which acts as abstraction layer to the algorithm
|
||||
for MTK platform.
|
||||
|
||||
config TAS25XX_ALGO
|
||||
bool "TAS25XX AP DSP Communication Support"
|
||||
depends on SND_SOC_TAS25XX
|
||||
help
|
||||
Enable support for TAS25XX Calibration driver.
|
||||
|
||||
This includes TAS25XX Calibration driver interfaces
|
||||
and functions also interfacing driver to corresponding
|
||||
Platform/DSP
|
||||
|
||||
config PLATFORM_QCOM
|
||||
bool "QCOM platform support"
|
||||
depends on TAS25XX_ALGO
|
||||
default n
|
||||
help
|
||||
Enable support for Qcom platform.
|
||||
|
||||
This enables the platform specific interface
|
||||
which acts as abstraction layer to the algorithm
|
||||
for Exynos platform.
|
||||
|
||||
config TISA_KBIN_INTF
|
||||
bool "Kbin file method support"
|
||||
depends on PLATFORM_QCOM
|
||||
default n
|
||||
help
|
||||
Enable support for KBin file method
|
||||
|
||||
This is the algorithm specific configuration
|
||||
where the binary file will be opened in the kernel
|
||||
using request_firmware API. This interface currently supported
|
||||
only on the Qualcomm platform
|
||||
|
||||
config TAS25XX_CALIB_VAL_BIG
|
||||
bool "For bigdata & calibration support"
|
||||
depends on TAS25XX_ALGO
|
||||
default n
|
||||
help
|
||||
Enable support for bigdata & calibration.
|
||||
|
||||
Enables the support for sysfs entries under
|
||||
/sys/class/tas25xx directory
|
||||
for calibration, validataion and bigdata
|
||||
|
||||
config TAS25XX_IRQ_BD
|
||||
bool "For bigdata IRQ data"
|
||||
depends on SND_SOC_TAS25XX
|
||||
default n
|
||||
help
|
||||
Enable support for bigdata & calibration.
|
||||
|
||||
Enables the support for sysfs entries under
|
||||
/sys/class/tas25xx_dev/ directory
|
||||
for irq related big data
|
||||
|
||||
config TISA_SYSFS_INTF
|
||||
bool "sysfs interface for calibration and algo support"
|
||||
depends on TAS25XX_ALGO
|
||||
default n
|
||||
help
|
||||
Enable the support for sysfs based interfaces
|
||||
for calibration and algo control
|
||||
|
||||
config TAS25XX_MISC
|
||||
bool "Misc Driver support"
|
||||
default y
|
||||
help
|
||||
Enable misc driver support.
|
||||
|
||||
Enable the misc driver "TAS25XX" which is
|
||||
interface to communicate to device via register
|
||||
read and write
|
||||
|
||||
endif # SND_SOC_TAS25XX
|
@ -1,53 +0,0 @@
|
||||
ccflags-y += -I$(srctree)/$(src)/inc/
|
||||
ccflags-y += -I$(srctree)/sound/soc/codecs/uda20/driver/tas25xx_driver/inc/
|
||||
ccflags-y += -I$(srctree)/sound/soc/mediatek/common/
|
||||
ccflags-y += -I$(src)
|
||||
|
||||
obj-$(CONFIG_SND_SOC_TAS25XX) += snd-soc-tas25xx.o
|
||||
|
||||
snd-soc-tas25xx-$(CONFIG_SND_SOC_TAS25XX) := src/tas25xx-codec.o \
|
||||
src/tas25xx-regmap.o \
|
||||
src/tas25xx.o \
|
||||
src/tas25xx-logic.o \
|
||||
src/tas25xx-regbin-parser.o
|
||||
|
||||
ifneq ($(CONFIG_TAS25XX_ALGO),)
|
||||
snd-soc-tas25xx-objs += algo/src/tas25xx-algo-intf.o \
|
||||
algo/src/tas25xx-calib.o \
|
||||
algo/src/tas25xx-algo-common.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PLATFORM_MTK),)
|
||||
snd-soc-tas25xx-objs += algo/platform/mtk/tas25xx-mtk-wrapper.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TAS25XX_MISC),)
|
||||
snd-soc-tas25xx-objs += src/tas25xx-misc.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PLATFORM_QCOM),)
|
||||
snd-soc-tas25xx-objs += algo/platform/qcom/tas25xx-algo-qdsp-intf.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TISA_KBIN_INTF),)
|
||||
snd-soc-tas25xx-objs += algo/src/tas25xx-algo-kbin-intf.o \
|
||||
algo/src/tas25xx-algo-bin-utils.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TAS25XX_CALIB_VAL_BIG),)
|
||||
snd-soc-tas25xx-objs += algo/src/tas25xx-calib-validation.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TISA_SYSFS_INTF),)
|
||||
snd-soc-tas25xx-objs += algo/src/tas25xx-sysfs-debugfs-utils.o \
|
||||
algo/src/smartpa-debug-common.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_TISA_BIN_INTF),)
|
||||
snd-soc-tas25xx-objs += algo/src/tas25xx-algo-bin-intf.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PLATFORM_EXYNOS),)
|
||||
snd-soc-tas25xx-objs += algo/platform/exynos/tas25xx-algo-exynos-dsp-intf.o
|
||||
snd-soc-tas25xx-objs += algo/platform/exynos/skinprot-sysfs-cb.o
|
||||
endif
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* =============================================================================
|
||||
* Copyright (c) 2016 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.
|
||||
*
|
||||
* File:
|
||||
* tas25xx-codec.h
|
||||
*
|
||||
* Description:
|
||||
* header file for tas25xx-codec.c
|
||||
*
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _TAS25XX_CODEC_H
|
||||
#define _TAS25XX_CODEC_H
|
||||
|
||||
#include "tas25xx.h"
|
||||
|
||||
int tas25xx_register_codec(struct tas25xx_priv *p_tas25xx);
|
||||
int tas25xx_deregister_codec(struct tas25xx_priv *p_tas25xx);
|
||||
|
||||
#endif /* _TAS25XX_CODEC_H */
|
@ -1,22 +0,0 @@
|
||||
#ifndef __TAS25XX_DEVICE_
|
||||
#define __TAS25XX_DEVICE_
|
||||
|
||||
#include "tas25xx.h"
|
||||
|
||||
int tas25xx_software_reset(struct tas25xx_priv *p_tas25xx, int ch);
|
||||
int tas25xx_set_power_mute(struct tas25xx_priv *p_tas25xx, int ch);
|
||||
int tas25xx_tx_set_edge(struct tas25xx_priv *p_tas25xx,
|
||||
unsigned int tx_edge, int ch);
|
||||
int tas25xx_tx_set_start_slot(struct tas25xx_priv *p_tas25xx,
|
||||
unsigned int tx_start_slot, int ch);
|
||||
int tas25xx_rx_set_edge(struct tas25xx_priv *p_tas25xx,
|
||||
unsigned int rx_edge, int ch);
|
||||
int tas25xx_rx_set_bitwidth(struct tas25xx_priv *p_tas25xx,
|
||||
int bitwidth, int ch);
|
||||
/* Interrupt Related Functions */
|
||||
int tas_dev_interrupt_clear(struct tas25xx_priv *p_tas25xx, int ch);
|
||||
int tas_dev_interrupt_enable(struct tas25xx_priv *p_tas25xx, int ch);
|
||||
int tas_dev_interrupt_disable(struct tas25xx_priv *p_tas25xx, int ch);
|
||||
int tas_dev_interrupt_read(struct tas25xx_priv *p_tas25xx, int ch, int *type);
|
||||
|
||||
#endif /* __TAS25XX_DEVICE_ */
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* ALSA SoC Texas Instruments TAS25XX High Performance Smart Amplifier
|
||||
*
|
||||
* Copyright (C) 2024 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Niranjan H Y
|
||||
*
|
||||
* This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
#ifndef __TAS25XX_EXT_H__
|
||||
#define __TAS25XX_EXT_H__
|
||||
|
||||
enum tas_amp_status_t {
|
||||
TAS_AMP_ERR_EINVAL = -3, /* invalid parameter */
|
||||
TAS_AMP_ERR_FW_LOAD = -2, /* amp fw download failure */
|
||||
TAS_AMP_ERR_I2C = -1, /* amp i2c error */
|
||||
TAS_AMP_STATE_UNINIT = 0, /* uninitialized state */
|
||||
TAS_AMP_STATE_BOOT_SUCCESS = 1, /* amp first i2c successful */
|
||||
TAS_AMP_STATE_FW_LOAD_SUCCESS = 2, /* amp fully initialized for playback */
|
||||
};
|
||||
|
||||
enum tas_amp_error_t {
|
||||
TAS_AMP_NO_ERR = 0,
|
||||
TAS_AMP_SHORTCIRCUIT_ERR = 1,
|
||||
TAS_AMP_ERR_MAX,
|
||||
};
|
||||
|
||||
/* get the current amp status */
|
||||
enum tas_amp_status_t tas25xx_get_state(uint32_t id);
|
||||
|
||||
/* error callback for i2c error */
|
||||
void tas25xx_register_i2c_error_callback(void (*i2c_err_cb)(uint32_t i2caddr));
|
||||
void tas25xx_register_amp_error_callback(void (*amp_err_cb)(int32_t i2caddr, int32_t err));
|
||||
|
||||
|
||||
#endif /* __TAS25XX_EXT_H__ */
|
@ -1,42 +0,0 @@
|
||||
#ifndef __TAS25XX_LOGIC_
|
||||
#define __TAS25XX_LOGIC_
|
||||
|
||||
#include "tas25xx.h"
|
||||
|
||||
#define TAS25XX_STREAM_PLAYBACK 0
|
||||
#define TAS25XX_STREAM_CAPTURE 1
|
||||
|
||||
int tas25xx_register_device(struct tas25xx_priv *p_tas25xx);
|
||||
int tas25xx_probe(struct tas25xx_priv *p_tas25xx);
|
||||
void tas25xx_remove(struct tas25xx_priv *p_tas25xx);
|
||||
int tas25xx_load_init(struct tas25xx_priv *p_tas25xx, int chn);
|
||||
int tas25xx_irq_work_func(struct tas25xx_priv *p_tas25xx);
|
||||
void tas25xx_load_config(struct tas25xx_priv *p_tas25xx, int chn);
|
||||
int tas25xx_init_work_func(struct tas25xx_priv *p_tas25xx,
|
||||
struct tas_device *dev_tas25xx);
|
||||
int tas25xx_dc_work_func(struct tas25xx_priv *p_tas25xx, int chn);
|
||||
void tas_reload(struct tas25xx_priv *p_tas25xx, int chn);
|
||||
int tas25xx_set_power_state(struct tas25xx_priv *p_tas25xx,
|
||||
enum tas_power_states_t state, uint32_t chbitmask);
|
||||
int tas25xx_iv_vbat_slot_config(struct tas25xx_priv *p_tas25xx,
|
||||
int mn_slot_width);
|
||||
int tas25xx_set_bitwidth(struct tas25xx_priv *p_tas25xx,
|
||||
int bitwidth, int stream);
|
||||
int tas25xx_set_dai_fmt_for_fmt(struct tas25xx_priv *p_tas25xx,
|
||||
unsigned int fmt);
|
||||
int tas25xx_set_tdm_rx_slot(struct tas25xx_priv *p_tas25xx,
|
||||
int slots, int slot_width);
|
||||
int tas25xx_set_tdm_tx_slot(struct tas25xx_priv *p_tas25xx,
|
||||
int slots, int slot_width);
|
||||
|
||||
int tas25xx_change_book(struct tas25xx_priv *p_tas25xx,
|
||||
int32_t chn, int book);
|
||||
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_IRQ_BD)
|
||||
void tas25xx_log_interrupt_stats(struct tas25xx_priv *p_tas25xx);
|
||||
void tas25xx_clear_interrupt_stats(struct tas25xx_priv *p_tas25xx);
|
||||
#endif /* CONFIG_TAS25XX_IRQ_BD */
|
||||
|
||||
int tas25xx_get_drv_channel_opmode(void);
|
||||
|
||||
#endif /*__TAS25XX_LOGIC_*/
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* =============================================================================
|
||||
* Copyright (c) 2016 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* File:
|
||||
* tas2562-misc.h
|
||||
*
|
||||
* Description:
|
||||
* header file for tas2562-misc.c
|
||||
*
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _TAS25XX_MISC_H
|
||||
#define _TAS25XX_MISC_H
|
||||
|
||||
#define TIAUDIO_CMD_REG_WITE 1
|
||||
#define TIAUDIO_CMD_REG_READ 2
|
||||
#define TIAUDIO_CMD_DEBUG_ON 3
|
||||
#define TIAUDIO_CMD_CALIBRATION 7
|
||||
#define TIAUDIO_CMD_SAMPLERATE 8
|
||||
#define TIAUDIO_CMD_BITRATE 9
|
||||
#define TIAUDIO_CMD_DACVOLUME 10
|
||||
#define TIAUDIO_CMD_SPEAKER 11
|
||||
|
||||
int tas25xx_register_misc(struct tas25xx_priv *p_tas25xx);
|
||||
int tas25xx_deregister_misc(struct tas25xx_priv *p_tas25xx);
|
||||
|
||||
#endif /* _TAS25XX_MISC_H */
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* ALSA SoC Texas Instruments TAS25XX High Performance 4W Smart Amplifier
|
||||
*
|
||||
* Copyright (C) 2021 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Vijeth P O
|
||||
* Modified: 10-07-21
|
||||
*
|
||||
* This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TAS25XX_REGBIN_PARSER__
|
||||
#define __TAS25XX_REGBIN_PARSER__
|
||||
|
||||
#define SampleRate_48000 0
|
||||
#define SampleRate_44100 1
|
||||
#define SampleRate_96000 2
|
||||
|
||||
#define FMT_INV_NB_NF 0
|
||||
#define FMT_INV_IB_NF 1
|
||||
#define FMT_INV_NB_IF 2
|
||||
#define FMT_INV_IB_IF 3
|
||||
|
||||
#define FMT_MASK_I2S 0
|
||||
#define FMT_MASK_DSP_A 1
|
||||
#define FMT_MASK_DSP_B 2
|
||||
#define FMT_MASK_LEFT_J 3
|
||||
|
||||
#define RX_SLOTS_16 0
|
||||
#define RX_SLOTS_24 1
|
||||
#define RX_SLOTS_32 2
|
||||
|
||||
#define TX_SLOTS_16 0
|
||||
#define TX_SLOTS_24 1
|
||||
#define TX_SLOTS_32 2
|
||||
|
||||
#define RX_BITWIDTH_16 0
|
||||
#define RX_BITWIDTH_24 1
|
||||
#define RX_BITWIDTH_32 2
|
||||
|
||||
#define RX_SLOTLEN_16 0
|
||||
#define RX_SLOTLEN_24 1
|
||||
#define RX_SLOTLEN_32 2
|
||||
|
||||
#define TX_SLOTLEN_16 0
|
||||
#define TX_SLOTLEN_24 1
|
||||
#define TX_SLOTLEN_32 2
|
||||
|
||||
#define SUPPORTED_BIN_VERSION 7
|
||||
|
||||
#define TAS25XX_DEFAULT 0xFFFFFFFF
|
||||
|
||||
enum kcntl_during_t {
|
||||
KCNTR_ANYTIME = 0, /* instant update */
|
||||
KCNTR_PRE_POWERUP = 1, /* during pre-power up */
|
||||
KCNTR_POST_POWERUP = 2, /* during post-power up */
|
||||
};
|
||||
|
||||
struct default_hw_params {
|
||||
char sample_rate;
|
||||
char fmt_inv;
|
||||
char fmt_mask;
|
||||
char rx_slots;
|
||||
char tx_slots;
|
||||
char rx_bitwidth;
|
||||
char rx_slotlen;
|
||||
char tx_slotlen;
|
||||
};
|
||||
|
||||
struct tas_dev {
|
||||
u8 device;
|
||||
u8 i2c_addr;
|
||||
};
|
||||
|
||||
struct bin_header {
|
||||
u32 version;
|
||||
u8 name[64];
|
||||
u32 timestamp;
|
||||
u32 size;
|
||||
u32 channels;
|
||||
struct tas_dev dev[MAX_CHANNELS];
|
||||
u8 iv_width;
|
||||
u8 vbat_mon;
|
||||
u32 features;
|
||||
} __attribute__((packed));
|
||||
|
||||
int32_t tas25xx_load_firmware(struct tas25xx_priv *p_tas25xx, int max_retry_count);
|
||||
int32_t tas25xx_create_kcontrols(struct tas25xx_priv *p_tas25xx);
|
||||
int32_t tas25xx_remove_binfile(struct tas25xx_priv *p_tas25xx);
|
||||
int32_t tas25xx_set_init_params(struct tas25xx_priv *p_tas25xx, int32_t ch);
|
||||
int32_t tas25xx_set_sample_rate(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t sample_rate);
|
||||
int32_t tas25xx_set_fmt_inv(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t fmt_inv);
|
||||
int32_t tas25xx_set_fmt_mask(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t fmt_mask);
|
||||
int32_t tas25xx_set_rx_slots(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t rx_slot);
|
||||
int32_t tas25xx_set_tx_slots(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t tx_slot);
|
||||
int32_t tas25xx_set_rx_bitwidth(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t rx_bitwidth);
|
||||
int32_t tas25xx_set_rx_slotlen(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t rx_slotlen);
|
||||
int32_t tas25xx_set_tx_slotlen(struct tas25xx_priv *p_tas25xx, int32_t ch, int32_t tx_slotlen);
|
||||
int32_t tas25xx_set_pre_powerup(struct tas25xx_priv *p_tas25xx, int32_t ch);
|
||||
int32_t tas25xx_set_post_powerup(struct tas25xx_priv *p_tas25xx, int32_t ch);
|
||||
int32_t tas25xx_set_pre_powerdown(struct tas25xx_priv *p_tas25xx, int32_t ch);
|
||||
int32_t tas25xx_set_post_powerdown(struct tas25xx_priv *p_tas25xx, int32_t ch);
|
||||
|
||||
int32_t tas25xx_process_block(struct tas25xx_priv *p_tas25xx, char *mem, int32_t chn);
|
||||
|
||||
int32_t tas25xx_check_if_powered_on(struct tas25xx_priv *p_tas25xx, int *state, int ch);
|
||||
int tas_write_init_config_params(struct tas25xx_priv *p_tas25xx, int number_of_channels);
|
||||
|
||||
int32_t tas25xx_update_kcontrol_data(struct tas25xx_priv *p_tas25xx, enum kcntl_during_t cur_state,
|
||||
uint32_t chmask);
|
||||
|
||||
void tas25xx_prep_dev_for_calib(int start);
|
||||
#endif /* __TAS25XX_REGBIN_PARSER__ */
|
@ -1,26 +0,0 @@
|
||||
#ifndef __TAS25XX_REGMAP__
|
||||
#define __TAS25XX_REGMAP__
|
||||
#include <linux/version.h>
|
||||
#include "tas25xx.h"
|
||||
|
||||
struct linux_platform {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap[MAX_CHANNELS];
|
||||
struct hrtimer mtimer;
|
||||
struct snd_soc_component *codec;
|
||||
/* device is working, but system is suspended */
|
||||
int (*runtime_suspend)(struct tas25xx_priv *p_tas25xx);
|
||||
int (*runtime_resume)(struct tas25xx_priv *p_tas25xx);
|
||||
bool mb_runtime_suspend;
|
||||
bool i2c_suspend;
|
||||
};
|
||||
|
||||
void tas25xx_select_cfg_blk(void *pContext, int conf_no,
|
||||
unsigned char block_type);
|
||||
void tas25xx_dump_regs(struct tas25xx_priv *p_tas25xx, int chn);
|
||||
|
||||
|
||||
void tas25xx_register_i2c_error_callback(void (*i2c_err_cb)(uint32_t));
|
||||
int tas25xx_check_last_i2c_error_n_reset(void);
|
||||
#endif /*__TAS25XX_REGMAP__*/
|
@ -1,420 +0,0 @@
|
||||
/*
|
||||
* ALSA SoC Texas Instruments TAS25XX High Performance 4W Smart Amplifier
|
||||
*
|
||||
* Copyright (C) 2022 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Niranjan H Y, Vijeth P O
|
||||
*
|
||||
* This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
#ifndef __TAS25XX__
|
||||
#define __TAS25XX__
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#define TAS25XX_DRIVER_TAG "UDA_0.0.21_6_K6.1"
|
||||
|
||||
#define MAX_CHANNELS 4
|
||||
|
||||
/* Page Control Register */
|
||||
#define TAS25XX_PAGECTL_REG 0
|
||||
|
||||
/* Book Control Register (available in page0 of each book) */
|
||||
#define TAS25XX_BOOKCTL_PAGE 0
|
||||
#define TAS25XX_BOOKCTL_REG 127
|
||||
|
||||
#define TAS25XX_REG(book, page, reg) (((book * 256 * 128) + \
|
||||
(page * 128)) + reg)
|
||||
|
||||
#define TAS25XX_BOOK_ID(reg) (reg / (256 * 128))
|
||||
#define TAS25XX_PAGE_ID(reg) ((reg % (256 * 128)) / 128)
|
||||
#define TAS25XX_BOOK_REG(reg) (reg % (256 * 128))
|
||||
#define TAS25XX_PAGE_REG(reg) ((reg % (256 * 128)) % 128)
|
||||
#define TAS25XX_REG_NO_BOOK(reg) (reg - (TAS25XX_BOOK_ID(reg) * 256 * 128))
|
||||
|
||||
/* Book */
|
||||
#define TAS25XX_BOOK TAS25XX_REG(0x0, 0x0, 0x7F)
|
||||
#define TAS25XX_BOOK_BOOK70_MASK (0xff << 0)
|
||||
|
||||
/* Rev Info */
|
||||
#define TAS25XX_REVID_REG TAS25XX_REG(0x0, 0x0, 0x78)
|
||||
|
||||
/* data format */
|
||||
#define TAS25XX_DATAFORMAT_SHIFT 2
|
||||
#define TAS25XX_DATAFORMAT_I2S 0x0
|
||||
#define TAS25XX_DATAFORMAT_DSP 0x1
|
||||
#define TAS25XX_DATAFORMAT_RIGHT_J 0x2
|
||||
#define TAS25XX_DATAFORMAT_LEFT_J 0x3
|
||||
|
||||
#define TAS25XX_DAI_FMT_MASK (0x7 << TAS25XX_DATAFORMAT_SHIFT)
|
||||
|
||||
|
||||
#define ERROR_NONE 0x0000000
|
||||
#define ERROR_PLL_ABSENT 0x0000001
|
||||
#define ERROR_DEVA_I2C_COMM 0x0000002
|
||||
#define ERROR_DEVB_I2C_COMM 0x0000004
|
||||
#define ERROR_CLOCK 0x0000008
|
||||
#define ERROR_YRAM_CRCCHK 0x0000010
|
||||
#define ERROR_OVER_CURRENT 0x0000020
|
||||
#define ERROR_DIE_OVERTEMP 0x0000040
|
||||
#define ERROR_OVER_VOLTAGE 0x0000080
|
||||
#define ERROR_UNDER_VOLTAGE 0x0000100
|
||||
#define ERROR_BROWNOUT 0x0000200
|
||||
#define ERROR_CLASSD_PWR 0x0000400
|
||||
#define ERROR_FAILSAFE 0x0000800
|
||||
|
||||
#define TAS25XX_IRQ_DET_TIMEOUT 30000
|
||||
#define TAS25XX_IRQ_DET_CNT_LIMIT 500
|
||||
|
||||
/* 5 second */
|
||||
#define CHECK_PERIOD 5000
|
||||
|
||||
#define TAS25XX_I2C_RETRY_COUNT 3
|
||||
|
||||
#define TAS25XX_SWITCH 0x10000001
|
||||
#define TAS25XX_RIGHT_SWITCH 0x10000002
|
||||
#define RX_SCFG_LEFT 0x10000003
|
||||
#define RX_SCFG_RIGHT 0x10000004
|
||||
|
||||
#define RESTART_MAX 3
|
||||
#define MAX_CMD_LIST 5 /* sysfs cmd nodes */
|
||||
|
||||
struct tas25xx_priv;
|
||||
struct snd_soc_component;
|
||||
|
||||
/* REGBIN related */
|
||||
#define TAS25XX_CONFIG_SIZE (10)
|
||||
#define TAS25XX_DEVICE_SUM (8)
|
||||
|
||||
#define TAS25XX_CMD_SING_W (0x1)
|
||||
#define TAS25XX_CMD_BURST (0x2)
|
||||
#define TAS25XX_CMD_DELAY (0x3)
|
||||
#define TAS25XX_CMD_FIELD_W (0x4)
|
||||
|
||||
#define SMS_HTONS(a, b) ((((a)&0x00FF)<<8) | \
|
||||
((b)&0x00FF))
|
||||
#define SMS_HTONL(a, b, c, d) ((((a)&0x000000FF)<<24) |\
|
||||
(((b)&0x000000FF)<<16) | \
|
||||
(((c)&0x000000FF)<<8) | \
|
||||
((d)&0x000000FF))
|
||||
|
||||
|
||||
#define CMD_SINGLE_WRITE 0
|
||||
#define CMD_BURST_WRITES 1
|
||||
#define CMD_UPDATE_BITS 2
|
||||
#define CMD_DELAY 3
|
||||
|
||||
#define CMD_SINGLE_WRITE_SZ 6
|
||||
#define CMD_BURST_WRITES_SZ 9
|
||||
#define CMD_UPDATE_BITS_SZ 7
|
||||
#define CMD_DELAY_SZ 5
|
||||
|
||||
#define DSP_FW_LOAD_NTRIES 20
|
||||
|
||||
#define INTERRUPT_TYPE_CLOCK_BASED (1<<0)
|
||||
#define INTERRUPT_TYPE_NON_CLOCK_BASED (1<<1)
|
||||
|
||||
enum tas_power_states_t {
|
||||
TAS_POWER_ACTIVE = 0,
|
||||
TAS_POWER_MUTE = 1,
|
||||
TAS_POWER_SHUTDOWN = 2,
|
||||
};
|
||||
|
||||
enum tas25xx_dsp_fw_state {
|
||||
TAS25XX_DSP_FW_NONE = 0,
|
||||
TAS25XX_DSP_FW_TRYLOAD,
|
||||
TAS25XX_DSP_FW_PARSE_FAIL,
|
||||
TAS25XX_DSP_FW_LOAD_FAIL,
|
||||
TAS25XX_DSP_FW_OK,
|
||||
};
|
||||
|
||||
enum tas25xx_bin_blk_type {
|
||||
TAS25XX_BIN_BLK_COEFF = 1,
|
||||
TAS25XX_BIN_BLK_POST_POWER_UP,
|
||||
TAS25XX_BIN_BLK_PRE_SHUTDOWN,
|
||||
TAS25XX_BIN_BLK_PRE_POWER_UP,
|
||||
TAS25XX_BIN_BLK_POST_SHUTDOWN
|
||||
};
|
||||
|
||||
enum tas_int_action_t {
|
||||
TAS_INT_ACTION_NOACTION = 0,
|
||||
TAS_INT_ACTION_SW_RESET = 1 << 0,
|
||||
TAS_INT_ACTION_HW_RESET = 1 << 1,
|
||||
TAS_INT_ACTION_POWER_ON = 1 << 2,
|
||||
};
|
||||
|
||||
struct tas25xx_block_data {
|
||||
unsigned char dev_idx;
|
||||
unsigned char block_type;
|
||||
unsigned short yram_checksum;
|
||||
unsigned int block_size;
|
||||
unsigned int nSublocks;
|
||||
unsigned char *regdata;
|
||||
};
|
||||
|
||||
struct tas25xx_config_info {
|
||||
unsigned int nblocks;
|
||||
unsigned int real_nblocks;
|
||||
struct tas25xx_block_data **blk_data;
|
||||
};
|
||||
|
||||
void tas25xx_select_cfg_blk(void *pContext, int conf_no,
|
||||
unsigned char block_type);
|
||||
int tas25xx_load_container(struct tas25xx_priv *pTAS256x);
|
||||
void tas25xx_config_info_remove(void *pContext);
|
||||
|
||||
struct tas25xx_register {
|
||||
int book;
|
||||
int page;
|
||||
int reg;
|
||||
};
|
||||
|
||||
/* Used for Register Dump */
|
||||
struct tas25xx_reg {
|
||||
unsigned int reg_index;
|
||||
unsigned int reg_val;
|
||||
};
|
||||
|
||||
struct tas25xx_dai_cfg {
|
||||
unsigned int dai_fmt;
|
||||
unsigned int tdm_delay;
|
||||
};
|
||||
|
||||
/*struct tas25xx_buf_cfg {
|
||||
* unsigned short bufSize;
|
||||
* unsigned char *buf;
|
||||
*};
|
||||
*/
|
||||
|
||||
//This should be removed or modified
|
||||
enum ch_bitmask {
|
||||
channel_left = 0x1 << 0,
|
||||
channel_right = 0x1 << 1,
|
||||
channel_both = channel_left|channel_right
|
||||
};
|
||||
|
||||
/*
|
||||
* device ops function structure
|
||||
*/
|
||||
struct tas_device_ops {
|
||||
/**< init typically for loading optimal settings */
|
||||
int (*tas_init)(struct tas25xx_priv *p_tas25xx, int chn);
|
||||
int (*tas_probe)(struct tas25xx_priv *p_tas25xx,
|
||||
struct snd_soc_component *codec, int chn);
|
||||
/*TODO:*/
|
||||
};
|
||||
|
||||
|
||||
struct tas_device {
|
||||
int mn_chip_id;
|
||||
int mn_current_book;
|
||||
int mn_addr;
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
int irq_no;
|
||||
int device_id;
|
||||
int channel_no;
|
||||
int rx_mode;
|
||||
int dvc_pcm;
|
||||
int bst_vltg;
|
||||
int bst_ilm;
|
||||
int ampoutput_lvl;
|
||||
int lim_switch;
|
||||
int lim_max_attn;
|
||||
int lim_thr_max;
|
||||
int lim_thr_min;
|
||||
int lim_att_rate;
|
||||
int lim_rel_rate;
|
||||
int lim_att_stp_size;
|
||||
int lim_rel_stp_size;
|
||||
int lim_max_thd;
|
||||
int lim_min_thd;
|
||||
int lim_infl_pt;
|
||||
int lim_trk_slp;
|
||||
int bop_enable;
|
||||
int bop_thd;
|
||||
int bop_att_rate;
|
||||
int bop_att_stp_size;
|
||||
int bop_hld_time;
|
||||
int bop_mute;
|
||||
int bosd_enable;
|
||||
int bosd_thd;
|
||||
int vbat_lpf;
|
||||
int rx_cfg;
|
||||
int classh_timer;
|
||||
int reciever_enable;
|
||||
int icn_sw;
|
||||
int icn_thr;
|
||||
int icn_hyst;
|
||||
struct tas_device_ops dev_ops;
|
||||
struct delayed_work init_work;
|
||||
struct tas25xx_priv *prv_data;
|
||||
/* interrupt count since interrupt enable */
|
||||
uint8_t irq_count;
|
||||
unsigned long jiffies;
|
||||
/* Fail Safe */
|
||||
unsigned int mn_restart;
|
||||
};
|
||||
|
||||
struct tas25xx_intr_info {
|
||||
char name[64];
|
||||
int32_t reg;
|
||||
int32_t mask;
|
||||
int32_t action;
|
||||
int32_t detected;
|
||||
int32_t is_clock_based;
|
||||
int32_t notify_int_val;
|
||||
uint32_t count;
|
||||
uint64_t count_persist;
|
||||
struct device_attribute *dev_attr;
|
||||
};
|
||||
|
||||
struct tas25xx_interrupts {
|
||||
uint8_t count;
|
||||
uint8_t *buf_intr_enable;
|
||||
uint8_t *buf_intr_disable;
|
||||
uint8_t *buf_intr_clear;
|
||||
struct tas25xx_intr_info *intr_info;
|
||||
uint32_t processing_delay;
|
||||
};
|
||||
|
||||
struct tas_regbin_read_blok_t {
|
||||
int32_t reg;
|
||||
int32_t mask;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
struct tas_block_op_data_t {
|
||||
uint32_t no_of_rx_blks;
|
||||
uint32_t no_of_tx_blks;
|
||||
uint8_t *sw_reset;
|
||||
uint8_t *power_check;
|
||||
uint8_t *mute;
|
||||
uint8_t *cal_init;
|
||||
uint8_t *cal_deinit;
|
||||
uint8_t *rx_fmt_data;
|
||||
uint8_t *tx_fmt_data;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_IRQ_BD)
|
||||
struct irq_bigdata {
|
||||
struct device_attribute *p_dev_attr;
|
||||
struct attribute **p_attr_arr;
|
||||
struct device *irq_dev;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct cmd_data {
|
||||
struct device_attribute *p_dev_attr;
|
||||
struct attribute **p_attr_arr;
|
||||
struct device *cmd_dev;
|
||||
};
|
||||
|
||||
struct tas25xx_priv {
|
||||
struct linux_platform *platform_data;
|
||||
struct kobject *k_obj;
|
||||
int m_power_state;
|
||||
int mn_frame_size;
|
||||
int mn_ppg;
|
||||
int mn_ch_size;
|
||||
int mn_rx_width;
|
||||
int mn_tx_slot_width;
|
||||
int sample_rate;
|
||||
int mn_iv_width;
|
||||
int curr_mn_iv_width;
|
||||
int mn_vbat;
|
||||
int curr_mn_vbat;
|
||||
int ch_count;
|
||||
int mn_slots;
|
||||
unsigned int mn_fmt;
|
||||
int mn_fmt_mode;
|
||||
int mn_frame_start;
|
||||
int mn_rx_edge;
|
||||
int mn_rx_offset;
|
||||
int mn_tx_edge;
|
||||
int mn_tx_offset;
|
||||
int *ti_amp_state;
|
||||
int dac_power; /* this is set based on the DAC events */
|
||||
struct tas_device **devs;
|
||||
int (*read)(struct tas25xx_priv *p_tas25xx, int32_t chn,
|
||||
unsigned int reg, unsigned int *pValue);
|
||||
int (*write)(struct tas25xx_priv *p_tas25xx, int32_t chn,
|
||||
unsigned int reg, unsigned int Value);
|
||||
int (*bulk_read)(struct tas25xx_priv *p_tas25xx, int32_t chn,
|
||||
unsigned int reg, unsigned char *p_data, unsigned int len);
|
||||
int (*bulk_write)(struct tas25xx_priv *p_tas25xx, int32_t chn,
|
||||
unsigned int reg, unsigned char *p_data, unsigned int len);
|
||||
int (*update_bits)(struct tas25xx_priv *p_tas25xx, int32_t chn,
|
||||
unsigned int reg, unsigned int mask, unsigned int value);
|
||||
void (*hw_reset)(struct tas25xx_priv *p_tas25xx);
|
||||
void (*clear_irq)(struct tas25xx_priv *p_tas25xx);
|
||||
void (*enable_irq)(struct tas25xx_priv *p_tas25xx);
|
||||
void (*disable_irq)(struct tas25xx_priv *p_tas25xx);
|
||||
unsigned int mn_err_code;
|
||||
int (*plat_write)(void *plat_data,
|
||||
unsigned int i2c_addr, unsigned int reg, unsigned int value,
|
||||
unsigned int channel);
|
||||
int (*plat_bulk_write)(void *plat_data, unsigned int i2c_addr,
|
||||
unsigned int reg, unsigned char *pData,
|
||||
unsigned int nLength, unsigned int channel);
|
||||
int (*plat_read)(void *plat_data, unsigned int i2c_addr,
|
||||
unsigned int reg, unsigned int *value, unsigned int channel);
|
||||
int (*plat_bulk_read)(void *plat_data, unsigned int i2c_addr,
|
||||
unsigned int reg, unsigned char *pData,
|
||||
unsigned int nLength, unsigned int channel);
|
||||
int (*plat_update_bits)(void *plat_data, unsigned int i2c_addr,
|
||||
unsigned int reg, unsigned int mask,
|
||||
unsigned int value, unsigned int channel);
|
||||
void (*schedule_init_work)(struct tas25xx_priv *p_tas25xx, int ch);
|
||||
void (*cancel_init_work) (struct tas25xx_priv *p_tas25xx, int ch);
|
||||
struct mutex dev_lock;
|
||||
struct mutex codec_lock;
|
||||
struct mutex file_lock;
|
||||
struct delayed_work irq_work;
|
||||
struct delayed_work dc_work;
|
||||
int iv_enable;
|
||||
uint32_t dev_revid;
|
||||
uint32_t fw_size;
|
||||
uint8_t *fw_data;
|
||||
struct delayed_work post_fw_load_work;
|
||||
struct delayed_work fw_load_work;
|
||||
wait_queue_head_t fw_wait;
|
||||
int fw_load_retry_count;
|
||||
atomic_t fw_state;
|
||||
atomic_t fw_wait_complete;
|
||||
wait_queue_head_t dev_init_wait;
|
||||
atomic_t dev_init_status;
|
||||
int device_used;
|
||||
int irq_enabled[MAX_CHANNELS];
|
||||
struct tas25xx_interrupts intr_data[MAX_CHANNELS];
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_IRQ_BD)
|
||||
struct irq_bigdata irqdata;
|
||||
#endif
|
||||
struct class *class;
|
||||
struct cmd_data cmd_data;
|
||||
struct tas_block_op_data_t block_op_data[MAX_CHANNELS];
|
||||
};
|
||||
|
||||
static inline int is_power_up_state(enum tas_power_states_t state)
|
||||
{
|
||||
if (state == TAS_POWER_ACTIVE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __TAS25XX__ */
|
||||
|
@ -1,716 +0,0 @@
|
||||
/*
|
||||
* =============================================================================
|
||||
* Copyright (c) 2016 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.
|
||||
*
|
||||
* File:
|
||||
* tas25xx-codec.c
|
||||
*
|
||||
* Description:
|
||||
* ALSA SoC driver for Texas Instruments TAS25XX High Performance 4W Smart
|
||||
* Amplifier
|
||||
*
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#define DEBUG 5
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "../inc/tas25xx.h"
|
||||
#include "../inc/tas25xx-ext.h"
|
||||
#include "../inc/tas25xx-device.h"
|
||||
#include "../inc/tas25xx-logic.h"
|
||||
#include "../inc/tas25xx-regmap.h"
|
||||
#include "../inc/tas25xx-regbin-parser.h"
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_ALGO)
|
||||
#include "../algo/inc/tas_smart_amp_v2.h"
|
||||
#include "../algo/inc/tas25xx-calib.h"
|
||||
#endif /*CONFIG_TAS25XX_ALGO*/
|
||||
|
||||
static const char *irq_gpio_label[2] = {
|
||||
"TAS25XX-IRQ", "TAS25XX-IRQ2"
|
||||
};
|
||||
|
||||
static struct tas25xx_priv *s_tas25xx;
|
||||
|
||||
int tas25xx_start_fw_load(struct tas25xx_priv *p_tas25xx, int retry_count);
|
||||
|
||||
static unsigned int tas25xx_codec_read(struct snd_soc_component *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
int ret = -1;
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
switch (reg) {
|
||||
case TAS25XX_SWITCH:
|
||||
dev_dbg(plat_data->dev, "%s: %d, %d TAS25XX_SWITCH",
|
||||
__func__, reg, value);
|
||||
value = p_tas25xx->device_used;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_dbg(plat_data->dev, "%s: %d, %d default read",
|
||||
__func__, reg, value);
|
||||
ret = p_tas25xx->read(p_tas25xx, 0, reg, &value);
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(plat_data->dev, "%s, reg=%d, value=%d", __func__, reg, value);
|
||||
|
||||
if (ret == 0)
|
||||
return value;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int tas25xx_codec_write(struct snd_soc_component *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
int ret = 0;
|
||||
|
||||
switch (reg) {
|
||||
case TAS25XX_SWITCH:
|
||||
dev_dbg(plat_data->dev, "%s: %d, %d TAS25XX_SWITCH",
|
||||
__func__, reg, value);
|
||||
p_tas25xx->device_used = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
dev_dbg(plat_data->dev, "%s: %d, %d UNIMPLEMENTED",
|
||||
__func__, reg, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if IS_ENABLED(CODEC_PM)
|
||||
static int tas25xx_codec_suspend(struct snd_soc_component *codec)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
int ret = -1;
|
||||
|
||||
dev_dbg(plat_data->dev, "%s\n", __func__);
|
||||
|
||||
mutex_lock(&p_tas25xx->codec_lock);
|
||||
ret = plat_data->runtime_suspend(p_tas25xx);
|
||||
mutex_unlock(&p_tas25xx->codec_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_codec_resume(struct snd_soc_component *codec)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&p_tas25xx->codec_lock);
|
||||
|
||||
dev_dbg(plat_data->dev, "%s\n", __func__);
|
||||
ret = plat_data->runtime_resume(p_tas25xx);
|
||||
|
||||
mutex_unlock(&p_tas25xx->codec_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int tas25xx_dac_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
int ret = -1;
|
||||
|
||||
mutex_lock(&p_tas25xx->codec_lock);
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
p_tas25xx->dac_power = 1;
|
||||
dev_info(plat_data->dev, "SND_SOC_DAPM_POST_PMU\n");
|
||||
ret = tas25xx_set_power_state(p_tas25xx, TAS_POWER_ACTIVE, 0xffff);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
p_tas25xx->dac_power = 0;
|
||||
dev_info(plat_data->dev, "SND_SOC_DAPM_PRE_PMD\n");
|
||||
if (p_tas25xx->m_power_state != TAS_POWER_SHUTDOWN)
|
||||
ret = tas25xx_set_power_state(p_tas25xx, TAS_POWER_SHUTDOWN, 0xffff);
|
||||
else
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&p_tas25xx->codec_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new dapm_switch =
|
||||
SOC_DAPM_SINGLE("Switch", TAS25XX_SWITCH, 0, 1, 0);
|
||||
|
||||
static const struct snd_soc_dapm_widget tas25xx_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_SWITCH("TAS25XX ASI", SND_SOC_NOPM, 0, 0, &dapm_switch),
|
||||
SND_SOC_DAPM_AIF_OUT("Voltage Sense", "ASI1 Capture", 1,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("Current Sense", "ASI1 Capture", 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas25xx_dac_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
||||
SND_SOC_DAPM_OUTPUT("OUT"),
|
||||
SND_SOC_DAPM_SIGGEN("VMON"),
|
||||
SND_SOC_DAPM_SIGGEN("IMON")
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route tas25xx_audio_map[] = {
|
||||
{"DAC", NULL, "ASI1"},
|
||||
{"TAS25XX ASI", "Switch", "DAC"},
|
||||
{"OUT", NULL, "TAS25XX ASI"},
|
||||
{"Voltage Sense", NULL, "VMON"},
|
||||
{"Current Sense", NULL, "IMON"},
|
||||
};
|
||||
|
||||
static bool fw_load_required(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
return (atomic_read(&p_tas25xx->fw_state) == TAS25XX_DSP_FW_LOAD_FAIL);
|
||||
}
|
||||
|
||||
static int tas25xx_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int i;
|
||||
struct snd_soc_component *codec = dai->component;
|
||||
struct tas25xx_priv *p_tas25xx
|
||||
= snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
int bitwidth = 16;
|
||||
int ret = -EINVAL;
|
||||
unsigned int channels = params_channels(params);
|
||||
|
||||
if (fw_load_required(p_tas25xx)) {
|
||||
dev_warn(plat_data->dev, "%s, firmware is not loaded, retry", __func__);
|
||||
ret = tas25xx_start_fw_load(p_tas25xx, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(plat_data->dev, "%s fw load failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&p_tas25xx->codec_lock);
|
||||
|
||||
dev_dbg(plat_data->dev, "%s, stream %s format: %d\n", __func__,
|
||||
(substream->stream ==
|
||||
SNDRV_PCM_STREAM_PLAYBACK) ? ("Playback") : ("Capture"),
|
||||
params_format(params));
|
||||
|
||||
if (channels > 2) {
|
||||
/* assume TDM mode */
|
||||
p_tas25xx->mn_fmt_mode = 2;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
bitwidth = 16;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
bitwidth = 24;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
bitwidth = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
ret = tas25xx_set_tdm_rx_slot(p_tas25xx, channels,
|
||||
bitwidth);
|
||||
else /*Assumed Capture*/
|
||||
ret = tas25xx_set_tdm_tx_slot(p_tas25xx, channels,
|
||||
bitwidth);
|
||||
} else {
|
||||
/* assume I2S mode*/
|
||||
p_tas25xx->mn_fmt_mode = 1;
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
bitwidth = 16;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
bitwidth = 24;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
bitwidth = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = tas25xx_set_bitwidth(p_tas25xx,
|
||||
bitwidth, substream->stream);
|
||||
if (ret < 0) {
|
||||
dev_info(plat_data->dev, "set bitwidth failed, %d\n",
|
||||
ret);
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(plat_data->dev, "%s, stream %s sample rate: %d\n", __func__,
|
||||
(substream->stream ==
|
||||
SNDRV_PCM_STREAM_PLAYBACK) ? ("Playback") : ("Capture"),
|
||||
params_rate(params));
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
for (i = 0; i < p_tas25xx->ch_count; i++)
|
||||
ret = tas25xx_set_sample_rate(p_tas25xx, i, params_rate(params));
|
||||
|
||||
ret:
|
||||
mutex_unlock(&p_tas25xx->codec_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_component *codec = dai->component;
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (fw_load_required(p_tas25xx)) {
|
||||
dev_warn(plat_data->dev, "%s, firmware is not loaded, retry", __func__);
|
||||
ret = tas25xx_start_fw_load(p_tas25xx, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(plat_data->dev, "%s fw load failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(plat_data->dev, "%s, format=0x%x\n", __func__, fmt);
|
||||
|
||||
p_tas25xx->mn_fmt = fmt;
|
||||
ret = tas25xx_set_dai_fmt_for_fmt(p_tas25xx, fmt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
||||
unsigned int tx_mask, unsigned int rx_mask,
|
||||
int slots, int slot_width)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct snd_soc_component *codec = dai->component;
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
if (fw_load_required(p_tas25xx)) {
|
||||
dev_warn(plat_data->dev, "%s, firmware is not loaded, retry", __func__);
|
||||
ret = tas25xx_start_fw_load(p_tas25xx, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(plat_data->dev, "%s fw load failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(plat_data->dev, "%s, tx_mask:%d, rx_mask:%d",
|
||||
__func__, tx_mask, rx_mask);
|
||||
dev_dbg(plat_data->dev, "%s, slots:%d,slot_width:%d",
|
||||
__func__, slots, slot_width);
|
||||
|
||||
if (rx_mask) {
|
||||
p_tas25xx->mn_fmt_mode = 2; /*TDM Mode*/
|
||||
ret = tas25xx_set_tdm_rx_slot(p_tas25xx, slots, slot_width);
|
||||
} else if (tx_mask) {
|
||||
p_tas25xx->mn_fmt_mode = 2;
|
||||
ret = tas25xx_set_tdm_tx_slot(p_tas25xx, slots, slot_width);
|
||||
} else {
|
||||
dev_err(plat_data->dev, "%s, Invalid Mask",
|
||||
__func__);
|
||||
p_tas25xx->mn_fmt_mode = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_component *codec = dai->component;
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
if (fw_load_required(p_tas25xx)) {
|
||||
dev_warn(plat_data->dev, "%s, firmware is not loaded, retry", __func__);
|
||||
ret = tas25xx_start_fw_load(p_tas25xx, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(plat_data->dev, "%s fw load failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(plat_data->dev, "%s, stream %s mute %d\n", __func__,
|
||||
(stream == SNDRV_PCM_STREAM_PLAYBACK) ? ("Playback") : ("Capture"),
|
||||
mute);
|
||||
|
||||
if (stream != SNDRV_PCM_STREAM_PLAYBACK)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&p_tas25xx->codec_lock);
|
||||
if (mute)
|
||||
ret = tas25xx_set_power_state(p_tas25xx, TAS_POWER_MUTE,
|
||||
(0xf & tas25xx_get_drv_channel_opmode()));
|
||||
mutex_unlock(&p_tas25xx->codec_lock);
|
||||
|
||||
if (mute) {
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_ALGO)
|
||||
tas25xx_stop_algo_processing();
|
||||
#endif /* CONFIG_TAS25XX_ALGO */
|
||||
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_IRQ_BD)
|
||||
tas25xx_log_interrupt_stats(p_tas25xx);
|
||||
#endif /* CONFIG_TAS25XX_IRQ_BD */
|
||||
} else {
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_ALGO)
|
||||
tas25xx_start_algo_processing(p_tas25xx->curr_mn_iv_width,
|
||||
p_tas25xx->curr_mn_vbat);
|
||||
#endif /* CONFIG_TAS25XX_ALGO */
|
||||
#if IS_ENABLED(CONFIG_TAS25XX_IRQ_BD)
|
||||
tas25xx_clear_interrupt_stats(p_tas25xx);
|
||||
#endif /* CONFIG_TAS25XX_IRQ_BD */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops tas25xx_dai_ops = {
|
||||
.hw_params = tas25xx_hw_params,
|
||||
.set_fmt = tas25xx_set_dai_fmt,
|
||||
.set_tdm_slot = tas25xx_set_dai_tdm_slot,
|
||||
.mute_stream = tas25xx_mute_stream,
|
||||
};
|
||||
|
||||
#define TAS25XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
|
||||
SNDRV_PCM_FMTBIT_S20_3LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE |\
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static struct snd_soc_dai_driver tas25xx_dai_driver[] = {
|
||||
{
|
||||
.name = "tas25xx ASI1",
|
||||
.id = 0,
|
||||
.playback = {
|
||||
.stream_name = "ASI1 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = TAS25XX_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "ASI1 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = TAS25XX_FORMATS,
|
||||
},
|
||||
.ops = &tas25xx_dai_ops,
|
||||
.symmetric_rate = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static irqreturn_t tas25xx_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx = (struct tas25xx_priv *)dev_id;
|
||||
|
||||
if (p_tas25xx != s_tas25xx)
|
||||
return IRQ_NONE;
|
||||
|
||||
schedule_delayed_work(&p_tas25xx->irq_work,
|
||||
msecs_to_jiffies(p_tas25xx->intr_data[0].processing_delay));
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tas25xx_setup_irq(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
if (!plat_data)
|
||||
return ret;
|
||||
|
||||
/* register for interrupts */
|
||||
for (i = 0; i < p_tas25xx->ch_count; i++) {
|
||||
if (gpio_is_valid(p_tas25xx->devs[i]->irq_gpio)) {
|
||||
ret = gpio_request(p_tas25xx->devs[i]->irq_gpio,
|
||||
irq_gpio_label[i]);
|
||||
if (ret) {
|
||||
dev_err(plat_data->dev,
|
||||
"%s:%u: ch 0x%02x: GPIO %d request error\n",
|
||||
__func__, __LINE__,
|
||||
p_tas25xx->devs[i]->mn_addr,
|
||||
p_tas25xx->devs[i]->irq_gpio);
|
||||
continue;
|
||||
}
|
||||
gpio_direction_input(p_tas25xx->devs[i]->irq_gpio);
|
||||
|
||||
p_tas25xx->devs[i]->irq_no =
|
||||
gpio_to_irq(p_tas25xx->devs[i]->irq_gpio);
|
||||
dev_info(plat_data->dev, "irq = %d\n",
|
||||
p_tas25xx->devs[i]->irq_no);
|
||||
|
||||
ret = devm_request_threaded_irq(plat_data->dev,
|
||||
p_tas25xx->devs[i]->irq_no, tas25xx_irq_handler, NULL,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED,
|
||||
"tas25xx", p_tas25xx);
|
||||
if (ret) {
|
||||
dev_err(plat_data->dev, "request_irq failed, error=%d\n", ret);
|
||||
} else {
|
||||
p_tas25xx->irq_enabled[i] = 1;
|
||||
dev_info(plat_data->dev, "Interrupt registration successful!!!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_dev_with_fw_data(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
int ret, i;
|
||||
struct linux_platform *plat_data = NULL;
|
||||
|
||||
plat_data = (struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
/* software reset and initial writes */
|
||||
for (i = 0; i < p_tas25xx->ch_count; i++) {
|
||||
ret = tas25xx_software_reset(p_tas25xx, i);
|
||||
if (ret < 0) {
|
||||
dev_err(plat_data->dev, "I2c fail, %d\n", ret);
|
||||
goto post_fw_load_work_done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = tas_write_init_config_params(p_tas25xx, p_tas25xx->ch_count);
|
||||
if (ret) {
|
||||
dev_err(plat_data->dev, "Failed to initialize, error=%d", ret);
|
||||
goto post_fw_load_work_done;
|
||||
}
|
||||
|
||||
ret = tas25xx_probe(p_tas25xx);
|
||||
if (ret) {
|
||||
dev_err(plat_data->dev, "Failed to initialize, error=%d", ret);
|
||||
goto post_fw_load_work_done;
|
||||
}
|
||||
|
||||
ret = tas25xx_setup_irq(p_tas25xx);
|
||||
if (ret) {
|
||||
dev_err(plat_data->dev, "failed to initialize irq=%d", ret);
|
||||
}
|
||||
|
||||
post_fw_load_work_done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fw_load_work_routine(struct work_struct *work)
|
||||
{
|
||||
int ret;
|
||||
struct linux_platform *plat_data = NULL;
|
||||
struct tas25xx_priv *p_tas25xx =
|
||||
container_of(work, struct tas25xx_priv, fw_load_work.work);
|
||||
|
||||
plat_data = (struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
ret = tas25xx_load_firmware(p_tas25xx, p_tas25xx->fw_load_retry_count);
|
||||
dev_info(plat_data->dev, "%s FW loading %s", __func__,
|
||||
!ret ? "success" : "fail");
|
||||
|
||||
if (!ret) {
|
||||
ret = init_dev_with_fw_data(p_tas25xx);
|
||||
if (ret)
|
||||
dev_err(plat_data->dev,
|
||||
"%s fw dnld to device error=%d", __func__, ret);
|
||||
else
|
||||
atomic_set(&p_tas25xx->dev_init_status, 1);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
atomic_set(&p_tas25xx->dev_init_status, ret);
|
||||
|
||||
wake_up(&p_tas25xx->dev_init_wait);
|
||||
}
|
||||
|
||||
int tas25xx_start_fw_load(struct tas25xx_priv *p_tas25xx, int retry_count)
|
||||
{
|
||||
int i, ret, i2c_err, ch_count;
|
||||
struct linux_platform *plat_data = NULL;
|
||||
|
||||
atomic_set(&p_tas25xx->dev_init_status, 0);
|
||||
atomic_set(&p_tas25xx->fw_state, TAS25XX_DSP_FW_TRYLOAD);
|
||||
p_tas25xx->fw_load_retry_count = retry_count;
|
||||
plat_data = (struct linux_platform *) p_tas25xx->platform_data;
|
||||
ch_count = p_tas25xx->ch_count;
|
||||
|
||||
tas25xx_check_last_i2c_error_n_reset();
|
||||
INIT_DELAYED_WORK(&p_tas25xx->fw_load_work, fw_load_work_routine);
|
||||
schedule_delayed_work(&p_tas25xx->fw_load_work, msecs_to_jiffies(0));
|
||||
|
||||
wait_event_interruptible(p_tas25xx->dev_init_wait,
|
||||
atomic_read(&p_tas25xx->dev_init_status) != 0);
|
||||
|
||||
/* set -ve errno or success 1*/
|
||||
ret = atomic_read(&p_tas25xx->dev_init_status);
|
||||
if (ret == 1) {
|
||||
for (i = 0; i < ch_count; i++)
|
||||
p_tas25xx->ti_amp_state[i] = TAS_AMP_STATE_FW_LOAD_SUCCESS;
|
||||
} else {
|
||||
i2c_err = tas25xx_check_last_i2c_error_n_reset();
|
||||
for (i = 0; i < ch_count; i++)
|
||||
if (i2c_err)
|
||||
p_tas25xx->ti_amp_state[i] = TAS_AMP_ERR_I2C;
|
||||
else
|
||||
p_tas25xx->ti_amp_state[i] = TAS_AMP_ERR_FW_LOAD;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_codec_probe(struct snd_soc_component *codec)
|
||||
{
|
||||
int ret = -1, i = 0;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
char *w_name[4] = {NULL};
|
||||
const char *prefix = codec->name_prefix;
|
||||
int w_count = 0;
|
||||
|
||||
if (plat_data)
|
||||
plat_data->codec = codec;
|
||||
|
||||
s_tas25xx = p_tas25xx;
|
||||
|
||||
/*Moved from machine driver to codec*/
|
||||
if (prefix) {
|
||||
w_name[0] = kasprintf(GFP_KERNEL, "%s %s",
|
||||
prefix, "ASI1 Playback");
|
||||
w_name[1] = kasprintf(GFP_KERNEL, "%s %s",
|
||||
prefix, "ASI1 Capture");
|
||||
w_name[2] = kasprintf(GFP_KERNEL, "%s %s",
|
||||
prefix, "OUT");
|
||||
w_count = 3;
|
||||
} else {
|
||||
w_name[0] = kasprintf(GFP_KERNEL, "%s", "ASI1 Playback");
|
||||
w_name[1] = kasprintf(GFP_KERNEL, "%s", "ASI1 Capture");
|
||||
w_name[2] = kasprintf(GFP_KERNEL, "%s", "OUT");
|
||||
w_count = 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < w_count; i++) {
|
||||
snd_soc_dapm_ignore_suspend(dapm, w_name[i]);
|
||||
kfree(w_name[i]);
|
||||
}
|
||||
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
ret = tas25xx_start_fw_load(p_tas25xx, 800);
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
|
||||
dev_info(plat_data->dev, "%s returning ret=%d\n",
|
||||
__func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tas25xx_codec_remove(struct snd_soc_component *codec)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
tas25xx_remove(p_tas25xx);
|
||||
s_tas25xx = NULL;
|
||||
}
|
||||
|
||||
static struct snd_soc_component_driver soc_codec_driver_tas25xx = {
|
||||
.probe = tas25xx_codec_probe,
|
||||
.remove = tas25xx_codec_remove,
|
||||
.read = tas25xx_codec_read,
|
||||
.write = tas25xx_codec_write,
|
||||
#if IS_ENABLED(CODEC_PM)
|
||||
.suspend = tas25xx_codec_suspend,
|
||||
.resume = tas25xx_codec_resume,
|
||||
#endif
|
||||
.dapm_widgets = tas25xx_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(tas25xx_dapm_widgets),
|
||||
.dapm_routes = tas25xx_audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(tas25xx_audio_map),
|
||||
};
|
||||
|
||||
|
||||
int tas25xx_register_codec(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
int ret = -1;
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
dev_info(plat_data->dev, "%s, enter\n", __func__);
|
||||
|
||||
ret = devm_snd_soc_register_component(plat_data->dev,
|
||||
&soc_codec_driver_tas25xx,
|
||||
tas25xx_dai_driver, ARRAY_SIZE(tas25xx_dai_driver));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tas25xx_deregister_codec(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
snd_soc_unregister_component(plat_data->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Texas Instruments Inc.");
|
||||
MODULE_DESCRIPTION("TAS25XX ALSA SOC Smart Amplifier driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,497 +0,0 @@
|
||||
/*
|
||||
* =============================================================================
|
||||
* Copyright (c) 2016 Texas Instruments Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
* File:
|
||||
* tas25xx-misc.c
|
||||
*
|
||||
* Description:
|
||||
* misc driver for Texas Instruments
|
||||
* TAS25XX High Performance 4W Smart Amplifier
|
||||
*
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "../inc/tas25xx.h"
|
||||
#include "../inc/tas25xx-misc.h"
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#define FMT "%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n"
|
||||
#define MAX_FMT_COUNT 512
|
||||
|
||||
enum tas_devop_t {
|
||||
OP_REG_READ = 0,
|
||||
OP_PAGE_READ = 1,
|
||||
OP_SNG_WRITE = 2,
|
||||
OP_BURST_WRITE = 3,
|
||||
};
|
||||
|
||||
struct tas_audio_dev {
|
||||
uint8_t channel;
|
||||
uint8_t book;
|
||||
uint8_t page;
|
||||
uint8_t reg;
|
||||
uint8_t read_pending;
|
||||
enum tas_devop_t op;
|
||||
};
|
||||
|
||||
|
||||
static struct tas_audio_dev s_tasdevop;
|
||||
static uint32_t s_r[128];
|
||||
static struct tas25xx_priv *g_tas25xx;
|
||||
|
||||
static int32_t tas25xx_file_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx = g_tas25xx;
|
||||
|
||||
file->private_data = (void *)p_tas25xx;
|
||||
|
||||
pr_info("TAS25XX %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tas25xx_file_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
pr_info("TAS25XX %s\n", __func__);
|
||||
|
||||
file->private_data = (void *)NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tas25xx_file_read(struct file *file,
|
||||
char *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx =
|
||||
(struct tas25xx_priv *)file->private_data;
|
||||
int32_t ret = 0, i, count_l;
|
||||
uint8_t *p_kbuf = NULL;
|
||||
uint32_t reg = 0;
|
||||
uint32_t len = 0;
|
||||
uint32_t value = 0;
|
||||
uint32_t channel = 0;
|
||||
|
||||
mutex_lock(&p_tas25xx->file_lock);
|
||||
|
||||
pr_info("%s size=%zu", __func__, count);
|
||||
|
||||
if (count > 8) {
|
||||
uint8_t *ref_ptr;
|
||||
if (!s_tasdevop.read_pending) {
|
||||
count = 0;
|
||||
goto done_read;
|
||||
}
|
||||
|
||||
p_kbuf = kzalloc(MAX_FMT_COUNT, GFP_KERNEL);
|
||||
if (p_kbuf == NULL)
|
||||
goto done_read;
|
||||
|
||||
ref_ptr = p_kbuf;
|
||||
|
||||
channel = s_tasdevop.channel;
|
||||
pr_info("%s ch=%d B:P %02x:%02x\n",
|
||||
__func__, channel, s_tasdevop.book, s_tasdevop.page);
|
||||
|
||||
switch (s_tasdevop.op) {
|
||||
case OP_REG_READ:
|
||||
reg = TAS25XX_REG(s_tasdevop.book, s_tasdevop.page, s_tasdevop.reg);
|
||||
ret = p_tas25xx->read(p_tas25xx, channel,
|
||||
reg, &value);
|
||||
if (ret < 0)
|
||||
count = snprintf(ref_ptr, 64, "%s\n", "Error");
|
||||
else
|
||||
count = snprintf(ref_ptr, 64, "%02x\n", value);
|
||||
|
||||
ret = copy_to_user(buf, ref_ptr, count);
|
||||
if (ret) {
|
||||
pr_err("TAS25XX:%d reg read, copy to user buf ret= %d", __LINE__, ret);
|
||||
count = ret;
|
||||
} else {
|
||||
pr_info("TAS25XX: %s ch=%d B:P:R %02x:%02x:%02x(%d) value=%d\n",
|
||||
__func__, channel, s_tasdevop.book, s_tasdevop.page,
|
||||
s_tasdevop.reg, reg, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_PAGE_READ:
|
||||
reg = TAS25XX_REG(s_tasdevop.book, s_tasdevop.page, 0);
|
||||
for (i = 0; i < 128; i++) {
|
||||
ret = p_tas25xx->read(p_tas25xx, channel,
|
||||
reg + i, &s_r[i]);
|
||||
if (ret) {
|
||||
memset(s_r, 0, sizeof(s_r));
|
||||
break;
|
||||
}
|
||||
}
|
||||
p_tas25xx->read(p_tas25xx, channel, reg, &s_r[0]);
|
||||
|
||||
if (ret) {
|
||||
count = snprintf(ref_ptr, 64, "error=%d\n", ret);
|
||||
} else {
|
||||
count_l = 0;
|
||||
if (count < ((52*8)+1)) {
|
||||
count = snprintf(ref_ptr, 64,
|
||||
"page dump not possible\n");
|
||||
} else {
|
||||
for (i = 0; i < 8; i++) {
|
||||
count_l += snprintf(ref_ptr, 64, FMT, i, s_r[(i*16) + 0],
|
||||
s_r[(i*16) + 1], s_r[(i*16) + 2], s_r[(i*16) + 3], s_r[(i*16) + 4],
|
||||
s_r[(i*16) + 5], s_r[(i*16) + 6], s_r[(i*16) + 7], s_r[(i*16) + 8],
|
||||
s_r[(i*16) + 9], s_r[(i*16) + 10], s_r[(i*16) + 11], s_r[(i*16) + 12],
|
||||
s_r[(i*16) + 13], s_r[(i*16) + 14], s_r[(i*16) + 15]);
|
||||
ref_ptr += 52;
|
||||
}
|
||||
count = count_l;
|
||||
}
|
||||
}
|
||||
|
||||
ret = copy_to_user(buf, p_kbuf, count);
|
||||
if (ret) {
|
||||
pr_err("TAS25XX:%s page read, copy buffer failed.\n", __func__);
|
||||
count = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
count = snprintf(p_kbuf, 64, "%s\n", "invalid op");
|
||||
ret = copy_to_user(buf, p_kbuf, count);
|
||||
if (ret) {
|
||||
pr_err("TAS25XX:%s invalid op, copy buffer failed.\n", __func__);
|
||||
count = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
s_tasdevop.read_pending = 0;
|
||||
goto done_read;
|
||||
} else if (count == 7) {
|
||||
|
||||
p_kbuf = kzalloc(count, GFP_KERNEL);
|
||||
if (p_kbuf == NULL)
|
||||
goto done_read;
|
||||
|
||||
ret = copy_from_user(p_kbuf, buf, count);
|
||||
if (ret != 0) {
|
||||
pr_err("TAS25XX copy_from_user failed.\n");
|
||||
count = ret;
|
||||
goto done_read;
|
||||
}
|
||||
|
||||
if (p_kbuf[1] >= p_tas25xx->ch_count)
|
||||
goto done_read;
|
||||
|
||||
channel = p_kbuf[1];
|
||||
|
||||
switch (p_kbuf[0]) {
|
||||
case TIAUDIO_CMD_REG_READ:
|
||||
{
|
||||
reg = ((uint32_t)p_kbuf[2] << 24) +
|
||||
((uint32_t)p_kbuf[3] << 16) +
|
||||
((uint32_t)p_kbuf[4] << 8) +
|
||||
(uint32_t)p_kbuf[5];
|
||||
|
||||
pr_info("TAS25XX TIAUDIO_CMD_REG_READ: current_reg = 0x%x, count=%d\n",
|
||||
reg, (int)count-6);
|
||||
len = count-6;
|
||||
if (len == 1) {
|
||||
value = 0;
|
||||
|
||||
ret = p_tas25xx->read(p_tas25xx, channel,
|
||||
reg, &value);
|
||||
if (ret < 0) {
|
||||
pr_err("TAS25XX dev read fail %d\n", ret);
|
||||
break;
|
||||
}
|
||||
p_kbuf[6] = value;
|
||||
ret = copy_to_user(buf, p_kbuf, count);
|
||||
if (ret) {
|
||||
count = ret;
|
||||
pr_err("TAS25XX TIAUDIO_CMD_REG_READ copy to user %d\n", ret);
|
||||
}
|
||||
} else if (len > 1) {
|
||||
ret = p_tas25xx->bulk_read(p_tas25xx, channel,
|
||||
reg, (uint8_t *)&p_kbuf[6], len);
|
||||
if (ret < 0) {
|
||||
pr_err("TAS25XX dev bulk read fail %d\n", ret);
|
||||
} else {
|
||||
ret = copy_to_user(buf, p_kbuf, count);
|
||||
if (ret) {
|
||||
count = ret;
|
||||
pr_err("TAS25XX TIAUDIO_CMD_REG_READ copy to user fail %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
pr_err("TAS25XX:%d invalid size %zu", __LINE__, count);
|
||||
goto done_read;
|
||||
}
|
||||
|
||||
done_read:
|
||||
kfree(p_kbuf);
|
||||
mutex_unlock(&p_tas25xx->file_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static int32_t handle_read_write(struct tas25xx_priv *p_tas25xx,
|
||||
int32_t read_write_op, int32_t count, uint8_t *buf)
|
||||
{
|
||||
static uint8_t ch_bpr[8] = {0};
|
||||
int32_t val, buf_sz, i;
|
||||
int32_t ret = 0;
|
||||
int32_t reg;
|
||||
int8_t l_buf[3];
|
||||
|
||||
buf_sz = count - 2;
|
||||
buf += 2;
|
||||
|
||||
i = 0;
|
||||
l_buf[2] = 0;
|
||||
while (buf_sz >= 2) {
|
||||
memcpy(l_buf, buf, 2);
|
||||
ret = kstrtoint(l_buf, 16, &val);
|
||||
if (ret) {
|
||||
pr_err("TAS25XX:%d Parsing err for %s, err=%d", __LINE__, l_buf, ret);
|
||||
break;
|
||||
}
|
||||
if (i <= 7) {
|
||||
pr_info("tas25xx: %s i=%d, val=%d\n", __func__, i, val);
|
||||
ch_bpr[i] = (uint8_t)val;
|
||||
} else {
|
||||
pr_info("tas25xx: write supported only for 4 bytes,ignoring additional bytes\n");
|
||||
break;
|
||||
}
|
||||
buf += 3;
|
||||
buf_sz -= 3;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto read_write_done;
|
||||
|
||||
pr_info("tas25xx: ch=%d, BPR %02x:%02x:%02x v=%d %d %d %d(cnt=%d)\n",
|
||||
ch_bpr[0], ch_bpr[1], ch_bpr[2], ch_bpr[3],
|
||||
ch_bpr[4], ch_bpr[5], ch_bpr[6], ch_bpr[7], i);
|
||||
|
||||
if (ch_bpr[0] >= p_tas25xx->ch_count) {
|
||||
ret = -EINVAL;
|
||||
goto read_write_done;
|
||||
}
|
||||
|
||||
s_tasdevop.channel = ch_bpr[0];
|
||||
s_tasdevop.book = ch_bpr[1];
|
||||
s_tasdevop.page = ch_bpr[2];
|
||||
s_tasdevop.reg = ch_bpr[3];
|
||||
if (read_write_op == 1)
|
||||
s_tasdevop.read_pending = 1;
|
||||
else
|
||||
s_tasdevop.read_pending = 0;
|
||||
|
||||
if (read_write_op == 1) {
|
||||
if (i == 3) {
|
||||
pr_info("tas25xx: page read\n");
|
||||
s_tasdevop.op = OP_PAGE_READ;
|
||||
} else if (i == 4) {
|
||||
pr_info("tas25xx: single read\n");
|
||||
s_tasdevop.op = OP_REG_READ;
|
||||
} else {
|
||||
pr_info("tas25xx: page/single read is supported\n");
|
||||
s_tasdevop.read_pending = 0;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else if (read_write_op == 2) {
|
||||
if (i == 5) {
|
||||
pr_info("tas25xx: single write\n");
|
||||
s_tasdevop.op = OP_SNG_WRITE;
|
||||
} else if (i == 8) {
|
||||
pr_info("tas25xx: burst write\n");
|
||||
s_tasdevop.op = OP_BURST_WRITE;
|
||||
} else {
|
||||
pr_info("tas25xx: signle/burst write is supported\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
pr_info("tas25xx: Only read and write is supported\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (read_write_op == 2) {
|
||||
val = ch_bpr[4];
|
||||
reg = TAS25XX_REG(s_tasdevop.book, s_tasdevop.page, s_tasdevop.reg);
|
||||
if (s_tasdevop.op == OP_SNG_WRITE) {
|
||||
ret = p_tas25xx->write(p_tas25xx,
|
||||
s_tasdevop.channel, reg, val);
|
||||
} else if (s_tasdevop.op == OP_BURST_WRITE) {
|
||||
ret = p_tas25xx->bulk_write(p_tas25xx,
|
||||
s_tasdevop.channel, reg, &ch_bpr[4], 4);
|
||||
}
|
||||
}
|
||||
|
||||
read_write_done:
|
||||
if (ret < 0)
|
||||
count = ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t tas25xx_file_write(struct file *file,
|
||||
const char *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct tas25xx_priv *p_tas25xx =
|
||||
(struct tas25xx_priv *)file->private_data;
|
||||
int32_t ret = 0;
|
||||
uint8_t *p_kbuf = NULL;
|
||||
uint32_t reg = 0;
|
||||
uint32_t len = 0;
|
||||
uint32_t channel = 0;
|
||||
int32_t read_write_op;
|
||||
|
||||
mutex_lock(&p_tas25xx->file_lock);
|
||||
|
||||
pr_info("%s size=%zu", __func__, count);
|
||||
|
||||
if (count < 7) {
|
||||
pr_err("TAS25XX invalid size %zu\n", count);
|
||||
ret = -EINVAL;
|
||||
goto done_write;
|
||||
}
|
||||
|
||||
p_kbuf = kzalloc(count, GFP_KERNEL);
|
||||
if (p_kbuf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto done_write;
|
||||
}
|
||||
|
||||
ret = copy_from_user(p_kbuf, buf, count);
|
||||
if (ret != 0) {
|
||||
count = ret;
|
||||
pr_err("TAS25XX copy_from_user failed.\n");
|
||||
goto done_write;
|
||||
}
|
||||
|
||||
if ((p_kbuf[0] == 'w' || p_kbuf[0] == 'W') && p_kbuf[1] == ' ')
|
||||
read_write_op = 2;
|
||||
else if ((p_kbuf[0] == 'r' || p_kbuf[0] == 'R') && p_kbuf[1] == ' ')
|
||||
read_write_op = 1;
|
||||
else
|
||||
read_write_op = 0;
|
||||
|
||||
if (read_write_op) {
|
||||
count = handle_read_write(p_tas25xx, read_write_op, count, p_kbuf);
|
||||
goto done_write;
|
||||
}
|
||||
|
||||
if (p_kbuf[1] >= p_tas25xx->ch_count) {
|
||||
pr_err("TAS25XX: channel count exceeds actual chanel count\n");
|
||||
goto done_write;
|
||||
}
|
||||
channel = p_kbuf[1];
|
||||
|
||||
switch (p_kbuf[0]) {
|
||||
case TIAUDIO_CMD_REG_WITE:
|
||||
if (count > 5) {
|
||||
reg = ((uint32_t)p_kbuf[2] << 24) +
|
||||
((uint32_t)p_kbuf[3] << 16) +
|
||||
((uint32_t)p_kbuf[4] << 8) +
|
||||
(uint32_t)p_kbuf[5];
|
||||
len = count - 6;
|
||||
pr_info("TAS25XX TIAUDIO_CMD_REG_WITE, Reg=0x%x, Val=0x%x\n",
|
||||
reg, p_kbuf[6]);
|
||||
if (len == 1) {
|
||||
uint32_t value = 0;
|
||||
|
||||
value = p_kbuf[6];
|
||||
ret = p_tas25xx->write(p_tas25xx, channel, reg,
|
||||
value);
|
||||
} else if (len > 1) {
|
||||
ret = p_tas25xx->bulk_write(p_tas25xx, channel,
|
||||
reg, &p_kbuf[6], len);
|
||||
}
|
||||
} else {
|
||||
pr_err("TAS25XX %s, write len fail, count=%d.\n",
|
||||
__func__, (int)count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
done_write:
|
||||
kfree(p_kbuf);
|
||||
mutex_unlock(&p_tas25xx->file_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = tas25xx_file_read,
|
||||
.write = tas25xx_file_write,
|
||||
.unlocked_ioctl = NULL,
|
||||
.open = tas25xx_file_open,
|
||||
.release = tas25xx_file_release,
|
||||
};
|
||||
|
||||
#define MODULE_NAME "tas_audio_dev"
|
||||
static struct miscdevice tas25xx_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = MODULE_NAME,
|
||||
.fops = &fops,
|
||||
};
|
||||
|
||||
int32_t tas25xx_register_misc(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
g_tas25xx = p_tas25xx;
|
||||
ret = misc_register(&tas25xx_misc);
|
||||
if (ret)
|
||||
pr_err("TI-SmartPA TAS25XX misc fail: %d\n", ret);
|
||||
|
||||
pr_info("TI-SmartPA %s, leave\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tas25xx_register_misc);
|
||||
|
||||
int32_t tas25xx_deregister_misc(struct tas25xx_priv *p_tas25xx)
|
||||
{
|
||||
misc_deregister(&tas25xx_misc);
|
||||
g_tas25xx = NULL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tas25xx_deregister_misc);
|
||||
|
||||
/*
|
||||
* MODULE_AUTHOR("Texas Instruments Inc.");
|
||||
* MODULE_DESCRIPTION("TAS25XX Misc Smart Amplifier driver");
|
||||
* MODULE_LICENSE("GPL v2");
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,212 +0,0 @@
|
||||
/*
|
||||
* ALSA SoC Texas Instruments TAS25XX High Performance 4W Smart Amplifier
|
||||
*
|
||||
* Copyright (C) 2022 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Niranjan H Y, Vijeth P O
|
||||
*
|
||||
* This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
#include "../inc/tas25xx.h"
|
||||
#include "../inc/tas25xx-device.h"
|
||||
#include "../inc/tas25xx-regbin-parser.h"
|
||||
#include "../inc/tas25xx-regmap.h"
|
||||
|
||||
#define TAS25XX_MDELAY 0xFFFFFFFE
|
||||
#define TAS25XX_MSLEEP 0xFFFFFFFD
|
||||
#define TAS25XX_IVSENSER_ENABLE 1
|
||||
#define TAS25XX_IVSENSER_DISABLE 0
|
||||
|
||||
#define STR_RXBITS_SZ 5
|
||||
#define STR_16BIT "16BIT"
|
||||
#define STR_24BIT "24BIT"
|
||||
#define STR_32BIT "32BIT"
|
||||
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX ((u64)(~((u64)0)))
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX ((u32)(~((u32)0)))
|
||||
#endif
|
||||
|
||||
int tas25xx_rx_set_bitwidth(struct tas25xx_priv *p_tas25xx,
|
||||
int bitwidth, int ch)
|
||||
{
|
||||
int ret;
|
||||
int32_t i;
|
||||
uint32_t size, blk_count, sublk_sz;
|
||||
uint8_t *rx_data = p_tas25xx->block_op_data[ch].rx_fmt_data;
|
||||
uint8_t *fmt;
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
|
||||
ret = 0;
|
||||
size = *((uint32_t *)rx_data);
|
||||
rx_data += sizeof(uint32_t);
|
||||
blk_count = *((uint32_t *)rx_data);
|
||||
rx_data += sizeof(uint32_t);
|
||||
|
||||
switch (bitwidth) {
|
||||
case 16:
|
||||
fmt = STR_16BIT;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
fmt = STR_24BIT;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
fmt = STR_32BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
fmt = NULL;
|
||||
dev_info(plat_data->dev,
|
||||
"Not supported params bitwidth %d",
|
||||
bitwidth);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fmt)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < blk_count; i++) {
|
||||
if (memcmp(fmt, rx_data, STR_RXBITS_SZ) == 0) {
|
||||
rx_data += STR_RXBITS_SZ;
|
||||
break;
|
||||
} else {
|
||||
rx_data += STR_RXBITS_SZ;
|
||||
sublk_sz = *((uint32_t *)rx_data);
|
||||
rx_data += sizeof(uint32_t);
|
||||
rx_data += sublk_sz;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < blk_count)
|
||||
ret = tas25xx_process_block(p_tas25xx, rx_data, ch);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret == 0)
|
||||
p_tas25xx->mn_rx_width = bitwidth;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tas_dev_interrupt_clear(struct tas25xx_priv *p_tas25xx, int chn)
|
||||
{
|
||||
if (p_tas25xx->intr_data[chn].buf_intr_clear)
|
||||
return tas25xx_process_block(p_tas25xx,
|
||||
p_tas25xx->intr_data[chn].buf_intr_clear, chn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tas_dev_interrupt_enable(struct tas25xx_priv *p_tas25xx, int chn)
|
||||
{
|
||||
p_tas25xx->devs[chn]->irq_count = 0;
|
||||
|
||||
if (p_tas25xx->intr_data[chn].buf_intr_enable)
|
||||
return tas25xx_process_block(p_tas25xx,
|
||||
p_tas25xx->intr_data[chn].buf_intr_enable, chn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tas_dev_interrupt_disable(struct tas25xx_priv *p_tas25xx, int chn)
|
||||
{
|
||||
if (p_tas25xx->intr_data[chn].buf_intr_disable)
|
||||
return tas25xx_process_block(p_tas25xx,
|
||||
p_tas25xx->intr_data[chn].buf_intr_disable, chn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tas_dev_interrupt_read(struct tas25xx_priv *p_tas25xx, int chn, int *type)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
int32_t i;
|
||||
int32_t reg = -1;
|
||||
int32_t intr_detected = 0;
|
||||
uint32_t value = 0;
|
||||
int32_t powered_up = 0;
|
||||
|
||||
struct tas25xx_intr_info *intr_info;
|
||||
struct linux_platform *plat_data =
|
||||
(struct linux_platform *) p_tas25xx->platform_data;
|
||||
struct tas25xx_interrupts *intr_data = &p_tas25xx->intr_data[chn];
|
||||
|
||||
powered_up = is_power_up_state(p_tas25xx->m_power_state);
|
||||
|
||||
for (i = 0; i < intr_data->count; i++) {
|
||||
intr_info = &intr_data->intr_info[i];
|
||||
if (!powered_up && intr_info->is_clock_based) {
|
||||
/* ignore clock based interrupt during power off state */
|
||||
dev_dbg(plat_data->dev,
|
||||
"INTR: not checking for %s, reason: not active state",
|
||||
intr_info->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((reg != intr_info->reg) || ret) {
|
||||
reg = intr_info->reg;
|
||||
ret = p_tas25xx->read(p_tas25xx, chn, reg, &value);
|
||||
if (!ret)
|
||||
dev_err(plat_data->dev,
|
||||
"INTR: ch=%d reg=0x%2x(%d), value=0x%2x(%d)",
|
||||
chn, reg, reg, value, value);
|
||||
} else {
|
||||
dev_dbg(plat_data->dev, "INTR: skipping reading reg = %d",
|
||||
intr_info->reg);
|
||||
}
|
||||
if (ret) {
|
||||
dev_err(plat_data->dev,
|
||||
"INTR: Error reading the interrupt reg=%d, err=%d", reg, ret);
|
||||
} else {
|
||||
if (value & intr_info->mask) {
|
||||
if (powered_up && intr_info->is_clock_based)
|
||||
*type |= INTERRUPT_TYPE_CLOCK_BASED;
|
||||
else
|
||||
*type |= INTERRUPT_TYPE_NON_CLOCK_BASED;
|
||||
dev_err(plat_data->dev, "INTR: Detected, ch=%d, intr=%s",
|
||||
chn, intr_info->name);
|
||||
intr_info->detected = 1;
|
||||
if (intr_info->count < UINT32_MAX)
|
||||
intr_info->count++;
|
||||
if (intr_info->count_persist < UINT64_MAX)
|
||||
intr_info->count_persist++;
|
||||
intr_detected |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return intr_detected;
|
||||
}
|
||||
|
||||
int tas25xx_set_power_mute(struct tas25xx_priv *p_tas25xx, int ch)
|
||||
{
|
||||
return tas25xx_process_block(p_tas25xx,
|
||||
p_tas25xx->block_op_data[ch].mute, ch);
|
||||
}
|
||||
|
||||
int tas25xx_software_reset(struct tas25xx_priv *p_tas25xx, int ch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tas25xx_process_block(p_tas25xx,
|
||||
p_tas25xx->block_op_data[ch].sw_reset, ch);
|
||||
|
||||
p_tas25xx->devs[ch]->mn_current_book = -1;
|
||||
|
||||
usleep_range(10000, 10100);
|
||||
|
||||
return ret;
|
||||
}
|
@ -403,11 +403,6 @@ int msm_common_snd_hw_params(struct snd_pcm_substream *substream,
|
||||
struct msm_common_pdata *pdata = msm_common_get_pdata(card);
|
||||
int index = get_mi2s_tdm_auxpcm_intf_index(stream_name);
|
||||
struct clk_cfg intf_clk_cfg;
|
||||
#ifdef CONFIG_COMMON_AMP_CIRRUS
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
unsigned int num_codecs = rtd->dai_link->num_codecs;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
dev_dbg(rtd->card->dev,
|
||||
"%s: substream = %s stream = %d\n",
|
||||
@ -452,28 +447,6 @@ int msm_common_snd_hw_params(struct snd_pcm_substream *substream,
|
||||
__func__, ret);
|
||||
goto done;
|
||||
}
|
||||
#ifdef CONFIG_COMMON_AMP_CIRRUS
|
||||
for (i = 0; i < num_codecs; i++) {
|
||||
codec_dai = asoc_rtd_to_codec(rtd, i);
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0,
|
||||
intf_clk_cfg.clk_freq_in_hz, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0)
|
||||
pr_err("%s: failed to set codec tdm clk, err:%d\n",
|
||||
__func__, ret);
|
||||
|
||||
ret = snd_soc_component_set_sysclk(codec_dai->component,
|
||||
CLK_SRC_SCLK, 0, intf_clk_cfg.clk_freq_in_hz, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0)
|
||||
pr_err("%s: failed to set component sys clk, err:%d\n",
|
||||
__func__, ret);
|
||||
|
||||
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0, 0, 32);
|
||||
if (ret < 0)
|
||||
pr_err("%s: failed to set tdm slot, err:%d\n",
|
||||
__func__, ret);
|
||||
|
||||
}
|
||||
#endif
|
||||
} else if ((strnstr(stream_name, "MI2S", strlen(stream_name)))) {
|
||||
|
||||
ret = get_mi2s_clk_id(index);
|
||||
|
@ -9,25 +9,6 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#ifdef CONFIG_COMMON_AMP_CIRRUS
|
||||
#define CLK_SRC_SCLK 0
|
||||
#define CLK_SRC_LRCLK 1
|
||||
#define CLK_SRC_PDM 2
|
||||
#define CLK_SRC_SELF 3
|
||||
#define CLK_SRC_MCLK 4
|
||||
#define CLK_SRC_SWIRE 5
|
||||
#define CLK_SRC_DAI 0
|
||||
#define CLK_SRC_CODEC 1
|
||||
|
||||
#define CS35L43_MONO 0x31
|
||||
#define CS35L43_STEREO 0x32
|
||||
#define CS35L43_QUAD 0x34
|
||||
|
||||
#define CS35L45_MONO 0x51
|
||||
#define CS35L45_STEREO 0x52
|
||||
#define CS35L45_QUAD 0x54
|
||||
#endif
|
||||
|
||||
enum {
|
||||
MI2S = 0,
|
||||
TDM,
|
||||
|
@ -262,11 +262,7 @@ SND_SOC_DAILINK_DEFS(pri_mi2s_tx,
|
||||
|
||||
SND_SOC_DAILINK_DEFS(sec_mi2s_rx,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
|
||||
#ifdef CONFIG_USE_CS40L26
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("cs40l26-codec", "cs40l26-pcm")),
|
||||
#else
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
|
||||
#endif
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(sec_mi2s_tx,
|
||||
@ -646,33 +642,3 @@ SND_SOC_DAILINK_DEFS(hs_if4_tdm_tx_0_dummy,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
|
||||
|
||||
#ifdef CONFIG_COMMON_AMP_CIRRUS
|
||||
SND_SOC_DAILINK_DEFS(cirrus_pri_tdm_rx_0,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY(),
|
||||
COMP_DUMMY(),
|
||||
COMP_DUMMY(),
|
||||
COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(cirrus_pri_tdm_tx_0,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY(),
|
||||
COMP_DUMMY(),
|
||||
COMP_DUMMY(),
|
||||
COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
|
||||
#endif
|
||||
#ifdef CONFIG_SND_SOC_TAS25XX
|
||||
SND_SOC_DAILINK_DEFS(tas25xx_pri_tdm_rx_0,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
|
||||
DAILINK_COMP_ARRAY(
|
||||
COMP_CODEC("tas25xx.18-0048", "tas25xx ASI1")),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(tas25xx_pri_tdm_tx_0,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
|
||||
DAILINK_COMP_ARRAY(
|
||||
COMP_CODEC("tas25xx.18-0048", "tas25xx ASI1")),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,9 +75,6 @@ ifeq ($(call is-board-platform-in-list, holi blair), true)
|
||||
AUDIO_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/wcd938x_dlkm.ko \
|
||||
$(KERNEL_MODULES_OUT)/wcd938x_slave_dlkm.ko
|
||||
endif
|
||||
ifeq ($(PROJECT_NAME),$(filter $(PROJECT_NAME),q6q b6q q6aq))
|
||||
AUDIO_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/tas25xx_dlkm.ko
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifeq ($(call is-board-platform-in-list, gen4 msmnile), true)
|
||||
|
@ -60,9 +60,7 @@ ifeq ($(call is-board-platform-in-list, holi blair), true)
|
||||
PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/wcd938x_dlkm.ko \
|
||||
$(KERNEL_MODULES_OUT)/wcd938x_slave_dlkm.ko
|
||||
endif
|
||||
ifeq ($(PROJECT_NAME),$(filter $(PROJECT_NAME),q6q b6q q6aq))
|
||||
PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/tas25xx_dlkm.ko
|
||||
endif
|
||||
|
||||
ifeq ($(call is-board-platform-in-list, gen4 msmnile), true)
|
||||
ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), gen4_gvm msmnile_gvmq))
|
||||
PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/machine_dlkm.ko \
|
||||
|
@ -19,17 +19,12 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/remoteproc.h>
|
||||
#include <linux/remoteproc/qcom_rproc.h>
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
|
||||
#include <sound/samsung/snd_debug_proc.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define Q6_PIL_GET_DELAY_MS 100
|
||||
#define BOOT_CMD 1
|
||||
#define SSR_RESET_CMD 1
|
||||
#define IMAGE_UNLOAD_CMD 0
|
||||
#if IS_ENABLED(CONFIG_SEC_SENSORS_SSC)
|
||||
#define SUB_SNS_VDD_CHECK_CMD 0
|
||||
#endif
|
||||
#define MAX_FW_IMAGES 4
|
||||
#define ADSP_LOADER_APM_TIMEOUT_MS 10000
|
||||
|
||||
@ -48,12 +43,6 @@ static ssize_t adsp_ssr_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_SENSORS_SSC)
|
||||
static ssize_t adsp_check_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
#endif
|
||||
|
||||
struct adsp_loader_private {
|
||||
void *pil_h;
|
||||
struct kobject *boot_adsp_obj;
|
||||
@ -68,17 +57,9 @@ static struct kobj_attribute adsp_boot_attribute =
|
||||
static struct kobj_attribute adsp_ssr_attribute =
|
||||
__ATTR(ssr, 0220, NULL, adsp_ssr_store);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_SENSORS_SSC)
|
||||
static struct kobj_attribute adsp_check_attribute =
|
||||
__ATTR(check, 0220, NULL, adsp_check_store);
|
||||
#endif
|
||||
|
||||
static struct attribute *attrs[] = {
|
||||
&adsp_boot_attribute.attr,
|
||||
&adsp_ssr_attribute.attr,
|
||||
#if IS_ENABLED(CONFIG_SEC_SENSORS_SSC)
|
||||
&adsp_check_attribute.attr,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -191,10 +172,6 @@ load_adsp:
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "%s: pil get failed,\n",
|
||||
__func__);
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
|
||||
sdp_boot_print("%s: ADSP loadig is failed = %d\n",
|
||||
__func__, rc);
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
} else if (adsp_state == SPF_SUBSYS_LOADED) {
|
||||
@ -272,36 +249,6 @@ static ssize_t adsp_boot_store(struct kobject *kobj,
|
||||
return count;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_SENSORS_SSC)
|
||||
static ssize_t adsp_check_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int check_command = 0;
|
||||
|
||||
if (kstrtoint(buf, 10, &check_command) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_command == SUB_SNS_VDD_CHECK_CMD) {
|
||||
struct platform_device *pdev = adsp_private;
|
||||
struct adsp_loader_private *priv = NULL;
|
||||
struct rproc *adsp_rproc = NULL;
|
||||
|
||||
priv = platform_get_drvdata(pdev);
|
||||
if (priv) {
|
||||
adsp_rproc = (struct rproc *)priv->pil_h;
|
||||
if (adsp_rproc) {
|
||||
pr_info("check subsensor vdd\n");
|
||||
adsp_init_subsensor_regulator(adsp_rproc,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void adsp_loader_unload(struct platform_device *pdev)
|
||||
{
|
||||
struct adsp_loader_private *priv = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user