asoc: codecs: Add support for rouleur codec

Add support for rouleur codec driver and pm2250
spmi driver.

Change-Id: Ie56f7af012c0c7b6e68077463f43050e051a3ef9
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
This commit is contained in:
Aditya Bavanari
2020-03-03 21:59:03 +05:30
committed by Gerrit - the friendly Code Review server
parent 68f58b0d09
commit 9120845177
13 changed files with 4731 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
# Android makefile for audio kernel modules
# Assume no targets will be supported
# Check if this driver needs be built for current target
ifeq ($(call is-board-platform,bengal),true)
AUDIO_SELECT := CONFIG_SND_SOC_BENGAL=m
endif
AUDIO_CHIPSET := audio
# Build/Package only in case of supported target
ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) bengal),true)
LOCAL_PATH := $(call my-dir)
# This makefile is only for DLKM
ifneq ($(findstring vendor,$(LOCAL_PATH)),)
ifneq ($(findstring opensource,$(LOCAL_PATH)),)
AUDIO_BLD_DIR := $(shell pwd)/vendor/qcom/opensource/audio-kernel
endif # opensource
DLKM_DIR := $(TOP)/device/qcom/common/dlkm
# Build audio.ko as $(AUDIO_CHIPSET)_audio.ko
###########################################################
# This is set once per LOCAL_PATH, not per (kernel) module
KBUILD_OPTIONS := AUDIO_ROOT=$(AUDIO_BLD_DIR)
# We are actually building audio.ko here, as per the
# requirement we are specifying <chipset>_audio.ko as LOCAL_MODULE.
# This means we need to rename the module to <chipset>_audio.ko
# after audio.ko is built.
KBUILD_OPTIONS += MODNAME=rouleur_dlkm
KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
KBUILD_OPTIONS += $(AUDIO_SELECT)
###########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := $(AUDIO_CHIPSET)_rouleur.ko
LOCAL_MODULE_KBUILD_NAME := rouleur_dlkm.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
###########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := $(AUDIO_CHIPSET)_rouleur_slave.ko
LOCAL_MODULE_KBUILD_NAME := rouleur_slave_dlkm.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
###########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := $(AUDIO_CHIPSET)_pm2250_spmi.ko
LOCAL_MODULE_KBUILD_NAME := pm2250_spmi_dlkm.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk
###########################################################
endif # DLKM check
endif # supported target check

120
asoc/codecs/rouleur/Kbuild Normal file
View File

@@ -0,0 +1,120 @@
# We can build either as part of a standalone Kernel build or as
# an external module. Determine which mechanism is being used
ifeq ($(MODNAME),)
KERNEL_BUILD := 1
else
KERNEL_BUILD := 0
endif
ifeq ($(KERNEL_BUILD), 1)
# These are configurable via Kconfig for kernel-based builds
# Need to explicitly configure for Android-based builds
AUDIO_BLD_DIR := $(ANDROID_BUILD_TOP)/kernel/msm-4.19
AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
endif
ifeq ($(KERNEL_BUILD), 0)
ifeq ($(CONFIG_ARCH_BENGAL), y)
include $(AUDIO_ROOT)/config/bengalauto.conf
export
INCS += -include $(AUDIO_ROOT)/config/bengalautoconf.h
endif
endif
# As per target team, build is done as follows:
# Defconfig : build with default flags
# Slub : defconfig + CONFIG_SLUB_DEBUG := y +
# CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
# Perf : Using appropriate msmXXXX-perf_defconfig
#
# Shipment builds (user variants) should not have any debug feature
# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
# there is no other way to identify defconfig builds, QTI internal
# representation of perf builds (identified using the string 'perf'),
# is used to identify if the build is a slub or defconfig one. This
# way no critical debug feature will be enabled for perf and shipment
# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
# config.
############ UAPI ############
UAPI_DIR := uapi
UAPI_INC := -I$(AUDIO_ROOT)/include/$(UAPI_DIR)
############ COMMON ############
COMMON_DIR := include
COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR)
############ ROULEUR ############
# for ROULEUR Codec
ifdef CONFIG_SND_SOC_ROULEUR
ROULEUR_OBJS += rouleur.o
ROULEUR_OBJS += rouleur-regmap.o
ROULEUR_OBJS += rouleur-tables.o
ROULEUR_OBJS += rouleur-mbhc.o
endif
ifdef CONFIG_PM2250_SPMI
PM2250_SPMI_OBJS += pm2250_spmi.o
endif
ifdef CONFIG_SND_SOC_ROULEUR_SLAVE
ROULEUR_SLAVE_OBJS += rouleur_slave.o
endif
LINUX_INC += -Iinclude/linux
INCS += $(COMMON_INC) \
$(UAPI_INC)
EXTRA_CFLAGS += $(INCS)
CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \
-DANI_LITTLE_BIT_ENDIAN \
-DDOT11F_LITTLE_ENDIAN_HOST \
-DANI_COMPILER_TYPE_GCC \
-DANI_OS_TYPE_ANDROID=6 \
-DPTT_SOCK_SVC_ENABLE \
-Wall\
-Werror\
-D__linux__
KBUILD_CPPFLAGS += $(CDEFINES)
# Currently, for versions of gcc which support it, the kernel Makefile
# is disabling the maybe-uninitialized warning. Re-enable it for the
# AUDIO driver. Note that we must use EXTRA_CFLAGS here so that it
# will override the kernel settings.
ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
EXTRA_CFLAGS += -Wmaybe-uninitialized
endif
#EXTRA_CFLAGS += -Wmissing-prototypes
ifeq ($(call cc-option-yn, -Wheader-guard),y)
EXTRA_CFLAGS += -Wheader-guard
endif
ifeq ($(KERNEL_BUILD), 0)
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
endif
# Module information used by KBuild framework
obj-$(CONFIG_SND_SOC_ROULEUR) += rouleur_dlkm.o
rouleur_dlkm-y := $(ROULEUR_OBJS)
obj-$(CONFIG_SND_SOC_ROULEUR_SLAVE) += rouleur_slave_dlkm.o
rouleur_slave_dlkm-y := $(ROULEUR_SLAVE_OBJS)
obj-$(CONFIG_PM2250_SPMI) += pm2250_spmi_dlkm.o
pm2250_spmi_dlkm-y := $(PM2250_SPMI_OBJS)
# inject some build related information
DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

