X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fstaging%2Fchunkeey.git;a=blobdiff_plain;f=target%2Flinux%2Fbcm27xx%2Fpatches-5.10%2F950-0390-Allo-boss2-driver.patch;fp=target%2Flinux%2Fbcm27xx%2Fpatches-5.10%2F950-0390-Allo-boss2-driver.patch;h=0000000000000000000000000000000000000000;hp=b07f7c9f2d63bc4bd13253e6ba87340b4cdd8377;hb=d5c4f24b2af991df2ec24df1a3f906049370f59f;hpb=99ad84b6d9727a63f99a16e0b8386747262e3433 diff --git a/target/linux/bcm27xx/patches-5.10/950-0390-Allo-boss2-driver.patch b/target/linux/bcm27xx/patches-5.10/950-0390-Allo-boss2-driver.patch deleted file mode 100644 index b07f7c9f2d..0000000000 --- a/target/linux/bcm27xx/patches-5.10/950-0390-Allo-boss2-driver.patch +++ /dev/null @@ -1,1185 +0,0 @@ -From 5eba3bb8b48060a5ddf143c1aa69840a90dd9162 Mon Sep 17 00:00:00 2001 -From: Sudeep -Date: Fri, 23 Oct 2020 15:47:17 +0530 -Subject: [PATCH] Allo boss2 driver - -Signed-off-by: Sudeep ---- - sound/soc/bcm/Kconfig | 9 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/allo-boss2-dac.c | 1133 ++++++++++++++++++++++++++++++++ - 3 files changed, 1144 insertions(+) - create mode 100644 sound/soc/bcm/allo-boss2-dac.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -267,6 +267,15 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC - help - Say Y or M if you want to add support for Allo Boss DAC. - -+config SND_BCM2708_SOC_ALLO_BOSS2_DAC -+ tristate "Support for Allo Boss2 DAC" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ depends on I2C -+ select REGMAP_I2C -+ select SND_AUDIO_GRAPH_CARD -+ help -+ Say Y or M if you want to add support for Allo Boss2 DAC. -+ - config SND_BCM2708_SOC_ALLO_DIGIONE - tristate "Support for Allo DigiOne" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -38,6 +38,7 @@ snd-soc-digidac1-soundcard-objs := digid - snd-soc-dionaudio-loco-objs := dionaudio_loco.o - snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o - snd-soc-allo-boss-dac-objs := allo-boss-dac.o -+snd-soc-allo-boss2-dac-objs := allo-boss2-dac.o - snd-soc-allo-piano-dac-objs := allo-piano-dac.o - snd-soc-allo-piano-dac-plus-objs := allo-piano-dac-plus.o - snd-soc-allo-katana-codec-objs := allo-katana-codec.o -@@ -68,6 +69,7 @@ obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += snd-soc-allo-boss-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS2_DAC) += snd-soc-allo-boss2-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS) += snd-soc-allo-piano-dac-plus.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC) += snd-soc-allo-katana-codec.o ---- /dev/null -+++ b/sound/soc/bcm/allo-boss2-dac.c -@@ -0,0 +1,1133 @@ -+/* -+ * Driver for the ALLO KATANA CODEC -+ * -+ * Author: Jaikumar -+ * Copyright 2018 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/cs43130.h" -+ -+#include -+#include -+#define DEBUG -+ -+#define CS43130_DSD_EN_MASK 0x10 -+#define CS43130_PDN_DONE_INT_MASK 0x00 -+ -+static struct gpio_desc *snd_allo_clk44gpio; -+static struct gpio_desc *snd_allo_clk48gpio; -+ -+struct cs43130_priv { -+ struct snd_soc_component *component; -+ struct regmap *regmap; -+ struct regulator_bulk_data supplies[CS43130_NUM_SUPPLIES]; -+ struct gpio_desc *reset_gpio; -+ unsigned int dev_id; /* codec device ID */ -+ int xtal_ibias; -+ /* shared by both DAIs */ -+ struct mutex clk_mutex; -+ int clk_req; -+ bool pll_bypass; -+ struct completion xtal_rdy; -+ struct completion pll_rdy; -+ unsigned int mclk; -+ unsigned int mclk_int; -+ int mclk_int_src; -+ -+ /* DAI specific */ -+ struct cs43130_dai dais[CS43130_DAI_ID_MAX]; -+ -+ /* HP load specific */ -+ bool dc_meas; -+ bool ac_meas; -+ bool hpload_done; -+ struct completion hpload_evt; -+ unsigned int hpload_stat; -+ u16 hpload_dc[2]; -+ u16 dc_threshold[CS43130_DC_THRESHOLD]; -+ u16 ac_freq[CS43130_AC_FREQ]; -+ u16 hpload_ac[CS43130_AC_FREQ][2]; -+ struct workqueue_struct *wq; -+ struct work_struct work; -+ struct snd_soc_jack jack; -+}; -+ -+static const struct reg_default cs43130_reg_defaults[] = { -+ {CS43130_SYS_CLK_CTL_1, 0x06}, -+ {CS43130_SP_SRATE, 0x01}, -+ {CS43130_SP_BITSIZE, 0x05}, -+ {CS43130_PAD_INT_CFG, 0x03}, -+ {CS43130_PWDN_CTL, 0xFE}, -+ {CS43130_CRYSTAL_SET, 0x04}, -+ {CS43130_PLL_SET_1, 0x00}, -+ {CS43130_PLL_SET_2, 0x00}, -+ {CS43130_PLL_SET_3, 0x00}, -+ {CS43130_PLL_SET_4, 0x00}, -+ {CS43130_PLL_SET_5, 0x40}, -+ {CS43130_PLL_SET_6, 0x10}, -+ {CS43130_PLL_SET_7, 0x80}, -+ {CS43130_PLL_SET_8, 0x03}, -+ {CS43130_PLL_SET_9, 0x02}, -+ {CS43130_PLL_SET_10, 0x02}, -+ {CS43130_CLKOUT_CTL, 0x00}, -+ {CS43130_ASP_NUM_1, 0x01}, -+ {CS43130_ASP_NUM_2, 0x00}, -+ {CS43130_ASP_DEN_1, 0x08}, -+ {CS43130_ASP_DEN_2, 0x00}, -+ {CS43130_ASP_LRCK_HI_TIME_1, 0x1F}, -+ {CS43130_ASP_LRCK_HI_TIME_2, 0x00}, -+ {CS43130_ASP_LRCK_PERIOD_1, 0x3F}, -+ {CS43130_ASP_LRCK_PERIOD_2, 0x00}, -+ {CS43130_ASP_CLOCK_CONF, 0x0C}, -+ {CS43130_ASP_FRAME_CONF, 0x0A}, -+ {CS43130_XSP_NUM_1, 0x01}, -+ {CS43130_XSP_NUM_2, 0x00}, -+ {CS43130_XSP_DEN_1, 0x02}, -+ {CS43130_XSP_DEN_2, 0x00}, -+ {CS43130_XSP_LRCK_HI_TIME_1, 0x1F}, -+ {CS43130_XSP_LRCK_HI_TIME_2, 0x00}, -+ {CS43130_XSP_LRCK_PERIOD_1, 0x3F}, -+ {CS43130_XSP_LRCK_PERIOD_2, 0x00}, -+ {CS43130_XSP_CLOCK_CONF, 0x0C}, -+ {CS43130_XSP_FRAME_CONF, 0x0A}, -+ {CS43130_ASP_CH_1_LOC, 0x00}, -+ {CS43130_ASP_CH_2_LOC, 0x00}, -+ {CS43130_ASP_CH_1_SZ_EN, 0x06}, -+ {CS43130_ASP_CH_2_SZ_EN, 0x0E}, -+ {CS43130_XSP_CH_1_LOC, 0x00}, -+ {CS43130_XSP_CH_2_LOC, 0x00}, -+ {CS43130_XSP_CH_1_SZ_EN, 0x06}, -+ {CS43130_XSP_CH_2_SZ_EN, 0x0E}, -+ {CS43130_DSD_VOL_B, 0x78}, -+ {CS43130_DSD_VOL_A, 0x78}, -+ {CS43130_DSD_PATH_CTL_1, 0xA8}, -+ {CS43130_DSD_INT_CFG, 0x00}, -+ {CS43130_DSD_PATH_CTL_2, 0x02}, -+ {CS43130_DSD_PCM_MIX_CTL, 0x00}, -+ {CS43130_DSD_PATH_CTL_3, 0x40}, -+ {CS43130_HP_OUT_CTL_1, 0x30}, -+ {CS43130_PCM_FILT_OPT, 0x02}, -+ {CS43130_PCM_VOL_B, 0x78}, -+ {CS43130_PCM_VOL_A, 0x78}, -+ {CS43130_PCM_PATH_CTL_1, 0xA8}, -+ {CS43130_PCM_PATH_CTL_2, 0x00}, -+ {CS43130_CLASS_H_CTL, 0x1E}, -+ {CS43130_HP_DETECT, 0x04}, -+ {CS43130_HP_LOAD_1, 0x00}, -+ {CS43130_HP_MEAS_LOAD_1, 0x00}, -+ {CS43130_HP_MEAS_LOAD_2, 0x00}, -+ {CS43130_INT_MASK_1, 0xFF}, -+ {CS43130_INT_MASK_2, 0xFF}, -+ {CS43130_INT_MASK_3, 0xFF}, -+ {CS43130_INT_MASK_4, 0xFF}, -+ {CS43130_INT_MASK_5, 0xFF}, -+}; -+static bool cs43130_volatile_register(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5: -+ case CS43130_HP_DC_STAT_1 ... CS43130_HP_DC_STAT_2: -+ case CS43130_HP_AC_STAT_1 ... CS43130_HP_AC_STAT_2: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static const char * const pcm_spd_texts[] = { -+ "Fast", -+ "Slow", -+}; -+ -+static SOC_ENUM_SINGLE_DECL(pcm_spd_enum, CS43130_PCM_FILT_OPT, 7, -+ pcm_spd_texts); -+ -+static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0); -+ -+static const struct snd_kcontrol_new cs43130_controls[] = { -+ SOC_DOUBLE_R_TLV("Master Playback Volume", CS43130_PCM_VOL_B, -+ CS43130_PCM_VOL_A, 0, 255, 1, master_tlv), -+ SOC_DOUBLE("Master Playback Switch", CS43130_PCM_PATH_CTL_1, -+ 0, 1, 1, 1), -+ SOC_DOUBLE_R_TLV("Digital Playback Volume", CS43130_DSD_VOL_B, -+ CS43130_DSD_VOL_A, 0, 255, 1, master_tlv), -+ SOC_DOUBLE("Digital Playback Switch", CS43130_DSD_PATH_CTL_1, -+ 0, 1, 1, 1), -+ SOC_SINGLE("HV_Enable", CS43130_HP_OUT_CTL_1, 0, 1, 0), -+ SOC_ENUM("PCM Filter Speed", pcm_spd_enum), -+ SOC_SINGLE("PCM Phase Compensation", CS43130_PCM_FILT_OPT, 6, 1, 0), -+ SOC_SINGLE("PCM Nonoversample Emulate", CS43130_PCM_FILT_OPT, 5, 1, 0), -+ SOC_SINGLE("PCM High-pass Filter", CS43130_PCM_FILT_OPT, 1, 1, 0), -+ SOC_SINGLE("PCM De-emphasis Filter", CS43130_PCM_FILT_OPT, 0, 1, 0), -+}; -+ -+static bool cs43130_readable_register(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case CS43130_DEVID_AB ... CS43130_SYS_CLK_CTL_1: -+ case CS43130_SP_SRATE ... CS43130_PAD_INT_CFG: -+ case CS43130_PWDN_CTL: -+ case CS43130_CRYSTAL_SET: -+ case CS43130_PLL_SET_1 ... CS43130_PLL_SET_5: -+ case CS43130_PLL_SET_6: -+ case CS43130_PLL_SET_7: -+ case CS43130_PLL_SET_8: -+ case CS43130_PLL_SET_9: -+ case CS43130_PLL_SET_10: -+ case CS43130_CLKOUT_CTL: -+ case CS43130_ASP_NUM_1 ... CS43130_ASP_FRAME_CONF: -+ case CS43130_XSP_NUM_1 ... CS43130_XSP_FRAME_CONF: -+ case CS43130_ASP_CH_1_LOC: -+ case CS43130_ASP_CH_2_LOC: -+ case CS43130_ASP_CH_1_SZ_EN: -+ case CS43130_ASP_CH_2_SZ_EN: -+ case CS43130_XSP_CH_1_LOC: -+ case CS43130_XSP_CH_2_LOC: -+ case CS43130_XSP_CH_1_SZ_EN: -+ case CS43130_XSP_CH_2_SZ_EN: -+ case CS43130_DSD_VOL_B ... CS43130_DSD_PATH_CTL_3: -+ case CS43130_HP_OUT_CTL_1: -+ case CS43130_PCM_FILT_OPT ... CS43130_PCM_PATH_CTL_2: -+ case CS43130_CLASS_H_CTL: -+ case CS43130_HP_DETECT: -+ case CS43130_HP_STATUS: -+ case CS43130_HP_LOAD_1: -+ case CS43130_HP_MEAS_LOAD_1: -+ case CS43130_HP_MEAS_LOAD_2: -+ case CS43130_HP_DC_STAT_1: -+ case CS43130_HP_DC_STAT_2: -+ case CS43130_HP_AC_STAT_1: -+ case CS43130_HP_AC_STAT_2: -+ case CS43130_HP_LOAD_STAT: -+ case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5: -+ case CS43130_INT_MASK_1 ... CS43130_INT_MASK_5: -+ return true; -+ default: -+ return false; -+ } -+} -+static bool cs43130_precious_register(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5: -+ return true; -+ default: -+ return false; -+ } -+} -+static int cs43130_pcm_pdn(struct snd_soc_component *component) -+{ -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ int ret; -+ unsigned int reg, pdn_int; -+ -+ regmap_write(cs43130->regmap, CS43130_DSD_PATH_CTL_2, 0x02); -+ regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, -+ CS43130_PDN_DONE_INT_MASK, 0); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT); -+ usleep_range(10, 50); -+ ret = regmap_read(cs43130->regmap, CS43130_INT_STATUS_1, ®); -+ pdn_int = reg & 0xFE; -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_ASP_MASK, 1 << CS43130_PDN_ASP_SHIFT); -+ return 0; -+ -+} -+static int cs43130_pwr_up_asp_dac(struct snd_soc_component *component) -+{ -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ -+ regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG, -+ CS43130_ASP_3ST_MASK, 0); -+ regmap_write(cs43130->regmap, CS43130_DXD1, 0x99); -+ regmap_write(cs43130->regmap, CS43130_DXD13, 0x20); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_ASP_MASK, 0); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_HP_MASK, 0); -+ usleep_range(10000, 12000); -+ regmap_write(cs43130->regmap, CS43130_DXD1, 0x00); -+ regmap_write(cs43130->regmap, CS43130_DXD13, 0x00); -+ return 0; -+} -+static int cs43130_change_clksrc(struct snd_soc_component *component, -+ enum cs43130_mclk_src_sel src) -+{ -+ int ret; -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ int mclk_int_decoded; -+ -+ if (src == cs43130->mclk_int_src) { -+ /* clk source has not changed */ -+ return 0; -+ } -+ switch (cs43130->mclk_int) { -+ case CS43130_MCLK_22M: -+ mclk_int_decoded = CS43130_MCLK_22P5; -+ break; -+ case CS43130_MCLK_24M: -+ mclk_int_decoded = CS43130_MCLK_24P5; -+ break; -+ default: -+ dev_err(component->dev, "Invalid MCLK INT freq: %u\n", -+ cs43130->mclk_int); -+ return -EINVAL; -+ } -+ -+ switch (src) { -+ case CS43130_MCLK_SRC_EXT: -+ cs43130->pll_bypass = true; -+ cs43130->mclk_int_src = CS43130_MCLK_SRC_EXT; -+ if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) { -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_XTAL_MASK, -+ 1 << CS43130_PDN_XTAL_SHIFT); -+ } else { -+ reinit_completion(&cs43130->xtal_rdy); -+ regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, -+ CS43130_XTAL_RDY_INT_MASK, 0); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_XTAL_MASK, 0); -+ ret = wait_for_completion_timeout(&cs43130->xtal_rdy, -+ msecs_to_jiffies(100)); -+ regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, -+ CS43130_XTAL_RDY_INT_MASK, -+ 1 << CS43130_XTAL_RDY_INT_SHIFT); -+ if (ret == 0) { -+ dev_err(component->dev, "Timeout waiting for XTAL_READY interrupt\n"); -+ return -ETIMEDOUT; -+ } -+ } -+ regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1, -+ CS43130_MCLK_SRC_SEL_MASK, -+ src << CS43130_MCLK_SRC_SEL_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1, -+ CS43130_MCLK_INT_MASK, -+ mclk_int_decoded << CS43130_MCLK_INT_SHIFT); -+ usleep_range(150, 200); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_PLL_MASK, -+ 1 << CS43130_PDN_PLL_SHIFT); -+ break; -+ case CS43130_MCLK_SRC_RCO: -+ cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO; -+ -+ regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1, -+ CS43130_MCLK_SRC_SEL_MASK, -+ src << CS43130_MCLK_SRC_SEL_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1, -+ CS43130_MCLK_INT_MASK, -+ CS43130_MCLK_22P5 << CS43130_MCLK_INT_SHIFT); -+ usleep_range(150, 200); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_XTAL_MASK, -+ 1 << CS43130_PDN_XTAL_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_PLL_MASK, -+ 1 << CS43130_PDN_PLL_SHIFT); -+ break; -+ default: -+ dev_err(component->dev, "Invalid MCLK source value\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+static const struct cs43130_bitwidth_map cs43130_bitwidth_table[] = { -+ {8, CS43130_SP_BIT_SIZE_8, CS43130_CH_BIT_SIZE_8}, -+ {16, CS43130_SP_BIT_SIZE_16, CS43130_CH_BIT_SIZE_16}, -+ {24, CS43130_SP_BIT_SIZE_24, CS43130_CH_BIT_SIZE_24}, -+ {32, CS43130_SP_BIT_SIZE_32, CS43130_CH_BIT_SIZE_32}, -+}; -+ -+static const struct cs43130_bitwidth_map *cs43130_get_bitwidth_table( -+ unsigned int bitwidth) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(cs43130_bitwidth_table); i++) { -+ if (cs43130_bitwidth_table[i].bitwidth == bitwidth) -+ return &cs43130_bitwidth_table[i]; -+ } -+ -+ return NULL; -+} -+static int cs43130_set_bitwidth(int dai_id, unsigned int bitwidth_dai, -+ struct regmap *regmap) -+{ -+ const struct cs43130_bitwidth_map *bw_map; -+ -+ bw_map = cs43130_get_bitwidth_table(bitwidth_dai); -+ if (!bw_map) -+ return -EINVAL; -+ -+ switch (dai_id) { -+ case CS43130_ASP_PCM_DAI: -+ case CS43130_ASP_DOP_DAI: -+ regmap_update_bits(regmap, CS43130_ASP_CH_1_SZ_EN, -+ CS43130_CH_BITSIZE_MASK, bw_map->ch_bit); -+ regmap_update_bits(regmap, CS43130_ASP_CH_2_SZ_EN, -+ CS43130_CH_BITSIZE_MASK, bw_map->ch_bit); -+ regmap_update_bits(regmap, CS43130_SP_BITSIZE, -+ CS43130_ASP_BITSIZE_MASK, bw_map->sp_bit); -+ break; -+ case CS43130_XSP_DOP_DAI: -+ regmap_update_bits(regmap, CS43130_XSP_CH_1_SZ_EN, -+ CS43130_CH_BITSIZE_MASK, bw_map->ch_bit); -+ regmap_update_bits(regmap, CS43130_XSP_CH_2_SZ_EN, -+ CS43130_CH_BITSIZE_MASK, bw_map->ch_bit); -+ regmap_update_bits(regmap, CS43130_SP_BITSIZE, -+ CS43130_XSP_BITSIZE_MASK, bw_map->sp_bit << -+ CS43130_XSP_BITSIZE_SHIFT); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+static const struct cs43130_rate_map cs43130_rate_table[] = { -+ {32000, CS43130_ASP_SPRATE_32K}, -+ {44100, CS43130_ASP_SPRATE_44_1K}, -+ {48000, CS43130_ASP_SPRATE_48K}, -+ {88200, CS43130_ASP_SPRATE_88_2K}, -+ {96000, CS43130_ASP_SPRATE_96K}, -+ {176400, CS43130_ASP_SPRATE_176_4K}, -+ {192000, CS43130_ASP_SPRATE_192K}, -+ {352800, CS43130_ASP_SPRATE_352_8K}, -+ {384000, CS43130_ASP_SPRATE_384K}, -+}; -+ -+static const struct cs43130_rate_map *cs43130_get_rate_table(int fs) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(cs43130_rate_table); i++) { -+ if (cs43130_rate_table[i].fs == fs) -+ return &cs43130_rate_table[i]; -+ } -+ -+ return NULL; -+} -+ -+static const struct cs43130_clk_gen *cs43130_get_clk_gen(int mclk_int, int fs, -+ const struct cs43130_clk_gen *clk_gen_table, int len_clk_gen_table) -+{ -+ int i; -+ -+ for (i = 0; i < len_clk_gen_table; i++) { -+ if (clk_gen_table[i].mclk_int == mclk_int && -+ clk_gen_table[i].fs == fs) -+ return &clk_gen_table[i]; -+ } -+ return NULL; -+} -+ -+static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk, -+ struct snd_pcm_hw_params *params, -+ struct cs43130_priv *cs43130) -+{ -+ u16 frm_size; -+ u16 hi_size; -+ u8 frm_delay; -+ u8 frm_phase; -+ u8 frm_data; -+ u8 sclk_edge; -+ u8 lrck_edge; -+ u8 clk_data; -+ u8 loc_ch1; -+ u8 loc_ch2; -+ u8 dai_mode_val; -+ const struct cs43130_clk_gen *clk_gen; -+ -+ switch (cs43130->dais[dai_id].dai_format) { -+ case SND_SOC_DAIFMT_I2S: -+ hi_size = bitwidth_sclk; -+ frm_delay = 2; -+ frm_phase = 0; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ hi_size = bitwidth_sclk; -+ frm_delay = 2; -+ frm_phase = 1; -+ break; -+ case SND_SOC_DAIFMT_DSP_A: -+ hi_size = 1; -+ frm_delay = 2; -+ frm_phase = 1; -+ break; -+ case SND_SOC_DAIFMT_DSP_B: -+ hi_size = 1; -+ frm_delay = 0; -+ frm_phase = 1; -+ break; -+ default: -+ return -EINVAL; -+ } -+ switch (cs43130->dais[dai_id].dai_mode) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ dai_mode_val = 0; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ dai_mode_val = 1; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ frm_size = bitwidth_sclk * params_channels(params); -+ sclk_edge = 1; -+ lrck_edge = 0; -+ loc_ch1 = 0; -+ loc_ch2 = bitwidth_sclk * (params_channels(params) - 1); -+ -+ frm_data = frm_delay & CS43130_SP_FSD_MASK; -+ frm_data |= (frm_phase << CS43130_SP_STP_SHIFT) & CS43130_SP_STP_MASK; -+ -+ clk_data = lrck_edge & CS43130_SP_LCPOL_IN_MASK; -+ clk_data |= (lrck_edge << CS43130_SP_LCPOL_OUT_SHIFT) & -+ CS43130_SP_LCPOL_OUT_MASK; -+ clk_data |= (sclk_edge << CS43130_SP_SCPOL_IN_SHIFT) & -+ CS43130_SP_SCPOL_IN_MASK; -+ clk_data |= (sclk_edge << CS43130_SP_SCPOL_OUT_SHIFT) & -+ CS43130_SP_SCPOL_OUT_MASK; -+ clk_data |= (dai_mode_val << CS43130_SP_MODE_SHIFT) & -+ CS43130_SP_MODE_MASK; -+ switch (dai_id) { -+ case CS43130_ASP_PCM_DAI: -+ case CS43130_ASP_DOP_DAI: -+ regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_1, -+ CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >> -+ CS43130_SP_LCPR_LSB_DATA_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_2, -+ CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >> -+ CS43130_SP_LCPR_MSB_DATA_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_1, -+ CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >> -+ CS43130_SP_LCHI_LSB_DATA_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_2, -+ CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >> -+ CS43130_SP_LCHI_MSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_ASP_FRAME_CONF, frm_data); -+ regmap_write(cs43130->regmap, CS43130_ASP_CH_1_LOC, loc_ch1); -+ regmap_write(cs43130->regmap, CS43130_ASP_CH_2_LOC, loc_ch2); -+ regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_1_SZ_EN, -+ CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_2_SZ_EN, -+ CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_ASP_CLOCK_CONF, clk_data); -+ break; -+ case CS43130_XSP_DOP_DAI: -+ regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_1, -+ CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >> -+ CS43130_SP_LCPR_LSB_DATA_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_2, -+ CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >> -+ CS43130_SP_LCPR_MSB_DATA_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_1, -+ CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >> -+ CS43130_SP_LCHI_LSB_DATA_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_2, -+ CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >> -+ CS43130_SP_LCHI_MSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_XSP_FRAME_CONF, frm_data); -+ regmap_write(cs43130->regmap, CS43130_XSP_CH_1_LOC, loc_ch1); -+ regmap_write(cs43130->regmap, CS43130_XSP_CH_2_LOC, loc_ch2); -+ regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_1_SZ_EN, -+ CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_2_SZ_EN, -+ CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_XSP_CLOCK_CONF, clk_data); -+ break; -+ default: -+ return -EINVAL; -+ } -+ switch (frm_size) { -+ case 16: -+ clk_gen = cs43130_get_clk_gen(cs43130->mclk_int, -+ params_rate(params), -+ cs43130_16_clk_gen, -+ ARRAY_SIZE(cs43130_16_clk_gen)); -+ break; -+ case 32: -+ clk_gen = cs43130_get_clk_gen(cs43130->mclk_int, -+ params_rate(params), -+ cs43130_32_clk_gen, -+ ARRAY_SIZE(cs43130_32_clk_gen)); -+ break; -+ case 48: -+ clk_gen = cs43130_get_clk_gen(cs43130->mclk_int, -+ params_rate(params), -+ cs43130_48_clk_gen, -+ ARRAY_SIZE(cs43130_48_clk_gen)); -+ break; -+ case 64: -+ clk_gen = cs43130_get_clk_gen(cs43130->mclk_int, -+ params_rate(params), -+ cs43130_64_clk_gen, -+ ARRAY_SIZE(cs43130_64_clk_gen)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (!clk_gen) -+ return -EINVAL; -+ switch (dai_id) { -+ case CS43130_ASP_PCM_DAI: -+ case CS43130_ASP_DOP_DAI: -+ regmap_write(cs43130->regmap, CS43130_ASP_DEN_1, -+ (clk_gen->den & CS43130_SP_M_LSB_DATA_MASK) >> -+ CS43130_SP_M_LSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_ASP_DEN_2, -+ (clk_gen->den & CS43130_SP_M_MSB_DATA_MASK) >> -+ CS43130_SP_M_MSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_ASP_NUM_1, -+ (clk_gen->num & CS43130_SP_N_LSB_DATA_MASK) >> -+ CS43130_SP_N_LSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_ASP_NUM_2, -+ (clk_gen->num & CS43130_SP_N_MSB_DATA_MASK) >> -+ CS43130_SP_N_MSB_DATA_SHIFT); -+ break; -+ case CS43130_XSP_DOP_DAI: -+ regmap_write(cs43130->regmap, CS43130_XSP_DEN_1, -+ (clk_gen->den & CS43130_SP_M_LSB_DATA_MASK) >> -+ CS43130_SP_M_LSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_XSP_DEN_2, -+ (clk_gen->den & CS43130_SP_M_MSB_DATA_MASK) >> -+ CS43130_SP_M_MSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_XSP_NUM_1, -+ (clk_gen->num & CS43130_SP_N_LSB_DATA_MASK) >> -+ CS43130_SP_N_LSB_DATA_SHIFT); -+ regmap_write(cs43130->regmap, CS43130_XSP_NUM_2, -+ (clk_gen->num & CS43130_SP_N_MSB_DATA_MASK) >> -+ CS43130_SP_N_MSB_DATA_SHIFT); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static int cs43130_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_component *component = dai->component; -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ const struct cs43130_rate_map *rate_map; -+ unsigned int sclk = cs43130->dais[dai->id].sclk; -+ unsigned int bitwidth_sclk; -+ unsigned int bitwidth_dai = (unsigned int)(params_width(params)); -+ unsigned int dop_rate = (unsigned int)(params_rate(params)); -+ unsigned int required_clk, ret; -+ u8 dsd_speed; -+ -+ cs43130->pll_bypass = true; -+ cs43130_pcm_pdn(component); -+ mutex_lock(&cs43130->clk_mutex); -+ if (!cs43130->clk_req) { -+ /* no DAI is currently using clk */ -+ if (!(CS43130_MCLK_22M % params_rate(params))) { -+ required_clk = CS43130_MCLK_22M; -+ cs43130->mclk_int = CS43130_MCLK_22M; -+ gpiod_set_value_cansleep(snd_allo_clk44gpio, 1); -+ gpiod_set_value_cansleep(snd_allo_clk48gpio, 0); -+ usleep_range(13500, 14000); -+ } else { -+ required_clk = CS43130_MCLK_24M; -+ cs43130->mclk_int = CS43130_MCLK_24M; -+ gpiod_set_value_cansleep(snd_allo_clk48gpio, 1); -+ gpiod_set_value_cansleep(snd_allo_clk44gpio, 0); -+ usleep_range(13500, 14000); -+ } -+ if (cs43130->pll_bypass) -+ cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT); -+ else -+ cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL); -+ } -+ -+ cs43130->clk_req++; -+ mutex_unlock(&cs43130->clk_mutex); -+ -+ switch (dai->id) { -+ case CS43130_ASP_DOP_DAI: -+ case CS43130_XSP_DOP_DAI: -+ /* DoP bitwidth is always 24-bit */ -+ bitwidth_dai = 24; -+ sclk = params_rate(params) * bitwidth_dai * -+ params_channels(params); -+ -+ switch (params_rate(params)) { -+ case 176400: -+ dsd_speed = 0; -+ break; -+ case 352800: -+ dsd_speed = 1; -+ break; -+ default: -+ dev_err(component->dev, "Rate(%u) not supported\n", -+ params_rate(params)); -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_SPEED_MASK, -+ dsd_speed << CS43130_DSD_SPEED_SHIFT); -+ break; -+ case CS43130_ASP_PCM_DAI: -+ rate_map = cs43130_get_rate_table(params_rate(params)); -+ if (!rate_map) -+ return -EINVAL; -+ -+ regmap_write(cs43130->regmap, CS43130_SP_SRATE, rate_map->val); -+ if ((dop_rate == 176400) && (bitwidth_dai == 24)) { -+ dsd_speed = 0; -+ regmap_update_bits(cs43130->regmap, -+ CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_SPEED_MASK, -+ dsd_speed << CS43130_DSD_SPEED_SHIFT); -+ regmap_update_bits(cs43130->regmap, -+ CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_SRC_MASK, -+ CS43130_DSD_SRC_ASP << -+ CS43130_DSD_SRC_SHIFT); -+ regmap_update_bits(cs43130->regmap, -+ CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_EN_MASK, 0x01 << -+ CS43130_DSD_EN_SHIFT); -+ } -+ break; -+ default: -+ dev_err(component->dev, "Invalid DAI (%d)\n", dai->id); -+ return -EINVAL; -+ } -+ -+ switch (dai->id) { -+ case CS43130_ASP_DOP_DAI: -+ regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_ASP << -+ CS43130_DSD_SRC_SHIFT); -+ regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_EN_MASK, 0x01 << -+ CS43130_DSD_EN_SHIFT); -+ break; -+ case CS43130_XSP_DOP_DAI: -+ regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2, -+ CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_XSP << -+ CS43130_DSD_SRC_SHIFT); -+ break; -+ } -+ if (!sclk && cs43130->dais[dai->id].dai_mode == -+ SND_SOC_DAIFMT_CBM_CFM) { -+ /* Calculate SCLK in master mode if unassigned */ -+ sclk = params_rate(params) * bitwidth_dai * -+ params_channels(params); -+ } -+ if (!sclk) { -+ /* at this point, SCLK must be set */ -+ dev_err(component->dev, "SCLK freq is not set\n"); -+ return -EINVAL; -+ } -+ -+ bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params); -+ if (bitwidth_sclk < bitwidth_dai) { -+ dev_err(component->dev, "Format not supported: SCLK freq is too low\n"); -+ return -EINVAL; -+ } -+ -+ dev_dbg(component->dev, -+ "sclk = %u, fs = %d, bitwidth_dai = %u\n", -+ sclk, params_rate(params), bitwidth_dai); -+ -+ dev_dbg(component->dev, -+ "bitwidth_sclk = %u, num_ch = %u\n", -+ bitwidth_sclk, params_channels(params)); -+ -+ cs43130_set_bitwidth(dai->id, bitwidth_dai, cs43130->regmap); -+ cs43130_set_sp_fmt(dai->id, bitwidth_sclk, params, cs43130); -+ ret = cs43130_pwr_up_asp_dac(component); -+ return 0; -+} -+ -+static int cs43130_hw_free(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_component *component = dai->component; -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ -+ mutex_lock(&cs43130->clk_mutex); -+ cs43130->clk_req--; -+ if (!cs43130->clk_req) { -+ /* no DAI is currently using clk */ -+ cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO); -+ cs43130_pcm_pdn(component); -+ } -+ mutex_unlock(&cs43130->clk_mutex); -+ -+ return 0; -+} -+ -+static const unsigned int cs43130_asp_src_rates[] = { -+ 32000, 44100, 48000, 88200, 96000, 176400, 192000 -+}; -+ -+static const struct snd_pcm_hw_constraint_list cs43130_asp_constraints = { -+ .count = ARRAY_SIZE(cs43130_asp_src_rates), -+ .list = cs43130_asp_src_rates, -+}; -+ -+static int cs43130_pcm_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ return snd_pcm_hw_constraint_list(substream->runtime, 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &cs43130_asp_constraints); -+} -+ -+static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -+{ -+ struct snd_soc_component *component = codec_dai->component; -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM; -+ break; -+ default: -+ dev_err(component->dev, "unsupported mode\n"); -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_I2S; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_LEFT_J; -+ break; -+ default: -+ dev_err(component->dev, -+ "unsupported audio format\n"); -+ return -EINVAL; -+ } -+ -+ dev_dbg(component->dev, "dai_id = %d, dai_mode = %u, dai_format = %u\n", -+ codec_dai->id, -+ cs43130->dais[codec_dai->id].dai_mode, -+ cs43130->dais[codec_dai->id].dai_format); -+ -+ return 0; -+} -+ -+static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai, -+ int clk_id, unsigned int freq, int dir) -+{ -+ struct snd_soc_component *component = codec_dai->component; -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ -+ cs43130->dais[codec_dai->id].sclk = freq; -+ dev_dbg(component->dev, "dai_id = %d, sclk = %u\n", codec_dai->id, -+ cs43130->dais[codec_dai->id].sclk); -+ -+ return 0; -+} -+ -+static int cs43130_component_set_sysclk(struct snd_soc_component *component, -+ int clk_id, int source, -+ unsigned int freq, int dir) -+{ -+ struct cs43130_priv *cs43130 = -+ snd_soc_component_get_drvdata(component); -+ -+ dev_dbg(component->dev, "clk_id = %d, source = %d, freq = %d, dir = %d\n", -+ clk_id, source, freq, dir); -+ -+ switch (freq) { -+ case CS43130_MCLK_22M: -+ case CS43130_MCLK_24M: -+ cs43130->mclk = freq; -+ break; -+ default: -+ dev_err(component->dev, "Invalid MCLK INT freq: %u\n", freq); -+ return -EINVAL; -+ } -+ -+ if (source == CS43130_MCLK_SRC_EXT) { -+ cs43130->pll_bypass = true; -+ } else { -+ dev_err(component->dev, "Invalid MCLK source\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = { -+ 24, -+ 43, -+ 93, -+ 200, -+ 431, -+ 928, -+ 2000, -+ 4309, -+ 9283, -+ 20000, -+}; -+static const struct snd_soc_dai_ops cs43130_dai_ops = { -+ .startup = cs43130_pcm_startup, -+ .hw_params = cs43130_hw_params, -+ .hw_free = cs43130_hw_free, -+ .set_sysclk = cs43130_set_sysclk, -+ .set_fmt = cs43130_pcm_set_fmt, -+}; -+ -+static struct snd_soc_dai_driver cs43130_codec_dai = { -+ .name = "allo-cs43130", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_CONTINUOUS, -+ .rate_min = 44100, -+ .rate_max = 192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE -+ -+ }, -+ .ops = &cs43130_dai_ops, -+}; -+ -+static struct snd_soc_component_driver cs43130_component_driver = { -+ .idle_bias_on = true, -+ .controls = cs43130_controls, -+ .num_controls = ARRAY_SIZE(cs43130_controls), -+ .set_sysclk = cs43130_component_set_sysclk, -+ .idle_bias_on = 1, -+ .use_pmdown_time = 1, -+ .endianness = 1, -+ .non_legacy_dai_naming = 1, -+}; -+ -+static const struct regmap_config cs43130_regmap = { -+ .reg_bits = 24, -+ .pad_bits = 8, -+ .val_bits = 8, -+ -+ .max_register = CS43130_LASTREG, -+ .reg_defaults = cs43130_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(cs43130_reg_defaults), -+ .readable_reg = cs43130_readable_register, -+ .precious_reg = cs43130_precious_register, -+ .volatile_reg = cs43130_volatile_register, -+ .cache_type = REGCACHE_RBTREE, -+ /* needed for regcache_sync */ -+ .use_single_read = true, -+ .use_single_write = true, -+}; -+ -+static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = { -+ 50, -+ 120, -+}; -+ -+static int cs43130_handle_device_data(struct i2c_client *i2c_client, -+ struct cs43130_priv *cs43130) -+{ -+ struct device_node *np = i2c_client->dev.of_node; -+ unsigned int val; -+ int i; -+ -+ if (of_property_read_u32(np, "cirrus,xtal-ibias", &val) < 0) { -+ /* Crystal is unused. System clock is used for external MCLK */ -+ cs43130->xtal_ibias = CS43130_XTAL_UNUSED; -+ return 0; -+ } -+ -+ switch (val) { -+ case 1: -+ cs43130->xtal_ibias = CS43130_XTAL_IBIAS_7_5UA; -+ break; -+ case 2: -+ cs43130->xtal_ibias = CS43130_XTAL_IBIAS_12_5UA; -+ break; -+ case 3: -+ cs43130->xtal_ibias = CS43130_XTAL_IBIAS_15UA; -+ break; -+ default: -+ dev_err(&i2c_client->dev, -+ "Invalid cirrus,xtal-ibias value: %d\n", val); -+ return -EINVAL; -+ } -+ -+ cs43130->dc_meas = of_property_read_bool(np, "cirrus,dc-measure"); -+ cs43130->ac_meas = of_property_read_bool(np, "cirrus,ac-measure"); -+ -+ if (of_property_read_u16_array(np, "cirrus,ac-freq", cs43130->ac_freq, -+ CS43130_AC_FREQ) < 0) { -+ for (i = 0; i < CS43130_AC_FREQ; i++) -+ cs43130->ac_freq[i] = cs43130_ac_freq[i]; -+ } -+ -+ if (of_property_read_u16_array(np, "cirrus,dc-threshold", -+ cs43130->dc_threshold, -+ CS43130_DC_THRESHOLD) < 0) { -+ for (i = 0; i < CS43130_DC_THRESHOLD; i++) -+ cs43130->dc_threshold[i] = cs43130_dc_threshold[i]; -+ } -+ -+ return 0; -+} -+ -+ -+static int allo_cs43130_component_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ struct regmap *regmap; -+ struct regmap_config config = cs43130_regmap; -+ struct device *dev = &i2c->dev; -+ struct cs43130_priv *cs43130; -+ unsigned int devid = 0; -+ unsigned int reg; -+ int ret; -+ -+ regmap = devm_regmap_init_i2c(i2c, &config); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ cs43130 = devm_kzalloc(dev, sizeof(struct cs43130_priv), -+ GFP_KERNEL); -+ if (!cs43130) -+ return -ENOMEM; -+ -+ dev_set_drvdata(dev, cs43130); -+ cs43130->regmap = regmap; -+ -+ if (i2c->dev.of_node) { -+ ret = cs43130_handle_device_data(i2c, cs43130); -+ if (ret != 0) -+ return ret; -+ } -+ usleep_range(2000, 2050); -+ -+ ret = regmap_read(cs43130->regmap, CS43130_DEVID_AB, ®); -+ devid = (reg & 0xFF) << 12; -+ ret = regmap_read(cs43130->regmap, CS43130_DEVID_CD, ®); -+ devid |= (reg & 0xFF) << 4; -+ ret = regmap_read(cs43130->regmap, CS43130_DEVID_E, ®); -+ devid |= (reg & 0xF0) >> 4; -+ if (devid != CS43198_CHIP_ID) { -+ dev_err(dev, "Failed to read Chip or wrong Chip id: %d\n", ret); -+ return ret; -+ } -+ -+ cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO; -+ msleep(20); -+ -+ ret = snd_soc_register_component(dev, &cs43130_component_driver, -+ &cs43130_codec_dai, 1); -+ if (ret != 0) { -+ dev_err(dev, "failed to register codec: %d\n", ret); -+ return ret; -+ } -+ regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG, -+ CS43130_ASP_3ST_MASK, 0); -+ regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG, -+ CS43130_XSP_3ST_MASK, 1); -+ regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, -+ CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT); -+ msleep(20); -+ regmap_write(cs43130->regmap, CS43130_CLASS_H_CTL, 0x06); -+ snd_allo_clk44gpio = devm_gpiod_get(dev, "clock44", GPIOD_OUT_HIGH); -+ if (IS_ERR(snd_allo_clk44gpio)) -+ dev_err(dev, "devm_gpiod_get() failed\n"); -+ -+ snd_allo_clk48gpio = devm_gpiod_get(dev, "clock48", GPIOD_OUT_LOW); -+ if (IS_ERR(snd_allo_clk48gpio)) -+ dev_err(dev, "devm_gpiod_get() failed\n"); -+ -+ return 0; -+} -+ -+static int allo_cs43130_component_remove(struct i2c_client *i2c) -+{ -+ snd_soc_unregister_component(&i2c->dev); -+ return 0; -+} -+ -+static const struct i2c_device_id allo_cs43130_component_id[] = { -+ { "allo-cs43198", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, allo_cs43130_component_id); -+ -+static const struct of_device_id allo_cs43130_codec_of_match[] = { -+ { .compatible = "allo,allo-cs43198", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, allo_cs43130_codec_of_match); -+ -+static struct i2c_driver allo_cs43130_component_driver = { -+ .probe = allo_cs43130_component_probe, -+ .remove = allo_cs43130_component_remove, -+ .id_table = allo_cs43130_component_id, -+ .driver = { -+ .name = "allo-cs43198", -+ .of_match_table = allo_cs43130_codec_of_match, -+ }, -+}; -+ -+module_i2c_driver(allo_cs43130_component_driver); -+ -+MODULE_DESCRIPTION("ASoC Allo Boss2 Codec Driver"); -+MODULE_AUTHOR("Sudeepkumar "); -+MODULE_LICENSE("GPL v2");