mirror of
https://github.com/armbian/build.git
synced 2025-09-19 04:31:38 +02:00
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>
5005 lines
168 KiB
Diff
5005 lines
168 KiB
Diff
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(<8911exb->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(<8911exb->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(<9711->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(<9711->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(<9711->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, <9711_regmap_config);
|
||
@@ -280,7 +296,7 @@ static int lt9711_probe(struct i2c_client *client,
|
||
}
|
||
|
||
drm_panel_init(<9711->base, dev, <9711_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(<9711->init_work, init_work_func);
|
||
+ INIT_DELAYED_WORK(<9711->detect_work, detect_work_func);
|
||
+ schedule_delayed_work(<9711->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(<9711->detect_work);
|
||
+ lt9711->detect_work_pending = false;
|
||
+ }
|
||
|
||
- drm_panel_remove(<9711->base);
|
||
+ lt9711->connector = NULL;
|
||
+ lt9711->spacemit_dsi = NULL;
|
||
|
||
+ mipi_dsi_detach(lt9711->dsi);
|
||
+ drm_panel_remove(<9711->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
|
||
|