View File

@@ -0,0 +1,172 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _ROULEUR_INTERNAL_H
#define _ROULEUR_INTERNAL_H
#include <asoc/wcd-clsh.h>
#include <asoc/wcd-mbhc-v2.h>
#include <asoc/wcd-irq.h>
#include "rouleur-mbhc.h"
#define ROULEUR_MAX_MICBIAS 3
/* Convert from vout ctl to micbias voltage in mV */
#define WCD_VOUT_CTL_TO_MICB(v) (1600 + v * 50)
#define MAX_PORT 8
#define MAX_CH_PER_PORT 8
extern struct regmap_config rouleur_regmap_config;
struct codec_port_info {
u32 slave_port_type;
u32 master_port_type;
u32 ch_mask;
u32 num_ch;
u32 ch_rate;
};
struct rouleur_priv {
struct device *dev;
int variant;
struct snd_soc_component *component;
struct device_node *spmi_np;
struct regmap *regmap;
struct swr_device *rx_swr_dev;
struct swr_device *tx_swr_dev;
s32 micb_ref[ROULEUR_MAX_MICBIAS];
s32 pullup_ref[ROULEUR_MAX_MICBIAS];
struct fw_info *fw_data;
struct mutex micb_lock;
s32 dmic_0_1_clk_cnt;
/* mbhc module */
struct rouleur_mbhc *mbhc;
bool comp1_enable;
bool comp2_enable;
struct irq_domain *virq;
struct wcd_irq_info irq_info;
u32 rx_clk_cnt;
int num_irq_regs;
/* to track the status */
unsigned long status_mask;
u8 num_tx_ports;
u8 num_rx_ports;
struct codec_port_info
tx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
struct codec_port_info
rx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
struct regulator_bulk_data *supplies;
struct notifier_block nblock;
/* wcd callback to bolero */
void *handle;
int (*update_wcd_event)(void *handle, u16 event, u32 data);
int (*register_notifier)(void *handle,
struct notifier_block *nblock,
bool enable);
int (*wakeup)(void *handle, bool enable);
u32 version;
/* Entry for version info */
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
struct device *spmi_dev;
int reset_reg;
int mbias_cnt;
struct mutex rx_clk_lock;
struct mutex main_bias_lock;
};
struct rouleur_micbias_setting {
u32 micb1_mv;
u32 micb2_mv;
u32 micb3_mv;
};
struct rouleur_pdata {
struct device_node *spmi_np;
struct device_node *rx_slave;
struct device_node *tx_slave;
struct rouleur_micbias_setting micbias;
struct cdc_regulator *regulator;
int num_supplies;
int reset_reg;
};
struct wcd_ctrl_platform_data {
void *handle;
int (*update_wcd_event)(void *handle, u16 event, u32 data);
int (*register_notifier)(void *handle,
struct notifier_block *nblock,
bool enable);
};
enum {
WCD_RX1,
WCD_RX2,
WCD_RX3
};
enum {
BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
BOLERO_WCD_EVT_PA_OFF_PRE_SSR,
BOLERO_WCD_EVT_SSR_DOWN,
BOLERO_WCD_EVT_SSR_UP,
};
enum {
WCD_BOLERO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
WCD_BOLERO_EVT_IMPED_TRUE, /* for imped true */
WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */
WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
WCD_BOLERO_EVT_BCS_CLK_OFF,
};
enum {
/* INTR_CTRL_INT_MASK_0 */
ROULEUR_IRQ_MBHC_BUTTON_PRESS_DET = 0,
ROULEUR_IRQ_MBHC_BUTTON_RELEASE_DET,
ROULEUR_IRQ_MBHC_ELECT_INS_REM_DET,
ROULEUR_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
ROULEUR_IRQ_MBHC_SW_DET,
ROULEUR_IRQ_HPHR_OCP_INT,
ROULEUR_IRQ_HPHR_CNP_INT,
ROULEUR_IRQ_HPHL_OCP_INT,
/* INTR_CTRL_INT_MASK_1 */
ROULEUR_IRQ_HPHL_CNP_INT,
ROULEUR_IRQ_EAR_CNP_INT,
ROULEUR_IRQ_EAR_OCP_INT,
ROULEUR_IRQ_LO_CNP_INT,
ROULEUR_IRQ_LO_OCP_INT,
ROULEUR_IRQ_HPHL_PDM_WD_INT,
ROULEUR_IRQ_HPHR_PDM_WD_INT,
ROULEUR_IRQ_RESERVED_0,
/* INTR_CTRL_INT_MASK_2 */
ROULEUR_IRQ_RESERVED_1,
ROULEUR_IRQ_RESERVED_2,
ROULEUR_IRQ_HPHL_SURGE_DET_INT,
ROULEUR_IRQ_HPHR_SURGE_DET_INT,
ROULEUR_NUM_IRQS,
};
extern void rouleur_disable_bcs_before_slow_insert(
struct snd_soc_component *component,
bool bcs_disable);
extern struct rouleur_mbhc *rouleur_soc_get_mbhc(
struct snd_soc_component *component);
extern int rouleur_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
int volt, int micb_num);
extern int rouleur_get_micb_vout_ctl_val(u32 micb_mv);
extern int rouleur_micbias_control(struct snd_soc_component *component,
int micb_num, int req, bool is_dapm);
#endif

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _PM2250_SPMI_H
#define _PM2250_SPMI_H
#ifdef CONFIG_PM2250_SPMI
int pm2250_spmi_write(struct device *dev, int reg, int value);
#else
int pm2250_spmi_write(struct device *dev, int reg, int value)
{
return 0;
}
#endif /* CONFIG_PM2250_SPMI */
#endif

