From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Patrick Yavitz 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 Signed-off-by: Patrick Yavitz --- 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;lenlength) + 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;lenlength) + 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;lenlength) + 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;lenlength) + 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;lenlength) + 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;lenlength) + 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 #include #include +#include #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 #include +#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 #include #include +#if defined(CONFIG_SOC_SPACEMIT_K1X) +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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