armbian_build/patch/kernel/archive/spacemit-6.1/058-update-to-v1.0.5.patch
Patrick Yavitz c5be5a8537 SpacemiT: BananaPi F3: update to BL v1.0.8
Legacy: use TAG instead of BRANCH (gives us more control)
Current: update DTS files
Current: add needed patches up to v1.0.8
Fixup bluetooth node and disable by default (half broke anyway)
Misc fixups to bananapif3.wip and spacemit.conf file

Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
2024-07-17 03:30:39 -04:00

5005 lines
168 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Sat, 29 Jun 2024 08:10:12 -0400
Subject: update to v1.0.5
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: James Deng <james.deng@spacemit.com>
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
arch/riscv/boot/dts/spacemit/lcd/lcd_jd9365da_mipi_1280x800.dtsi | 66 +
arch/riscv/boot/dts/spacemit/lcd/lcd_orisetech_ota7290b_mipi.dtsi | 66 +
drivers/crypto/spacemit/spacemit-ce-glue.c | 24 +-
drivers/gpio/gpio-k1x.c | 6 +
drivers/gpu/drm/spacemit/dpu/dpu_saturn.c | 2 +-
drivers/gpu/drm/spacemit/lt8911exb.c | 62 +-
drivers/gpu/drm/spacemit/lt9711.c | 104 +-
drivers/gpu/drm/spacemit/spacemit_dpu.c | 99 +-
drivers/gpu/drm/spacemit/spacemit_dsi.c | 30 +-
drivers/gpu/drm/spacemit/spacemit_dsi.h | 20 +-
drivers/gpu/drm/spacemit/spacemit_hdmi.c | 60 +-
drivers/nvme/host/pci.c | 7 +
sound/soc/codecs/Kconfig | 9 +
sound/soc/codecs/Makefile | 4 +
sound/soc/codecs/es7210.c | 1993 ++++++++++
sound/soc/codecs/es7210.h | 140 +
sound/soc/codecs/es7210_config.c | 280 ++
sound/soc/codecs/es7210_config.h | 259 ++
sound/soc/codecs/es7210_snd_controls.c | 174 +
sound/soc/codecs/es8156.c | 872 ++++
sound/soc/codecs/es8156.h | 85 +
sound/soc/spacemit/spacemit-snd-pcm-dma.c | 4 +-
22 files changed, 4162 insertions(+), 204 deletions(-)
diff --git a/arch/riscv/boot/dts/spacemit/lcd/lcd_jd9365da_mipi_1280x800.dtsi b/arch/riscv/boot/dts/spacemit/lcd/lcd_jd9365da_mipi_1280x800.dtsi
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/arch/riscv/boot/dts/spacemit/lcd/lcd_jd9365da_mipi_1280x800.dtsi
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ { lcds: lcds {
+ lcd_jd9365da_mipi_1280x800: lcd_jd9365da_mipi_1280x800 {
+ dsi-work-mode = <1>; /* video burst mode*/
+ dsi-lane-number = <4>;
+ dsi-color-format = "rgb888";
+ width-mm = <142>;
+ height-mm = <228>;
+ use-dcs-write;
+
+ /*mipi info*/
+ height = <1280>;
+ width = <800>;
+ hfp = <16>;
+ hbp = <48>;
+ hsync = <16>;
+ vfp = <8>;
+ vbp = <4>;
+ vsync = <4>;
+ fps = <60>;
+ work-mode = <0>;
+ rgb-mode = <3>;
+ lane-number = <4>;
+ phy-bit-clock = <480000000>;
+ //phy-esc-clock = <76800000>;
+ split-enable = <0>;
+ eotp-enable = <0>;
+ burst-mode = <2>;
+ esd-check-enable = <0>;
+
+ /* DSI_CMD, DSI_MODE, timeout, len, cmd */
+ initial-command = [
+ 39 01 F0 01 11
+ 39 01 28 01 29
+ ];
+ sleep-in-command = [
+ 39 01 78 01 28
+ 39 01 78 01 10
+ ];
+ sleep-out-command = [
+ 39 01 96 01 11
+ 39 01 32 01 29
+ ];
+ read-id-command = [
+ 37 01 00 01 01
+ 14 01 00 01 04
+ ];
+
+ display-timings {
+ timing0 {
+ clock-frequency = <68430000>;
+ hactive = <800>;
+ hfront-porch = <16>;
+ hback-porch = <48>;
+ hsync-len = <16>;
+ vactive = <1280>;
+ vfront-porch = <8>;
+ vback-porch = <4>;
+ vsync-len = <4>;
+ vsync-active = <1>;
+ hsync-active = <1>;
+ };
+ };
+ };
+};};
diff --git a/arch/riscv/boot/dts/spacemit/lcd/lcd_orisetech_ota7290b_mipi.dtsi b/arch/riscv/boot/dts/spacemit/lcd/lcd_orisetech_ota7290b_mipi.dtsi
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/arch/riscv/boot/dts/spacemit/lcd/lcd_orisetech_ota7290b_mipi.dtsi
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ { lcds: lcds {
+ lcd_orisetech_ota7290b_mipi: lcd_orisetech_ota7290b_mipi {
+ dsi-work-mode = <1>; /* video burst mode*/
+ dsi-lane-number = <4>;
+ dsi-color-format = "rgb888";
+ width-mm = <135>;
+ height-mm = <217>;
+ use-dcs-write;
+
+ /*mipi info*/
+ height = <1920>;
+ width = <1200>;
+ hfp = <80>;
+ hbp = <60>;
+ hsync = <4>;
+ vfp = <35>;
+ vbp = <25>;
+ vsync = <4>;
+ fps = <55>;
+ work-mode = <0>;
+ rgb-mode = <3>;
+ lane-number = <4>;
+ phy-bit-clock = <1000000000>;
+ phy-esc-clock = <76800000>;
+ split-enable = <0>;
+ eotp-enable = <0>;
+ burst-mode = <2>;
+ esd-check-enable = <0>;
+
+ /* DSI_CMD, DSI_MODE, timeout, len, cmd */
+ initial-command = [
+ 39 01 F0 01 11
+ 39 01 28 01 29
+ ];
+ sleep-in-command = [
+ 39 01 78 01 28
+ 39 01 78 01 10
+ ];
+ sleep-out-command = [
+ 39 01 96 01 11
+ 39 01 32 01 29
+ ];
+ read-id-command = [
+ 37 01 00 01 05
+ 14 01 00 05 fb fc fd fe ff
+ ];
+
+ display-timings {
+ timing0 {
+ clock-frequency = <143000000>;
+ hactive = <1200>;
+ hfront-porch = <80>;
+ hback-porch = <60>;
+ hsync-len = <4>;
+ vactive = <1920>;
+ vfront-porch = <35>;
+ vback-porch = <25>;
+ vsync-len = <4>;
+ vsync-active = <0>;
+ hsync-active = <0>;
+ };
+ };
+ };
+};};
diff --git a/drivers/crypto/spacemit/spacemit-ce-glue.c b/drivers/crypto/spacemit/spacemit-ce-glue.c
index 111111111111..222222222222 100644
--- a/drivers/crypto/spacemit/spacemit-ce-glue.c
+++ b/drivers/crypto/spacemit/spacemit-ce-glue.c
@@ -65,10 +65,10 @@ static int ecb_encrypt(struct skcipher_request *req)
page_len = singal_len = total_len;
if(singal_len % AES_BLOCK_SIZE)
- singal_len = (total_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
+ singal_len = (page_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
map_addr = in_buffer;
- for(sg = start_srcsg,len = 0;len<singal_len;len += sg->length)
+ for(sg = start_srcsg,len = 0;len < page_len;len += sg->length)
{
if(len != 0)
sg = sg_next(sg);
@@ -126,10 +126,10 @@ static int ecb_decrypt(struct skcipher_request *req)
else
page_len = singal_len = total_len;
if(singal_len % AES_BLOCK_SIZE)
- singal_len = (total_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
+ singal_len = (page_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
map_addr = in_buffer;
- for(sg = start_srcsg,len = 0;len<page_len;len += sg->length)
+ for(sg = start_srcsg,len = 0;len < page_len;len += sg->length)
{
if(len != 0)
sg = sg_next(sg);
@@ -187,10 +187,10 @@ static int cbc_encrypt(struct skcipher_request *req)
page_len = singal_len = total_len;
if(singal_len % AES_BLOCK_SIZE)
- singal_len = (total_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
+ singal_len = (page_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
map_addr = in_buffer;
- for(sg = start_srcsg,len = 0;len<singal_len;len += sg->length)
+ for(sg = start_srcsg,len = 0;len < page_len;len += sg->length)
{
if(len != 0)
sg = sg_next(sg);
@@ -248,10 +248,10 @@ static int cbc_decrypt(struct skcipher_request *req)
else
page_len = singal_len = total_len;
if(singal_len % AES_BLOCK_SIZE)
- singal_len = (total_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
+ singal_len = (page_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
map_addr = in_buffer;
- for(sg = start_srcsg,len = 0;len<page_len;len += sg->length)
+ for(sg = start_srcsg,len = 0;len < page_len;len += sg->length)
{
if(len != 0)
sg = sg_next(sg);
@@ -310,10 +310,10 @@ static int xts_encrypt(struct skcipher_request *req)
page_len = singal_len = total_len;
if(singal_len % AES_BLOCK_SIZE)
- singal_len = (total_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
+ singal_len = (page_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
map_addr = in_buffer;
- for(sg = start_srcsg,len = 0;len<singal_len;len += sg->length)
+ for(sg = start_srcsg,len = 0;len < page_len;len += sg->length)
{
if(len != 0)
sg = sg_next(sg);
@@ -372,10 +372,10 @@ static int xts_decrypt(struct skcipher_request *req)
else
page_len = singal_len = total_len;
if(singal_len % AES_BLOCK_SIZE)
- singal_len = (total_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
+ singal_len = (page_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
map_addr = in_buffer;
- for(sg = start_srcsg,len = 0;len<page_len;len += sg->length)
+ for(sg = start_srcsg,len = 0;len < page_len;len += sg->length)
{
if(len != 0)
sg = sg_next(sg);
diff --git a/drivers/gpio/gpio-k1x.c b/drivers/gpio/gpio-k1x.c
index 111111111111..222222222222 100644
--- a/drivers/gpio/gpio-k1x.c
+++ b/drivers/gpio/gpio-k1x.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
+#include <linux/pm_wakeirq.h>
#define GPLR 0x0
#define GPDR 0xc
@@ -392,6 +393,11 @@ static int k1x_gpio_probe(struct platform_device *pdev)
goto err;
}
+#ifdef CONFIG_PM
+ dev_pm_set_wake_irq(&pdev->dev, irq);
+ device_init_wakeup(&pdev->dev, true);
+#endif
+
gpiochip_add(&k1x_chip->chip);
/* clear all GPIO edge detects */
diff --git a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
+++ b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
@@ -594,7 +594,7 @@ static int dpu_enable_clocks(struct spacemit_dpu *dpu)
}
clk_val = clk_get_rate(clk_ctx->hmclk);
- DRM_INFO("get hdmi mclk=%lld\n", clk_val);
+ DRM_DEBUG("get hdmi mclk=%lld\n", clk_val);
udelay(10);
} else {
diff --git a/drivers/gpu/drm/spacemit/lt8911exb.c b/drivers/gpu/drm/spacemit/lt8911exb.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/lt8911exb.c
+++ b/drivers/gpu/drm/spacemit/lt8911exb.c
@@ -422,14 +422,14 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
}
}
- for( i = 0; i < 128; i++ ) //print edid data
- {
- if( ( i % 16 ) == 0 )
- {
- DRM_INFO( "\n" );
- }
- DRM_INFO( "%x", EDID_DATA[i] );
- }
+ // for( i = 0; i < 128; i++ ) //print edid data
+ // {
+ // if( ( i % 16 ) == 0 )
+ // {
+ // DRM_INFO( "\n" );
+ // }
+ // DRM_INFO( "%x", EDID_DATA[i] );
+ // }
EDID_Timing[hfp] = (EDID_DATA[0x41] & 0xC0) * 4 + EDID_DATA[0x3e];
@@ -991,9 +991,9 @@ void lt8911exb_reset(struct lt8911exb *lt8911exb)
}
gpiod_direction_output(lt8911exb->reset_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
+ usleep_range(50*1000, 100*1000); //100ms
gpiod_direction_output(lt8911exb->reset_gpio, 0);
- usleep_range(100*1000, 150*1000); //150ms
+ usleep_range(50*1000, 100*1000); //100ms
gpiod_direction_output(lt8911exb->reset_gpio, 1);
usleep_range(100*1000, 150*1000); //150ms
}
@@ -1154,14 +1154,11 @@ static int lt8911exb_panel_enable(struct drm_panel *panel)
DRM_INFO("%s()\n", __func__);
gpiod_direction_output(lt8911exb->enable_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
gpiod_direction_output(lt8911exb->standby_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
-
- gpiod_direction_output(lt8911exb->bl_gpio, 1);
+ usleep_range(50*1000, 100*1000); //100ms
schedule_delayed_work(&lt8911exb->init_work,
- msecs_to_jiffies(2000));
+ msecs_to_jiffies(500));
lt8911exb->init_work_pending = true;
return 0;
@@ -1174,11 +1171,9 @@ static int lt8911exb_panel_disable(struct drm_panel *panel)
DRM_INFO("%s()\n", __func__);
gpiod_direction_output(lt8911exb->bl_gpio, 0);
-
gpiod_direction_output(lt8911exb->standby_gpio, 0);
- usleep_range(100*1000, 150*1000); //150ms
gpiod_direction_output(lt8911exb->enable_gpio, 0);
- usleep_range(100*1000, 150*1000); //150ms
+ usleep_range(50*1000, 100*1000); //100ms
if (lt8911exb->init_work_pending) {
cancel_delayed_work_sync(&lt8911exb->init_work);
@@ -1249,11 +1244,7 @@ static void init_work_func(struct work_struct *work)
DRM_DEBUG(" %s() \n", __func__);
- gpiod_direction_output(lt8911exb->enable_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
-
lt8911exb_reset(lt8911exb);
-
lt8911exb_chip_id(lt8911exb);
lt8911exb_edp_video_cfg(lt8911exb);
@@ -1272,6 +1263,7 @@ static void init_work_func(struct work_struct *work)
PCR_Status(lt8911exb);
+ gpiod_direction_output(lt8911exb->bl_gpio, 1);
}
static int lt8911exb_probe(struct i2c_client *client,
@@ -1323,9 +1315,6 @@ static int lt8911exb_probe(struct i2c_client *client,
dev_err(&client->dev, "Failed get enable gpio\n");
return PTR_ERR(lt8911exb->enable_gpio);
}
- //disable firstly
- gpiod_direction_output(lt8911exb->enable_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
lt8911exb->standby_gpio = devm_gpiod_get_optional(dev, "standby",
GPIOD_IN);
@@ -1334,8 +1323,21 @@ static int lt8911exb_probe(struct i2c_client *client,
return PTR_ERR(lt8911exb->standby_gpio);
}
+ lt8911exb->bl_gpio = devm_gpiod_get_optional(dev, "bl",
+ GPIOD_IN);
+ if (IS_ERR(lt8911exb->bl_gpio)) {
+ dev_err(&client->dev, "Failed get bl gpio\n");
+ return PTR_ERR(lt8911exb->bl_gpio);
+ }
+ gpiod_direction_output(lt8911exb->bl_gpio, 0);
+
+ //disable firstly
+ gpiod_direction_output(lt8911exb->standby_gpio, 0);
+ gpiod_direction_output(lt8911exb->enable_gpio, 0);
+ usleep_range(50*1000, 100*1000); //100ms
+ gpiod_direction_output(lt8911exb->enable_gpio, 1);
gpiod_direction_output(lt8911exb->standby_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
+ usleep_range(50*1000, 100*1000); //100ms
lt8911exb->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_IN);
@@ -1346,14 +1348,6 @@ static int lt8911exb_probe(struct i2c_client *client,
lt8911exb_reset(lt8911exb);
- lt8911exb->bl_gpio = devm_gpiod_get_optional(dev, "bl",
- GPIOD_IN);
- if (IS_ERR(lt8911exb->bl_gpio)) {
- dev_err(&client->dev, "Failed get bl gpio\n");
- return PTR_ERR(lt8911exb->bl_gpio);
- }
- gpiod_direction_output(lt8911exb->bl_gpio, 1);
-
i2c_set_clientdata(client, lt8911exb);
//check i2c communicate
diff --git a/drivers/gpu/drm/spacemit/lt9711.c b/drivers/gpu/drm/spacemit/lt9711.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/lt9711.c
+++ b/drivers/gpu/drm/spacemit/lt9711.c
@@ -34,6 +34,8 @@
#include <drm/display/drm_dp_aux_bus.h>
#include <drm/display/drm_dp_helper.h>
+#include "spacemit_dsi.h"
+
#define IT9711_DSI_DRIVER_NAME "spacemit-dp-drv"
#define MIPI_DSI_1920x1080 1
@@ -58,10 +60,10 @@ static const struct drm_display_mode lt9711_panel_modes[] = {
struct lt9711 {
struct device *dev;
struct drm_bridge bridge;
- struct drm_connector connector;
+ struct drm_connector *connector;
+ struct spacemit_dsi_device *spacemit_dsi;
struct regmap *regmap;
-
struct gpio_desc *reset_gpio;
struct i2c_client *client;
@@ -69,9 +71,8 @@ struct lt9711 {
struct mipi_dsi_device *dsi;
enum drm_connector_status status;
-
- struct delayed_work init_work;
- bool init_work_pending;
+ struct delayed_work detect_work;
+ bool detect_work_pending;
};
static const struct regmap_config lt9711_regmap_config = {
@@ -98,14 +99,16 @@ static int lt9711_i2c_detect(struct lt9711 *lt9711)
dev_err(lt9711->dev, "LT9711 i2c detect write addr:0xff failed\n");
continue;
}
- usleep_range(100*1000, 150*1000); //150ms
regmap_read(lt9711->regmap, 0xd6, &status);
// LT9711 i2c detect success status: 0xee
- DRM_INFO("LT9711 i2c detect success status: 0x%x\n", status);
+ DRM_DEBUG("LT9711 i2c detect success status: 0x%x\n", status);
if (0xee == status)
- ret = 0;
+ lt9711->status = connector_status_connected;
+ else
+ lt9711->status = connector_status_disconnected;
+
break;
}
@@ -114,27 +117,16 @@ static int lt9711_i2c_detect(struct lt9711 *lt9711)
static int lt9711_panel_enable(struct drm_panel *panel)
{
- struct lt9711 *lt9711 = panel_to_lt9711(panel);
-
- DRM_INFO(" %s() \n", __func__);
-
- schedule_delayed_work(&lt9711->init_work,
- msecs_to_jiffies(1000));
- lt9711->init_work_pending = true;
+ // struct lt9711 *lt9711 = panel_to_lt9711(panel);
+ DRM_DEBUG(" %s() \n", __func__);
return 0;
}
static int lt9711_panel_disable(struct drm_panel *panel)
{
- struct lt9711 *lt9711 = panel_to_lt9711(panel);
-
- DRM_INFO(" %s() \n", __func__);
-
- if (lt9711->init_work_pending) {
- cancel_delayed_work_sync(&lt9711->init_work);
- lt9711->init_work_pending = false;
- }
+ // struct lt9711 *lt9711 = panel_to_lt9711(panel);
+ DRM_DEBUG(" %s() \n", __func__);
return 0;
}
@@ -142,6 +134,7 @@ static int lt9711_panel_disable(struct drm_panel *panel)
static int lt9711_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
+ // struct lt9711 *lt9711 = panel_to_lt9711(panel);
unsigned int i, num = 0;
static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
@@ -188,16 +181,36 @@ static const struct drm_panel_funcs lt9711_panel_funcs = {
.get_modes = lt9711_panel_get_modes,
};
-static void init_work_func(struct work_struct *work)
+static void detect_work_func(struct work_struct *work)
{
struct lt9711 *lt9711 = container_of(work, struct lt9711,
- init_work.work);
- DRM_DEBUG(" %s() \n", __func__);
+ detect_work.work);
+ int ret;
- lt9711_i2c_detect(lt9711);
+ //check i2c communicate
+ ret = lt9711_i2c_detect(lt9711);
+ if (ret < 0) {
+ DRM_INFO("detect DP failed communicate with IC use I2C\n");
+ }
+
+ if (lt9711->spacemit_dsi) {
+ DRM_DEBUG(" %s() connector status %d\n", __func__, lt9711->spacemit_dsi->connector_status);
+ lt9711->spacemit_dsi->connector_status = lt9711->status;
+
+ if (lt9711->spacemit_dsi->previous_connector_status != lt9711->spacemit_dsi->connector_status) {
+ if (lt9711->connector) {
+ DRM_INFO(" %s() detect DP connector hpd event\n", __func__);
+ lt9711->spacemit_dsi->previous_connector_status = lt9711->spacemit_dsi->connector_status;
+ drm_helper_hpd_irq_event(lt9711->connector->dev);
+ }
+ }
+ }
+ schedule_delayed_work(&lt9711->detect_work,
+ msecs_to_jiffies(2000));
}
+
static int lt9711_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -233,6 +246,9 @@ static int lt9711_probe(struct i2c_client *client,
lt9711->dev = &client->dev;
lt9711->client = client;
+ lt9711->connector = NULL;
+ lt9711->spacemit_dsi = NULL;
+ lt9711->status = connector_status_disconnected;
//regmap i2c , maybe useless
lt9711->regmap = devm_regmap_init_i2c(client, &lt9711_regmap_config);
@@ -280,7 +296,7 @@ static int lt9711_probe(struct i2c_client *client,
}
drm_panel_init(&lt9711->base, dev, &lt9711_panel_funcs,
- DRM_MODE_CONNECTOR_DSI);
+ DRM_MODE_CONNECTOR_DisplayPort);
/* This appears last, as it's what will unblock the DSI host
* driver's component bind function.
@@ -300,7 +316,10 @@ static int lt9711_probe(struct i2c_client *client,
return PTR_ERR(lt9711->dsi);
}
- INIT_DELAYED_WORK(&lt9711->init_work, init_work_func);
+ INIT_DELAYED_WORK(&lt9711->detect_work, detect_work_func);
+ schedule_delayed_work(&lt9711->detect_work,
+ msecs_to_jiffies(2000));
+ lt9711->detect_work_pending = true;
return 0;
error:
@@ -314,10 +333,16 @@ static void lt9711_remove(struct i2c_client *client)
DRM_DEBUG("%s()\n", __func__);
- mipi_dsi_detach(lt9711->dsi);
+ if (lt9711->detect_work_pending) {
+ cancel_delayed_work_sync(&lt9711->detect_work);
+ lt9711->detect_work_pending = false;
+ }
- drm_panel_remove(&lt9711->base);
+ lt9711->connector = NULL;
+ lt9711->spacemit_dsi = NULL;
+ mipi_dsi_detach(lt9711->dsi);
+ drm_panel_remove(&lt9711->base);
mipi_dsi_device_unregister(lt9711->dsi);
}
@@ -346,6 +371,10 @@ static struct i2c_driver lt9711_driver = {
static int lt9711_dsi_probe(struct mipi_dsi_device *dsi)
{
int ret;
+ struct mipi_dsi_host *host;
+ struct drm_panel *panel;
+ struct spacemit_dsi *mipi_dsi;
+ struct lt9711 *lt9711;
DRM_DEBUG("%s()\n", __func__);
@@ -359,6 +388,19 @@ static int lt9711_dsi_probe(struct mipi_dsi_device *dsi)
if (ret < 0) {
dev_err(&dsi->dev, "failed to attach dsi to host\n");
mipi_dsi_device_unregister(dsi);
+ } else {
+ host = dsi->host;
+ mipi_dsi = host_to_dsi(host);
+
+ panel = mipi_dsi->panel;
+ lt9711 = panel_to_lt9711(panel);
+
+ mipi_dsi->ctx.dsi_subconnector = SPACEMIT_DSI_SUBCONNECTOR_DP;
+ mipi_dsi->ctx.previous_connector_status = lt9711->status;
+ mipi_dsi->ctx.connector_status = mipi_dsi->ctx.previous_connector_status;
+
+ lt9711->connector = &mipi_dsi->connector;
+ lt9711->spacemit_dsi = &mipi_dsi->ctx;
}
return ret;
diff --git a/drivers/gpu/drm/spacemit/spacemit_dpu.c b/drivers/gpu/drm/spacemit/spacemit_dpu.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/spacemit_dpu.c
+++ b/drivers/gpu/drm/spacemit/spacemit_dpu.c
@@ -301,14 +301,13 @@ static void spacemit_crtc_atomic_enable(struct drm_crtc *crtc,
/* If bootloader logo is boot on, release its resources first */
if (unlikely(spacemit_dpu_logo_booton)) {
+ dpu_pm_suspend(dpu->dev);
pm_runtime_put_sync(dpu->dev);
spacemit_dpu_free_bootloader_mem();
}
- if (!pm_runtime_status_suspended(dpu->dev))
- dpu_pm_resume(dpu->dev);
- else
- pm_runtime_get_sync(dpu->dev);
+ pm_runtime_get_sync(dpu->dev);
+ dpu_pm_resume(dpu->dev);
#ifdef CONFIG_SPACEMIT_DEBUG
dpu->is_working = true;
@@ -334,10 +333,8 @@ static void spacemit_crtc_atomic_disable(struct drm_crtc *crtc,
dpu->is_working = false;
#endif
- if (!pm_runtime_status_suspended(dpu->dev))
- dpu_pm_suspend(dpu->dev);
- else
- pm_runtime_put_sync(dpu->dev);
+ dpu_pm_suspend(dpu->dev);
+ pm_runtime_put_sync(dpu->dev);
spin_lock_irq(&drm->event_lock);
if (crtc->state->event) {
@@ -962,8 +959,9 @@ static int spacemit_dpu_probe(struct platform_device *pdev)
// reset dpu
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
-
- pm_runtime_put_sync(dpu->dev);
+ dpu_pm_resume(&pdev->dev);
+ dpu_pm_suspend(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
msleep(10);
/*
@@ -971,8 +969,10 @@ static int spacemit_dpu_probe(struct platform_device *pdev)
* done in probe func as power domain framework will turn
* on/off lcd power domain before/after probe func.
*/
- if (spacemit_dpu_logo_booton)
+ if (spacemit_dpu_logo_booton) {
pm_runtime_get_sync(&pdev->dev);
+ dpu_pm_resume(&pdev->dev);
+ }
dpu->is_probed = true;
@@ -1083,95 +1083,18 @@ static int dpu_pm_resume(struct device *dev)
static int dpu_rt_pm_suspend(struct device *dev)
{
struct spacemit_dpu *dpu = dev_get_drvdata(dev);
- int result;
DRM_DEBUG("%s() type %d\n", __func__, dpu->type);
- if (dpu->core && dpu->core->disable_clk)
- dpu->core->disable_clk(dpu);
-
- if (dpu->type == HDMI) {
- if (!IS_ERR_OR_NULL(dpu->hdmi_reset)) {
- result = reset_control_assert(dpu->hdmi_reset);
- if (result < 0) {
- DRM_INFO("Failed to assert hdmi_reset: %d\n", result);
- }
- }
- } else if (dpu->type == DSI) {
-
- if (!IS_ERR_OR_NULL(dpu->lcd_reset)) {
- result = reset_control_assert(dpu->lcd_reset);
- if (result < 0) {
- DRM_INFO("Failed to assert lcd_reset: %d\n", result);
- }
- }
- if (!IS_ERR_OR_NULL(dpu->esc_reset)) {
- result = reset_control_assert(dpu->esc_reset);
- if (result < 0) {
- DRM_INFO("Failed to assert esc_reset: %d\n", result);
- }
- }
- if (!IS_ERR_OR_NULL(dpu->mclk_reset)) {
- result = reset_control_assert(dpu->mclk_reset);
- if (result < 0) {
- DRM_INFO("Failed to assert mclk_reset: %d\n", result);
- }
- }
- if (!IS_ERR_OR_NULL(dpu->dsi_reset)) {
- result = reset_control_assert(dpu->dsi_reset);
- if (result < 0) {
- DRM_INFO("Failed to assert dsi_reset: %d\n", result);
- }
- }
- }
-
return 0;
}
static int dpu_rt_pm_resume(struct device *dev)
{
struct spacemit_dpu *dpu = dev_get_drvdata(dev);
- int result;
DRM_DEBUG("%s() type %d\n", __func__, dpu->type);
- if (dpu->type == HDMI) {
- if (!IS_ERR_OR_NULL(dpu->hdmi_reset)) {
- result = reset_control_deassert(dpu->hdmi_reset);
- if (result < 0) {
- DRM_INFO("Failed to deassert hdmi_reset: %d\n", result);
- }
- }
- } else if (dpu->type == DSI){
- if (!IS_ERR_OR_NULL(dpu->dsi_reset)) {
- result = reset_control_deassert(dpu->dsi_reset);
- if (result < 0) {
- DRM_INFO("Failed to deassert dsi_reset: %d\n", result);
- }
- }
- if (!IS_ERR_OR_NULL(dpu->mclk_reset)) {
- result = reset_control_deassert(dpu->mclk_reset);
- if (result < 0) {
- DRM_INFO("Failed to deassert mclk_reset: %d\n", result);
- }
- }
- if (!IS_ERR_OR_NULL(dpu->esc_reset)) {
- result = reset_control_deassert(dpu->esc_reset);
- if (result < 0) {
- DRM_INFO("Failed to deassert esc_reset: %d\n", result);
- }
- }
- if (!IS_ERR_OR_NULL(dpu->lcd_reset)) {
- result = reset_control_deassert(dpu->lcd_reset);
- if (result < 0) {
- DRM_INFO("Failed to deassert lcd_reset: %d\n", result);
- }
- }
- }
-
- if (dpu->core && dpu->core->enable_clk)
- dpu->core->enable_clk(dpu);
-
return 0;
}
diff --git a/drivers/gpu/drm/spacemit/spacemit_dsi.c b/drivers/gpu/drm/spacemit/spacemit_dsi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/spacemit_dsi.c
+++ b/drivers/gpu/drm/spacemit/spacemit_dsi.c
@@ -19,13 +19,6 @@
#include "spacemit_dsi.h"
#include "sysfs/sysfs_display.h"
-#define encoder_to_dsi(encoder) \
- container_of(encoder, struct spacemit_dsi, encoder)
-#define host_to_dsi(host) \
- container_of(host, struct spacemit_dsi, host)
-#define connector_to_dsi(connector) \
- container_of(connector, struct spacemit_dsi, connector)
-
LIST_HEAD(dsi_core_head);
static void spacemit_dsi_encoder_enable(struct drm_encoder *encoder)
@@ -496,9 +489,14 @@ static struct drm_connector_helper_funcs spacemit_dsi_connector_helper_funcs = {
static enum drm_connector_status
spacemit_dsi_connector_detect(struct drm_connector *connector, bool force)
{
- DRM_DEBUG("%s()\n", __func__);
+ struct spacemit_dsi *dsi = connector_to_dsi(connector);
- return connector_status_connected;
+ DRM_DEBUG("%s() dsi subconnector type %d status %d\n", __func__, dsi->ctx.dsi_subconnector, dsi->ctx.connector_status);
+
+ if (SPACEMIT_DSI_SUBCONNECTOR_DP == dsi->ctx.dsi_subconnector)
+ return dsi->ctx.connector_status;
+ else
+ return connector_status_connected;
}
static void spacemit_dsi_connector_destroy(struct drm_connector *connector)
@@ -524,11 +522,13 @@ static int spacemit_dsi_connector_init(struct drm_device *drm, struct spacemit_d
struct drm_connector *connector = &dsi->connector;
int ret;
+ DRM_DEBUG("%s()\n", __func__);
+
connector->polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(drm, connector,
- &spacemit_dsi_atomic_connector_funcs,
- DRM_MODE_CONNECTOR_DSI);
+ &spacemit_dsi_atomic_connector_funcs,
+ DRM_MODE_CONNECTOR_DSI);
if (ret) {
DRM_ERROR("drm_connector_init() failed\n");
return ret;
@@ -574,7 +574,7 @@ static int __maybe_unused spacemit_dsi_bridge_attach(struct spacemit_dsi *dsi)
static irqreturn_t spacemit_dsi_isr(int irq, void *data)
{
struct spacemit_dsi *dsi = data;
- pr_debug("%s: dsi Enter\n", __func__);
+ DRM_DEBUG("%s: dsi Enter\n", __func__);
if (dsi->core && dsi->core->isr)
dsi->core->isr(&dsi->ctx);
@@ -606,6 +606,8 @@ static int spacemit_dsi_bind(struct device *dev, struct device *master, void *da
struct spacemit_dsi *dsi = dev_get_drvdata(dev);
int ret;
+ DRM_DEBUG("%s()\n", __func__);
+
ret = spacemit_dsi_encoder_init(drm, dsi);
if (ret)
goto cleanup_host;
@@ -678,6 +680,10 @@ static int spacemit_dsi_context_init(struct spacemit_dsi *dsi, struct device_nod
return -ENODEV;
}
+ ctx->dsi_subconnector = SPACEMIT_DSI_SUBCONNECTOR_MIPI_DSI;
+ ctx->previous_connector_status = connector_status_connected;
+ ctx->connector_status = connector_status_connected;
+
if (!of_property_read_u32(np, "dev-id", &tmp))
ctx->id = tmp;
diff --git a/drivers/gpu/drm/spacemit/spacemit_dsi.h b/drivers/gpu/drm/spacemit/spacemit_dsi.h
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/spacemit_dsi.h
+++ b/drivers/gpu/drm/spacemit/spacemit_dsi.h
@@ -182,6 +182,13 @@ struct spacemit_dsi_rx_buf {
uint8_t data[MAX_RX_DATA_COUNT];
};
+enum spacemit_dsi_subconnector {
+ SPACEMIT_DSI_SUBCONNECTOR_MIPI_DSI = 0,
+ SPACEMIT_DSI_SUBCONNECTOR_HDMI = 1,
+ SPACEMIT_DSI_SUBCONNECTOR_DP = 2,
+ SPACEMIT_DSI_SUBCONNECTOR_eDP = 3,
+};
+
struct spacemit_dsi_device {
uint16_t id;
void __iomem *base_addr;
@@ -189,7 +196,10 @@ struct spacemit_dsi_device {
struct spacemit_mipi_info mipi_info;
struct videomode vm;
struct spacemit_dphy *phy;
- int status;
+ enum spacemit_dsi_status status;
+ enum drm_connector_status previous_connector_status;
+ enum drm_connector_status connector_status;
+ enum spacemit_dsi_subconnector dsi_subconnector;
};
struct dsi_core_ops {
@@ -216,7 +226,6 @@ struct spacemit_dsi {
struct spacemit_dsi_device ctx;
};
-
extern struct list_head dsi_core_head;
#define dsi_core_ops_register(entry) \
@@ -224,4 +233,11 @@ extern struct list_head dsi_core_head;
#define dsi_core_ops_attach(str) \
disp_ops_attach(str, &dsi_core_head)
+#define encoder_to_dsi(encoder) \
+ container_of(encoder, struct spacemit_dsi, encoder)
+#define host_to_dsi(host) \
+ container_of(host, struct spacemit_dsi, host)
+#define connector_to_dsi(connector) \
+ container_of(connector, struct spacemit_dsi, connector)
+
#endif /* _SPACEMIT_DSI_H_ */
diff --git a/drivers/gpu/drm/spacemit/spacemit_hdmi.c b/drivers/gpu/drm/spacemit/spacemit_hdmi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/spacemit_hdmi.c
+++ b/drivers/gpu/drm/spacemit/spacemit_hdmi.c
@@ -40,7 +40,7 @@
struct hdmi_data_info {
- uint8_t edid[EDID_LENGTH];
+ uint8_t edid[256];
int vic;
bool sink_has_audio;
unsigned int enc_in_format;
@@ -484,13 +484,26 @@ int edid_read (struct spacemit_hdmi *hdmi){
}
if (result < 0) {
- memset(hdmi_data->edid, 0x00, EDID_LENGTH);
+ // memset(hdmi_data->edid, 0x00, EDID_LENGTH);
+ memset(hdmi_data->edid, 0x00, 256);
return result;
}
- for(i = 0; i < EDID_LENGTH; i += 4){
- DRM_DEBUG("EDID 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\r\n", i,
- hdmi_data->edid[i], hdmi_data->edid[i+1], hdmi_data->edid[i+2], hdmi_data->edid[i+3]);
+ if (hdmi_data->edid[0x7e] == 0x01) {
+ // extend edid
+ for(i = 8; i < 16; i++) {
+ offset = i * 16;
+ result = hdmi_i2c_write(hdmi, 0x50, &offset, 1);
+ if (result < 0)
+ break;
+ hdmi_i2c_read(hdmi, 0x50, hdmi_data->edid + offset, 16);
+ }
+ }
+
+ for(i = 0; i < 256; i += 8){
+ DRM_DEBUG("EDID 0x%x: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n", i,
+ hdmi_data->edid[i], hdmi_data->edid[i+1], hdmi_data->edid[i+2], hdmi_data->edid[i+3],
+ hdmi_data->edid[i+4], hdmi_data->edid[i+5], hdmi_data->edid[i+6], hdmi_data->edid[i+7]);
}
if ((hdmi_data->edid[0] == 0x00) && (hdmi_data->edid[1] == 0xff) && (hdmi_data->edid[2] == 0xff) &&
@@ -511,7 +524,7 @@ static int spacemit_hdmi_get_edid_block(void *data, u8 *buf, unsigned int block,
uint32_t value;
int ret;
- DRM_DEBUG("%s()\n", __func__);
+ DRM_INFO("%s() len %zd\n", __func__, len);
if (len > 128)
return -EINVAL;
@@ -535,7 +548,7 @@ static int spacemit_hdmi_get_edid_block(void *data, u8 *buf, unsigned int block,
}
} else {
- memcpy(buf, hdmi_data->edid, len);
+ memcpy(buf, hdmi_data->edid + EDID_LENGTH, len);
}
return 0;
@@ -603,22 +616,21 @@ static int spacemit_hdmi_setup(struct spacemit_hdmi *hdmi,
if (value == 0xa08501) {
// default 10bpc
bit_depth = TEN_BPP;
- if (hdmi->edid_done) {
- // 08H, 09H: ID Manufacturer Nanme
- // 0AH, 0BH: ID Product Code
- if ((hdmi_data->edid[8] == 0x30) && (hdmi_data->edid[9] == 0xa3) &&
- ((hdmi_data->edid[10] == 0x88) || (hdmi_data->edid[10] == 0x89)) && (hdmi_data->edid[11] == 0x23)) {
- // Lecoo HU20238FB0
- bit_depth = EIGHT_BPP;
- } else if ((hdmi_data->edid[8] == 0x26) && (hdmi_data->edid[9] == 0x01) &&
- (hdmi_data->edid[10] == 0x12) && (hdmi_data->edid[11] == 0x24)) {
- // IPASON XC242-J
- bit_depth = EIGHT_BPP;
- } else if ((hdmi_data->edid[8] == 0x05) && (hdmi_data->edid[9] == 0xe3) &&
- (hdmi_data->edid[10] == 0x90) && (hdmi_data->edid[11] == 0x24)) {
- // AOC Q2490W1
- bit_depth = EIGHT_BPP;
- }
+
+ // 08H, 09H: ID Manufacturer Nanme
+ // 0AH, 0BH: ID Product Code
+ if ((hdmi_data->edid[8] == 0x30) && (hdmi_data->edid[9] == 0xa3) &&
+ ((hdmi_data->edid[10] == 0x88) || (hdmi_data->edid[10] == 0x89)) && (hdmi_data->edid[11] == 0x23)) {
+ // Lecoo HU20238FB0
+ bit_depth = EIGHT_BPP;
+ } else if ((hdmi_data->edid[8] == 0x26) && (hdmi_data->edid[9] == 0x01) &&
+ (hdmi_data->edid[10] == 0x12) && (hdmi_data->edid[11] == 0x24)) {
+ // IPASON XC242-J
+ bit_depth = EIGHT_BPP;
+ } else if ((hdmi_data->edid[8] == 0x05) && (hdmi_data->edid[9] == 0xe3) &&
+ (hdmi_data->edid[10] == 0x90) && (hdmi_data->edid[11] == 0x24)) {
+ // AOC Q2490W1
+ bit_depth = EIGHT_BPP;
}
}
@@ -743,6 +755,8 @@ static int spacemit_hdmi_connector_get_modes(struct drm_connector *connector)
hdmi_writeb(hdmi, SPACEMIT_HDMI_PHY_STATUS, value);
udelay(5);
+ hdmi->edid_done = false;
+
edid = drm_do_get_edid(connector, spacemit_hdmi_get_edid_block, hdmi);
if (edid) {
if (hdmi->edid_done) {
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 111111111111..222222222222 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -28,6 +28,9 @@
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/sed-opal.h>
#include <linux/pci-p2pdma.h>
+#if defined(CONFIG_SOC_SPACEMIT_K1X)
+#include <linux/leds.h>
+#endif
#include "trace.h"
#include "nvme.h"
@@ -1019,6 +1022,10 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
if (blk_rq_nr_phys_segments(req))
nvme_unmap_data(dev, req);
+
+#if defined(CONFIG_SOC_SPACEMIT_K1X)
+ ledtrig_disk_activity(req_op(req) == REQ_OP_WRITE);
+#endif
}
static void nvme_pci_complete_rq(struct request *req)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 111111111111..222222222222 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -97,11 +97,13 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_DA732X
imply SND_SOC_DA9055
imply SND_SOC_DMIC
+ imply SND_SOC_ES8156
imply SND_SOC_ES8316
imply SND_SOC_ES8326
imply SND_SOC_ES8328_SPI
imply SND_SOC_ES8328_I2C
imply SND_SOC_ES7134
+ imply SND_SOC_ES7210
imply SND_SOC_ES7241
imply SND_SOC_GTM601
imply SND_SOC_HDAC_HDMI
@@ -922,9 +924,16 @@ config SND_SOC_HDMI_CODEC
config SND_SOC_ES7134
tristate "Everest Semi ES7134 CODEC"
+config SND_SOC_ES7210
+ tristate "Everest Semi ES7210 CODEC"
+
config SND_SOC_ES7241
tristate "Everest Semi ES7241 CODEC"
+config SND_SOC_ES8156
+ tristate "Everest Semi ES8156 CODEC"
+ depends on I2C
+
config SND_SOC_ES8316
tristate "Everest Semi ES8316 CODEC"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 111111111111..222222222222 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -100,7 +100,9 @@ snd-soc-da732x-objs := da732x.o
snd-soc-da9055-objs := da9055.o
snd-soc-dmic-objs := dmic.o
snd-soc-es7134-objs := es7134.o
+snd-soc-es7210-objs := es7210.o
snd-soc-es7241-objs := es7241.o
+snd-soc-es8156-objs := es8156.o
snd-soc-es8316-objs := es8316.o
snd-soc-es8326-objs := es8326.o
snd-soc-es8328-objs := es8328.o
@@ -461,7 +463,9 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o
+obj-$(CONFIG_SND_SOC_ES7210) += snd-soc-es7210.o
obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o
+obj-$(CONFIG_SND_SOC_ES8156) += snd-soc-es8156.o
obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o
obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
diff --git a/sound/soc/codecs/es7210.c b/sound/soc/codecs/es7210.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es7210.c
@@ -0,0 +1,1993 @@
+/*
+ * ALSA SoC ES7210 adc driver
+ *
+ * Copyright: (C) 2018 Everest Semiconductor Co Ltd.,
+ *
+ * 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.
+ *
+ * Notes:
+ * ES7210 is a 4-ch ADC of Everest
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include "es7210.h"
+
+
+#define DOUBLESPEED 0
+
+#define ENABLE 1
+#define DISABLE 0
+
+#define MIC_CHN_16 16
+#define MIC_CHN_14 14
+#define MIC_CHN_12 12
+#define MIC_CHN_10 10
+#define MIC_CHN_8 8
+#define MIC_CHN_6 6
+#define MIC_CHN_4 4
+#define MIC_CHN_2 2
+
+#define ES7210_TDM_ENABLE ENABLE
+//#define ES7210_CHANNELS_MAX MIC_CHN_8
+
+static int ADC_DEV_MAXNUM = 1;
+static int ES7210_CHANNELS_MAX = 1;
+
+#define ES7210_TDM_1LRCK_DSPA 0
+#define ES7210_TDM_1LRCK_DSPB 1
+#define ES7210_TDM_1LRCK_I2S 2
+#define ES7210_TDM_1LRCK_LJ 3
+#define ES7210_TDM_NLRCK_DSPA 4
+#define ES7210_TDM_NLRCK_DSPB 5
+#define ES7210_TDM_NLRCK_I2S 6
+#define ES7210_TDM_NLRCK_LJ 7
+#define ES7210_NORMAL_I2S 8
+
+#define ES7210_WORK_MODE ES7210_TDM_1LRCK_DSPB
+
+
+#define ES7210_I2C_BUS_NUM 1
+#define ES7210_CODEC_RW_TEST_EN 0
+#define ES7210_IDLE_RESET_EN 1 //reset ES7210 when in idle time
+
+#define ES7210_MIC_GAIN 0x1c // need check hw design and channel
+#define ES7210_AEC_GAIN 0x13 // need check hw design and channel
+
+/* to set internal mclk and adclrclk ratio */
+
+#define RATIO_768 0xC3
+#define RATIO_256 0xC1
+#define RATIO_128 0x01
+#define RATIO_64 0x41 /* mclk from bclk pin */
+
+#define ES7210_MCLK_LRCK_RATIO RATIO_256 // mclk=sclk. mclk/lrck = sclk / lrck = 16bit*4slot=RATIO_64. 32bit*4slot=16bit*8slot=RATIO_128 32bit*8slot=RATIO_256
+
+struct i2c_client *i2c_clt1[4] = {0};
+
+struct es7210_priv *resume_es7210 = NULL;
+
+struct snd_soc_component *tron_codec1[4];
+
+int es7210_init_reg = 0;
+int es7210_hw_param_reg = 0;
+static int es7210_codec_num = 0;
+
+static const struct regmap_config es7210_regmap_config = {
+ .reg_bits = 8, //Number of bits in a register address
+ .val_bits = 8, //Number of bits in a register value
+};
+/*
+* ES7210 register cache
+*/
+static const u8 es7210_reg[] = {
+ 0x32, 0x40, 0x02, 0x04, 0x01, 0x00, 0x00, 0x20, /* 0 - 7 */
+ 0x10, 0x40, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, /* 8 - F */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 - 17 */
+ 0xf7, 0xf7, 0x00, 0xbf, 0xbf, 0xbf, 0xbf, 0x00, /* 18 - 1f */
+ 0x26, 0x26, 0x06, 0x26, 0x00, 0x00, 0x00, 0x00, /* 20 - 27 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 - 2f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 37 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x10, 0x00, /* 38 - 3f */
+ 0x80, 0x71, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, /* 40 - 47 */
+ 0x00, 0x00, 0x00, 0xff, 0xff, /* 48 - 4c */
+};
+
+struct es7210_reg_config {
+ unsigned char reg_addr;
+ unsigned char reg_v;
+};
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg1[] = {
+ { 0x00, 0xFF },
+ { 0x00, 0x32 },
+ { 0x09, 0x30 },
+ { 0x0A, 0x30 },
+ { 0x23, 0x2a },
+ { 0x22, 0x0a },
+ { 0x21, 0x2a },
+ { 0x20, 0x0a },
+};
+static const struct es7210_reg_config es7210_tdm_reg_fmt_cfg[] = {
+ { 0x11, 0x63 },
+ { 0x12, 0x01 },
+};
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg2[] = {
+ { 0x40, 0xC3 },
+ { 0x41, 0x70 },
+ { 0x42, 0x70 },
+ { 0x43, 0x1E },
+ { 0x44, 0x1E },
+ { 0x45, 0x1E },
+ { 0x46, 0x1E },
+ { 0x47, 0x08 },
+ { 0x48, 0x08 },
+ { 0x49, 0x08 },
+ { 0x4A, 0x08 },
+ { 0x07, 0x20 },
+};
+static const struct es7210_reg_config es7210_tdm_reg_mclk_cfg[] = {
+ { 0x02, 0xC1 },
+};
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg3[] = {
+ { 0x06, 0x00 },
+ { 0x4B, 0x0F },
+ { 0x4C, 0x0F },
+ { 0x00, 0x71 },
+ { 0x00, 0x41 },
+};
+static int es7210_read(u8 reg, u8 *rt_value, struct i2c_client *client)
+{
+ int ret;
+ u8 read_cmd[3] = {0};
+ u8 cmd_len = 0;
+
+ read_cmd[0] = reg;
+ cmd_len = 1;
+
+ if (client->adapter == NULL)
+ pr_err("es7210_read client->adapter==NULL\n");
+
+ ret = i2c_master_send(client, read_cmd, cmd_len);
+ if (ret != cmd_len) {
+ return -1;
+ }
+
+ ret = i2c_master_recv(client, rt_value, 1);
+ if (ret != 1) {
+ return -1;
+ }
+
+ return 0;
+}
+static int es7210_write(u8 reg, unsigned char value, struct i2c_client *client)
+{
+ int ret;
+ u8 write_cmd[2] = {0};
+
+ write_cmd[0] = reg;
+ write_cmd[1] = value;
+
+ ret = i2c_master_send(client, write_cmd, 2);
+ if (ret != 2) {
+ return -1;
+ }
+
+ return 0;
+}
+static int es7210_update_bits(u8 reg, u8 mask, u8 value, struct i2c_client *client)
+{
+ u8 val_old, val_new;
+
+ es7210_read(reg, &val_old, client);
+ val_new = (val_old & ~mask) | (value & mask);
+ if (val_new != val_old) {
+ es7210_write(reg, val_new, client);
+ }
+
+ return 0;
+}
+/*
+static int es7210_multi_chips_read(u8 reg, unsigned char *rt_value)
+{
+ u8 i;
+
+ for(i=0; i< ADC_DEV_MAXNUM; i++){
+ es7210_read(reg, rt_value++, i2c_clt1[i]);
+ }
+
+ return 0;
+}
+*/
+static int es7210_multi_chips_write(u8 reg, unsigned char value)
+{
+ u8 i;
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ es7210_write(reg, value, i2c_clt1[i]);
+ }
+
+ return 0;
+}
+
+static int es7210_multi_chips_update_bits(u8 reg, u8 mask, u8 value)
+{
+ u8 i;
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ es7210_update_bits(reg, mask, value, i2c_clt1[i]);
+ }
+
+ return 0;
+}
+
+/*
+* Note that this should be called from init rather than from hw_params.
+*/
+static int es7210_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ return 0;
+}
+
+static int es7210_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ return 0;
+}
+static void es7210_tdm_init_ratio(struct es7210_priv *priv)
+{
+ int cnt, channel, width;
+
+ channel = ES7210_CHANNELS_MAX;
+
+ switch(priv->tdm_mode) {
+ case ES7210_TDM_1LRCK_DSPB:
+ switch(priv->pcm_format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ width = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ width = 32;
+ }
+ break;
+ case ES7210_NORMAL_I2S:
+ width = 32;
+ if (channel > 2) // i2s 8ch has 2 channels in actual.
+ channel = 2;
+ break;
+ default:
+ break;
+ }
+
+ priv->sclk_lrck_ratio = channel * width ;
+
+ switch(priv->sclk_lrck_ratio * priv->mclk_sclk_ratio) {
+ case 64:
+ priv->mclk_lrck_ratio = RATIO_64;
+ break;
+ case 128:
+ priv->mclk_lrck_ratio = RATIO_128;
+ break;
+ case 256:
+ priv->mclk_lrck_ratio = RATIO_256;
+ break;
+ case 768:
+ priv->mclk_lrck_ratio = RATIO_768;
+ break;
+ default:
+ pr_err("%s Unable to calculate proper mclk_lrck_ratio with sclk_lrck_ratio=%d!\n", __func__, priv->sclk_lrck_ratio);
+ break;
+ }
+
+ switch (priv->tdm_mode) {
+ case ES7210_TDM_1LRCK_DSPA:
+ case ES7210_TDM_1LRCK_DSPB:
+ case ES7210_TDM_1LRCK_I2S:
+ case ES7210_TDM_1LRCK_LJ:
+ case ES7210_NORMAL_I2S:
+ /*
+ * to set internal mclk
+ * here, we assume that cpu/soc always provides
+ * 256FS i2s clock
+ * to es7210.
+ * dll bypassed, use clock doubler to get double
+ * frequency for
+ * internal modem which need
+ * 512FS clock. the clk divider ratio is 1.
+ * user must modify the setting of register0x02
+ * according to FS
+ * ratio provided by CPU/SOC.
+ */
+
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_MCLK_CTL_REG02,
+ priv->mclk_lrck_ratio, i2c_clt1[cnt]);
+ }
+ // es7210_multi_chips_write(ES7210_MCLK_CTL_REG02,
+ // 0xc1);
+ break;
+ case ES7210_TDM_NLRCK_DSPA:
+ case ES7210_TDM_NLRCK_DSPB:
+ case ES7210_TDM_NLRCK_I2S:
+ case ES7210_TDM_NLRCK_LJ:
+ /*
+ * Here to set TDM format for DSP-A with
+ * multiple LRCK TDM mode
+ */
+ channel = ES7210_CHANNELS_MAX;
+ /*
+ * Set the microphone numbers in array
+ */
+ switch (channel) {
+ case 2:
+ /* ES7210_CHANNELS_MAX=2 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x10);
+ break;
+ case 4:
+ /* ES7210_CHANNELS_MAX=4 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x20);
+ break;
+ case 6:
+ /* ES7210_CHANNELS_MAX=6 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x30);
+ break;
+ case 8:
+ /* ES7210_CHANNELS_MAX=8 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x40);
+ break;
+ case 10:
+ /* ES7210_CHANNELS_MAX=10 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x50);
+ break;
+ case 12:
+ /* ES7210_CHANNELS_MAX=12 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x60);
+ break;
+ case 14:
+ /* ES7210_CHANNELS_MAX=14 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x70);
+ break;
+ case 16:
+ /* ES7210_CHANNELS_MAX=16 */
+ es7210_multi_chips_write(
+ ES7210_MODE_CFG_REG08, 0x80);
+ break;
+ default:
+ break;
+ }
+ /*
+ * to set internal mclk
+ * here, we assume that cpu/soc always provides
+ * 256FS i2s clock
+ * to es7210 and there is four
+ * es7210 devices in tdm link. so the
+ * internal FS in es7210
+ * is only FS/4;
+ * dll bypassed, clock doubler bypassed. the clk
+ * divider ratio is
+ * 2. so the clock of internal
+ * modem equals to (256FS / (FS/4) / 2) * FS
+ * = 512FS
+ * user must modify the setting of register0x02
+ * according to FS
+ * ratio provided by CPU/SOC.
+ */
+
+ es7210_multi_chips_write(ES7210_MCLK_CTL_REG02,
+ priv->mclk_lrck_ratio);// NFS MODE:RATIO_768 ,12.288M/48K(16K 6 CH),12.288M/64K(16K 8 CH)
+ break;
+ default:
+ /*
+ * to set internal mclk for normal mode
+ * here, we assume that cpu/soc always provides
+ * 256FS i2s clock
+ * to es7210.
+ * dll bypassed, use clock doubler to get double
+ * frequency for
+ * internal modem which need
+ * 512FS clock. the clk divider ratio is 1.
+ * user must modify the setting of register0x02
+ * according to FS
+ * ratio provided by CPU/SOC.
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_MCLK_CTL_REG02,
+ priv->mclk_lrck_ratio, i2c_clt1[cnt]);
+ }
+
+ break;
+ }
+ return;
+}
+
+/*
+* to initialize es7210 for tdm mode
+*/
+static void es7210_tdm_init_codec(u8 mode)
+{
+ int cnt, i;
+
+ for (cnt = 0;
+ cnt < sizeof(es7210_tdm_reg_common_cfg1) /
+ sizeof(es7210_tdm_reg_common_cfg1[0]);
+ cnt++) {
+ es7210_multi_chips_write(
+ es7210_tdm_reg_common_cfg1[cnt].reg_addr,
+ es7210_tdm_reg_common_cfg1[cnt].reg_v);
+ }
+ if(DOUBLESPEED)
+ es7210_multi_chips_update_bits(ES7210_MODE_CFG_REG08, 0x02, 0x02);
+
+ switch (mode) {
+ case ES7210_TDM_1LRCK_DSPA:
+ /*
+ * Here to set TDM format for DSP-A mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x63, i2c_clt1[cnt]);
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x01, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_1LRCK_DSPB:
+ /*
+ * Here to set TDM format for DSP-B mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x73, i2c_clt1[cnt]);
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x01, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_1LRCK_I2S:
+ /*
+ * Here to set TDM format for I2S mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x60, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x02, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_1LRCK_LJ:
+ /*
+ * Here to set TDM format for Left Justified mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x61, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x02, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_NLRCK_DSPA:
+ /*
+ * set format, dsp-a with multiple LRCK tdm mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x63, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ /*
+ * set tdm flag in the interface
+ * chip
+ */
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x07,
+ i2c_clt1[cnt]);
+ } else {
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x03,
+ i2c_clt1[cnt]);
+ }
+ }
+ break;
+ case ES7210_TDM_NLRCK_DSPB:
+ /*
+ * set format, dsp-b with multiple LRCK tdm mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x73, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ /*
+ * set tdm flag in the interface
+ * chip
+ */
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x07,
+ i2c_clt1[cnt]);
+ } else {
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x03,
+ i2c_clt1[cnt]);
+ }
+ }
+
+ break;
+ case ES7210_TDM_NLRCK_I2S:
+ /*
+ * set format, I2S with multiple LRCK tdm mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x60, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ /*
+ * set tdm flag in the interface
+ * chip
+ */
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x07,
+ i2c_clt1[cnt]);
+ } else {
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x03,
+ i2c_clt1[cnt]);
+ }
+ }
+
+ break;
+ case ES7210_TDM_NLRCK_LJ:
+ /*
+ * set format, left justified with multiple LRCK
+ * tdm mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x61, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ /*
+ * set tdm flag in the interface
+ * chip
+ */
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x07,
+ i2c_clt1[cnt]);
+ } else {
+ es7210_write(
+ ES7210_SDP_CFG2_REG12, 0x03,
+ i2c_clt1[cnt]);
+ }
+ }
+
+ break;
+ case ES7210_NORMAL_I2S:
+ /*
+ * Here to set Normal i2s mode format for SD1/SD2 output
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x60, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x00, i2c_clt1[cnt]);
+ }
+
+ break;
+
+ default:
+ /*
+ * here to disable tdm and set i2s-16bit for
+ * normal mode
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x60, i2c_clt1[cnt]);
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x00, i2c_clt1[cnt]);
+ }
+ break;
+ }
+ for (cnt = 0;
+ cnt < sizeof(es7210_tdm_reg_common_cfg2) /
+ sizeof(es7210_tdm_reg_common_cfg2[0]);
+ cnt++) {
+ es7210_multi_chips_write(
+ es7210_tdm_reg_common_cfg2[cnt].reg_addr,
+ es7210_tdm_reg_common_cfg2[cnt].reg_v);
+ }
+
+ for (cnt = 0;
+ cnt < sizeof(es7210_tdm_reg_common_cfg3) /
+ sizeof(es7210_tdm_reg_common_cfg3[0]);
+ cnt++) {
+ es7210_multi_chips_write(
+ es7210_tdm_reg_common_cfg3[cnt].reg_addr,
+ es7210_tdm_reg_common_cfg3[cnt].reg_v);
+ }
+ /*
+ * Mute All ADC
+ */
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_ADC34_MUTE_REG14, 0x03,
+ i2c_clt1[cnt]);
+ es7210_write(ES7210_ADC12_MUTE_REG15, 0x03,
+ i2c_clt1[cnt]);
+ }
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ if (i == 0) {
+ /* set first es7210 PGA GAIN */
+ es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ }
+ if (i == 1) {
+ /* set second es7210 PGA GAIN */
+ es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ }
+ if (i == 2) {
+ /* set third es7210 PGA GAIN */
+ es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ }
+
+ if (i == 3) {
+ /* set third es7210 PGA GAIN */
+ es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN,
+ i2c_clt1[i]);
+ }
+ }
+}
+static void es7210_unmute(void)
+{
+ es7210_multi_chips_update_bits(ES7210_ADC34_MUTE_REG14, 0x03, 0x00);
+ es7210_multi_chips_update_bits(ES7210_ADC12_MUTE_REG15, 0x03, 0x00);
+ es7210_multi_chips_update_bits(ES7210_MIC1_GAIN_REG43, 0x1f, ES7210_MIC_GAIN);
+ es7210_multi_chips_update_bits(ES7210_MIC2_GAIN_REG44, 0x1f, ES7210_MIC_GAIN);
+ es7210_multi_chips_update_bits(ES7210_MIC3_GAIN_REG45, 0x1f, ES7210_MIC_GAIN);
+ es7210_multi_chips_update_bits(ES7210_MIC4_GAIN_REG46, 0x1f, ES7210_MIC_GAIN);
+}
+
+static void pcm_pop_work_events(struct work_struct *work)
+{
+ es7210_unmute();
+}
+
+static int es7210_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct es7210_priv *es7210 = snd_soc_component_get_drvdata(component);
+
+ if (es7210_init_reg == 0) {
+ es7210_init_reg = 1;
+ schedule_delayed_work(&es7210->pcm_pop_work, msecs_to_jiffies(100));
+ }
+ return 0;
+}
+static int es7210_pcm_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 es7210_priv *priv = snd_soc_component_get_drvdata(component);
+ int i;
+
+ if (es7210_hw_param_reg == 1 && params_format(params) == priv->pcm_format) {
+ return 0;
+ }
+
+ es7210_hw_param_reg = 1;
+ priv->pcm_format = params_format(params);
+ es7210_tdm_init_ratio(priv);
+
+ es7210_multi_chips_update_bits(ES7210_RESET_CTL_REG00, 0x30, 0x30);
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ /* set es7210 bit size */
+ switch (priv->pcm_format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ es7210_update_bits(0x11, 0xE0, 0x60,
+ i2c_clt1[i]);
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ es7210_update_bits(0x11, 0xE0, 0x20,
+ i2c_clt1[i]);
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ es7210_update_bits(0x11, 0xE0, 0x00,
+ i2c_clt1[i]);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ es7210_update_bits(0x11, 0xE0, 0x80,
+ i2c_clt1[i]);
+ break;
+ }
+ }
+ es7210_multi_chips_update_bits(ES7210_RESET_CTL_REG00, 0x30, 0x00);
+ switch (params_rate(params)) {
+ case 16000:
+ break;
+ case 32000:
+ break;
+ case 48000:
+ break;
+ case 64000:
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+#define es7210_RATES SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|SNDRV_PCM_RATE_88200
+
+#define es7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops es7210_ops = {
+ .startup = es7210_pcm_startup,
+ .hw_params = es7210_pcm_hw_params,
+ .set_fmt = es7210_set_dai_fmt,
+ .set_sysclk = es7210_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver es7210_dai0 = {
+ .name = "ES7210 ADC 0",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = es7210_RATES,
+ .formats = es7210_FORMATS,
+ },
+ .ops = &es7210_ops,
+};
+
+
+static struct snd_soc_dai_driver es7210_dai1 = {
+ .name = "ES7210 4CH ADC 1",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = es7210_RATES,
+ .formats = es7210_FORMATS,
+ },
+ .ops = &es7210_ops,
+};
+
+static struct snd_soc_dai_driver es7210_dai2 = {
+ .name = "ES7210 4CH ADC 2",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = es7210_RATES,
+ .formats = es7210_FORMATS,
+ },
+ .ops = &es7210_ops,
+};
+
+static struct snd_soc_dai_driver es7210_dai3 = {
+ .name = "ES7210 4CH ADC 3",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = es7210_RATES,
+ .formats = es7210_FORMATS,
+ },
+ .ops = &es7210_ops,
+};
+
+static struct snd_soc_dai_driver *es7210_dai[] = {
+ &es7210_dai0,
+ &es7210_dai1,
+ &es7210_dai2,
+ &es7210_dai3,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int es7210_suspend(struct snd_soc_component *component)
+{
+ int i = 0;
+ struct es7210_priv *priv = snd_soc_component_get_drvdata(component);
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ es7210_read(ES7210_RESET_CTL_REG00, &priv->suspend_reg00[i], i2c_clt1[i]);
+ es7210_read(ES7210_CLK_ON_OFF_REG01, &priv->suspend_reg01[i], i2c_clt1[i]);
+ es7210_read(ES7210_MCLK_CTL_REG02, &priv->suspend_reg02[i], i2c_clt1[i]);
+ es7210_read(ES7210_MST_CLK_CTL_REG03, &priv->suspend_reg03[i], i2c_clt1[i]);
+ es7210_read(ES7210_MST_LRCDIVH_REG04, &priv->suspend_reg04[i], i2c_clt1[i]);
+ es7210_read(ES7210_MST_LRCDIVL_REG05, &priv->suspend_reg05[i], i2c_clt1[i]);
+ es7210_read(ES7210_DIGITAL_PDN_REG06, &priv->suspend_reg06[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC_OSR_REG07, &priv->suspend_reg07[i], i2c_clt1[i]);
+ es7210_read(ES7210_MODE_CFG_REG08, &priv->suspend_reg08[i], i2c_clt1[i]);
+ es7210_read(ES7210_TCT0_CHPINI_REG09, &priv->suspend_reg09[i], i2c_clt1[i]);
+ es7210_read(ES7210_TCT1_CHPINI_REG0A, &priv->suspend_reg0A[i], i2c_clt1[i]);
+ es7210_read(ES7210_CHIP_STA_REG0B, &priv->suspend_reg0B[i], i2c_clt1[i]);
+ es7210_read(ES7210_IRQ_CTL_REG0C, &priv->suspend_reg0C[i], i2c_clt1[i]);
+ es7210_read(ES7210_MISC_CTL_REG0D, &priv->suspend_reg0D[i], i2c_clt1[i]);
+ es7210_read(ES7210_DMIC_CTL_REG10, &priv->suspend_reg10[i], i2c_clt1[i]);
+ es7210_read(ES7210_SDP_CFG1_REG11, &priv->suspend_reg11[i], i2c_clt1[i]);
+ es7210_read(ES7210_SDP_CFG2_REG12, &priv->suspend_reg12[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC_AUTOMUTE_REG13, &priv->suspend_reg13[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC34_MUTE_REG14, &priv->suspend_reg14[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC12_MUTE_REG15, &priv->suspend_reg15[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC_SEL_REG16, &priv->suspend_reg16[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC_COM_CFG1_REG17, &priv->suspend_reg17[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC34_LVL_REG18, &priv->suspend_reg18[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC12_LVL_REG19, &priv->suspend_reg19[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC_COM_CFG2_REG1A, &priv->suspend_reg1A[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC4_MAX_GAIN_REG1B, &priv->suspend_reg1B[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC3_MAX_GAIN_REG1C, &priv->suspend_reg1C[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC2_MAX_GAIN_REG1D, &priv->suspend_reg1D[i], i2c_clt1[i]);
+ es7210_read(ES7210_ALC1_MAX_GAIN_REG1E, &priv->suspend_reg1E[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC34_HPF2_REG20, &priv->suspend_reg20[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC34_HPF1_REG21, &priv->suspend_reg21[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC12_HPF2_REG22, &priv->suspend_reg22[i], i2c_clt1[i]);
+ es7210_read(ES7210_ADC12_HPF1_REG23, &priv->suspend_reg23[i], i2c_clt1[i]);
+ es7210_read(ES7210_ANALOG_SYS_REG40, &priv->suspend_reg40[i], i2c_clt1[i]);
+ es7210_read(ES7210_MICBIAS12_REG41, &priv->suspend_reg41[i], i2c_clt1[i]);
+ es7210_read(ES7210_MICBIAS34_REG42, &priv->suspend_reg42[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC1_GAIN_REG43, &priv->suspend_reg43[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC2_GAIN_REG44, &priv->suspend_reg44[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC3_GAIN_REG45, &priv->suspend_reg45[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC4_GAIN_REG46, &priv->suspend_reg46[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC1_LP_REG47, &priv->suspend_reg47[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC2_LP_REG48, &priv->suspend_reg48[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC3_LP_REG49, &priv->suspend_reg49[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC4_LP_REG4A, &priv->suspend_reg4A[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC12_PDN_REG4B, &priv->suspend_reg4B[i], i2c_clt1[i]);
+ es7210_read(ES7210_MIC34_PDN_REG4C, &priv->suspend_reg4C[i], i2c_clt1[i]);
+ }
+
+ es7210_init_reg = 0;
+
+ /* power down the controller */
+ if (priv->pvdd)
+ regulator_disable(priv->pvdd);
+ if (priv->dvdd)
+ regulator_disable(priv->dvdd);
+ if (priv->avdd)
+ regulator_disable(priv->avdd);
+ if (priv->mvdd)
+ regulator_disable(priv->mvdd);
+
+ return 0;
+}
+
+static int es7210_resume(struct snd_soc_component *component)
+{
+ int ret = 0, i = 0;
+ struct es7210_priv *priv = snd_soc_component_get_drvdata(component);
+
+ /* power up the controller */
+ if (priv->mvdd)
+ ret |= regulator_enable(priv->mvdd);
+ if (priv->avdd)
+ ret |= regulator_enable(priv->avdd);
+ if (priv->dvdd)
+ ret |= regulator_enable(priv->dvdd);
+ if (priv->pvdd)
+ ret |= regulator_enable(priv->pvdd);
+ if (ret) {
+ pr_err("Failed to enable VDD regulator: %d\n", ret);
+ return ret;
+ }
+ mdelay(10); // es7210 need 10ms setup time after power up.
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ es7210_write(ES7210_RESET_CTL_REG00, priv->suspend_reg00[i], i2c_clt1[i]);
+ es7210_write(ES7210_CLK_ON_OFF_REG01, priv->suspend_reg01[i], i2c_clt1[i]);
+ es7210_write(ES7210_MCLK_CTL_REG02, priv->suspend_reg02[i], i2c_clt1[i]);
+ es7210_write(ES7210_MST_CLK_CTL_REG03, priv->suspend_reg03[i], i2c_clt1[i]);
+ es7210_write(ES7210_MST_LRCDIVH_REG04, priv->suspend_reg04[i], i2c_clt1[i]);
+ es7210_write(ES7210_MST_LRCDIVL_REG05, priv->suspend_reg05[i], i2c_clt1[i]);
+ es7210_write(ES7210_DIGITAL_PDN_REG06, priv->suspend_reg06[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC_OSR_REG07, priv->suspend_reg07[i], i2c_clt1[i]);
+ es7210_write(ES7210_MODE_CFG_REG08, priv->suspend_reg08[i], i2c_clt1[i]);
+ es7210_write(ES7210_TCT0_CHPINI_REG09, priv->suspend_reg09[i], i2c_clt1[i]);
+ es7210_write(ES7210_TCT1_CHPINI_REG0A, priv->suspend_reg0A[i], i2c_clt1[i]);
+ es7210_write(ES7210_CHIP_STA_REG0B, priv->suspend_reg0B[i], i2c_clt1[i]);
+ es7210_write(ES7210_IRQ_CTL_REG0C, priv->suspend_reg0C[i], i2c_clt1[i]);
+ es7210_write(ES7210_MISC_CTL_REG0D, priv->suspend_reg0D[i], i2c_clt1[i]);
+ es7210_write(ES7210_DMIC_CTL_REG10, priv->suspend_reg10[i], i2c_clt1[i]);
+ es7210_write(ES7210_SDP_CFG1_REG11, priv->suspend_reg11[i], i2c_clt1[i]);
+ es7210_write(ES7210_SDP_CFG2_REG12, priv->suspend_reg12[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC_AUTOMUTE_REG13, priv->suspend_reg13[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC34_MUTE_REG14, priv->suspend_reg14[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC12_MUTE_REG15, priv->suspend_reg15[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC_SEL_REG16, priv->suspend_reg16[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC_COM_CFG1_REG17, priv->suspend_reg17[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC34_LVL_REG18, priv->suspend_reg18[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC12_LVL_REG19, priv->suspend_reg19[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC_COM_CFG2_REG1A, priv->suspend_reg1A[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC4_MAX_GAIN_REG1B, priv->suspend_reg1B[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC3_MAX_GAIN_REG1C, priv->suspend_reg1C[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC2_MAX_GAIN_REG1D, priv->suspend_reg1D[i], i2c_clt1[i]);
+ es7210_write(ES7210_ALC1_MAX_GAIN_REG1E, priv->suspend_reg1E[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC34_HPF2_REG20, priv->suspend_reg20[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC34_HPF1_REG21, priv->suspend_reg21[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC12_HPF2_REG22, priv->suspend_reg22[i], i2c_clt1[i]);
+ es7210_write(ES7210_ADC12_HPF1_REG23, priv->suspend_reg23[i], i2c_clt1[i]);
+ es7210_write(ES7210_ANALOG_SYS_REG40, priv->suspend_reg40[i], i2c_clt1[i]);
+ es7210_write(ES7210_MICBIAS12_REG41, priv->suspend_reg41[i], i2c_clt1[i]);
+ es7210_write(ES7210_MICBIAS34_REG42, priv->suspend_reg42[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC1_GAIN_REG43, priv->suspend_reg43[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC2_GAIN_REG44, priv->suspend_reg44[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC3_GAIN_REG45, priv->suspend_reg45[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC4_GAIN_REG46, priv->suspend_reg46[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC1_LP_REG47, priv->suspend_reg47[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC2_LP_REG48, priv->suspend_reg48[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC3_LP_REG49, priv->suspend_reg49[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC4_LP_REG4A, priv->suspend_reg4A[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC12_PDN_REG4B, priv->suspend_reg4B[i], i2c_clt1[i]);
+ es7210_write(ES7210_MIC34_PDN_REG4C, priv->suspend_reg4C[i], i2c_clt1[i]);
+ }
+
+ return ret;
+}
+#endif
+
+static int es7210_probe(struct snd_soc_component *component)
+{
+ struct es7210_priv *es7210 = snd_soc_component_get_drvdata(component);
+ u8 val, val1, cnt;
+ int ret = 0;
+ resume_es7210 = es7210;
+
+ /* power up the controller */
+ if (es7210->mvdd)
+ ret |= regulator_enable(es7210->mvdd);
+ if (es7210->avdd)
+ ret |= regulator_enable(es7210->avdd);
+ if (es7210->dvdd)
+ ret |= regulator_enable(es7210->dvdd);
+ if (es7210->pvdd)
+ ret |= regulator_enable(es7210->pvdd);
+ if (ret) {
+ pr_err("Failed to enable VDD regulator: %d\n", ret);
+ return ret;
+ }
+
+ tron_codec1[es7210_codec_num++] = component;
+
+ INIT_DELAYED_WORK(&es7210->pcm_pop_work, pcm_pop_work_events);
+
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ /* es7210 chip id */
+ ret = es7210_read(0x3D, &val, i2c_clt1[cnt]);
+ ret = es7210_read(0x3E, &val1, i2c_clt1[cnt]);
+ if (ret < 0) {
+ pr_err("%s: read chipid failed %d\n", __func__, ret);
+ goto exit_i2c_check_id_failed;
+ }
+ }
+
+ es7210_tdm_init_codec(es7210->tdm_mode);
+
+exit_i2c_check_id_failed:
+ return 0;
+}
+
+static void es7210_remove(struct snd_soc_component *component)
+{
+ struct es7210_priv *es7210 = snd_soc_component_get_drvdata(component);
+
+ /* power down the controller */
+ if (es7210->pvdd)
+ regulator_disable(es7210->pvdd);
+ if (es7210->dvdd)
+ regulator_disable(es7210->dvdd);
+ if (es7210->avdd)
+ regulator_disable(es7210->avdd);
+ if (es7210->mvdd)
+ regulator_disable(es7210->mvdd);
+}
+
+static int es7210_set_bias_level(struct snd_soc_component *component,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ break;
+ }
+ return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 300, 0);
+
+static int es7210_micboost1_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_micboost1_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(0x43, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+
+static int es7210_micboost2_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_micboost2_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(0x44, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+
+static int es7210_micboost3_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_micboost3_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(0x45, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost4_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_micboost4_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(0x46, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+
+static int es7210_adc1_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_adc1_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+
+static int es7210_adc2_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_adc2_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_adc3_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_adc3_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+static int es7210_adc4_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[0]);
+ return 0;
+}
+
+static int es7210_adc4_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[0]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_micboost5_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_micboost5_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(0x43, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost6_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_micboost6_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(0x44, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost7_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_micboost7_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(0x45, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost8_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_micboost8_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(0x46, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_adc5_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_adc5_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+
+static int es7210_adc6_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_adc6_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_adc7_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_adc7_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+static int es7210_adc8_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[1]);
+ return 0;
+}
+
+static int es7210_adc8_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[1] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[1]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_micboost9_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_micboost9_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(0x43, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost10_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_micboost10_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(0x44, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost11_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_micboost11_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(0x45, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost12_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_micboost12_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(0x46, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_adc9_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_adc9_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+
+static int es7210_adc10_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_adc10_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_adc11_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_adc11_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+static int es7210_adc12_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[2]);
+ return 0;
+}
+
+static int es7210_adc12_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[2] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[2]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_micboost13_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_micboost13_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(0x43, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost14_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_micboost14_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(0x44, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost15_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_micboost15_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(0x45, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_micboost16_setting_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_micboost16_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(0x46, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+}
+static int es7210_adc13_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_adc13_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+
+static int es7210_adc14_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_adc14_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static int es7210_adc15_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01,
+ ucontrol->value.integer.value[0]&0x01, i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_adc15_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = val & 0x01;
+ return 0;
+}
+static int es7210_adc16_mute_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02,
+ (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[3]);
+ return 0;
+}
+
+static int es7210_adc16_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 val;
+ if (i2c_clt1[3] == NULL)
+ return 0;
+ es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[3]);
+ ucontrol->value.integer.value[0] = (val & 0x02) >> 1;
+ return 0;
+}
+
+static const struct snd_kcontrol_new es7210_snd_controls[] = {
+ SOC_SINGLE_EXT_TLV("PGA1_setting",
+ 0x43, 0, 0x0E, 0,
+ es7210_micboost1_setting_get, es7210_micboost1_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA2_setting",
+ 0x44, 0, 0x0E, 0,
+ es7210_micboost2_setting_get, es7210_micboost2_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA3_setting",
+ 0x45, 0, 0x0E, 0,
+ es7210_micboost3_setting_get, es7210_micboost3_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA4_setting",
+ 0x46, 0, 0x0E, 0,
+ es7210_micboost4_setting_get, es7210_micboost4_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT("ADC1_MUTE", ES7210_ADC12_MUTE_REG15, 0, 1, 0,
+ es7210_adc1_mute_get, es7210_adc1_mute_set),
+ SOC_SINGLE_EXT("ADC2_MUTE", ES7210_ADC12_MUTE_REG15, 1, 1, 0,
+ es7210_adc2_mute_get, es7210_adc2_mute_set),
+ SOC_SINGLE_EXT("ADC3_MUTE", ES7210_ADC34_MUTE_REG14, 0, 1, 0,
+ es7210_adc3_mute_get, es7210_adc3_mute_set),
+ SOC_SINGLE_EXT("ADC4_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0,
+ es7210_adc4_mute_get, es7210_adc4_mute_set),
+ SOC_SINGLE_EXT_TLV("PGA5_setting",
+ 0x43, 0, 0x0E, 0,
+ es7210_micboost5_setting_get, es7210_micboost5_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA6_setting",
+ 0x44, 0, 0x0E, 0,
+ es7210_micboost6_setting_get, es7210_micboost6_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA7_setting",
+ 0x45, 0, 0x0E, 0,
+ es7210_micboost7_setting_get, es7210_micboost7_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA8_setting",
+ 0x46, 0, 0x0E, 0,
+ es7210_micboost8_setting_get, es7210_micboost8_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT("ADC5_MUTE", ES7210_ADC12_MUTE_REG15, 0, 1, 0,
+ es7210_adc5_mute_get, es7210_adc5_mute_set),
+ SOC_SINGLE_EXT("ADC6_MUTE", ES7210_ADC12_MUTE_REG15, 1, 1, 0,
+ es7210_adc6_mute_get, es7210_adc6_mute_set),
+ SOC_SINGLE_EXT("ADC7_MUTE", ES7210_ADC34_MUTE_REG14, 0, 1, 0,
+ es7210_adc7_mute_get, es7210_adc7_mute_set),
+ SOC_SINGLE_EXT("ADC8_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0,
+ es7210_adc8_mute_get, es7210_adc8_mute_set),
+ SOC_SINGLE_EXT_TLV("PGA9_setting",
+ 0x43, 0, 0x0E, 0,
+ es7210_micboost9_setting_get, es7210_micboost9_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA10_setting",
+ 0x44, 0, 0x0E, 0,
+ es7210_micboost10_setting_get, es7210_micboost10_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA11_setting",
+ 0x45, 0, 0x0E, 0,
+ es7210_micboost11_setting_get, es7210_micboost11_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA12_setting",
+ 0x46, 0, 0x0E, 0,
+ es7210_micboost12_setting_get, es7210_micboost12_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT("ADC9_MUTE", ES7210_ADC12_MUTE_REG15, 0, 1, 0,
+ es7210_adc9_mute_get, es7210_adc9_mute_set),
+ SOC_SINGLE_EXT("ADC10_MUTE", ES7210_ADC12_MUTE_REG15, 1, 1, 0,
+ es7210_adc10_mute_get, es7210_adc10_mute_set),
+ SOC_SINGLE_EXT("ADC11_MUTE", ES7210_ADC34_MUTE_REG14, 0, 1, 0,
+ es7210_adc11_mute_get, es7210_adc11_mute_set),
+ SOC_SINGLE_EXT("ADC12_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0,
+ es7210_adc12_mute_get, es7210_adc12_mute_set),
+ SOC_SINGLE_EXT_TLV("PGA13_setting",
+ 0x43, 0, 0x0E, 0,
+ es7210_micboost13_setting_get, es7210_micboost13_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA14_setting",
+ 0x44, 0, 0x0E, 0,
+ es7210_micboost14_setting_get, es7210_micboost14_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA15_setting",
+ 0x45, 0, 0x0E, 0,
+ es7210_micboost15_setting_get, es7210_micboost15_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT_TLV("PGA16_setting",
+ 0x46, 0, 0x0E, 0,
+ es7210_micboost16_setting_get, es7210_micboost16_setting_set,
+ mic_boost_tlv),
+ SOC_SINGLE_EXT("ADC13_MUTE", ES7210_ADC12_MUTE_REG15, 0, 1, 0,
+ es7210_adc13_mute_get, es7210_adc13_mute_set),
+ SOC_SINGLE_EXT("ADC14_MUTE", ES7210_ADC12_MUTE_REG15, 1, 1, 0,
+ es7210_adc14_mute_get, es7210_adc14_mute_set),
+ SOC_SINGLE_EXT("ADC15_MUTE", ES7210_ADC34_MUTE_REG14, 0, 1, 0,
+ es7210_adc15_mute_get, es7210_adc15_mute_set),
+ SOC_SINGLE_EXT("ADC16_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0,
+ es7210_adc16_mute_get, es7210_adc16_mute_set),
+};
+
+static struct snd_soc_component_driver soc_codec_dev_es7210 = {
+ .name = "es7210",
+ .probe = es7210_probe,
+ .remove = es7210_remove,
+#ifdef CONFIG_PM_SLEEP
+ .suspend = es7210_suspend,
+ .resume = es7210_resume,
+#endif
+ .set_bias_level = es7210_set_bias_level,
+ .controls = es7210_snd_controls,
+ .num_controls = ARRAY_SIZE(es7210_snd_controls),
+
+};
+
+static ssize_t es7210_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int val = 0, flag = 0;
+ u8 i = 0, reg, num, value_w, value_r;
+
+ struct es7210_priv *es7210 = dev_get_drvdata(dev);
+ val = simple_strtol(buf, NULL, 16);
+ flag = (val >> 16) & 0xFF;
+
+ if (flag) {
+ reg = (val >> 8) & 0xFF;
+ value_w = val & 0xFF;
+ printk("\nWrite: start REG:0x%02x,val:0x%02x,count:0x%02x\n", reg, value_w, flag);
+ while (flag--) {
+ es7210_write(reg, value_w, es7210->i2c_client);
+ printk("Write 0x%02x to REG:0x%02x\n", value_w, reg);
+ reg++;
+ }
+ } else {
+ reg = (val >> 8) & 0xFF;
+ num = val & 0xff;
+ printk("\nRead: start REG:0x%02x,count:0x%02x\n", reg, num);
+ do {
+ value_r = 0;
+ es7210_read(reg, &value_r, es7210->i2c_client);
+ printk("REG[0x%02x]: 0x%02x; ", reg, value_r);
+ reg++;
+ i++;
+ if ((i == num) || (i % 4 == 0)) printk("\n");
+ } while (i < num);
+ }
+
+ return count;
+}
+
+static ssize_t es7210_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 value, i;
+ struct es7210_priv *es7210 = dev_get_drvdata(dev);
+
+ printk("echo flag|reg|val > es7210\n");
+ printk("eg read star address=0x06,count 0x10:echo 0610 >es7210\n");
+ printk("eg write star address=0x90,value=0x3c,count=4:echo 4903c >es7210\n");
+
+ for (i = 0; i < 0x4d; i++) {
+ es7210_read(i, &value, es7210->i2c_client);
+ printk("reg[0x%x]=0x%x\n", i, value);
+ }
+ return 0;
+}
+
+static DEVICE_ATTR(es7210, 0644, es7210_show, es7210_store);
+
+static struct attribute *es7210_debug_attrs[] = {
+ &dev_attr_es7210.attr,
+ NULL,
+};
+
+static struct attribute_group es7210_debug_attr_group = {
+ .name = "es7210_debug",
+ .attrs = es7210_debug_attrs,
+};
+
+/*
+ * If the i2c layer weren't so broken, we could pass this kind of data
+ * around
+ */
+static int es7210_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *i2c_id)
+{
+ struct es7210_priv *es7210;
+ struct device_node *np = i2c_client->dev.of_node;
+ const char* property;
+ int ret;
+
+ es7210 = devm_kzalloc(&i2c_client->dev, sizeof(struct es7210_priv),
+ GFP_KERNEL);
+ if (es7210 == NULL)
+ return -ENOMEM;
+ es7210->i2c_client = i2c_client;
+
+ property = of_get_property(np, "work-mode", NULL);
+ if (property) {
+ if (!strcmp(property, "ES7210_TDM_1LRCK_DSPB")) {
+ es7210->tdm_mode = ES7210_TDM_1LRCK_DSPB;
+ } else if (!strcmp(property, "ES7210_NORMAL_I2S")) {
+ es7210->tdm_mode = ES7210_NORMAL_I2S;
+ } else {
+ pr_err("unsupported work mode\n");
+ return -EINVAL;
+ }
+ } else {
+ pr_warn("es7210 work-mode not defined.using ES7210_NORMAL_I2S by default\n");
+ es7210->tdm_mode = ES7210_NORMAL_I2S;
+ }
+
+ if (of_property_read_u32(np, "channels-max", &ES7210_CHANNELS_MAX) == 0) {
+ if (ES7210_CHANNELS_MAX == MIC_CHN_2 || ES7210_CHANNELS_MAX == MIC_CHN_4) {
+ ADC_DEV_MAXNUM = 1;
+ } else if (ES7210_CHANNELS_MAX == MIC_CHN_6 || ES7210_CHANNELS_MAX == MIC_CHN_8) {
+ ADC_DEV_MAXNUM = 2;
+ } else if (ES7210_CHANNELS_MAX == MIC_CHN_10 || ES7210_CHANNELS_MAX == MIC_CHN_12) {
+ ADC_DEV_MAXNUM = 3;
+ } else if (ES7210_CHANNELS_MAX == MIC_CHN_14 || ES7210_CHANNELS_MAX == MIC_CHN_16) {
+ ADC_DEV_MAXNUM = 4;
+ } else {
+ pr_err("es7210 unsupported channels-max\n");
+ return -EINVAL;
+ }
+ } else {
+ pr_warn("es7210 channels-max not defined.using MIC_CHN_2 by default\n");
+ ES7210_CHANNELS_MAX = MIC_CHN_2;
+ ADC_DEV_MAXNUM = 1;
+ }
+ pr_debug("%s es7210->tdm_mode=%d channels-max=%d ADC_DEV_MAXNUM=%d\n", __func__, es7210->tdm_mode, ES7210_CHANNELS_MAX, ADC_DEV_MAXNUM);
+
+ es7210->mvdd = devm_regulator_get(&i2c_client->dev, "MVDD");
+ if (IS_ERR(es7210->mvdd)) {
+ ret = PTR_ERR(es7210->mvdd);
+ dev_warn(&i2c_client->dev, "Failed to get MVDD regulator: %d\n", ret);
+ es7210->mvdd = NULL;
+ }
+ es7210->avdd = devm_regulator_get(&i2c_client->dev, "AVDD");
+ if (IS_ERR(es7210->avdd)) {
+ ret = PTR_ERR(es7210->avdd);
+ dev_warn(&i2c_client->dev, "Failed to get AVDD regulator: %d\n", ret);
+ es7210->avdd = NULL;
+ }
+ es7210->dvdd = devm_regulator_get(&i2c_client->dev, "DVDD");
+ if (IS_ERR(es7210->dvdd)) {
+ ret = PTR_ERR(es7210->dvdd);
+ dev_warn(&i2c_client->dev, "Failed to get DVDD regulator: %d\n", ret);
+ es7210->dvdd = NULL;
+ }
+ es7210->pvdd = devm_regulator_get(&i2c_client->dev, "PVDD");
+ if (IS_ERR(es7210->pvdd)) {
+ ret = PTR_ERR(es7210->pvdd);
+ dev_warn(&i2c_client->dev, "Failed to get PVDD regulator: %d\n", ret);
+ es7210->pvdd = NULL;
+ }
+
+ if (of_property_read_u32(np, "mclk-sclk-ratio", &es7210->mclk_sclk_ratio) != 0) {
+ es7210->mclk_sclk_ratio = 1;
+ }
+
+ i2c_set_clientdata(i2c_client, es7210);
+ if (i2c_id->driver_data < ADC_DEV_MAXNUM) {
+ i2c_clt1[i2c_id->driver_data] = i2c_client;
+ ret = devm_snd_soc_register_component(&i2c_client->dev, &soc_codec_dev_es7210,
+ es7210_dai[i2c_id->driver_data], 1);
+ if (ret < 0) {
+ kfree(es7210);
+ return ret;
+ }
+ }
+ ret = sysfs_create_group(&i2c_client->dev.kobj, &es7210_debug_attr_group);
+ if (ret) {
+ pr_err("failed to create attr group\n");
+ }
+ return ret;
+}
+
+
+static const struct i2c_device_id es7210_i2c_id[] = {
+ { "MicArray_0", 0 },//es7210_0
+ { "MicArray_1", 1 },//es7210_1
+ { "MicArray_2", 2 },//es7210_2
+ { "MicArray_3", 3 },//es7210_3
+ { }
+};
+MODULE_DEVICE_TABLE(i2c_client, es7210_i2c_id);
+
+static const struct of_device_id es7210_dt_ids[] = {
+ { .compatible = "MicArray_0", },//es7210_0
+ { .compatible = "MicArray_1", },//es7210_1
+ { .compatible = "MicArray_2", },//es7210_2
+ { .compatible = "MicArray_3", },//es7210_3
+ {}
+};
+MODULE_DEVICE_TABLE(of, es7210_dt_ids);
+
+static struct i2c_driver es7210_i2c_driver = {
+ .driver = {
+ .name = "es7210",
+ .owner = THIS_MODULE,
+ .of_match_table = es7210_dt_ids,
+ },
+ .probe = es7210_i2c_probe,
+ .id_table = es7210_i2c_id,
+
+};
+
+
+static int __init es7210_modinit(void)
+{
+ int ret;
+ ret = i2c_add_driver(&es7210_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register es7210 i2c driver : %d \n", ret);
+ return ret;
+
+}
+module_init(es7210_modinit);
+
+MODULE_DESCRIPTION("ASoC ES7210 audio adc driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/es7210.h b/sound/soc/codecs/es7210.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es7210.h
@@ -0,0 +1,140 @@
+/*
+ * ALSA SoC ES7210 codec driver
+ *
+ * Copyright: (C) 2018 Everest Semiconductor Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef _ES7210_H
+#define _ES7210_H
+
+#define ES7210_RESET_CTL_REG00 0x00
+#define ES7210_CLK_ON_OFF_REG01 0x01
+#define ES7210_MCLK_CTL_REG02 0x02
+#define ES7210_MST_CLK_CTL_REG03 0x03
+#define ES7210_MST_LRCDIVH_REG04 0x04
+#define ES7210_MST_LRCDIVL_REG05 0x05
+#define ES7210_DIGITAL_PDN_REG06 0x06
+#define ES7210_ADC_OSR_REG07 0x07
+#define ES7210_MODE_CFG_REG08 0x08
+
+#define ES7210_TCT0_CHPINI_REG09 0x09
+#define ES7210_TCT1_CHPINI_REG0A 0x0A
+#define ES7210_CHIP_STA_REG0B 0x0B
+
+#define ES7210_IRQ_CTL_REG0C 0x0C
+#define ES7210_MISC_CTL_REG0D 0x0D
+#define ES7210_DMIC_CTL_REG10 0x10
+
+#define ES7210_SDP_CFG1_REG11 0x11
+#define ES7210_SDP_CFG2_REG12 0x12
+
+#define ES7210_ADC_AUTOMUTE_REG13 0x13
+#define ES7210_ADC34_MUTE_REG14 0x14
+#define ES7210_ADC12_MUTE_REG15 0x15
+
+#define ES7210_ALC_SEL_REG16 0x16
+#define ES7210_ALC_COM_CFG1_REG17 0x17
+#define ES7210_ALC34_LVL_REG18 0x18
+#define ES7210_ALC12_LVL_REG19 0x19
+#define ES7210_ALC_COM_CFG2_REG1A 0x1A
+#define ES7210_ALC4_MAX_GAIN_REG1B 0x1B
+#define ES7210_ALC3_MAX_GAIN_REG1C 0x1C
+#define ES7210_ALC2_MAX_GAIN_REG1D 0x1D
+#define ES7210_ALC1_MAX_GAIN_REG1E 0x1E
+
+#define ES7210_ADC34_HPF2_REG20 0x20
+#define ES7210_ADC34_HPF1_REG21 0x21
+#define ES7210_ADC12_HPF2_REG22 0x22
+#define ES7210_ADC12_HPF1_REG23 0x23
+
+#define ES7210_CHP_ID1_REG3D 0x3D
+#define ES7210_CHP_ID0_REG3E 0x3E
+#define ES7210_CHP_VER_REG3F 0x3F
+
+#define ES7210_ANALOG_SYS_REG40 0x40
+
+#define ES7210_MICBIAS12_REG41 0x41
+#define ES7210_MICBIAS34_REG42 0x42
+#define ES7210_MIC1_GAIN_REG43 0x43
+#define ES7210_MIC2_GAIN_REG44 0x44
+#define ES7210_MIC3_GAIN_REG45 0x45
+#define ES7210_MIC4_GAIN_REG46 0x46
+#define ES7210_MIC1_LP_REG47 0x47
+#define ES7210_MIC2_LP_REG48 0x48
+#define ES7210_MIC3_LP_REG49 0x49
+#define ES7210_MIC4_LP_REG4A 0x4A
+#define ES7210_MIC12_PDN_REG4B 0x4B
+#define ES7210_MIC34_PDN_REG4C 0x4C
+
+/* codec private data */
+struct es7210_priv {
+ struct regmap *regmap;
+ struct i2c_client *i2c_client;
+ unsigned int dmic_enable;
+ unsigned int sysclk;
+ struct clk *mclk;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ struct regulator *mvdd;
+ struct regulator *avdd;
+ struct regulator *dvdd;
+ struct regulator *pvdd;
+ unsigned int tdm_mode;
+ struct delayed_work pcm_pop_work;
+ int mclk_lrck_ratio;
+ int pcm_format;
+ int mclk_sclk_ratio; // mclk_sclk_ratio=1 is when mclk hardwired to sclk.
+ int sclk_lrck_ratio;
+
+ u8 suspend_reg00[4];
+ u8 suspend_reg01[4];
+ u8 suspend_reg02[4];
+ u8 suspend_reg03[4];
+ u8 suspend_reg04[4];
+ u8 suspend_reg05[4];
+ u8 suspend_reg06[4];
+ u8 suspend_reg07[4];
+ u8 suspend_reg08[4];
+ u8 suspend_reg09[4];
+ u8 suspend_reg0A[4];
+ u8 suspend_reg0B[4];
+ u8 suspend_reg0C[4];
+ u8 suspend_reg0D[4];
+ u8 suspend_reg10[4];
+ u8 suspend_reg11[4];
+ u8 suspend_reg12[4];
+ u8 suspend_reg13[4];
+ u8 suspend_reg14[4];
+ u8 suspend_reg15[4];
+ u8 suspend_reg16[4];
+ u8 suspend_reg17[4];
+ u8 suspend_reg18[4];
+ u8 suspend_reg19[4];
+ u8 suspend_reg1A[4];
+ u8 suspend_reg1B[4];
+ u8 suspend_reg1C[4];
+ u8 suspend_reg1D[4];
+ u8 suspend_reg1E[4];
+ u8 suspend_reg20[4];
+ u8 suspend_reg21[4];
+ u8 suspend_reg22[4];
+ u8 suspend_reg23[4];
+ u8 suspend_reg40[4];
+ u8 suspend_reg41[4];
+ u8 suspend_reg42[4];
+ u8 suspend_reg43[4];
+ u8 suspend_reg44[4];
+ u8 suspend_reg45[4];
+ u8 suspend_reg46[4];
+ u8 suspend_reg47[4];
+ u8 suspend_reg48[4];
+ u8 suspend_reg49[4];
+ u8 suspend_reg4A[4];
+ u8 suspend_reg4B[4];
+ u8 suspend_reg4C[4];
+};
+
+#endif /* _ES7210_H_ */
diff --git a/sound/soc/codecs/es7210_config.c b/sound/soc/codecs/es7210_config.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es7210_config.c
@@ -0,0 +1,280 @@
+/*
+ * ALSA SoC ES7210 adc driver
+ *
+ * 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.^M
+ *
+ * Notes:
+ * ES7210 is a 4-ch ADC of Everest
+ */
+static int es7210_read(u8 reg, u8 * rt_value, struct i2c_client *client)
+{
+ int ret;
+ u8 read_cmd[3] = { 0 };
+ u8 cmd_len = 0;
+
+ read_cmd[0] = reg;
+ cmd_len = 1;
+
+ if (client->adapter == NULL)
+ printk("es7210_read client->adapter==NULL\n");
+
+ ret = i2c_master_send(client, read_cmd, cmd_len);
+ if (ret != cmd_len) {
+ printk("es7210_read error1\n");
+ return -1;
+ }
+
+ ret = i2c_master_recv(client, rt_value, 1);
+ if (ret != 1) {
+ printk("es7210_read error2, ret = %d.\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int es7210_write(u8 reg, unsigned char value, struct i2c_client *client)
+{
+ int ret = 0;
+ u8 write_cmd[2] = { 0 };
+
+ write_cmd[0] = reg;
+ write_cmd[1] = value;
+
+ ret = i2c_master_send(client, write_cmd, 2);
+ if (ret != 2) {
+ printk("es7210_write error->[REG-0x%02x,val-0x%02x]\n",
+ reg, value);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int es7210_update_bits(u8 reg, u8 mask, u8 value,
+ struct i2c_client *client)
+{
+ u8 val_old, val_new;
+
+ es7210_read(reg, &val_old, client);
+ val_new = (val_old & ~mask) | (value & mask);
+ if (val_new != val_old) {
+ es7210_write(reg, val_new, client);
+ }
+
+ return 0;
+}
+
+static int es7210_multi_chips_write(u8 reg, unsigned char value)
+{
+ u8 i;
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ es7210_write(reg, value, i2c_clt1[i]);
+ }
+
+ return 0;
+}
+
+static int es7210_multi_chips_update_bits(u8 reg, u8 mask, u8 value)
+{
+ u8 i;
+
+ for (i = 0; i < ADC_DEV_MAXNUM; i++) {
+ es7210_update_bits(reg, mask, value, i2c_clt1[i]);
+ }
+
+ return 0;
+}
+
+/*
+* to initialize es7210 for tdm mode
+*/
+static void es7210_tdm_init_codec(u8 mode)
+{
+ int cnt, channel;
+
+ for (cnt = 0;
+ cnt < sizeof(es7210_tdm_reg_common_cfg1) /
+ sizeof(es7210_tdm_reg_common_cfg1[0]); cnt++) {
+ es7210_multi_chips_write(es7210_tdm_reg_common_cfg1
+ [cnt].reg_addr,
+ es7210_tdm_reg_common_cfg1
+ [cnt].reg_v);
+ }
+ switch (mode) {
+ case ES7210_TDM_1LRCK_DSPA:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x63, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x01, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_1LRCK_DSPB:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x73, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x01, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_1LRCK_I2S:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x60, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x02, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_1LRCK_LJ:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x61, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x02, i2c_clt1[cnt]);
+ }
+ break;
+ case ES7210_TDM_NLRCK_DSPA:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x63, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x07, i2c_clt1[cnt]);
+ } else {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x03, i2c_clt1[cnt]);
+ }
+ }
+ break;
+ case ES7210_TDM_NLRCK_DSPB:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x73, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x07, i2c_clt1[cnt]);
+ } else {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x03, i2c_clt1[cnt]);
+ }
+ }
+ break;
+ case ES7210_TDM_NLRCK_I2S:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x60, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x07, i2c_clt1[cnt]);
+ } else {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x03, i2c_clt1[cnt]);
+ }
+ }
+ break;
+ case ES7210_TDM_NLRCK_LJ:
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ es7210_write(ES7210_SDP_CFG1_REG11,
+ 0x61, i2c_clt1[cnt]);
+ }
+ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) {
+ if (cnt == 0) {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x07, i2c_clt1[cnt]);
+ } else {
+ es7210_write(ES7210_SDP_CFG2_REG12,
+ 0x03, i2c_clt1[cnt]);
+ }
+ }
+ break;
+ case ES7210_NORMAL_I2S:
+ es7210_multi_chips_write(ES7210_SDP_CFG1_REG11, 0x60);
+ es7210_multi_chips_write(ES7210_SDP_CFG2_REG12, 0x00);
+ break;
+ case ES7210_NORMAL_LJ:
+ es7210_multi_chips_write(ES7210_SDP_CFG1_REG11, 0x61);
+ es7210_multi_chips_write(ES7210_SDP_CFG2_REG12, 0x00);
+ break;
+ case ES7210_NORMAL_DSPA:
+ es7210_multi_chips_write(ES7210_SDP_CFG1_REG11, 0x63);
+ es7210_multi_chips_write(ES7210_SDP_CFG2_REG12, 0x00);
+ break;
+ case ES7210_NORMAL_DSPB:
+ es7210_multi_chips_write(ES7210_SDP_CFG1_REG11, 0x73);
+ es7210_multi_chips_write(ES7210_SDP_CFG2_REG12, 0x00);
+ break;
+ default:
+ es7210_multi_chips_write(ES7210_SDP_CFG1_REG11, 0x60);
+ es7210_multi_chips_write(ES7210_SDP_CFG2_REG12, 0x00);
+ break;
+
+ }
+ for (cnt = 0;
+ cnt < sizeof(es7210_tdm_reg_common_cfg2) /
+ sizeof(es7210_tdm_reg_common_cfg2[0]); cnt++) {
+ es7210_multi_chips_write(es7210_tdm_reg_common_cfg2
+ [cnt].reg_addr,
+ es7210_tdm_reg_common_cfg2
+ [cnt].reg_v);
+ }
+ switch (mode) {
+ case ES7210_TDM_1LRCK_DSPA:
+ case ES7210_TDM_1LRCK_DSPB:
+ case ES7210_TDM_1LRCK_I2S:
+ case ES7210_TDM_1LRCK_LJ:
+ es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, 0xc1);
+ break;
+ case ES7210_TDM_NLRCK_DSPA:
+ case ES7210_TDM_NLRCK_DSPB:
+ case ES7210_TDM_NLRCK_I2S:
+ case ES7210_TDM_NLRCK_LJ:
+ channel = ES7210_CHANNELS_MAX / 2;
+ channel &= 0x0f;
+ channel = channel << 4;
+ printk("ADC Analg channel register = 0x%2x\n", channel);
+ es7210_multi_chips_write(ES7210_MODE_CFG_REG08, channel);
+ es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, 0x01);
+ break;
+ default:
+ es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, 0x41);
+ break;
+ }
+ for (cnt = 0; cnt < sizeof(es7210_tdm_reg_common_cfg3) /
+ sizeof(es7210_tdm_reg_common_cfg3[0]); cnt++) {
+ es7210_multi_chips_write(es7210_tdm_reg_common_cfg3
+ [cnt].reg_addr,
+ es7210_tdm_reg_common_cfg3
+ [cnt].reg_v);
+ }
+ /*
+ * Mute All ADC
+ */
+ es7210_multi_chips_update_bits(ES7210_ADC34_MUTE_REG14, 0x03, 0x03);
+ es7210_multi_chips_update_bits(ES7210_ADC12_MUTE_REG15, 0x03, 0x03);
+ /*
+ * Set Direct DB Gain
+ */
+ es7210_multi_chips_update_bits(ES7210_ALC_COM_CFG2_REG1A, 0x03, 0x00);
+ es7210_multi_chips_write(ES7210_ALC1_MAX_GAIN_REG1E, 0xBF);
+ es7210_multi_chips_write(ES7210_ALC2_MAX_GAIN_REG1D, 0xBF);
+ es7210_multi_chips_write(ES7210_ALC3_MAX_GAIN_REG1C, 0xBF);
+ es7210_multi_chips_write(ES7210_ALC4_MAX_GAIN_REG1B, 0xBF);
+}
diff --git a/sound/soc/codecs/es7210_config.h b/sound/soc/codecs/es7210_config.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es7210_config.h
@@ -0,0 +1,259 @@
+/*
+ * ALSA SoC ES7210 adc driver
+ *
+ * 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.^M
+ *
+ * Notes:
+ * ES7210 is a 4-ch ADC of Everest
+ * This is user configuration document.
+ * You can update this file according to your application
+ */
+#ifndef _ES7210_CONFIG_H
+#define _ES7210_CONFIG_H
+
+#define ENABLE 1
+#define DISABLE 0
+
+#define MIC_CHN_16 16
+#define MIC_CHN_14 14
+#define MIC_CHN_12 12
+#define MIC_CHN_10 10
+#define MIC_CHN_8 8
+#define MIC_CHN_6 6
+#define MIC_CHN_4 4
+#define MIC_CHN_2 2
+
+#define ES7210_TDM_ENABLE ENABLE
+#define ES7210_CHANNELS_MAX MIC_CHN_2
+
+#if ES7210_CHANNELS_MAX == MIC_CHN_2
+#define ADC_DEV_MAXNUM 1
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_4
+#define ADC_DEV_MAXNUM 1
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_6
+#define ADC_DEV_MAXNUM 2
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_8
+#define ADC_DEV_MAXNUM 2
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_10
+#define ADC_DEV_MAXNUM 3
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_12
+#define ADC_DEV_MAXNUM 3
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_14
+#define ADC_DEV_MAXNUM 4
+#endif
+#if ES7210_CHANNELS_MAX == MIC_CHN_16
+#define ADC_DEV_MAXNUM 4
+#endif
+
+#define ES7210_TDM_1LRCK_DSPA 0
+#define ES7210_TDM_1LRCK_DSPB 1
+#define ES7210_TDM_1LRCK_I2S 2
+#define ES7210_TDM_1LRCK_LJ 3
+#define ES7210_TDM_NLRCK_DSPA 4
+#define ES7210_TDM_NLRCK_DSPB 5
+#define ES7210_TDM_NLRCK_I2S 6
+#define ES7210_TDM_NLRCK_LJ 7
+#define ES7210_NORMAL_I2S 8
+#define ES7210_NORMAL_LJ 9
+#define ES7210_NORMAL_DSPA 10
+#define ES7210_NORMAL_DSPB 11
+
+#define ES7210_WORK_MODE ES7210_NORMAL_I2S
+
+#define RATIO_MCLK_LRCK_64 64
+#define RATIO_MCLK_LRCK_128 128
+#define RATIO_MCLK_LRCK_192 192
+#define RATIO_MCLK_LRCK_256 256
+#define RATIO_MCLK_LRCK_38 84
+#define RATIO_MCLK_LRCK_512 512
+#define RATIO_MCLK_LRCK_768 768
+#define RATIO_MCLK_LRCK_896 896
+#define RATIO_MCLK_LRCK_1024 1024
+#define RATIO_MCLK_LRCK_1152 1152
+#define RATIO_MCLK_LRCK_1280 1280
+#define RATIO_MCLK_LRCK_1408 1408
+#define RAITO_MCLK_LRCK_1536 1536
+#define RATIO_MCLK_LRCK_1664 1664
+#define RATIO_MCLK_LRCK_1792 1792
+#define RATIO_MCLK_LRCK_1920 1920
+#define RATIO_MCLK_LRCK_2048 2048
+#define RATIO_MCLK_LRCK_3072 3072
+#define RATIO_MCLK_LRCK_4096 4096
+
+#define RATIO_MCLK_LRCK RATIO_MCLK_LRCK_64
+
+#define ES7210_I2C_BUS_NUM 1
+#define ES7210_CODEC_RW_TEST_EN 0
+#define ES7210_IDLE_RESET_EN 1 //reset ES7210 when in idle time
+#define ES7210_MATCH_DTS_EN 1 //ES7210 match method select: 0: i2c_detect, 1:of_device_id
+
+struct i2c_client *i2c_clt1[ADC_DEV_MAXNUM];
+struct snd_soc_component *tron_codec1[ADC_DEV_MAXNUM];
+
+int es7210_init_reg = 0;
+static int es7210_codec_num = 0;
+struct es7210_reg_config {
+ unsigned char reg_addr;
+ unsigned char reg_v;
+};
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg1[] = {
+ {0x00, 0xFF},
+ {0x00, 0x32},
+ {0x09, 0x30},
+ {0x0A, 0x30},
+ {0x23, 0x2a},
+ {0x22, 0x0a},
+ {0x21, 0x2a},
+ {0x20, 0x0a},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_fmt_cfg[] = {
+ {0x11, 0x63},
+ {0x12, 0x01},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg2[] = {
+ {0x40, 0xC7},
+ {0x41, 0x70},
+ {0x42, 0x70},
+ {0x43, 0x10},
+ {0x44, 0x10},
+ {0x45, 0x10},
+ {0x46, 0x10},
+ {0x47, 0x08},
+ {0x48, 0x08},
+ {0x49, 0x08},
+ {0x4A, 0x08},
+ {0x07, 0x20},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_mclk_cfg[] = {
+ {0x02, 0xC1},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg3[] = {
+ {0x06, 0x00},
+ {0x4B, 0x0F},
+ {0x4C, 0x0F},
+ {0x00, 0x71},
+ {0x00, 0x41},
+};
+
+struct es7210_mclklrck_ratio_config {
+ int ratio;
+ unsigned char nfs;
+ unsigned char channels;
+ unsigned char reg02_v;
+ unsigned char reg06_v;
+};
+
+static const struct es7210_mclklrck_ratio_config es7210_1fs_ratio_cfg[] = {
+ //ratio, nfs, channels, reg02_v, reg06_v
+ {64, 0, 0, 0x41, 0x00},
+ {128, 0, 0, 0x01, 0x00},
+ {192, 0, 0, 0x43, 0x00},
+ {256, 0, 0, 0xc1, 0x04},
+ {384, 0, 0, 0x03, 0x00},
+ {512, 0, 0, 0x81, 0x04},
+ {768, 0, 0, 0xc3, 0x04},
+ {896, 0, 0, 0x07, 0x00},
+ {1024, 0, 0, 0x82, 0x04},
+ {1152, 0, 0, 0x09, 0x00},
+ {1280, 0, 0, 0x0a, 0x00},
+ {1408, 0, 0, 0x0b, 0x00},
+ {1536, 0, 0, 0xc6, 0x04},
+ {1664, 0, 0, 0x0d, 0x00},
+ {1792, 0, 0, 0xc7, 0x04},
+ {1920, 0, 0, 0x0f, 0x00},
+ {2048, 0, 0, 0x84, 0x04},
+ {3072, 0, 0, 0x86, 0x04},
+ {4096, 0, 0, 0x88, 0x04},
+};
+
+static const struct es7210_mclklrck_ratio_config es7210_nfs_ratio_cfg[] = {
+ //ratio, nfs, channels, reg02_v, reg06_v
+ {32, 1, 4, 0x41, 0x00},
+ {32, 1, 8, 0x01, 0x00},
+ {32, 1, 12, 0x43, 0x00},
+ {32, 1, 16, 0xC1, 0x04},
+
+ {64, 1, 4, 0x01, 0x00},
+ {64, 1, 6, 0x43, 0x00},
+ {64, 1, 8, 0xC1, 0x04},
+ {64, 1, 10, 0x45, 0x00},
+ {64, 1, 12, 0x03, 0x00},
+ {64, 1, 14, 0x47, 0x00},
+ {64, 1, 16, 0x81, 0x04},
+
+ {96, 1, 4, 0x43, 0x00},
+ {96, 1, 8, 0x03, 0x00},
+ {96, 1, 12, 0x49, 0x00},
+ {96, 1, 16, 0xc3, 0x04},
+
+ {128, 1, 4, 0xc1, 0x04},
+ {128, 1, 6, 0x03, 0x00},
+ {128, 1, 8, 0x81, 0x04},
+ {128, 1, 10, 0x05, 0x00},
+ {128, 1, 12, 0xc3, 0x04},
+ {128, 1, 14, 0x07, 0x00},
+ {128, 1, 16, 0x82, 0x04},
+
+ {192, 1, 4, 0x03, 0x00},
+ {192, 1, 6, 0x49, 0x00},
+ {192, 1, 8, 0xc3, 0x04},
+ {192, 1, 10, 0x4f, 0x00},
+ {192, 1, 12, 0x09, 0x00},
+ {192, 1, 14, 0x55, 0x00},
+ {192, 1, 16, 0x83, 0x04},
+
+ {256, 1, 4, 0x81, 0x04},
+ {256, 1, 6, 0xc3, 0x04},
+ {256, 1, 8, 0x82, 0x04},
+ {256, 1, 10, 0xc5, 0x04},
+ {256, 1, 12, 0x83, 0x04},
+ {256, 1, 14, 0xc7, 0x04},
+ {256, 1, 16, 0x84, 0x04},
+
+ {384, 1, 4, 0xc3, 0x04},
+ {384, 1, 6, 0x09, 0x00},
+ {384, 1, 8, 0x83, 0x04},
+ {384, 1, 10, 0x0f, 0x00},
+ {384, 1, 12, 0xc9, 0x04},
+ {384, 1, 14, 0x15, 0x00},
+ {384, 1, 16, 0x86, 0x04},
+
+ {512, 1, 4, 0x82, 0x04},
+ {512, 1, 6, 0x83, 0x04},
+ {512, 1, 8, 0x84, 0x04},
+ {512, 1, 10, 0x85, 0x04},
+ {512, 1, 12, 0x86, 0x04},
+ {512, 1, 14, 0x87, 0x04},
+ {512, 1, 16, 0x88, 0x04},
+
+ {768, 1, 4, 0x83, 0x04},
+ {768, 1, 6, 0xC9, 0x04},
+ {768, 1, 8, 0x86, 0x04},
+ {768, 1, 10, 0xCf, 0x04},
+ {768, 1, 12, 0x89, 0x04},
+ {768, 1, 14, 0xD5, 0x04},
+ {768, 1, 16, 0x8C, 0x04},
+
+ {1024, 1, 4, 0x84, 0x04},
+ {1024, 1, 6, 0x86, 0x04},
+ {1024, 1, 8, 0x88, 0x04},
+ {1024, 1, 10, 0x8a, 0x04},
+ {1024, 1, 12, 0x8c, 0x04},
+ {1024, 1, 14, 0x8e, 0x04},
+ {1024, 1, 16, 0x90, 0x04},
+
+};
+
+#endif
\ No newline at end of file
diff --git a/sound/soc/codecs/es7210_snd_controls.c b/sound/soc/codecs/es7210_snd_controls.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es7210_snd_controls.c
@@ -0,0 +1,174 @@
+/*
+ * ALSA SoC ES7210 adc driver
+ *
+ * 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.^M
+ *
+ * Notes:
+ * ES7210 is a 4-ch ADC of Everest
+ * This is user configuration document.
+ * You can update this file according to your application
+ */
+#include "es7210_config.h"
+
+struct i2c_client *i2c_clt1[ADC_DEV_MAXNUM];
+struct snd_soc_component *tron_codec1[ADC_DEV_MAXNUM];
+
+int es7210_init_reg = 0;
+static int es7210_codec_num = 0;
+struct es7210_reg_config {
+ unsigned char reg_addr;
+ unsigned char reg_v;
+};
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg1[] = {
+ {0x00, 0xFF},
+ {0x00, 0x32},
+ {0x09, 0x30},
+ {0x0A, 0x30},
+ {0x23, 0x2a},
+ {0x22, 0x0a},
+ {0x21, 0x2a},
+ {0x20, 0x0a},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_fmt_cfg[] = {
+ {0x11, 0x63},
+ {0x12, 0x01},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg2[] = {
+ {0x40, 0xC7},
+ {0x41, 0x70},
+ {0x42, 0x70},
+ {0x43, 0x10},
+ {0x44, 0x10},
+ {0x45, 0x10},
+ {0x46, 0x10},
+ {0x47, 0x08},
+ {0x48, 0x08},
+ {0x49, 0x08},
+ {0x4A, 0x08},
+ {0x07, 0x20},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_mclk_cfg[] = {
+ {0x02, 0xC1},
+};
+
+static const struct es7210_reg_config es7210_tdm_reg_common_cfg3[] = {
+ {0x06, 0x00},
+ {0x4B, 0x0F},
+ {0x4C, 0x0F},
+ {0x00, 0x71},
+ {0x00, 0x41},
+};
+
+struct es7210_mclklrck_ratio_config {
+ int ratio;
+ unsigned char nfs;
+ unsigned char channels;
+ unsigned char reg02_v;
+ unsigned char reg06_v;
+};
+
+static const struct es7210_mclklrck_ratio_config es7210_1fs_ratio_cfg[] = {
+ //ratio, nfs, channels, reg02_v, reg06_v
+ {64, 0, 0, 0x41, 0x00},
+ {128, 0, 0, 0x01, 0x00},
+ {192, 0, 0, 0x43, 0x00},
+ {256, 0, 0, 0xc1, 0x04},
+ {384, 0, 0, 0x03, 0x00},
+ {512, 0, 0, 0x81, 0x04},
+ {768, 0, 0, 0xc3, 0x04},
+ {896, 0, 0, 0x07, 0x00},
+ {1024, 0, 0, 0x82, 0x04},
+ {1152, 0, 0, 0x09, 0x00},
+ {1280, 0, 0, 0x0a, 0x00},
+ {1408, 0, 0, 0x0b, 0x00},
+ {1536, 0, 0, 0xc6, 0x04},
+ {1664, 0, 0, 0x0d, 0x00},
+ {1792, 0, 0, 0xc7, 0x04},
+ {1920, 0, 0, 0x0f, 0x00},
+ {2048, 0, 0, 0x84, 0x04},
+ {3072, 0, 0, 0x86, 0x04},
+ {4096, 0, 0, 0x88, 0x04},
+};
+
+static const struct es7210_mclklrck_ratio_config es7210_nfs_ratio_cfg[] = {
+ //ratio, nfs, channels, reg02_v, reg06_v
+ {32, 1, 4, 0x41, 0x00},
+ {32, 1, 8, 0x01, 0x00},
+ {32, 1, 12, 0x43, 0x00},
+ {32, 1, 16, 0xC1, 0x04},
+
+ {64, 1, 4, 0x01, 0x00},
+ {64, 1, 6, 0x43, 0x00},
+ {64, 1, 8, 0xC1, 0x04},
+ {64, 1, 10, 0x45, 0x00},
+ {64, 1, 12, 0x03, 0x00},
+ {64, 1, 14, 0x47, 0x00},
+ {64, 1, 16, 0x81, 0x04},
+
+ {96, 1, 4, 0x43, 0x00},
+ {96, 1, 8, 0x03, 0x00},
+ {96, 1, 12, 0x49, 0x00},
+ {96, 1, 16, 0xc3, 0x04},
+
+ {128, 1, 4, 0xc1, 0x04},
+ {128, 1, 6, 0x03, 0x00},
+ {128, 1, 8, 0x81, 0x04},
+ {128, 1, 10, 0x05, 0x00},
+ {128, 1, 12, 0xc3, 0x04},
+ {128, 1, 14, 0x07, 0x00},
+ {128, 1, 16, 0x82, 0x04},
+
+ {192, 1, 4, 0x03, 0x00},
+ {192, 1, 6, 0x49, 0x00},
+ {192, 1, 8, 0xc3, 0x04},
+ {192, 1, 10, 0x4f, 0x00},
+ {192, 1, 12, 0x09, 0x00},
+ {192, 1, 14, 0x55, 0x00},
+ {192, 1, 16, 0x83, 0x04},
+
+ {256, 1, 4, 0x81, 0x04},
+ {256, 1, 6, 0xc3, 0x04},
+ {256, 1, 8, 0x82, 0x04},
+ {256, 1, 10, 0xc5, 0x04},
+ {256, 1, 12, 0x83, 0x04},
+ {256, 1, 14, 0xc7, 0x04},
+ {256, 1, 16, 0x84, 0x04},
+
+ {384, 1, 4, 0xc3, 0x04},
+ {384, 1, 6, 0x09, 0x00},
+ {384, 1, 8, 0x83, 0x04},
+ {384, 1, 10, 0x0f, 0x00},
+ {384, 1, 12, 0xc9, 0x04},
+ {384, 1, 14, 0x15, 0x00},
+ {384, 1, 16, 0x86, 0x04},
+
+ {512, 1, 4, 0x82, 0x04},
+ {512, 1, 6, 0x83, 0x04},
+ {512, 1, 8, 0x84, 0x04},
+ {512, 1, 10, 0x85, 0x04},
+ {512, 1, 12, 0x86, 0x04},
+ {512, 1, 14, 0x87, 0x04},
+ {512, 1, 16, 0x88, 0x04},
+
+ {768, 1, 4, 0x83, 0x04},
+ {768, 1, 6, 0xC9, 0x04},
+ {768, 1, 8, 0x86, 0x04},
+ {768, 1, 10, 0xCf, 0x04},
+ {768, 1, 12, 0x89, 0x04},
+ {768, 1, 14, 0xD5, 0x04},
+ {768, 1, 16, 0x8C, 0x04},
+
+ {1024, 1, 4, 0x84, 0x04},
+ {1024, 1, 6, 0x86, 0x04},
+ {1024, 1, 8, 0x88, 0x04},
+ {1024, 1, 10, 0x8a, 0x04},
+ {1024, 1, 12, 0x8c, 0x04},
+ {1024, 1, 14, 0x8e, 0x04},
+ {1024, 1, 16, 0x90, 0x04},
+
+};
diff --git a/sound/soc/codecs/es8156.c b/sound/soc/codecs/es8156.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es8156.c
@@ -0,0 +1,872 @@
+/*
+ * es8156.c -- es8156 ALSA SoC audio driver
+ * Copyright Everest Semiconductor Co.,Ltd
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#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/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <linux/proc_fs.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include "es8156.h"
+
+#define INVALID_GPIO -1
+#define GPIO_LOW 0
+#define GPIO_HIGH 1
+#define es8156_DEF_VOL 0xBF
+#define ES8156_VOL_MAX 0xBF
+/*
+* If your system doesn't have MCLK, define this to 0 or the
+* driver will crash.
+*/
+#define MCLK 0
+
+static struct snd_soc_component *es8156_codec;
+
+static const struct reg_default es8156_reg_defaults[] = {
+ {0x00, 0x1c}, {0x01, 0x20}, {0x02, 0x00}, {0x03, 0x01},
+ {0x04, 0x00}, {0x05, 0x04}, {0x06, 0x11}, {0x07, 0x00},
+ {0x08, 0x06}, {0x09, 0x00}, {0x0a, 0x50}, {0x0b, 0x50},
+ {0x0c, 0x00}, {0x0d, 0x10}, {0x10, 0x40}, {0x10, 0x40},
+ {0x11, 0x00}, {0x12, 0x04}, {0x13, 0x11}, {0x14, 0xbf},
+ {0x15, 0x00}, {0x16, 0x00}, {0x17, 0xf7}, {0x18, 0x00},
+ {0x19, 0x20}, {0x1a, 0x00}, {0x20, 0x16}, {0x21, 0x7f},
+ {0x22, 0x00}, {0x23, 0x86}, {0x24, 0x00}, {0x25, 0x07},
+ {0xfc, 0x00}, {0xfd, 0x81}, {0xfe, 0x55}, {0xff, 0x10},
+};
+
+/* codec private data */
+struct es8156_priv {
+ struct regmap *regmap;
+ unsigned int dmic_amic;
+ unsigned int sysclk;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ struct clk *mclk;
+ struct regulator *avdd;
+ struct regulator *dvdd;
+ struct regulator *pvdd;
+ int debounce_time;
+ int hp_det_invert;
+ struct delayed_work work;
+
+ int spk_ctl_gpio;
+ int hp_det_gpio;
+ bool muted;
+ bool hp_inserted;
+ bool spk_active_level;
+
+ int pwr_count;
+ u32 mclk_sclk_ratio;
+
+ u32 suspend_reg_00;
+ u32 suspend_reg_01;
+ u32 suspend_reg_02;
+ u32 suspend_reg_03;
+ u32 suspend_reg_04;
+ u32 suspend_reg_05;
+ u32 suspend_reg_06;
+ u32 suspend_reg_07;
+ u32 suspend_reg_08;
+ u32 suspend_reg_09;
+ u32 suspend_reg_0A;
+ u32 suspend_reg_0B;
+ u32 suspend_reg_0C;
+ u32 suspend_reg_0D;
+ u32 suspend_reg_10;
+ u32 suspend_reg_11;
+ u32 suspend_reg_12;
+ u32 suspend_reg_13;
+ u32 suspend_reg_14;
+ u32 suspend_reg_15;
+ u32 suspend_reg_16;
+ u32 suspend_reg_17;
+ u32 suspend_reg_18;
+ u32 suspend_reg_19;
+ u32 suspend_reg_1A;
+ u32 suspend_reg_20;
+ u32 suspend_reg_21;
+ u32 suspend_reg_22;
+ u32 suspend_reg_23;
+ u32 suspend_reg_24;
+ u32 suspend_reg_25;
+};
+
+/*
+ * es8156_reset
+ */
+static int es8156_reset(struct snd_soc_component *codec)
+{
+ snd_soc_component_write(codec, ES8156_RESET_REG00, 0x1c);
+ usleep_range(5000, 5500);
+ return snd_soc_component_write(codec, ES8156_RESET_REG00, 0x03);
+}
+
+static void es8156_enable_spk(struct es8156_priv *es8156, bool enable)
+{
+ bool level;
+
+ level = enable ? es8156->spk_active_level : !es8156->spk_active_level;
+ gpio_set_value(es8156->spk_ctl_gpio, level);
+}
+
+
+static const char *es8156_DAC_SRC[] = { "Left to Left, Right to Right",
+"Right to both Left and Right","Left to both Left & Right", "Left to Right, Right to Left" };
+
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9600, 50, 1);
+static const DECLARE_TLV_DB_SCALE(alc_gain_tlv,-2800,400,1);
+static SOC_ENUM_SINGLE_DECL(es8165_dac_enum, ES8156_MISC_CONTROL3_REG18, 4, es8156_DAC_SRC);
+
+static const struct snd_kcontrol_new es8156_DAC_MUX =SOC_DAPM_ENUM("Route", es8165_dac_enum);
+
+static const struct snd_kcontrol_new es8156_snd_controls[] = {
+ SOC_SINGLE("Timer 1",ES8156_TIME_CONTROL1_REG0A,0,63,0),
+ SOC_SINGLE("Timer 2",ES8156_TIME_CONTROL2_REG0B,0,63,0),
+ SOC_SINGLE("DAC Automute Gate",ES8156_AUTOMUTE_SET_REG12,4,15,0),
+ SOC_SINGLE_TLV("ALC Gain",ES8156_ALC_CONFIG1_REG15,1,7,1,alc_gain_tlv),
+ SOC_SINGLE("ALC Ramp Rate",ES8156_ALC_CONFIG2_REG16,4,15,0),
+ SOC_SINGLE("ALC Window Size",ES8156_ALC_CONFIG2_REG16,0,15,0),
+ SOC_DOUBLE("ALC Maximum Minimum Volume",ES8156_ALC_CONFIG3_REG17,
+ 4,0,15,0),
+ /* DAC Digital controls */
+ SOC_SINGLE_TLV("DAC Playback Volume", ES8156_VOLUME_CONTROL_REG14,
+ 0, ES8156_VOL_MAX, 0, dac_vol_tlv),
+ SOC_SINGLE("HP Switch",ES8156_ANALOG_SYS3_REG22,3,1,0),
+
+
+};
+
+
+static const struct snd_soc_dapm_widget es8156_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_OUT("AIFSDOUT", "I2S Capture", 0,
+ ES8156_P2S_CONTROL_REG0D, 2, 0),
+
+ SND_SOC_DAPM_AIF_IN("SDIN", "I2S Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_MUX("Channel Select Mux", SND_SOC_NOPM, 0, 0,
+ &es8156_DAC_MUX),
+
+ SND_SOC_DAPM_DAC("DACL", "Left Playback", ES8156_DAC_MUTE_REG13, 1, 1),
+ SND_SOC_DAPM_DAC("DACR", "Right Playback", ES8156_DAC_MUTE_REG13, 2, 1),
+
+
+ SND_SOC_DAPM_PGA("SDOUT TRISTATE", ES8156_P2S_CONTROL_REG0D,
+ 0, 1, NULL, 0),
+
+ SND_SOC_DAPM_OUTPUT("SDOUT"),
+ SND_SOC_DAPM_OUTPUT("LOUT"),
+ SND_SOC_DAPM_OUTPUT("ROUT"),
+};
+
+/*************** parameter define ***************/
+#define STATEconfirm 0x0C
+#define NORMAL_I2S 0x00
+#define NORMAL_LJ 0x01
+#define NORMAL_DSPA 0x03
+#define NORMAL_DSPB 0x07
+#define Format_Len24 0x00
+#define Format_Len20 0x01
+#define Format_Len18 0x02
+#define Format_Len16 0x03
+#define Format_Len32 0x04
+
+#define VDDA_3V3 0x00
+#define VDDA_1V8 0x01
+#define MCLK_PIN 0x00
+#define SCLK_PIN 0x01
+
+/**************************************************/
+#define MSMode_MasterSelOn 0 // SlaveMode:0, MasterMode:1
+static unsigned int Ratio = 64; // Ratio = MCLK/LRCK on board
+#define Format NORMAL_I2S
+#define Format_Len Format_Len16 // data format
+#define SCLK_DIV 8 // SCLK_DIV = MCLK/SCLK
+#define SCLK_INV 0
+static unsigned int MCLK_SOURCE; // select MCLK source, MCLK_PIN or SCLK_PIN
+#define EQ7bandOn 0
+#define VDDA_VOLTAGE VDDA_3V3
+#define DAC_Volume 191 // DAC digital gain
+#define DACHPModeOn 0 // disable:0, enable:1
+
+/**************************************************/
+
+static int es8156_init_regs(struct snd_soc_component *codec)
+{
+ //struct es8156_priv *priv = snd_soc_component_get_drvdata(codec);
+ snd_soc_component_write(codec,0x02,(MCLK_SOURCE<<7) + (SCLK_INV<<4) + (EQ7bandOn<<3) + 0x04 + MSMode_MasterSelOn);
+ snd_soc_component_write(codec,0x19,0x20);
+
+ if (DACHPModeOn == 0) { // output from PA
+ snd_soc_component_write(codec,0x20,0x2A);
+ snd_soc_component_write(codec,0x21,0x3C);
+ snd_soc_component_write(codec,0x22,0x02);
+ snd_soc_component_write(codec,0x24,0x07);
+ snd_soc_component_write(codec,0x23,0x40 + (0x30*VDDA_VOLTAGE));
+ } else if (DACHPModeOn == 1) { // output from headphone
+ snd_soc_component_write(codec,0x20,0x16);
+ snd_soc_component_write(codec,0x21,0x3F);
+ snd_soc_component_write(codec,0x22,0x0A);
+ snd_soc_component_write(codec,0x24,0x01);
+ snd_soc_component_write(codec,0x23,0xCA + (0x30*VDDA_VOLTAGE));
+ }
+ snd_soc_component_write(codec,0x0A,0x01);
+ snd_soc_component_write(codec,0x0B,0x01);
+ //snd_soc_component_write(codec,0x11,NORMAL_I2S + (Format_Len<<4));
+
+ if (Ratio == 1536) {// Ratio=MCLK/LRCK=1536; 12M288/8K; 24M576/16K
+ snd_soc_component_write(codec,0x01,0x26 - (0x03*EQ7bandOn)); // 1536 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 1536 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x06); // LRCK H
+ snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/1536
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if (Ratio == 1024) {// Ratio=MCLK/LRCK=1024; 12M288/12K; 24M576/24K
+ snd_soc_component_write(codec,0x01,0x24 - (0x02*EQ7bandOn)); // 256 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 256 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x04); // LRCK H
+ snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/256
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if (Ratio == 768) {// Ratio=MCLK/LRCK=768; 12M288/16K; 24M576/32K
+ snd_soc_component_write(codec,0x01,0x23 + (0x40*EQ7bandOn)); // 768 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 768 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x03); // LRCK H
+ snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/768
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if (Ratio == 512) {// Ratio=MCLK/LRCK=512; 12M288/24K; 24M576/48K
+ snd_soc_component_write(codec,0x01,0xC0 + 0x22 - (0x01*EQ7bandOn)); // 512 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 512 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x02); // LRCK H
+ snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/512
+ snd_soc_component_write(codec,0x05,SCLK_DIV); //BCLK=MCLK/4
+ } else if (Ratio == 400) {// Ratio=MCLK/LRCK=400; 19M2/48K
+ // DVDD must be 3.3V
+ snd_soc_component_write(codec,0x01,0x21 + (0x40*EQ7bandOn)); // 384 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 400 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x10,0x64); // 400 OSR
+ snd_soc_component_write(codec,0x03,0x01); // LRCK H
+ snd_soc_component_write(codec,0x04,0x90); // LRCK=MCLK/400
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if (Ratio == 384) {// Ratio=MCLK/LRCK=384; 12M288/32K; 6M144/16K
+ snd_soc_component_write(codec,0x01,0x63 + (0x40*EQ7bandOn)); // 384 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 384 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x01); // LRCK H
+ snd_soc_component_write(codec,0x04,0x80); // LRCK=MCLK/384
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if (Ratio == 256) {// Ratio=MCLK/LRCK=256; 12M288/48K
+ snd_soc_component_write(codec,0x01,0x21 + (0x40*EQ7bandOn)); // 256 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 256 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x01); // LRCK H
+ snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/256
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if(Ratio == 128) {// Ratio=MCLK/LRCK=128; 6M144/48K
+ snd_soc_component_write(codec,0x01,0x61 + (0x40*EQ7bandOn)); // 128 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x00); // 128 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x00); // LRCK H
+ snd_soc_component_write(codec,0x04,0x80); // LRCK=MCLK/128
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4
+ } else if(Ratio == 64) {// Ratio=MCLK/LRCK=64; 3M072/48K
+ snd_soc_component_write(codec,0x01,0xE1); // 64 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x09,0x02); // 64 Ratio(MCLK/LRCK)
+ snd_soc_component_write(codec,0x03,0x00); // LRCK H
+ snd_soc_component_write(codec,0x04,0x40); // LRCK=MCLK/64
+ snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/2
+ }
+
+ snd_soc_component_write(codec,0x0D,0x14);
+ snd_soc_component_write(codec,0x18,0x00);
+ snd_soc_component_write(codec,0x08,0x3F);
+ snd_soc_component_write(codec,0x00,0x02);
+ snd_soc_component_write(codec,0x00,0x03);
+ snd_soc_component_write(codec,0x25,0x20);
+
+ return 0;
+}
+
+static int es8156_init_sequence(struct snd_soc_component *codec)
+{
+ es8156_init_regs(codec);
+ snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14, DAC_Volume);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_route es8156_dapm_routes[] = {
+ {"SDOUT TRISTATE",NULL,"SDIN"},
+ {"SDOUT",NULL,"SDOUT TRISTATE"},
+
+ {"Channel Select Mux","Left to Left, Right to Right","SDIN"},
+ {"Channel Select Mux","Right to both Left and Right","SDIN"},
+ {"Channel Select Mux","Left to both Left & Right","SDIN"},
+ {"Channel Select Mux","Left to Right, Right to Left","SDIN"},
+
+ {"DACL",NULL,"Channel Select Mux"},
+ {"DACR",NULL,"Channel Select Mux"},
+
+
+
+ { "LOUT", NULL, "DACL" },
+ { "ROUT", NULL, "DACR" },
+};
+
+static int es8156_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_component *codec = codec_dai->component;
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM://es8156 master
+ snd_soc_component_update_bits(codec, ES8156_SCLK_MODE_REG02, 0x01,0x01);
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS://es8156 slave
+ snd_soc_component_update_bits(codec, ES8156_SCLK_MODE_REG02, 0x01,0x00);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* interface format */
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x07,0x00);
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ return -EINVAL;
+ case SND_SOC_DAIFMT_LEFT_J:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x07,0x01);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x07,0x03);
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x07,0x07);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ snd_soc_component_update_bits(codec, ES8156_SCLK_MODE_REG02, 0x01,0x00);
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ snd_soc_component_update_bits(codec, ES8156_SCLK_MODE_REG02, 0x01,0x01);
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ snd_soc_component_update_bits(codec, ES8156_SCLK_MODE_REG02, 0x01,0x01);
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ snd_soc_component_update_bits(codec, ES8156_SCLK_MODE_REG02, 0x01,0x00);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static int es8156_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *codec = dai->component;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ 4096, UINT_MAX);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x70,0x30);
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x70,0x10);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x70,0x00);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_component_update_bits(codec, ES8156_DAC_SDP_REG11, 0x70,0x40);
+ break;
+ }
+ return 0;
+}
+
+static int es8156_set_bias_level(struct snd_soc_component *codec,
+ enum snd_soc_bias_level level)
+{
+ //int ret, i;
+ //struct es8156_priv *priv = snd_soc_component_get_drvdata(codec);
+
+ switch (level)
+ {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ break;
+ }
+ return 0;
+}
+
+#define es8156_RATES SNDRV_PCM_RATE_8000_96000
+
+#define es8156_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FORMAT_S32_LE)
+
+static struct snd_soc_dai_ops es8156_ops = {
+ .startup = NULL,
+ .hw_params = es8156_pcm_hw_params,
+ .set_fmt = es8156_set_dai_fmt,
+ .set_sysclk = NULL,
+ .shutdown = NULL,
+};
+
+static struct snd_soc_dai_driver es8156_dai = {
+ .name = "ES8156 HiFi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = es8156_RATES,
+ .formats = es8156_FORMATS,
+ },
+ .ops = &es8156_ops,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int es8156_suspend(struct snd_soc_component *codec)
+{
+ struct es8156_priv *priv = snd_soc_component_get_drvdata(codec);
+
+ pr_debug("Entered: %s\n", __func__);
+
+ es8156_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ priv->suspend_reg_00 = snd_soc_component_read(codec, ES8156_RESET_REG00);
+ priv->suspend_reg_01 = snd_soc_component_read(codec, ES8156_MAINCLOCK_CTL_REG01);
+ priv->suspend_reg_02 = snd_soc_component_read(codec, ES8156_SCLK_MODE_REG02);
+ priv->suspend_reg_03 = snd_soc_component_read(codec, ES8156_LRCLK_DIV_H_REG03);
+ priv->suspend_reg_04 = snd_soc_component_read(codec, ES8156_LRCLK_DIV_L_REG04);
+ priv->suspend_reg_05 = snd_soc_component_read(codec, ES8156_SCLK_DIV_REG05);
+ priv->suspend_reg_06 = snd_soc_component_read(codec, ES8156_NFS_CONFIG_REG06);
+ priv->suspend_reg_07 = snd_soc_component_read(codec, ES8156_MISC_CONTROL1_REG07);
+ priv->suspend_reg_08 = snd_soc_component_read(codec, ES8156_CLOCK_ON_OFF_REG08);
+ priv->suspend_reg_09 = snd_soc_component_read(codec, ES8156_MISC_CONTROL2_REG09);
+ priv->suspend_reg_0A = snd_soc_component_read(codec, ES8156_TIME_CONTROL1_REG0A);
+ priv->suspend_reg_0B = snd_soc_component_read(codec, ES8156_TIME_CONTROL2_REG0B);
+ priv->suspend_reg_0C = snd_soc_component_read(codec, ES8156_CHIP_STATUS_REG0C);
+ priv->suspend_reg_0D = snd_soc_component_read(codec, ES8156_P2S_CONTROL_REG0D);
+ priv->suspend_reg_10 = snd_soc_component_read(codec, ES8156_DAC_OSR_COUNTER_REG10);
+ priv->suspend_reg_11 = snd_soc_component_read(codec, ES8156_DAC_SDP_REG11);
+ priv->suspend_reg_12 = snd_soc_component_read(codec, ES8156_AUTOMUTE_SET_REG12);
+ priv->suspend_reg_13 = snd_soc_component_read(codec, ES8156_DAC_MUTE_REG13);
+ priv->suspend_reg_14 = snd_soc_component_read(codec, ES8156_VOLUME_CONTROL_REG14);
+ priv->suspend_reg_15 = snd_soc_component_read(codec, ES8156_ALC_CONFIG1_REG15);
+ priv->suspend_reg_16 = snd_soc_component_read(codec, ES8156_ALC_CONFIG2_REG16);
+ priv->suspend_reg_17 = snd_soc_component_read(codec, ES8156_ALC_CONFIG3_REG17);
+ priv->suspend_reg_18 = snd_soc_component_read(codec, ES8156_MISC_CONTROL3_REG18);
+ priv->suspend_reg_19 = snd_soc_component_read(codec, ES8156_EQ_CONTROL1_REG19);
+ priv->suspend_reg_1A = snd_soc_component_read(codec, ES8156_EQ_CONTROL2_REG1A);
+ priv->suspend_reg_20 = snd_soc_component_read(codec, ES8156_ANALOG_SYS1_REG20);
+ priv->suspend_reg_21 = snd_soc_component_read(codec, ES8156_ANALOG_SYS2_REG21);
+ priv->suspend_reg_22 = snd_soc_component_read(codec, ES8156_ANALOG_SYS3_REG22);
+ priv->suspend_reg_23 = snd_soc_component_read(codec, ES8156_ANALOG_SYS4_REG23);
+ priv->suspend_reg_24 = snd_soc_component_read(codec, ES8156_ANALOG_LP_REG24);
+ priv->suspend_reg_25 = snd_soc_component_read(codec, ES8156_ANALOG_SYS5_REG25);
+
+ return 0;
+}
+
+static int es8156_resume(struct snd_soc_component *codec)
+{
+ struct es8156_priv *priv = snd_soc_component_get_drvdata(codec);
+
+ pr_debug("Entered: %s\n", __func__);
+ snd_soc_component_write(codec, ES8156_RESET_REG00, priv->suspend_reg_00);
+ snd_soc_component_write(codec, ES8156_MAINCLOCK_CTL_REG01, priv->suspend_reg_01);
+ snd_soc_component_write(codec, ES8156_SCLK_MODE_REG02, priv->suspend_reg_02);
+ snd_soc_component_write(codec, ES8156_LRCLK_DIV_H_REG03, priv->suspend_reg_03);
+ snd_soc_component_write(codec, ES8156_LRCLK_DIV_L_REG04, priv->suspend_reg_04);
+ snd_soc_component_write(codec, ES8156_SCLK_DIV_REG05, priv->suspend_reg_05);
+ snd_soc_component_write(codec, ES8156_NFS_CONFIG_REG06, priv->suspend_reg_06);
+ snd_soc_component_write(codec, ES8156_MISC_CONTROL1_REG07, priv->suspend_reg_07);
+ snd_soc_component_write(codec, ES8156_CLOCK_ON_OFF_REG08, priv->suspend_reg_08);
+ snd_soc_component_write(codec, ES8156_MISC_CONTROL2_REG09, priv->suspend_reg_09);
+ snd_soc_component_write(codec, ES8156_TIME_CONTROL1_REG0A, priv->suspend_reg_0A);
+ snd_soc_component_write(codec, ES8156_TIME_CONTROL2_REG0B, priv->suspend_reg_0B);
+ snd_soc_component_write(codec, ES8156_CHIP_STATUS_REG0C, priv->suspend_reg_0C);
+ snd_soc_component_write(codec, ES8156_P2S_CONTROL_REG0D, priv->suspend_reg_0D);
+ snd_soc_component_write(codec, ES8156_DAC_OSR_COUNTER_REG10, priv->suspend_reg_10);
+ snd_soc_component_write(codec, ES8156_DAC_SDP_REG11, priv->suspend_reg_11);
+ snd_soc_component_write(codec, ES8156_AUTOMUTE_SET_REG12, priv->suspend_reg_12);
+ snd_soc_component_write(codec, ES8156_DAC_MUTE_REG13, priv->suspend_reg_13);
+ snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14, priv->suspend_reg_14);
+ snd_soc_component_write(codec, ES8156_ALC_CONFIG1_REG15, priv->suspend_reg_15);
+ snd_soc_component_write(codec, ES8156_ALC_CONFIG2_REG16, priv->suspend_reg_16);
+ snd_soc_component_write(codec, ES8156_ALC_CONFIG3_REG17, priv->suspend_reg_17);
+ snd_soc_component_write(codec, ES8156_MISC_CONTROL3_REG18, priv->suspend_reg_18);
+ snd_soc_component_write(codec, ES8156_EQ_CONTROL1_REG19, priv->suspend_reg_19);
+ snd_soc_component_write(codec, ES8156_EQ_CONTROL2_REG1A, priv->suspend_reg_1A);
+ snd_soc_component_write(codec, ES8156_ANALOG_SYS1_REG20, priv->suspend_reg_20);
+ snd_soc_component_write(codec, ES8156_ANALOG_SYS2_REG21, priv->suspend_reg_21);
+ snd_soc_component_write(codec, ES8156_ANALOG_SYS3_REG22, priv->suspend_reg_22);
+ snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23, priv->suspend_reg_23);
+ snd_soc_component_write(codec, ES8156_ANALOG_LP_REG24, priv->suspend_reg_24);
+ snd_soc_component_write(codec, ES8156_ANALOG_SYS5_REG25, priv->suspend_reg_25);
+
+ return 0;
+}
+#endif
+
+#ifdef HP_DET_FUNTION
+static irqreturn_t es8156_irq_handler(int irq, void *data)
+{
+ struct es8156_priv *es8156 = data;
+
+ queue_delayed_work(system_power_efficient_wq, &es8156->work,
+ msecs_to_jiffies(es8156->debounce_time));
+
+ return IRQ_HANDLED;
+}
+#endif
+
+/*
+ * Call from rk_headset_irq_hook_adc.c
+ *
+ * Enable micbias for HOOK detection and disable external Amplifier
+ * when jack insertion.
+ */
+int es8156_headset_detect(int jack_insert)
+{
+ struct es8156_priv *es8156;
+
+ if (!es8156_codec)
+ return -1;
+
+ es8156 = snd_soc_component_get_drvdata(es8156_codec);
+
+ es8156->hp_inserted = jack_insert;
+
+ /*enable micbias and disable PA*/
+ if (jack_insert) {
+ es8156_enable_spk(es8156, false);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(es8156_headset_detect);
+
+#ifdef HP_DET_FUNTION
+static void hp_work(struct work_struct *work)
+{
+ struct es8156_priv *es8156;
+ int enable;
+
+ es8156 = container_of(work, struct es8156_priv, work.work);
+ enable = gpio_get_value(es8156->hp_det_gpio);
+ if (es8156->hp_det_invert)
+ enable = !enable;
+
+ es8156->hp_inserted = enable ? true : false;
+ if (!es8156->muted) {
+ if (es8156->hp_inserted)
+ es8156_enable_spk(es8156, false);
+ else
+ es8156_enable_spk(es8156, true);
+ }
+}
+#endif
+
+static int es8156_probe(struct snd_soc_component *codec)
+{
+ struct es8156_priv *es8156 = snd_soc_component_get_drvdata(codec);
+ int ret = 0;
+
+ es8156_codec = codec;
+
+ /* power up the controller */
+ if (es8156->avdd)
+ ret |= regulator_enable(es8156->avdd);
+ if (es8156->dvdd)
+ ret |= regulator_enable(es8156->dvdd);
+ if (es8156->pvdd)
+ ret |= regulator_enable(es8156->pvdd);
+ if (ret) {
+ pr_err("Failed to enable VDD regulator: %d\n", ret);
+ return ret;
+ }
+
+#if MCLK
+ es8156->mclk = devm_clk_get(codec->dev, "mclk");
+ if (PTR_ERR(es8156->mclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ ret = clk_prepare_enable(es8156->mclk);
+#endif
+ es8156_reset(codec);
+ es8156_init_sequence(codec);
+ return ret;
+}
+
+static void es8156_remove(struct snd_soc_component *codec)
+{
+ struct es8156_priv *es8156 = snd_soc_component_get_drvdata(codec);
+
+ es8156_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ /* power down the controller */
+ if (es8156->pvdd)
+ regulator_disable(es8156->pvdd);
+ if (es8156->dvdd)
+ regulator_disable(es8156->dvdd);
+ if (es8156->avdd)
+ regulator_disable(es8156->avdd);
+}
+
+const struct regmap_config es8156_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = es8156_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(es8156_reg_defaults),
+};
+
+static struct snd_soc_component_driver soc_codec_dev_es8156 = {
+ .name = "es8156",
+ .probe = es8156_probe,
+ .remove = es8156_remove,
+#ifdef CONFIG_PM_SLEEP
+ .suspend = es8156_suspend,
+ .resume = es8156_resume,
+#endif
+ .set_bias_level = es8156_set_bias_level,
+ .controls = es8156_snd_controls,
+ .num_controls = ARRAY_SIZE(es8156_snd_controls),
+ .dapm_widgets = es8156_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(es8156_dapm_widgets),
+ .dapm_routes = es8156_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(es8156_dapm_routes),
+};
+
+static ssize_t es8156_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ return 0;
+}
+
+static ssize_t es8156_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ for (i = 0; i < 0x26; i++) {
+ printk("reg 0x%x = 0x%x\n", i, snd_soc_component_read(es8156_codec, i));
+ }
+
+ return 0;
+}
+
+static DEVICE_ATTR(registers, 0644, es8156_show, es8156_store);
+
+static struct attribute *es8156_debug_attrs[] = {
+ &dev_attr_registers.attr,
+ NULL,
+};
+
+static struct attribute_group es8516_debug_attr_group = {
+ .name = "es8156_debug",
+ .attrs = es8156_debug_attrs,
+};
+
+/*
+*es8156 7bit i2c address:CE pin:0 0x08 / CE pin:1 0x09
+*/
+static int es8156_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct es8156_priv *es8156;
+ int ret = -1;
+ struct device_node *np = i2c->dev.of_node;
+#ifdef HP_DET_FUNTION
+ int hp_irq;
+ enum of_gpio_flags flags;
+#endif
+ es8156 = devm_kzalloc(&i2c->dev, sizeof(*es8156), GFP_KERNEL);
+ if (!es8156)
+ return -ENOMEM;
+
+ es8156->debounce_time = 200;
+ es8156->hp_det_invert = 0;
+ es8156->pwr_count = 0;
+ es8156->hp_inserted = false;
+ es8156->muted = true;
+
+ es8156->regmap = devm_regmap_init_i2c(i2c, &es8156_regmap_config);
+ if (IS_ERR(es8156->regmap)) {
+ ret = PTR_ERR(es8156->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
+ es8156->avdd = devm_regulator_get(&i2c->dev, "AVDD");
+ if (IS_ERR(es8156->avdd)) {
+ ret = PTR_ERR(es8156->avdd);
+ dev_warn(&i2c->dev, "Failed to get AVDD regulator: %d\n", ret);
+ es8156->avdd = NULL;
+ }
+ es8156->dvdd = devm_regulator_get(&i2c->dev, "DVDD");
+ if (IS_ERR(es8156->dvdd)) {
+ ret = PTR_ERR(es8156->dvdd);
+ dev_warn(&i2c->dev, "Failed to get DVDD regulator: %d\n", ret);
+ es8156->dvdd = NULL;
+ }
+ es8156->pvdd = devm_regulator_get(&i2c->dev, "PVDD");
+ if (IS_ERR(es8156->pvdd)) {
+ ret = PTR_ERR(es8156->pvdd);
+ dev_warn(&i2c->dev, "Failed to get PVDD regulator: %d\n", ret);
+ es8156->pvdd = NULL;
+ }
+
+ if (of_property_read_u32(np, "mclk-sclk-ratio", &es8156->mclk_sclk_ratio) != 0) {
+ es8156->mclk_sclk_ratio = 1;
+ }
+
+ Ratio *= es8156->mclk_sclk_ratio;
+
+ if (es8156->mclk_sclk_ratio == 1) {
+ MCLK_SOURCE = SCLK_PIN;
+ } else {
+ MCLK_SOURCE = MCLK_PIN;
+ }
+
+ i2c_set_clientdata(i2c, es8156);
+#ifdef HP_DET_FUNTION
+ es8156->spk_ctl_gpio = of_get_named_gpio_flags(np,
+ "spk-con-gpio",
+ 0,
+ &flags);
+ if (es8156->spk_ctl_gpio < 0) {
+ dev_info(&i2c->dev, "Can not read property spk_ctl_gpio\n");
+ es8156->spk_ctl_gpio = INVALID_GPIO;
+ } else {
+ es8156->spk_active_level = !(flags & OF_GPIO_ACTIVE_LOW);
+ ret = devm_gpio_request_one(&i2c->dev, es8156->spk_ctl_gpio,
+ GPIOF_DIR_OUT, NULL);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to request spk_ctl_gpio\n");
+ return ret;
+ }
+ es8156_enable_spk(es8156, false);
+ }
+
+ es8156->hp_det_gpio = of_get_named_gpio_flags(np,
+ "hp-det-gpio",
+ 0,
+ &flags);
+ if (es8156->hp_det_gpio < 0) {
+ dev_info(&i2c->dev, "Can not read property hp_det_gpio\n");
+ es8156->hp_det_gpio = INVALID_GPIO;
+ } else {
+ INIT_DELAYED_WORK(&es8156->work, hp_work);
+ es8156->hp_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW);
+ ret = devm_gpio_request_one(&i2c->dev, es8156->hp_det_gpio,
+ GPIOF_IN, "hp det");
+ if (ret < 0)
+ return ret;
+ hp_irq = gpio_to_irq(es8156->hp_det_gpio);
+ ret = devm_request_threaded_irq(&i2c->dev, hp_irq, NULL,
+ es8156_irq_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT,
+ "es8156_interrupt", es8156);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "request_irq failed: %d\n", ret);
+ return ret;
+ }
+
+ schedule_delayed_work(&es8156->work,
+ msecs_to_jiffies(es8156->debounce_time));
+ }
+#endif
+ ret = snd_soc_register_component(&i2c->dev,
+ &soc_codec_dev_es8156,
+ &es8156_dai, 1);
+
+ ret = sysfs_create_group(&i2c->dev.kobj, &es8516_debug_attr_group);
+ if (ret) {
+ pr_err("failed to create attr group\n");
+ }
+
+ return ret;
+}
+
+static void es8156_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_component(&client->dev);
+ return ;
+}
+
+static void es8156_i2c_shutdown(struct i2c_client *client)
+{
+ struct es8156_priv *es8156 = i2c_get_clientdata(client);
+
+ if (es8156_codec != NULL) {
+ es8156_enable_spk(es8156, false);
+ msleep(20);
+ es8156_set_bias_level(es8156_codec, SND_SOC_BIAS_OFF);
+ }
+}
+
+static const struct i2c_device_id es8156_i2c_id[] = {
+ {"es8156", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, es8156_i2c_id);
+
+
+static const struct of_device_id es8156_of_match[] = {
+ { .compatible = "everest,es8156", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, es8156_of_match);
+
+static struct i2c_driver es8156_i2c_driver = {
+ .driver = {
+ .name = "es8156",
+ .of_match_table = es8156_of_match,
+ },
+ .probe = es8156_i2c_probe,
+ .remove = es8156_i2c_remove,
+ .shutdown = es8156_i2c_shutdown,
+ .id_table = es8156_i2c_id,
+};
+module_i2c_driver(es8156_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC es8156 driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/es8156.h b/sound/soc/codecs/es8156.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/sound/soc/codecs/es8156.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright Everest Semiconductor Co.,Ltd *
+ *
+ * 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.
+ *
+ */
+
+#ifndef _ES8156_H
+#define _ES8156_H
+
+/* ES8156 register space */
+/*
+* RESET Control
+*/
+#define ES8156_RESET_REG00 0x00
+/*
+* Clock Managerment
+*/
+#define ES8156_MAINCLOCK_CTL_REG01 0x01
+#define ES8156_SCLK_MODE_REG02 0x02
+#define ES8156_LRCLK_DIV_H_REG03 0x03
+#define ES8156_LRCLK_DIV_L_REG04 0x04
+#define ES8156_SCLK_DIV_REG05 0x05
+#define ES8156_NFS_CONFIG_REG06 0x06
+#define ES8156_MISC_CONTROL1_REG07 0x07
+#define ES8156_CLOCK_ON_OFF_REG08 0x08
+#define ES8156_MISC_CONTROL2_REG09 0x09
+#define ES8156_TIME_CONTROL1_REG0A 0x0a
+#define ES8156_TIME_CONTROL2_REG0B 0x0b
+/*
+* System Control
+*/
+#define ES8156_CHIP_STATUS_REG0C 0x0c
+#define ES8156_P2S_CONTROL_REG0D 0x0d
+#define ES8156_DAC_OSR_COUNTER_REG10 0x10
+/*
+* SDP Control
+*/
+#define ES8156_DAC_SDP_REG11 0x11
+#define ES8156_AUTOMUTE_SET_REG12 0x12
+#define ES8156_DAC_MUTE_REG13 0x13
+#define ES8156_VOLUME_CONTROL_REG14 0x14
+
+/*
+* ALC Control
+*/
+#define ES8156_ALC_CONFIG1_REG15 0x15
+#define ES8156_ALC_CONFIG2_REG16 0x16
+#define ES8156_ALC_CONFIG3_REG17 0x17
+#define ES8156_MISC_CONTROL3_REG18 0x18
+#define ES8156_EQ_CONTROL1_REG19 0x19
+#define ES8156_EQ_CONTROL2_REG1A 0x1a
+/*
+* Analog System Control
+*/
+#define ES8156_ANALOG_SYS1_REG20 0x20
+#define ES8156_ANALOG_SYS2_REG21 0x21
+#define ES8156_ANALOG_SYS3_REG22 0x22
+#define ES8156_ANALOG_SYS4_REG23 0x23
+#define ES8156_ANALOG_LP_REG24 0x24
+#define ES8156_ANALOG_SYS5_REG25 0x25
+/*
+* Chip Information
+*/
+#define ES8156_I2C_PAGESEL_REGFC 0xFC
+#define ES8156_CHIPID1_REGFD 0xFD
+#define ES8156_CHIPID0_REGFE 0xFE
+#define ES8156_CHIP_VERSION_REGFF 0xFF
+
+
+enum vmidlow {
+ VMIDLEVEL0,
+ VMIDLEVEL1,
+ VMIDLEVEL2,
+ VMIDLEVEL3,
+};
+
+#define ES8156_3V3 0
+#define ES8156_1V8 1
+#define ES8156_DVDD ES8156_1V8
+
+#endif
+
diff --git a/sound/soc/spacemit/spacemit-snd-pcm-dma.c b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
index 111111111111..222222222222 100644
--- a/sound/soc/spacemit/spacemit-snd-pcm-dma.c
+++ b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
@@ -591,6 +591,7 @@ spacemit_snd_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_sub
struct dma_tx_state state;
enum dma_status status;
unsigned int buf_size;
+ unsigned int preriod_size;
unsigned int pos = 0;
unsigned long flags;
@@ -598,8 +599,9 @@ spacemit_snd_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_sub
status = dmaengine_tx_status(dmadata->dma_chan, dmadata->cookie, &state);
if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
buf_size = I2S_PERIOD_SIZE * I2S_PERIOD_COUNT * 4;
+ preriod_size = I2S_PERIOD_SIZE * 4;
if (state.residue > 0 && state.residue <= buf_size) {
- pos = (buf_size - state.residue);
+ pos = ((buf_size - state.residue) / preriod_size) * preriod_size;
}
runtime->delay = bytes_to_frames(runtime, state.in_flight_bytes);
}
--
Armbian