View File

@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
/**
* @regmap: regmap used to access PMIC registers
*/
struct pm2250_spmi {
struct regmap *regmap;
};
static const struct of_device_id pm2250_id_table[] = {
{ .compatible = "qcom,pm2250-spmi" },
{ },
};
MODULE_DEVICE_TABLE(of, pm2250_id_table);
int pm2250_spmi_write(struct device *dev, int reg, int value)
{
int rc;
struct pm2250_spmi *spmi_dd;
if (!of_device_is_compatible(dev->of_node, "qcom,pm2250-spmi")) {
pr_err("%s: Device node is invalid\n", __func__);
return -EINVAL;
}
spmi_dd = dev_get_drvdata(dev);
if (!spmi_dd)
return -EINVAL;
rc = regmap_write(spmi_dd->regmap, reg, value);
if (rc)
dev_err(dev, "%s: Write to PMIC register failed\n", __func__);
return rc;
}
EXPORT_SYMBOL(pm2250_spmi_write);
static int pm2250_spmi_probe(struct platform_device *pdev)
{
struct pm2250_spmi *spmi_dd;
const struct of_device_id *match;
match = of_match_node(pm2250_id_table, pdev->dev.of_node);
if (!match)
return -ENXIO;
spmi_dd = devm_kzalloc(&pdev->dev, sizeof(*spmi_dd), GFP_KERNEL);
if (spmi_dd == NULL)
return -ENOMEM;
spmi_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!spmi_dd->regmap) {
dev_err(&pdev->dev, "Parent regmap unavailable.\n");
return -ENXIO;
}
platform_set_drvdata(pdev, spmi_dd);
dev_dbg(&pdev->dev, "Probe success !!\n");
return 0;
}
static int pm2250_spmi_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
return 0;
}
static struct platform_driver pm2250_spmi_driver = {
.probe = pm2250_spmi_probe,
.remove = pm2250_spmi_remove,
.driver = {
.name = "pm2250-spmi",
.of_match_table = pm2250_id_table,
},
};
module_platform_driver(pm2250_spmi_driver);
MODULE_ALIAS("platform:pm2250-spmi");
MODULE_DESCRIPTION("PMIC SPMI driver");
MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef __ROULEUR_MBHC_H__
#define __ROULEUR_MBHC_H__
#include <asoc/wcd-mbhc-v2.h>
struct rouleur_mbhc {
struct wcd_mbhc wcd_mbhc;
struct blocking_notifier_head notifier;
struct fw_info *fw_data;
};
#if IS_ENABLED(CONFIG_SND_SOC_ROULEUR)
extern int rouleur_mbhc_init(struct rouleur_mbhc **mbhc,
struct snd_soc_component *component,
struct fw_info *fw_data);
extern void rouleur_mbhc_hs_detect_exit(struct snd_soc_component *component);
extern int rouleur_mbhc_hs_detect(struct snd_soc_component *component,
struct wcd_mbhc_config *mbhc_cfg);
extern void rouleur_mbhc_deinit(struct snd_soc_component *component);
extern int rouleur_mbhc_post_ssr_init(struct rouleur_mbhc *mbhc,
struct snd_soc_component *component);
extern void rouleur_mbhc_ssr_down(struct rouleur_mbhc *mbhc,
struct snd_soc_component *component);
extern int rouleur_mbhc_get_impedance(struct rouleur_mbhc *rouleur_mbhc,
uint32_t *zl, uint32_t *zr);
#else
static inline int rouleur_mbhc_init(struct rouleur_mbhc **mbhc,
struct snd_soc_component *component,
struct fw_info *fw_data)
{
return 0;
}
static inline void rouleur_mbhc_hs_detect_exit(
struct snd_soc_component *component)
{
}
static inline int rouleur_mbhc_hs_detect(struct snd_soc_component *component,
struct wcd_mbhc_config *mbhc_cfg)
{
return 0;
}
static inline void rouleur_mbhc_deinit(struct snd_soc_component *component)
{
}
static inline int rouleur_mbhc_post_ssr_init(struct rouleur_mbhc *mbhc,
struct snd_soc_component *component)
{
return 0;
}
static inline void rouleur_mbhc_ssr_down(struct rouleur_mbhc *mbhc,
struct snd_soc_component *component)
{
}
static inline int rouleur_mbhc_get_impedance(struct rouleur_mbhc *rouleur_mbhc,
uint32_t *zl, uint32_t *zr)
{
if (zl)
*zl = 0;
if (zr)
*zr = 0;
return -EINVAL;
}
#endif
#endif /* __ROULEUR_MBHC_H__ */

View File

@@ -0,0 +1,121 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _ROULEUR_REGISTERS_H
#define _ROULEUR_REGISTERS_H
#define ROULEUR_ANA_BASE_ADDR 0x3000
#define ROULEUR_DIG_BASE_ADDR 0x3400
#define ROULEUR_REG(reg) ((reg > ROULEUR_DIG_BASE_ADDR) ? \
(reg - ROULEUR_DIG_BASE_ADDR) : \
(reg - ROULEUR_ANA_BASE_ADDR))
enum {
REG_NO_ACCESS,
RD_REG,
WR_REG,
RD_WR_REG
};
#define ROULEUR_ANA_MICBIAS_MICB_1_2_EN (ROULEUR_ANA_BASE_ADDR+0x040)
#define ROULEUR_ANA_MICBIAS_MICB_3_EN (ROULEUR_ANA_BASE_ADDR+0x041)
#define ROULEUR_ANA_MICBIAS_LDO_1_SETTING (ROULEUR_ANA_BASE_ADDR+0x042)
#define ROULEUR_ANA_MICBIAS_LDO_1_CTRL (ROULEUR_ANA_BASE_ADDR+0x043)
#define ROULEUR_ANA_TX_AMIC1 (ROULEUR_ANA_BASE_ADDR+0x047)
#define ROULEUR_ANA_TX_AMIC2 (ROULEUR_ANA_BASE_ADDR+0x048)
#define ROULEUR_ANA_MBHC_MECH (ROULEUR_ANA_BASE_ADDR+0x05A)
#define ROULEUR_ANA_MBHC_ELECT (ROULEUR_ANA_BASE_ADDR+0x05B)
#define ROULEUR_ANA_MBHC_ZDET (ROULEUR_ANA_BASE_ADDR+0x05C)
#define ROULEUR_ANA_MBHC_RESULT_1 (ROULEUR_ANA_BASE_ADDR+0x05D)
#define ROULEUR_ANA_MBHC_RESULT_2 (ROULEUR_ANA_BASE_ADDR+0x05E)
#define ROULEUR_ANA_MBHC_RESULT_3 (ROULEUR_ANA_BASE_ADDR+0x05F)
#define ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1 (ROULEUR_ANA_BASE_ADDR+0x060)
#define ROULEUR_ANA_MBHC_BTN1_ZDET_VREF2 (ROULEUR_ANA_BASE_ADDR+0x061)
#define ROULEUR_ANA_MBHC_BTN2_ZDET_VREF3 (ROULEUR_ANA_BASE_ADDR+0x062)
#define ROULEUR_ANA_MBHC_BTN3_ZDET_DBG_400 (ROULEUR_ANA_BASE_ADDR+0x063)
#define ROULEUR_ANA_MBHC_BTN4_ZDET_DBG_1400 (ROULEUR_ANA_BASE_ADDR+0x064)
#define ROULEUR_ANA_MBHC_MICB2_RAMP (ROULEUR_ANA_BASE_ADDR+0x065)
#define ROULEUR_ANA_MBHC_CTL_1 (ROULEUR_ANA_BASE_ADDR+0x066)
#define ROULEUR_ANA_MBHC_CTL_2 (ROULEUR_ANA_BASE_ADDR+0x067)
#define ROULEUR_ANA_MBHC_PLUG_DETECT_CTL (ROULEUR_ANA_BASE_ADDR+0x068)
#define ROULEUR_ANA_MBHC_ZDET_ANA_CTL (ROULEUR_ANA_BASE_ADDR+0x069)
#define ROULEUR_ANA_MBHC_ZDET_RAMP_CTL (ROULEUR_ANA_BASE_ADDR+0x06A)
#define ROULEUR_ANA_MBHC_FSM_STATUS (ROULEUR_ANA_BASE_ADDR+0x06B)
#define ROULEUR_ANA_MBHC_ADC_RESULT (ROULEUR_ANA_BASE_ADDR+0x06C)
#define ROULEUR_ANA_MBHC_MCLK (ROULEUR_ANA_BASE_ADDR+0x06D)
#define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT (ROULEUR_ANA_BASE_ADDR+0x072)
#define ROULEUR_ANA_NCP_EN (ROULEUR_ANA_BASE_ADDR+0x077)
#define ROULEUR_ANA_HPHPA_CNP_CTL_2 (ROULEUR_ANA_BASE_ADDR+0x084)
#define ROULEUR_ANA_HPHPA_PA_STATUS (ROULEUR_ANA_BASE_ADDR+0x087)
#define ROULEUR_ANA_HPHPA_FSM_CLK (ROULEUR_ANA_BASE_ADDR+0x088)
#define ROULEUR_ANA_HPHPA_L_GAIN (ROULEUR_ANA_BASE_ADDR+0x08B)
#define ROULEUR_ANA_HPHPA_R_GAIN (ROULEUR_ANA_BASE_ADDR+0x08C)
#define ROULEUR_ANA_HPHPA_SPARE_CTL (ROULEUR_ANA_BASE_ADDR+0x08E)
#define ROULEUR_ANA_SURGE_EN (ROULEUR_ANA_BASE_ADDR+0x097)
#define ROULEUR_ANA_COMBOPA_CTL (ROULEUR_ANA_BASE_ADDR+0x09B)
#define ROULEUR_ANA_RXLDO_CTL (ROULEUR_ANA_BASE_ADDR+0x0B2)
#define ROULEUR_ANA_MBIAS_EN (ROULEUR_ANA_BASE_ADDR+0x0B4)
#define ROULEUR_DIG_SWR_CHIP_ID0 (ROULEUR_DIG_BASE_ADDR+0x001)
#define ROULEUR_DIG_SWR_CHIP_ID1 (ROULEUR_DIG_BASE_ADDR+0x002)
#define ROULEUR_DIG_SWR_CHIP_ID2 (ROULEUR_DIG_BASE_ADDR+0x003)
#define ROULEUR_DIG_SWR_CHIP_ID3 (ROULEUR_DIG_BASE_ADDR+0x004)
#define ROULEUR_DIG_SWR_SWR_TX_CLK_RATE (ROULEUR_DIG_BASE_ADDR+0x040)
#define ROULEUR_DIG_SWR_CDC_RST_CTL (ROULEUR_DIG_BASE_ADDR+0x041)
#define ROULEUR_DIG_SWR_TOP_CLK_CFG (ROULEUR_DIG_BASE_ADDR+0x042)
#define ROULEUR_DIG_SWR_CDC_RX_CLK_CTL (ROULEUR_DIG_BASE_ADDR+0x043)
#define ROULEUR_DIG_SWR_CDC_TX_CLK_CTL (ROULEUR_DIG_BASE_ADDR+0x044)
#define ROULEUR_DIG_SWR_SWR_RST_EN (ROULEUR_DIG_BASE_ADDR+0x045)
#define ROULEUR_DIG_SWR_CDC_RX_RST (ROULEUR_DIG_BASE_ADDR+0x047)
#define ROULEUR_DIG_SWR_CDC_RX0_CTL (ROULEUR_DIG_BASE_ADDR+0x048)
#define ROULEUR_DIG_SWR_CDC_RX1_CTL (ROULEUR_DIG_BASE_ADDR+0x049)
#define ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1 (ROULEUR_DIG_BASE_ADDR+0x04B)
#define ROULEUR_DIG_SWR_CDC_COMP_CTL_0 (ROULEUR_DIG_BASE_ADDR+0x04F)
#define ROULEUR_DIG_SWR_CDC_RX_DELAY_CTL (ROULEUR_DIG_BASE_ADDR+0x052)
#define ROULEUR_DIG_SWR_CDC_RX_GAIN_0 (ROULEUR_DIG_BASE_ADDR+0x053)
#define ROULEUR_DIG_SWR_CDC_RX_GAIN_1 (ROULEUR_DIG_BASE_ADDR+0x054)
#define ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL (ROULEUR_DIG_BASE_ADDR+0x057)
#define ROULEUR_DIG_SWR_CDC_TX0_CTL (ROULEUR_DIG_BASE_ADDR+0x060)
#define ROULEUR_DIG_SWR_CDC_TX1_CTL (ROULEUR_DIG_BASE_ADDR+0x061)
#define ROULEUR_DIG_SWR_CDC_TX_RST (ROULEUR_DIG_BASE_ADDR+0x063)
#define ROULEUR_DIG_SWR_CDC_REQ0_CTL (ROULEUR_DIG_BASE_ADDR+0x064)
#define ROULEUR_DIG_SWR_CDC_REQ1_CTL (ROULEUR_DIG_BASE_ADDR+0x065)
#define ROULEUR_DIG_SWR_CDC_RST (ROULEUR_DIG_BASE_ADDR+0x067)
#define ROULEUR_DIG_SWR_CDC_AMIC_CTL (ROULEUR_DIG_BASE_ADDR+0x06A)
#define ROULEUR_DIG_SWR_CDC_DMIC_CTL (ROULEUR_DIG_BASE_ADDR+0x06B)
#define ROULEUR_DIG_SWR_CDC_DMIC1_CTL (ROULEUR_DIG_BASE_ADDR+0x06C)
#define ROULEUR_DIG_SWR_CDC_DMIC1_RATE (ROULEUR_DIG_BASE_ADDR+0x06D)
#define ROULEUR_DIG_SWR_PDM_WD_CTL0 (ROULEUR_DIG_BASE_ADDR+0x070)
#define ROULEUR_DIG_SWR_PDM_WD_CTL1 (ROULEUR_DIG_BASE_ADDR+0x071)
#define ROULEUR_DIG_SWR_INTR_MODE (ROULEUR_DIG_BASE_ADDR+0x080)
#define ROULEUR_DIG_SWR_INTR_MASK_0 (ROULEUR_DIG_BASE_ADDR+0x081)
#define ROULEUR_DIG_SWR_INTR_MASK_1 (ROULEUR_DIG_BASE_ADDR+0x082)
#define ROULEUR_DIG_SWR_INTR_MASK_2 (ROULEUR_DIG_BASE_ADDR+0x083)
#define ROULEUR_DIG_SWR_INTR_STATUS_0 (ROULEUR_DIG_BASE_ADDR+0x084)
#define ROULEUR_DIG_SWR_INTR_STATUS_1 (ROULEUR_DIG_BASE_ADDR+0x085)
#define ROULEUR_DIG_SWR_INTR_STATUS_2 (ROULEUR_DIG_BASE_ADDR+0x086)
#define ROULEUR_DIG_SWR_INTR_CLEAR_0 (ROULEUR_DIG_BASE_ADDR+0x087)
#define ROULEUR_DIG_SWR_INTR_CLEAR_1 (ROULEUR_DIG_BASE_ADDR+0x088)
#define ROULEUR_DIG_SWR_INTR_CLEAR_2 (ROULEUR_DIG_BASE_ADDR+0x089)
#define ROULEUR_DIG_SWR_INTR_LEVEL_0 (ROULEUR_DIG_BASE_ADDR+0x08A)
#define ROULEUR_DIG_SWR_INTR_LEVEL_1 (ROULEUR_DIG_BASE_ADDR+0x08B)
#define ROULEUR_DIG_SWR_INTR_LEVEL_2 (ROULEUR_DIG_BASE_ADDR+0x08C)
#define ROULEUR_DIG_SWR_CDC_CONN_RX0_CTL (ROULEUR_DIG_BASE_ADDR+0x093)
#define ROULEUR_DIG_SWR_CDC_CONN_RX1_CTL (ROULEUR_DIG_BASE_ADDR+0x094)
#define ROULEUR_DIG_SWR_LOOP_BACK_MODE (ROULEUR_DIG_BASE_ADDR+0x097)
#define ROULEUR_DIG_SWR_DRIVE_STRENGTH_0 (ROULEUR_DIG_BASE_ADDR+0x0A0)
#define ROULEUR_DIG_SWR_DIG_DEBUG_CTL (ROULEUR_DIG_BASE_ADDR+0x0AB)
#define ROULEUR_DIG_SWR_DIG_DEBUG_EN (ROULEUR_DIG_BASE_ADDR+0x0AC)
#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA0 (ROULEUR_DIG_BASE_ADDR+0x0B0)
#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA1 (ROULEUR_DIG_BASE_ADDR+0x0B1)
#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA2 (ROULEUR_DIG_BASE_ADDR+0x0B2)
#define ROULEUR_DIG_SWR_DEM_BYPASS_DATA3 (ROULEUR_DIG_BASE_ADDR+0x0B3)
#define ROULEUR_ANALOG_REGISTERS_MAX_SIZE (ROULEUR_ANA_BASE_ADDR+0x0B5)
#define ROULEUR_DIGITAL_REGISTERS_MAX_SIZE (ROULEUR_DIG_BASE_ADDR+0x0B4)
#define ROULEUR_ANALOG_MAX_REGISTER (ROULEUR_ANALOG_REGISTERS_MAX_SIZE - 1)
#define ROULEUR_DIGITAL_MAX_REGISTER (ROULEUR_DIGITAL_REGISTERS_MAX_SIZE - 1)
#endif

View File

@@ -0,0 +1,160 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/regmap.h>
#include <linux/device.h>
#include "rouleur-registers.h"
extern const u8 rouleur_reg_access_analog[
ROULEUR_REG(ROULEUR_ANALOG_REGISTERS_MAX_SIZE)];
extern const u8 rouleur_reg_access_digital[
ROULEUR_REG(ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)];
static const struct reg_default rouleur_defaults[] = {
{ ROULEUR_ANA_MICBIAS_MICB_1_2_EN, 0x01 },
{ ROULEUR_ANA_MICBIAS_MICB_3_EN, 0x00 },
{ ROULEUR_ANA_MICBIAS_LDO_1_SETTING, 0x21 },
{ ROULEUR_ANA_MICBIAS_LDO_1_CTRL, 0x01 },
{ ROULEUR_ANA_TX_AMIC1, 0x00 },
{ ROULEUR_ANA_TX_AMIC2, 0x00 },
{ ROULEUR_ANA_MBHC_MECH, 0x39 },
{ ROULEUR_ANA_MBHC_ELECT, 0x08 },
{ ROULEUR_ANA_MBHC_ZDET, 0x10 },
{ ROULEUR_ANA_MBHC_RESULT_1, 0x00 },
{ ROULEUR_ANA_MBHC_RESULT_2, 0x00 },
{ ROULEUR_ANA_MBHC_RESULT_3, 0x00 },
{ ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1, 0x00 },
{ ROULEUR_ANA_MBHC_BTN1_ZDET_VREF2, 0x10 },
{ ROULEUR_ANA_MBHC_BTN2_ZDET_VREF3, 0x20 },
{ ROULEUR_ANA_MBHC_BTN3_ZDET_DBG_400, 0x30 },
{ ROULEUR_ANA_MBHC_BTN4_ZDET_DBG_1400, 0x40 },
{ ROULEUR_ANA_MBHC_MICB2_RAMP, 0x00 },
{ ROULEUR_ANA_MBHC_CTL_1, 0x02 },
{ ROULEUR_ANA_MBHC_CTL_2, 0x05 },
{ ROULEUR_ANA_MBHC_PLUG_DETECT_CTL, 0xE9 },
{ ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x0F },
{ ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, 0x00 },
{ ROULEUR_ANA_MBHC_FSM_STATUS, 0x00 },
{ ROULEUR_ANA_MBHC_ADC_RESULT, 0x00 },
{ ROULEUR_ANA_MBHC_MCLK, 0x30 },
{ ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 },
{ ROULEUR_ANA_NCP_EN, 0x00 },
{ ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x2B },
{ ROULEUR_ANA_HPHPA_PA_STATUS, 0x00 },
{ ROULEUR_ANA_HPHPA_FSM_CLK, 0x12 },
{ ROULEUR_ANA_HPHPA_SPARE_CTL, 0x02 },
{ ROULEUR_ANA_SURGE_EN, 0x38 },
{ ROULEUR_ANA_COMBOPA_CTL, 0x35 },
{ ROULEUR_ANA_RXLDO_CTL, 0x86 },
{ ROULEUR_ANA_MBIAS_EN, 0x00 },
{ ROULEUR_DIG_SWR_CHIP_ID0, 0x00 },
{ ROULEUR_DIG_SWR_CHIP_ID1, 0x00 },
{ ROULEUR_DIG_SWR_CHIP_ID2, 0x0C },
{ ROULEUR_DIG_SWR_CHIP_ID3, 0x01 },
{ ROULEUR_DIG_SWR_SWR_TX_CLK_RATE, 0x00 },
{ ROULEUR_DIG_SWR_CDC_RST_CTL, 0x03 },
{ ROULEUR_DIG_SWR_TOP_CLK_CFG, 0x00 },
{ ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x00 },
{ ROULEUR_DIG_SWR_CDC_TX_CLK_CTL, 0x33 },
{ ROULEUR_DIG_SWR_SWR_RST_EN, 0x00 },
{ ROULEUR_DIG_SWR_CDC_RX_RST, 0x00 },
{ ROULEUR_DIG_SWR_CDC_RX0_CTL, 0xFC },
{ ROULEUR_DIG_SWR_CDC_RX1_CTL, 0xFC },
{ ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1, 0x00 },
{ ROULEUR_DIG_SWR_CDC_COMP_CTL_0, 0x00 },
{ ROULEUR_DIG_SWR_CDC_RX_DELAY_CTL, 0x66 },
{ ROULEUR_DIG_SWR_CDC_RX_GAIN_0, 0x55 },
{ ROULEUR_DIG_SWR_CDC_RX_GAIN_1, 0xA9 },
{ ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x00 },
{ ROULEUR_DIG_SWR_CDC_TX0_CTL, 0x68 },
{ ROULEUR_DIG_SWR_CDC_TX1_CTL, 0x68 },
{ ROULEUR_DIG_SWR_CDC_TX_RST, 0x00 },
{ ROULEUR_DIG_SWR_CDC_REQ0_CTL, 0x01 },
{ ROULEUR_DIG_SWR_CDC_REQ1_CTL, 0x01 },
{ ROULEUR_DIG_SWR_CDC_RST, 0x00 },
{ ROULEUR_DIG_SWR_CDC_AMIC_CTL, 0x02 },
{ ROULEUR_DIG_SWR_CDC_DMIC_CTL, 0x00 },
{ ROULEUR_DIG_SWR_CDC_DMIC1_CTL, 0x00 },
{ ROULEUR_DIG_SWR_CDC_DMIC1_RATE, 0x01 },
{ ROULEUR_DIG_SWR_PDM_WD_CTL0, 0x00 },
{ ROULEUR_DIG_SWR_PDM_WD_CTL1, 0x00 },
{ ROULEUR_DIG_SWR_INTR_MODE, 0x00 },
{ ROULEUR_DIG_SWR_INTR_MASK_0, 0xFF },
{ ROULEUR_DIG_SWR_INTR_MASK_1, 0x7F },
{ ROULEUR_DIG_SWR_INTR_MASK_2, 0x0C },
{ ROULEUR_DIG_SWR_INTR_STATUS_0, 0x00 },
{ ROULEUR_DIG_SWR_INTR_STATUS_1, 0x00 },
{ ROULEUR_DIG_SWR_INTR_STATUS_2, 0x00 },
{ ROULEUR_DIG_SWR_INTR_CLEAR_0, 0x00 },
{ ROULEUR_DIG_SWR_INTR_CLEAR_1, 0x00 },
{ ROULEUR_DIG_SWR_INTR_CLEAR_2, 0x00 },
{ ROULEUR_DIG_SWR_INTR_LEVEL_0, 0x00 },
{ ROULEUR_DIG_SWR_INTR_LEVEL_1, 0x2A },
{ ROULEUR_DIG_SWR_INTR_LEVEL_2, 0x00 },
{ ROULEUR_DIG_SWR_CDC_CONN_RX0_CTL, 0x00 },
{ ROULEUR_DIG_SWR_CDC_CONN_RX1_CTL, 0x00 },
{ ROULEUR_DIG_SWR_LOOP_BACK_MODE, 0x00 },
{ ROULEUR_DIG_SWR_DRIVE_STRENGTH_0, 0x00 },
{ ROULEUR_DIG_SWR_DIG_DEBUG_CTL, 0x00 },
{ ROULEUR_DIG_SWR_DIG_DEBUG_EN, 0x00 },
{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA0, 0x55 },
{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA1, 0x55 },
{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA2, 0x55 },
{ ROULEUR_DIG_SWR_DEM_BYPASS_DATA3, 0x01 },
};
static bool rouleur_readable_register(struct device *dev, unsigned int reg)
{
if (reg > ROULEUR_ANA_BASE_ADDR && reg <
ROULEUR_ANALOG_REGISTERS_MAX_SIZE)
return rouleur_reg_access_analog[ROULEUR_REG(reg)] & RD_REG;
if (reg > ROULEUR_DIG_BASE_ADDR && reg <
ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)
return rouleur_reg_access_digital[ROULEUR_REG(reg)] & RD_REG;
return 0;
}
static bool rouleur_writeable_register(struct device *dev, unsigned int reg)
{
if (reg > ROULEUR_ANA_BASE_ADDR && reg <
ROULEUR_ANALOG_REGISTERS_MAX_SIZE)
return rouleur_reg_access_analog[ROULEUR_REG(reg)] & WR_REG;
if (reg > ROULEUR_DIG_BASE_ADDR && reg <
ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)
return rouleur_reg_access_digital[ROULEUR_REG(reg)] & WR_REG;
return 0;
}
static bool rouleur_volatile_register(struct device *dev, unsigned int reg)
{
if (reg > ROULEUR_ANA_BASE_ADDR && reg <
ROULEUR_ANALOG_REGISTERS_MAX_SIZE)
if ((rouleur_reg_access_analog[ROULEUR_REG(reg)] & RD_REG)
&& !(rouleur_reg_access_analog[ROULEUR_REG(reg)] & WR_REG))
return true;
return false;
if (reg > ROULEUR_DIG_BASE_ADDR && reg <
ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)
if ((rouleur_reg_access_digital[ROULEUR_REG(reg)] & RD_REG)
&& !(rouleur_reg_access_digital[ROULEUR_REG(reg)] & WR_REG))
return true;
return false;
return 0;
}
struct regmap_config rouleur_regmap_config = {
.name = "rouleur_csr",
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rouleur_defaults,
.num_reg_defaults = ARRAY_SIZE(rouleur_defaults),
.max_register = ROULEUR_ANALOG_MAX_REGISTER +
ROULEUR_DIGITAL_MAX_REGISTER,
.readable_reg = rouleur_readable_register,
.writeable_reg = rouleur_writeable_register,
.volatile_reg = rouleur_volatile_register,
.can_multi_write = true,
};

View File

@@ -0,0 +1,105 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/types.h>
#include "rouleur-registers.h"
const u8 rouleur_reg_access_analog[ROULEUR_REG(
ROULEUR_ANALOG_REGISTERS_MAX_SIZE)] = {
[ROULEUR_REG(ROULEUR_ANA_MICBIAS_MICB_1_2_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MICBIAS_MICB_3_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MICBIAS_LDO_1_SETTING)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MICBIAS_LDO_1_CTRL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_TX_AMIC1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_TX_AMIC2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_MECH)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ELECT)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_RESULT_1)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_RESULT_2)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_RESULT_3)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN0_ZDET_VREF1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN1_ZDET_VREF2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN2_ZDET_VREF3)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN3_ZDET_DBG_400)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_BTN4_ZDET_DBG_1400)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_MICB2_RAMP)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_PLUG_DETECT_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_ANA_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_RAMP_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_FSM_STATUS)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ADC_RESULT)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_MCLK)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_PA_STATUS)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_FSM_CLK)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_SPARE_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_SURGE_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_RXLDO_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBIAS_EN)] = RD_WR_REG,
};
const u8 rouleur_reg_access_digital[ROULEUR_REG(
ROULEUR_DIGITAL_REGISTERS_MAX_SIZE)] = {
[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID0)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID1)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID2)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CHIP_ID3)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_SWR_TX_CLK_RATE)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RST_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_TOP_CLK_CFG)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_CLK_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX_CLK_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_SWR_RST_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_RST)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX0_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX1_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX_ANA_MODE_0_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_COMP_CTL_0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_DELAY_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_GAIN_0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_GAIN_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX0_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX1_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_TX_RST)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_REQ0_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_REQ1_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_RST)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_AMIC_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_DMIC_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_DMIC1_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_DMIC1_RATE)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_PDM_WD_CTL0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_PDM_WD_CTL1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MODE)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MASK_0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MASK_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_MASK_2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_STATUS_0)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_STATUS_1)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_STATUS_2)] = RD_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_CLEAR_0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_CLEAR_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_CLEAR_2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_LEVEL_0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_LEVEL_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_INTR_LEVEL_2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_CONN_RX0_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_CDC_CONN_RX1_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_LOOP_BACK_MODE)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DRIVE_STRENGTH_0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DIG_DEBUG_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DIG_DEBUG_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA0)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_DIG_SWR_DEM_BYPASS_DATA3)] = RD_WR_REG,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _ROULEUR_H
#define _ROULEUR_H
#ifdef CONFIG_SND_SOC_ROULEUR
extern int rouleur_info_create_codec_entry(struct snd_info_entry *codec_root,
struct snd_soc_component *component);
#else
extern int rouleur_info_create_codec_entry(struct snd_info_entry *codec_root,
struct snd_soc_component *component)
{
return 0;
}
#endif /* CONFIG_SND_SOC_ROULEUR */
#endif

View File

@@ -0,0 +1,144 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/component.h>
#include <soc/soundwire.h>
struct rouleur_slave_priv {
struct swr_device *swr_slave;
};
static int rouleur_slave_bind(struct device *dev,
struct device *master, void *data)
{
int ret = 0;
struct rouleur_slave_priv *rouleur_slave = NULL;
uint8_t devnum = 0;
struct swr_device *pdev = to_swr_device(dev);
if (pdev == NULL) {
dev_err(dev, "%s: pdev is NULL\n", __func__);
return -EINVAL;
}
rouleur_slave = devm_kzalloc(&pdev->dev,
sizeof(struct rouleur_slave_priv), GFP_KERNEL);
if (!rouleur_slave)
return -ENOMEM;
swr_set_dev_data(pdev, rouleur_slave);
rouleur_slave->swr_slave = pdev;
ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
if (ret) {
dev_dbg(&pdev->dev,
"%s get devnum %d for dev addr %lx failed\n",
__func__, devnum, pdev->addr);
swr_remove_device(pdev);
return ret;
}
pdev->dev_num = devnum;
return ret;
}
static void rouleur_slave_unbind(struct device *dev,
struct device *master, void *data)
{
struct rouleur_slave_priv *rouleur_slave = NULL;
struct swr_device *pdev = to_swr_device(dev);
if (pdev == NULL) {
dev_err(dev, "%s: pdev is NULL\n", __func__);
return;
}
rouleur_slave = swr_get_dev_data(pdev);
if (!rouleur_slave) {
dev_err(&pdev->dev, "%s: rouleur_slave is NULL\n", __func__);
return;
}
swr_set_dev_data(pdev, NULL);
}
static const struct swr_device_id rouleur_swr_id[] = {
{"rouleur-slave", 0},
{}
};
static const struct of_device_id rouleur_swr_dt_match[] = {
{
.compatible = "qcom,rouleur-slave",
},
{}
};
static const struct component_ops rouleur_slave_comp_ops = {
.bind = rouleur_slave_bind,
.unbind = rouleur_slave_unbind,
};
static int rouleur_swr_up(struct swr_device *pdev)
{
return 0;
}
static int rouleur_swr_down(struct swr_device *pdev)
{
return 0;
}
static int rouleur_swr_reset(struct swr_device *pdev)
{
return 0;
}
static int rouleur_swr_probe(struct swr_device *pdev)
{
return component_add(&pdev->dev, &rouleur_slave_comp_ops);
}
static int rouleur_swr_remove(struct swr_device *pdev)
{
component_del(&pdev->dev, &rouleur_slave_comp_ops);
return 0;
}
static struct swr_driver rouleur_slave_driver = {
.driver = {
.name = "rouleur-slave",
.owner = THIS_MODULE,
.of_match_table = rouleur_swr_dt_match,
},
.probe = rouleur_swr_probe,
.remove = rouleur_swr_remove,
.id_table = rouleur_swr_id,
.device_up = rouleur_swr_up,
.device_down = rouleur_swr_down,
.reset_device = rouleur_swr_reset,
};
static int __init rouleur_slave_init(void)
{
return swr_driver_register(&rouleur_slave_driver);
}
static void __exit rouleur_slave_exit(void)
{
swr_driver_unregister(&rouleur_slave_driver);
}
module_init(rouleur_slave_init);
module_exit(rouleur_slave_exit);
MODULE_DESCRIPTION("WCD937X Swr Slave driver");
MODULE_LICENSE("GPL v2");