From f5f8cc31e99350ba9f94fe1d8bb302704209e2cd Mon Sep 17 00:00:00 2001 From: Martin Sekera Date: Wed, 22 Feb 2023 11:59:38 +0100 Subject: [PATCH] drop long deprecated sys-kernel/decade-sources --- .../decade-sources-5.13.19.ebuild | 25 - .../decade-sources-5.14.6.ebuild | 25 - .../patches-5.13/add-board-nanopi-m4v2.patch | 96 - .../add-csgpio-to-rockchip-spi.patch | 83 - .../patches-5.13/add-fusb30x-driver.patch | 4047 ---------- .../patches-5.13/add-maker-friendlyarm.patch | 211 - ...board-nanopi-m4v2-dts-add-sound-card.patch | 106 - ...board-nanopi-m4v2-dts-ethernet-tweak.patch | 15 - ...nanopi-m4v2-dts-fix-stability-issues.patch | 29 - ...roc-rk3399-pc-fix-fusb302-compatible.patch | 22 - ...dwmac-rk-Add-MAC-driver-support-for-.patch | 88 - ...ockchip-add-tsadc-support-for-rk3308.patch | 78 - ...d-support-for-rockchip-i2s-tdm-contr.patch | 1083 --- ...ecs-Add-RK3308-internal-codec-driver.patch | 2645 ------- ...s-0019-Sync-rk3308_codec-to-BSP-tree.patch | 6740 ----------------- ...308_codec-replace-codec-to-component.patch | 459 -- .../general-emmc-hs400es-init-tweak.patch | 22 - .../general-fix-es8316-kernel-panic.patch | 11 - ..._DMA_block_memory_allocation_to_2048.patch | 21 - .../general-rt5651-add-mclk.patch | 60 - .../rk3399-add-sclk-i2sout-src-clock.patch | 25 - ...k3399-enable-dwc3-xhci-usb-trb-quirk.patch | 20 - ...kchip-support-ep-gpio-undefined-case.patch | 28 - .../rk3399-sd-drive-level-8ma.patch | 49 - .../patches-5.14/add-board-nanopi-m4v2.patch | 95 - .../add-csgpio-to-rockchip-spi.patch | 83 - .../patches-5.14/add-fusb30x-driver.patch | 4047 ---------- .../patches-5.14/add-maker-friendlyarm.patch | 211 - ...board-nanopi-m4v2-dts-add-sound-card.patch | 106 - ...board-nanopi-m4v2-dts-ethernet-tweak.patch | 15 - ...nanopi-m4v2-dts-fix-stability-issues.patch | 29 - .../board-nanopi-r2s-r8152-mac-from-dt.patch | 40 - ...roc-rk3399-pc-fix-fusb302-compatible.patch | 22 - ...ockchip-add-tsadc-support-for-rk3308.patch | 77 - ...d-support-for-rockchip-i2s-tdm-contr.patch | 1083 --- ...IP-Sync-rockchip_i2s_tdm-to-BSP-tree.patch | 1981 ----- ...ecs-Add-RK3308-internal-codec-driver.patch | 2645 ------- ...s-0019-Sync-rk3308_codec-to-BSP-tree.patch | 6740 ----------------- ...308_codec-replace-codec-to-component.patch | 459 -- .../general-emmc-hs400es-init-tweak.patch | 22 - .../general-fix-es8316-kernel-panic.patch | 11 - ...fix-mmc-signal-voltage-before-reboot.patch | 43 - ..._DMA_block_memory_allocation_to_2048.patch | 21 - ...08-configurable-switch-voltage-steps.patch | 91 - .../general-rt5651-add-mclk.patch | 60 - .../rk3399-add-sclk-i2sout-src-clock.patch | 25 - ...k3399-enable-dwc3-xhci-usb-trb-quirk.patch | 20 - ...kchip-support-ep-gpio-undefined-case.patch | 28 - .../rk3399-sd-drive-level-8ma.patch | 49 - 49 files changed, 33991 deletions(-) delete mode 100644 sys-kernel/decade-sources/decade-sources-5.13.19.ebuild delete mode 100644 sys-kernel/decade-sources/decade-sources-5.14.6.ebuild delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/add-board-nanopi-m4v2.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/add-csgpio-to-rockchip-spi.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/add-fusb30x-driver.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/add-maker-friendlyarm.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-add-sound-card.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-ethernet-tweak.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-fix-stability-issues.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-roc-rk3399-pc-fix-fusb302-compatible.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0004-ethernet-stmmac-dwmac-rk-Add-MAC-driver-support-for-.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/general-emmc-hs400es-init-tweak.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/general-fix-es8316-kernel-panic.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/general-increasing_DMA_block_memory_allocation_to_2048.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/general-rt5651-add-mclk.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/rk3399-add-sclk-i2sout-src-clock.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.13/rk3399-sd-drive-level-8ma.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/add-board-nanopi-m4v2.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/add-csgpio-to-rockchip-spi.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/add-fusb30x-driver.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/add-maker-friendlyarm.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-add-sound-card.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-ethernet-tweak.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-fix-stability-issues.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-nanopi-r2s-r8152-mac-from-dt.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-roc-rk3399-pc-fix-fusb302-compatible.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0017-WIP-Sync-rockchip_i2s_tdm-to-BSP-tree.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/general-emmc-hs400es-init-tweak.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/general-fix-es8316-kernel-panic.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/general-fix-mmc-signal-voltage-before-reboot.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/general-increasing_DMA_block_memory_allocation_to_2048.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/general-rk808-configurable-switch-voltage-steps.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/general-rt5651-add-mclk.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/rk3399-add-sclk-i2sout-src-clock.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch delete mode 100644 sys-kernel/decade-sources/files/patches-5.14/rk3399-sd-drive-level-8ma.patch diff --git a/sys-kernel/decade-sources/decade-sources-5.13.19.ebuild b/sys-kernel/decade-sources/decade-sources-5.13.19.ebuild deleted file mode 100644 index fad735a..0000000 --- a/sys-kernel/decade-sources/decade-sources-5.13.19.ebuild +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 1999-2021 Gentoo Authors -# Distributed under the terms of the GNU General Public License v2 - -EAPI="7" -ETYPE="sources" - -inherit kernel-2 -detect_version -detect_arch - -KEYWORDS="~arm64" -HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches" - -DESCRIPTION="Full sources for the Linux ${KV_MAJOR}.${KV_MINOR} kernel tree." -SRC_URI="${KERNEL_URI}" - -src_prepare() { - DECADE_PATCHES=( ${FILESDIR}/patches-${KV_MAJOR}.${KV_MINOR}/*.patch ) - - for P in ${DECADE_PATCHES[@]}; do - eapply "${P}" - done - - kernel-2_src_prepare -} diff --git a/sys-kernel/decade-sources/decade-sources-5.14.6.ebuild b/sys-kernel/decade-sources/decade-sources-5.14.6.ebuild deleted file mode 100644 index 95b26de..0000000 --- a/sys-kernel/decade-sources/decade-sources-5.14.6.ebuild +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 1999-2021 Gentoo Authors -# Distributed under the terms of the GNU General Public License v2 - -EAPI="7" -ETYPE="sources" - -inherit kernel-2 -detect_version -detect_arch - -KEYWORDS="" -HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches" - -DESCRIPTION="Full sources for the Linux ${KV_MAJOR}.${KV_MINOR} kernel tree." -SRC_URI="${KERNEL_URI}" - -DECADE_PATCHES=( ${FILESDIR}/patches-${KV_MAJOR}.${KV_MINOR}/*.patch ) - -src_prepare() { - for P in ${DECADE_PATCHES[@]}; do - eapply "${P}" - done - - kernel-2_src_prepare -} diff --git a/sys-kernel/decade-sources/files/patches-5.13/add-board-nanopi-m4v2.patch b/sys-kernel/decade-sources/files/patches-5.13/add-board-nanopi-m4v2.patch deleted file mode 100644 index f95481d..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/add-board-nanopi-m4v2.patch +++ /dev/null @@ -1,96 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile -index c3e00c0e2db7..c41203318e3a 100644 ---- a/arch/arm64/boot/dts/rockchip/Makefile -+++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -34,6 +34,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-kobol-helios64.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-leez-p710.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4v2.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4b.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-neo4.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-r4s.dtb -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -new file mode 100644 -index 000000000..60358ab8c ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * FriendlyElec NanoPi M4V2 board device tree source -+ * -+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * Copyright (c) 2018 Collabora Ltd. -+ * Copyright (c) 2019 Arm Ltd. -+ */ -+ -+/dts-v1/; -+#include "rk3399-nanopi4.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi M4 Ver2.0"; -+ compatible = "friendlyarm,nanopi-m4", "rockchip,rk3399"; -+ -+ vdd_5v: vdd-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "vdd_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vcc5v0_core: vcc5v0-core { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_core"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vdd_5v>; -+ }; -+ -+ vcc5v0_usb1: vcc5v0-usb1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_usb1"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vcc5v0_usb2: vcc5v0-usb2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_usb2"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vdd_log: vdd-log { -+ compatible = "pwm-regulator"; -+ pwms = <&pwm2 0 25000 1>; -+ regulator-name = "vdd_log"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-init-microvolt = <900000>; -+ vin-supply = <&vcc5v0_core>; -+ }; -+}; -+ -+&vcc3v3_sys { -+ vin-supply = <&vcc5v0_core>; -+}; -+ -+&u2phy0_host { -+ phy-supply = <&vcc5v0_usb1>; -+}; -+ -+&u2phy1_host { -+ phy-supply = <&vcc5v0_usb2>; -+}; -+ -+&vbus_typec { -+ regulator-always-on; -+ vin-supply = <&vdd_5v>; -+}; diff --git a/sys-kernel/decade-sources/files/patches-5.13/add-csgpio-to-rockchip-spi.patch b/sys-kernel/decade-sources/files/patches-5.13/add-csgpio-to-rockchip-spi.patch deleted file mode 100644 index b65a5b1..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/add-csgpio-to-rockchip-spi.patch +++ /dev/null @@ -1,83 +0,0 @@ -diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c -index 2cc6d99..19e05ad 100644 ---- a/drivers/spi/spi-rockchip.c -+++ b/drivers/spi/spi-rockchip.c -@@ -6,6 +6,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -185,6 +186,10 @@ struct rockchip_spi { - bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; - }; - -+struct rockchip_spi_data { -+ bool cs_gpio_requested; -+}; -+ - static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable) - { - writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR); -@@ -455,6 +460,50 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs, - return 1; - } - -+static int rockchip_spi_setup(struct spi_device *spi) -+{ -+ int ret = 0; -+ unsigned long flags = (spi->mode & SPI_CS_HIGH) ? -+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; -+ struct rockchip_spi_data *data = spi_get_ctldata(spi); -+ -+ if (!gpio_is_valid(spi->cs_gpio)) -+ return 0; -+ -+ if (!data) { -+ data = kzalloc(sizeof(*data), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ spi_set_ctldata(spi, data); -+ } -+ -+ if (!data->cs_gpio_requested) { -+ ret = gpio_request_one(spi->cs_gpio, flags, -+ dev_name(&spi->dev)); -+ if (!ret) -+ data->cs_gpio_requested = 1; -+ } else -+ ret = gpio_direction_output(spi->cs_gpio, flags); -+ -+ if (ret < 0) -+ dev_err(&spi->dev, "Failed to setup cs gpio(%d): %d\n", -+ spi->cs_gpio, ret); -+ -+ return ret; -+} -+ -+static void rockchip_spi_cleanup(struct spi_device *spi) -+{ -+ struct rockchip_spi_data *data = spi_get_ctldata(spi); -+ -+ if (data) { -+ if (data->cs_gpio_requested) -+ gpio_free(spi->cs_gpio); -+ kfree(data); -+ spi_set_ctldata(spi, NULL); -+ } -+} -+ - static int rockchip_spi_config(struct rockchip_spi *rs, - struct spi_device *spi, struct spi_transfer *xfer, - bool use_dma) -@@ -683,6 +732,8 @@ static int rockchip_spi_probe(struct platform_device *pdev) - ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT); - - ctlr->set_cs = rockchip_spi_set_cs; -+ ctlr->setup = rockchip_spi_setup; -+ ctlr->cleanup = rockchip_spi_cleanup; - ctlr->transfer_one = rockchip_spi_transfer_one; - ctlr->max_transfer_size = rockchip_spi_max_transfer_size; - ctlr->handle_err = rockchip_spi_handle_err; diff --git a/sys-kernel/decade-sources/files/patches-5.13/add-fusb30x-driver.patch b/sys-kernel/decade-sources/files/patches-5.13/add-fusb30x-driver.patch deleted file mode 100644 index 67233f0..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/add-fusb30x-driver.patch +++ /dev/null @@ -1,4047 +0,0 @@ -diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig -index 1abf76be2..7ad8b090c 100644 ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -92,6 +92,8 @@ source "drivers/staging/fbtft/Kconfig" - - source "drivers/staging/fsl-dpaa2/Kconfig" - -+source "drivers/staging/fusb30x/Kconfig" -+ - source "drivers/staging/most/Kconfig" - - source "drivers/staging/ks7010/Kconfig" -diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile -index ab0cbe881..2e308d901 100644 ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -36,6 +36,7 @@ obj-$(CONFIG_UNISYSSPAR) += unisys/ - obj-$(CONFIG_UNISYSSPAR) += unisys/ - obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ - obj-$(CONFIG_FB_TFT) += fbtft/ -+obj-$(CONFIG_FUSB_30X) += fusb30x/ - obj-$(CONFIG_MOST) += most/ - obj-$(CONFIG_KS7010) += ks7010/ - obj-$(CONFIG_GREYBUS) += greybus/ -diff --git a/drivers/staging/fusb30x/Kconfig b/drivers/staging/fusb30x/Kconfig -new file mode 100644 -index 000000000..5bb75270f ---- /dev/null -+++ b/drivers/staging/fusb30x/Kconfig -@@ -0,0 +1,10 @@ -+config FUSB_30X -+ tristate "Fairchild FUSB30X Type-C chip driver" -+ depends on I2C -+ help -+ This is a driver for the Fairchild FUSB302 Type-C chip. It supports -+ USB Type-C PD functionality controlled using I2C. -+ -+ This driver supports extcon reporting not yet implemented in the -+ mainline FUSB302 driver. -+ -diff --git a/drivers/staging/fusb30x/Makefile b/drivers/staging/fusb30x/Makefile -new file mode 100644 -index 000000000..1c8e35df3 ---- /dev/null -+++ b/drivers/staging/fusb30x/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_FUSB_30X) += fusb30x.o -diff --git a/drivers/staging/fusb30x/fusb30x.c b/drivers/staging/fusb30x/fusb30x.c -new file mode 100644 -index 000000000..56d22648c ---- /dev/null -+++ b/drivers/staging/fusb30x/fusb30x.c -@@ -0,0 +1,3434 @@ -+/* -+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd -+ * Author: Zain Wang -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * Some ideas are from chrome ec and fairchild GPL fusb302 driver. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "fusb30x.h" -+ -+#define FUSB302_MAX_REG (FUSB_REG_FIFO + 50) -+#define FUSB_MS_TO_NS(x) ((s64)x * 1000 * 1000) -+ -+#define TYPEC_CC_VOLT_OPEN 0 -+#define TYPEC_CC_VOLT_RA 1 -+#define TYPEC_CC_VOLT_RD 2 -+#define TYPEC_CC_VOLT_RP 3 -+ -+#define EVENT_CC BIT(0) -+#define EVENT_RX BIT(1) -+#define EVENT_TX BIT(2) -+#define EVENT_REC_RESET BIT(3) -+#define EVENT_WORK_CONTINUE BIT(5) -+#define EVENT_TIMER_MUX BIT(6) -+#define EVENT_TIMER_STATE BIT(7) -+#define EVENT_DELAY_CC BIT(8) -+#define FLAG_EVENT (EVENT_RX | EVENT_TIMER_MUX | \ -+ EVENT_TIMER_STATE) -+ -+#define PACKET_IS_CONTROL_MSG(header, type) \ -+ (PD_HEADER_CNT(header) == 0 && \ -+ PD_HEADER_TYPE(header) == type) -+ -+#define PACKET_IS_DATA_MSG(header, type) \ -+ (PD_HEADER_CNT(header) != 0 && \ -+ PD_HEADER_TYPE(header) == type) -+ -+/* -+ * DisplayPort modes capabilities -+ * ------------------------------- -+ * <31:24> : Reserved (always 0). -+ * <23:16> : UFP_D pin assignment supported -+ * <15:8> : DFP_D pin assignment supported -+ * <7> : USB 2.0 signaling (0b=yes, 1b=no) -+ * <6> : Plug | Receptacle (0b == plug, 1b == receptacle) -+ * <5:2> : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling -+ * Other bits are reserved. -+ * <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both ) -+ */ -+#define PD_DP_PIN_CAPS(x) ((((x) >> 6) & 0x1) ? (((x) >> 16) & 0x3f) \ -+ : (((x) >> 8) & 0x3f)) -+#define PD_DP_SIGNAL_GEN2(x) (((x) >> 3) & 0x1) -+ -+#define MODE_DP_PIN_A BIT(0) -+#define MODE_DP_PIN_B BIT(1) -+#define MODE_DP_PIN_C BIT(2) -+#define MODE_DP_PIN_D BIT(3) -+#define MODE_DP_PIN_E BIT(4) -+#define MODE_DP_PIN_F BIT(5) -+ -+/* Pin configs B/D/F support multi-function */ -+#define MODE_DP_PIN_MF_MASK (MODE_DP_PIN_B | MODE_DP_PIN_D | MODE_DP_PIN_F) -+/* Pin configs A/B support BR2 signaling levels */ -+#define MODE_DP_PIN_BR2_MASK (MODE_DP_PIN_A | MODE_DP_PIN_B) -+/* Pin configs C/D/E/F support DP signaling levels */ -+#define MODE_DP_PIN_DP_MASK (MODE_DP_PIN_C | MODE_DP_PIN_D | \ -+ MODE_DP_PIN_E | MODE_DP_PIN_F) -+ -+/* -+ * DisplayPort Status VDO -+ * ---------------------- -+ * <31:9> : Reserved (always 0). -+ * <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0. -+ * <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH -+ * <6> : Exit DP Alt mode: 0 == maintain, 1 == exit -+ * <5> : USB config : 0 == maintain current, 1 == switch to USB from DP -+ * <4> : Multi-function preference : 0 == no pref, 1 == MF preferred. -+ * <3> : enabled : is DPout on/off. -+ * <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM -+ * <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled. -+ * 01b == DFP_D connected, 10b == UFP_D connected, 11b == both. -+ */ -+#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 0x1) -+#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 0x1) -+#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 0x1) -+ -+static u8 fusb30x_port_used; -+static struct fusb30x_chip *fusb30x_port_info[256]; -+ -+static bool is_write_reg(struct device *dev, unsigned int reg) -+{ -+ if (reg >= FUSB_REG_FIFO) -+ return true; -+ else -+ return ((reg < (FUSB_REG_CONTROL4 + 1)) && (reg > 0x01)) ? -+ true : false; -+} -+ -+static bool is_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ if (reg > FUSB_REG_CONTROL4) -+ return true; -+ -+ switch (reg) { -+ case FUSB_REG_CONTROL0: -+ case FUSB_REG_CONTROL1: -+ case FUSB_REG_CONTROL3: -+ case FUSB_REG_RESET: -+ return true; -+ } -+ return false; -+} -+ -+struct regmap_config fusb302_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .writeable_reg = is_write_reg, -+ .volatile_reg = is_volatile_reg, -+ .max_register = FUSB302_MAX_REG, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ -+static void dump_notify_info(struct fusb30x_chip *chip) -+{ -+ dev_dbg(chip->dev, "port %d\n", chip->port_num); -+ dev_dbg(chip->dev, "orientation %d\n", chip->notify.orientation); -+ dev_dbg(chip->dev, "power_role %d\n", chip->notify.power_role); -+ dev_dbg(chip->dev, "data_role %d\n", chip->notify.data_role); -+ dev_dbg(chip->dev, "cc %d\n", chip->notify.is_cc_connected); -+ dev_dbg(chip->dev, "pd %d\n", chip->notify.is_pd_connected); -+ dev_dbg(chip->dev, "enter_mode %d\n", chip->notify.is_enter_mode); -+ dev_dbg(chip->dev, "pin support %d\n", -+ chip->notify.pin_assignment_support); -+ dev_dbg(chip->dev, "pin def %d\n", chip->notify.pin_assignment_def); -+ dev_dbg(chip->dev, "attention %d\n", chip->notify.attention); -+} -+ -+static const unsigned int fusb302_cable[] = { -+ EXTCON_USB, -+ EXTCON_USB_HOST, -+ EXTCON_CHG_USB_SDP, -+ EXTCON_CHG_USB_CDP, -+ EXTCON_CHG_USB_DCP, -+ EXTCON_CHG_USB_SLOW, -+ EXTCON_CHG_USB_FAST, -+ EXTCON_DISP_DP, -+ EXTCON_NONE, -+}; -+ -+static void fusb_set_pos_power(struct fusb30x_chip *chip, int max_vol, -+ int max_cur) -+{ -+ int i; -+ int pos_find; -+ int tmp; -+ -+ pos_find = 0; -+ for (i = PD_HEADER_CNT(chip->rec_head) - 1; i >= 0; i--) { -+ switch (CAP_POWER_TYPE(chip->rec_load[i])) { -+ case 0: -+ /* Fixed Supply */ -+ if ((CAP_FPDO_VOLTAGE(chip->rec_load[i]) * 50) <= -+ max_vol && -+ (CAP_FPDO_CURRENT(chip->rec_load[i]) * 10) <= -+ max_cur) { -+ chip->pos_power = i + 1; -+ tmp = CAP_FPDO_VOLTAGE(chip->rec_load[i]); -+ chip->pd_output_vol = tmp * 50; -+ tmp = CAP_FPDO_CURRENT(chip->rec_load[i]); -+ chip->pd_output_cur = tmp * 10; -+ pos_find = 1; -+ } -+ break; -+ case 1: -+ /* Battery */ -+ if ((CAP_VPDO_VOLTAGE(chip->rec_load[i]) * 50) <= -+ max_vol && -+ (CAP_VPDO_CURRENT(chip->rec_load[i]) * 10) <= -+ max_cur) { -+ chip->pos_power = i + 1; -+ tmp = CAP_VPDO_VOLTAGE(chip->rec_load[i]); -+ chip->pd_output_vol = tmp * 50; -+ tmp = CAP_VPDO_CURRENT(chip->rec_load[i]); -+ chip->pd_output_cur = tmp * 10; -+ pos_find = 1; -+ } -+ break; -+ default: -+ /* not meet battery caps */ -+ break; -+ } -+ if (pos_find) -+ break; -+ } -+} -+ -+static int fusb302_set_pos_power_by_charge_ic(struct fusb30x_chip *chip) -+{ -+ struct power_supply *psy = NULL; -+ union power_supply_propval val; -+ enum power_supply_property psp; -+ int max_vol, max_cur; -+ -+ max_vol = 0; -+ max_cur = 0; -+ psy = power_supply_get_by_phandle(chip->dev->of_node, "charge-dev"); -+ if (!psy || IS_ERR(psy)) -+ return -1; -+ -+ psp = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX; -+ if (power_supply_get_property(psy, psp, &val) == 0) -+ max_vol = val.intval / 1000; -+ -+ psp = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT; -+ if (power_supply_get_property(psy, psp, &val) == 0) -+ max_cur = val.intval / 1000; -+ -+ if (max_vol > 0 && max_cur > 0) -+ fusb_set_pos_power(chip, max_vol, max_cur); -+ -+ return 0; -+} -+ -+void fusb_irq_disable(struct fusb30x_chip *chip) -+{ -+ unsigned long irqflags = 0; -+ -+ spin_lock_irqsave(&chip->irq_lock, irqflags); -+ if (chip->enable_irq) { -+ disable_irq_nosync(chip->gpio_int_irq); -+ chip->enable_irq = 0; -+ } else { -+ dev_warn(chip->dev, "irq have already disabled\n"); -+ } -+ spin_unlock_irqrestore(&chip->irq_lock, irqflags); -+} -+ -+void fusb_irq_enable(struct fusb30x_chip *chip) -+{ -+ unsigned long irqflags = 0; -+ -+ spin_lock_irqsave(&chip->irq_lock, irqflags); -+ if (!chip->enable_irq) { -+ enable_irq(chip->gpio_int_irq); -+ chip->enable_irq = 1; -+ } -+ spin_unlock_irqrestore(&chip->irq_lock, irqflags); -+} -+ -+static void platform_fusb_notify(struct fusb30x_chip *chip) -+{ -+ bool plugged = false, flip = false, dfp = false, ufp = false, -+ dp = false, usb_ss = false, hpd = false; -+ union extcon_property_value property; -+ -+ if (chip->notify.is_cc_connected) -+ chip->notify.orientation = -+ (chip->cc_polarity == TYPEC_POLARITY_CC1) ? -+ CC1 : CC2; -+ -+ /* avoid notify repeated */ -+ if (memcmp(&chip->notify, &chip->notify_cmp, -+ sizeof(struct notify_info))) { -+ dump_notify_info(chip); -+ chip->notify.attention = false; -+ memcpy(&chip->notify_cmp, &chip->notify, -+ sizeof(struct notify_info)); -+ -+ plugged = chip->notify.is_cc_connected || -+ chip->notify.is_pd_connected; -+ if (chip->notify.orientation != NONE) -+ flip = (chip->notify.orientation == CC1) ? false : true; -+ dp = chip->notify.is_enter_mode; -+ -+ if (dp) { -+ dfp = true; -+ usb_ss = (chip->notify.pin_assignment_def & -+ MODE_DP_PIN_MF_MASK) ? true : false; -+ hpd = GET_DP_STATUS_HPD(chip->notify.dp_status); -+ } else if (chip->notify.data_role) { -+ dfp = true; -+ usb_ss = true; -+ } else if (plugged) { -+ ufp = true; -+ usb_ss = true; -+ } -+ -+ property.intval = flip; -+ extcon_set_property(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_TYPEC_POLARITY, property); -+ extcon_set_property(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_TYPEC_POLARITY, property); -+ extcon_set_property(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_TYPEC_POLARITY, property); -+ -+ property.intval = usb_ss; -+ extcon_set_property(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_SS, property); -+ extcon_set_property(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_SS, property); -+ extcon_set_property(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_SS, property); -+ extcon_set_state(chip->extcon, EXTCON_USB, ufp); -+ extcon_set_state(chip->extcon, EXTCON_USB_HOST, dfp); -+ extcon_set_state(chip->extcon, EXTCON_DISP_DP, dp && hpd); -+ extcon_sync(chip->extcon, EXTCON_USB); -+ extcon_sync(chip->extcon, EXTCON_USB_HOST); -+ extcon_sync(chip->extcon, EXTCON_DISP_DP); -+ if (chip->notify.power_role == POWER_ROLE_SINK && -+ chip->notify.is_pd_connected && -+ chip->pd_output_vol > 0 && chip->pd_output_cur > 0) { -+ extcon_set_state(chip->extcon, EXTCON_CHG_USB_FAST, true); -+ property.intval = -+ (chip->pd_output_cur << 15 | -+ chip->pd_output_vol); -+ extcon_set_property(chip->extcon, EXTCON_CHG_USB_FAST, -+ EXTCON_PROP_USB_TYPEC_POLARITY, -+ property); -+ extcon_sync(chip->extcon, EXTCON_CHG_USB_FAST); -+ } -+ } -+} -+ -+static bool platform_get_device_irq_state(struct fusb30x_chip *chip) -+{ -+ return !gpiod_get_value(chip->gpio_int); -+} -+ -+static void fusb_timer_start(struct hrtimer *timer, int ms) -+{ -+ ktime_t ktime; -+ -+ ktime = ktime_set(0, FUSB_MS_TO_NS(ms)); -+ hrtimer_start(timer, ktime, HRTIMER_MODE_REL); -+} -+ -+static void platform_set_vbus_lvl_enable(struct fusb30x_chip *chip, int vbus_5v, -+ int vbus_other) -+{ -+ bool gpio_vbus_value = false; -+ -+ gpio_vbus_value = gpiod_get_value(chip->gpio_vbus_5v); -+ if (chip->gpio_vbus_5v) { -+ gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_5v); -+ } -+ -+ if (chip->gpio_vbus_other) -+ gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_other); -+ -+ if (chip->gpio_discharge && !vbus_5v && gpio_vbus_value) { -+ gpiod_set_value(chip->gpio_discharge, 1); -+ msleep(20); -+ gpiod_set_value(chip->gpio_discharge, 0); -+ } -+} -+ -+static void set_state(struct fusb30x_chip *chip, enum connection_state state) -+{ -+ dev_dbg(chip->dev, "port %d, state %d\n", chip->port_num, state); -+ if (!state) -+ dev_info(chip->dev, "PD disabled\n"); -+ chip->conn_state = state; -+ chip->sub_state = 0; -+ chip->val_tmp = 0; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+} -+ -+static int tcpm_get_message(struct fusb30x_chip *chip) -+{ -+ u8 buf[32]; -+ int len; -+ -+ do { -+ regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, 3); -+ chip->rec_head = (buf[1] & 0xff) | ((buf[2] << 8) & 0xff00); -+ -+ len = PD_HEADER_CNT(chip->rec_head) << 2; -+ regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, len + 4); -+ /* ignore good_crc message */ -+ } while (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_GOODCRC)); -+ -+ memcpy(chip->rec_load, buf, len); -+ -+ return 0; -+} -+ -+static void fusb302_flush_rx_fifo(struct fusb30x_chip *chip) -+{ -+ regmap_write(chip->regmap, FUSB_REG_CONTROL1, CONTROL1_RX_FLUSH); -+} -+ -+static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2) -+{ -+ u32 val; -+ int *CC_MEASURE; -+ u32 store; -+ -+ *CC1 = TYPEC_CC_VOLT_OPEN; -+ *CC2 = TYPEC_CC_VOLT_OPEN; -+ -+ if (chip->cc_state & CC_STATE_TOGSS_CC1) -+ CC_MEASURE = CC1; -+ else -+ CC_MEASURE = CC2; -+ -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) { -+ regmap_read(chip->regmap, FUSB_REG_SWITCHES0, &store); -+ /* measure cc1 first */ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2 | -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2, -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2 | -+ SWITCHES0_MEAS_CC1); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ val &= STATUS0_BC_LVL; -+ *CC1 = val ? TYPEC_CC_VOLT_RP : TYPEC_CC_VOLT_OPEN; -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2 | -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2, -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2 | -+ SWITCHES0_MEAS_CC2); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ val &= STATUS0_BC_LVL; -+ *CC2 = val ? TYPEC_CC_VOLT_RP : TYPEC_CC_VOLT_OPEN; -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2, -+ store); -+ } else { -+ regmap_read(chip->regmap, FUSB_REG_SWITCHES0, &store); -+ val = store; -+ val &= ~(SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2); -+ if (chip->cc_state & CC_STATE_TOGSS_CC1) { -+ val |= SWITCHES0_MEAS_CC1 | SWITCHES0_PU_EN1; -+ } else { -+ val |= SWITCHES0_MEAS_CC2 | SWITCHES0_PU_EN2; -+ } -+ regmap_write(chip->regmap, FUSB_REG_SWITCHES0, val); -+ -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, chip->cc_meas_high); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ if (val & STATUS0_COMP) { -+ int retry = 3; -+ int comp_times = 0; -+ -+ while (retry--) { -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, chip->cc_meas_high); -+ usleep_range(250, 300); -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ if (val & STATUS0_COMP) { -+ comp_times++; -+ if (comp_times == 3) { -+ *CC_MEASURE = TYPEC_CC_VOLT_OPEN; -+ regmap_write(chip->regmap, FUSB_REG_SWITCHES0, store); -+ } -+ } -+ } -+ } else { -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, chip->cc_meas_low); -+ regmap_read(chip->regmap, FUSB_REG_MEASURE, &val); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ -+ if (val & STATUS0_COMP) -+ *CC_MEASURE = TYPEC_CC_VOLT_RD; -+ else -+ *CC_MEASURE = TYPEC_CC_VOLT_RA; -+ } -+ regmap_write(chip->regmap, FUSB_REG_SWITCHES0, store); -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, -+ chip->cc_meas_high); -+ } -+ -+ return 0; -+} -+ -+static void tcpm_set_cc_pull_mode(struct fusb30x_chip *chip, enum CC_MODE mode) -+{ -+ u8 val; -+ -+ switch (mode) { -+ case CC_PULL_UP: -+ if (chip->cc_polarity == TYPEC_POLARITY_CC1) -+ val = SWITCHES0_PU_EN1; -+ else -+ val = SWITCHES0_PU_EN2; -+ break; -+ case CC_PULL_DOWN: -+ val = SWITCHES0_PDWN1 | SWITCHES0_PDWN2; -+ break; -+ default: -+ val = 0; -+ break; -+ } -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2 | -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2, -+ val); -+ -+ if (chip->cc_meas_high && mode == CC_PULL_UP) -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, -+ chip->cc_meas_high); -+} -+ -+static int tcpm_set_cc(struct fusb30x_chip *chip, enum role_mode mode) -+{ -+ switch (mode) { -+ case ROLE_MODE_DFP: -+ tcpm_set_cc_pull_mode(chip, CC_PULL_UP); -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_MODE | CONTROL2_TOG_RD_ONLY, -+ CONTROL2_MODE_DFP | CONTROL2_TOG_RD_ONLY); -+ break; -+ case ROLE_MODE_UFP: -+ tcpm_set_cc_pull_mode(chip, CC_PULL_UP); -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_MODE | CONTROL2_TOG_RD_ONLY, -+ CONTROL2_MODE_UFP); -+ break; -+ case ROLE_MODE_DRP: -+ tcpm_set_cc_pull_mode(chip, CC_PULL_NONE); -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_MODE | CONTROL2_TOG_RD_ONLY, -+ CONTROL2_MODE_DRP | CONTROL2_TOG_RD_ONLY); -+ break; -+ default: -+ dev_err(chip->dev, "%s: Unsupport cc mode %d\n", -+ __func__, mode); -+ return -EINVAL; -+ break; -+ } -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, CONTROL2_TOGGLE, -+ CONTROL2_TOGGLE); -+ -+ return 0; -+} -+ -+static int tcpm_set_rx_enable(struct fusb30x_chip *chip, int enable) -+{ -+ u8 val = 0; -+ -+ if (enable) { -+ if (chip->cc_polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES0_MEAS_CC1; -+ else -+ val |= SWITCHES0_MEAS_CC2; -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2, -+ val); -+ fusb302_flush_rx_fifo(chip); -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_AUTO_CRC, SWITCHES1_AUTO_CRC); -+ } else { -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2, -+ 0); -+ regmap_update_bits(chip->regmap, -+ FUSB_REG_SWITCHES1, SWITCHES1_AUTO_CRC, 0); -+ } -+ -+ return 0; -+} -+ -+static int tcpm_set_msg_header(struct fusb30x_chip *chip) -+{ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_POWERROLE | SWITCHES1_DATAROLE, -+ (chip->notify.power_role << 7) | -+ (chip->notify.data_role << 4)); -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_SPECREV, 2 << 5); -+ return 0; -+} -+ -+static int tcpm_set_polarity(struct fusb30x_chip *chip, -+ enum typec_cc_polarity polarity) -+{ -+ u8 val = 0; -+ -+ if (chip->vconn_enabled) { -+ if (polarity) -+ val |= SWITCHES0_VCONN_CC1; -+ else -+ val |= SWITCHES0_VCONN_CC2; -+ } -+ -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) { -+ if (polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES0_MEAS_CC1; -+ else -+ val |= SWITCHES0_MEAS_CC2; -+ } else { -+ if (polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES0_MEAS_CC1 | SWITCHES0_PU_EN1; -+ else -+ val |= SWITCHES0_MEAS_CC2 | SWITCHES0_PU_EN2; -+ } -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_VCONN_CC1 | SWITCHES0_VCONN_CC2 | -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2, -+ val); -+ -+ val = 0; -+ if (polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES1_TXCC1; -+ else -+ val |= SWITCHES1_TXCC2; -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_TXCC1 | SWITCHES1_TXCC2, -+ val); -+ -+ chip->cc_polarity = polarity; -+ -+ return 0; -+} -+ -+static int tcpm_set_vconn(struct fusb30x_chip *chip, int enable) -+{ -+ u8 val = 0; -+ -+ if (enable) { -+ if (chip->cc_polarity == TYPEC_POLARITY_CC1) -+ val = SWITCHES0_VCONN_CC2; -+ else -+ val = SWITCHES0_VCONN_CC1; -+ } -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_VCONN_CC1 | SWITCHES0_VCONN_CC2, -+ val); -+ chip->vconn_enabled = (bool)enable; -+ return 0; -+} -+ -+static void fusb302_pd_reset(struct fusb30x_chip *chip) -+{ -+ regmap_write(chip->regmap, FUSB_REG_RESET, RESET_PD_RESET); -+ regmap_reinit_cache(chip->regmap, &fusb302_regmap_config); -+} -+ -+static void tcpm_select_rp_value(struct fusb30x_chip *chip, u32 rp) -+{ -+ u32 control0_reg; -+ -+ regmap_read(chip->regmap, FUSB_REG_CONTROL0, &control0_reg); -+ -+ control0_reg &= ~CONTROL0_HOST_CUR; -+ /* -+ * according to the host current, the compare value is different -+ * Fusb302 datasheet Table 3 -+ */ -+ switch (rp) { -+ /* -+ * host pull up current is 80ua , high voltage is 1.596v, -+ * low is 0.21v -+ */ -+ case TYPEC_RP_USB: -+ chip->cc_meas_high = 0x26; -+ chip->cc_meas_low = 0x5; -+ control0_reg |= CONTROL0_HOST_CUR_USB; -+ break; -+ /* -+ * host pull up current is 330ua , high voltage is 2.604v, -+ * low is 0.798v -+ */ -+ case TYPEC_RP_3A0: -+ chip->cc_meas_high = 0x3e; -+ chip->cc_meas_low = 0x13; -+ control0_reg |= CONTROL0_HOST_CUR_3A0; -+ break; -+ /* -+ * host pull up current is 180ua , high voltage is 1.596v, -+ * low is 0.42v -+ */ -+ case TYPEC_RP_1A5: -+ default: -+ chip->cc_meas_high = 0x26; -+ chip->cc_meas_low = 0xa; -+ control0_reg |= CONTROL0_HOST_CUR_1A5; -+ break; -+ } -+ -+ regmap_write(chip->regmap, FUSB_REG_CONTROL0, control0_reg); -+} -+ -+static int tcpm_check_vbus(struct fusb30x_chip *chip) -+{ -+ u32 val; -+ -+ /* Read status register */ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ -+ return (val & STATUS0_VBUSOK) ? 1 : 0; -+} -+ -+static void tcpm_init(struct fusb30x_chip *chip) -+{ -+ u8 val; -+ u32 tmp; -+ -+ regmap_read(chip->regmap, FUSB_REG_DEVICEID, &tmp); -+ chip->chip_id = (u8)tmp; -+ platform_set_vbus_lvl_enable(chip, 0, 0); -+ chip->notify.is_cc_connected = false; -+ chip->cc_state = 0; -+ -+ /* restore default settings */ -+ regmap_update_bits(chip->regmap, FUSB_REG_RESET, RESET_SW_RESET, -+ RESET_SW_RESET); -+ fusb302_pd_reset(chip); -+ /* set auto_retry and number of retries */ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL3, -+ CONTROL3_AUTO_RETRY | CONTROL3_N_RETRIES, -+ CONTROL3_AUTO_RETRY | CONTROL3_N_RETRIES), -+ -+ /* set interrupts */ -+ val = 0xff; -+ val &= ~(MASK_M_COLLISION | MASK_M_ALERT | MASK_M_VBUSOK); -+ regmap_write(chip->regmap, FUSB_REG_MASK, val); -+ -+ val = 0xff; -+ val &= ~(MASKA_M_RETRYFAIL | MASKA_M_HARDSENT | MASKA_M_TXSENT | -+ MASKA_M_HARDRST | MASKA_M_TOGDONE); -+ regmap_write(chip->regmap, FUSB_REG_MASKA, val); -+ -+ val = ~MASKB_M_GCRCSEND; -+ regmap_write(chip->regmap, FUSB_REG_MASKB, val); -+ -+ tcpm_select_rp_value(chip, TYPEC_RP_1A5); -+ /* Interrupts Enable */ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL0, CONTROL0_INT_MASK, -+ ~CONTROL0_INT_MASK); -+ -+ tcpm_set_vconn(chip, 0); -+ -+ regmap_write(chip->regmap, FUSB_REG_POWER, 0xf); -+} -+ -+static void pd_execute_hard_reset(struct fusb30x_chip *chip) -+{ -+ chip->msg_id = 0; -+ chip->vdm_state = VDM_STATE_DISCOVERY_ID; -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_transition_default); -+ else -+ set_state(chip, policy_snk_transition_default); -+} -+ -+static void tcpc_alert(struct fusb30x_chip *chip, u32 *evt) -+{ -+ int interrupt, interrupta, interruptb; -+ u32 val; -+ static int retry; -+ -+ regmap_read(chip->regmap, FUSB_REG_INTERRUPT, &interrupt); -+ regmap_read(chip->regmap, FUSB_REG_INTERRUPTA, &interrupta); -+ regmap_read(chip->regmap, FUSB_REG_INTERRUPTB, &interruptb); -+ -+ if ((interrupt & INTERRUPT_COMP_CHNG) && -+ (!(chip->cc_state & CC_STATE_TOGSS_IS_UFP))) { -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ if (val & STATUS0_COMP) -+ *evt |= EVENT_CC; -+ } -+ -+ if (interrupt & INTERRUPT_VBUSOK) { -+ if (chip->notify.is_cc_connected) -+ *evt |= EVENT_CC; -+ } -+ -+ if (interrupta & INTERRUPTA_TOGDONE) { -+ *evt |= EVENT_CC; -+ regmap_read(chip->regmap, FUSB_REG_STATUS1A, &val); -+ chip->cc_state = ((u8)val >> 3) & 0x07; -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_TOGGLE, -+ 0); -+ } -+ -+ if (interrupta & INTERRUPTA_TXSENT) { -+ *evt |= EVENT_TX; -+ chip->tx_state = tx_success; -+ } -+ -+ if (interruptb & INTERRUPTB_GCRCSENT) -+ *evt |= EVENT_RX; -+ -+ if (interrupta & INTERRUPTA_HARDRST) { -+ fusb302_pd_reset(chip); -+ pd_execute_hard_reset(chip); -+ *evt |= EVENT_REC_RESET; -+ } -+ -+ if (interrupta & INTERRUPTA_RETRYFAIL) { -+ *evt |= EVENT_TX; -+ chip->tx_state = tx_failed; -+ } -+ -+ if (interrupta & INTERRUPTA_HARDSENT) { -+ /* -+ * The fusb PD should be reset once to sync adapter PD -+ * signal after fusb sent hard reset cmd.This is not PD -+ * device if reset failed. -+ */ -+ if (!retry) { -+ retry = 1; -+ fusb302_pd_reset(chip); -+ pd_execute_hard_reset(chip); -+ } else { -+ retry = 0; -+ chip->tx_state = tx_success; -+ chip->timer_state = T_DISABLED; -+ *evt |= EVENT_TX; -+ } -+ } -+} -+ -+static void mux_alert(struct fusb30x_chip *chip, u32 *evt) -+{ -+ if (!chip->timer_mux) { -+ *evt |= EVENT_TIMER_MUX; -+ chip->timer_mux = T_DISABLED; -+ } -+ -+ if (!chip->timer_state) { -+ *evt |= EVENT_TIMER_STATE; -+ chip->timer_state = T_DISABLED; -+ } -+ -+ if (chip->work_continue) { -+ *evt |= chip->work_continue; -+ chip->work_continue = 0; -+ } -+} -+ -+static void set_state_unattached(struct fusb30x_chip *chip) -+{ -+ dev_info(chip->dev, "connection has disconnected\n"); -+ tcpm_init(chip); -+ tcpm_set_rx_enable(chip, 0); -+ set_state(chip, unattached); -+ tcpm_set_cc(chip, chip->role); -+ -+ /* claer notify_info */ -+ memset(&chip->notify, 0, sizeof(struct notify_info)); -+ platform_fusb_notify(chip); -+ -+ if (chip->gpio_discharge) -+ gpiod_set_value(chip->gpio_discharge, 1); -+ msleep(100); -+ if (chip->gpio_discharge) -+ gpiod_set_value(chip->gpio_discharge, 0); -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_MASK, -+ MASK_M_COMP_CHNG, MASK_M_COMP_CHNG); -+ chip->try_role_complete = false; -+} -+ -+static void set_mesg(struct fusb30x_chip *chip, int cmd, int is_DMT) -+{ -+ int i; -+ struct PD_CAP_INFO *pd_cap_info = &chip->pd_cap_info; -+ -+ chip->send_head = ((chip->msg_id & 0x7) << 9) | -+ ((chip->notify.power_role & 0x1) << 8) | -+ (1 << 6) | -+ ((chip->notify.data_role & 0x1) << 5); -+ -+ if (is_DMT) { -+ switch (cmd) { -+ case DMT_SOURCECAPABILITIES: -+ chip->send_head |= ((chip->n_caps_used & 0x3) << 12) | (cmd & 0xf); -+ -+ for (i = 0; i < chip->n_caps_used; i++) { -+ chip->send_load[i] = (pd_cap_info->supply_type << 30) | -+ (pd_cap_info->dual_role_power << 29) | -+ (pd_cap_info->usb_suspend_support << 28) | -+ (pd_cap_info->externally_powered << 27) | -+ (pd_cap_info->usb_communications_cap << 26) | -+ (pd_cap_info->data_role_swap << 25) | -+ (pd_cap_info->peak_current << 20) | -+ (chip->source_power_supply[i] << 10) | -+ (chip->source_max_current[i]); -+ } -+ break; -+ case DMT_REQUEST: -+ chip->send_head |= ((1 << 12) | (cmd & 0xf)); -+ /* send request with FVRDO */ -+ chip->send_load[0] = (chip->pos_power << 28) | -+ (0 << 27) | -+ (1 << 26) | -+ (0 << 25) | -+ (0 << 24); -+ -+ switch (CAP_POWER_TYPE(chip->rec_load[chip->pos_power - 1])) { -+ case 0: -+ /* Fixed Supply */ -+ chip->send_load[0] |= ((CAP_FPDO_VOLTAGE(chip->rec_load[chip->pos_power - 1]) << 10) & 0x3ff); -+ chip->send_load[0] |= (CAP_FPDO_CURRENT(chip->rec_load[chip->pos_power - 1]) & 0x3ff); -+ break; -+ case 1: -+ /* Battery */ -+ chip->send_load[0] |= ((CAP_VPDO_VOLTAGE(chip->rec_load[chip->pos_power - 1]) << 10) & 0x3ff); -+ chip->send_load[0] |= (CAP_VPDO_CURRENT(chip->rec_load[chip->pos_power - 1]) & 0x3ff); -+ break; -+ default: -+ /* not meet battery caps */ -+ break; -+ } -+ break; -+ case DMT_SINKCAPABILITIES: -+ break; -+ case DMT_VENDERDEFINED: -+ break; -+ default: -+ break; -+ } -+ } else { -+ chip->send_head |= (cmd & 0xf); -+ } -+} -+ -+/* -+ * This algorithm defaults to choosing higher pin config over lower ones in -+ * order to prefer multi-function if desired. -+ * -+ * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG -+ * ------------------------------------------------------------- -+ * A | USB G2 | ? | no | 00_0001 -+ * B | USB G2 | ? | yes | 00_0010 -+ * C | DP | CONVERTED | no | 00_0100 -+ * D | PD | CONVERTED | yes | 00_1000 -+ * E | DP | DP | no | 01_0000 -+ * F | PD | DP | yes | 10_0000 -+ * -+ * if UFP has NOT asserted multi-function preferred code masks away B/D/F -+ * leaving only A/C/E. For single-output dongles that should leave only one -+ * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP -+ * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C -+ * receptacle must always choose C/D in those cases. -+ */ -+static int pd_dfp_dp_get_pin_assignment(struct fusb30x_chip *chip, -+ uint32_t caps, uint32_t status) -+{ -+ uint32_t pin_caps; -+ -+ /* revisit with DFP that can be a sink */ -+ pin_caps = PD_DP_PIN_CAPS(caps); -+ -+ /* if don't want multi-function then ignore those pin configs */ -+ if (!PD_VDO_DPSTS_MF_PREF(status)) -+ pin_caps &= ~MODE_DP_PIN_MF_MASK; -+ -+ /* revisit if DFP drives USB Gen 2 signals */ -+ if (PD_DP_SIGNAL_GEN2(caps)) -+ pin_caps &= ~MODE_DP_PIN_DP_MASK; -+ else -+ pin_caps &= ~MODE_DP_PIN_BR2_MASK; -+ -+ /* if C/D present they have precedence over E/F for USB-C->USB-C */ -+ if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) -+ pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); -+ -+ /* returns undefined for zero */ -+ if (!pin_caps) -+ return 0; -+ -+ /* choosing higher pin config over lower ones */ -+ return 1 << (31 - __builtin_clz(pin_caps)); -+} -+ -+static void set_vdm_mesg(struct fusb30x_chip *chip, int cmd, int type, int mode) -+{ -+ chip->send_head = (chip->msg_id & 0x7) << 9; -+ chip->send_head |= (chip->notify.power_role & 0x1) << 8; -+ -+ chip->send_head = ((chip->msg_id & 0x7) << 9) | -+ ((chip->notify.power_role & 0x1) << 8) | -+ (1 << 6) | -+ ((chip->notify.data_role & 0x1) << 5) | -+ (DMT_VENDERDEFINED & 0xf); -+ -+ chip->send_load[0] = (1 << 15) | -+ (0 << 13) | -+ (type << 6) | -+ (cmd); -+ -+ switch (cmd) { -+ case VDM_DISCOVERY_ID: -+ case VDM_DISCOVERY_SVIDS: -+ case VDM_ATTENTION: -+ chip->send_load[0] |= (0xff00 << 16); -+ chip->send_head |= (1 << 12); -+ break; -+ case VDM_DISCOVERY_MODES: -+ chip->send_load[0] |= -+ (chip->vdm_svid[chip->val_tmp >> 1] << 16); -+ chip->send_head |= (1 << 12); -+ break; -+ case VDM_ENTER_MODE: -+ chip->send_head |= (1 << 12); -+ chip->send_load[0] |= (mode << 8) | (0xff01 << 16); -+ break; -+ case VDM_EXIT_MODE: -+ chip->send_head |= (1 << 12); -+ chip->send_load[0] |= (0x0f << 8) | (0xff01 << 16); -+ break; -+ case VDM_DP_STATUS_UPDATE: -+ chip->send_head |= (2 << 12); -+ chip->send_load[0] |= (1 << 8) | (0xff01 << 16); -+ chip->send_load[1] = 5; -+ break; -+ case VDM_DP_CONFIG: -+ chip->send_head |= (2 << 12); -+ chip->send_load[0] |= (1 << 8) | (0xff01 << 16); -+ -+ chip->notify.pin_assignment_def = -+ pd_dfp_dp_get_pin_assignment(chip, chip->notify.dp_caps, -+ chip->notify.dp_status); -+ -+ chip->send_load[1] = (chip->notify.pin_assignment_def << 8) | -+ (1 << 2) | 2; -+ dev_dbg(chip->dev, "DisplayPort Configurations: 0x%08x\n", -+ chip->send_load[1]); -+ break; -+ default: -+ break; -+ } -+} -+ -+static enum tx_state policy_send_hardrst(struct fusb30x_chip *chip, u32 evt) -+{ -+ switch (chip->tx_state) { -+ case 0: -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL3, -+ CONTROL3_SEND_HARDRESET, -+ CONTROL3_SEND_HARDRESET); -+ chip->tx_state = tx_busy; -+ chip->timer_state = T_BMC_TIMEOUT; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ break; -+ default: -+ if (evt & EVENT_TIMER_STATE) -+ chip->tx_state = tx_success; -+ break; -+ } -+ return chip->tx_state; -+} -+ -+static enum tx_state policy_send_data(struct fusb30x_chip *chip) -+{ -+ u8 senddata[40]; -+ int pos = 0; -+ u8 len; -+ -+ switch (chip->tx_state) { -+ case 0: -+ senddata[pos++] = FUSB_TKN_SYNC1; -+ senddata[pos++] = FUSB_TKN_SYNC1; -+ senddata[pos++] = FUSB_TKN_SYNC1; -+ senddata[pos++] = FUSB_TKN_SYNC2; -+ -+ len = PD_HEADER_CNT(chip->send_head) << 2; -+ senddata[pos++] = FUSB_TKN_PACKSYM | ((len + 2) & 0x1f); -+ -+ senddata[pos++] = chip->send_head & 0xff; -+ senddata[pos++] = (chip->send_head >> 8) & 0xff; -+ -+ memcpy(&senddata[pos], chip->send_load, len); -+ pos += len; -+ -+ senddata[pos++] = FUSB_TKN_JAMCRC; -+ senddata[pos++] = FUSB_TKN_EOP; -+ senddata[pos++] = FUSB_TKN_TXOFF; -+ senddata[pos++] = FUSB_TKN_TXON; -+ -+ regmap_raw_write(chip->regmap, FUSB_REG_FIFO, senddata, pos); -+ chip->tx_state = tx_busy; -+ break; -+ -+ default: -+ /* wait Tx result */ -+ break; -+ } -+ -+ return chip->tx_state; -+} -+ -+static void process_vdm_msg(struct fusb30x_chip *chip) -+{ -+ u32 vdm_header = chip->rec_load[0]; -+ int i; -+ u32 tmp; -+ -+ /* can't procee unstructed vdm msg */ -+ if (!GET_VDMHEAD_STRUCT_TYPE(vdm_header)) { -+ dev_warn(chip->dev, "unknown unstructed vdm message\n"); -+ return; -+ } -+ -+ switch (GET_VDMHEAD_CMD_TYPE(vdm_header)) { -+ case VDM_TYPE_INIT: -+ switch (GET_VDMHEAD_CMD(vdm_header)) { -+ case VDM_ATTENTION: -+ chip->notify.dp_status = GET_DP_STATUS(chip->rec_load[1]); -+ dev_info(chip->dev, "attention, dp_status %x\n", -+ chip->rec_load[1]); -+ chip->notify.attention = true; -+ platform_fusb_notify(chip); -+ break; -+ default: -+ dev_warn(chip->dev, "rec unknown init vdm msg\n"); -+ break; -+ } -+ break; -+ case VDM_TYPE_ACK: -+ switch (GET_VDMHEAD_CMD(vdm_header)) { -+ case VDM_DISCOVERY_ID: -+ chip->vdm_id = chip->rec_load[1]; -+ break; -+ case VDM_DISCOVERY_SVIDS: -+ for (i = 0; i < 6; i++) { -+ tmp = (chip->rec_load[i + 1] >> 16) & -+ 0x0000ffff; -+ if (tmp) { -+ chip->vdm_svid[i * 2] = tmp; -+ chip->vdm_svid_num++; -+ } else { -+ break; -+ } -+ -+ tmp = (chip->rec_load[i + 1] & 0x0000ffff); -+ if (tmp) { -+ chip->vdm_svid[i * 2 + 1] = tmp; -+ chip->vdm_svid_num++; -+ } else { -+ break; -+ } -+ } -+ break; -+ case VDM_DISCOVERY_MODES: -+ /* indicate there are some vdo modes */ -+ if (PD_HEADER_CNT(chip->rec_head) > 1) { -+ /* -+ * store mode config, -+ * enter first mode default -+ */ -+ tmp = chip->rec_load[1]; -+ -+ if ((!((tmp >> 8) & 0x3f)) && -+ (!((tmp >> 16) & 0x3f))) { -+ chip->val_tmp |= 1; -+ break; -+ } -+ chip->notify.dp_caps = chip->rec_load[1]; -+ chip->notify.pin_assignment_def = 0; -+ chip->notify.pin_assignment_support = -+ PD_DP_PIN_CAPS(tmp); -+ chip->val_tmp |= 1; -+ dev_dbg(chip->dev, -+ "DisplayPort Capabilities: 0x%08x\n", -+ chip->rec_load[1]); -+ } -+ break; -+ case VDM_ENTER_MODE: -+ chip->val_tmp = 1; -+ break; -+ case VDM_DP_STATUS_UPDATE: -+ chip->notify.dp_status = GET_DP_STATUS(chip->rec_load[1]); -+ dev_dbg(chip->dev, "DisplayPort Status: 0x%08x\n", -+ chip->rec_load[1]); -+ chip->val_tmp = 1; -+ break; -+ case VDM_DP_CONFIG: -+ chip->val_tmp = 1; -+ dev_info(chip->dev, -+ "DP config successful, pin_assignment 0x%x\n", -+ chip->notify.pin_assignment_def); -+ chip->notify.is_enter_mode = true; -+ break; -+ default: -+ break; -+ } -+ break; -+ case VDM_TYPE_NACK: -+ dev_warn(chip->dev, "REC NACK for 0x%x\n", -+ GET_VDMHEAD_CMD(vdm_header)); -+ /* disable vdm */ -+ chip->vdm_state = VDM_STATE_ERR; -+ break; -+ } -+} -+ -+static int vdm_send_discoveryid(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DISCOVERY_ID, VDM_TYPE_INIT, 0); -+ chip->vdm_id = 0; -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_ID send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->vdm_id) { -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_ID time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_discoverysvid(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DISCOVERY_SVIDS, VDM_TYPE_INIT, 0); -+ memset(chip->vdm_svid, 0, sizeof(chip->vdm_svid)); -+ chip->vdm_svid_num = 0; -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_SVIDS send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->vdm_svid_num) { -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_SVIDS time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_discoverymodes(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ if ((chip->val_tmp >> 1) != chip->vdm_svid_num) { -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DISCOVERY_MODES, -+ VDM_TYPE_INIT, 0); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, -+ "VDM_DISCOVERY_MODES send failed\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp & 1) { -+ chip->val_tmp &= 0xfe; -+ chip->val_tmp += 2; -+ chip->vdm_send_state = 0; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, -+ "VDM_DISCOVERY_MODES time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ } else { -+ chip->val_tmp = 0; -+ return 0; -+ } -+ -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_entermode(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_ENTER_MODE, VDM_TYPE_INIT, 1); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ chip->notify.is_enter_mode = false; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "VDM_ENTER_MODE send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp) { -+ chip->val_tmp = 0; -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_ENTER_MODE time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_getdpstatus(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DP_STATUS_UPDATE, VDM_TYPE_INIT, 1); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, -+ "VDM_DP_STATUS_UPDATE send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp) { -+ chip->val_tmp = 0; -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_DP_STATUS_UPDATE time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_dpconfig(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DP_CONFIG, VDM_TYPE_INIT, 0); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "vdm_send_dpconfig send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp) { -+ chip->val_tmp = 0; -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "vdm_send_dpconfig time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+/* without break if success */ -+#define AUTO_VDM_HANDLE(func, chip, evt, conditions) \ -+do { \ -+ conditions = func(chip, evt); \ -+ if (!conditions) { \ -+ chip->vdm_state++; \ -+ chip->work_continue |= EVENT_WORK_CONTINUE; \ -+ } else { \ -+ if (conditions != -EINPROGRESS) \ -+ chip->vdm_state = VDM_STATE_ERR; \ -+ } \ -+} while (0) -+ -+static void auto_vdm_machine(struct fusb30x_chip *chip, u32 evt) -+{ -+ int conditions; -+ -+ switch (chip->vdm_state) { -+ case VDM_STATE_DISCOVERY_ID: -+ AUTO_VDM_HANDLE(vdm_send_discoveryid, chip, evt, conditions); -+ break; -+ case VDM_STATE_DISCOVERY_SVID: -+ AUTO_VDM_HANDLE(vdm_send_discoverysvid, chip, evt, conditions); -+ break; -+ case VDM_STATE_DISCOVERY_MODES: -+ AUTO_VDM_HANDLE(vdm_send_discoverymodes, chip, evt, conditions); -+ break; -+ case VDM_STATE_ENTER_MODE: -+ AUTO_VDM_HANDLE(vdm_send_entermode, chip, evt, conditions); -+ break; -+ case VDM_STATE_UPDATE_STATUS: -+ AUTO_VDM_HANDLE(vdm_send_getdpstatus, chip, evt, conditions); -+ break; -+ case VDM_STATE_DP_CONFIG: -+ AUTO_VDM_HANDLE(vdm_send_dpconfig, chip, evt, conditions); -+ break; -+ case VDM_STATE_NOTIFY: -+ platform_fusb_notify(chip); -+ chip->vdm_state = VDM_STATE_READY; -+ break; -+ default: -+ break; -+ } -+} -+ -+static void fusb_state_disabled(struct fusb30x_chip *chip, u32 evt) -+{ -+ /* Do nothing */ -+} -+ -+static void fusb_state_unattached(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.is_cc_connected = false; -+ chip->is_pd_support = false; -+ -+ if ((evt & EVENT_CC) && chip->cc_state) { -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) -+ set_state(chip, attach_wait_sink); -+ else -+ set_state(chip, attach_wait_source); -+ -+ chip->vbus_begin = tcpm_check_vbus(chip); -+ -+ tcpm_set_polarity(chip, (chip->cc_state & CC_STATE_TOGSS_CC1) ? -+ TYPEC_POLARITY_CC1 : -+ TYPEC_POLARITY_CC2); -+ tcpm_get_cc(chip, &chip->cc1, &chip->cc2); -+ chip->debounce_cnt = 0; -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, chip->timer_mux); -+ } -+} -+ -+static void fusb_state_try_attach_set(struct fusb30x_chip *chip, -+ enum role_mode mode) -+{ -+ if (mode == ROLE_MODE_NONE || mode == ROLE_MODE_DRP || -+ mode == ROLE_MODE_ASS) -+ return; -+ -+ tcpm_init(chip); -+ tcpm_set_cc(chip, (mode == ROLE_MODE_DFP) ? -+ ROLE_MODE_DFP : ROLE_MODE_UFP); -+ chip->timer_mux = T_PD_TRY_DRP; -+ fusb_timer_start(&chip->timer_mux_machine, chip->timer_mux); -+ set_state(chip, (mode == ROLE_MODE_DFP) ? -+ attach_try_src : attach_try_snk); -+} -+ -+static void fusb_state_attach_wait_sink(struct fusb30x_chip *chip, u32 evt) -+{ -+ int cc1, cc2; -+ -+ if (evt & EVENT_TIMER_MUX) { -+ if (tcpm_check_vbus(chip)) { -+ chip->timer_mux = T_DISABLED; -+ if (chip->role == ROLE_MODE_DRP && -+ chip->try_role == ROLE_MODE_DFP && -+ !chip->try_role_complete) { -+ fusb_state_try_attach_set(chip, ROLE_MODE_DFP); -+ return; -+ } else if (chip->try_role_complete) { -+ chip->timer_mux = T_PD_SOURCE_ON; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ set_state(chip, attached_sink); -+ return; -+ } -+ } -+ -+ tcpm_get_cc(chip, &cc1, &cc2); -+ -+ if ((chip->cc1 == cc1) && (chip->cc2 == cc2)) { -+ chip->debounce_cnt++; -+ } else { -+ chip->cc1 = cc1; -+ chip->cc2 = cc2; -+ chip->debounce_cnt = 0; -+ } -+ -+ if (chip->debounce_cnt > N_DEBOUNCE_CNT) { -+ chip->timer_mux = T_DISABLED; -+ if ((chip->cc1 == TYPEC_CC_VOLT_RP && -+ chip->cc2 == TYPEC_CC_VOLT_OPEN) || -+ (chip->cc2 == TYPEC_CC_VOLT_RP && -+ chip->cc1 == TYPEC_CC_VOLT_OPEN)) { -+ chip->timer_mux = T_PD_SOURCE_ON; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ set_state(chip, attached_sink); -+ } else { -+ set_state_unattached(chip); -+ } -+ return; -+ } -+ -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ } -+} -+ -+static void fusb_state_attach_wait_source(struct fusb30x_chip *chip, u32 evt) -+{ -+ int cc1, cc2; -+ -+ if (evt & EVENT_TIMER_MUX) { -+ tcpm_get_cc(chip, &cc1, &cc2); -+ -+ if ((chip->cc1 == cc1) && (chip->cc2 == cc2)) { -+ chip->debounce_cnt++; -+ } else { -+ chip->cc1 = cc1; -+ chip->cc2 = cc2; -+ chip->debounce_cnt = 0; -+ } -+ -+ if (chip->debounce_cnt > N_DEBOUNCE_CNT) { -+ if (((!chip->cc1) || (!chip->cc2)) && -+ ((chip->cc1 == TYPEC_CC_VOLT_RD) || -+ (chip->cc2 == TYPEC_CC_VOLT_RD))) { -+ if (chip->role == ROLE_MODE_DRP && -+ chip->try_role == ROLE_MODE_UFP && -+ !chip->try_role_complete) -+ fusb_state_try_attach_set(chip, -+ ROLE_MODE_UFP); -+ else -+ set_state(chip, attached_source); -+ } else { -+ set_state_unattached(chip); -+ } -+ return; -+ } -+ -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ } -+} -+ -+static void fusb_state_attached_source(struct fusb30x_chip *chip, u32 evt) -+{ -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ tcpm_set_polarity(chip, (chip->cc_state & CC_STATE_TOGSS_CC1) ? -+ TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2); -+ tcpm_set_vconn(chip, 1); -+ -+ chip->notify.is_cc_connected = true; -+ -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ chip->notify.data_role = DATA_ROLE_DFP; -+ chip->hardrst_count = 0; -+ set_state(chip, policy_src_startup); -+ regmap_update_bits(chip->regmap, FUSB_REG_MASK, MASK_M_COMP_CHNG, 0); -+ dev_info(chip->dev, "CC connected in %s as DFP\n", -+ chip->cc_polarity ? "CC1" : "CC2"); -+} -+ -+static void fusb_state_attached_sink(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (tcpm_check_vbus(chip)) { -+ chip->timer_mux = T_DISABLED; -+ chip->timer_state = T_DISABLED; -+ if (!chip->try_role_complete && -+ chip->try_role == ROLE_MODE_DFP && -+ chip->role == ROLE_MODE_DRP) { -+ fusb_state_try_attach_set(chip, ROLE_MODE_DFP); -+ return; -+ } -+ -+ chip->try_role_complete = true; -+ chip->notify.is_cc_connected = true; -+ chip->notify.power_role = POWER_ROLE_SINK; -+ chip->notify.data_role = DATA_ROLE_UFP; -+ chip->hardrst_count = 0; -+ set_state(chip, policy_snk_startup); -+ dev_info(chip->dev, "CC connected in %s as UFP\n", -+ chip->cc_polarity ? "CC1" : "CC2"); -+ return; -+ } else if (evt & EVENT_TIMER_MUX) { -+ set_state_unattached(chip); -+ return; -+ } -+ -+ chip->timer_state = 2; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+} -+ -+static void fusb_state_try_attach(struct fusb30x_chip *chip, u32 evt, -+ enum role_mode mode) -+{ -+ if ((evt & EVENT_CC) && chip->cc_state) { -+ chip->try_role_complete = true; -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) -+ set_state(chip, (mode == ROLE_MODE_UFP) ? -+ attach_wait_sink : error_recovery); -+ else -+ set_state(chip, (mode == ROLE_MODE_DFP) ? -+ attach_wait_source : error_recovery); -+ -+ tcpm_set_polarity(chip, (chip->cc_state & CC_STATE_TOGSS_CC1) ? -+ TYPEC_POLARITY_CC1 : -+ TYPEC_POLARITY_CC2); -+ tcpm_get_cc(chip, &chip->cc1, &chip->cc2); -+ chip->debounce_cnt = 0; -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, chip->timer_mux); -+ } else if (evt & EVENT_TIMER_MUX) { -+ if (!chip->try_role_complete) { -+ chip->try_role_complete = true; -+ fusb_state_try_attach_set(chip, -+ (mode == ROLE_MODE_DFP) ? -+ ROLE_MODE_UFP : -+ ROLE_MODE_DFP); -+ } else { -+ set_state(chip, error_recovery); -+ } -+ } -+} -+ -+static void fusb_soft_reset_parameter(struct fusb30x_chip *chip) -+{ -+ chip->caps_counter = 0; -+ chip->msg_id = 0; -+ chip->vdm_state = VDM_STATE_DISCOVERY_ID; -+ chip->vdm_substate = 0; -+ chip->vdm_send_state = 0; -+ chip->val_tmp = 0; -+ chip->pos_power = 0; -+} -+ -+static void fusb_state_src_startup(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.is_pd_connected = false; -+ fusb_soft_reset_parameter(chip); -+ -+ memset(chip->partner_cap, 0, sizeof(chip->partner_cap)); -+ -+ tcpm_set_msg_header(chip); -+ tcpm_set_polarity(chip, chip->cc_polarity); -+ tcpm_set_rx_enable(chip, 1); -+ -+ set_state(chip, policy_src_send_caps); -+ platform_fusb_notify(chip); -+} -+ -+static void fusb_state_src_discovery(struct fusb30x_chip *chip, u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->caps_counter++; -+ -+ if (chip->caps_counter < N_CAPS_COUNT) { -+ chip->timer_state = T_TYPEC_SEND_SOURCECAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state = 1; -+ } else { -+ set_state(chip, disabled); -+ } -+ break; -+ default: -+ if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_src_send_caps); -+ } else if (evt & EVENT_TIMER_MUX) { -+ if (!chip->is_pd_support) -+ set_state(chip, disabled); -+ else if (chip->hardrst_count > N_HARDRESET_COUNT) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_send_caps(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, DMT_SOURCECAPABILITIES, DATAMESSAGE); -+ chip->sub_state = 1; -+ chip->tx_state = tx_idle; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ -+ if (tmp == tx_success) { -+ chip->hardrst_count = 0; -+ chip->caps_counter = 0; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->timer_mux = T_DISABLED; -+ chip->sub_state++; -+ chip->is_pd_support = true; -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_discovery); -+ break; -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_REQUEST)) { -+ set_state(chip, policy_src_negotiate_cap); -+ } else { -+ set_state(chip, policy_src_send_softrst); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->hardrst_count <= N_HARDRESET_COUNT) -+ set_state(chip, policy_src_send_hardrst); -+ else -+ set_state(chip, disabled); -+ } else if (evt & EVENT_TIMER_MUX) { -+ if (!chip->is_pd_support) -+ set_state(chip, disabled); -+ else if (chip->hardrst_count > N_HARDRESET_COUNT) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_negotiate_cap(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ /* base on evb1 */ -+ tmp = (chip->rec_load[0] >> 28) & 0x07; -+ if (tmp > chip->n_caps_used) -+ set_state(chip, policy_src_cap_response); -+ else -+ set_state(chip, policy_src_transition_supply); -+} -+ -+static void fusb_state_src_transition_supply(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_ACCEPT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SRC_TRANSITION; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ break; -+ case 2: -+ if (evt & EVENT_TIMER_STATE) { -+ chip->notify.is_pd_connected = true; -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ set_mesg(chip, CMT_PS_RDY, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ } -+ break; -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ dev_info(chip->dev, -+ "PD connected as DFP, supporting 5V\n"); -+ set_state(chip, policy_src_ready); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_cap_response(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_REJECT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ if (chip->notify.is_pd_connected) { -+ dev_info(chip->dev, -+ "PD connected as DFP, supporting 5V\n"); -+ set_state(chip, policy_src_ready); -+ } else { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_transition_default(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->notify.is_pd_connected = false; -+ platform_set_vbus_lvl_enable(chip, 0, 0); -+ if (chip->notify.data_role) -+ regmap_update_bits(chip->regmap, -+ FUSB_REG_SWITCHES1, -+ SWITCHES1_DATAROLE, -+ SWITCHES1_DATAROLE); -+ else -+ regmap_update_bits(chip->regmap, -+ FUSB_REG_SWITCHES1, -+ SWITCHES1_DATAROLE, -+ 0); -+ -+ chip->timer_state = T_SRC_RECOVER; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ break; -+ default: -+ if (evt & EVENT_TIMER_STATE) { -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ chip->timer_mux = T_NO_RESPONSE; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ set_state(chip, policy_src_startup); -+ dev_dbg(chip->dev, "reset over-> src startup\n"); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_vcs_ufp_evaluate_swap(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (chip->vconn_supported) -+ set_state(chip, policy_vcs_ufp_accept); -+ else -+ set_state(chip, policy_vcs_ufp_reject); -+} -+ -+static void fusb_state_swap_msg_process(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_PR_SWAP)) { -+ set_state(chip, policy_src_prs_evaluate); -+ } else if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_VCONN_SWAP)) { -+ if (chip->notify.data_role) -+ set_state(chip, chip->conn_state); -+ else -+ set_state(chip, policy_vcs_ufp_evaluate_swap); -+ } else if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_DR_SWAP)) { -+ if (chip->notify.data_role) -+ set_state(chip, policy_drs_dfp_evaluate); -+ else -+ set_state(chip, policy_drs_ufp_evaluate); -+ } -+ } -+} -+ -+#define VDM_IS_ACTIVE(chip) \ -+ (chip->notify.data_role && chip->vdm_state < VDM_STATE_READY) -+ -+static void fusb_state_src_ready(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_VENDERDEFINED)) { -+ process_vdm_msg(chip); -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ chip->timer_state = T_DISABLED; -+ } else if (!VDM_IS_ACTIVE(chip)) { -+ fusb_state_swap_msg_process(chip, evt); -+ } -+ } -+ -+ if (!chip->partner_cap[0]) -+ set_state(chip, policy_src_get_sink_caps); -+ else if (VDM_IS_ACTIVE(chip)) -+ auto_vdm_machine(chip, evt); -+} -+ -+static void fusb_state_prs_evaluate(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (chip->role == ROLE_MODE_DRP) -+ set_state(chip, policy_src_prs_accept); -+ else -+ set_state(chip, policy_src_prs_reject); -+} -+ -+static void fusb_state_send_simple_msg(struct fusb30x_chip *chip, u32 evt, -+ int cmd, int is_DMT, -+ enum connection_state state_success, -+ enum connection_state state_failed) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, cmd, is_DMT); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) -+ set_state(chip, state_success); -+ else if (tmp == tx_failed) -+ set_state(chip, state_failed); -+ } -+} -+ -+static void fusb_state_prs_reject(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_REJECT, CONTROLMESSAGE, -+ (chip->notify.power_role) ? -+ policy_src_ready : policy_snk_ready, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_prs_accept(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_ACCEPT, CONTROLMESSAGE, -+ (chip->notify.power_role) ? -+ policy_src_prs_transition_to_off : -+ policy_snk_prs_transition_to_off, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_vcs_ufp_accept(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_ACCEPT, CONTROLMESSAGE, -+ (chip->vconn_enabled) ? -+ policy_vcs_ufp_wait_for_dfp_vconn : -+ policy_vcs_ufp_turn_on_vconn, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_vcs_set_vconn(struct fusb30x_chip *chip, -+ u32 evt, bool on) -+{ -+ if (on) { -+ tcpm_set_vconn(chip, 1); -+ set_state(chip, chip->notify.data_role ? -+ policy_vcs_dfp_send_ps_rdy : -+ policy_vcs_ufp_send_ps_rdy); -+ } else { -+ tcpm_set_vconn(chip, 0); -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_ready); -+ else -+ set_state(chip, policy_snk_ready); -+ } -+} -+ -+static void fusb_state_vcs_send_ps_rdy(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_PS_RDY, CONTROLMESSAGE, -+ (chip->notify.power_role) ? -+ policy_src_ready : policy_snk_ready, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_vcs_wait_for_vconn(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->timer_state = T_PD_VCONN_SRC_ON; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_PS_RDY)) -+ set_state(chip, chip->notify.data_role ? -+ policy_vcs_dfp_turn_off_vconn : -+ policy_vcs_ufp_turn_off_vconn); -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_send_hardrst); -+ else -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ } -+} -+ -+static void fusb_state_src_prs_transition_to_off(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->timer_state = T_SRC_TRANSITION; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ break; -+ case 1: -+ if (evt & EVENT_TIMER_STATE) { -+ platform_set_vbus_lvl_enable(chip, 0, 0); -+ chip->notify.power_role = POWER_ROLE_SINK; -+ tcpm_set_msg_header(chip); -+ if (chip->role == ROLE_MODE_DRP) -+ set_state(chip, policy_src_prs_assert_rd); -+ else -+ set_state(chip, policy_src_prs_source_off); -+ } -+ } -+} -+ -+static void fusb_state_src_prs_assert_rd(struct fusb30x_chip *chip, u32 evt) -+{ -+ tcpm_set_cc_pull_mode(chip, CC_PULL_DOWN); -+ set_state(chip, policy_src_prs_source_off); -+} -+ -+static void fusb_state_src_prs_source_off(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_PS_RDY, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_PD_SOURCE_ON; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_src_send_hardrst); -+ } -+ if (chip->sub_state != 3) -+ break; -+ case 2: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_PS_RDY)) { -+ chip->timer_state = T_DISABLED; -+ /* snk startup */ -+ chip->notify.is_pd_connected = false; -+ chip->cc_state |= CC_STATE_TOGSS_IS_UFP; -+ tcpm_set_polarity(chip, chip->cc_polarity); -+ tcpm_set_rx_enable(chip, 1); -+ set_state(chip, policy_snk_discovery); -+ } else { -+ dev_dbg(chip->dev, -+ "rec careless msg: head %x\n", -+ chip->rec_head); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_src_send_hardrst); -+ } -+ } -+} -+ -+static void fusb_state_drs_evaluate(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (chip->pd_cap_info.data_role_swap) -+ /* -+ * TODO: -+ * NOW REJECT swap when the port is DFP -+ * since we should work together with USB part -+ */ -+ set_state(chip, chip->notify.data_role ? -+ policy_drs_dfp_reject : policy_drs_ufp_accept); -+ else -+ set_state(chip, chip->notify.data_role ? -+ policy_drs_dfp_reject : policy_drs_ufp_reject); -+} -+ -+static void fusb_state_drs_send_accept(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_ACCEPT, CONTROLMESSAGE, -+ chip->notify.power_role ? -+ policy_drs_dfp_change : -+ policy_drs_ufp_change, -+ error_recovery); -+} -+ -+static void fusb_state_drs_role_change(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.data_role = chip->notify.data_role ? -+ DATA_ROLE_UFP : DATA_ROLE_DFP; -+ tcpm_set_msg_header(chip); -+ set_state(chip, chip->notify.power_role ? policy_src_ready : -+ policy_snk_ready); -+} -+ -+static void fusb_state_src_get_sink_cap(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_GETSINKCAP, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, -+ DMT_SINKCAPABILITIES)) { -+ for (tmp = 0; -+ tmp < PD_HEADER_CNT(chip->rec_head); -+ tmp++) { -+ chip->partner_cap[tmp] = -+ chip->rec_load[tmp]; -+ } -+ set_state(chip, policy_src_ready); -+ } else { -+ chip->partner_cap[0] = 0xffffffff; -+ set_state(chip, policy_src_ready); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "Get sink cap time out\n"); -+ chip->partner_cap[0] = 0xffffffff; -+ set_state(chip, policy_src_ready); -+ } -+ } -+} -+ -+static void fusb_state_src_send_hardreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_hardrst(chip, evt); -+ if (tmp == tx_success) { -+ chip->hardrst_count++; -+ set_state(chip, policy_src_transition_default); -+ } else if (tmp == tx_failed) { -+ /* can't reach here */ -+ set_state(chip, error_recovery); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_softreset(struct fusb30x_chip *chip) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_ACCEPT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ fusb_soft_reset_parameter(chip); -+ set_state(chip, policy_src_send_caps); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_send_softreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_SOFTRESET, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_ACCEPT)) { -+ fusb_soft_reset_parameter(chip); -+ set_state(chip, policy_src_send_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_startup(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.is_pd_connected = false; -+ fusb_soft_reset_parameter(chip); -+ -+ memset(chip->partner_cap, 0, sizeof(chip->partner_cap)); -+ -+ tcpm_set_msg_header(chip); -+ tcpm_set_polarity(chip, chip->cc_polarity); -+ tcpm_set_rx_enable(chip, 1); -+ set_state(chip, policy_snk_discovery); -+ platform_fusb_notify(chip); -+} -+ -+static void fusb_state_snk_discovery(struct fusb30x_chip *chip, u32 evt) -+{ -+ set_state(chip, policy_snk_wait_caps); -+ chip->timer_state = T_TYPEC_SINK_WAIT_CAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+} -+ -+static void fusb_state_snk_wait_caps(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, -+ DMT_SOURCECAPABILITIES)) { -+ chip->is_pd_support = true; -+ chip->timer_mux = T_DISABLED; -+ set_state(chip, policy_snk_evaluate_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->hardrst_count <= N_HARDRESET_COUNT) { -+ if (chip->vbus_begin) { -+ chip->vbus_begin = false; -+ set_state(chip, policy_snk_send_softrst); -+ } else { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ } else { -+ if (chip->is_pd_support) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, disabled); -+ } -+ } else if ((evt & EVENT_TIMER_MUX) && -+ (chip->hardrst_count > N_HARDRESET_COUNT)) { -+ if (chip->is_pd_support) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, disabled); -+ } -+} -+ -+static void fusb_state_snk_evaluate_caps(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ chip->hardrst_count = 0; -+ chip->pos_power = 0; -+ -+ for (tmp = 0; tmp < PD_HEADER_CNT(chip->rec_head); tmp++) { -+ switch (CAP_POWER_TYPE(chip->rec_load[tmp])) { -+ case 0: -+ /* Fixed Supply */ -+ if (CAP_FPDO_VOLTAGE(chip->rec_load[tmp]) <= 100) -+ chip->pos_power = tmp + 1; -+ break; -+ case 1: -+ /* Battery */ -+ if (CAP_VPDO_VOLTAGE(chip->rec_load[tmp]) <= 100) -+ chip->pos_power = tmp + 1; -+ break; -+ default: -+ /* not meet battery caps */ -+ break; -+ } -+ } -+ fusb302_set_pos_power_by_charge_ic(chip); -+ -+ if ((!chip->pos_power) || (chip->pos_power > 7)) { -+ chip->pos_power = 0; -+ set_state(chip, policy_snk_wait_caps); -+ } else { -+ set_state(chip, policy_snk_select_cap); -+ } -+} -+ -+static void fusb_state_snk_select_cap(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, DMT_REQUEST, DATAMESSAGE); -+ chip->sub_state = 1; -+ chip->tx_state = tx_idle; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_snk_discovery); -+ break; -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (!PD_HEADER_CNT(chip->rec_head)) { -+ switch (PD_HEADER_TYPE(chip->rec_head)) { -+ case CMT_ACCEPT: -+ set_state(chip, -+ policy_snk_transition_sink); -+ chip->timer_state = T_PS_TRANSITION; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ break; -+ case CMT_WAIT: -+ case CMT_REJECT: -+ if (chip->notify.is_pd_connected) { -+ dev_info(chip->dev, -+ "PD connected as UFP, fetching 5V\n"); -+ set_state(chip, -+ policy_snk_ready); -+ } else { -+ set_state(chip, -+ policy_snk_wait_caps); -+ /* -+ * make sure don't send -+ * hard reset to prevent -+ * infinite loop -+ */ -+ chip->hardrst_count = -+ N_HARDRESET_COUNT + 1; -+ } -+ break; -+ default: -+ break; -+ } -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_transition_sink(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_PS_RDY)) { -+ chip->notify.is_pd_connected = true; -+ dev_info(chip->dev, -+ "PD connected as UFP, fetching 5V\n"); -+ set_state(chip, policy_snk_ready); -+ } else if (PACKET_IS_DATA_MSG(chip->rec_head, -+ DMT_SOURCECAPABILITIES)) { -+ set_state(chip, policy_snk_evaluate_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+} -+ -+static void fusb_state_snk_transition_default(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->notify.is_pd_connected = false; -+ chip->timer_mux = T_NO_RESPONSE; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ chip->timer_state = T_PS_HARD_RESET_MAX + T_SAFE_0V; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ if (chip->notify.data_role) -+ tcpm_set_msg_header(chip); -+ -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ if (!tcpm_check_vbus(chip)) { -+ chip->sub_state++; -+ chip->timer_state = T_SRC_RECOVER_MAX + T_SRC_TURN_ON; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_startup); -+ } -+ break; -+ default: -+ if (tcpm_check_vbus(chip)) { -+ chip->timer_state = T_DISABLED; -+ set_state(chip, policy_snk_startup); -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_startup); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_ready(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_VENDERDEFINED)) { -+ process_vdm_msg(chip); -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ chip->timer_state = T_DISABLED; -+ } else if (!VDM_IS_ACTIVE(chip)) { -+ fusb_state_swap_msg_process(chip, evt); -+ } -+ } -+ -+ if (VDM_IS_ACTIVE(chip)) -+ auto_vdm_machine(chip, evt); -+ -+ fusb_state_swap_msg_process(chip, evt); -+ platform_fusb_notify(chip); -+} -+ -+static void fusb_state_snk_send_hardreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ default: -+ tmp = policy_send_hardrst(chip, evt); -+ if (tmp == tx_success) { -+ chip->hardrst_count++; -+ set_state(chip, policy_snk_transition_default); -+ } else if (tmp == tx_failed) { -+ set_state(chip, error_recovery); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_send_swap(struct fusb30x_chip *chip, u32 evt, int cmd) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, cmd, CONTROLMESSAGE); -+ chip->sub_state = 1; -+ chip->tx_state = tx_idle; -+ /* fallthrough */ -+ case 1: -+ tmp = policy_send_data(chip); -+ -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ if (cmd == CMT_DR_SWAP) { -+ set_state(chip, error_recovery); -+ return; -+ } -+ -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_send_softrst); -+ else -+ set_state(chip, policy_snk_send_softrst); -+ } -+ break; -+ case 2: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_ACCEPT)) { -+ chip->timer_state = T_DISABLED; -+ if (cmd == CMT_VCONN_SWAP) { -+ set_state(chip, chip->vconn_enabled ? -+ policy_vcs_dfp_wait_for_ufp_vconn : -+ policy_vcs_dfp_turn_on_vconn); -+ } else if (cmd == CMT_PR_SWAP) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_prs_transition_to_off); -+ else -+ set_state(chip, policy_snk_prs_transition_to_off); -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ tcpm_set_msg_header(chip); -+ } else if (cmd == CMT_DR_SWAP) { -+ set_state(chip, chip->notify.data_role ? -+ policy_drs_dfp_change : -+ policy_drs_ufp_change); -+ } -+ } else if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_REJECT) || -+ PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_WAIT)) { -+ chip->timer_state = T_DISABLED; -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_ready); -+ else -+ set_state(chip, policy_snk_ready); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_ready); -+ else -+ set_state(chip, policy_snk_ready); -+ } -+ } -+} -+ -+static void fusb_state_snk_prs_transition_to_off(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->timer_state = T_PD_SOURCE_OFF; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_PS_RDY)) { -+ if (chip->role == ROLE_MODE_DRP) -+ set_state(chip, -+ policy_snk_prs_assert_rp); -+ else -+ set_state(chip, -+ policy_snk_prs_source_on); -+ } else { -+ dev_dbg(chip->dev, -+ "rec careless msg: head %x\n", -+ chip->rec_head); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ chip->notify.power_role = POWER_ROLE_SINK; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_prs_assert_rp(struct fusb30x_chip *chip, u32 evt) -+{ -+ tcpm_set_cc_pull_mode(chip, CC_PULL_UP); -+ set_state(chip, policy_snk_prs_source_on); -+} -+ -+static void fusb_state_snk_prs_source_on(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ /* supply power in 50ms */ -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ chip->sub_state++; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ break; -+ case 1: -+ set_mesg(chip, CMT_PS_RDY, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* fallthrough */ -+ case 2: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ /* PD spe 6.5.10.2 */ -+ chip->timer_state = T_PD_SWAP_SOURCE_START; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ chip->notify.power_role = POWER_ROLE_SINK; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ case 3: -+ if (evt & EVENT_TIMER_STATE) { -+ chip->cc_state &= ~CC_STATE_TOGSS_IS_UFP; -+ regmap_update_bits(chip->regmap, FUSB_REG_MASK, -+ MASK_M_COMP_CHNG, 0); -+ set_state(chip, policy_src_send_caps); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_softreset(struct fusb30x_chip *chip) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_ACCEPT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ fusb_soft_reset_parameter(chip); -+ chip->timer_state = T_TYPEC_SINK_WAIT_CAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ set_state(chip, policy_snk_wait_caps); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_send_softreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_SOFTRESET, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ /* can't reach here */ -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if ((!PD_HEADER_CNT(chip->rec_head)) && -+ (PD_HEADER_TYPE(chip->rec_head) == CMT_ACCEPT)) { -+ fusb_soft_reset_parameter(chip); -+ chip->timer_state = T_TYPEC_SINK_WAIT_CAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ set_state(chip, policy_snk_wait_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_try_detach(struct fusb30x_chip *chip) -+{ -+ int cc1, cc2; -+ -+ if ((chip->cc_state & CC_STATE_TOGSS_IS_UFP) && -+ (chip->conn_state != -+ policy_snk_transition_default) && -+ (chip->conn_state != -+ policy_src_prs_source_off) && -+ (chip->conn_state != policy_snk_prs_send_swap) && -+ (chip->conn_state != policy_snk_prs_assert_rp) && -+ (chip->conn_state != policy_snk_prs_source_on) && -+ (chip->conn_state != policy_snk_prs_transition_to_off)) { -+ if (!tcpm_check_vbus(chip)) -+ set_state_unattached(chip); -+ } else if ((chip->conn_state != -+ policy_src_transition_default) && -+ (chip->conn_state != -+ policy_src_prs_source_off) && -+ (chip->conn_state != policy_snk_prs_source_on)) { -+ tcpm_get_cc(chip, &cc1, &cc2); -+ if (chip->cc_state & CC_STATE_TOGSS_CC2) -+ cc1 = cc2; -+ if (cc1 == TYPEC_CC_VOLT_OPEN) -+ set_state_unattached(chip); -+ } else { -+ /* -+ * Detached may occurred at swap operations. So, DON'T ignore -+ * the EVENT_CC during swapping at all, check the connection -+ * after it. -+ */ -+ chip->work_continue |= EVENT_DELAY_CC; -+ } -+} -+ -+static void state_machine_typec(struct fusb30x_chip *chip) -+{ -+ u32 evt = 0; -+ -+ tcpc_alert(chip, &evt); -+ mux_alert(chip, &evt); -+ if (!evt) -+ goto BACK; -+ -+ if (chip->notify.is_cc_connected) -+ if (evt & (EVENT_CC | EVENT_DELAY_CC)) -+ fusb_try_detach(chip); -+ -+ if (evt & EVENT_RX) { -+ tcpm_get_message(chip); -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_SOFTRESET)) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_softrst); -+ else -+ set_state(chip, policy_snk_softrst); -+ } -+ } -+ -+ if (evt & EVENT_TX) { -+ if (chip->tx_state == tx_success) -+ chip->msg_id++; -+ } -+ switch (chip->conn_state) { -+ case disabled: -+ fusb_state_disabled(chip, evt); -+ break; -+ case error_recovery: -+ set_state_unattached(chip); -+ break; -+ case unattached: -+ fusb_state_unattached(chip, evt); -+ break; -+ case attach_wait_sink: -+ fusb_state_attach_wait_sink(chip, evt); -+ break; -+ case attach_wait_source: -+ fusb_state_attach_wait_source(chip, evt); -+ break; -+ case attached_source: -+ fusb_state_attached_source(chip, evt); -+ break; -+ case attached_sink: -+ fusb_state_attached_sink(chip, evt); -+ break; -+ case attach_try_src: -+ fusb_state_try_attach(chip, evt, ROLE_MODE_DFP); -+ break; -+ case attach_try_snk: -+ fusb_state_try_attach(chip, evt, ROLE_MODE_UFP); -+ break; -+ -+ /* POWER DELIVERY */ -+ case policy_src_startup: -+ fusb_state_src_startup(chip, evt); -+ break; -+ case policy_src_discovery: -+ fusb_state_src_discovery(chip, evt); -+ break; -+ case policy_src_send_caps: -+ fusb_state_src_send_caps(chip, evt); -+ if (chip->conn_state != policy_src_negotiate_cap) -+ break; -+ case policy_src_negotiate_cap: -+ fusb_state_src_negotiate_cap(chip, evt); -+ -+ case policy_src_transition_supply: -+ fusb_state_src_transition_supply(chip, evt); -+ break; -+ case policy_src_cap_response: -+ fusb_state_src_cap_response(chip, evt); -+ break; -+ case policy_src_transition_default: -+ fusb_state_src_transition_default(chip, evt); -+ break; -+ case policy_src_ready: -+ fusb_state_src_ready(chip, evt); -+ break; -+ case policy_src_get_sink_caps: -+ fusb_state_src_get_sink_cap(chip, evt); -+ break; -+ case policy_src_send_hardrst: -+ fusb_state_src_send_hardreset(chip, evt); -+ break; -+ case policy_src_send_softrst: -+ fusb_state_src_send_softreset(chip, evt); -+ break; -+ case policy_src_softrst: -+ fusb_state_src_softreset(chip); -+ break; -+ -+ /* UFP */ -+ case policy_snk_startup: -+ fusb_state_snk_startup(chip, evt); -+ break; -+ case policy_snk_discovery: -+ fusb_state_snk_discovery(chip, evt); -+ break; -+ case policy_snk_wait_caps: -+ fusb_state_snk_wait_caps(chip, evt); -+ break; -+ case policy_snk_evaluate_caps: -+ fusb_state_snk_evaluate_caps(chip, evt); -+ /* without break */ -+ case policy_snk_select_cap: -+ fusb_state_snk_select_cap(chip, evt); -+ break; -+ case policy_snk_transition_sink: -+ fusb_state_snk_transition_sink(chip, evt); -+ break; -+ case policy_snk_transition_default: -+ fusb_state_snk_transition_default(chip, evt); -+ break; -+ case policy_snk_ready: -+ fusb_state_snk_ready(chip, evt); -+ break; -+ case policy_snk_send_hardrst: -+ fusb_state_snk_send_hardreset(chip, evt); -+ break; -+ case policy_snk_send_softrst: -+ fusb_state_snk_send_softreset(chip, evt); -+ break; -+ case policy_snk_softrst: -+ fusb_state_snk_softreset(chip); -+ break; -+ -+ /* -+ * PD Spec 1.0: PR SWAP: chap 8.3.3.6.3.1/2 -+ * VC SWAP: chap 8.3.3.7.1/2 -+ */ -+ case policy_src_prs_evaluate: -+ case policy_snk_prs_evaluate: -+ fusb_state_prs_evaluate(chip, evt); -+ break; -+ case policy_snk_prs_accept: -+ case policy_src_prs_accept: -+ fusb_state_prs_accept(chip, evt); -+ break; -+ case policy_snk_prs_reject: -+ case policy_src_prs_reject: -+ case policy_vcs_ufp_reject: -+ case policy_drs_dfp_reject: -+ case policy_drs_ufp_reject: -+ fusb_state_prs_reject(chip, evt); -+ break; -+ case policy_src_prs_transition_to_off: -+ fusb_state_src_prs_transition_to_off(chip, evt); -+ break; -+ case policy_src_prs_assert_rd: -+ fusb_state_src_prs_assert_rd(chip, evt); -+ break; -+ case policy_src_prs_source_off: -+ fusb_state_src_prs_source_off(chip, evt); -+ break; -+ case policy_snk_prs_send_swap: -+ case policy_src_prs_send_swap: -+ fusb_state_send_swap(chip, evt, CMT_PR_SWAP); -+ break; -+ case policy_snk_prs_transition_to_off: -+ fusb_state_snk_prs_transition_to_off(chip, evt); -+ break; -+ case policy_snk_prs_assert_rp: -+ fusb_state_snk_prs_assert_rp(chip, evt); -+ break; -+ case policy_snk_prs_source_on: -+ fusb_state_snk_prs_source_on(chip, evt); -+ break; -+ case policy_vcs_ufp_evaluate_swap: -+ fusb_state_vcs_ufp_evaluate_swap(chip, evt); -+ break; -+ case policy_vcs_ufp_accept: -+ fusb_state_vcs_ufp_accept(chip, evt); -+ break; -+ case policy_vcs_ufp_wait_for_dfp_vconn: -+ case policy_vcs_dfp_wait_for_ufp_vconn: -+ fusb_state_vcs_wait_for_vconn(chip, evt); -+ break; -+ case policy_vcs_ufp_turn_off_vconn: -+ case policy_vcs_dfp_turn_off_vconn: -+ fusb_state_vcs_set_vconn(chip, evt, false); -+ break; -+ case policy_vcs_ufp_turn_on_vconn: -+ case policy_vcs_dfp_turn_on_vconn: -+ fusb_state_vcs_set_vconn(chip, evt, true); -+ break; -+ case policy_vcs_ufp_send_ps_rdy: -+ case policy_vcs_dfp_send_ps_rdy: -+ fusb_state_vcs_send_ps_rdy(chip, evt); -+ break; -+ case policy_vcs_dfp_send_swap: -+ fusb_state_send_swap(chip, evt, CMT_VCONN_SWAP); -+ break; -+ case policy_drs_ufp_evaluate: -+ case policy_drs_dfp_evaluate: -+ fusb_state_drs_evaluate(chip, evt); -+ break; -+ case policy_drs_dfp_accept: -+ case policy_drs_ufp_accept: -+ fusb_state_drs_send_accept(chip, evt); -+ break; -+ case policy_drs_dfp_change: -+ case policy_drs_ufp_change: -+ fusb_state_drs_role_change(chip, evt); -+ break; -+ case policy_drs_ufp_send_swap: -+ case policy_drs_dfp_send_swap: -+ fusb_state_send_swap(chip, evt, CMT_DR_SWAP); -+ break; -+ -+ default: -+ break; -+ } -+ -+BACK: -+ if (chip->work_continue) { -+ queue_work(chip->fusb30x_wq, &chip->work); -+ return; -+ } -+ -+ if (!platform_get_device_irq_state(chip)) -+ fusb_irq_enable(chip); -+ else -+ queue_work(chip->fusb30x_wq, &chip->work); -+} -+ -+static irqreturn_t cc_interrupt_handler(int irq, void *dev_id) -+{ -+ struct fusb30x_chip *chip = dev_id; -+ -+ queue_work(chip->fusb30x_wq, &chip->work); -+ fusb_irq_disable(chip); -+ return IRQ_HANDLED; -+} -+ -+static int fusb_initialize_gpio(struct fusb30x_chip *chip) -+{ -+ chip->gpio_int = devm_gpiod_get_optional(chip->dev, "int-n", GPIOD_IN); -+ if (IS_ERR(chip->gpio_int)) -+ return PTR_ERR(chip->gpio_int); -+ -+ /* some board support vbus with other ways */ -+ chip->gpio_vbus_5v = devm_gpiod_get_optional(chip->dev, "vbus-5v", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(chip->gpio_vbus_5v)) -+ dev_warn(chip->dev, -+ "Could not get named GPIO for VBus5V!\n"); -+ else -+ gpiod_set_raw_value(chip->gpio_vbus_5v, 0); -+ -+ chip->gpio_vbus_other = devm_gpiod_get_optional(chip->dev, -+ "vbus-other", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(chip->gpio_vbus_other)) -+ dev_warn(chip->dev, -+ "Could not get named GPIO for VBusOther!\n"); -+ else -+ gpiod_set_raw_value(chip->gpio_vbus_other, 0); -+ -+ chip->gpio_discharge = devm_gpiod_get_optional(chip->dev, "discharge", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(chip->gpio_discharge)) { -+ dev_warn(chip->dev, -+ "Could not get named GPIO for discharge!\n"); -+ chip->gpio_discharge = NULL; -+ } -+ -+ return 0; -+} -+ -+static enum hrtimer_restart fusb_timer_handler(struct hrtimer *timer) -+{ -+ int i; -+ -+ for (i = 0; i < fusb30x_port_used; i++) { -+ if (timer == &fusb30x_port_info[i]->timer_state_machine) { -+ if (fusb30x_port_info[i]->timer_state != T_DISABLED) -+ fusb30x_port_info[i]->timer_state = 0; -+ break; -+ } -+ -+ if (timer == &fusb30x_port_info[i]->timer_mux_machine) { -+ if (fusb30x_port_info[i]->timer_mux != T_DISABLED) -+ fusb30x_port_info[i]->timer_mux = 0; -+ break; -+ } -+ } -+ -+ if (i != fusb30x_port_used) -+ queue_work(fusb30x_port_info[i]->fusb30x_wq, -+ &fusb30x_port_info[i]->work); -+ -+ return HRTIMER_NORESTART; -+} -+ -+static void fusb_initialize_timer(struct fusb30x_chip *chip) -+{ -+ hrtimer_init(&chip->timer_state_machine, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ chip->timer_state_machine.function = fusb_timer_handler; -+ -+ hrtimer_init(&chip->timer_mux_machine, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ chip->timer_mux_machine.function = fusb_timer_handler; -+ -+ chip->timer_state = T_DISABLED; -+ chip->timer_mux = T_DISABLED; -+} -+ -+static void fusb302_work_func(struct work_struct *work) -+{ -+ struct fusb30x_chip *chip; -+ -+ chip = container_of(work, struct fusb30x_chip, work); -+ state_machine_typec(chip); -+} -+ -+static int fusb30x_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct fusb30x_chip *chip; -+ struct PD_CAP_INFO *pd_cap_info; -+ int ret; -+ char *string[2]; -+ -+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); -+ if (!chip) -+ return -ENOMEM; -+ -+ if (fusb30x_port_used == 0xff) -+ return -1; -+ -+ chip->port_num = fusb30x_port_used++; -+ fusb30x_port_info[chip->port_num] = chip; -+ -+ chip->dev = &client->dev; -+ chip->regmap = devm_regmap_init_i2c(client, &fusb302_regmap_config); -+ if (IS_ERR(chip->regmap)) { -+ dev_err(&client->dev, "Failed to allocate regmap!\n"); -+ return PTR_ERR(chip->regmap); -+ } -+ -+ ret = fusb_initialize_gpio(chip); -+ if (ret) -+ return ret; -+ -+ fusb_initialize_timer(chip); -+ -+ chip->fusb30x_wq = create_workqueue("fusb302_wq"); -+ INIT_WORK(&chip->work, fusb302_work_func); -+ -+ chip->role = ROLE_MODE_NONE; -+ chip->try_role = ROLE_MODE_NONE; -+ if (!of_property_read_string(chip->dev->of_node, "fusb302,role", -+ (const char **)&string[0])) { -+ if (!strcmp(string[0], "ROLE_MODE_DRP")) -+ chip->role = ROLE_MODE_DRP; -+ else if (!strcmp(string[0], "ROLE_MODE_DFP")) -+ chip->role = ROLE_MODE_DFP; -+ else if (!strcmp(string[0], "ROLE_MODE_UFP")) -+ chip->role = ROLE_MODE_UFP; -+ } -+ -+ if (chip->role == ROLE_MODE_NONE) { -+ dev_warn(chip->dev, -+ "Can't get property of role, set role to default DRP\n"); -+ chip->role = ROLE_MODE_DRP; -+ string[0] = "ROLE_MODE_DRP"; -+ } -+ -+ if (!of_property_read_string(chip->dev->of_node, "fusb302,try_role", -+ (const char **)&string[1])) { -+ if (!strcmp(string[1], "ROLE_MODE_DFP")) -+ chip->try_role = ROLE_MODE_DFP; -+ else if (!strcmp(string[1], "ROLE_MODE_UFP")) -+ chip->try_role = ROLE_MODE_UFP; -+ } -+ -+ if (chip->try_role == ROLE_MODE_NONE) -+ string[1] = "ROLE_MODE_NONE"; -+ -+ chip->vconn_supported = true; -+ tcpm_init(chip); -+ tcpm_set_rx_enable(chip, 0); -+ chip->conn_state = unattached; -+ tcpm_set_cc(chip, chip->role); -+ -+ chip->n_caps_used = 1; -+ chip->source_power_supply[0] = 0x64; -+ chip->source_max_current[0] = 0x96; -+ -+ pd_cap_info = &chip->pd_cap_info; -+ pd_cap_info->dual_role_power = 1; -+ pd_cap_info->data_role_swap = 1; -+ -+ pd_cap_info->externally_powered = 1; -+ pd_cap_info->usb_suspend_support = 0; -+ pd_cap_info->usb_communications_cap = 0; -+ pd_cap_info->supply_type = 0; -+ pd_cap_info->peak_current = 0; -+ -+ chip->extcon = devm_extcon_dev_allocate(&client->dev, fusb302_cable); -+ if (IS_ERR(chip->extcon)) { -+ dev_err(&client->dev, "allocat extcon failed\n"); -+ return PTR_ERR(chip->extcon); -+ } -+ -+ ret = devm_extcon_dev_register(&client->dev, chip->extcon); -+ if (ret) { -+ dev_err(&client->dev, "failed to register extcon: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB_HOST property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set DISP_DP property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_SS); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB USB_SS property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_SS); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB_HOST USB_SS property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_SS); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set DISP_DP USB_SS property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_CHG_USB_FAST, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB_PD property capability: %d\n", ret); -+ return ret; -+ } -+ -+ i2c_set_clientdata(client, chip); -+ -+ spin_lock_init(&chip->irq_lock); -+ chip->enable_irq = 1; -+ -+ chip->gpio_int_irq = gpiod_to_irq(chip->gpio_int); -+ if (chip->gpio_int_irq < 0) { -+ dev_err(&client->dev, -+ "Unable to request IRQ for INT_N GPIO! %d\n", -+ ret); -+ ret = chip->gpio_int_irq; -+ goto IRQ_ERR; -+ } -+ -+ ret = devm_request_threaded_irq(&client->dev, -+ chip->gpio_int_irq, -+ NULL, -+ cc_interrupt_handler, -+ IRQF_ONESHOT | IRQF_TRIGGER_LOW, -+ client->name, -+ chip); -+ if (ret) { -+ dev_err(&client->dev, "irq request failed\n"); -+ goto IRQ_ERR; -+ } -+ -+ dev_info(chip->dev, -+ "port %d probe success with role %s, try_role %s\n", -+ chip->port_num, string[0], string[1]); -+ -+ return 0; -+ -+IRQ_ERR: -+ destroy_workqueue(chip->fusb30x_wq); -+ return ret; -+} -+ -+static int fusb30x_remove(struct i2c_client *client) -+{ -+ struct fusb30x_chip *chip = i2c_get_clientdata(client); -+ -+ destroy_workqueue(chip->fusb30x_wq); -+ return 0; -+} -+ -+static void fusb30x_shutdown(struct i2c_client *client) -+{ -+ struct fusb30x_chip *chip = i2c_get_clientdata(client); -+ -+ if (chip->gpio_vbus_5v) -+ gpiod_set_value(chip->gpio_vbus_5v, 0); -+ if (chip->gpio_discharge) { -+ gpiod_set_value(chip->gpio_discharge, 1); -+ msleep(100); -+ gpiod_set_value(chip->gpio_discharge, 0); -+ } -+} -+ -+static const struct of_device_id fusb30x_dt_match[] = { -+ { .compatible = FUSB30X_I2C_DEVICETREE_NAME }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, fusb30x_dt_match); -+ -+static const struct i2c_device_id fusb30x_i2c_device_id[] = { -+ { FUSB30X_I2C_DRIVER_NAME, 0 }, -+ {} -+}; -+MODULE_DEVICE_TABLE(i2c, fusb30x_i2c_device_id); -+ -+static struct i2c_driver fusb30x_driver = { -+ .driver = { -+ .name = FUSB30X_I2C_DRIVER_NAME, -+ .of_match_table = of_match_ptr(fusb30x_dt_match), -+ }, -+ .probe = fusb30x_probe, -+ .remove = fusb30x_remove, -+ .shutdown = fusb30x_shutdown, -+ .id_table = fusb30x_i2c_device_id, -+}; -+ -+module_i2c_driver(fusb30x_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("zain wang "); -+MODULE_DESCRIPTION("fusb302 typec pd driver"); -diff --git a/drivers/staging/fusb30x/fusb30x.h b/drivers/staging/fusb30x/fusb30x.h -new file mode 100644 -index 000000000..4f5ca64f7 ---- /dev/null -+++ b/drivers/staging/fusb30x/fusb30x.h -@@ -0,0 +1,552 @@ -+/* -+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd -+ * Author: Zain Wang -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * Some ideas are from chrome ec and fairchild GPL fusb302 driver. -+ */ -+ -+#ifndef FUSB302_H -+#define FUSB302_H -+ -+#include -+#include -+ -+const char *FUSB_DT_INTERRUPT_INTN = "fsc_interrupt_int_n"; -+#define FUSB_DT_GPIO_INTN "fairchild,int_n" -+#define FUSB_DT_GPIO_VBUS_5V "fairchild,vbus5v" -+#define FUSB_DT_GPIO_VBUS_OTHER "fairchild,vbusOther" -+ -+#define FUSB30X_I2C_DRIVER_NAME "fusb302" -+#define FUSB30X_I2C_DEVICETREE_NAME "fairchild,fusb302" -+ -+/* FUSB300 Register Addresses */ -+#define FUSB_REG_DEVICEID 0x01 -+#define FUSB_REG_SWITCHES0 0x02 -+#define FUSB_REG_SWITCHES1 0x03 -+#define FUSB_REG_MEASURE 0x04 -+#define FUSB_REG_SLICE 0x05 -+#define FUSB_REG_CONTROL0 0x06 -+#define FUSB_REG_CONTROL1 0x07 -+#define FUSB_REG_CONTROL2 0x08 -+#define FUSB_REG_CONTROL3 0x09 -+#define FUSB_REG_MASK 0x0A -+#define FUSB_REG_POWER 0x0B -+#define FUSB_REG_RESET 0x0C -+#define FUSB_REG_OCPREG 0x0D -+#define FUSB_REG_MASKA 0x0E -+#define FUSB_REG_MASKB 0x0F -+#define FUSB_REG_CONTROL4 0x10 -+#define FUSB_REG_STATUS0A 0x3C -+#define FUSB_REG_STATUS1A 0x3D -+#define FUSB_REG_INTERRUPTA 0x3E -+#define FUSB_REG_INTERRUPTB 0x3F -+#define FUSB_REG_STATUS0 0x40 -+#define FUSB_REG_STATUS1 0x41 -+#define FUSB_REG_INTERRUPT 0x42 -+#define FUSB_REG_FIFO 0x43 -+ -+enum connection_state { -+ disabled = 0, -+ error_recovery, -+ unattached, -+ attach_wait_sink, -+ attach_wait_source, -+ attached_source, -+ attached_sink, -+ -+ policy_src_startup, -+ policy_src_send_caps, -+ policy_src_discovery, -+ policy_src_negotiate_cap, -+ policy_src_cap_response, -+ policy_src_transition_supply, -+ policy_src_transition_default, -+ -+ policy_src_ready, -+ policy_src_get_sink_caps, -+ -+ policy_src_send_softrst, -+ policy_src_softrst, -+ policy_src_send_hardrst, -+ -+ policy_snk_startup, -+ policy_snk_discovery, -+ policy_snk_wait_caps, -+ policy_snk_evaluate_caps, -+ policy_snk_select_cap, -+ policy_snk_transition_sink, -+ policy_snk_ready, -+ -+ policy_snk_send_softrst, -+ policy_snk_softrst, -+ policy_snk_send_hardrst, -+ -+ policy_snk_transition_default, -+ -+ /* PR SWAP */ -+ policy_src_prs_evaluate, -+ policy_src_prs_accept, -+ policy_src_prs_transition_to_off, -+ policy_src_prs_source_off, -+ policy_src_prs_assert_rd, -+ policy_src_prs_reject, -+ policy_src_prs_send_swap, -+ -+ policy_snk_prs_evaluate, -+ policy_snk_prs_accept, -+ policy_snk_prs_transition_to_off, -+ policy_snk_prs_source_on, -+ policy_snk_prs_assert_rp, -+ policy_snk_prs_reject, -+ policy_snk_prs_send_swap, -+ -+ /* VC SWAP */ -+ policy_vcs_dfp_send_swap, -+ policy_vcs_dfp_wait_for_ufp_vconn, -+ policy_vcs_dfp_turn_off_vconn, -+ policy_vcs_dfp_turn_on_vconn, -+ policy_vcs_dfp_send_ps_rdy, -+ -+ policy_vcs_ufp_evaluate_swap, -+ policy_vcs_ufp_reject, -+ policy_vcs_ufp_accept, -+ policy_vcs_ufp_wait_for_dfp_vconn, -+ policy_vcs_ufp_turn_off_vconn, -+ policy_vcs_ufp_turn_on_vconn, -+ policy_vcs_ufp_send_ps_rdy, -+ -+ policy_drs_ufp_evaluate, -+ policy_drs_ufp_accept, -+ policy_drs_ufp_reject, -+ policy_drs_ufp_change, -+ policy_drs_ufp_send_swap, -+ -+ policy_drs_dfp_evaluate, -+ policy_drs_dfp_accept, -+ policy_drs_dfp_reject, -+ policy_drs_dfp_change, -+ policy_drs_dfp_send_swap, -+ -+ attach_try_src, -+ attach_try_snk, -+}; -+ -+enum vdm_state { -+ VDM_STATE_DISCOVERY_ID, -+ VDM_STATE_DISCOVERY_SVID, -+ VDM_STATE_DISCOVERY_MODES, -+ VDM_STATE_ENTER_MODE, -+ VDM_STATE_UPDATE_STATUS, -+ VDM_STATE_DP_CONFIG, -+ VDM_STATE_NOTIFY, -+ VDM_STATE_READY, -+ VDM_STATE_ERR, -+}; -+ -+enum tcpm_rp_value { -+ TYPEC_RP_USB = 0, -+ TYPEC_RP_1A5 = 1, -+ TYPEC_RP_3A0 = 2, -+ TYPEC_RP_RESERVED = 3, -+}; -+ -+enum role_mode { -+ ROLE_MODE_NONE, -+ ROLE_MODE_DRP, -+ ROLE_MODE_UFP, -+ ROLE_MODE_DFP, -+ ROLE_MODE_ASS, -+}; -+ -+#define SBF(s, v) ((s) << (v)) -+#define SWITCHES0_PDWN1 SBF(1, 0) -+#define SWITCHES0_PDWN2 SBF(1, 1) -+#define SWITCHES0_MEAS_CC1 SBF(1, 2) -+#define SWITCHES0_MEAS_CC2 SBF(1, 3) -+#define SWITCHES0_VCONN_CC1 SBF(1, 4) -+#define SWITCHES0_VCONN_CC2 SBF(1, 5) -+#define SWITCHES0_PU_EN1 SBF(1, 6) -+#define SWITCHES0_PU_EN2 SBF(1, 7) -+ -+#define SWITCHES1_TXCC1 SBF(1, 0) -+#define SWITCHES1_TXCC2 SBF(1, 1) -+#define SWITCHES1_AUTO_CRC SBF(1, 2) -+#define SWITCHES1_DATAROLE SBF(1, 4) -+#define SWITCHES1_SPECREV SBF(3, 5) -+#define SWITCHES1_POWERROLE SBF(1, 7) -+ -+#define MEASURE_MDAC SBF(0x3f, 0) -+#define MEASURE_VBUS SBF(1, 6) -+ -+#define SLICE_SDAC SBF(0x3f, 0) -+#define SLICE_SDAC_HYS SBF(3, 6) -+ -+#define CONTROL0_TX_START SBF(1, 0) -+#define CONTROL0_AUTO_PRE SBF(1, 1) -+#define CONTROL0_HOST_CUR SBF(3, 2) -+#define CONTROL0_HOST_CUR_USB SBF(1, 2) -+#define CONTROL0_HOST_CUR_1A5 SBF(2, 2) -+#define CONTROL0_HOST_CUR_3A0 SBF(3, 2) -+#define CONTROL0_INT_MASK SBF(1, 5) -+#define CONTROL0_TX_FLUSH SBF(1, 6) -+ -+#define CONTROL1_ENSOP1 SBF(1, 0) -+#define CONTROL1_ENSOP2 SBF(1, 1) -+#define CONTROL1_RX_FLUSH SBF(1, 2) -+#define CONTROL1_BIST_MODE2 SBF(1, 4) -+#define CONTROL1_ENSOP1DB SBF(1, 5) -+#define CONTROL1_ENSOP2DB SBF(1, 6) -+ -+#define CONTROL2_TOGGLE SBF(1, 0) -+#define CONTROL2_MODE SBF(3, 1) -+#define CONTROL2_MODE_NONE 0 -+#define CONTROL2_MODE_DFP SBF(3, 1) -+#define CONTROL2_MODE_UFP SBF(2, 1) -+#define CONTROL2_MODE_DRP SBF(1, 1) -+#define CONTROL2_WAKE_EN SBF(1, 3) -+#define CONTROL2_TOG_RD_ONLY SBF(1, 5) -+#define CONTROL2_TOG_SAVE_PWR1 SBF(1, 6) -+#define CONTROL2_TOG_SAVE_PWR2 SBF(1, 7) -+ -+#define CONTROL3_AUTO_RETRY SBF(1, 0) -+#define CONTROL3_N_RETRIES SBF(3, 1) -+#define CONTROL3_AUTO_SOFTRESET SBF(1, 3) -+#define CONTROL3_AUTO_HARDRESET SBF(1, 4) -+#define CONTROL3_SEND_HARDRESET SBF(1, 6) -+ -+#define MASK_M_BC_LVL SBF(1, 0) -+#define MASK_M_COLLISION SBF(1, 1) -+#define MASK_M_WAKE SBF(1, 2) -+#define MASK_M_ALERT SBF(1, 3) -+#define MASK_M_CRC_CHK SBF(1, 4) -+#define MASK_M_COMP_CHNG SBF(1, 5) -+#define MASK_M_ACTIVITY SBF(1, 6) -+#define MASK_M_VBUSOK SBF(1, 7) -+ -+#define POWER_PWR SBF(0xf, 0) -+ -+#define RESET_SW_RESET SBF(1, 0) -+#define RESET_PD_RESET SBF(1, 1) -+ -+#define MASKA_M_HARDRST SBF(1, 0) -+#define MASKA_M_SOFTRST SBF(1, 1) -+#define MASKA_M_TXSENT SBF(1, 2) -+#define MASKA_M_HARDSENT SBF(1, 3) -+#define MASKA_M_RETRYFAIL SBF(1, 4) -+#define MASKA_M_SOFTFAIL SBF(1, 5) -+#define MASKA_M_TOGDONE SBF(1, 6) -+#define MASKA_M_OCP_TEMP SBF(1, 7) -+ -+#define MASKB_M_GCRCSEND SBF(1, 0) -+ -+#define CONTROL4_TOG_USRC_EXIT SBF(1, 0) -+ -+#define MDAC_1P6V 0x26 -+ -+#define STATUS0A_HARDRST SBF(1, 0) -+#define STATUS0A_SOFTRST SBF(1, 1) -+#define STATUS0A_POWER23 SBF(3, 2) -+#define STATUS0A_RETRYFAIL SBF(1, 4) -+#define STATUS0A_SOFTFAIL SBF(1, 5) -+#define STATUS0A_TOGDONE SBF(1, 6) -+#define STATUS0A_M_OCP_TEMP SBF(1, 7) -+ -+#define STATUS1A_RXSOP SBF(1, 0) -+#define STATUS1A_RXSOP1DB SBF(1, 1) -+#define STATUS1A_RXSOP2DB SBF(1, 2) -+#define STATUS1A_TOGSS SBF(7, 3) -+#define CC_STATE_TOGSS_CC1 SBF(1, 0) -+#define CC_STATE_TOGSS_CC2 SBF(1, 1) -+#define CC_STATE_TOGSS_IS_UFP SBF(1, 2) -+ -+#define INTERRUPTA_HARDRST SBF(1, 0) -+#define INTERRUPTA_SOFTRST SBF(1, 1) -+#define INTERRUPTA_TXSENT SBF(1, 2) -+#define INTERRUPTA_HARDSENT SBF(1, 3) -+#define INTERRUPTA_RETRYFAIL SBF(1, 4) -+#define INTERRUPTA_SOFTFAIL SBF(1, 5) -+#define INTERRUPTA_TOGDONE SBF(1, 6) -+#define INTERRUPTA_OCP_TEMP SBF(1, 7) -+ -+#define INTERRUPTB_GCRCSENT SBF(1, 0) -+ -+#define STATUS0_BC_LVL SBF(3, 0) -+#define STATUS0_WAKE SBF(1, 2) -+#define STATUS0_ALERT SBF(1, 3) -+#define STATUS0_CRC_CHK SBF(1, 4) -+#define STATUS0_COMP SBF(1, 5) -+#define STATUS0_ACTIVITY SBF(1, 6) -+#define STATUS0_VBUSOK SBF(1, 7) -+ -+#define STATUS1_OCP SBF(1, 0) -+#define STATUS1_OVRTEMP SBF(1, 1) -+#define STATUS1_TX_FULL SBF(1, 2) -+#define STATUS1_TX_EMPTY SBF(1, 3) -+#define STATUS1_RX_FULL SBF(1, 4) -+#define STATUS1_RX_EMPTY SBF(1, 5) -+#define STATUS1_RXSOP1 SBF(1, 6) -+#define STATUS1_RXSOP2 SBF(1, 7) -+ -+#define INTERRUPT_BC_LVL SBF(1, 0) -+#define INTERRUPT_COLLISION SBF(1, 1) -+#define INTERRUPT_WAKE SBF(1, 2) -+#define INTERRUPT_ALERT SBF(1, 3) -+#define INTERRUPT_CRC_CHK SBF(1, 4) -+#define INTERRUPT_COMP_CHNG SBF(1, 5) -+#define INTERRUPT_ACTIVITY SBF(1, 6) -+#define INTERRUPT_VBUSOK SBF(1, 7) -+ -+#define FUSB_TKN_TXON 0xa1 -+#define FUSB_TKN_SYNC1 0x12 -+#define FUSB_TKN_SYNC2 0x13 -+#define FUSB_TKN_SYNC3 0x1b -+#define FUSB_TKN_RST1 0x15 -+#define FUSB_TKN_RST2 0x16 -+#define FUSB_TKN_PACKSYM 0x80 -+#define FUSB_TKN_JAMCRC 0xff -+#define FUSB_TKN_EOP 0x14 -+#define FUSB_TKN_TXOFF 0xfe -+ -+/* USB PD Control Message Types */ -+#define CONTROLMESSAGE 0 -+#define CMT_GOODCRC 1 -+#define CMT_GOTOMIN 2 -+#define CMT_ACCEPT 3 -+#define CMT_REJECT 4 -+#define CMT_PING 5 -+#define CMT_PS_RDY 6 -+#define CMT_GETSOURCECAP 7 -+#define CMT_GETSINKCAP 8 -+#define CMT_DR_SWAP 9 -+#define CMT_PR_SWAP 10 -+#define CMT_VCONN_SWAP 11 -+#define CMT_WAIT 12 -+#define CMT_SOFTRESET 13 -+ -+/* USB PD Data Message Types */ -+#define DATAMESSAGE 1 -+#define DMT_SOURCECAPABILITIES 1 -+#define DMT_REQUEST 2 -+#define DMT_BIST 3 -+#define DMT_SINKCAPABILITIES 4 -+#define DMT_VENDERDEFINED 15 -+ -+/* VDM Command Types */ -+#define VDM_DISCOVERY_ID 0X01 -+#define VDM_DISCOVERY_SVIDS 0X02 -+#define VDM_DISCOVERY_MODES 0X03 -+#define VDM_ENTER_MODE 0X04 -+#define VDM_EXIT_MODE 0X05 -+#define VDM_ATTENTION 0X06 -+#define VDM_DP_STATUS_UPDATE 0X10 -+#define VDM_DP_CONFIG 0X11 -+ -+#define VDM_TYPE_INIT 0 -+#define VDM_TYPE_ACK 1 -+#define VDM_TYPE_NACK 2 -+#define VDM_TYPE_BUSY 3 -+ -+/* 200ms at least, 1 cycle about 6ms */ -+#define N_DEBOUNCE_CNT 33 -+#define N_CAPS_COUNT 50 -+#define N_HARDRESET_COUNT 0 -+ -+#define T_NO_RESPONSE 5000 -+#define T_SRC_RECOVER 830 -+#define T_TYPEC_SEND_SOURCECAP 100 -+#define T_SENDER_RESPONSE 30 -+#define T_SRC_TRANSITION 30 -+#define T_TYPEC_SINK_WAIT_CAP 500 -+#define T_PS_TRANSITION 500 -+#define T_BMC_TIMEOUT 5 -+#define T_PS_HARD_RESET_MAX 35 -+#define T_SAFE_0V 650 -+#define T_SRC_TURN_ON 275 -+#define T_SRC_RECOVER_MAX 1000 -+#define T_PD_SOURCE_OFF 920 -+#define T_PD_SOURCE_ON 480 -+#define T_PD_SWAP_SOURCE_START 20 -+#define T_PD_VCONN_SRC_ON 100 -+#define T_PD_TRY_DRP 75 -+ -+#define T_NO_TRIGGER 500 -+#define T_DISABLED 0xffff -+ -+#define PD_HEADER_CNT(header) (((header) >> 12) & 7) -+#define PD_HEADER_TYPE(header) ((header) & 0xF) -+#define PD_HEADER_ID(header) (((header) >> 9) & 7) -+ -+#define VDM_HEADER_TYPE(header) (((header) >> 6) & 3) -+#define VDMHEAD_CMD_TYPE_MASK (3 << 6) -+#define VDMHEAD_CMD_MASK (0x1f << 0) -+#define VDMHEAD_STRUCT_TYPE_MASK BIT(15) -+ -+#define GET_VDMHEAD_CMD_TYPE(head) ((head & VDMHEAD_CMD_TYPE_MASK) >> 6) -+#define GET_VDMHEAD_CMD(head) (head & VDMHEAD_CMD_MASK) -+#define GET_VDMHEAD_STRUCT_TYPE(head) ((head & VDMHEAD_STRUCT_TYPE_MASK) >> 15) -+ -+#define DP_STATUS_MASK 0x000000ff -+#define DP_STATUS_HPD_STATE BIT(7) -+ -+#define GET_DP_STATUS(status) (status & DP_STATUS_MASK) -+#define GET_DP_STATUS_HPD(status) ((status & DP_STATUS_HPD_STATE) >> 7) -+ -+#define VDM_IDHEAD_USBVID_MASK (0xffff << 0) -+#define VDM_IDHEAD_MODALSUPPORT_MASK BIT(26) -+#define VDM_IDHEAD_PRODUCTTYPE (7 << 27) -+#define VDM_IDHEAD_USBDEVICE BIT(30) -+#define VDM_IDHEAD_USBHOST BIT(30) -+ -+#define CAP_POWER_TYPE(PDO) ((PDO >> 30) & 3) -+#define CAP_FPDO_VOLTAGE(PDO) ((PDO >> 10) & 0x3ff) -+#define CAP_VPDO_VOLTAGE(PDO) ((PDO >> 20) & 0x3ff) -+#define CAP_FPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff) -+#define CAP_VPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff) -+ -+enum CC_ORIENTATION { -+ NONE, -+ CC1, -+ CC2, -+}; -+ -+enum typec_cc_polarity { -+ TYPEC_POLARITY_CC1, -+ TYPEC_POLARITY_CC2, -+}; -+ -+enum CC_MODE { -+ CC_PULL_UP, -+ CC_PULL_DOWN, -+ CC_PULL_NONE, -+}; -+ -+enum typec_power_role { -+ POWER_ROLE_SINK = 0, -+ POWER_ROLE_SOURCE, -+}; -+ -+enum typec_data_role { -+ DATA_ROLE_UFP = 0, -+ DATA_ROLE_DFP, -+}; -+ -+struct notify_info { -+ enum CC_ORIENTATION orientation; -+ /* 0 UFP : 1 DFP */ -+ enum typec_power_role power_role; -+ enum typec_data_role data_role; -+ -+ bool is_cc_connected; -+ bool is_pd_connected; -+ -+ bool is_enter_mode; -+ int pin_assignment_support; -+ int pin_assignment_def; -+ bool attention; -+ u32 dp_status; -+ u32 dp_caps; -+}; -+ -+enum tx_state { -+ tx_idle, -+ tx_busy, -+ tx_failed, -+ tx_success -+}; -+ -+struct PD_CAP_INFO { -+ u32 peak_current; -+ u32 specification_revision; -+ u32 externally_powered; -+ u32 usb_suspend_support; -+ u32 usb_communications_cap; -+ u32 dual_role_power; -+ u32 data_role_swap; -+ u32 supply_type; -+}; -+ -+struct fusb30x_chip { -+ struct i2c_client *client; -+ struct device *dev; -+ struct regmap *regmap; -+ struct work_struct work; -+ struct workqueue_struct *fusb30x_wq; -+ struct hrtimer timer_state_machine; -+ struct hrtimer timer_mux_machine; -+ struct PD_CAP_INFO pd_cap_info; -+ struct notify_info notify; -+ struct notify_info notify_cmp; -+ struct extcon_dev *extcon; -+ enum connection_state conn_state; -+ struct gpio_desc *gpio_vbus_5v; -+ struct gpio_desc *gpio_vbus_other; -+ struct gpio_desc *gpio_int; -+ struct gpio_desc *gpio_discharge; -+ int timer_state; -+ int timer_mux; -+ int port_num; -+ u32 work_continue; -+ spinlock_t irq_lock; -+ int gpio_int_irq; -+ int enable_irq; -+ -+ /* -+ * --------------------------------- -+ * | role 0x03 << 2, | cc_use 0x03 | -+ * | src 1 << 2, | cc1 1 | -+ * | snk 2 << 2, | cc2 2 | -+ * --------------------------------- -+ */ -+ u8 cc_state; -+ int cc1; -+ int cc2; -+ enum typec_cc_polarity cc_polarity; -+ u8 val_tmp; -+ u8 debounce_cnt; -+ int sub_state; -+ int caps_counter; -+ u32 send_load[7]; -+ u32 rec_load[7]; -+ u16 send_head; -+ u16 rec_head; -+ int msg_id; -+ enum tx_state tx_state; -+ int hardrst_count; -+ u32 source_power_supply[7]; -+ /* 50mv unit */ -+ u32 source_max_current[7]; -+ /* 10ma uint*/ -+ int pos_power; -+ /* -+ * if PartnerCap[0] == 0xffffffff -+ * show Partner Device do not support supply -+ */ -+ u32 partner_cap[7]; -+ int n_caps_used; -+ int vdm_state; -+ int vdm_substate; -+ int vdm_send_state; -+ u16 vdm_svid[12]; -+ int vdm_svid_num; -+ u32 vdm_id; -+ u8 chip_id; -+ bool vconn_enabled; -+ bool is_pd_support; -+ int pd_output_vol; -+ int pd_output_cur; -+ int cc_meas_high; -+ int cc_meas_low; -+ bool vbus_begin; -+ -+ enum role_mode role; -+ bool vconn_supported; -+ bool try_role_complete; -+ enum role_mode try_role; -+}; -+ -+#endif /* FUSB302_H */ -+ diff --git a/sys-kernel/decade-sources/files/patches-5.13/add-maker-friendlyarm.patch b/sys-kernel/decade-sources/files/patches-5.13/add-maker-friendlyarm.patch deleted file mode 100644 index f48596b..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/add-maker-friendlyarm.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 2fc2cbaaaf0dcebdeffa6e87bbc9ad843a5470dd Mon Sep 17 00:00:00 2001 -From: hmz007 -Date: Sat, 11 Jan 2020 19:35:03 +0800 -Subject: [PATCH] soc: friendlyelec: Add board info driver - -Change-Id: I122adb4f99c816b5c177f16392fb2df9c10a47be -Signed-off-by: hmz007 ---- - drivers/soc/Kconfig | 1 + - drivers/soc/Makefile | 1 + - drivers/soc/friendlyelec/Kconfig | 11 ++ - drivers/soc/friendlyelec/Makefile | 1 + - drivers/soc/friendlyelec/board.c | 143 ++++++++++++++++++ - 8 files changed, 161 insertions(+) - create mode 100644 drivers/soc/friendlyelec/Kconfig - create mode 100644 drivers/soc/friendlyelec/Makefile - create mode 100644 drivers/soc/friendlyelec/board.c - -diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig -index 833e04a7835c..9ddbd976395d 100644 ---- a/drivers/soc/Kconfig -+++ b/drivers/soc/Kconfig -@@ -21,5 +21,6 @@ source "drivers/soc/ux500/Kconfig" - source "drivers/soc/ux500/Kconfig" - source "drivers/soc/versatile/Kconfig" - source "drivers/soc/xilinx/Kconfig" -+source "drivers/soc/friendlyelec/Kconfig" - - endmenu -diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile -index f678e4d9e..cfc815a7e 100644 ---- a/drivers/soc/Makefile -+++ b/drivers/soc/Makefile -@@ -29,3 +29,4 @@ obj-y += ti/ - obj-$(CONFIG_ARCH_U8500) += ux500/ - obj-$(CONFIG_PLAT_VERSATILE) += versatile/ - obj-y += xilinx/ -+obj-$(CONFIG_VENDOR_FRIENDLYELEC) += friendlyelec/ -diff --git a/drivers/soc/friendlyelec/Kconfig b/drivers/soc/friendlyelec/Kconfig -new file mode 100644 -index 000000000000..9e21c663e6c8 ---- /dev/null -+++ b/drivers/soc/friendlyelec/Kconfig -@@ -0,0 +1,11 @@ -+# -+# Machine drivers -+# -+ -+if ARCH_ROCKCHIP -+ -+config VENDOR_FRIENDLYELEC -+ bool "FriendlyElec board based on RK33XX SoCs" -+ default n -+ -+endif -diff --git a/drivers/soc/friendlyelec/Makefile b/drivers/soc/friendlyelec/Makefile -new file mode 100644 -index 000000000000..870542f05177 ---- /dev/null -+++ b/drivers/soc/friendlyelec/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_VENDOR_FRIENDLYELEC) += board.o -diff --git a/drivers/soc/friendlyelec/board.c b/drivers/soc/friendlyelec/board.c -new file mode 100644 -index 000000000000..886a8e1f7dc0 ---- /dev/null -+++ b/drivers/soc/friendlyelec/board.c -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) Guangzhou FriendlyELEC Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, you can access it online at -+ * http://www.gnu.org/licenses/gpl-2.0.html. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define BOARD_MANF "FriendlyELEC Computer Tech. Co., Ltd." -+ -+static const char *board_mach; -+static const char *board_name; -+static u32 board_rev; -+static u32 board_serial_high, board_serial_low; -+ -+static ssize_t board_sys_info_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ char *s = buf; -+ -+ s += sprintf(s, "Hardware\t: %s\n", board_mach); -+ s += sprintf(s, "Revision\t: %04x\n", board_rev); -+ s += sprintf(s, "Serial\t\t: %08x%08x\n", -+ board_serial_high, board_serial_low); -+ s += sprintf(s, "\nModel\t\t: %s\n", board_name); -+ s += sprintf(s, "Manufacturer\t: %s\n", BOARD_MANF); -+ -+ return (s - buf); -+} -+ -+static struct device_attribute board_attr_info = -+ __ATTR(info, S_IRUGO, board_sys_info_show, NULL); -+ -+static int rockchip_cpuinfo_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct nvmem_cell *cell; -+ unsigned char *efuse_buf, buf[16]; -+ size_t len; -+ int i; -+ -+ cell = nvmem_cell_get(dev, "id"); -+ if (IS_ERR(cell)) { -+ dev_err(dev, "failed to get id cell: %ld\n", PTR_ERR(cell)); -+ return PTR_ERR(cell); -+ } -+ -+ efuse_buf = nvmem_cell_read(cell, &len); -+ nvmem_cell_put(cell); -+ -+ if (len != 16) { -+ kfree(efuse_buf); -+ dev_err(dev, "invalid id len: %zu\n", len); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < 8; i++) { -+ buf[i] = efuse_buf[1 + (i << 1)]; -+ buf[i + 8] = efuse_buf[i << 1]; -+ } -+ -+ kfree(efuse_buf); -+ -+ board_serial_low = crc32(0, buf, 8); -+ board_serial_high = crc32(board_serial_low, buf + 8, 8); -+ -+ dev_info(dev, "Serial\t\t: %08x%08x\n", -+ board_serial_high, board_serial_low); -+ -+ return 0; -+} -+ -+static int board_sys_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *root; -+ -+ root = of_find_node_by_path("/"); -+ -+ of_property_read_u32(np, "hwrev", &board_rev); -+ -+ if (of_property_read_string(np, "machine", &board_mach)) -+ of_property_read_string(root, "compatible", &board_mach); -+ -+ if (of_property_read_string(np, "model", &board_name)) -+ of_property_read_string(root, "model", &board_name); -+ -+ of_node_put(root); -+ -+ rockchip_cpuinfo_probe(pdev); -+ -+ device_create_file(&pdev->dev, &board_attr_info); -+ -+ return 0; -+} -+ -+static const struct of_device_id board_sys_of_match[] = { -+ { .compatible = "friendlyelec,board" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, board_sys_of_match); -+ -+static struct platform_driver board_sys_driver = { -+ .probe = board_sys_probe, -+ .driver = { -+ .name = "friendlyelec-board", -+ .of_match_table = board_sys_of_match, -+ }, -+}; -+ -+static int __init board_sys_init(void) -+{ -+ return platform_driver_register(&board_sys_driver); -+} -+late_initcall(board_sys_init); -+ -+MODULE_AUTHOR("support@friendlyarm.com"); -+MODULE_DESCRIPTION("FriendlyElec NanoPi Series Machine Driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-add-sound-card.patch b/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-add-sound-card.patch deleted file mode 100644 index 6f5c6c6..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-add-sound-card.patch +++ /dev/null @@ -1,106 +0,0 @@ -diff -u a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi 2019-10-17 23:47:33.000000000 +0300 -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi 2019-10-27 22:34:55.988303874 +0300 -@@ -105,6 +105,27 @@ - }; - }; - -+ rt5651-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "realtek,rt5651-codec"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <256>; -+ simple-audio-card,widgets = -+ "Microphone", "Mic Jack", -+ "Headphone", "Headphone Jack"; -+ simple-audio-card,routing = -+ "Mic Jack", "micbias1", -+ "IN1P", "Mic Jack", -+ "Headphone Jack", "HPOL", -+ "Headphone Jack", "HPOR"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s1>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&rt5651>; -+ }; -+ }; -+ - sdio_pwrseq: sdio-pwrseq { - compatible = "mmc-pwrseq-simple"; - clocks = <&rk808 1>; -@@ -184,6 +205,10 @@ - status = "okay"; - }; - -+&hdmi_sound { -+ status = "okay"; -+}; -+ - &i2c0 { - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <160>; -@@ -432,6 +457,16 @@ - i2c-scl-rising-time-ns = <150>; - i2c-scl-falling-time-ns = <30>; - status = "okay"; -+ -+ rt5651: rt5651@1a { -+ compatible = "realtek,rt5651"; -+ reg = <0x1a>; -+ clocks = <&cru SCLK_I2S_8CH_OUT>; -+ clock-names = "mclk"; -+ hp-det-gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; -+ // spk-con-gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; -+ #sound-dai-cells = <0>; -+ }; - }; - - &i2c2 { -@@ -459,6 +494,16 @@ - status = "okay"; - }; - -+&i2s1 { -+ rockchip,playback-channels = <8>; -+ rockchip,capture-channels = <8>; -+ status = "okay"; -+}; -+ -+&i2s2 { -+ status = "okay"; -+}; -+ - &io_domains { - bt656-supply = <&vcc_1v8>; - audio-supply = <&vcca1v8_codec>; -@@ -724,3 +769,9 @@ - &vopl_mmu { - status = "okay"; - }; -+ -+&spdif { -+ i2c-scl-rising-time-ns = <450>; -+ i2c-scl-falling-time-ns = <15>; -+ status = "okay"; -+}; -diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig -index b43657e6e..fb75c425e 100644 ---- a/sound/soc/rockchip/Kconfig -+++ b/sound/soc/rockchip/Kconfig -@@ -53,6 +53,15 @@ config SND_SOC_ROCKCHIP_RT5645 - Say Y or M here if you want to add support for SoC audio on Rockchip - boards using the RT5645/RT5650 codec, such as Veyron. - -+config SND_SOC_ROCKCHIP_RT5651 -+ tristate "ASoC support for Rockchip boards using a RT5651 codec" -+ depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP -+ select SND_SOC_ROCKCHIP_I2S -+ select SND_SOC_RT5651 -+ help -+ Say Y or M here if you want to add support for SoC audio on Rockchip -+ boards using the RT5651 codec, such as FriendlyARM's Nano{Pi,PC} family. -+ - config SND_SOC_RK3288_HDMI_ANALOG - tristate "ASoC support multiple codecs for Rockchip RK3288 boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-ethernet-tweak.patch b/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-ethernet-tweak.patch deleted file mode 100644 index bb2cef9..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-ethernet-tweak.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -index 60358ab8c..057045ca3 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -@@ -48,6 +48,10 @@ - }; - }; - -+&gmac { -+ rx_delay = <0x16>; -+}; -+ - &vcc3v3_sys { - vin-supply = <&vcc5v0_core>; - }; diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-fix-stability-issues.patch b/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-fix-stability-issues.patch deleted file mode 100644 index d666555..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-nanopi-m4v2-dts-fix-stability-issues.patch +++ /dev/null @@ -1,29 +0,0 @@ -By default rk808's buck regulators switch voltage in multiple 100mV jumps. -This seems to be too much for NanoPi M4V2 and makes it unstable. - -Shortening the steps to 50mV (4 multiple of base buck step which is 12.5mV) -makes the NanoPi M4V2 stable. -Tested with multiple hours of running memtester without a single failure. - -Signed-off-by: Piotr Szczepanik - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -index 2dcaf497c..094440ce3 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -@@ -64,6 +64,10 @@ &gmac { - rx_delay = <0x16>; - }; - -+&rk808 { -+ max-buck-steps-per-change = <4>; -+}; -+ - &vcc3v3_sys { - vin-supply = <&vcc5v0_core>; - }; -@@ -80,3 +84,4 @@ &vbus_typec { - regulator-always-on; - vin-supply = <&vdd_5v>; - }; -+ diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-roc-rk3399-pc-fix-fusb302-compatible.patch b/sys-kernel/decade-sources/files/patches-5.13/board-roc-rk3399-pc-fix-fusb302-compatible.patch deleted file mode 100644 index 5f41dd4..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-roc-rk3399-pc-fix-fusb302-compatible.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -index 9f225e9c3..057c938be 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -@@ -506,7 +506,7 @@ - status = "okay"; - - fusb1: usb-typec@22 { -- compatible = "fcs,fusb302"; -+ compatible = "fairchild,fusb302"; - reg = <0x22>; - interrupt-parent = <&gpio1>; - interrupts = <1 IRQ_TYPE_LEVEL_LOW>; -@@ -523,7 +523,7 @@ - status = "okay"; - - fusb0: usb-typec@22 { -- compatible = "fcs,fusb302"; -+ compatible = "fairchild,fusb302"; - reg = <0x22>; - interrupt-parent = <&gpio1>; - interrupts = <2 IRQ_TYPE_LEVEL_LOW>; diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0004-ethernet-stmmac-dwmac-rk-Add-MAC-driver-support-for-.patch b/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0004-ethernet-stmmac-dwmac-rk-Add-MAC-driver-support-for-.patch deleted file mode 100644 index 8653970..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0004-ethernet-stmmac-dwmac-rk-Add-MAC-driver-support-for-.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 3aab567792a7fa949e8aca7a92a31f15d435efbe Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Thu, 16 Jan 2020 21:11:56 +0100 -Subject: [PATCH 04/23] ethernet: stmmac: dwmac-rk: Add MAC driver support for - rk3308 - -Probably in the wrong place, as it's only 10/100 but :meh: - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -index dc50ba13a746..cfeca75ed284 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -482,6 +482,64 @@ static const struct rk_gmac_ops rk3288_ops = { - .set_rmii_speed = rk3288_set_rmii_speed, - }; - -+#define RK3308_GRF_MAC_CON0 0x04a0 -+ -+/* Rk3308_GRF_MAC_CON1 */ -+#define RK3308_MAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(2) | GRF_CLR_BIT(3) | \ -+ GRF_BIT(4)) -+#define RK3308_MAC_SPEED_10M GRF_CLR_BIT(0) -+#define Rk3308_MAC_SPEED_100M GRF_BIT(0) -+ -+static void rk3308_set_to_rmii(struct rk_priv_data *bsp_priv) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ return; -+ } -+ -+ regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, -+ RK3308_MAC_PHY_INTF_SEL_RMII); -+} -+ -+static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ int ret; -+ -+ if (IS_ERR(bsp_priv->clk_mac_speed)) { -+ dev_err(dev, "%s: Missing clk_mac_speed clock\n", __func__); -+ return; -+ } -+ -+ if (speed == 10) { -+ regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, -+ RK3308_MAC_SPEED_10M); -+ -+ ret = clk_set_rate(bsp_priv->clk_mac_speed, 2500000); -+ if (ret) -+ dev_err(dev, "%s: set clk_mac_speed rate 2500000 failed: %d\n", -+ __func__, ret); -+ } else if (speed == 100) { -+ regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, -+ Rk3308_MAC_SPEED_100M); -+ -+ ret = clk_set_rate(bsp_priv->clk_mac_speed, 25000000); -+ if (ret) -+ dev_err(dev, "%s: set clk_mac_speed rate 25000000 failed: %d\n", -+ __func__, ret); -+ -+ } else { -+ dev_err(dev, "unknown speed value for RMII! speed=%d", speed); -+ } -+} -+ -+static const struct rk_gmac_ops rk3308_ops = { -+ .set_to_rmii = rk3308_set_to_rmii, -+ .set_rmii_speed = rk3308_set_rmii_speed, -+}; -+ - #define RK3328_GRF_MAC_CON0 0x0900 - #define RK3328_GRF_MAC_CON1 0x0904 - #define RK3328_GRF_MAC_CON2 0x0908 -@@ -1477,6 +1535,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = { - { .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops }, - { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, - { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, -+ { .compatible = "rockchip,rk3308-gmac", .data = &rk3308_ops }, - { .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops }, - { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops }, - { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch b/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch deleted file mode 100644 index b041586..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 498c9f200325f0397fd03163a98e053430b80aa4 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Fri, 17 Jan 2020 15:58:20 +0100 -Subject: [PATCH 08/23] thermal: rockchip: add tsadc support for rk3308 - -From a231e9c68e5f5e6cf5a82a40828cfd1df4ad1f3e Mon Sep 17 00:00:00 2001 -From: Rocky Hao -Date: Fri, 9 Mar 2018 17:36:39 +0800 -Subject: [PATCH] thermal: rockchip: add tsadc support for rk3308 - -Change-Id: Ibf1782ca471c8ad4b14d6fd64eeb123181903adc -Signed-off-by: Rocky Hao ---- - .../bindings/thermal/rockchip-thermal.txt | 1 + - drivers/thermal/rockchip_thermal.c | 28 +++++++++++++++++++ - 2 files changed, 29 insertions(+) - -diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt -index c6aac9bcacf1..3a0a9556680e 100644 ---- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt -+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt -@@ -6,6 +6,7 @@ Required properties: - "rockchip,rv1108-tsadc": found on RV1108 SoCs - "rockchip,rk3228-tsadc": found on RK3228 SoCs - "rockchip,rk3288-tsadc": found on RK3288 SoCs -+ "rockchip,rk3308-tsadc": found on RK3308 SoCs - "rockchip,rk3328-tsadc": found on RK3328 SoCs - "rockchip,rk3368-tsadc": found on RK3368 SoCs - "rockchip,rk3399-tsadc": found on RK3399 SoCs -diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c -index 343c2f5c5a25..d4d66724535a 100644 ---- a/drivers/thermal/rockchip_thermal.c -+++ b/drivers/thermal/rockchip_thermal.c -@@ -821,6 +821,30 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, - writel_relaxed(val, regs + TSADCV2_INT_EN); - } - -+static const struct rockchip_tsadc_chip rk3308_tsadc_data = { -+ .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ -+ .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ -+ .chn_num = 2, /* 2 channels for tsadc */ -+ -+ .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ -+ .tshut_temp = 95000, -+ -+ .initialize = rk_tsadcv4_initialize, -+ .irq_ack = rk_tsadcv3_irq_ack, -+ .control = rk_tsadcv3_control, -+ .get_temp = rk_tsadcv2_get_temp, -+ .set_alarm_temp = rk_tsadcv2_alarm_temp, -+ .set_tshut_temp = rk_tsadcv2_tshut_temp, -+ .set_tshut_mode = rk_tsadcv2_tshut_mode, -+ -+ .table = { -+ .id = rk3328_code_table, -+ .length = ARRAY_SIZE(rk3328_code_table), -+ .data_mask = TSADCV2_DATA_MASK, -+ .mode = ADC_INCREMENT, -+ }, -+}; -+ - static const struct rockchip_tsadc_chip px30_tsadc_data = { - .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ - .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ -@@ -1032,6 +1056,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = { - .compatible = "rockchip,rk3288-tsadc", - .data = (void *)&rk3288_tsadc_data, - }, -+ { -+ .compatible = "rockchip,rk3308-tsadc", -+ .data = (void *)&rk3308_tsadc_data, -+ }, - { - .compatible = "rockchip,rk3328-tsadc", - .data = (void *)&rk3328_tsadc_data, --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch b/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch deleted file mode 100644 index 8509312..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch +++ /dev/null @@ -1,1083 +0,0 @@ -From e07dd04b6af66325e3dee7a88aa8c6be5a8cb472 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 15:26:23 +0100 -Subject: [PATCH 16/23] ASoC: rockchip: add support for rockchip i2s/tdm - controller - -From 018d1c86c16617eaae1b9fd0d07cc2c70c11006f Mon Sep 17 00:00:00 2001 -From: Sugar Zhang -Date: Sat, 24 Mar 2018 17:01:49 +0800 -Subject: [PATCH] ASoC: rockchip: add support for rockchip i2s/tdm controller - -This patch is add for rockchip i2s/tdm controller. - -Change-Id: I428e311402220ff14441c48e13fa51356ced46e8 -Signed-off-by: Sugar Zhang ---- - .../bindings/sound/rockchip,i2s-tdm.txt | 42 ++ - sound/soc/rockchip/Kconfig | 9 + - sound/soc/rockchip/Makefile | 2 + - sound/soc/rockchip/rockchip_i2s_tdm.c | 700 ++++++++++++++++++ - sound/soc/rockchip/rockchip_i2s_tdm.h | 256 +++++++ - 5 files changed, 1009 insertions(+) - create mode 100644 Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt - create mode 100644 sound/soc/rockchip/rockchip_i2s_tdm.c - create mode 100644 sound/soc/rockchip/rockchip_i2s_tdm.h - -diff --git a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -new file mode 100644 -index 000000000000..e26e72e3315f ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -@@ -0,0 +1,42 @@ -+* Rockchip I2S/TDM controller -+ -+Required properties: -+ -+- compatible: should be one of the following -+ - "rockchip,rk3308-i2s-tdm": for rk3308 -+- reg: physical base address of the controller and length of memory mapped -+ region. -+- interrupts: should contain the I2S interrupt. -+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding, -+ Documentation/devicetree/bindings/dma/dma.txt -+- dma-names: should include "tx" and "rx". -+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. -+- clock-names: clock names. -+- rockchip,bclk-fs: configure the bclk fs. -+ -+Example for rk3308 I2S/TDM controller: -+ -+i2s_8ch_0: i2s@ff300000 { -+ compatible = "rockchip,rk3308-i2s-tdm"; -+ reg = <0x0 0xff300000 0x0 0x1000>; -+ interrupts = ; -+ clocks = <&cru SCLK_I2S0_8CH_TX>, <&cru SCLK_I2S0_8CH_RX>, <&cru HCLK_I2S0_8CH>; -+ clock-names = "mclk_tx", "mclk_rx", "hclk"; -+ dmas = <&dmac1 0>, <&dmac1 1>; -+ dma-names = "tx", "rx"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_8ch_0_sclktx -+ &i2s_8ch_0_sclkrx -+ &i2s_8ch_0_lrcktx -+ &i2s_8ch_0_lrckrx -+ &i2s_8ch_0_sdi0 -+ &i2s_8ch_0_sdi1 -+ &i2s_8ch_0_sdi2 -+ &i2s_8ch_0_sdi3 -+ &i2s_8ch_0_sdo0 -+ &i2s_8ch_0_sdo1 -+ &i2s_8ch_0_sdo2 -+ &i2s_8ch_0_sdo3 -+ &i2s_8ch_0_mclk>; -+ status = "disabled"; -+}; -diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig -index d610b553ea3b..25e26d85c2d1 100644 ---- a/sound/soc/rockchip/Kconfig -+++ b/sound/soc/rockchip/Kconfig -@@ -16,6 +16,15 @@ config SND_SOC_ROCKCHIP_I2S - Rockchip I2S device. The device supports upto maximum of - 8 channels each for play and record. - -+config SND_SOC_ROCKCHIP_I2S_TDM -+ tristate "Rockchip I2S/TDM Device Driver" -+ depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP -+ select SND_SOC_GENERIC_DMAENGINE_PCM -+ help -+ Say Y or M if you want to add support for I2S/TDM driver for -+ Rockchip I2S/TDM device. The device supports up to maximum of -+ 8 channels each for play and record. -+ - config SND_SOC_ROCKCHIP_PDM - tristate "Rockchip PDM Controller Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP -diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile -index 65e814d46006..b10f5e7b136d 100644 ---- a/sound/soc/rockchip/Makefile -+++ b/sound/soc/rockchip/Makefile -@@ -1,11 +1,13 @@ - # SPDX-License-Identifier: GPL-2.0 - # ROCKCHIP Platform Support - snd-soc-rockchip-i2s-objs := rockchip_i2s.o -+snd-soc-rockchip-i2s-tdm-objs := rockchip_i2s_tdm.o - snd-soc-rockchip-pcm-objs := rockchip_pcm.o - snd-soc-rockchip-pdm-objs := rockchip_pdm.o - snd-soc-rockchip-spdif-objs := rockchip_spdif.o - - obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o snd-soc-rockchip-pcm.o -+obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S_TDM) += snd-soc-rockchip-i2s-tdm.o - obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o - obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o - -diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c -new file mode 100644 -index 000000000000..39c1b98f9593 ---- /dev/null -+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c -@@ -0,0 +1,700 @@ -+/* sound/soc/rockchip/rockchip_i2s_tdm.c -+ * -+ * ALSA SoC Audio Layer - Rockchip I2S/TDM Controller driver -+ * -+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd. -+ * Author: Sugar Zhang -+ * -+ * 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 "rockchip_i2s_tdm.h" -+ -+#define DRV_NAME "rockchip-i2s-tdm" -+ -+struct rk_i2s_tdm_dev { -+ struct device *dev; -+ struct clk *hclk; -+ struct clk *mclk_tx; -+ struct clk *mclk_rx; -+ struct regmap *regmap; -+ struct snd_dmaengine_dai_dma_data capture_dma_data; -+ struct snd_dmaengine_dai_dma_data playback_dma_data; -+ -+ bool is_master_mode; -+ unsigned int bclk_fs; -+}; -+ -+static int i2s_tdm_runtime_suspend(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ -+ regcache_cache_only(i2s_tdm->regmap, true); -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_disable_unprepare(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_disable_unprepare(i2s_tdm->mclk_rx); -+ -+ return 0; -+} -+ -+static int i2s_tdm_runtime_resume(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ int ret; -+ -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_prepare_enable(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_prepare_enable(i2s_tdm->mclk_rx); -+ -+ regcache_cache_only(i2s_tdm->regmap, false); -+ regcache_mark_dirty(i2s_tdm->regmap); -+ -+ ret = regcache_sync(i2s_tdm->regmap); -+ if (ret) { -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_disable_unprepare(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_disable_unprepare(i2s_tdm->mclk_rx); -+ } -+ -+ return ret; -+} -+ -+static inline struct rk_i2s_tdm_dev *to_info(struct snd_soc_dai *dai) -+{ -+ return snd_soc_dai_get_drvdata(dai); -+} -+ -+static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) -+{ -+ unsigned int val = 0; -+ int retry = 10; -+ -+ if (on) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START, -+ I2S_XFER_TXS_START); -+ } else { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START, -+ I2S_XFER_TXS_STOP); -+ -+ udelay(150); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, -+ I2S_CLR_TXC, -+ I2S_CLR_TXC); -+ -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ -+ /* Should wait for clear operation to finish */ -+ while (val) { -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ retry--; -+ if (!retry) { -+ dev_warn(i2s_tdm->dev, "fail to clear\n"); -+ break; -+ } -+ } -+ } -+} -+ -+static void rockchip_snd_rxctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) -+{ -+ unsigned int val = 0; -+ int retry = 10; -+ -+ if (on) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_RXS_START, -+ I2S_XFER_RXS_START); -+ } else { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_RXS_START, -+ I2S_XFER_RXS_STOP); -+ -+ udelay(150); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, -+ I2S_CLR_RXC, -+ I2S_CLR_RXC); -+ -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ -+ /* Should wait for clear operation to finish */ -+ while (val) { -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ retry--; -+ if (!retry) { -+ dev_warn(i2s_tdm->dev, "fail to clear\n"); -+ break; -+ } -+ } -+ } -+} -+ -+static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai, -+ unsigned int fmt) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai); -+ unsigned int mask = 0, val = 0; -+ int ret = 0; -+ -+ pm_runtime_get_sync(cpu_dai->dev); -+ mask = I2S_CKR_MSS_MASK; -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* Set source clock in Master mode */ -+ val = I2S_CKR_MSS_MASTER; -+ i2s_tdm->is_master_mode = true; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ val = I2S_CKR_MSS_SLAVE; -+ i2s_tdm->is_master_mode = false; -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, mask, val); -+ -+ mask = I2S_CKR_CKP_MASK; -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ val = I2S_CKR_CKP_NEG; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ val = I2S_CKR_CKP_POS; -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, mask, val); -+ -+ mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK; -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_RIGHT_J: -+ val = I2S_TXCR_IBM_RSJM; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ val = I2S_TXCR_IBM_LSJM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ val = I2S_TXCR_IBM_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ -+ val = I2S_TXCR_TFS_PCM; -+ break; -+ case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ -+ val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1); -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, mask, val); -+ -+ mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK; -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_RIGHT_J: -+ val = I2S_RXCR_IBM_RSJM; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ val = I2S_RXCR_IBM_LSJM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ val = I2S_RXCR_IBM_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ -+ val = I2S_RXCR_TFS_PCM; -+ break; -+ case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ -+ val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1); -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val); -+ -+err_pm_put: -+ pm_runtime_put(cpu_dai->dev); -+ -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct clk *mclk; -+ unsigned int val = 0; -+ unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ mclk = i2s_tdm->mclk_tx; -+ else -+ mclk = i2s_tdm->mclk_rx; -+ -+ if (i2s_tdm->is_master_mode) { -+ mclk_rate = clk_get_rate(mclk); -+ bclk_rate = i2s_tdm->bclk_fs * params_rate(params); -+ if (!bclk_rate) -+ return -EINVAL; -+ -+ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); -+ div_lrck = bclk_rate / params_rate(params); -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, -+ I2S_CLKDIV_TXM_MASK, -+ I2S_CLKDIV_TXM(div_bclk)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_TSD_MASK, -+ I2S_CKR_TSD(div_lrck)); -+ } else { -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, -+ I2S_CLKDIV_RXM_MASK, -+ I2S_CLKDIV_RXM(div_bclk)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_RSD_MASK, -+ I2S_CKR_RSD(div_lrck)); -+ } -+ } -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S8: -+ val |= I2S_TXCR_VDW(8); -+ break; -+ case SNDRV_PCM_FORMAT_S16_LE: -+ val |= I2S_TXCR_VDW(16); -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ val |= I2S_TXCR_VDW(20); -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ val |= I2S_TXCR_VDW(24); -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ val |= I2S_TXCR_VDW(32); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 8: -+ val |= I2S_CHN_8; -+ break; -+ case 6: -+ val |= I2S_CHN_6; -+ break; -+ case 4: -+ val |= I2S_CHN_4; -+ break; -+ case 2: -+ val |= I2S_CHN_2; -+ break; -+ default: -+ dev_err(i2s_tdm->dev, "invalid channel: %d\n", -+ params_channels(params)); -+ return -EINVAL; -+ } -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, -+ I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK, -+ val); -+ else -+ regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, -+ I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK, -+ val); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, -+ I2S_DMACR_TDL(16)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, -+ I2S_DMACR_RDL(16)); -+ -+ val = I2S_CKR_TRCM_TXRX; -+ if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates) -+ val = I2S_CKR_TRCM_TXONLY; -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_TRCM_MASK, -+ val); -+ return 0; -+} -+ -+static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, -+ int cmd, struct snd_soc_dai *dai) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); -+ int ret = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ rockchip_snd_rxctrl(i2s_tdm, 1); -+ else -+ rockchip_snd_txctrl(i2s_tdm, 1); -+ break; -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ rockchip_snd_rxctrl(i2s_tdm, 0); -+ else -+ rockchip_snd_txctrl(i2s_tdm, 0); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, -+ unsigned int freq, int dir) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai); -+ int ret; -+ -+ ret = clk_set_rate(i2s_tdm->mclk_tx, freq); -+ if (ret) -+ dev_err(i2s_tdm->dev, "Fail to set mclk_tx %d\n", ret); -+ -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ ret = clk_set_rate(i2s_tdm->mclk_rx, freq); -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); -+ -+ dai->capture_dma_data = &i2s_tdm->capture_dma_data; -+ dai->playback_dma_data = &i2s_tdm->playback_dma_data; -+ -+ return 0; -+} -+ -+static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { -+ .hw_params = rockchip_i2s_tdm_hw_params, -+ .set_sysclk = rockchip_i2s_tdm_set_sysclk, -+ .set_fmt = rockchip_i2s_tdm_set_fmt, -+ .trigger = rockchip_i2s_tdm_trigger, -+}; -+ -+static struct snd_soc_dai_driver rockchip_i2s_tdm_dai = { -+ .probe = rockchip_i2s_tdm_dai_probe, -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "Capture", -+ .channels_min = 2, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rockchip_i2s_tdm_dai_ops, -+ .symmetric_rates = 1, -+}; -+ -+static const struct snd_soc_component_driver rockchip_i2s_tdm_component = { -+ .name = DRV_NAME, -+}; -+ -+static bool rockchip_i2s_tdm_wr_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_TXCR: -+ case I2S_RXCR: -+ case I2S_CKR: -+ case I2S_DMACR: -+ case I2S_INTCR: -+ case I2S_XFER: -+ case I2S_CLR: -+ case I2S_TXDR: -+ case I2S_TDM_TXCR: -+ case I2S_TDM_RXCR: -+ case I2S_CLKDIV: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_TXCR: -+ case I2S_RXCR: -+ case I2S_CKR: -+ case I2S_DMACR: -+ case I2S_INTCR: -+ case I2S_XFER: -+ case I2S_CLR: -+ case I2S_RXDR: -+ case I2S_FIFOLR: -+ case I2S_INTSR: -+ case I2S_TDM_TXCR: -+ case I2S_TDM_RXCR: -+ case I2S_CLKDIV: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_INTSR: -+ case I2S_CLR: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool rockchip_i2s_tdm_precious_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ default: -+ return false; -+ } -+} -+ -+static const struct reg_default rockchip_i2s_tdm_reg_defaults[] = { -+ {0x00, 0x7200000f}, -+ {0x04, 0x01c8000f}, -+ {0x08, 0x00001f1f}, -+ {0x10, 0x001f0000}, -+ {0x14, 0x01f00000}, -+ {0x30, 0x00003eff}, -+ {0x34, 0x00003eff}, -+ {0x38, 0x00000707}, -+}; -+ -+static const struct regmap_config rockchip_i2s_tdm_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = I2S_CLKDIV, -+ .reg_defaults = rockchip_i2s_tdm_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(rockchip_i2s_tdm_reg_defaults), -+ .writeable_reg = rockchip_i2s_tdm_wr_reg, -+ .readable_reg = rockchip_i2s_tdm_rd_reg, -+ .volatile_reg = rockchip_i2s_tdm_volatile_reg, -+ .precious_reg = rockchip_i2s_tdm_precious_reg, -+ .cache_type = REGCACHE_FLAT, -+}; -+ -+static const struct of_device_id rockchip_i2s_tdm_match[] = { -+ { .compatible = "rockchip,rk3308-i2s-tdm", }, -+ {}, -+}; -+ -+static int rockchip_i2s_tdm_probe(struct platform_device *pdev) -+{ -+ struct device_node *node = pdev->dev.of_node; -+ struct rk_i2s_tdm_dev *i2s_tdm; -+ struct resource *res; -+ void __iomem *regs; -+ int ret; -+ int val; -+ -+ i2s_tdm = devm_kzalloc(&pdev->dev, sizeof(*i2s_tdm), GFP_KERNEL); -+ if (!i2s_tdm) -+ return -ENOMEM; -+ -+ i2s_tdm->dev = &pdev->dev; -+ -+ i2s_tdm->hclk = devm_clk_get(&pdev->dev, "hclk"); -+ if (IS_ERR(i2s_tdm->hclk)) -+ return PTR_ERR(i2s_tdm->hclk); -+ -+ ret = clk_prepare_enable(i2s_tdm->hclk); -+ if (ret) -+ return ret; -+ -+ i2s_tdm->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx"); -+ if (IS_ERR(i2s_tdm->mclk_tx)) -+ return PTR_ERR(i2s_tdm->mclk_tx); -+ -+ i2s_tdm->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx"); -+ if (IS_ERR(i2s_tdm->mclk_rx)) -+ return PTR_ERR(i2s_tdm->mclk_rx); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(regs)) -+ return PTR_ERR(regs); -+ -+ i2s_tdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs, -+ &rockchip_i2s_tdm_regmap_config); -+ if (IS_ERR(i2s_tdm->regmap)) -+ return PTR_ERR(i2s_tdm->regmap); -+ -+ i2s_tdm->playback_dma_data.addr = res->start + I2S_TXDR; -+ i2s_tdm->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ i2s_tdm->playback_dma_data.maxburst = 8; -+ -+ i2s_tdm->capture_dma_data.addr = res->start + I2S_RXDR; -+ i2s_tdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ i2s_tdm->capture_dma_data.maxburst = 8; -+ -+ dev_set_drvdata(&pdev->dev, i2s_tdm); -+ -+ pm_runtime_enable(&pdev->dev); -+ if (!pm_runtime_enabled(&pdev->dev)) { -+ ret = i2s_tdm_runtime_resume(&pdev->dev); -+ if (ret) -+ goto err_pm_disable; -+ } -+ -+ i2s_tdm->bclk_fs = 64; -+ if (!of_property_read_u32(node, "rockchip,bclk-fs", &val)) { -+ if ((val >= 32) && (val % 2 == 0)) -+ i2s_tdm->bclk_fs = val; -+ } -+ -+ ret = devm_snd_soc_register_component(&pdev->dev, -+ &rockchip_i2s_tdm_component, -+ &rockchip_i2s_tdm_dai, 1); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register DAI\n"); -+ goto err_suspend; -+ } -+ -+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register PCM\n"); -+ return ret; -+ } -+ -+ return 0; -+ -+err_suspend: -+ if (!pm_runtime_status_suspended(&pdev->dev)) -+ i2s_tdm_runtime_suspend(&pdev->dev); -+err_pm_disable: -+ pm_runtime_disable(&pdev->dev); -+ -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_remove(struct platform_device *pdev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(&pdev->dev); -+ -+ pm_runtime_disable(&pdev->dev); -+ if (!pm_runtime_status_suspended(&pdev->dev)) -+ i2s_tdm_runtime_suspend(&pdev->dev); -+ -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_prepare_enable(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_prepare_enable(i2s_tdm->mclk_rx); -+ if (!IS_ERR(i2s_tdm->hclk)) -+ clk_disable_unprepare(i2s_tdm->hclk); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int rockchip_i2s_tdm_suspend(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ -+ regcache_mark_dirty(i2s_tdm->regmap); -+ -+ return 0; -+} -+ -+static int rockchip_i2s_tdm_resume(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ ret = regcache_sync(i2s_tdm->regmap); -+ pm_runtime_put(dev); -+ -+ return ret; -+} -+#endif -+ -+static const struct dev_pm_ops rockchip_i2s_tdm_pm_ops = { -+ SET_RUNTIME_PM_OPS(i2s_tdm_runtime_suspend, i2s_tdm_runtime_resume, -+ NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_tdm_suspend, -+ rockchip_i2s_tdm_resume) -+}; -+ -+static struct platform_driver rockchip_i2s_tdm_driver = { -+ .probe = rockchip_i2s_tdm_probe, -+ .remove = rockchip_i2s_tdm_remove, -+ .driver = { -+ .name = DRV_NAME, -+ .of_match_table = of_match_ptr(rockchip_i2s_tdm_match), -+ .pm = &rockchip_i2s_tdm_pm_ops, -+ }, -+}; -+module_platform_driver(rockchip_i2s_tdm_driver); -+ -+MODULE_DESCRIPTION("ROCKCHIP I2S/TDM ASoC Interface"); -+MODULE_AUTHOR("Sugar Zhang "); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:" DRV_NAME); -+MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match); -diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.h b/sound/soc/rockchip/rockchip_i2s_tdm.h -new file mode 100644 -index 000000000000..1a28523cfd82 ---- /dev/null -+++ b/sound/soc/rockchip/rockchip_i2s_tdm.h -@@ -0,0 +1,256 @@ -+/* -+ * sound/soc/rockchip/rockchip_i2s_tdm.h -+ * -+ * ALSA SoC Audio Layer - Rockchip I2S_TDM Controller driver -+ * -+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd. -+ * Author: Sugar Zhang -+ * -+ * 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 _ROCKCHIP_I2S_TDM_H -+#define _ROCKCHIP_I2S_TDM_H -+ -+/* -+ * TXCR -+ * transmit operation control register -+ */ -+#define I2S_TXCR_RCNT_SHIFT 17 -+#define I2S_TXCR_RCNT_MASK (0x3f << I2S_TXCR_RCNT_SHIFT) -+#define I2S_TXCR_CSR_SHIFT 15 -+#define I2S_TXCR_CSR(x) (x << I2S_TXCR_CSR_SHIFT) -+#define I2S_TXCR_CSR_MASK (3 << I2S_TXCR_CSR_SHIFT) -+#define I2S_TXCR_HWT BIT(14) -+#define I2S_TXCR_SJM_SHIFT 12 -+#define I2S_TXCR_SJM_R (0 << I2S_TXCR_SJM_SHIFT) -+#define I2S_TXCR_SJM_L (1 << I2S_TXCR_SJM_SHIFT) -+#define I2S_TXCR_FBM_SHIFT 11 -+#define I2S_TXCR_FBM_MSB (0 << I2S_TXCR_FBM_SHIFT) -+#define I2S_TXCR_FBM_LSB (1 << I2S_TXCR_FBM_SHIFT) -+#define I2S_TXCR_IBM_SHIFT 9 -+#define I2S_TXCR_IBM_NORMAL (0 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_IBM_LSJM (1 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_IBM_RSJM (2 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_IBM_MASK (3 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_PBM_SHIFT 7 -+#define I2S_TXCR_PBM_MODE(x) (x << I2S_TXCR_PBM_SHIFT) -+#define I2S_TXCR_PBM_MASK (3 << I2S_TXCR_PBM_SHIFT) -+#define I2S_TXCR_TFS_SHIFT 5 -+#define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_MASK (1 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_VDW_SHIFT 0 -+#define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) -+#define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) -+ -+/* -+ * RXCR -+ * receive operation control register -+ */ -+#define I2S_RXCR_CSR_SHIFT 15 -+#define I2S_RXCR_CSR(x) (x << I2S_RXCR_CSR_SHIFT) -+#define I2S_RXCR_CSR_MASK (3 << I2S_RXCR_CSR_SHIFT) -+#define I2S_RXCR_HWT BIT(14) -+#define I2S_RXCR_SJM_SHIFT 12 -+#define I2S_RXCR_SJM_R (0 << I2S_RXCR_SJM_SHIFT) -+#define I2S_RXCR_SJM_L (1 << I2S_RXCR_SJM_SHIFT) -+#define I2S_RXCR_FBM_SHIFT 11 -+#define I2S_RXCR_FBM_MSB (0 << I2S_RXCR_FBM_SHIFT) -+#define I2S_RXCR_FBM_LSB (1 << I2S_RXCR_FBM_SHIFT) -+#define I2S_RXCR_IBM_SHIFT 9 -+#define I2S_RXCR_IBM_NORMAL (0 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_IBM_LSJM (1 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_IBM_RSJM (2 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_IBM_MASK (3 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_PBM_SHIFT 7 -+#define I2S_RXCR_PBM_MODE(x) (x << I2S_RXCR_PBM_SHIFT) -+#define I2S_RXCR_PBM_MASK (3 << I2S_RXCR_PBM_SHIFT) -+#define I2S_RXCR_TFS_SHIFT 5 -+#define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_MASK (1 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_VDW_SHIFT 0 -+#define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) -+#define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) -+ -+/* -+ * CKR -+ * clock generation register -+ */ -+#define I2S_CKR_TRCM_SHIFT 28 -+#define I2S_CKR_TRCM(x) (x << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_TXRX (0 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_TXONLY (1 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_RXONLY (2 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_MASK (3 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_MSS_SHIFT 27 -+#define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT) -+#define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT) -+#define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT) -+#define I2S_CKR_CKP_SHIFT 26 -+#define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) -+#define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) -+#define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT) -+#define I2S_CKR_RLP_SHIFT 25 -+#define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) -+#define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) -+#define I2S_CKR_TLP_SHIFT 24 -+#define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT) -+#define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT) -+#define I2S_CKR_MDIV_SHIFT 16 -+#define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT) -+#define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT) -+#define I2S_CKR_RSD_SHIFT 8 -+#define I2S_CKR_RSD(x) ((x - 1) << I2S_CKR_RSD_SHIFT) -+#define I2S_CKR_RSD_MASK (0xff << I2S_CKR_RSD_SHIFT) -+#define I2S_CKR_TSD_SHIFT 0 -+#define I2S_CKR_TSD(x) ((x - 1) << I2S_CKR_TSD_SHIFT) -+#define I2S_CKR_TSD_MASK (0xff << I2S_CKR_TSD_SHIFT) -+ -+/* -+ * FIFOLR -+ * FIFO level register -+ */ -+#define I2S_FIFOLR_RFL_SHIFT 24 -+#define I2S_FIFOLR_RFL_MASK (0x3f << I2S_FIFOLR_RFL_SHIFT) -+#define I2S_FIFOLR_TFL3_SHIFT 18 -+#define I2S_FIFOLR_TFL3_MASK (0x3f << I2S_FIFOLR_TFL3_SHIFT) -+#define I2S_FIFOLR_TFL2_SHIFT 12 -+#define I2S_FIFOLR_TFL2_MASK (0x3f << I2S_FIFOLR_TFL2_SHIFT) -+#define I2S_FIFOLR_TFL1_SHIFT 6 -+#define I2S_FIFOLR_TFL1_MASK (0x3f << I2S_FIFOLR_TFL1_SHIFT) -+#define I2S_FIFOLR_TFL0_SHIFT 0 -+#define I2S_FIFOLR_TFL0_MASK (0x3f << I2S_FIFOLR_TFL0_SHIFT) -+ -+/* -+ * DMACR -+ * DMA control register -+ */ -+#define I2S_DMACR_RDE_SHIFT 24 -+#define I2S_DMACR_RDE_DISABLE (0 << I2S_DMACR_RDE_SHIFT) -+#define I2S_DMACR_RDE_ENABLE (1 << I2S_DMACR_RDE_SHIFT) -+#define I2S_DMACR_RDL_SHIFT 16 -+#define I2S_DMACR_RDL(x) ((x - 1) << I2S_DMACR_RDL_SHIFT) -+#define I2S_DMACR_RDL_MASK (0x1f << I2S_DMACR_RDL_SHIFT) -+#define I2S_DMACR_TDE_SHIFT 8 -+#define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT) -+#define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT) -+#define I2S_DMACR_TDL_SHIFT 0 -+#define I2S_DMACR_TDL(x) ((x) << I2S_DMACR_TDL_SHIFT) -+#define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT) -+ -+/* -+ * INTCR -+ * interrupt control register -+ */ -+#define I2S_INTCR_RFT_SHIFT 20 -+#define I2S_INTCR_RFT(x) ((x - 1) << I2S_INTCR_RFT_SHIFT) -+#define I2S_INTCR_RXOIC BIT(18) -+#define I2S_INTCR_RXOIE_SHIFT 17 -+#define I2S_INTCR_RXOIE_DISABLE (0 << I2S_INTCR_RXOIE_SHIFT) -+#define I2S_INTCR_RXOIE_ENABLE (1 << I2S_INTCR_RXOIE_SHIFT) -+#define I2S_INTCR_RXFIE_SHIFT 16 -+#define I2S_INTCR_RXFIE_DISABLE (0 << I2S_INTCR_RXFIE_SHIFT) -+#define I2S_INTCR_RXFIE_ENABLE (1 << I2S_INTCR_RXFIE_SHIFT) -+#define I2S_INTCR_TFT_SHIFT 4 -+#define I2S_INTCR_TFT(x) ((x - 1) << I2S_INTCR_TFT_SHIFT) -+#define I2S_INTCR_TFT_MASK (0x1f << I2S_INTCR_TFT_SHIFT) -+#define I2S_INTCR_TXUIC BIT(2) -+#define I2S_INTCR_TXUIE_SHIFT 1 -+#define I2S_INTCR_TXUIE_DISABLE (0 << I2S_INTCR_TXUIE_SHIFT) -+#define I2S_INTCR_TXUIE_ENABLE (1 << I2S_INTCR_TXUIE_SHIFT) -+ -+/* -+ * INTSR -+ * interrupt status register -+ */ -+#define I2S_INTSR_TXEIE_SHIFT 0 -+#define I2S_INTSR_TXEIE_DISABLE (0 << I2S_INTSR_TXEIE_SHIFT) -+#define I2S_INTSR_TXEIE_ENABLE (1 << I2S_INTSR_TXEIE_SHIFT) -+#define I2S_INTSR_RXOI_SHIFT 17 -+#define I2S_INTSR_RXOI_INA (0 << I2S_INTSR_RXOI_SHIFT) -+#define I2S_INTSR_RXOI_ACT (1 << I2S_INTSR_RXOI_SHIFT) -+#define I2S_INTSR_RXFI_SHIFT 16 -+#define I2S_INTSR_RXFI_INA (0 << I2S_INTSR_RXFI_SHIFT) -+#define I2S_INTSR_RXFI_ACT (1 << I2S_INTSR_RXFI_SHIFT) -+#define I2S_INTSR_TXUI_SHIFT 1 -+#define I2S_INTSR_TXUI_INA (0 << I2S_INTSR_TXUI_SHIFT) -+#define I2S_INTSR_TXUI_ACT (1 << I2S_INTSR_TXUI_SHIFT) -+#define I2S_INTSR_TXEI_SHIFT 0 -+#define I2S_INTSR_TXEI_INA (0 << I2S_INTSR_TXEI_SHIFT) -+#define I2S_INTSR_TXEI_ACT (1 << I2S_INTSR_TXEI_SHIFT) -+ -+/* -+ * XFER -+ * Transfer start register -+ */ -+#define I2S_XFER_RXS_SHIFT 1 -+#define I2S_XFER_RXS_STOP (0 << I2S_XFER_RXS_SHIFT) -+#define I2S_XFER_RXS_START (1 << I2S_XFER_RXS_SHIFT) -+#define I2S_XFER_TXS_SHIFT 0 -+#define I2S_XFER_TXS_STOP (0 << I2S_XFER_TXS_SHIFT) -+#define I2S_XFER_TXS_START (1 << I2S_XFER_TXS_SHIFT) -+ -+/* -+ * CLR -+ * clear SCLK domain logic register -+ */ -+#define I2S_CLR_RXC BIT(1) -+#define I2S_CLR_TXC BIT(0) -+ -+/* -+ * TXDR -+ * Transimt FIFO data register, write only. -+ */ -+#define I2S_TXDR_MASK (0xff) -+ -+/* -+ * RXDR -+ * Receive FIFO data register, write only. -+ */ -+#define I2S_RXDR_MASK (0xff) -+ -+/* -+ * CLKDIV -+ * Mclk div register -+ */ -+#define I2S_CLKDIV_TXM_SHIFT 0 -+#define I2S_CLKDIV_TXM(x) ((x - 1) << I2S_CLKDIV_TXM_SHIFT) -+#define I2S_CLKDIV_TXM_MASK (0xff << I2S_CLKDIV_TXM_SHIFT) -+#define I2S_CLKDIV_RXM_SHIFT 8 -+#define I2S_CLKDIV_RXM(x) ((x - 1) << I2S_CLKDIV_RXM_SHIFT) -+#define I2S_CLKDIV_RXM_MASK (0xff << I2S_CLKDIV_RXM_SHIFT) -+ -+/* Clock divider id */ -+enum { -+ ROCKCHIP_DIV_MCLK = 0, -+ ROCKCHIP_DIV_BCLK, -+}; -+ -+/* channel select */ -+#define I2S_CSR_SHIFT 15 -+#define I2S_CHN_2 (0 << I2S_CSR_SHIFT) -+#define I2S_CHN_4 (1 << I2S_CSR_SHIFT) -+#define I2S_CHN_6 (2 << I2S_CSR_SHIFT) -+#define I2S_CHN_8 (3 << I2S_CSR_SHIFT) -+ -+/* I2S REGS */ -+#define I2S_TXCR (0x0000) -+#define I2S_RXCR (0x0004) -+#define I2S_CKR (0x0008) -+#define I2S_FIFOLR (0x000c) -+#define I2S_DMACR (0x0010) -+#define I2S_INTCR (0x0014) -+#define I2S_INTSR (0x0018) -+#define I2S_XFER (0x001c) -+#define I2S_CLR (0x0020) -+#define I2S_TXDR (0x0024) -+#define I2S_RXDR (0x0028) -+#define I2S_TDM_TXCR (0x0030) -+#define I2S_TDM_RXCR (0x0034) -+#define I2S_CLKDIV (0x0038) -+ -+#endif /* _ROCKCHIP_I2S_TDM_H */ --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch b/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch deleted file mode 100644 index 1e280ec..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch +++ /dev/null @@ -1,2645 +0,0 @@ -From 76f98b4d0be07417ab9bc4a5669d185299f54cdf Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 17:09:38 +0100 -Subject: [PATCH 18/23] ASoC: codecs: Add RK3308 internal codec driver - -From b9d097610177b7117a09ea74ed00476a2105f169 Mon Sep 17 00:00:00 2001 -From: Xing Zheng -Date: Sun, 11 Mar 2018 11:37:28 +0800 -Subject: [PATCH] ASoC: codecs: Add RK3308 internal codec driver - -This adds support for the RK3308 audio codec. - -Change-Id: Ieccdebaa27f4a46f6de9406046a6e02e20398013 -Signed-off-by: Xing Zheng ---- - sound/soc/codecs/Kconfig | 5 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/rk3308_codec.c | 1604 +++++++++++++++++++++++++++++++ - sound/soc/codecs/rk3308_codec.h | 960 ++++++++++++++++++ - 4 files changed, 2571 insertions(+) - create mode 100644 sound/soc/codecs/rk3308_codec.c - create mode 100644 sound/soc/codecs/rk3308_codec.h - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 030f500f3bc8..1f4675a59014 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -144,6 +144,7 @@ config SND_SOC_ALL_CODECS - imply SND_SOC_PCM5102A - imply SND_SOC_PCM512x_I2C - imply SND_SOC_PCM512x_SPI -+ imply SND_SOC_RK3308 - imply SND_SOC_RK3328 - imply SND_SOC_RT274 - imply SND_SOC_RT286 -@@ -931,6 +932,10 @@ config SND_SOC_PCM512x_SPI - select SND_SOC_PCM512x - select REGMAP_SPI - -+config SND_SOC_RK3308 -+ select REGMAP_MMIO -+ tristate "Rockchip RK3308 CODEC" -+ - config SND_SOC_RK3328 - tristate "Rockchip RK3328 audio CODEC" - select REGMAP_MMIO -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index ddfd07071925..9a35df4862dc 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -148,6 +148,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-pcm512x-objs := pcm512x.o - snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o - snd-soc-pcm512x-spi-objs := pcm512x-spi.o -+snd-soc-rk3308-objs := rk3308_codec.o - snd-soc-rk3328-objs := rk3328_codec.o - snd-soc-rl6231-objs := rl6231.o - snd-soc-rl6347a-objs := rl6347a.o -@@ -437,6 +438,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o - obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o - obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o -+obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o - obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o - obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o - obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -new file mode 100644 -index 000000000000..106f09738dd0 ---- /dev/null -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -0,0 +1,1604 @@ -+/* -+ * rk3308_codec.c -- RK3308 ALSA Soc Audio Driver -+ * -+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "rk3308_codec.h" -+ -+struct rk3308_codec_priv { -+ const struct device *plat_dev; -+ struct device dev; -+ struct reset_control *reset; -+ struct regmap *regmap; -+ struct clk *pclk; -+ struct gpio_desc *spk_ctl_gpio; -+ int adc_ch; /* To select ADCs for channel */ -+ int adc_ch0_using_linein; -+}; -+ -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_gain_tlv, -+ -1800, 150, 2850); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_max_gain_tlv, -+ -1350, 600, 2850); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_min_gain_tlv, -+ -1800, 600, 2400); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_mic_gain_tlv, -+ 0, 600, 3000); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, -+ -1800, 150, 2850); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_gain_tlv, -+ 0, 150, 600); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, -+ -3900, 150, 600); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, -+ -600, 600, 0); -+ -+static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { -+ /* ALC AGC Channel*/ -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Volume", -+ RK3308_ALC_L_DIG_CON03(0), -+ RK3308_ALC_R_DIG_CON03(0), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Volume", -+ RK3308_ALC_L_DIG_CON03(1), -+ RK3308_ALC_R_DIG_CON03(1), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Volume", -+ RK3308_ALC_L_DIG_CON03(2), -+ RK3308_ALC_R_DIG_CON03(2), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Volume", -+ RK3308_ALC_L_DIG_CON03(3), -+ RK3308_ALC_R_DIG_CON03(3), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ -+ /* ALC AGC MAX */ -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Max Volume", -+ RK3308_ALC_L_DIG_CON09(0), -+ RK3308_ALC_R_DIG_CON09(0), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Max Volume", -+ RK3308_ALC_L_DIG_CON09(1), -+ RK3308_ALC_R_DIG_CON09(1), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Max Volume", -+ RK3308_ALC_L_DIG_CON09(2), -+ RK3308_ALC_R_DIG_CON09(2), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Max Volume", -+ RK3308_ALC_L_DIG_CON09(3), -+ RK3308_ALC_R_DIG_CON09(3), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ -+ /* ALC AGC MIN */ -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Min Volume", -+ RK3308_ALC_L_DIG_CON09(0), -+ RK3308_ALC_R_DIG_CON09(0), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Min Volume", -+ RK3308_ALC_L_DIG_CON09(1), -+ RK3308_ALC_R_DIG_CON09(1), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Min Volume", -+ RK3308_ALC_L_DIG_CON09(2), -+ RK3308_ALC_R_DIG_CON09(2), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Min Volume", -+ RK3308_ALC_L_DIG_CON09(3), -+ RK3308_ALC_R_DIG_CON09(3), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ -+ /* ADC MIC */ -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Left Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Right Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Left Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Right Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Left Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Right Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Left Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Right Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ -+ /* ADC ALC */ -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Left Volume", -+ RK3308_ADC_ANA_CON03(0), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Right Volume", -+ RK3308_ADC_ANA_CON04(0), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Left Volume", -+ RK3308_ADC_ANA_CON03(1), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Right Volume", -+ RK3308_ADC_ANA_CON04(1), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Left Volume", -+ RK3308_ADC_ANA_CON03(2), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Right Volume", -+ RK3308_ADC_ANA_CON04(2), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Left Volume", -+ RK3308_ADC_ANA_CON03(3), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Right Volume", -+ RK3308_ADC_ANA_CON04(3), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ -+ /* DAC */ -+ SOC_SINGLE_RANGE_TLV("DAC Left Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_GAIN_SFT, -+ RK3308_DAC_L_GAIN_0DB, -+ RK3308_DAC_L_GAIN_PDB_6, -+ 0, rk3308_codec_dac_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("DAC Right Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_R_GAIN_SFT, -+ RK3308_DAC_R_GAIN_0DB, -+ RK3308_DAC_R_GAIN_PDB_6, -+ 0, rk3308_codec_dac_gain_tlv), -+ -+ /* DAC HPOUT */ -+ SOC_SINGLE_RANGE_TLV("DAC HPOUT Left Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_SFT, -+ RK3308_DAC_L_HPOUT_GAIN_NDB_39, -+ RK3308_DAC_L_HPOUT_GAIN_PDB_6, -+ 0, rk3308_codec_dac_hpout_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("DAC HPOUT Right Volume", -+ RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_SFT, -+ RK3308_DAC_R_HPOUT_GAIN_NDB_39, -+ RK3308_DAC_R_HPOUT_GAIN_PDB_6, -+ 0, rk3308_codec_dac_hpout_gain_tlv), -+ -+ /* DAC HPMIX */ -+ SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPMIX_GAIN_SFT, -+ RK3308_DAC_L_HPMIX_GAIN_NDB_6, -+ RK3308_DAC_L_HPMIX_GAIN_0DB, -+ 0, rk3308_codec_dac_hpmix_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("DAC HPMIX Right Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_R_HPMIX_GAIN_SFT, -+ RK3308_DAC_R_HPMIX_GAIN_NDB_6, -+ RK3308_DAC_R_HPMIX_GAIN_0DB, -+ 0, rk3308_codec_dac_hpmix_gain_tlv), -+}; -+ -+static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) -+{ -+ gpiod_direction_output(rk3308->spk_ctl_gpio, on); -+} -+ -+static int rk3308_codec_reset(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ reset_control_assert(rk3308->reset); -+ usleep_range(200, 300); /* estimated value */ -+ reset_control_deassert(rk3308->reset); -+ -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); -+ usleep_range(200, 300); /* estimated value */ -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_SYS_WORK | -+ RK3308_DAC_DIG_WORK | -+ RK3308_ADC_DIG_WORK); -+ -+ return 0; -+} -+ -+static int rk3308_set_bias_level(struct snd_soc_codec *codec, -+ 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: -+ case SND_SOC_BIAS_OFF: -+ break; -+ } -+ -+ snd_soc_codec_force_bias_level(codec, level); -+ -+ return 0; -+} -+ -+static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -+ unsigned int fmt) -+{ -+ struct snd_soc_codec *codec = codec_dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -+ int ch = rk3308->adc_ch; -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; -+ adc_aif2 |= RK3308_ADC_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_MODE_SLAVE; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; -+ adc_aif2 |= RK3308_ADC_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_MODE_MASTER; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_DSP_A: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -+ RK3308_ADC_I2S_LRC_POL_MSK | -+ RK3308_ADC_I2S_MODE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -+ RK3308_ADC_IO_MODE_MSK | -+ RK3308_ADC_MODE_MSK | -+ RK3308_ADC_I2S_BIT_CLK_POL_MSK, -+ adc_aif2); -+ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_LRC_POL_MSK | -+ RK3308_DAC_I2S_MODE_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_IO_MODE_MSK | -+ RK3308_DAC_MODE_MSK | -+ RK3308_DAC_I2S_BIT_CLK_POL_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -+ int ch = rk3308->adc_ch; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 1: -+ adc_aif1 |= RK3308_ADC_I2S_MONO; -+ break; -+ case 2: -+ adc_aif1 |= RK3308_ADC_I2S_STEREO; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_WORK; -+ dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_WORK; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -+ RK3308_ADC_I2S_VALID_LEN_MSK | -+ RK3308_ADC_I2S_LR_MSK | -+ RK3308_ADC_I2S_TYPE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -+ RK3308_ADC_I2S_MSK, -+ adc_aif2); -+ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_VALID_LEN_MSK | -+ RK3308_DAC_I2S_LR_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_I2S_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_digital_mute(struct snd_soc_dai *dai, int mute) -+{ -+ return 0; -+} -+ -+static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 01 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_MSK, -+ RK3308_DAC_CURRENT_EN); -+ -+ /* Step 02 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_MSK | -+ RK3308_DAC_BUF_REF_R_MSK, -+ RK3308_DAC_BUF_REF_L_EN | -+ RK3308_DAC_BUF_REF_R_EN); -+ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_L_MSK | -+ RK3308_DAC_POP_SOUND_R_MSK, -+ RK3308_DAC_POP_SOUND_L_WORK | -+ RK3308_DAC_POP_SOUND_R_WORK); -+ -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN); -+ -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK); -+ -+ /* Step 06 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN); -+ -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN); -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_I2S | -+ RK3308_DAC_R_HPMIX_I2S); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE); -+ -+ /* Step 15 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_GAIN_MSK | -+ RK3308_DAC_R_HPMIX_GAIN_MSK, -+ RK3308_DAC_L_HPMIX_GAIN_0DB | -+ RK3308_DAC_R_HPMIX_GAIN_0DB); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE); -+ -+ /* Step 17 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ RK3308_DAC_L_HPOUT_GAIN_0DB); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ RK3308_DAC_R_HPOUT_GAIN_0DB); -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -+ RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 01 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -+ RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -+ -+ /* -+ * Step 02 -+ * -+ * Note1. In the step2, adjusting the register step by step to the -+ * appropriate value and taking 20ms as time step -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ RK3308_DAC_L_HPOUT_GAIN_NDB_39); -+ -+ /* Step 02 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ RK3308_DAC_R_HPOUT_GAIN_NDB_39); -+ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_MUTE | -+ RK3308_DAC_R_HPMIX_MUTE); -+ -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_NONE | -+ RK3308_DAC_R_HPMIX_NONE); -+ -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_MUTE | -+ RK3308_DAC_R_HPOUT_MUTE); -+ -+ /* Step 06 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_INIT | RK3308_DAC_R_DAC_INIT); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_DIS | RK3308_DAC_R_HPOUT_DIS); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_MUTE | -+ RK3308_DAC_R_LINEOUT_MUTE); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_DIS | RK3308_DAC_R_LINEOUT_DIS); -+ -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_DIS | RK3308_DAC_R_HPMIX_DIS); -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_DIS | RK3308_DAC_R_DAC_DIS); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_DIS | RK3308_DAC_R_CLK_DIS); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_DIS | RK3308_DAC_R_REF_DIS); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_L_MSK | -+ RK3308_DAC_POP_SOUND_R_MSK, -+ RK3308_DAC_POP_SOUND_L_INIT | -+ RK3308_DAC_POP_SOUND_R_INIT); -+ -+ /* Step 15 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_EN | RK3308_DAC_BUF_REF_R_EN, -+ RK3308_DAC_BUF_REF_L_DIS | RK3308_DAC_BUF_REF_R_DIS); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_EN, -+ RK3308_DAC_CURRENT_DIS); -+ -+ /* Step 17 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_INIT | RK3308_DAC_R_HPOUT_INIT); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_INIT | RK3308_DAC_R_HPMIX_INIT); -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_GAIN_MSK | -+ RK3308_DAC_R_HPMIX_GAIN_MSK, -+ RK3308_DAC_L_HPMIX_GAIN_NDB_6 | -+ RK3308_DAC_R_HPMIX_GAIN_NDB_6); -+ -+ /* -+ * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -+ * is set to 0x1, add the steps from the section Disable DAC -+ * Configuration Standard Usage Flow after complete the step 19 -+ */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_on(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ /* 1. Supply the power of digital part and reset the Audio Codec */ -+ /* Do nothing */ -+ -+ /* -+ * 2. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] -+ * to 0x1, to setup dc voltage of the DAC channel output -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_L_MSK, RK3308_DAC_POP_SOUND_L_INIT); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_R_MSK, RK3308_DAC_POP_SOUND_R_INIT); -+ -+ /* -+ * 3. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 -+ * -+ * Note: Only the reg (ADC_ANA_CON10+0x0)[6:0] represent the control -+ * signal to select current to pre-charge/dis_charge -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ -+ /* 4. Supply the power of the analog part(AVDD,AVDDRV) */ -+ -+ /* -+ * 5. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup -+ * reference voltage -+ * -+ * Note: Only the reg (ADC_ANA_CON10+0x0)[7] represent the enable -+ * signal of reference voltage module -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); -+ -+ /* -+ * 6. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to -+ * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to -+ * 0x7f directly. The suggestion slot time of the step is 20ms. -+ */ -+ mdelay(20); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_DONT_SEL_ALL); -+ -+ /* 7. Wait until the voltage of VCM keeps stable at the AVDD/2 */ -+ usleep_range(200, 300); /* estimated value */ -+ -+ /* -+ * 8. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the -+ * appropriate value(expect 0x0) for reducing power. -+ */ -+ -+ /* TODO: choose an appropriate charge value */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_off(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ /* -+ * 1. Keep the power on and disable the DAC and ADC path according to -+ * the section power on configuration standard usage flow. -+ */ -+ -+ /* 2. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ -+ /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, RK3308_ADC_REF_DIS); -+ -+ /* -+ * 4.Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f -+ * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f -+ * directly. The suggestion slot time of the step is 20ms -+ */ -+ mdelay(20); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_DONT_SEL_ALL); -+ -+ /* 5. Wait until the voltage of VCM keeps stable at the AGND */ -+ usleep_range(200, 300); /* estimated value */ -+ -+ /* 6. Power off the analog power supply */ -+ /* 7. Power off the digital power supply */ -+ -+ /* Do something via hardware */ -+ -+ return 0; -+} -+ -+static int check_micbias(int micbias) -+{ -+ switch (micbias) { -+ case RK3308_ADC_MICBIAS_VOLT_0_85: -+ case RK3308_ADC_MICBIAS_VOLT_0_8: -+ case RK3308_ADC_MICBIAS_VOLT_0_75: -+ case RK3308_ADC_MICBIAS_VOLT_0_7: -+ case RK3308_ADC_MICBIAS_VOLT_0_65: -+ case RK3308_ADC_MICBIAS_VOLT_0_6: -+ case RK3308_ADC_MICBIAS_VOLT_0_55: -+ case RK3308_ADC_MICBIAS_VOLT_0_5: -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -+ int micbias) -+{ -+ int ch = rk3308->adc_ch; -+ int ret; -+ -+ if (ch != 1 && ch != 2) { -+ dev_err(rk3308->plat_dev, -+ "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -+ __func__, ch); -+ return -EINVAL; -+ } -+ -+ /* 1. Power up the ACODEC and keep the AVDDH stable */ -+ -+ /* 2. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ -+ ret = check_micbias(micbias); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", -+ micbias); -+ return ret; -+ } -+ -+ /* -+ * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range -+ * control signal of MICBIAS voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -+ micbias); -+ -+ /* 3. Wait until the VCMH keep stable */ -+ usleep_range(200, 300); /* estimated value */ -+ -+ /* 4. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_EN); -+ -+ /* -+ * 5. Configure the (ADC_ANA_CON7+0x40)[3] or (ADC_ANA_CON7+0x80)[3] -+ * to 0x1. -+ * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and -+ * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 -+ */ -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_EN); -+ -+ return 0; -+} -+ -+static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ if (ch != 1 && ch != 2) { -+ dev_err(rk3308->plat_dev, -+ "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -+ __func__, ch); -+ return -EINVAL; -+ } -+ -+ /* 1. Enable the MICBIAS and keep the Audio Codec stable */ -+ /* Do nothing */ -+ -+ /* -+ * 2. Configure the (ADC_ANA_CON7+0x40)[3] or -+ * (ADC_ANA_CON7+0x80)[3] to 0x0 -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_DIS); -+ -+ /* 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set he max level and min level of the ALC need to control. -+ * -+ * These values are estimated -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -+ RK3308_AGC_LO_8BITS_AGC_MIN_MSK, -+ 0x16); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -+ RK3308_AGC_HI_8BITS_AGC_MIN_MSK, -+ 0x40); -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -+ RK3308_AGC_LO_8BITS_AGC_MAX_MSK, -+ 0x26); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -+ RK3308_AGC_HI_8BITS_AGC_MAX_MSK, -+ 0x40); -+ -+ /* -+ * 2. Set ACODEC_ALC_DIG_CON4[2:0] according to the sample rate -+ * -+ * By default is 44.1KHz for sample. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(ch), -+ RK3308_AGC_APPROX_RATE_MSK, -+ RK3308_AGC_APPROX_RATE_44_1K); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(ch), -+ RK3308_AGC_APPROX_RATE_MSK, -+ RK3308_AGC_APPROX_RATE_44_1K); -+ -+ /* 3. Set ACODEC_ALC_DIG_CON9[6] to 0x1, to enable the ALC module */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ -+ /* -+ * 4. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -+ * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -+ * to 0x3, to enable the ALC module to control the gain of PGA. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_EN | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); -+ -+ /* -+ * 5.Observe the current ALC output gain by reading -+ * ACODEC_ALC_DIG_CON12[4:0] -+ * -+ * The default GAIN is 0x0c -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON12(ch), -+ RK3308_AGC_GAIN_MSK, -+ 0x0c); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON12(ch), -+ RK3308_AGC_GAIN_MSK, -+ 0x0c); -+ -+ return 0; -+} -+ -+static int rk3308_codec_alc_disable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set ACODEC_ALC_DIG_CON9[6] to 0x0, to disable the ALC module, -+ * then the ALC output gain will keep to the last value -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -+ * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -+ * to 0x0, to disable the ALC module to control the gain of PGA. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int adc_aif1 = 0, adc_aif2 = 0; -+ unsigned int agc_func_en; -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], -+ * to select the line-in or microphone as input of ADC -+ * -+ * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, -+ * ADC6, ADC7, and ADC8 -+ */ -+ if (ch == 0) { -+ if (rk3308->adc_ch0_using_linein) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH1_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_LINEIN); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH2_IN_LINEIN); -+ } else { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH1_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_MIC); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH2_IN_MIC); -+ } -+ } -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON0[7:0] to 0xff, to end the mute station -+ * of ADC, to enable the MIC module, to enable the reference voltage -+ * buffer, and to end the initialization of MIC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -+ RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -+ RK3308_ADC_CH1_CH2_MIC_ALL); -+ -+ /* -+ * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source -+ * of audio -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_EN); -+ -+ /* -+ * 4. Set ACODEC_ADC_ANA_CON2[7:0] to 0x77, to enable the ALC module, -+ * to enable the zero-crossing detection function, and to end the -+ * initialization of ALC -+ * -+ * Note2. Please set ACODEC_ADC_ANA_CON2[7:0] to 0x33 in step4 -+ * if the AGC function is closed -+ */ -+ -+ adc_aif1 = RK3308_ADC_CH1_ALC_EN | RK3308_ADC_CH1_ALC_WORK; -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -+ if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -+ adc_aif1 |= RK3308_ADC_CH1_ZEROCROSS_DET_EN; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH1_ALC_ZC_MSK, -+ adc_aif1); -+ -+ adc_aif2 = RK3308_ADC_CH2_ALC_EN | RK3308_ADC_CH2_ALC_WORK; -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -+ if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -+ adc_aif2 |= RK3308_ADC_CH2_ZEROCROSS_DET_EN; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH2_ALC_ZC_MSK, -+ adc_aif2); -+ -+ /* -+ * 5. Set ACODEC_ADC_ANA_CON5[7:0] to 0x77, to enable the clock and -+ * ADC module, and to end the initialization of ADC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH1_ADC_CLK_MSK, -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH1_ADC_WORK); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH2_ADC_CLK_MSK, -+ RK3308_ADC_CH2_CLK_EN | -+ RK3308_ADC_CH2_ADC_EN | -+ RK3308_ADC_CH2_ADC_WORK); -+ -+ /* -+ * 6. Set ACODEC_ADC_ANA_CON1[5:4] and ACODEC_ADC_ANA_CON1[1:0], -+ * to select the gain of the MIC -+ * -+ * By default is 0db. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH1_MIC_GAIN_MSK, -+ RK3308_ADC_CH1_MIC_GAIN_0DB); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH2_MIC_GAIN_MSK, -+ RK3308_ADC_CH2_MIC_GAIN_0DB); -+ -+ /* -+ * 7.Set ACODEC_ADC_ANA_CON3[4:0] and ACODEC_ADC_ANA_CON4[3:0] to -+ * select the gain of ALC -+ * -+ * By default is 0db. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(ch), -+ RK3308_ADC_CH1_ALC_GAIN_MSK, -+ RK3308_ADC_CH1_ALC_GAIN_0DB); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(ch), -+ RK3308_ADC_CH2_ALC_GAIN_MSK, -+ RK3308_ADC_CH2_ALC_GAIN_0DB); -+ -+ /* 8.Begin recording */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set ACODEC_ADC_ANA_CON2[7:0] to 0x0, to disable the ALC module, -+ * to disable the zero-crossing detection function, and to begin the -+ * initialization of ALC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH1_ALC_ZC_MSK, -+ 0); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH2_ALC_ZC_MSK, -+ 0); -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON5[7:0] to 0x0, to disable the clock and -+ * ADC module, and to begin the initialization of ADC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH1_ADC_CLK_MSK, -+ 0); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH2_ADC_CLK_MSK, -+ 0); -+ -+ /* -+ * 3. Set ACODEC_ADC_ANA_CON0[7:0] to 0x88, to disable the MIC module, -+ * to disable the reference voltage buffer, and to begin the -+ * initialization of MIC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -+ RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -+ RK3308_ADC_CH1_MIC_UNMUTE | -+ RK3308_ADC_CH2_MIC_UNMUTE); -+ -+ /* -+ * 4. Set ACODEC_ADC_ANA_CON6[0] to 0x0, to disable the current -+ * source of audio -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_capture(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_alc_enable(rk3308); -+ rk3308_codec_adc_ana_enable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_capture(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_alc_disable(rk3308); -+ rk3308_codec_adc_ana_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_playback(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_dac_enable(rk3308); -+ rk3308_speaker_ctl(rk3308, 1); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_playback(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_speaker_ctl(rk3308, 0); -+ rk3308_codec_dac_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_pcm_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ int ret = 0; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ ret = rk3308_codec_open_playback(codec); -+ else -+ ret = rk3308_codec_open_capture(codec); -+ -+ return ret; -+} -+ -+static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ rk3308_codec_close_playback(codec); -+ else -+ rk3308_codec_close_capture(codec); -+} -+ -+static struct snd_soc_dai_ops rk3308_dai_ops = { -+ .hw_params = rk3308_hw_params, -+ .set_fmt = rk3308_set_dai_fmt, -+ .digital_mute = rk3308_digital_mute, -+ .startup = rk3308_pcm_startup, -+ .shutdown = rk3308_pcm_shutdown, -+}; -+ -+static struct snd_soc_dai_driver rk3308_dai[] = { -+ { -+ .name = "rk3308-hifi", -+ .id = RK3308_HIFI, -+ .playback = { -+ .stream_name = "HiFi Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_96000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "HiFi Capture", -+ .channels_min = 1, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_96000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rk3308_dai_ops, -+ }, -+}; -+ -+static int rk3308_suspend(struct snd_soc_codec *codec) -+{ -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ -+ return 0; -+} -+ -+static int rk3308_resume(struct snd_soc_codec *codec) -+{ -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ -+ return 0; -+} -+ -+static int rk3308_probe(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_reset(codec); -+ rk3308_codec_power_on(codec); -+ -+ rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_7); -+ -+ return 0; -+} -+ -+static int rk3308_remove(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_speaker_ctl(rk3308, 0); -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308_codec_power_off(codec); -+ -+ return 0; -+} -+ -+static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -+ .probe = rk3308_probe, -+ .remove = rk3308_remove, -+ .suspend = rk3308_suspend, -+ .resume = rk3308_resume, -+ .set_bias_level = rk3308_set_bias_level, -+ .controls = rk3308_codec_dapm_controls, -+ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+}; -+ -+static const struct reg_default rk3308_codec_reg_defaults[] = { -+ { RK3308_GLB_CON, 0x07 }, -+}; -+ -+static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) -+{ -+ /* All registers can be read / write */ -+ return true; -+} -+ -+static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case RK3308_GLB_CON: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static const struct regmap_config rk3308_codec_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = RK3308_DAC_ANA_CON13, -+ .writeable_reg = rk3308_codec_write_read_reg, -+ .readable_reg = rk3308_codec_write_read_reg, -+ .volatile_reg = rk3308_codec_volatile_reg, -+ .reg_defaults = rk3308_codec_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), -+ .cache_type = REGCACHE_FLAT, -+}; -+ -+static ssize_t adc_ch_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ -+ return sprintf(buf, "adc_ch: %d\n", rk3308->adc_ch); -+} -+ -+static ssize_t adc_ch_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long ch; -+ int ret = kstrtoul(buf, 10, &ch); -+ -+ if (ret < 0 || ch > 4) { -+ dev_err(dev, "Invalid ch: %ld, ret: %d\n", ch, ret); -+ return -EINVAL; -+ } -+ -+ rk3308->adc_ch = ch; -+ -+ dev_info(dev, "Store ch: %d\n", rk3308->adc_ch); -+ -+ return count; -+} -+ -+static const struct device_attribute adc_ch_attrs[] = { -+ __ATTR(adc_ch, 0644, adc_ch_show, adc_ch_store), -+}; -+ -+static void rk3308_codec_device_release(struct device *dev) -+{ -+ /* Do nothing */ -+} -+ -+static int rk3308_codec_sysfs_init(struct platform_device *pdev, -+ struct rk3308_codec_priv *rk3308) -+{ -+ struct device *dev = &rk3308->dev; -+ int i; -+ -+ dev->release = rk3308_codec_device_release; -+ dev->parent = &pdev->dev; -+ set_dev_node(dev, dev_to_node(&pdev->dev)); -+ dev_set_name(dev, "rk3308-acodec-dev"); -+ -+ if (device_register(dev)) { -+ dev_err(&pdev->dev, -+ "Register 'rk3308-acodec-dev' failed\n"); -+ dev->parent = NULL; -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(adc_ch_attrs); i++) { -+ if (device_create_file(dev, &adc_ch_attrs[i])) { -+ dev_err(&pdev->dev, -+ "Create 'rk3308-acodec-dev' attr failed\n"); -+ device_unregister(dev); -+ return -ENOMEM; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_platform_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct rk3308_codec_priv *rk3308; -+ struct resource *res; -+ void __iomem *base; -+ int ret = 0; -+ struct regmap *grf; -+ -+ grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); -+ if (IS_ERR(grf)) { -+ dev_err(&pdev->dev, -+ "Missing 'rockchip,grf' property\n"); -+ return PTR_ERR(grf); -+ } -+ -+ rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); -+ if (!rk3308) -+ return -ENOMEM; -+ -+ ret = rk3308_codec_sysfs_init(pdev, rk3308); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Sysfs init failed\n"); -+ return ret; -+ } -+ -+ rk3308->plat_dev = &pdev->dev; -+ -+ rk3308->reset = devm_reset_control_get(&pdev->dev, "acodec-reset"); -+ if (IS_ERR(rk3308->reset)) { -+ ret = PTR_ERR(rk3308->reset); -+ if (ret != -ENOENT) -+ return ret; -+ -+ dev_dbg(&pdev->dev, "No reset control found\n"); -+ rk3308->reset = NULL; -+ } -+ -+ /* GPIO0_A5 control speaker on RK3308 EVB */ -+ rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk_ctl", -+ GPIOD_OUT_HIGH); -+ if (IS_ERR(rk3308->spk_ctl_gpio)) { -+ ret = PTR_ERR(rk3308->spk_ctl_gpio); -+ dev_err(&pdev->dev, "Unable to claim gpio spk_ctl\n"); -+ return ret; -+ } -+ -+ rk3308->pclk = devm_clk_get(&pdev->dev, "acodec"); -+ if (IS_ERR(rk3308->pclk)) { -+ dev_err(&pdev->dev, "Can't get acodec pclk\n"); -+ return PTR_ERR(rk3308->pclk); -+ } -+ -+ ret = clk_prepare_enable(rk3308->pclk); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret); -+ return ret; -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) { -+ ret = PTR_ERR(base); -+ dev_err(&pdev->dev, "Failed to ioremap resource\n"); -+ goto failed; -+ } -+ -+ rk3308->regmap = devm_regmap_init_mmio(&pdev->dev, base, -+ &rk3308_codec_regmap_config); -+ if (IS_ERR(rk3308->regmap)) { -+ ret = PTR_ERR(rk3308->regmap); -+ dev_err(&pdev->dev, "Failed to regmap mmio\n"); -+ goto failed; -+ } -+ -+ platform_set_drvdata(pdev, rk3308); -+ -+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3308, -+ rk3308_dai, ARRAY_SIZE(rk3308_dai)); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); -+ goto failed; -+ } -+ -+ return ret; -+ -+failed: -+ clk_disable_unprepare(rk3308->pclk); -+ -+ return ret; -+} -+ -+static int rk3308_platform_remove(struct platform_device *pdev) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ (struct rk3308_codec_priv *)platform_get_drvdata(pdev); -+ -+ clk_disable_unprepare(rk3308->pclk); -+ snd_soc_unregister_codec(&pdev->dev); -+ -+ return 0; -+} -+ -+static const struct of_device_id rk3308codec_of_match[] = { -+ { .compatible = "rockchip,rk3308-codec", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rk3308codec_of_match); -+ -+static struct platform_driver rk3308_codec_driver = { -+ .driver = { -+ .name = "rk3308-acodec", -+ .of_match_table = of_match_ptr(rk3308codec_of_match), -+ }, -+ .probe = rk3308_platform_probe, -+ .remove = rk3308_platform_remove, -+}; -+module_platform_driver(rk3308_codec_driver); -+ -+MODULE_AUTHOR("Xing Zheng "); -+MODULE_DESCRIPTION("ASoC RK3308 Codec Driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h -new file mode 100644 -index 000000000000..6cfa69157785 ---- /dev/null -+++ b/sound/soc/codecs/rk3308_codec.h -@@ -0,0 +1,960 @@ -+/* -+ * rk3308_codec.h -- RK3308 ALSA Soc Audio Driver -+ * -+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#ifndef __RK3308_CODEC_H__ -+#define __RK3308_CODEC_H__ -+ -+#define ACODEC_RESET_CTL 0x00 /* REG 0x00 */ -+ -+/* ADC DIGITAL REGISTERS */ -+#define ACODEC_ADC_I2S_CTL0 0x04 /* REG 0x01 */ -+#define ACODEC_ADC_I2S_CTL1 0x08 /* REG 0x02 */ -+#define ACODEC_ADC_BIST_MODE_SEL 0x0c /* REG 0x03 */ -+/* Resevred REG 0x04 ~ 0x06 */ -+#define ACODEC_ADC_DATA_PATH 0x1c /* REG 0x07 */ -+/* Resevred REG 0x08 ~ 0x0f */ -+ -+/* REG 0x10 ~ 0x1c are used to configure AGC of Left channel (ALC1) */ -+#define ACODEC_ADC_PGA_AGC_L_CTL0 0x40 /* REG 0x10 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL1 0x44 /* REG 0x11 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL2 0x48 /* REG 0x12 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL3 0x4c /* REG 0x13 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL4 0x50 /* REG 0x14 */ -+#define ACODEC_ADC_PGA_AGC_L_LO_MAX 0x54 /* REG 0x15 */ -+#define ACODEC_ADC_PGA_AGC_L_HI_MAX 0x58 /* REG 0x16 */ -+#define ACODEC_ADC_PGA_AGC_L_LO_MIN 0x5c /* REG 0x17 */ -+#define ACODEC_ADC_PGA_AGC_L_HI_MIN 0x60 /* REG 0x18 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL5 0x64 /* REG 0x19 */ -+/* Resevred REG 0x1a ~ 0x1b */ -+#define ACODEC_ADC_AGC_L_RO_GAIN 0x70 /* REG 0x1c */ -+ -+/* REG 0x20 ~ 0x2c are used to configure AGC of Right channel (ALC2) */ -+#define ACODEC_ADC_PGA_AGC_R_CTL0 0x80 /* REG 0x20 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL1 0x84 /* REG 0x21 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL2 0x88 /* REG 0x22 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL3 0x8c /* REG 0x23 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL4 0x90 /* REG 0x24 */ -+#define ACODEC_ADC_PGA_AGC_R_LO_MAX 0x94 /* REG 0x25 */ -+#define ACODEC_ADC_PGA_AGC_R_HI_MAX 0x98 /* REG 0x26 */ -+#define ACODEC_ADC_PGA_AGC_R_LO_MIN 0x9c /* REG 0x27 */ -+#define ACODEC_ADC_PGA_AGC_R_HI_MIN 0xa0 /* REG 0x28 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL5 0xa4 /* REG 0x29 */ -+/* Resevred REG 0x2a ~ 0x2b */ -+#define ACODEC_ADC_AGC_R_RO_GAIN 0xb0 /* REG 0x2c */ -+ -+/* DAC DIGITAL REGISTERS */ -+#define ACODEC_DAC_I2S_CTL0 0x04 /* REG 0x01 */ -+#define ACODEC_DAC_I2S_CTL1 0x08 /* REG 0x02 */ -+#define ACODEC_DAC_BIST_MODE_SEL 0x0c /* REG 0x03 */ -+/* Resevred REG 0x04 */ -+#define ACODEC_DAC_DATA_SEL 0x14 /* REG 0x05 */ -+/* Resevred REG 0x06 ~ 0x09 */ -+#define ACODEC_DAC_DATA_HI 0x28 /* REG 0x0a */ -+#define ACODEC_DAC_DATA_LO 0x2c /* REG 0x0b */ -+/* Resevred REG 0x0c ~ 0x0f */ -+ -+/* ADC ANALOG REGISTERS */ -+#define ACODEC_ADC_ANA_MIC_CTL 0x00 /* REG 0x00 */ -+#define ACODEC_ADC_ANA_MIC_GAIN 0x04 /* REG 0x01 */ -+#define ACODEC_ADC_ANA_ALC_CTL 0x08 /* REG 0x02 */ -+#define ACODEC_ADC_ANA_ALC_GAIN1 0x0c /* REG 0x03 */ -+#define ACODEC_ADC_ANA_ALC_GAIN2 0x10 /* REG 0x04 */ -+#define ACODEC_ADC_ANA_CTL0 0x14 /* REG 0x05 */ -+#define ACODEC_ADC_ANA_CTL1 0x18 /* REG 0x06 */ -+#define ACODEC_ADC_ANA_CTL2 0x1c /* REG 0x07 */ -+#define ACODEC_ADC_ANA_CTL3 0x20 /* REG 0x08 */ -+/* Resevred REG 0x09 */ -+#define ACODEC_ADC_ANA_CTL4 0x28 /* REG 0x0a */ -+#define ACODEC_ADC_ANA_ALC_PGA 0x2c /* REG 0x0b */ -+/* Resevred REG 0x0c ~ 0x0f */ -+ -+/* DAC ANALOG REGISTERS */ -+#define ACODEC_DAC_ANA_CTL0 0x00 /* REG 0x00 */ -+#define ACODEC_DAC_ANA_POP_VOLT 0x04 /* REG 0x01 */ -+#define ACODEC_DAC_ANA_CTL1 0x08 /* REG 0x02 */ -+#define ACODEC_DAC_ANA_HPOUT 0x0c /* REG 0x03 */ -+#define ACODEC_DAC_ANA_LINEOUT 0x10 /* REG 0x04 */ -+#define ACODEC_DAC_ANA_L_HPOUT_GAIN 0x14 /* REG 0x05 */ -+#define ACODEC_DAC_ANA_R_HPOUT_GAIN 0x18 /* REG 0x06 */ -+/* Resevred REG 0x07 ~ 0x0b */ -+#define ACODEC_DAC_ANA_HPMIX_CTL0 0x30 /* REG 0x0c */ -+#define ACODEC_DAC_ANA_HPMIX_CTL1 0x34 /* REG 0x0d */ -+/* Resevred REG 0x0e ~ 0x0f */ -+ -+/* -+ * These registers are referenced by codec driver -+ */ -+ -+#define RK3308_GLB_CON ACODEC_RESET_CTL -+ -+/* ADC DIGITAL REGISTERS */ -+ -+/* -+ * The ADC chanel are 0 ~ 3, that control: -+ * -+ * CH0: left_0(ADC1) and right_0(ADC2) -+ * CH1: left_1(ADC3) and right_1(ADC4) -+ * CH2: left_2(ADC5) and right_2(ADC6) -+ * CH3: left_3(ADC7) and right_3(ADC8) -+ */ -+#define RK3308_ADC_DIG_OFFSET(ch) ((ch & 0x3) * 0xc0 + 0x0) -+ -+#define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL0) -+#define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL1) -+#define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_BIST_MODE_SEL) -+#define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_DATA_PATH) -+ -+#define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL0) -+#define RK3308_ALC_L_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL1) -+#define RK3308_ALC_L_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL2) -+#define RK3308_ALC_L_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL3) -+#define RK3308_ALC_L_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL4) -+#define RK3308_ALC_L_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_LO_MAX) -+#define RK3308_ALC_L_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_HI_MAX) -+#define RK3308_ALC_L_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_LO_MIN) -+#define RK3308_ALC_L_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_HI_MIN) -+#define RK3308_ALC_L_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL5) -+#define RK3308_ALC_L_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_AGC_L_RO_GAIN) -+ -+#define RK3308_ALC_R_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL0) -+#define RK3308_ALC_R_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL1) -+#define RK3308_ALC_R_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL2) -+#define RK3308_ALC_R_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL3) -+#define RK3308_ALC_R_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL4) -+#define RK3308_ALC_R_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_LO_MAX) -+#define RK3308_ALC_R_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_HI_MAX) -+#define RK3308_ALC_R_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_LO_MIN) -+#define RK3308_ALC_R_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_HI_MIN) -+#define RK3308_ALC_R_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL5) -+#define RK3308_ALC_R_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_AGC_R_RO_GAIN) -+ -+/* DAC DIGITAL REGISTERS */ -+#define RK3308_DAC_DIG_OFFSET 0x300 -+ -+#define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL0) -+#define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL1) -+#define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_BIST_MODE_SEL) -+#define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_SEL) -+#define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_HI) -+#define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_LO) -+ -+/* ADC ANALOG REGISTERS */ -+/* -+ * The ADC chanel are 0 ~ 3, that control: -+ * -+ * CH0: left_0(ADC1) and right_0(ADC2) -+ * CH1: left_1(ADC3) and right_1(ADC4) -+ * CH2: left_2(ADC5) and right_2(ADC6) -+ * CH3: left_3(ADC7) and right_3(ADC8) -+ */ -+#define RK3308_ADC_ANA_OFFSET(ch) ((ch & 0x3) * 0x40 + 0x340) -+ -+#define RK3308_ADC_ANA_CON00(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_MIC_CTL) -+#define RK3308_ADC_ANA_CON01(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_MIC_GAIN) -+#define RK3308_ADC_ANA_CON02(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_CTL) -+#define RK3308_ADC_ANA_CON03(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_GAIN1) -+#define RK3308_ADC_ANA_CON04(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_GAIN2) -+#define RK3308_ADC_ANA_CON05(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL0) -+#define RK3308_ADC_ANA_CON06(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL1) -+#define RK3308_ADC_ANA_CON07(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL2) -+#define RK3308_ADC_ANA_CON08(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL3) -+#define RK3308_ADC_ANA_CON10(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL4) -+#define RK3308_ADC_ANA_CON11(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_PGA) -+ -+/* DAC ANALOG REGISTERS */ -+#define RK3308_DAC_ANA_OFFSET 0x440 -+ -+#define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL0) -+#define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_POP_VOLT) -+#define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL1) -+#define RK3308_DAC_ANA_CON03 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPOUT) -+#define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT) -+#define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_L_HPOUT_GAIN) -+#define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_R_HPOUT_GAIN) -+#define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL0) -+#define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL1) -+ -+/* -+ * These are the bits for registers -+ */ -+ -+/* RK3308_GLB_CON - REG: 0x0000 */ -+#define RK3308_ADC_BIST_WORK (1 << 7) -+#define RK3308_ADC_BIST_RESET (0 << 7) -+#define RK3308_DAC_BIST_WORK (1 << 6) -+#define RK3308_DAC_BIST_RESET (0 << 6) -+#define RK3308_CODEC_RST_MSK (0x7 << 0) -+#define RK3308_ADC_DIG_WORK (1 << 2) -+#define RK3308_ADC_DIG_RESET (0 << 2) -+#define RK3308_DAC_DIG_WORK (1 << 1) -+#define RK3308_DAC_DIG_RESET (0 << 1) -+#define RK3308_SYS_WORK (1 << 0) -+#define RK3308_SYS_RESET (0 << 0) -+ -+/* RK3308_ADC_DIG_CON01 - REG: 0x0004 */ -+#define RK3308_ADC_I2S_LRC_POL_MSK (1 << 0) -+#define RK3308_ADC_I2S_LRC_POL_REVERSAL (1 << 0) -+#define RK3308_ADC_I2S_LRC_POL_NORMAL (0 << 0) -+#define RK3308_ADC_I2S_VALID_LEN_SFT 5 -+#define RK3308_ADC_I2S_VALID_LEN_MSK (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_32BITS (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_24BITS (0x2 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_20BITS (0x1 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_16BITS (0x0 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_MODE_SFT 3 -+#define RK3308_ADC_I2S_MODE_MSK (0x3 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_PCM (0x3 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_I2S (0x2 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_LJ (0x1 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_RJ (0x0 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_LR_MSK (1 << 1) -+#define RK3308_ADC_I2S_LR_SWAP (1 << 1) -+#define RK3308_ADC_I2S_LR_NORMAL (0 << 1) -+#define RK3308_ADC_I2S_TYPE_MSK (1 << 0) -+#define RK3308_ADC_I2S_MONO (1 << 0) -+#define RK3308_ADC_I2S_STEREO (0 << 0) -+ -+/* RK3308_ADC_DIG_CON02 - REG: 0x0008 */ -+#define RK3308_ADC_IO_MODE_MSK (1 << 5) -+#define RK3308_ADC_IO_MODE_MASTER (1 << 5) -+#define RK3308_ADC_IO_MODE_SLAVE (0 << 5) -+#define RK3308_ADC_MODE_MSK (1 << 4) -+#define RK3308_ADC_MODE_MASTER (1 << 4) -+#define RK3308_ADC_MODE_SLAVE (0 << 4) -+#define RK3308_ADC_I2S_FRAME_LEN_SFT 2 -+#define RK3308_ADC_I2S_FRAME_LEN_MSK (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_32BITS (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_24BITS (0x2 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_20BITS (0x1 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_16BITS (0x0 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_MSK (0x1 << 1) -+#define RK3308_ADC_I2S_WORK (0x1 << 1) -+#define RK3308_ADC_I2S_RESET (0x0 << 1) -+#define RK3308_ADC_I2S_BIT_CLK_POL_MSK (0x1 << 0) -+#define RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0) -+#define RK3308_ADC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0) -+ -+/* RK3308_ADC_DIG_CON03 - REG: 0x000c */ -+#define RK3308_ADC_L_CH_BIST_SFT 2 -+#define RK3308_ADC_L_CH_BIST_MSK (0x3 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_LEFT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_L_CH_BIST_SINE (0x2 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_CUBE (0x1 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_RIGHT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_BIST_SFT 0 -+#define RK3308_ADC_R_CH_BIST_MSK (0x3 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_BIST_SINE (0x2 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_CUBE (0x1 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+ -+/* RK3308_ADC_DIG_CON07 - REG: 0x001c */ -+#define RK3308_ADCL_DATA_SFT 4 -+#define RK3308_ADCL_DATA(x) (x << RK3308_ADCL_DATA_SFT) -+#define RK3308_ADCR_DATA_SFT 2 -+#define RK3308_ADCR_DATA(x) (x << RK3308_ADCR_DATA_SFT) -+#define RK3308_ADCL_DATA_SEL_ADCL (0x1 << 1) -+#define RK3308_ADCL_DATA_SEL_NORMAL (0x0 << 1) -+#define RK3308_ADCR_DATA_SEL_ADCR (0x1 << 0) -+#define RK3308_ADCR_DATA_SEL_NORMAL (0x0 << 0) -+ -+/* -+ * RK3308_ALC_L_DIG_CON00 - REG: 0x0040 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON00 - REG: 0x0080 + ch * 0xc0 -+ */ -+#define RK3308_GAIN_ATTACK_JACK (0x1 << 6) -+#define RK3308_GAIN_ATTACK_NORMAL (0x0 << 6) -+#define RK3308_CTRL_GEN_SFT 4 -+#define RK3308_CTRL_GEN_MSK (0x3 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_JACK3 (0x3 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_JACK2 (0x2 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_JACK1 (0x1 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_NORMAL (0x0 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_AGC_HOLD_TIME_SFT 0 -+#define RK3308_AGC_HOLD_TIME_MSK (0xf << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_1S (0xa << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_512MS (0x9 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_256MS (0x8 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_128MS (0x7 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_64MS (0x6 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_32MS (0x5 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_16MS (0x4 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_8MS (0x3 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_4MS (0x2 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_2MS (0x1 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_0MS (0x0 << RK3308_AGC_HOLD_TIME_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON01 - REG: 0x0044 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON01 - REG: 0x0084 + ch * 0xc0 -+ */ -+#define RK3308_AGC_DECAY_TIME_SFT 4 -+/* Normal mode (reg_agc_mode = 0) */ -+#define RK3308_AGC_DECAY_NORMAL_MSK (0xf << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_512MS (0xa << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_256MS (0x9 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_128MS (0x8 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_64MS (0x7 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_32MS (0x6 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_16MS (0x5 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_8MS (0x4 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_4MS (0x3 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_2MS (0x2 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_1MS (0x1 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_0MS (0x0 << RK3308_AGC_DECAY_TIME_SFT) -+/* Limiter mode (reg_agc_mode = 1) */ -+#define RK3308_AGC_DECAY_LIMITER_MSK (0xf << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_128MS (0xa << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_64MS (0x9 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_32MS (0x8 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_16MS (0x7 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_8MS (0x6 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_4MS (0x5 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_2MS (0x4 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_1MS (0x3 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_500US (0x2 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_250US (0x1 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_125US (0x0 << RK3308_AGC_DECAY_TIME_SFT) -+ -+#define RK3308_AGC_ATTACK_TIME_SFT 0 -+/* Normal mode (reg_agc_mode = 0) */ -+#define RK3308_AGC_ATTACK_NORMAL_MSK (0xf << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_128MS (0xa << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_64MS (0x9 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_32MS (0x8 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_16MS (0x7 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_8MS (0x6 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_4MS (0x5 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_2MS (0x4 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_1MS (0x3 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_500US (0x2 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_250US (0x1 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_125US (0x0 << RK3308_AGC_ATTACK_TIME_SFT) -+/* Limiter mode (reg_agc_mode = 1) */ -+#define RK3308_AGC_ATTACK_LIMITER_MSK (0xf << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_32MS (0xa << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_16MS (0x9 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_8MS (0x8 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_4MS (0x7 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_2MS (0x6 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_1MS (0x5 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_500US (0x4 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_250US (0x3 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_125US (0x2 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_64US (0x1 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_32US (0x0 << RK3308_AGC_ATTACK_TIME_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON02 - REG: 0x0048 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON02 - REG: 0x0088 + ch * 0xc0 -+ */ -+#define RK3308_AGC_MODE_LIMITER (0x1 << 7) -+#define RK3308_AGC_MODE_NORMAL (0x0 << 7) -+#define RK3308_AGC_ZERO_CRO_EN (0x1 << 6) -+#define RK3308_AGC_ZERO_CRO_DIS (0x0 << 6) -+#define RK3308_AGC_AMP_RECOVER_GAIN (0x1 << 5) -+#define RK3308_AGC_AMP_RECOVER_LVOL (0x0 << 5) -+#define RK3308_AGC_FAST_DEC_EN (0x1 << 4) -+#define RK3308_AGC_FAST_DEC_DIS (0x0 << 4) -+#define RK3308_AGC_NOISE_GATE_EN (0x1 << 3) -+#define RK3308_AGC_NOISE_GATE_DIS (0x0 << 3) -+#define RK3308_AGC_NOISE_GATE_THRESH_SFT 0 -+#define RK3308_AGC_NOISE_GATE_THRESH_MSK (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N81DB (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N75DB (0x6 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N69DB (0x5 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N63DB (0x4 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N57DB (0x3 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N51DB (0x2 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N45DB (0x1 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N39DB (0x0 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON03 - REG: 0x004c + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON03 - REG: 0x008c + ch * 0xc0 -+ */ -+#define RK3308_AGC_PGA_ZERO_CRO_EN (0x1 << 5) -+#define RK3308_AGC_PGA_ZERO_CRO_DIS (0x0 << 5) -+#define RK3308_AGC_PGA_GAIN_SFT 0 -+#define RK3308_AGC_PGA_GAIN_MSK (0x1f << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_28_5 (0x1f << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_27 (0x1e << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_25_5 (0x1d << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_24 (0x1c << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_22_5 (0x1b << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_21 (0x1a << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_19_5 (0x19 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_18 (0x18 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_16_5 (0x17 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_15 (0x16 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_13_5 (0x15 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_12 (0x14 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_10_5 (0x13 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_9 (0x12 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_7_5 (0x11 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_6 (0x10 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_4_5 (0x0f << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_3 (0x0e << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_1_5 (0x0d << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_0DB (0x0c << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_1_5 (0x0b << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_3 (0x0a << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_4_5 (0x09 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_6 (0x08 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_7_5 (0x07 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_9 (0x06 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_10_5 (0x05 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_12 (0x04 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_13_5 (0x03 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_15 (0x02 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_16_5 (0x01 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_18 (0x00 << RK3308_AGC_PGA_GAIN_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON04 - REG: 0x0050 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON04 - REG: 0x0090 + ch * 0xc0 -+ */ -+#define RK3308_AGC_SLOW_CLK_EN (0x1 << 3) -+#define RK3308_AGC_SLOW_CLK_DIS (0x0 << 3) -+#define RK3308_AGC_APPROX_RATE_SFT 0 -+#define RK3308_AGC_APPROX_RATE_MSK (0x7 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_8K (0x7 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_12K (0x6 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_16K (0x5 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_24K (0x4 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_32K (0x3 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_44_1K (0x2 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_48K (0x1 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_96K (0x0 << RK3308_AGC_APPROX_RATE_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON05 - REG: 0x0054 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON05 - REG: 0x0094 + ch * 0xc0 -+ */ -+#define RK3308_AGC_LO_8BITS_AGC_MAX_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON06 - REG: 0x0058 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON06 - REG: 0x0098 + ch * 0xc0 -+ */ -+#define RK3308_AGC_HI_8BITS_AGC_MAX_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON07 - REG: 0x005c + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON07 - REG: 0x009c + ch * 0xc0 -+ */ -+#define RK3308_AGC_LO_8BITS_AGC_MIN_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON08 - REG: 0x0060 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON08 - REG: 0x00a0 + ch * 0xc0 -+ */ -+#define RK3308_AGC_HI_8BITS_AGC_MIN_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON09 - REG: 0x0064 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON09 - REG: 0x00a4 + ch * 0xc0 -+ */ -+#define RK3308_AGC_FUNC_SEL_MSK (0x1 << 6) -+#define RK3308_AGC_FUNC_SEL_EN (0x1 << 6) -+#define RK3308_AGC_FUNC_SEL_DIS (0x0 << 6) -+#define RK3308_AGC_MAX_GAIN_PGA_SFT 3 -+#define RK3308_AGC_MAX_GAIN_PGA_MSK (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_28_5 (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_22_5 (0x6 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_16_5 (0x5 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_10_5 (0x4 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_4_5 (0x3 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_NDB_1_5 (0x2 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_NDB_7_5 (0x1 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_NDB_13_5 (0x0 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_SFT 0 -+#define RK3308_AGC_MIN_GAIN_PGA_MSK (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_24 (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_18 (0x6 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_12 (0x5 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_6 (0x4 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_0DB (0x3 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_NDB_6 (0x2 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_NDB_12 (0x1 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_NDB_18 (0x0 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON12 - REG: 0x0068 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON12 - REG: 0x00a8 + ch * 0xc0 -+ */ -+#define RK3308_AGC_GAIN_MSK 0x1f -+ -+/* RK3308_DAC_DIG_CON01 - REG: 0x0304 */ -+#define RK3308_DAC_I2S_LRC_POL_MSK (0x1 << 7) -+#define RK3308_DAC_I2S_LRC_POL_REVERSAL (0x1 << 7) -+#define RK3308_DAC_I2S_LRC_POL_NORMAL (0x0 << 7) -+#define RK3308_DAC_I2S_VALID_LEN_SFT 5 -+#define RK3308_DAC_I2S_VALID_LEN_MSK (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_32BITS (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_24BITS (0x2 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_20BITS (0x1 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_16BITS (0x0 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_MODE_SFT 3 -+#define RK3308_DAC_I2S_MODE_MSK (0x3 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_PCM (0x3 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_I2S (0x2 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_LJ (0x1 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_RJ (0x0 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_LR_MSK (0x1 << 2) -+#define RK3308_DAC_I2S_LR_SWAP (0x1 << 2) -+#define RK3308_DAC_I2S_LR_NORMAL (0x0 << 2) -+ -+/* RK3308_DAC_DIG_CON02 - REG: 0x0308 */ -+#define RK3308_DAC_IO_MODE_MSK (0x1 << 5) -+#define RK3308_DAC_IO_MODE_MASTER (0x1 << 5) -+#define RK3308_DAC_IO_MODE_SLAVE (0x0 << 5) -+#define RK3308_DAC_MODE_MSK (0x1 << 4) -+#define RK3308_DAC_MODE_MASTER (0x1 << 4) -+#define RK3308_DAC_MODE_SLAVE (0x0 << 4) -+#define RK3308_DAC_I2S_FRAME_LEN_SFT 2 -+#define RK3308_DAC_I2S_FRAME_LEN_MSK (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_32BITS (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_24BITS (0x2 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_20BITS (0x1 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_16BITS (0x0 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_MSK (0x1 << 1) -+#define RK3308_DAC_I2S_WORK (0x1 << 1) -+#define RK3308_DAC_I2S_RESET (0x0 << 1) -+#define RK3308_DAC_I2S_BIT_CLK_POL_MSK (0x1 << 0) -+#define RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0) -+#define RK3308_DAC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0) -+ -+/* RK3308_DAC_DIG_CON03 - REG: 0x030C */ -+#define RK3308_DAC_L_CH_BIST_SFT 2 -+#define RK3308_DAC_L_CH_BIST_MSK (0x3 << RK3308_DAC_L_CH_BIST_SFT) -+#define RK3308_DAC_L_CH_BIST_LEFT (0x3 << RK3308_DAC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_DAC_L_CH_BIST_CUBE (0x2 << RK3308_DAC_L_CH_BIST_SFT) -+#define RK3308_DAC_L_CH_BIST_SINE (0x1 << RK3308_DAC_L_CH_BIST_SFT) -+#define RK3308_DAC_L_CH_BIST_RIGHT (0x0 << RK3308_DAC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_DAC_R_CH_BIST_SFT 0 -+#define RK3308_DAC_R_CH_BIST_MSK (0x3 << RK3308_DAC_R_CH_BIST_SFT) -+#define RK3308_DAC_R_CH_BIST_LEFT (0x3 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_DAC_R_CH_BIST_CUBE (0x2 << RK3308_DAC_R_CH_BIST_SFT) -+#define RK3308_DAC_R_CH_BIST_SINE (0x1 << RK3308_DAC_R_CH_BIST_SFT) -+#define RK3308_DAC_R_CH_BIST_RIGHT (0x0 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ -+ -+/* RK3308_DAC_DIG_CON05 - REG: 0x0314 */ -+#define RK3308_DAC_L_REG_CTL_INDATA (0x1 << 2) -+#define RK3308_DAC_L_NORMAL_DATA (0x0 << 2) -+#define RK3308_DAC_R_REG_CTL_INDATA (0x1 << 1) -+#define RK3308_DAC_R_NORMAL_DATA (0x0 << 1) -+ -+/* RK3308_DAC_DIG_CON10 - REG: 0x0328 */ -+#define RK3308_DAC_DATA_HI4(x) (x & 0xf) /* Need to RK3308_DAC_x_REG_CTL_INDATA */ -+ -+/* RK3308_DAC_DIG_CON11 - REG: 0x032c */ -+#define RK3308_DAC_DATA_LO8(x) (x & 0xff) /* Need to RK3308_DAC_x_REG_CTL_INDATA */ -+ -+/* RK3308_ADC_ANA_CON00 - REG: 0x0340 */ -+#define RK3308_ADC_CH1_CH2_MIC_ALL_MSK (0xff << 0) -+#define RK3308_ADC_CH1_CH2_MIC_ALL 0xff -+#define RK3308_ADC_CH2_MIC_UNMUTE (0x1 << 7) -+#define RK3308_ADC_CH2_MIC_MUTE (0x0 << 7) -+#define RK3308_ADC_CH2_MIC_WORK (0x1 << 6) -+#define RK3308_ADC_CH2_MIC_INIT (0x0 << 6) -+#define RK3308_ADC_CH2_MIC_EN (0x1 << 5) -+#define RK3308_ADC_CH2_MIC_DIS (0x0 << 5) -+#define RK3308_ADC_CH2_BUF_REF_EN (0x1 << 4) -+#define RK3308_ADC_CH2_BUF_REF_DIS (0x0 << 4) -+#define RK3308_ADC_CH1_MIC_UNMUTE (0x1 << 3) -+#define RK3308_ADC_CH1_MIC_MUTE (0x0 << 3) -+#define RK3308_ADC_CH1_MIC_WORK (0x1 << 2) -+#define RK3308_ADC_CH1_MIC_INIT (0x0 << 2) -+#define RK3308_ADC_CH1_MIC_EN (0x1 << 1) -+#define RK3308_ADC_CH1_MIC_DIS (0x0 << 1) -+#define RK3308_ADC_CH1_BUF_REF_EN (0x1 << 0) -+#define RK3308_ADC_CH1_BUF_REF_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON01 - REG: 0x0344 */ -+#define RK3308_ADC_CH2_MIC_GAIN_SFT 4 -+#define RK3308_ADC_CH2_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_SFT 0 -+#define RK3308_ADC_CH1_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+ -+/* RK3308_ADC_ANA_CON02 - REG: 0x0348 */ -+#define RK3308_ADC_CH2_ALC_ZC_MSK (0x7 << 4) -+#define RK3308_ADC_CH2_ZEROCROSS_DET_EN (0x1 << 6) -+#define RK3308_ADC_CH2_ZEROCROSS_DET_DIS (0x0 << 6) -+#define RK3308_ADC_CH2_ALC_WORK (0x1 << 5) -+#define RK3308_ADC_CH2_ALC_INIT (0x0 << 5) -+#define RK3308_ADC_CH2_ALC_EN (0x1 << 4) -+#define RK3308_ADC_CH2_ALC_DIS (0x0 << 4) -+ -+#define RK3308_ADC_CH1_ALC_ZC_MSK (0x7 << 0) -+#define RK3308_ADC_CH1_ZEROCROSS_DET_EN (0x1 << 2) -+#define RK3308_ADC_CH1_ZEROCROSS_DET_DIS (0x0 << 2) -+#define RK3308_ADC_CH1_ALC_WORK (0x1 << 1) -+#define RK3308_ADC_CH1_ALC_INIT (0x0 << 1) -+#define RK3308_ADC_CH1_ALC_EN (0x1 << 0) -+#define RK3308_ADC_CH1_ALC_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON03 - REG: 0x034c */ -+#define RK3308_ADC_CH1_ALC_GAIN_SFT 0 -+#define RK3308_ADC_CH1_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_27 (0x1e << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_25_5 (0x1d << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_24 (0x1c << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_22_5 (0x1b << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_21 (0x1a << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_19_5 (0x19 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_18 (0x18 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_16_5 (0x17 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_15 (0x16 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_13_5 (0x15 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_12 (0x14 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_10_5 (0x13 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_9 (0x12 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_7_5 (0x11 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_6 (0x10 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_4_5 (0x0f << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_3 (0x0e << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_1_5 (0x0d << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_1_5 (0x0b << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_3 (0x0a << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_4_5 (0x09 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_6 (0x08 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_7_5 (0x07 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_9 (0x06 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_10_5 (0x05 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_12 (0x04 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_13_5 (0x03 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_15 (0x02 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_16_5 (0x01 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+ -+/* RK3308_ADC_ANA_CON04 - REG: 0x0350 */ -+#define RK3308_ADC_CH2_ALC_GAIN_SFT 0 -+#define RK3308_ADC_CH2_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_27 (0x1e << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_25_5 (0x1d << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_24 (0x1c << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_22_5 (0x1b << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_21 (0x1a << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_19_5 (0x19 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_18 (0x18 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_16_5 (0x17 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_15 (0x16 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_13_5 (0x15 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_12 (0x14 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_10_5 (0x13 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_9 (0x12 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_7_5 (0x11 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_6 (0x10 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_4_5 (0x0f << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_3 (0x0e << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_1_5 (0x0d << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_1_5 (0x0b << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_3 (0x0a << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_4_5 (0x09 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_6 (0x08 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_7_5 (0x07 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_9 (0x06 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_10_5 (0x05 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_12 (0x04 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_13_5 (0x03 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_15 (0x02 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_16_5 (0x01 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+ -+/* RK3308_ADC_ANA_CON05 - REG: 0x0354 */ -+#define RK3308_ADC_CH2_ADC_CLK_MSK (0x7 << 4) -+#define RK3308_ADC_CH2_ADC_WORK (0x1 << 6) -+#define RK3308_ADC_CH2_ADC_INIT (0x0 << 6) -+#define RK3308_ADC_CH2_ADC_EN (0x1 << 5) -+#define RK3308_ADC_CH2_ADC_DIS (0x0 << 5) -+#define RK3308_ADC_CH2_CLK_EN (0x1 << 4) -+#define RK3308_ADC_CH2_CLK_DIS (0x0 << 4) -+ -+#define RK3308_ADC_CH1_ADC_CLK_MSK (0x7 << 0) -+#define RK3308_ADC_CH1_ADC_WORK (0x1 << 2) -+#define RK3308_ADC_CH1_ADC_INIT (0x0 << 2) -+#define RK3308_ADC_CH1_ADC_EN (0x1 << 1) -+#define RK3308_ADC_CH1_ADC_DIS (0x0 << 1) -+#define RK3308_ADC_CH1_CLK_EN (0x1 << 0) -+#define RK3308_ADC_CH1_CLK_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON06 - REG: 0x0358 */ -+#define RK3308_ADC_CURRENT_MSK (0x1 << 0) -+#define RK3308_ADC_CURRENT_EN (0x1 << 0) -+#define RK3308_ADC_CURRENT_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON07 - REG: 0x035c */ -+/* Note: The register configuration is only valid for ADC2 */ -+#define RK3308_ADC_CH2_IN_SEL_SFT 6 -+#define RK3308_ADC_CH2_IN_SEL_MSK (0x3 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_LINEIN_MIC (0x3 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_LINEIN (0x2 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_MIC (0x1 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_NONE (0x0 << RK3308_ADC_CH2_IN_SEL_SFT) -+/* Note: The register configuration is only valid for ADC1 */ -+#define RK3308_ADC_CH1_IN_SEL_SFT 4 -+#define RK3308_ADC_CH1_IN_SEL_MSK (0x3 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_LINEIN_MIC (0x3 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_LINEIN (0x2 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_MIC (0x1 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_NONE (0x0 << RK3308_ADC_CH1_IN_SEL_SFT) -+ -+#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << 3) -+#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << 3) -+#define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 -+#define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_85 (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_8 (0x6 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_75 (0x5 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_7 (0x4 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_65 (0x3 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_6 (0x2 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_55 (0x1 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_5 (0x0 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+ -+/* RK3308_ADC_ANA_CON08 - REG: 0x0360 */ -+#define RK3308_ADC_MICBIAS_CURRENT_MSK (0x1 << 4) -+#define RK3308_ADC_MICBIAS_CURRENT_EN (0x1 << 4) -+#define RK3308_ADC_MICBIAS_CURRENT_DIS (0x0 << 4) -+ -+/* RK3308_ADC_ANA_CON10 - REG: 0x0368 */ -+#define RK3308_ADC_REF_EN (0x1 << 7) -+#define RK3308_ADC_REF_DIS (0x0 << 7) -+#define RK3308_ADC_CURRENT_CHARGE_SFT 0 -+#define RK3308_ADC_CURRENT_CHARGE_MSK (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) -+#define RK3308_ADC_DONT_SEL_ALL (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) -+/* -+ * 0: Choose the current I -+ * 1: Don't choose the current I -+ */ -+#define RK3308_ADC_SEL_I_1(x) ((x & 0x1) << 6) -+#define RK3308_ADC_SEL_I_2(x) ((x & 0x1) << 5) -+#define RK3308_ADC_SEL_I_4(x) ((x & 0x1) << 4) -+#define RK3308_ADC_SEL_I_8(x) ((x & 0x1) << 3) -+#define RK3308_ADC_SEL_I_16(x) ((x & 0x1) << 2) -+#define RK3308_ADC_SEL_I_32(x) ((x & 0x1) << 1) -+#define RK3308_ADC_SEL_I_64(x) ((x & 0x1) << 0) -+ -+/* RK3308_ADC_ANA_CON11 - REG: 0x036c */ -+#define RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK (0x1 << 1) -+#define RK3308_ADC_ALCR_CON_GAIN_PGAR_EN (0x1 << 1) -+#define RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS (0x0 << 1) -+#define RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK (0x1 << 0) -+#define RK3308_ADC_ALCL_CON_GAIN_PGAL_EN (0x1 << 0) -+#define RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON00 - REG: 0x0440 */ -+#define RK3308_DAC_HEADPHONE_DET_EN (0x1 << 1) -+#define RK3308_DAC_HEADPHONE_DET_DIS (0x0 << 1) -+#define RK3308_DAC_CURRENT_MSK (0x1 << 0) -+#define RK3308_DAC_CURRENT_EN (0x1 << 0) -+#define RK3308_DAC_CURRENT_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON01 - REG: 0x0444 */ -+#define RK3308_DAC_BUF_REF_R_MSK (0x1 << 6) -+#define RK3308_DAC_BUF_REF_R_EN (0x1 << 6) -+#define RK3308_DAC_BUF_REF_R_DIS (0x0 << 6) -+#define RK3308_DAC_POP_SOUND_R_SFT 4 -+#define RK3308_DAC_POP_SOUND_R_MSK (0x3 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_POP_SOUND_R_WORK (0x2 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_POP_SOUND_R_INIT (0x1 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_BUF_REF_L_MSK (0x1 << 2) -+#define RK3308_DAC_BUF_REF_L_EN (0x1 << 2) -+#define RK3308_DAC_BUF_REF_L_DIS (0x0 << 2) -+#define RK3308_DAC_POP_SOUND_L_SFT 0 -+#define RK3308_DAC_POP_SOUND_L_MSK (0x3 << RK3308_DAC_POP_SOUND_L_SFT) -+#define RK3308_DAC_POP_SOUND_L_WORK (0x2 << RK3308_DAC_POP_SOUND_L_SFT) -+#define RK3308_DAC_POP_SOUND_L_INIT (0x1 << RK3308_DAC_POP_SOUND_L_SFT) -+ -+/* RK3308_DAC_ANA_CON02 - REG: 0x0448 */ -+#define RK3308_DAC_R_DAC_WORK (0x1 << 7) -+#define RK3308_DAC_R_DAC_INIT (0x0 << 7) -+#define RK3308_DAC_R_DAC_EN (0x1 << 6) -+#define RK3308_DAC_R_DAC_DIS (0x0 << 6) -+#define RK3308_DAC_R_CLK_EN (0x1 << 5) -+#define RK3308_DAC_R_CLK_DIS (0x0 << 5) -+#define RK3308_DAC_R_REF_EN (0x1 << 4) -+#define RK3308_DAC_R_REF_DIS (0x0 << 4) -+#define RK3308_DAC_L_DAC_WORK (0x1 << 3) -+#define RK3308_DAC_L_DAC_INIT (0x0 << 3) -+#define RK3308_DAC_L_DAC_EN (0x1 << 2) -+#define RK3308_DAC_L_DAC_DIS (0x0 << 2) -+#define RK3308_DAC_L_CLK_EN (0x1 << 1) -+#define RK3308_DAC_L_CLK_DIS (0x0 << 1) -+#define RK3308_DAC_L_REF_EN (0x1 << 0) -+#define RK3308_DAC_L_REF_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON03 - REG: 0x044c */ -+#define RK3308_DAC_R_HPOUT_WORK (0x1 << 6) -+#define RK3308_DAC_R_HPOUT_INIT (0x0 << 6) -+#define RK3308_DAC_R_HPOUT_EN (0x1 << 5) -+#define RK3308_DAC_R_HPOUT_DIS (0x0 << 5) -+#define RK3308_DAC_R_HPOUT_UNMUTE (0x1 << 4) -+#define RK3308_DAC_R_HPOUT_MUTE (0x0 << 4) -+#define RK3308_DAC_L_HPOUT_WORK (0x1 << 2) -+#define RK3308_DAC_L_HPOUT_INIT (0x0 << 2) -+#define RK3308_DAC_L_HPOUT_EN (0x1 << 1) -+#define RK3308_DAC_L_HPOUT_DIS (0x0 << 1) -+#define RK3308_DAC_L_HPOUT_UNMUTE (0x1 << 0) -+#define RK3308_DAC_L_HPOUT_MUTE (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON04 - REG: 0x0450 */ -+#define RK3308_DAC_R_GAIN_SFT 6 -+#define RK3308_DAC_R_GAIN_MSK (0x3 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_0DB (0x3 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_PDB_1_5 (0x2 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_PDB_3 (0x1 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_PDB_6 (0x0 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_UNMUTE (0x1 << 5) -+#define RK3308_DAC_R_LINEOUT_MUTE (0x0 << 5) -+#define RK3308_DAC_R_LINEOUT_EN (0x1 << 4) -+#define RK3308_DAC_R_LINEOUT_DIS (0x0 << 4) -+#define RK3308_DAC_L_GAIN_SFT 2 -+#define RK3308_DAC_L_GAIN_MSK (0x3 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_0DB (0x3 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_PDB_1_5 (0x2 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_PDB_3 (0x1 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_PDB_6 (0x0 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_UNMUTE (0x1 << 1) -+#define RK3308_DAC_L_LINEOUT_MUTE (0x0 << 1) -+#define RK3308_DAC_L_LINEOUT_EN (0x1 << 0) -+#define RK3308_DAC_L_LINEOUT_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON05 - REG: 0x0454, step is 1.5db */ -+#define RK3308_DAC_L_HPOUT_GAIN_SFT 0 -+#define RK3308_DAC_L_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_4_5 (0x1d << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_3 (0x1c << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_1_5 (0x1b << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_0DB (0x1a << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_1_5 (0x19 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_3 (0x18 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_4_5 (0x17 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_6 (0x16 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_7_5 (0x15 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_9 (0x14 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_10_5 (0x13 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_12 (0x12 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_13_5 (0x11 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_15 (0x10 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_16_5 (0x0f << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_18 (0x0e << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_19_5 (0x0d << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_21 (0x0c << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_22_5 (0x0b << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_24 (0x0a << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_25_5 (0x09 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_27 (0x08 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_28_5 (0x07 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_30 (0x06 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_31_5 (0x05 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_33 (0x04 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_34_5 (0x03 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_36 (0x02 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+ -+/* RK3308_DAC_ANA_CON06 - REG: 0x0458, step is 1.5db */ -+#define RK3308_DAC_R_HPOUT_GAIN_SFT 0 -+#define RK3308_DAC_R_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_4_5 (0x1d << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_3 (0x1c << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_1_5 (0x1b << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_0DB (0x1a << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_1_5 (0x19 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_3 (0x18 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_4_5 (0x17 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_6 (0x16 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_7_5 (0x15 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_9 (0x14 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_10_5 (0x13 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_12 (0x12 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_13_5 (0x11 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_15 (0x10 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_16_5 (0x0f << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_18 (0x0e << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_19_5 (0x0d << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_21 (0x0c << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_22_5 (0x0b << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_24 (0x0a << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_25_5 (0x09 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_27 (0x08 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_28_5 (0x07 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_30 (0x06 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_31_5 (0x05 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_33 (0x04 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_34_5 (0x03 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_36 (0x02 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+ -+/* RK3308_DAC_ANA_CON12 - REG: 0x0470 */ -+#define RK3308_DAC_R_HPMIX_SEL_SFT 6 -+#define RK3308_DAC_R_HPMIX_SEL_MSK (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_LINEIN (0x2 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_I2S (0x1 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_NONE (0x0 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_SFT 4 -+#define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_R_HPMIX_GAIN_SFT) -+#define RK3308_DAC_L_HPMIX_SEL_SFT 2 -+#define RK3308_DAC_L_HPMIX_SEL_MSK (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_LINEIN (0x2 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_I2S (0x1 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_NONE (0x0 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_SFT 0 -+#define RK3308_DAC_L_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_L_HPMIX_GAIN_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_L_HPMIX_GAIN_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_L_HPMIX_GAIN_SFT) -+ -+/* RK3308_DAC_ANA_CON13 - REG: 0x0474 */ -+#define RK3308_DAC_R_HPMIX_UNMUTE (0x1 << 6) -+#define RK3308_DAC_R_HPMIX_MUTE (0x0 << 6) -+#define RK3308_DAC_R_HPMIX_WORK (0x1 << 5) -+#define RK3308_DAC_R_HPMIX_INIT (0x0 << 5) -+#define RK3308_DAC_R_HPMIX_EN (0x1 << 4) -+#define RK3308_DAC_R_HPMIX_DIS (0x0 << 4) -+#define RK3308_DAC_L_HPMIX_UNMUTE (0x1 << 2) -+#define RK3308_DAC_L_HPMIX_MUTE (0x0 << 2) -+#define RK3308_DAC_L_HPMIX_WORK (0x1 << 1) -+#define RK3308_DAC_L_HPMIX_INIT (0x0 << 1) -+#define RK3308_DAC_L_HPMIX_EN (0x1 << 0) -+#define RK3308_DAC_L_HPMIX_DIS (0x0 << 0) -+ -+#define RK3308_HIFI 0x0 -+ -+#endif /* __RK3308_CODEC_H__ */ --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch b/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch deleted file mode 100644 index 0cb1086..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch +++ /dev/null @@ -1,6740 +0,0 @@ -From 26d61ff64d9a61425d017846db61e9a06de07286 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 17:13:59 +0100 -Subject: [PATCH 19/23] Sync `rk3308_codec` to BSP tree - ---- - .../bindings/sound/rockchip,rk3308-codec.txt | 78 + - sound/soc/codecs/rk3308_codec.c | 5687 ++++++++++++++--- - sound/soc/codecs/rk3308_codec.h | 217 +- - sound/soc/codecs/rk3308_codec_provider.h | 28 + - 4 files changed, 4894 insertions(+), 1116 deletions(-) - create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt - create mode 100644 sound/soc/codecs/rk3308_codec_provider.h - -diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt -new file mode 100644 -index 000000000000..e20bbd73e37e ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt -@@ -0,0 +1,78 @@ -+* Rockchip RK3308 Internal Codec -+ -+Required properties: -+ -+- compatible: "rockchip,rk3308-codec" -+- reg: The physical base address of the controller and length of memory -+ mapped region. -+- rockchip,grf: The phandle of the syscon node for GRF register. -+- clocks: A list of phandle + clock-specifer pairs, one for each entry in -+ clock-names. -+- clock-names: It should be "acodec". -+- resets : Must contain an entry for each entry in reset-names. -+- reset-names : Must include the following entries: "acodec-reset". -+ -+Optional properties: -+- rockchip,enable-all-adcs: This is a boolean type property, that shows whether -+ force enable all of ADCs. The following shows the relationship between grps -+ and ADC: -+ * grp 0 -- select ADC1 / ADC2 -+ * grp 1 -- select ADC3 / ADC4 -+ * grp 2 -- select ADC5 / ADC6 -+ * grp 3 -- select ADC7 / ADC8 -+ If the property is not used, the enabled ADC groups refer to needed channels -+ via configure hw_params. -+ -+- rockchip,adc-grps-route: This is a variable length array, that shows the -+ mapping route of ACODEC sdo to I2S sdi. By default, they are one-to-one -+ mapping: -+ * sdi_0 <-- sdo_0 -+ * sdi_1 <-- sdo_1 -+ * sdi_2 <-- sdo_2 -+ * sdi_3 <-- sdo_3 -+ If you would like to change the route mapping like this: -+ * sdi_0 <-- sdo_3 -+ * sdi_1 <-- sdo_0 -+ * sdi_2 <-- sdo_2 -+ * sdi_3 <-- sdo_1 -+ You need to add the property on dts: -+ - rockchip,adc-grps-route = <3 0 2 1>; -+ -+- rockchip,delay-loopback-handle-ms: This property points out that the delay for -+ handling ADC after enable PAs during loopback. -+- rockchip,delay-start-play-ms: This property points out the delay ms of start -+ playback according to different amplifier performance. -+- rockchip,en-always-grps: This property will keep the needed ADCs enabled -+ always after enabling once. -+- rockchip,loopback-grp: It points out the ADC group which is the loopback used. -+- rockchip,no-deep-low-power: The codec will not enter deep low power mode -+ during suspend. -+- rockchip,no-hp-det: If there is no headphone on boards, we don't need to -+ enable headphone detection. -+- rockchip,micbias1: Using internal micbias1 supply which are from codec. -+- rockchip,micbias2: Using internal micbias2 supply which are from codec. -+- rockchip,hp-jack-reversed;: To detect headphone via the reversed jack. -+- hp-ctl-gpios: The gpio of head phone controller. -+- pa-drv-gpios: The gpio of poweramplifier controller -+- rockchip,delay-pa-drv-ms: This property points out that the delay for -+ power on amplifier -+- spk-ctl-gpios: The gpio of speak controller. -+- micbias-en-gpios: The GPIO to enable external micbias. -+- vmicbias-supply: The phandle to the regulator to handle external micbias. -+ -+Example for rk3308 internal codec: -+ -+acodec: acodec@ff560000 { -+ compatible = "rockchip,rk3308-codec"; -+ reg = <0x0 0xff560000 0x0 0x10000>; -+ rockchip,grf = <&grf>; -+ clocks = <&cru PCLK_ACODEC>; -+ clock-names = "acodec"; -+ resets = <&cru SRST_ACODEC_P>; -+ reset-names = "acodec-reset"; -+ rockchip,loopback-grp = <0>; -+ hp-ctl-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; -+ pa-drv-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; -+ spk-ctl-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -index 106f09738dd0..815e22fc346c 100644 ---- a/sound/soc/codecs/rk3308_codec.c -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -29,1420 +29,4699 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include -+#include - #include - #include - - #include "rk3308_codec.h" -+#include "rk3308_codec_provider.h" -+ -+#if defined(CONFIG_DEBUG_FS) -+#include -+#include -+#include -+#endif -+ -+#define CODEC_DRV_NAME "rk3308-acodec" -+ -+#define ADC_GRP_SKIP_MAGIC 0x1001 -+#define ADC_LR_GROUP_MAX 4 -+#define ADC_STABLE_MS 200 -+#define DEBUG_POP_ALWAYS 0 -+#define HPDET_POLL_MS 2000 -+#define NOT_USED 255 -+#define LOOPBACK_HANDLE_MS 100 -+#define PA_DRV_MS 5 -+ -+#define GRF_SOC_CON1 0x304 -+#define GRF_CHIP_ID 0x800 -+#define GRF_I2S2_8CH_SDI_SFT 0 -+#define GRF_I2S3_4CH_SDI_SFT 8 -+#define GRF_I2S1_2CH_SDI_SFT 12 -+ -+#define GRF_I2S2_8CH_SDI_R_MSK(i, v) ((v >> (i * 2 + GRF_I2S2_8CH_SDI_SFT)) & 0x3) -+#define GRF_I2S2_8CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S2_8CH_SDI_SFT + 16)) -+#define GRF_I2S2_8CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S2_8CH_SDI_SFT)) |\ -+ GRF_I2S2_8CH_SDI_W_MSK(i)) -+ -+#define GRF_I2S3_4CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S3_4CH_SDI_SFT + 16)) -+#define GRF_I2S3_4CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S3_4CH_SDI_SFT)) |\ -+ GRF_I2S3_4CH_SDI_W_MSK(i)) -+ -+#define GRF_I2S1_2CH_SDI_W_MSK (0x3 << (GRF_I2S1_2CH_SDI_SFT + 16)) -+#define GRF_I2S1_2CH_SDI(v) (((v & 0x3) << GRF_I2S1_2CH_SDI_SFT) |\ -+ GRF_I2S1_2CH_SDI_W_MSK) -+ -+#define DETECT_GRF_ACODEC_HPDET_COUNTER 0x0030 -+#define DETECT_GRF_ACODEC_HPDET_CON 0x0034 -+#define DETECT_GRF_ACODEC_HPDET_STATUS 0x0038 -+#define DETECT_GRF_ACODEC_HPDET_STATUS_CLR 0x003c -+ -+/* 200ms based on pclk is 100MHz */ -+#define DEFAULT_HPDET_COUNT 20000000 -+#define HPDET_NEG_IRQ_SFT 1 -+#define HPDET_POS_IRQ_SFT 0 -+#define HPDET_BOTH_NEG_POS ((1 << HPDET_NEG_IRQ_SFT) |\ -+ (1 << HPDET_POS_IRQ_SFT)) -+ -+#define ACODEC_VERSION_A 0xa -+#define ACODEC_VERSION_B 0xb -+ -+enum { -+ ACODEC_TO_I2S2_8CH = 0, -+ ACODEC_TO_I2S3_4CH, -+ ACODEC_TO_I2S1_2CH, -+}; -+ -+enum { -+ ADC_GRP0_MICIN = 0, -+ ADC_GRP0_LINEIN -+}; -+ -+enum { -+ ADC_TYPE_NORMAL = 0, -+ ADC_TYPE_LOOPBACK, -+ ADC_TYPE_DBG, -+ ADC_TYPE_ALL, -+}; -+ -+enum { -+ DAC_LINEOUT = 0, -+ DAC_HPOUT = 1, -+ DAC_LINEOUT_HPOUT = 11, -+}; -+ -+enum { -+ EXT_MICBIAS_NONE = 0, -+ EXT_MICBIAS_FUNC1, /* enable external micbias via GPIO */ -+ EXT_MICBIAS_FUNC2, /* enable external micbias via regulator */ -+}; -+ -+enum { -+ PATH_IDLE = 0, -+ PATH_BUSY, -+}; -+ -+enum { -+ PM_NORMAL = 0, -+ PM_LLP_DOWN, /* light low power down */ -+ PM_LLP_UP, -+ PM_DLP_DOWN, /* deep low power down */ -+ PM_DLP_UP, -+ PM_DLP_DOWN2, -+ PM_DLP_UP2, -+}; - - struct rk3308_codec_priv { - const struct device *plat_dev; - struct device dev; - struct reset_control *reset; - struct regmap *regmap; -+ struct regmap *grf; -+ struct regmap *detect_grf; - struct clk *pclk; -+ struct clk *mclk_rx; -+ struct clk *mclk_tx; -+ struct gpio_desc *micbias_en_gpio; -+ struct gpio_desc *hp_ctl_gpio; - struct gpio_desc *spk_ctl_gpio; -- int adc_ch; /* To select ADCs for channel */ -- int adc_ch0_using_linein; -+ struct gpio_desc *pa_drv_gpio; -+ struct snd_soc_codec *codec; -+ struct snd_soc_jack *hpdet_jack; -+ struct regulator *vcc_micbias; -+ u32 codec_ver; -+ -+ /* -+ * To select ADCs for groups: -+ * -+ * grp 0 -- select ADC1 / ADC2 -+ * grp 1 -- select ADC3 / ADC4 -+ * grp 2 -- select ADC5 / ADC6 -+ * grp 3 -- select ADC7 / ADC8 -+ */ -+ u32 used_adc_grps; -+ /* The ADC group which is used for loop back */ -+ u32 loopback_grp; -+ u32 cur_dbg_grp; -+ u32 en_always_grps[ADC_LR_GROUP_MAX]; -+ u32 en_always_grps_num; -+ u32 skip_grps[ADC_LR_GROUP_MAX]; -+ u32 i2s_sdis[ADC_LR_GROUP_MAX]; -+ u32 to_i2s_grps; -+ u32 delay_loopback_handle_ms; -+ u32 delay_start_play_ms; -+ u32 delay_pa_drv_ms; -+ u32 micbias_num; -+ u32 micbias_volt; -+ int which_i2s; -+ int irq; -+ int adc_grp0_using_linein; -+ int adc_zerocross; -+ /* 0: line out, 1: hp out, 11: lineout and hpout */ -+ int dac_output; -+ int dac_path_state; -+ -+ int ext_micbias; -+ int pm_state; -+ -+ /* AGC L/R Off/on */ -+ unsigned int agc_l[ADC_LR_GROUP_MAX]; -+ unsigned int agc_r[ADC_LR_GROUP_MAX]; -+ -+ /* AGC L/R Approximate Sample Rate */ -+ unsigned int agc_asr_l[ADC_LR_GROUP_MAX]; -+ unsigned int agc_asr_r[ADC_LR_GROUP_MAX]; -+ -+ /* ADC MIC Mute/Work */ -+ unsigned int mic_mute_l[ADC_LR_GROUP_MAX]; -+ unsigned int mic_mute_r[ADC_LR_GROUP_MAX]; -+ -+ /* For the high pass filter */ -+ unsigned int hpf_cutoff[ADC_LR_GROUP_MAX]; -+ -+ /* Only hpout do fade-in and fade-out */ -+ unsigned int hpout_l_dgain; -+ unsigned int hpout_r_dgain; -+ -+ bool adc_grps_endisable[ADC_LR_GROUP_MAX]; -+ bool dac_endisable; -+ bool enable_all_adcs; -+ bool enable_micbias; -+ bool micbias1; -+ bool micbias2; -+ bool hp_jack_reversed; -+ bool hp_plugged; -+ bool loopback_dacs_enabled; -+ bool no_deep_low_power; -+ bool no_hp_det; -+ struct delayed_work hpdet_work; -+ struct delayed_work loopback_work; -+ -+#if defined(CONFIG_DEBUG_FS) -+ struct dentry *dbg_codec; -+#endif - }; - --static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_gain_tlv, -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_gain_tlv, - -1800, 150, 2850); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_max_gain_tlv, -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_max_gain_tlv, - -1350, 600, 2850); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_min_gain_tlv, -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_min_gain_tlv, - -1800, 600, 2400); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_mic_gain_tlv, -- 0, 600, 3000); - static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, - -1800, 150, 2850); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_gain_tlv, -- 0, 150, 600); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_lineout_gain_tlv, -+ -600, 150, 0); - static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, - -3900, 150, 600); - static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, - -600, 600, 0); - -+static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_a, -+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), -+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), -+); -+ -+static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_b, -+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), -+ 1, 1, TLV_DB_SCALE_ITEM(660, 0, 0), -+ 2, 2, TLV_DB_SCALE_ITEM(1300, 0, 0), -+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), -+); -+ -+static bool handle_loopback(struct rk3308_codec_priv *rk3308); -+ -+static int check_micbias(int micbias); -+ -+static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -+ int micbias); -+static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308); -+ -+static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+ -+static const char *offon_text[2] = { -+ [0] = "Off", -+ [1] = "On", -+}; -+ -+static const char *mute_text[2] = { -+ [0] = "Work", -+ [1] = "Mute", -+}; -+ -+/* ADC MICBIAS Volt */ -+#define MICBIAS_VOLT_NUM 8 -+ -+#define MICBIAS_VREFx0_5 0 -+#define MICBIAS_VREFx0_55 1 -+#define MICBIAS_VREFx0_6 2 -+#define MICBIAS_VREFx0_65 3 -+#define MICBIAS_VREFx0_7 4 -+#define MICBIAS_VREFx0_75 5 -+#define MICBIAS_VREFx0_8 6 -+#define MICBIAS_VREFx0_85 7 -+ -+static const char *micbias_volts_enum_array[MICBIAS_VOLT_NUM] = { -+ [MICBIAS_VREFx0_5] = "VREFx0_5", -+ [MICBIAS_VREFx0_55] = "VREFx0_55", -+ [MICBIAS_VREFx0_6] = "VREFx0_6", -+ [MICBIAS_VREFx0_65] = "VREFx0_65", -+ [MICBIAS_VREFx0_7] = "VREFx0_7", -+ [MICBIAS_VREFx0_75] = "VREFx0_75", -+ [MICBIAS_VREFx0_8] = "VREFx0_8", -+ [MICBIAS_VREFx0_85] = "VREFx0_85", -+}; -+ -+static const struct soc_enum rk3308_micbias_volts_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(micbias_volts_enum_array), micbias_volts_enum_array), -+}; -+ -+/* ADC MICBIAS1 and MICBIAS2 Main Switch */ -+static const struct soc_enum rk3308_main_micbias_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), -+}; -+ -+static const struct soc_enum rk3308_hpf_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text), -+}; -+ -+/* ALC AGC Switch */ -+static const struct soc_enum rk3308_agc_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(offon_text), offon_text), -+}; -+ -+/* ADC MIC Mute/Work Switch */ -+static const struct soc_enum rk3308_mic_mute_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(mute_text), mute_text), -+}; -+ -+/* ALC AGC Approximate Sample Rate */ -+#define AGC_ASR_NUM 8 -+ -+#define AGC_ASR_96KHZ 0 -+#define AGC_ASR_48KHZ 1 -+#define AGC_ASR_44_1KHZ 2 -+#define AGC_ASR_32KHZ 3 -+#define AGC_ASR_24KHZ 4 -+#define AGC_ASR_16KHZ 5 -+#define AGC_ASR_12KHZ 6 -+#define AGC_ASR_8KHZ 7 -+ -+static const char *agc_asr_text[AGC_ASR_NUM] = { -+ [AGC_ASR_96KHZ] = "96KHz", -+ [AGC_ASR_48KHZ] = "48KHz", -+ [AGC_ASR_44_1KHZ] = "44.1KHz", -+ [AGC_ASR_32KHZ] = "32KHz", -+ [AGC_ASR_24KHZ] = "24KHz", -+ [AGC_ASR_16KHZ] = "16KHz", -+ [AGC_ASR_12KHZ] = "12KHz", -+ [AGC_ASR_8KHZ] = "8KHz", -+}; -+ -+static const struct soc_enum rk3308_agc_asr_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+}; -+ -+static const struct snd_kcontrol_new mic_gains_a[] = { -+ /* ADC MIC */ -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+}; -+ -+static const struct snd_kcontrol_new mic_gains_b[] = { -+ /* ADC MIC */ -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+}; -+ - static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { -- /* ALC AGC Channel*/ -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Volume", -+ /* ALC AGC Group */ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Volume", - RK3308_ALC_L_DIG_CON03(0), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Volume", - RK3308_ALC_R_DIG_CON03(0), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Volume", -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Volume", - RK3308_ALC_L_DIG_CON03(1), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Volume", - RK3308_ALC_R_DIG_CON03(1), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Volume", -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Volume", - RK3308_ALC_L_DIG_CON03(2), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Volume", - RK3308_ALC_R_DIG_CON03(2), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Volume", -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Volume", - RK3308_ALC_L_DIG_CON03(3), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Volume", - RK3308_ALC_R_DIG_CON03(3), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), - - /* ALC AGC MAX */ -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Max Volume", -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Max Volume", - RK3308_ALC_L_DIG_CON09(0), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Max Volume", - RK3308_ALC_R_DIG_CON09(0), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Max Volume", -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Max Volume", - RK3308_ALC_L_DIG_CON09(1), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Max Volume", - RK3308_ALC_R_DIG_CON09(1), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Max Volume", -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Max Volume", - RK3308_ALC_L_DIG_CON09(2), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Max Volume", - RK3308_ALC_R_DIG_CON09(2), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Max Volume", -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Max Volume", - RK3308_ALC_L_DIG_CON09(3), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Max Volume", - RK3308_ALC_R_DIG_CON09(3), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), - - /* ALC AGC MIN */ -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Min Volume", -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Min Volume", - RK3308_ALC_L_DIG_CON09(0), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Min Volume", - RK3308_ALC_R_DIG_CON09(0), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Min Volume", -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Min Volume", - RK3308_ALC_L_DIG_CON09(1), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Min Volume", - RK3308_ALC_R_DIG_CON09(1), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Min Volume", -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Min Volume", - RK3308_ALC_L_DIG_CON09(2), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Min Volume", - RK3308_ALC_R_DIG_CON09(2), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Min Volume", -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Min Volume", - RK3308_ALC_L_DIG_CON09(3), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Min Volume", - RK3308_ALC_R_DIG_CON09(3), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- -- /* ADC MIC */ -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Left Volume", -- RK3308_ADC_ANA_CON01(0), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Right Volume", -- RK3308_ADC_ANA_CON01(0), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Left Volume", -- RK3308_ADC_ANA_CON01(1), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Right Volume", -- RK3308_ADC_ANA_CON01(1), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Left Volume", -- RK3308_ADC_ANA_CON01(2), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Right Volume", -- RK3308_ADC_ANA_CON01(2), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Left Volume", -- RK3308_ADC_ANA_CON01(3), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Right Volume", -- RK3308_ADC_ANA_CON01(3), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ /* ALC AGC Switch */ -+ SOC_ENUM_EXT("ALC AGC Group 0 Left Switch", rk3308_agc_enum_array[0], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 0 Right Switch", rk3308_agc_enum_array[1], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 1 Left Switch", rk3308_agc_enum_array[2], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 1 Right Switch", rk3308_agc_enum_array[3], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 2 Left Switch", rk3308_agc_enum_array[4], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 2 Right Switch", rk3308_agc_enum_array[5], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 3 Left Switch", rk3308_agc_enum_array[6], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 3 Right Switch", rk3308_agc_enum_array[7], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ -+ /* ALC AGC Approximate Sample Rate */ -+ SOC_ENUM_EXT("AGC Group 0 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[0], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 0 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[1], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 1 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[2], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 1 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[3], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 2 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[4], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 2 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[5], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 3 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[6], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 3 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[7], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ -+ /* ADC MICBIAS Voltage */ -+ SOC_ENUM_EXT("ADC MICBIAS Voltage", rk3308_micbias_volts_enum_array[0], -+ rk3308_codec_micbias_volts_get, rk3308_codec_micbias_volts_put), -+ -+ /* ADC Main MICBIAS Switch */ -+ SOC_ENUM_EXT("ADC Main MICBIAS", rk3308_main_micbias_enum_array[0], -+ rk3308_codec_main_micbias_get, rk3308_codec_main_micbias_put), -+ -+ /* ADC MICBIAS1 and MICBIAS2 Switch */ -+ SOC_SINGLE("ADC MICBIAS1", RK3308_ADC_ANA_CON07(1), -+ RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0), -+ SOC_SINGLE("ADC MICBIAS2", RK3308_ADC_ANA_CON07(2), -+ RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0), -+ -+ /* ADC MIC Mute/Work Switch */ -+ SOC_ENUM_EXT("ADC MIC Group 0 Left Switch", rk3308_mic_mute_enum_array[0], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 0 Right Switch", rk3308_mic_mute_enum_array[1], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 1 Left Switch", rk3308_mic_mute_enum_array[2], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 1 Right Switch", rk3308_mic_mute_enum_array[3], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 2 Left Switch", rk3308_mic_mute_enum_array[4], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 2 Right Switch", rk3308_mic_mute_enum_array[5], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 3 Left Switch", rk3308_mic_mute_enum_array[6], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 3 Right Switch", rk3308_mic_mute_enum_array[7], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), - - /* ADC ALC */ -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Left Volume", - RK3308_ADC_ANA_CON03(0), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Right Volume", - RK3308_ADC_ANA_CON04(0), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Left Volume", - RK3308_ADC_ANA_CON03(1), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Right Volume", - RK3308_ADC_ANA_CON04(1), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Left Volume", - RK3308_ADC_ANA_CON03(2), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Right Volume", - RK3308_ADC_ANA_CON04(2), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Left Volume", - RK3308_ADC_ANA_CON03(3), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Right Volume", - RK3308_ADC_ANA_CON04(3), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), - -- /* DAC */ -- SOC_SINGLE_RANGE_TLV("DAC Left Volume", -- RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_GAIN_SFT, -- RK3308_DAC_L_GAIN_0DB, -- RK3308_DAC_L_GAIN_PDB_6, -- 0, rk3308_codec_dac_gain_tlv), -- SOC_SINGLE_RANGE_TLV("DAC Right Volume", -- RK3308_DAC_ANA_CON04, -- RK3308_DAC_R_GAIN_SFT, -- RK3308_DAC_R_GAIN_0DB, -- RK3308_DAC_R_GAIN_PDB_6, -- 0, rk3308_codec_dac_gain_tlv), -+ /* ADC High Pass Filter */ -+ SOC_ENUM_EXT("ADC Group 0 HPF Cut-off", rk3308_hpf_enum_array[0], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ SOC_ENUM_EXT("ADC Group 1 HPF Cut-off", rk3308_hpf_enum_array[1], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ SOC_ENUM_EXT("ADC Group 2 HPF Cut-off", rk3308_hpf_enum_array[2], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ SOC_ENUM_EXT("ADC Group 3 HPF Cut-off", rk3308_hpf_enum_array[3], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ -+ /* DAC LINEOUT */ -+ SOC_SINGLE_TLV("DAC LINEOUT Left Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_GAIN_SFT, -+ RK3308_DAC_L_LINEOUT_GAIN_MAX, -+ 0, rk3308_codec_dac_lineout_gain_tlv), -+ SOC_SINGLE_TLV("DAC LINEOUT Right Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_R_LINEOUT_GAIN_SFT, -+ RK3308_DAC_R_LINEOUT_GAIN_MAX, -+ 0, rk3308_codec_dac_lineout_gain_tlv), - - /* DAC HPOUT */ -- SOC_SINGLE_RANGE_TLV("DAC HPOUT Left Volume", -- RK3308_DAC_ANA_CON05, -- RK3308_DAC_L_HPOUT_GAIN_SFT, -- RK3308_DAC_L_HPOUT_GAIN_NDB_39, -- RK3308_DAC_L_HPOUT_GAIN_PDB_6, -- 0, rk3308_codec_dac_hpout_gain_tlv), -- SOC_SINGLE_RANGE_TLV("DAC HPOUT Right Volume", -- RK3308_DAC_ANA_CON06, -- RK3308_DAC_R_HPOUT_GAIN_SFT, -- RK3308_DAC_R_HPOUT_GAIN_NDB_39, -- RK3308_DAC_R_HPOUT_GAIN_PDB_6, -- 0, rk3308_codec_dac_hpout_gain_tlv), -+ SOC_SINGLE_EXT_TLV("DAC HPOUT Left Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_SFT, -+ RK3308_DAC_L_HPOUT_GAIN_MAX, -+ 0, -+ rk3308_codec_hpout_l_get_tlv, -+ rk3308_codec_hpout_l_put_tlv, -+ rk3308_codec_dac_hpout_gain_tlv), -+ SOC_SINGLE_EXT_TLV("DAC HPOUT Right Volume", -+ RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_SFT, -+ RK3308_DAC_R_HPOUT_GAIN_MAX, -+ 0, -+ rk3308_codec_hpout_r_get_tlv, -+ rk3308_codec_hpout_r_put_tlv, -+ rk3308_codec_dac_hpout_gain_tlv), - - /* DAC HPMIX */ - SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume", -- RK3308_DAC_ANA_CON05, -+ RK3308_DAC_ANA_CON12, - RK3308_DAC_L_HPMIX_GAIN_SFT, -- RK3308_DAC_L_HPMIX_GAIN_NDB_6, -- RK3308_DAC_L_HPMIX_GAIN_0DB, -+ RK3308_DAC_L_HPMIX_GAIN_MIN, -+ RK3308_DAC_L_HPMIX_GAIN_MAX, - 0, rk3308_codec_dac_hpmix_gain_tlv), - SOC_SINGLE_RANGE_TLV("DAC HPMIX Right Volume", -- RK3308_DAC_ANA_CON05, -+ RK3308_DAC_ANA_CON12, - RK3308_DAC_R_HPMIX_GAIN_SFT, -- RK3308_DAC_R_HPMIX_GAIN_NDB_6, -- RK3308_DAC_R_HPMIX_GAIN_0DB, -+ RK3308_DAC_R_HPMIX_GAIN_MIN, -+ RK3308_DAC_R_HPMIX_GAIN_MAX, - 0, rk3308_codec_dac_hpmix_gain_tlv), - }; - --static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) -+static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- gpiod_direction_output(rk3308->spk_ctl_gpio, on); -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } -+ -+ if (e->shift_l) -+ ucontrol->value.integer.value[0] = rk3308->agc_r[e->reg]; -+ else -+ ucontrol->value.integer.value[0] = rk3308->agc_l[e->reg]; -+ -+ return 0; - } - --static int rk3308_codec_reset(struct snd_soc_codec *codec) -+static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.integer.value[0]; -+ int grp = e->reg; - -- reset_control_assert(rk3308->reset); -- usleep_range(200, 300); /* estimated value */ -- reset_control_deassert(rk3308->reset); -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } - -- regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); -- usleep_range(200, 300); /* estimated value */ -- regmap_write(rk3308->regmap, RK3308_GLB_CON, -- RK3308_SYS_WORK | -- RK3308_DAC_DIG_WORK | -- RK3308_ADC_DIG_WORK); -+ if (value) { -+ /* ALC AGC On */ -+ if (e->shift_l) { -+ /* ALC AGC Right On */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); -+ -+ rk3308->agc_r[e->reg] = 1; -+ } else { -+ /* ALC AGC Left On */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_EN); -+ -+ rk3308->agc_l[e->reg] = 1; -+ } -+ } else { -+ /* ALC AGC Off */ -+ if (e->shift_l) { -+ /* ALC AGC Right Off */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); -+ -+ rk3308->agc_r[e->reg] = 0; -+ } else { -+ /* ALC AGC Left Off */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS); -+ -+ rk3308->agc_l[e->reg] = 0; -+ } -+ } - - return 0; - } - --static int rk3308_set_bias_level(struct snd_soc_codec *codec, -- enum snd_soc_bias_level level) -+static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- switch (level) { -- case SND_SOC_BIAS_ON: -- break; -- -- case SND_SOC_BIAS_PREPARE: -- break; -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; - -- case SND_SOC_BIAS_STANDBY: -- case SND_SOC_BIAS_OFF: -- break; -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; - } - -- snd_soc_codec_force_bias_level(codec, level); -+ if (e->shift_l) { -+ regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON04(grp), &value); -+ rk3308->agc_asr_r[e->reg] = value >> RK3308_AGC_APPROX_RATE_SFT; -+ ucontrol->value.integer.value[0] = rk3308->agc_asr_r[e->reg]; -+ } else { -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp), &value); -+ rk3308->agc_asr_l[e->reg] = value >> RK3308_AGC_APPROX_RATE_SFT; -+ ucontrol->value.integer.value[0] = rk3308->agc_asr_l[e->reg]; -+ } - - return 0; - } - --static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -- unsigned int fmt) -+static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = codec_dai->codec; -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -- int ch = rk3308->adc_ch; -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; - -- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -- case SND_SOC_DAIFMT_CBS_CFS: -- adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; -- adc_aif2 |= RK3308_ADC_MODE_SLAVE; -- dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; -- dac_aif2 |= RK3308_DAC_MODE_SLAVE; -- break; -- case SND_SOC_DAIFMT_CBM_CFM: -- adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; -- adc_aif2 |= RK3308_ADC_MODE_MASTER; -- dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; -- dac_aif2 |= RK3308_DAC_MODE_MASTER; -- break; -- default: -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); - return -EINVAL; - } - -- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -- case SND_SOC_DAIFMT_DSP_A: -- adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; -- dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; -- break; -- case SND_SOC_DAIFMT_I2S: -- adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; -- dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; -- break; -- case SND_SOC_DAIFMT_RIGHT_J: -- adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -- dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; -- break; -- case SND_SOC_DAIFMT_LEFT_J: -- adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -- dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; -- break; -- default: -- return -EINVAL; -+ value = ucontrol->value.integer.value[0] << RK3308_AGC_APPROX_RATE_SFT; -+ -+ if (e->shift_l) { -+ /* ALC AGC Right Approximate Sample Rate */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(grp), -+ RK3308_AGC_APPROX_RATE_MSK, -+ value); -+ rk3308->agc_asr_r[e->reg] = ucontrol->value.integer.value[0]; -+ } else { -+ /* ALC AGC Left Approximate Sample Rate */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp), -+ RK3308_AGC_APPROX_RATE_MSK, -+ value); -+ rk3308->agc_asr_l[e->reg] = ucontrol->value.integer.value[0]; - } - -- switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -- case SND_SOC_DAIFMT_NB_NF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -- break; -- case SND_SOC_DAIFMT_IB_IF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -- break; -- case SND_SOC_DAIFMT_IB_NF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -- break; -- case SND_SOC_DAIFMT_NB_IF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -- break; -- default: -+ return 0; -+} -+ -+static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; -+ -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); - return -EINVAL; - } - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -- RK3308_ADC_I2S_LRC_POL_MSK | -- RK3308_ADC_I2S_MODE_MSK, -- adc_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -- RK3308_ADC_IO_MODE_MSK | -- RK3308_ADC_MODE_MSK | -- RK3308_ADC_I2S_BIT_CLK_POL_MSK, -- adc_aif2); -- -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -- RK3308_DAC_I2S_LRC_POL_MSK | -- RK3308_DAC_I2S_MODE_MSK, -- dac_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -- RK3308_DAC_IO_MODE_MSK | -- RK3308_DAC_MODE_MSK | -- RK3308_DAC_I2S_BIT_CLK_POL_MSK, -- dac_aif2); -+ if (e->shift_l) { -+ /* ADC MIC Right Mute/Work Infos */ -+ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value); -+ rk3308->mic_mute_r[e->reg] = (value & RK3308_ADC_R_CH_BIST_SINE) >> -+ RK3308_ADC_R_CH_BIST_SFT; -+ ucontrol->value.integer.value[0] = rk3308->mic_mute_r[e->reg]; -+ } else { -+ /* ADC MIC Left Mute/Work Infos */ -+ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value); -+ rk3308->mic_mute_l[e->reg] = (value & RK3308_ADC_L_CH_BIST_SINE) >> -+ RK3308_ADC_L_CH_BIST_SFT; -+ ucontrol->value.integer.value[0] = rk3308->mic_mute_l[e->reg]; -+ } - - return 0; - } - --static int rk3308_hw_params(struct snd_pcm_substream *substream, -- struct snd_pcm_hw_params *params, -- struct snd_soc_dai *dai) -+static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = dai->codec; -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -- int ch = rk3308->adc_ch; -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; - -- switch (params_format(params)) { -- case SNDRV_PCM_FORMAT_S16_LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; -- break; -- case SNDRV_PCM_FORMAT_S20_3LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; -- break; -- case SNDRV_PCM_FORMAT_S24_LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; -- break; -- case SNDRV_PCM_FORMAT_S32_LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; -- break; -- default: -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); - return -EINVAL; - } - -- switch (params_channels(params)) { -- case 1: -- adc_aif1 |= RK3308_ADC_I2S_MONO; -- break; -- case 2: -- adc_aif1 |= RK3308_ADC_I2S_STEREO; -- break; -- default: -- return -EINVAL; -+ if (e->shift_l) { -+ /* ADC MIC Right Mute/Work Configuration */ -+ value = ucontrol->value.integer.value[0] << RK3308_ADC_R_CH_BIST_SFT; -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_SINE, -+ value); -+ rk3308->mic_mute_r[e->reg] = ucontrol->value.integer.value[0]; -+ } else { -+ /* ADC MIC Left Mute/Work Configuration */ -+ value = ucontrol->value.integer.value[0] << RK3308_ADC_L_CH_BIST_SFT; -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_SINE, -+ value); -+ rk3308->mic_mute_l[e->reg] = ucontrol->value.integer.value[0]; - } - -- adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; -- adc_aif2 |= RK3308_ADC_I2S_WORK; -- dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; -- dac_aif2 |= RK3308_DAC_I2S_WORK; -+ return 0; -+} - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -- RK3308_ADC_I2S_VALID_LEN_MSK | -- RK3308_ADC_I2S_LR_MSK | -- RK3308_ADC_I2S_TYPE_MSK, -- adc_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -- RK3308_ADC_I2S_MSK, -- adc_aif2); -+static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -- RK3308_DAC_I2S_VALID_LEN_MSK | -- RK3308_DAC_I2S_LR_MSK, -- dac_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -- RK3308_DAC_I2S_MSK, -- dac_aif2); -+ ucontrol->value.integer.value[0] = rk3308->micbias_volt; - - return 0; - } - --static int rk3308_digital_mute(struct snd_soc_dai *dai, int mute) -+static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int volt = ucontrol->value.integer.value[0]; -+ int ret; -+ -+ ret = check_micbias(volt); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, "The invalid micbias volt: %d\n", -+ volt); -+ return ret; -+ } -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -+ volt); -+ -+ rk3308->micbias_volt = volt; -+ - return 0; - } - --static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) -+static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- /* Step 01 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -- RK3308_DAC_CURRENT_MSK, -- RK3308_DAC_CURRENT_EN); -- -- /* Step 02 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_BUF_REF_L_MSK | -- RK3308_DAC_BUF_REF_R_MSK, -- RK3308_DAC_BUF_REF_L_EN | -- RK3308_DAC_BUF_REF_R_EN); -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- /* Step 03 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_L_MSK | -- RK3308_DAC_POP_SOUND_R_MSK, -- RK3308_DAC_POP_SOUND_L_WORK | -- RK3308_DAC_POP_SOUND_R_WORK); -+ ucontrol->value.integer.value[0] = rk3308->enable_micbias; - -- /* Step 04 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -- RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN); -+ return 0; -+} - -- /* Step 05 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -- RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK); -+static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int on = ucontrol->value.integer.value[0]; -+ -+ if (on) { -+ if (!rk3308->enable_micbias) -+ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); -+ } else { -+ if (rk3308->enable_micbias) -+ rk3308_codec_micbias_disable(rk3308); -+ } - -- /* Step 06 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -- RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN); -+ return 0; -+} - -- /* Step 07 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -- RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN); -+static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ return snd_soc_get_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 08 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -- RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK); -+static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int gain = ucontrol->value.integer.value[0]; - -- /* Step 09 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -- RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN); -+ if (gain > RK3308_ADC_CH1_MIC_GAIN_MAX) { -+ dev_err(rk3308->plat_dev, "%s: invalid mic gain: %d\n", -+ __func__, gain); -+ return -EINVAL; -+ } - -- /* Step 10 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -- RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN); -+ if (rk3308->codec_ver == ACODEC_VERSION_A) { -+ /* -+ * From the TRM, there are only suupport 0dB(gain==0) and -+ * 20dB(gain==3) on the codec version A. -+ */ -+ if (!(gain == 0 || gain == RK3308_ADC_CH1_MIC_GAIN_MAX)) { -+ dev_err(rk3308->plat_dev, -+ "version A doesn't supported: %d, expect: 0,%d\n", -+ gain, RK3308_ADC_CH1_MIC_GAIN_MAX); -+ return 0; -+ } -+ } - -- /* Step 11 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); -+ return snd_soc_put_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 12 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -- RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK); -+static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; - -- /* Step 13 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_SEL_MSK | -- RK3308_DAC_R_HPMIX_SEL_MSK, -- RK3308_DAC_L_HPMIX_I2S | -- RK3308_DAC_R_HPMIX_I2S); -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } - -- /* Step 14 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_UNMUTE | -- RK3308_DAC_R_HPMIX_UNMUTE, -- RK3308_DAC_L_HPMIX_UNMUTE | -- RK3308_DAC_R_HPMIX_UNMUTE); -+ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), &value); -+ if (value & RK3308_ADC_HPF_PATH_MSK) -+ rk3308->hpf_cutoff[e->reg] = 0; -+ else -+ rk3308->hpf_cutoff[e->reg] = 1; - -- /* Step 15 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_GAIN_MSK | -- RK3308_DAC_R_HPMIX_GAIN_MSK, -- RK3308_DAC_L_HPMIX_GAIN_0DB | -- RK3308_DAC_R_HPMIX_GAIN_0DB); -+ ucontrol->value.integer.value[0] = rk3308->hpf_cutoff[e->reg]; - -- /* Step 16 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_UNMUTE | -- RK3308_DAC_R_HPOUT_UNMUTE, -- RK3308_DAC_L_HPOUT_UNMUTE | -- RK3308_DAC_R_HPOUT_UNMUTE); -+ return 0; -+} - -- /* Step 17 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_UNMUTE | -- RK3308_DAC_R_LINEOUT_UNMUTE, -- RK3308_DAC_L_LINEOUT_UNMUTE | -- RK3308_DAC_R_LINEOUT_UNMUTE); -+static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.integer.value[0]; - -- /* Step 18 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -- RK3308_DAC_L_HPOUT_GAIN_MSK, -- RK3308_DAC_L_HPOUT_GAIN_0DB); -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } - -- /* Step 18 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -- RK3308_DAC_R_HPOUT_GAIN_MSK, -- RK3308_DAC_R_HPOUT_GAIN_0DB); -+ if (value) { -+ /* Enable high pass filter for ADCs */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), -+ RK3308_ADC_HPF_PATH_MSK, -+ RK3308_ADC_HPF_PATH_EN); -+ } else { -+ /* Disable high pass filter for ADCs. */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), -+ RK3308_ADC_HPF_PATH_MSK, -+ RK3308_ADC_HPF_PATH_DIS); -+ } - -- /* Step 19 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -- RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -+ rk3308->hpf_cutoff[e->reg] = value; - - return 0; - } - --static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) -+static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- /* Step 01 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -- RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -- -- /* -- * Step 02 -- * -- * Note1. In the step2, adjusting the register step by step to the -- * appropriate value and taking 20ms as time step -- */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -- RK3308_DAC_L_HPOUT_GAIN_MSK, -- RK3308_DAC_L_HPOUT_GAIN_NDB_39); -- -- /* Step 02 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -- RK3308_DAC_R_HPOUT_GAIN_MSK, -- RK3308_DAC_R_HPOUT_GAIN_NDB_39); -+ return snd_soc_get_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 03 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_UNMUTE | -- RK3308_DAC_R_HPMIX_UNMUTE, -- RK3308_DAC_L_HPMIX_MUTE | -- RK3308_DAC_R_HPMIX_MUTE); -+static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int dgain = ucontrol->value.integer.value[0]; - -- /* Step 04 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_SEL_MSK | -- RK3308_DAC_R_HPMIX_SEL_MSK, -- RK3308_DAC_L_HPMIX_NONE | -- RK3308_DAC_R_HPMIX_NONE); -+ if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) { -+ dev_err(rk3308->plat_dev, "%s: invalid l_dgain: %d\n", -+ __func__, dgain); -+ return -EINVAL; -+ } - -- /* Step 05 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_UNMUTE | -- RK3308_DAC_R_HPOUT_UNMUTE, -- RK3308_DAC_L_HPOUT_MUTE | -- RK3308_DAC_R_HPOUT_MUTE); -+ rk3308->hpout_l_dgain = dgain; - -- /* Step 06 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -- RK3308_DAC_L_DAC_INIT | RK3308_DAC_R_DAC_INIT); -+ return snd_soc_put_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 07 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -- RK3308_DAC_L_HPOUT_DIS | RK3308_DAC_R_HPOUT_DIS); -+static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ return snd_soc_get_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 08 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_UNMUTE | -- RK3308_DAC_R_LINEOUT_UNMUTE, -- RK3308_DAC_L_LINEOUT_MUTE | -- RK3308_DAC_R_LINEOUT_MUTE); -+static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int dgain = ucontrol->value.integer.value[0]; - -- /* Step 09 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -- RK3308_DAC_L_LINEOUT_DIS | RK3308_DAC_R_LINEOUT_DIS); -+ if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) { -+ dev_err(rk3308->plat_dev, "%s: invalid r_dgain: %d\n", -+ __func__, dgain); -+ return -EINVAL; -+ } - -- /* Step 10 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -- RK3308_DAC_L_HPMIX_DIS | RK3308_DAC_R_HPMIX_DIS); -+ rk3308->hpout_r_dgain = dgain; - -- /* Step 11 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -- RK3308_DAC_L_DAC_DIS | RK3308_DAC_R_DAC_DIS); -+ return snd_soc_put_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 12 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -- RK3308_DAC_L_CLK_DIS | RK3308_DAC_R_CLK_DIS); -+static u32 to_mapped_grp(struct rk3308_codec_priv *rk3308, int idx) -+{ -+ return rk3308->i2s_sdis[idx]; -+} - -- /* Step 13 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -- RK3308_DAC_L_REF_DIS | RK3308_DAC_R_REF_DIS); -+static bool adc_for_each_grp(struct rk3308_codec_priv *rk3308, -+ int type, int idx, u32 *grp) -+{ -+ if (type == ADC_TYPE_NORMAL) { -+ u32 mapped_grp = to_mapped_grp(rk3308, idx); -+ int max_grps; -+ -+ if (rk3308->enable_all_adcs) -+ max_grps = ADC_LR_GROUP_MAX; -+ else -+ max_grps = rk3308->used_adc_grps; -+ -+ if (idx >= max_grps) -+ return false; -+ -+ if ((!rk3308->loopback_dacs_enabled) && -+ handle_loopback(rk3308) && -+ rk3308->loopback_grp == mapped_grp) { -+ /* -+ * Ths loopback DACs are closed, and specify the -+ * loopback ADCs. -+ */ -+ *grp = ADC_GRP_SKIP_MAGIC; -+ } else if (rk3308->en_always_grps_num && -+ rk3308->skip_grps[mapped_grp]) { -+ /* To set the skip flag if the ADC GRP is enabled. */ -+ *grp = ADC_GRP_SKIP_MAGIC; -+ } else { -+ *grp = mapped_grp; -+ } - -- /* Step 14 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_L_MSK | -- RK3308_DAC_POP_SOUND_R_MSK, -- RK3308_DAC_POP_SOUND_L_INIT | -- RK3308_DAC_POP_SOUND_R_INIT); -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_NORMAL, idx: %d, mapped_grp: %d, get grp: %d,\n", -+ idx, mapped_grp, *grp); -+ } else if (type == ADC_TYPE_ALL) { -+ if (idx >= ADC_LR_GROUP_MAX) -+ return false; -+ -+ *grp = idx; -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_ALL, idx: %d, get grp: %d\n", -+ idx, *grp); -+ } else if (type == ADC_TYPE_DBG) { -+ if (idx >= ADC_LR_GROUP_MAX) -+ return false; -+ -+ if (idx == (int)rk3308->cur_dbg_grp) -+ *grp = idx; -+ else -+ *grp = ADC_GRP_SKIP_MAGIC; -+ -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_DBG, idx: %d, get grp: %d\n", -+ idx, *grp); -+ } else { -+ if (idx >= 1) -+ return false; -+ -+ *grp = rk3308->loopback_grp; -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_LOOPBACK, idx: %d, get grp: %d\n", -+ idx, *grp); -+ } - -- /* Step 15 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_BUF_REF_L_EN | RK3308_DAC_BUF_REF_R_EN, -- RK3308_DAC_BUF_REF_L_DIS | RK3308_DAC_BUF_REF_R_DIS); -+ return true; -+} - -- /* Step 16 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -- RK3308_DAC_CURRENT_EN, -- RK3308_DAC_CURRENT_DIS); -+static int rk3308_codec_get_dac_path_state(struct rk3308_codec_priv *rk3308) -+{ -+ return rk3308->dac_path_state; -+} - -- /* Step 17 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -- RK3308_DAC_L_HPOUT_INIT | RK3308_DAC_R_HPOUT_INIT); -+static void rk3308_codec_set_dac_path_state(struct rk3308_codec_priv *rk3308, -+ int state) -+{ -+ rk3308->dac_path_state = state; -+} - -- /* Step 18 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -- RK3308_DAC_L_HPMIX_INIT | RK3308_DAC_R_HPMIX_INIT); -+static void rk3308_headphone_ctl(struct rk3308_codec_priv *rk3308, int on) -+{ -+ if (rk3308->hp_ctl_gpio) -+ gpiod_direction_output(rk3308->hp_ctl_gpio, on); -+} - -- /* Step 19 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_GAIN_MSK | -- RK3308_DAC_R_HPMIX_GAIN_MSK, -- RK3308_DAC_L_HPMIX_GAIN_NDB_6 | -- RK3308_DAC_R_HPMIX_GAIN_NDB_6); -+static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) -+{ -+ if (on) { -+ if (rk3308->pa_drv_gpio) { -+ gpiod_direction_output(rk3308->pa_drv_gpio, on); -+ msleep(rk3308->delay_pa_drv_ms); -+ } - -- /* -- * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -- * is set to 0x1, add the steps from the section Disable DAC -- * Configuration Standard Usage Flow after complete the step 19 -- */ -+ if (rk3308->spk_ctl_gpio) -+ gpiod_direction_output(rk3308->spk_ctl_gpio, on); -+ } else { -+ if (rk3308->spk_ctl_gpio) -+ gpiod_direction_output(rk3308->spk_ctl_gpio, on); - -- return 0; -+ if (rk3308->pa_drv_gpio) { -+ msleep(rk3308->delay_pa_drv_ms); -+ gpiod_direction_output(rk3308->pa_drv_gpio, on); -+ } -+ } - } - --static int rk3308_codec_power_on(struct snd_soc_codec *codec) -+static int rk3308_codec_reset(struct snd_soc_codec *codec) - { - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- /* 1. Supply the power of digital part and reset the Audio Codec */ -- /* Do nothing */ -+ reset_control_assert(rk3308->reset); -+ usleep_range(2000, 2500); /* estimated value */ -+ reset_control_deassert(rk3308->reset); - -- /* -- * 2. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] -- * to 0x1, to setup dc voltage of the DAC channel output -- */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_L_MSK, RK3308_DAC_POP_SOUND_L_INIT); -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_R_MSK, RK3308_DAC_POP_SOUND_R_INIT); -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); -+ usleep_range(200, 300); /* estimated value */ -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_SYS_WORK | -+ RK3308_DAC_DIG_WORK | -+ RK3308_ADC_DIG_WORK); - -- /* -- * 3. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 -- * -- * Note: Only the reg (ADC_ANA_CON10+0x0)[6:0] represent the control -- * signal to select current to pre-charge/dis_charge -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ return 0; -+} - -- /* 4. Supply the power of the analog part(AVDD,AVDDRV) */ -+static int rk3308_codec_adc_dig_reset(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_RESET); -+ udelay(50); -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_WORK); - -- /* -- * 5. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup -- * reference voltage -- * -- * Note: Only the reg (ADC_ANA_CON10+0x0)[7] represent the enable -- * signal of reference voltage module -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); -+ return 0; -+} - -- /* -- * 6. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to -- * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to -- * 0x7f directly. The suggestion slot time of the step is 20ms. -- */ -- mdelay(20); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, -- RK3308_ADC_DONT_SEL_ALL); -+static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_DIG_WORK, -+ RK3308_DAC_DIG_RESET); -+ udelay(50); -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_DIG_WORK, -+ RK3308_DAC_DIG_WORK); - -- /* 7. Wait until the voltage of VCM keeps stable at the AVDD/2 */ -- usleep_range(200, 300); /* estimated value */ -+ return 0; -+} - -- /* -- * 8. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the -- * appropriate value(expect 0x0) for reducing power. -- */ -+static int rk3308_set_bias_level(struct snd_soc_codec *codec, -+ enum snd_soc_bias_level level) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- /* TODO: choose an appropriate charge value */ -+ switch (level) { -+ case SND_SOC_BIAS_ON: -+ break; -+ case SND_SOC_BIAS_PREPARE: -+ break; -+ case SND_SOC_BIAS_STANDBY: -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ break; -+ case SND_SOC_BIAS_OFF: -+ break; -+ } - - return 0; - } - --static int rk3308_codec_power_off(struct snd_soc_codec *codec) -+static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -+ unsigned int fmt) - { -+ struct snd_soc_codec *codec = codec_dai->codec; - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -+ int idx, grp, is_master; -+ int type = ADC_TYPE_ALL; -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; -+ adc_aif2 |= RK3308_ADC_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_MODE_SLAVE; -+ is_master = 0; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; -+ adc_aif2 |= RK3308_ADC_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_MODE_MASTER; -+ is_master = 1; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_DSP_A: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_LJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ default: -+ return -EINVAL; -+ } - - /* -- * 1. Keep the power on and disable the DAC and ADC path according to -- * the section power on configuration standard usage flow. -+ * Hold ADC Digital registers start at master mode -+ * -+ * There are 8 ADCs and use the same SCLK and LRCK internal for master -+ * mode, We need to make sure that they are in effect at the same time, -+ * otherwise they will cause the abnormal clocks. - */ -+ if (is_master) -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_RESET); -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), -+ RK3308_ADC_I2S_LRC_POL_MSK | -+ RK3308_ADC_I2S_MODE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), -+ RK3308_ADC_IO_MODE_MSK | -+ RK3308_ADC_MODE_MSK | -+ RK3308_ADC_I2S_BIT_CLK_POL_MSK, -+ adc_aif2); -+ } - -- /* 2. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ /* Hold ADC Digital registers end at master mode */ -+ if (is_master) -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_WORK); - -- /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_REF_EN, RK3308_ADC_REF_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_LRC_POL_MSK | -+ RK3308_DAC_I2S_MODE_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_IO_MODE_MSK | -+ RK3308_DAC_MODE_MSK | -+ RK3308_DAC_I2S_BIT_CLK_POL_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308, -+ struct snd_pcm_hw_params *params) -+{ -+ unsigned int dac_aif1 = 0, dac_aif2 = 0; -+ -+ /* Clear the status of DAC DIG Digital reigisters */ -+ rk3308_codec_dac_dig_reset(rk3308); -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_WORK; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_VALID_LEN_MSK | -+ RK3308_DAC_I2S_LR_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_I2S_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308, -+ struct snd_pcm_hw_params *params) -+{ -+ unsigned int adc_aif1 = 0, adc_aif2 = 0; -+ int type = ADC_TYPE_NORMAL; -+ int idx, grp; -+ -+ /* Clear the status of ADC DIG Digital reigisters */ -+ rk3308_codec_adc_dig_reset(rk3308); -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 1: -+ adc_aif1 |= RK3308_ADC_I2S_MONO; -+ break; -+ case 2: -+ case 4: -+ case 6: -+ case 8: -+ adc_aif1 |= RK3308_ADC_I2S_STEREO; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_WORK; -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), -+ RK3308_ADC_I2S_VALID_LEN_MSK | -+ RK3308_ADC_I2S_LR_MSK | -+ RK3308_ADC_I2S_TYPE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), -+ RK3308_ADC_I2S_MSK, -+ adc_aif2); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_update_adc_grps(struct rk3308_codec_priv *rk3308, -+ struct snd_pcm_hw_params *params) -+{ -+ switch (params_channels(params)) { -+ case 1: -+ rk3308->used_adc_grps = 1; -+ break; -+ case 2: -+ case 4: -+ case 6: -+ case 8: -+ rk3308->used_adc_grps = params_channels(params) / 2; -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Invalid channels: %d\n", -+ params_channels(params)); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ int dgain; -+ -+ if (mute) { -+ for (dgain = 0x2; dgain <= 0x7; dgain++) { -+ /* -+ * Keep the max -> min digital CIC interpolation -+ * filter gain step by step. -+ * -+ * loud: 0x2; whisper: 0x7 -+ */ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_DAC_DIG_CON04, -+ RK3308_DAC_CIC_IF_GAIN_MSK, -+ dgain); -+ usleep_range(200, 300); /* estimated value */ -+ } -+ -+#if !DEBUG_POP_ALWAYS -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 0); -+#endif -+ } else { -+#if !DEBUG_POP_ALWAYS -+ if (rk3308->dac_output == DAC_LINEOUT) -+ rk3308_speaker_ctl(rk3308, 1); -+ else if (rk3308->dac_output == DAC_HPOUT) -+ rk3308_headphone_ctl(rk3308, 1); -+ -+ if (rk3308->delay_start_play_ms) -+ msleep(rk3308->delay_start_play_ms); -+#endif -+ for (dgain = 0x7; dgain >= 0x2; dgain--) { -+ /* -+ * Keep the min -> max digital CIC interpolation -+ * filter gain step by step -+ * -+ * loud: 0x2; whisper: 0x7 -+ */ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_DAC_DIG_CON04, -+ RK3308_DAC_CIC_IF_GAIN_MSK, -+ dgain); -+ usleep_range(200, 300); /* estimated value */ -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_digital_fadein(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int dgain, dgain_ref; -+ -+ if (rk3308->hpout_l_dgain != rk3308->hpout_r_dgain) { -+ pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n", -+ rk3308->hpout_l_dgain, rk3308->hpout_r_dgain); -+ dgain_ref = min(rk3308->hpout_l_dgain, rk3308->hpout_r_dgain); -+ } else { -+ dgain_ref = rk3308->hpout_l_dgain; -+ } - - /* -- * 4.Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f -- * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f -- * directly. The suggestion slot time of the step is 20ms -+ * We'd better change the gain of the left and right channels -+ * at the same time to avoid different listening - */ -- mdelay(20); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, -- RK3308_ADC_DONT_SEL_ALL); -+ for (dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39; -+ dgain <= dgain_ref; dgain++) { -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ dgain); -+ -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ dgain); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_digital_fadeout(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int l_dgain, r_dgain; -+ -+ /* -+ * Note. In the step2, adjusting the register step by step to -+ * the appropriate value and taking 20ms as time step -+ */ -+ regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON05, &l_dgain); -+ l_dgain &= RK3308_DAC_L_HPOUT_GAIN_MSK; -+ -+ regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON06, &r_dgain); -+ r_dgain &= RK3308_DAC_R_HPOUT_GAIN_MSK; -+ -+ if (l_dgain != r_dgain) { -+ pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n", -+ l_dgain, r_dgain); -+ l_dgain = min(l_dgain, r_dgain); -+ } -+ -+ /* -+ * We'd better change the gain of the left and right channels -+ * at the same time to avoid different listening -+ */ -+ while (l_dgain >= RK3308_DAC_L_HPOUT_GAIN_NDB_39) { -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ l_dgain); -+ -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ l_dgain); -+ -+ usleep_range(200, 300); /* estimated value */ -+ -+ if (l_dgain == RK3308_DAC_L_HPOUT_GAIN_NDB_39) -+ break; -+ -+ l_dgain--; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_lineout_enable(struct rk3308_codec_priv *rk3308) -+{ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_DC_FROM_INTERNAL); -+ } -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN); -+ -+ udelay(20); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL); -+ -+ udelay(20); -+ } -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE); -+ udelay(20); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_lineout_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_MUTE | -+ RK3308_DAC_R_LINEOUT_MUTE); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_DIS | -+ RK3308_DAC_R_LINEOUT_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_hpout_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_WORK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_WORK); -+ -+ udelay(20); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN); -+ -+ udelay(20); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK); -+ -+ udelay(20); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE); -+ -+ udelay(20); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_hpout_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_INIT | -+ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_DIS | -+ RK3308_DAC_R_HPOUT_DIS); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_INIT | -+ RK3308_DAC_R_HPOUT_INIT); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_MUTE | -+ RK3308_DAC_R_HPOUT_MUTE); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_switch(struct rk3308_codec_priv *rk3308, -+ int dac_output) -+{ int ret = 0; -+ -+ if (rk3308->dac_output == dac_output) { -+ dev_info(rk3308->plat_dev, -+ "Don't need to change dac_output: %d\n", dac_output); -+ goto out; -+ } -+ -+ switch (dac_output) { -+ case DAC_LINEOUT: -+ case DAC_HPOUT: -+ case DAC_LINEOUT_HPOUT: -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Unknown value: %d\n", dac_output); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (rk3308_codec_get_dac_path_state(rk3308) == PATH_BUSY) { -+ /* -+ * We can only switch the audio path to LINEOUT or HPOUT on -+ * codec during playbacking, otherwise, just update the -+ * dac_output flag. -+ */ -+ switch (dac_output) { -+ case DAC_LINEOUT: -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 1); -+ rk3308_codec_dac_hpout_disable(rk3308); -+ rk3308_codec_dac_lineout_enable(rk3308); -+ break; -+ case DAC_HPOUT: -+ rk3308_speaker_ctl(rk3308, 0); -+ rk3308_headphone_ctl(rk3308, 1); -+ rk3308_codec_dac_lineout_disable(rk3308); -+ rk3308_codec_dac_hpout_enable(rk3308); -+ break; -+ case DAC_LINEOUT_HPOUT: -+ rk3308_speaker_ctl(rk3308, 1); -+ rk3308_headphone_ctl(rk3308, 1); -+ rk3308_codec_dac_lineout_enable(rk3308); -+ rk3308_codec_dac_hpout_enable(rk3308); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ rk3308->dac_output = dac_output; -+out: -+ dev_dbg(rk3308->plat_dev, "switch dac_output to: %d\n", -+ rk3308->dac_output); -+ -+ return ret; -+} -+ -+static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Note1. If the ACODEC_DAC_ANA_CON12[6] or ACODEC_DAC_ANA_CON12[2] -+ * is set to 0x1, ignoring the step9~12. -+ */ -+ -+ /* -+ * Note2. If the ACODEC_ DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -+ * is set to 0x1, the ADC0 or ADC1 should be enabled firstly, and -+ * please refer to Enable ADC Configuration Standard Usage Flow(expect -+ * step7~step9,step14). -+ */ -+ -+ /* -+ * Note3. If no opening the line out, ignoring the step6, step17 and -+ * step19. -+ */ -+ -+ /* -+ * Note4. If no opening the headphone out, ignoring the step3,step7~8, -+ * step16 and step18. -+ */ -+ -+ /* -+ * Note5. In the step18, adjust the register step by step to the -+ * appropriate value and taking 10ms as one time step -+ */ -+ -+ /* -+ * 1. Set the ACODEC_DAC_ANA_CON0[0] to 0x1, to enable the current -+ * source of DAC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_MSK, -+ RK3308_DAC_CURRENT_EN); -+ -+ udelay(20); -+ -+ /* -+ * 2. Set the ACODEC_DAC_ANA_CON1[6] and ACODEC_DAC_ANA_CON1[2] to 0x1, -+ * to enable the reference voltage buffer -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_MSK | -+ RK3308_DAC_BUF_REF_R_MSK, -+ RK3308_DAC_BUF_REF_L_EN | -+ RK3308_DAC_BUF_REF_R_EN); -+ -+ /* Waiting the stable reference voltage */ -+ mdelay(1); -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_WORK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_WORK); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B && -+ (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT)) { -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_DC_FROM_INTERNAL); -+ -+ udelay(20); -+ } -+ -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | -+ RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_EN | -+ RK3308_DAC_R_HPMIX_EN); -+ -+ /* Waiting the stable HPMIX */ -+ mdelay(1); -+ -+ /* Step 06. Reset HPMIX and recover HPMIX gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_INIT | -+ RK3308_DAC_R_HPMIX_INIT); -+ udelay(50); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK); -+ -+ udelay(20); -+ -+ if (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN); -+ -+ udelay(20); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL); -+ -+ udelay(20); -+ } -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | -+ RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_EN | -+ RK3308_DAC_R_REF_EN); -+ -+ udelay(20); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | -+ RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_EN | -+ RK3308_DAC_R_CLK_EN); -+ -+ udelay(20); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | -+ RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_EN | -+ RK3308_DAC_R_DAC_EN); -+ -+ udelay(20); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | -+ RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_WORK | -+ RK3308_DAC_R_DAC_WORK); -+ -+ udelay(20); -+ -+ /* Step 15 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_I2S | -+ RK3308_DAC_R_HPMIX_I2S); -+ -+ udelay(20); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE); -+ -+ udelay(20); -+ -+ /* Step 17: Put configuration HPMIX Gain to DAPM */ -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE); -+ udelay(20); -+ } -+ -+ /* Step 20, put configuration HPOUT gain to DAPM control */ -+ /* Step 21, put configuration LINEOUT gain to DAPM control */ -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Just for HPOUT */ -+ rk3308_codec_digital_fadein(rk3308); -+ } -+ -+ rk3308->dac_endisable = true; -+ -+ /* TODO: TRY TO TEST DRIVE STRENGTH */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Step 00 skipped. Keep the DAC channel work and input the mute signal. -+ */ -+ -+ /* Step 01 skipped. May set the min gain for LINEOUT. */ -+ -+ /* Step 02 skipped. May set the min gain for HPOUT. */ -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Just for HPOUT */ -+ rk3308_codec_digital_fadeout(rk3308); -+ } -+ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE); -+ -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_NONE | -+ RK3308_DAC_R_HPMIX_NONE); -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_MUTE | -+ RK3308_DAC_R_HPOUT_MUTE); -+ -+ /* Step 06 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | -+ RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_INIT | -+ RK3308_DAC_R_DAC_INIT); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_DIS | -+ RK3308_DAC_R_HPOUT_DIS); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_MUTE | -+ RK3308_DAC_R_LINEOUT_MUTE); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_DIS | -+ RK3308_DAC_R_LINEOUT_DIS); -+ -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | -+ RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_DIS | -+ RK3308_DAC_R_HPMIX_DIS); -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | -+ RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_DIS | -+ RK3308_DAC_R_DAC_DIS); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | -+ RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_DIS | -+ RK3308_DAC_R_CLK_DIS); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | -+ RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_DIS | -+ RK3308_DAC_R_REF_DIS); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_INIT | -+ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); -+ -+ /* Step 15 */ -+ if (rk3308->codec_ver == ACODEC_VERSION_B && -+ (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT)) { -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_VCM | -+ RK3308_DAC_R_SEL_DC_FROM_VCM); -+ } -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_EN | -+ RK3308_DAC_BUF_REF_R_EN, -+ RK3308_DAC_BUF_REF_L_DIS | -+ RK3308_DAC_BUF_REF_R_DIS); -+ -+ /* Step 17 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_EN, -+ RK3308_DAC_CURRENT_DIS); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_INIT | -+ RK3308_DAC_R_HPOUT_INIT); -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK); -+ -+ /* Step 20 skipped, may set the min gain for HPOUT. */ -+ -+ /* -+ * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -+ * is set to 0x1, add the steps from the section Disable ADC -+ * Configuration Standard Usage Flow after complete the step 19 -+ * -+ * IF USING LINE-IN -+ * rk3308_codec_adc_ana_disable(rk3308, type); -+ */ -+ -+ rk3308->dac_endisable = false; -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_on(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int v; -+ -+ /* 0. Supply the power of digital part and reset the Audio Codec */ -+ /* Do nothing */ -+ -+ /* -+ * 1. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] -+ * to 0x1, to setup dc voltage of the DAC channel output. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_INIT); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 2. Configure ACODEC_DAC_ANA_CON15[1:0] and -+ * ACODEC_DAC_ANA_CON15[5:4] to 0x1, to setup dc voltage of -+ * the DAC channel output. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_VCM); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_R_SEL_DC_FROM_VCM); -+ } -+ -+ /* -+ * 3. Configure the register ACODEC_ADC_ANA_CON10[3:0] to 7’b000_0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_SEL_I(0x1)); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 4. Configure the register ACODEC_ADC_ANA_CON14[3:0] to -+ * 4’b0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, -+ RK3308_DAC_SEL_I(0x1)); -+ } -+ -+ /* 5. Supply the power of the analog part(AVDD,AVDDRV) */ -+ -+ /* -+ * 6. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup -+ * reference voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 7. Configure the register ACODEC_ADC_ANA_CON14[4] to 0x1 to -+ * setup reference voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_VCM_LINEOUT_EN, -+ RK3308_DAC_VCM_LINEOUT_EN); -+ } -+ -+ /* -+ * 8. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to -+ * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to -+ * 0x7f directly. Here the slot time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0x7f; v++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 9. Change the register ACODEC_ADC_ANA_CON14[3:0] from the 0x1 -+ * to 0xf step by step or configure the -+ * ACODEC_ADC_ANA_CON14[3:0] to 0xf directly. Here the slot -+ * time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0xf; v++) { -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ } -+ -+ /* 10. Wait until the voltage of VCM keeps stable at the AVDD/2 */ -+ msleep(20); /* estimated value */ -+ -+ /* -+ * 11. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the -+ * appropriate value(expect 0x0) for reducing power. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, 0x7c); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 12. Configure the register ACODEC_DAC_ANA_CON14[6:0] to the -+ * appropriate value(expect 0x0) for reducing power. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, 0xf); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_off(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int v; -+ -+ /* -+ * 0. Keep the power on and disable the DAC and ADC path according to -+ * the section power on configuration standard usage flow. -+ */ -+ -+ /* -+ * 1. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 7’b000_0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_SEL_I(0x1)); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 2. Configure the register ACODEC_DAC_ANA_CON14[3:0] to -+ * 4’b0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, -+ RK3308_DAC_SEL_I(0x1)); -+ } -+ -+ /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, -+ RK3308_ADC_REF_DIS); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* 4. Configure the register ACODEC_DAC_ANA_CON14[7] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_VCM_LINEOUT_EN, -+ RK3308_DAC_VCM_LINEOUT_DIS); -+ } -+ -+ /* -+ * 5. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f -+ * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f -+ * directly. Here the slot time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0x7f; v++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 6. Change the register ACODEC_DAC_ANA_CON14[3:0] from the 0x1 -+ * to 0xf step by step or configure the -+ * ACODEC_DAC_ANA_CON14[3:0] to 0xf directly. Here the slot -+ * time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0x7f; v++) { -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ } -+ -+ /* 7. Wait until the voltage of VCM keeps stable at the AGND */ -+ msleep(20); /* estimated value */ -+ -+ /* 8. Power off the analog power supply */ -+ /* 9. Power off the digital power supply */ -+ -+ /* Do something via hardware */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_headset_detect_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Set ACODEC_DAC_ANA_CON0[1] to 0x1, to enable the headset insert -+ * detection -+ * -+ * Note. When the voltage of PAD HPDET> 8*AVDD/9, the output value of -+ * the pin_hpdet will be set to 0x1 and assert a interrupt -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_HEADPHONE_DET_MSK, -+ RK3308_DAC_HEADPHONE_DET_EN); -+ -+ return 0; -+} -+ -+static int rk3308_codec_headset_detect_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Set ACODEC_DAC_ANA_CON0[1] to 0x0, to disable the headset insert -+ * detection -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_HEADPHONE_DET_MSK, -+ RK3308_DAC_HEADPHONE_DET_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_check_i2s_sdis(struct rk3308_codec_priv *rk3308, -+ int num) -+{ -+ int i, j, ret = 0; -+ -+ switch (num) { -+ case 1: -+ rk3308->which_i2s = ACODEC_TO_I2S1_2CH; -+ break; -+ case 2: -+ rk3308->which_i2s = ACODEC_TO_I2S3_4CH; -+ break; -+ case 4: -+ rk3308->which_i2s = ACODEC_TO_I2S2_8CH; -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Invalid i2s sdis num: %d\n", num); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ for (i = 0; i < num; i++) { -+ if (rk3308->i2s_sdis[i] > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "i2s_sdis[%d]: %d is overflow\n", -+ i, rk3308->i2s_sdis[i]); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ for (j = 0; j < num; j++) { -+ if (i == j) -+ continue; -+ -+ if (rk3308->i2s_sdis[i] == rk3308->i2s_sdis[j]) { -+ dev_err(rk3308->plat_dev, -+ "Invalid i2s_sdis: [%d]%d == [%d]%d\n", -+ i, rk3308->i2s_sdis[i], -+ j, rk3308->i2s_sdis[j]); -+ ret = -EINVAL; -+ goto err; -+ } -+ } -+ } -+ -+err: -+ return ret; -+} -+ -+static int rk3308_codec_adc_grps_route_config(struct rk3308_codec_priv *rk3308) -+{ -+ int idx = 0; -+ -+ if (rk3308->which_i2s == ACODEC_TO_I2S2_8CH) { -+ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S2_8CH_SDI(idx, rk3308->i2s_sdis[idx])); -+ } -+ } else if (rk3308->which_i2s == ACODEC_TO_I2S3_4CH) { -+ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S3_4CH_SDI(idx, rk3308->i2s_sdis[idx])); -+ } -+ } else if (rk3308->which_i2s == ACODEC_TO_I2S1_2CH) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S1_2CH_SDI(rk3308->i2s_sdis[idx])); -+ } -+ -+ return 0; -+} -+ -+/* Put default one-to-one mapping */ -+static int rk3308_codec_adc_grps_route_default(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int idx; -+ -+ /* -+ * The GRF values may be kept the previous status after hot reboot, -+ * if the property 'rockchip,adc-grps-route' is not set, we need to -+ * recover default the order of sdi/sdo for i2s2_8ch/i2s3_8ch/i2s1_2ch. -+ */ -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S1_2CH_SDI(0)); -+ -+ for (idx = 0; idx < 2; idx++) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S3_4CH_SDI(idx, idx)); -+ } -+ -+ /* Using i2s2_8ch by default. */ -+ rk3308->which_i2s = ACODEC_TO_I2S2_8CH; -+ rk3308->to_i2s_grps = ADC_LR_GROUP_MAX; -+ -+ for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) { -+ rk3308->i2s_sdis[idx] = idx; -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S2_8CH_SDI(idx, idx)); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_grps_route(struct rk3308_codec_priv *rk3308, -+ struct device_node *np) -+{ -+ int num, ret; -+ -+ num = of_count_phandle_with_args(np, "rockchip,adc-grps-route", NULL); -+ if (num < 0) { -+ if (num == -ENOENT) { -+ /* Not use 'rockchip,adc-grps-route' property here */ -+ rk3308_codec_adc_grps_route_default(rk3308); -+ ret = 0; -+ } else { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,adc-grps-route' num: %d\n", -+ num); -+ ret = num; -+ } -+ return ret; -+ } -+ -+ ret = of_property_read_u32_array(np, "rockchip,adc-grps-route", -+ rk3308->i2s_sdis, num); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,adc-grps-route': %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_check_i2s_sdis(rk3308, num); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to check i2s_sdis: %d\n", ret); -+ return ret; -+ } -+ -+ rk3308->to_i2s_grps = num; -+ -+ rk3308_codec_adc_grps_route_config(rk3308); -+ -+ return 0; -+} -+ -+static int check_micbias(int micbias) -+{ -+ switch (micbias) { -+ case RK3308_ADC_MICBIAS_VOLT_0_85: -+ case RK3308_ADC_MICBIAS_VOLT_0_8: -+ case RK3308_ADC_MICBIAS_VOLT_0_75: -+ case RK3308_ADC_MICBIAS_VOLT_0_7: -+ case RK3308_ADC_MICBIAS_VOLT_0_65: -+ case RK3308_ADC_MICBIAS_VOLT_0_6: -+ case RK3308_ADC_MICBIAS_VOLT_0_55: -+ case RK3308_ADC_MICBIAS_VOLT_0_5: -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static bool handle_loopback(struct rk3308_codec_priv *rk3308) -+{ -+ /* The version B doesn't need to handle loopback. */ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) -+ return false; -+ -+ switch (rk3308->loopback_grp) { -+ case 0: -+ case 1: -+ case 2: -+ case 3: -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool has_en_always_grps(struct rk3308_codec_priv *rk3308) -+{ -+ int idx; -+ -+ if (rk3308->en_always_grps_num) { -+ for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) { -+ if (rk3308->en_always_grps[idx] >= 0 && -+ rk3308->en_always_grps[idx] <= ADC_LR_GROUP_MAX - 1) -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -+ int micbias) -+{ -+ int ret; -+ -+ if (rk3308->ext_micbias != EXT_MICBIAS_NONE) -+ return 0; -+ -+ /* 0. Power up the ACODEC and keep the AVDDH stable */ -+ -+ /* Step 1. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ -+ ret = check_micbias(micbias); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", -+ micbias); -+ return ret; -+ } -+ -+ /* -+ * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range -+ * control signal of MICBIAS voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -+ micbias); -+ -+ /* Step 2. Wait until the VCMH keep stable */ -+ msleep(20); /* estimated value */ -+ -+ /* -+ * Step 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 -+ * -+ * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable -+ * signal of current source for MICBIAS -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_EN); -+ -+ /* -+ * Step 4. Configure the (ADC_ANA_CON7+0x40)[3] or -+ * (ADC_ANA_CON7+0x80)[3] to 0x1. -+ * -+ * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and -+ * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 -+ */ -+ if (rk3308->micbias1) -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_EN); -+ -+ if (rk3308->micbias2) -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_EN); -+ -+ /* waiting micbias stabled*/ -+ mdelay(50); -+ -+ rk3308->enable_micbias = true; -+ -+ return 0; -+} -+ -+static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) -+{ -+ if (rk3308->ext_micbias != EXT_MICBIAS_NONE) -+ return 0; -+ -+ /* Step 0. Enable the MICBIAS and keep the Audio Codec stable */ -+ /* Do nothing */ -+ -+ /* -+ * Step 1. Configure the (ADC_ANA_CON7+0x40)[3] or -+ * (ADC_ANA_CON7+0x80)[3] to 0x0 -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_DIS); -+ -+ /* -+ * Step 2. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 -+ * -+ * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable -+ * signal of current source for MICBIAS -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_DIS); -+ -+ rk3308->enable_micbias = false; -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308, -+ int type) -+{ -+ int idx, grp; -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_INIT | -+ RK3308_ADC_CH2_ADC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 2 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_INIT | -+ RK3308_ADC_CH2_ALC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 3 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_INIT | -+ RK3308_ADC_CH2_MIC_INIT); -+ } -+ -+ usleep_range(200, 250); /* estimated value */ -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 2 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 3 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308, -+ int type) -+{ -+ unsigned int agc_func_en; -+ int idx, grp; -+ -+ /* -+ * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], -+ * to select the line-in or microphone as input of ADC -+ * -+ * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, -+ * ADC6, ADC7, and ADC8 -+ */ -+ if (rk3308->adc_grp0_using_linein) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_CH1_IN_SEL_MSK | -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_LINEIN | -+ RK3308_ADC_CH2_IN_LINEIN); -+ -+ /* Keep other ADCs as MIC-IN */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ /* The groups without line-in are >= 1 */ -+ if (grp < 1 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON07(grp), -+ RK3308_ADC_CH1_IN_SEL_MSK | -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_MIC | -+ RK3308_ADC_CH2_IN_MIC); -+ } -+ } else { -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON07(grp), -+ RK3308_ADC_CH1_IN_SEL_MSK | -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_MIC | -+ RK3308_ADC_CH2_IN_MIC); -+ } -+ } -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON0[7] and [3] to 0x1, to end the mute station -+ * of ADC, to enable the MIC module, to enable the reference voltage -+ * buffer, and to end the initialization of MIC -+ */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_UNMUTE | -+ RK3308_ADC_CH2_MIC_UNMUTE, -+ RK3308_ADC_CH1_MIC_UNMUTE | -+ RK3308_ADC_CH2_MIC_UNMUTE); -+ } -+ -+ /* -+ * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source -+ * of audio -+ */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_EN); -+ } -+ -+ /* -+ * This is mainly used for BIST mode that wait ADCs are stable. -+ * -+ * By tested results, the type delay is >40us, but we need to leave -+ * enough delay margin. -+ */ -+ usleep_range(400, 500); -+ -+ /* vendor step 4*/ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_BUF_REF_EN | -+ RK3308_ADC_CH2_BUF_REF_EN, -+ RK3308_ADC_CH1_BUF_REF_EN | -+ RK3308_ADC_CH2_BUF_REF_EN); -+ } -+ -+ /* vendor step 5 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_EN | -+ RK3308_ADC_CH2_MIC_EN, -+ RK3308_ADC_CH1_MIC_EN | -+ RK3308_ADC_CH2_MIC_EN); -+ } -+ -+ /* vendor step 6 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_EN | -+ RK3308_ADC_CH2_ALC_EN, -+ RK3308_ADC_CH1_ALC_EN | -+ RK3308_ADC_CH2_ALC_EN); -+ } -+ -+ /* vendor step 7 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH2_CLK_EN, -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH2_CLK_EN); -+ } -+ -+ /* vendor step 8 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH2_ADC_EN, -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH2_ADC_EN); -+ } -+ -+ /* vendor step 9 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK); -+ } -+ -+ /* vendor step 10 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK); -+ } -+ -+ /* vendor step 11 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK); -+ } -+ -+ /* vendor step 12 */ -+ -+ /* vendor step 13 */ -+ -+ /* vendor step 14 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), -+ &agc_func_en); -+ if (rk3308->adc_zerocross || -+ agc_func_en & RK3308_AGC_FUNC_SEL_EN) { -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ZEROCROSS_DET_EN, -+ RK3308_ADC_CH1_ZEROCROSS_DET_EN); -+ } -+ regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), -+ &agc_func_en); -+ if (rk3308->adc_zerocross || -+ agc_func_en & RK3308_AGC_FUNC_SEL_EN) { -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH2_ZEROCROSS_DET_EN, -+ RK3308_ADC_CH2_ZEROCROSS_DET_EN); -+ } -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ rk3308->adc_grps_endisable[grp] = true; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308, -+ int type) -+{ -+ int idx, grp; -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ZEROCROSS_DET_EN | -+ RK3308_ADC_CH2_ZEROCROSS_DET_EN, -+ RK3308_ADC_CH1_ZEROCROSS_DET_DIS | -+ RK3308_ADC_CH2_ZEROCROSS_DET_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 2 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH2_ADC_EN, -+ RK3308_ADC_CH1_ADC_DIS | -+ RK3308_ADC_CH2_ADC_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 3 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH2_CLK_EN, -+ RK3308_ADC_CH1_CLK_DIS | -+ RK3308_ADC_CH2_CLK_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 4 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_EN | -+ RK3308_ADC_CH2_ALC_EN, -+ RK3308_ADC_CH1_ALC_DIS | -+ RK3308_ADC_CH2_ALC_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 5 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_EN | -+ RK3308_ADC_CH2_MIC_EN, -+ RK3308_ADC_CH1_MIC_DIS | -+ RK3308_ADC_CH2_MIC_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 6 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_BUF_REF_EN | -+ RK3308_ADC_CH2_BUF_REF_EN, -+ RK3308_ADC_CH1_BUF_REF_DIS | -+ RK3308_ADC_CH2_BUF_REF_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 7 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 8 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_INIT | -+ RK3308_ADC_CH2_ADC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 9 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_INIT | -+ RK3308_ADC_CH2_ALC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_INIT | -+ RK3308_ADC_CH2_MIC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ rk3308->adc_grps_endisable[grp] = false; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_capture(struct rk3308_codec_priv *rk3308) -+{ -+ int idx, grp = 0; -+ int type = ADC_TYPE_NORMAL; -+ -+ rk3308_codec_adc_ana_enable(rk3308, type); -+ rk3308_codec_adc_reinit_mics(rk3308, type); -+ -+ if (rk3308->adc_grp0_using_linein) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_RIGHT); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_LEFT); -+ } else { -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (handle_loopback(rk3308) && -+ idx == rk3308->loopback_grp && -+ grp == ADC_GRP_SKIP_MAGIC) { -+ /* -+ * Switch to dummy BIST mode (BIST keep reset -+ * now) to keep the zero input data in I2S bus. -+ * -+ * It may cause the glitch if we hold the ADC -+ * digtital i2s module in codec. -+ * -+ * Then, the grp which is set from loopback_grp. -+ */ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(rk3308->loopback_grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_BIST_SINE); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(rk3308->loopback_grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_BIST_SINE); -+ } else { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_LEFT); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_RIGHT); -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static void rk3308_codec_adc_mclk_disable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_MCLK_MSK, -+ RK3308_ADC_MCLK_DIS); -+} -+ -+static void rk3308_codec_adc_mclk_enable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_MCLK_MSK, -+ RK3308_ADC_MCLK_EN); -+ udelay(20); -+} -+ -+static void rk3308_codec_dac_mclk_disable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_MCLK_MSK, -+ RK3308_DAC_MCLK_DIS); -+} -+ -+static void rk3308_codec_dac_mclk_enable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_MCLK_MSK, -+ RK3308_DAC_MCLK_EN); -+ udelay(20); -+} -+ -+static int rk3308_codec_open_dbg_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_enable(rk3308, ADC_TYPE_DBG); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_dbg_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_DBG); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_all_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_ALL); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_NORMAL); -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_playback(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_dac_enable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_playback(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_dac_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_llp_down(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_mclk_disable(rk3308); -+ rk3308_codec_dac_mclk_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_llp_up(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_mclk_enable(rk3308); -+ rk3308_codec_dac_mclk_enable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dlp_down(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308_codec_power_off(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dlp_up(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_power_on(rk3308); -+ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); -+ -+ return 0; -+} -+ -+/* Just used for debug and trace power state */ -+static void rk3308_codec_set_pm_state(struct rk3308_codec_priv *rk3308, -+ int pm_state) -+{ -+ int ret; -+ -+ switch (pm_state) { -+ case PM_LLP_DOWN: -+ rk3308_codec_llp_down(rk3308); -+ break; -+ case PM_LLP_UP: -+ rk3308_codec_llp_up(rk3308); -+ break; -+ case PM_DLP_DOWN: -+ rk3308_codec_dlp_down(rk3308); -+ break; -+ case PM_DLP_UP: -+ rk3308_codec_dlp_up(rk3308); -+ break; -+ case PM_DLP_DOWN2: -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); -+ clk_disable_unprepare(rk3308->pclk); -+ break; -+ case PM_DLP_UP2: -+ ret = clk_prepare_enable(rk3308->pclk); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable acodec pclk: %d\n", ret); -+ goto err; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_rx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_rx: %d\n", ret); -+ goto err; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_tx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_tx: %d\n", ret); -+ goto err; -+ } -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Invalid pm_state: %d\n", pm_state); -+ goto err; -+ } -+ -+ rk3308->pm_state = pm_state; -+ -+err: -+ return; -+} -+ -+static void rk3308_codec_update_adcs_status(struct rk3308_codec_priv *rk3308, -+ int state) -+{ -+ int idx, grp; -+ -+ /* Update skip_grps flags if the ADCs need to be enabled always. */ -+ if (state == PATH_BUSY) { -+ for (idx = 0; idx < rk3308->used_adc_grps; idx++) { -+ u32 mapped_grp = to_mapped_grp(rk3308, idx); -+ -+ for (grp = 0; grp < rk3308->en_always_grps_num; grp++) { -+ u32 en_always_grp = rk3308->en_always_grps[grp]; -+ -+ if (mapped_grp == en_always_grp) -+ rk3308->skip_grps[en_always_grp] = 1; -+ } -+ } -+ } -+} -+ -+static int rk3308_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_pcm_str *playback_str = -+ &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; -+ int type = ADC_TYPE_LOOPBACK; -+ int idx, grp; -+ int ret; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ /* DAC only supports 2 channels */ -+ rk3308_codec_dac_mclk_enable(rk3308); -+ rk3308_codec_open_playback(rk3308); -+ rk3308_codec_dac_dig_config(rk3308, params); -+ rk3308_codec_set_dac_path_state(rk3308, PATH_BUSY); -+ } else { -+ if (rk3308->micbias_num && -+ !rk3308->enable_micbias) -+ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); -+ -+ rk3308_codec_adc_mclk_enable(rk3308); -+ ret = rk3308_codec_update_adc_grps(rk3308, params); -+ if (ret < 0) -+ return ret; -+ -+ if (handle_loopback(rk3308)) { -+ if (rk3308->micbias_num && -+ (params_channels(params) == 2) && -+ to_mapped_grp(rk3308, 0) == rk3308->loopback_grp) -+ rk3308_codec_micbias_disable(rk3308); -+ -+ /* Check the DACs are opened */ -+ if (playback_str->substream_opened) { -+ rk3308->loopback_dacs_enabled = true; -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_LEFT); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_RIGHT); -+ } -+ } else { -+ rk3308->loopback_dacs_enabled = false; -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_BIST_SINE); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_BIST_SINE); -+ } -+ } -+ } -+ -+ rk3308_codec_open_capture(rk3308); -+ rk3308_codec_adc_dig_config(rk3308, params); -+ rk3308_codec_update_adcs_status(rk3308, PATH_BUSY); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, -+ int cmd, struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ int type = ADC_TYPE_LOOPBACK; -+ int idx, grp; -+ -+ if (handle_loopback(rk3308) && -+ rk3308->dac_output == DAC_LINEOUT && -+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ if (cmd == SNDRV_PCM_TRIGGER_START) { -+ struct snd_pcm_str *capture_str = -+ &substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; -+ -+ if (capture_str->substream_opened) -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->loopback_work, -+ msecs_to_jiffies(rk3308->delay_loopback_handle_ms)); -+ } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { -+ /* -+ * Switch to dummy bist mode to kick the glitch during disable -+ * ADCs and keep zero input data -+ */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_BIST_SINE); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_BIST_SINE); -+ } -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_LOOPBACK); -+ } -+ } -+ -+ return 0; -+} -+ -+static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ rk3308_codec_close_playback(rk3308); -+ rk3308_codec_dac_mclk_disable(rk3308); -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); -+ } else { -+ rk3308_codec_close_capture(rk3308); -+ if (!has_en_always_grps(rk3308)) { -+ rk3308_codec_adc_mclk_disable(rk3308); -+ rk3308_codec_update_adcs_status(rk3308, PATH_IDLE); -+ if (rk3308->micbias_num && -+ rk3308->enable_micbias) -+ rk3308_codec_micbias_disable(rk3308); -+ } -+ -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ } -+} -+ -+static struct snd_soc_dai_ops rk3308_dai_ops = { -+ .hw_params = rk3308_hw_params, -+ .set_fmt = rk3308_set_dai_fmt, -+ .mute_stream = rk3308_mute_stream, -+ .trigger = rk3308_pcm_trigger, -+ .shutdown = rk3308_pcm_shutdown, -+}; -+ -+static struct snd_soc_dai_driver rk3308_dai[] = { -+ { -+ .name = "rk3308-hifi", -+ .id = RK3308_HIFI, -+ .playback = { -+ .stream_name = "HiFi Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "HiFi Capture", -+ .channels_min = 1, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rk3308_dai_ops, -+ }, -+}; -+ -+static int rk3308_suspend(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ if (rk3308->no_deep_low_power) -+ goto out; -+ -+ rk3308_codec_dlp_down(rk3308); -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); -+ clk_disable_unprepare(rk3308->pclk); -+ -+out: -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ return 0; -+} -+ -+static int rk3308_resume(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ int ret = 0; -+ -+ if (rk3308->no_deep_low_power) -+ goto out; -+ -+ ret = clk_prepare_enable(rk3308->pclk); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable acodec pclk: %d\n", ret); -+ goto out; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_rx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_rx: %d\n", ret); -+ goto out; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_tx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_tx: %d\n", ret); -+ goto out; -+ } -+ -+ rk3308_codec_dlp_up(rk3308); -+out: -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ return ret; -+} -+ -+static int rk3308_codec_default_gains(struct rk3308_codec_priv *rk3308) -+{ -+ int grp; -+ -+ /* Prepare ADC gains */ -+ /* vendor step 12, set MIC PGA default gains */ -+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp), -+ RK3308_ADC_CH1_MIC_GAIN_MSK | -+ RK3308_ADC_CH2_MIC_GAIN_MSK, -+ RK3308_ADC_CH1_MIC_GAIN_0DB | -+ RK3308_ADC_CH2_MIC_GAIN_0DB); -+ } -+ -+ /* vendor step 13, set ALC default gains */ -+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp), -+ RK3308_ADC_CH1_ALC_GAIN_MSK, -+ RK3308_ADC_CH1_ALC_GAIN_0DB); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(grp), -+ RK3308_ADC_CH2_ALC_GAIN_MSK, -+ RK3308_ADC_CH2_ALC_GAIN_0DB); -+ } -+ -+ /* Prepare DAC gains */ -+ /* Step 15, set HPMIX default gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_GAIN_MSK | -+ RK3308_DAC_R_HPMIX_GAIN_MSK, -+ RK3308_DAC_L_HPMIX_GAIN_NDB_6 | -+ RK3308_DAC_R_HPMIX_GAIN_NDB_6); -+ -+ /* Step 18, set HPOUT default gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ RK3308_DAC_L_HPOUT_GAIN_NDB_39); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ RK3308_DAC_R_HPOUT_GAIN_NDB_39); -+ -+ /* Using the same gain to HPOUT LR channels */ -+ rk3308->hpout_l_dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39; -+ -+ /* Step 19, set LINEOUT default gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_GAIN_MSK | -+ RK3308_DAC_R_LINEOUT_GAIN_MSK, -+ RK3308_DAC_L_LINEOUT_GAIN_NDB_6 | -+ RK3308_DAC_R_LINEOUT_GAIN_NDB_6); -+ -+ return 0; -+} -+ -+static int rk3308_codec_setup_en_always_adcs(struct rk3308_codec_priv *rk3308, -+ struct device_node *np) -+{ -+ int num, ret; -+ -+ num = of_count_phandle_with_args(np, "rockchip,en-always-grps", NULL); -+ if (num < 0) { -+ if (num == -ENOENT) { -+ /* -+ * If there is note use 'rockchip,en-always-grps' -+ * property, return 0 is also right. -+ */ -+ ret = 0; -+ } else { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,adc-grps-route' num: %d\n", -+ num); -+ ret = num; -+ } -+ -+ rk3308->en_always_grps_num = 0; -+ return ret; -+ } -+ -+ rk3308->en_always_grps_num = num; -+ -+ ret = of_property_read_u32_array(np, "rockchip,en-always-grps", -+ rk3308->en_always_grps, num); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,en-always-grps': %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Clear all of skip_grps flags. */ -+ for (num = 0; num < ADC_LR_GROUP_MAX; num++) -+ rk3308->skip_grps[num] = 0; -+ -+ /* The loopback grp should not be enabled always. */ -+ for (num = 0; num < rk3308->en_always_grps_num; num++) { -+ if (rk3308->en_always_grps[num] == rk3308->loopback_grp) { -+ dev_err(rk3308->plat_dev, -+ "loopback_grp: %d should not be enabled always!\n", -+ rk3308->loopback_grp); -+ ret = -EINVAL; -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) -+{ -+ int ret; -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ ret = snd_soc_add_codec_controls(rk3308->codec, -+ mic_gains_b, -+ ARRAY_SIZE(mic_gains_b)); -+ if (ret) { -+ dev_err(rk3308->plat_dev, -+ "%s: add mic_gains_b failed: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ } else { -+ ret = snd_soc_add_codec_controls(rk3308->codec, -+ mic_gains_a, -+ ARRAY_SIZE(mic_gains_a)); -+ if (ret) { -+ dev_err(rk3308->plat_dev, -+ "%s: add mic_gains_a failed: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_check_micbias(struct rk3308_codec_priv *rk3308, -+ struct device_node *np) -+{ -+ struct device *dev = (struct device *)rk3308->plat_dev; -+ int num = 0, ret; -+ -+ /* Check internal micbias */ -+ rk3308->micbias1 = -+ of_property_read_bool(np, "rockchip,micbias1"); -+ if (rk3308->micbias1) -+ num++; -+ -+ rk3308->micbias2 = -+ of_property_read_bool(np, "rockchip,micbias2"); -+ if (rk3308->micbias2) -+ num++; -+ -+ rk3308->micbias_volt = RK3308_ADC_MICBIAS_VOLT_0_85; /* by default */ -+ rk3308->micbias_num = num; -+ -+ /* Check external micbias */ -+ rk3308->ext_micbias = EXT_MICBIAS_NONE; -+ -+ rk3308->micbias_en_gpio = devm_gpiod_get_optional(dev, -+ "micbias-en", -+ GPIOD_IN); -+ if (!rk3308->micbias_en_gpio) { -+ dev_info(dev, "Don't need micbias-en gpio\n"); -+ } else if (IS_ERR(rk3308->micbias_en_gpio)) { -+ ret = PTR_ERR(rk3308->micbias_en_gpio); -+ dev_err(dev, "Unable to claim gpio micbias-en\n"); -+ return ret; -+ } else if (gpiod_get_value(rk3308->micbias_en_gpio)) { -+ rk3308->ext_micbias = EXT_MICBIAS_FUNC1; -+ } -+ -+ rk3308->vcc_micbias = devm_regulator_get_optional(dev, -+ "vmicbias"); -+ if (IS_ERR(rk3308->vcc_micbias)) { -+ if (PTR_ERR(rk3308->vcc_micbias) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ dev_info(dev, "no vmicbias regulator found\n"); -+ } else { -+ ret = regulator_enable(rk3308->vcc_micbias); -+ if (ret) { -+ dev_err(dev, "Can't enable vmicbias: %d\n", ret); -+ return ret; -+ } -+ rk3308->ext_micbias = EXT_MICBIAS_FUNC2; -+ } -+ -+ dev_info(dev, "Check ext_micbias: %d\n", rk3308->ext_micbias); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dapm_controls_prepare(struct rk3308_codec_priv *rk3308) -+{ -+ int grp; -+ -+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { -+ rk3308->hpf_cutoff[grp] = 0; -+ rk3308->agc_l[grp] = 0; -+ rk3308->agc_r[grp] = 0; -+ rk3308->agc_asr_l[grp] = AGC_ASR_96KHZ; -+ rk3308->agc_asr_r[grp] = AGC_ASR_96KHZ; -+ } -+ -+ rk3308_codec_dapm_mic_gains(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308) -+{ -+ /* Clear registers for ADC and DAC */ -+ rk3308_codec_close_playback(rk3308); -+ rk3308_codec_close_all_capture(rk3308); -+ rk3308_codec_default_gains(rk3308); -+ rk3308_codec_llp_down(rk3308); -+ rk3308_codec_dapm_controls_prepare(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_probe(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ int ext_micbias; -+ -+ rk3308->codec = codec; -+ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); -+ -+ rk3308_codec_reset(codec); -+ rk3308_codec_power_on(rk3308); -+ -+ /* From vendor recommend, disable micbias at first. */ -+ ext_micbias = rk3308->ext_micbias; -+ rk3308->ext_micbias = EXT_MICBIAS_NONE; -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308->ext_micbias = ext_micbias; -+ -+ rk3308_codec_prepare(rk3308); -+ if (!rk3308->no_hp_det) -+ rk3308_codec_headset_detect_enable(rk3308); -+ -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ -+ return 0; -+} - -- /* 5. Wait until the voltage of VCM keeps stable at the AGND */ -- usleep_range(200, 300); /* estimated value */ -+static int rk3308_remove(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 0); -+ if (!rk3308->no_hp_det) -+ rk3308_codec_headset_detect_disable(rk3308); -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308_codec_power_off(rk3308); - -- /* 6. Power off the analog power supply */ -- /* 7. Power off the digital power supply */ -+ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); - -- /* Do something via hardware */ -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); - - return 0; - } - --static int check_micbias(int micbias) -+static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -+ .probe = rk3308_probe, -+ .remove = rk3308_remove, -+ .suspend = rk3308_suspend, -+ .resume = rk3308_resume, -+ .set_bias_level = rk3308_set_bias_level, -+ .controls = rk3308_codec_dapm_controls, -+ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+}; -+ -+static const struct reg_default rk3308_codec_reg_defaults[] = { -+ { RK3308_GLB_CON, 0x07 }, -+}; -+ -+static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) - { -- switch (micbias) { -- case RK3308_ADC_MICBIAS_VOLT_0_85: -- case RK3308_ADC_MICBIAS_VOLT_0_8: -- case RK3308_ADC_MICBIAS_VOLT_0_75: -- case RK3308_ADC_MICBIAS_VOLT_0_7: -- case RK3308_ADC_MICBIAS_VOLT_0_65: -- case RK3308_ADC_MICBIAS_VOLT_0_6: -- case RK3308_ADC_MICBIAS_VOLT_0_55: -- case RK3308_ADC_MICBIAS_VOLT_0_5: -- return 0; -- } -+ /* All registers can be read / write */ -+ return true; -+} - -- return -EINVAL; -+static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ return true; - } - --static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -- int micbias) -+static void rk3308_codec_hpdetect_work(struct work_struct *work) - { -- int ch = rk3308->adc_ch; -- int ret; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(work, struct rk3308_codec_priv, hpdet_work.work); -+ unsigned int val; -+ int need_poll = 0, need_irq = 0; -+ int need_report = 0, report_type = 0; -+ int dac_output = DAC_LINEOUT; -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Check headphone plugged/unplugged directly. */ -+ regmap_read(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_STATUS, &val); -+ regmap_write(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_STATUS_CLR, val); -+ -+ if (rk3308->hp_jack_reversed) { -+ switch (val) { -+ case 0x0: -+ case 0x2: -+ dac_output = DAC_HPOUT; -+ report_type = SND_JACK_HEADPHONE; -+ break; -+ default: -+ break; -+ } -+ } else { -+ switch (val) { -+ case 0x1: -+ dac_output = DAC_HPOUT; -+ report_type = SND_JACK_HEADPHONE; -+ break; -+ default: -+ /* Includes val == 2 or others. */ -+ break; -+ } -+ } - -- if (ch != 1 && ch != 2) { -- dev_err(rk3308->plat_dev, -- "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -- __func__, ch); -- return -EINVAL; -- } -+ rk3308_codec_dac_switch(rk3308, dac_output); -+ if (rk3308->hpdet_jack) -+ snd_soc_jack_report(rk3308->hpdet_jack, -+ report_type, -+ SND_JACK_HEADPHONE); - -- /* 1. Power up the ACODEC and keep the AVDDH stable */ -+ enable_irq(rk3308->irq); - -- /* 2. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ -- ret = check_micbias(micbias); -- if (ret < 0) { -- dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", -- micbias); -- return ret; -+ return; - } - -- /* -- * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range -- * control signal of MICBIAS voltage -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -- RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -- micbias); -+ /* Check headphone unplugged via poll. */ -+ regmap_read(rk3308->regmap, RK3308_DAC_DIG_CON14, &val); - -- /* 3. Wait until the VCMH keep stable */ -- usleep_range(200, 300); /* estimated value */ -+ if (rk3308->hp_jack_reversed) { -+ if (!val) { -+ rk3308->hp_plugged = true; -+ report_type = SND_JACK_HEADPHONE; - -- /* 4. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -- RK3308_ADC_MICBIAS_CURRENT_MSK, -- RK3308_ADC_MICBIAS_CURRENT_EN); -+ need_report = 1; -+ need_irq = 1; -+ } else { -+ if (rk3308->hp_plugged) { -+ rk3308->hp_plugged = false; -+ need_report = 1; -+ } -+ need_poll = 1; -+ } -+ } else { -+ if (!val) { -+ rk3308->hp_plugged = false; - -- /* -- * 5. Configure the (ADC_ANA_CON7+0x40)[3] or (ADC_ANA_CON7+0x80)[3] -- * to 0x1. -- * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and -- * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 -- */ -+ need_report = 1; -+ need_irq = 1; -+ } else { -+ if (!rk3308->hp_plugged) { -+ rk3308->hp_plugged = true; -+ report_type = SND_JACK_HEADPHONE; -+ need_report = 1; -+ } -+ need_poll = 1; -+ } -+ } - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_MIC_BIAS_BUF_EN, -- RK3308_ADC_MIC_BIAS_BUF_EN); -+ if (need_poll) -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->hpdet_work, -+ msecs_to_jiffies(HPDET_POLL_MS)); - -- return 0; --} -+ if (need_report) { -+ if (report_type) -+ dac_output = DAC_HPOUT; - --static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) --{ -- int ch = rk3308->adc_ch; -+ rk3308_codec_dac_switch(rk3308, dac_output); - -- if (ch != 1 && ch != 2) { -- dev_err(rk3308->plat_dev, -- "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -- __func__, ch); -- return -EINVAL; -+ if (rk3308->hpdet_jack) -+ snd_soc_jack_report(rk3308->hpdet_jack, -+ report_type, -+ SND_JACK_HEADPHONE); - } - -- /* 1. Enable the MICBIAS and keep the Audio Codec stable */ -- /* Do nothing */ -- -- /* -- * 2. Configure the (ADC_ANA_CON7+0x40)[3] or -- * (ADC_ANA_CON7+0x80)[3] to 0x0 -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_MIC_BIAS_BUF_EN, -- RK3308_ADC_MIC_BIAS_BUF_DIS); -- -- /* 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -- RK3308_ADC_MICBIAS_CURRENT_MSK, -- RK3308_ADC_MICBIAS_CURRENT_DIS); -+ if (need_irq) -+ enable_irq(rk3308->irq); -+} - -- return 0; -+static void rk3308_codec_loopback_work(struct work_struct *work) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(work, struct rk3308_codec_priv, loopback_work.work); -+ int type = ADC_TYPE_LOOPBACK; -+ int idx, grp; -+ -+ /* Prepare loopback ADCs */ -+ rk3308_codec_adc_ana_enable(rk3308, type); -+ -+ /* Waiting ADCs are stable */ -+ msleep(ADC_STABLE_MS); -+ -+ /* Recover normal mode after enable ADCs */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_LEFT); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_RIGHT); -+ } - } - --static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308) -+static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data) - { -- int ch = rk3308->adc_ch; -+ struct rk3308_codec_priv *rk3308 = data; - - /* -- * 1. Set he max level and min level of the ALC need to control. -- * -- * These values are estimated -+ * For the high level irq trigger, disable irq and avoid a lot of -+ * repeated irq handlers entry. - */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -- RK3308_AGC_LO_8BITS_AGC_MIN_MSK, -- 0x16); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -- RK3308_AGC_HI_8BITS_AGC_MIN_MSK, -- 0x40); -- -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -- RK3308_AGC_LO_8BITS_AGC_MAX_MSK, -- 0x26); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -- RK3308_AGC_HI_8BITS_AGC_MAX_MSK, -- 0x40); -+ disable_irq_nosync(rk3308->irq); -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->hpdet_work, msecs_to_jiffies(10)); - -- /* -- * 2. Set ACODEC_ALC_DIG_CON4[2:0] according to the sample rate -- * -- * By default is 44.1KHz for sample. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(ch), -- RK3308_AGC_APPROX_RATE_MSK, -- RK3308_AGC_APPROX_RATE_44_1K); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(ch), -- RK3308_AGC_APPROX_RATE_MSK, -- RK3308_AGC_APPROX_RATE_44_1K); -- -- /* 3. Set ACODEC_ALC_DIG_CON9[6] to 0x1, to enable the ALC module */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_EN); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_EN); -+ return IRQ_HANDLED; -+} - -- /* -- * 4. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -- * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -- * to 0x3, to enable the ALC module to control the gain of PGA. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -- RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -- RK3308_ADC_ALCL_CON_GAIN_PGAL_EN | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); -+void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+ struct snd_soc_jack *hpdet_jack); -+EXPORT_SYMBOL_GPL(rk3308_codec_set_jack_detect_cb); - -- /* -- * 5.Observe the current ALC output gain by reading -- * ACODEC_ALC_DIG_CON12[4:0] -- * -- * The default GAIN is 0x0c -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON12(ch), -- RK3308_AGC_GAIN_MSK, -- 0x0c); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON12(ch), -- RK3308_AGC_GAIN_MSK, -- 0x0c); -+static void rk3308_codec_set_jack_detect(struct snd_soc_codec *codec, -+ struct snd_soc_jack *hpdet_jack) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- return 0; --} -+ rk3308->hpdet_jack = hpdet_jack; - --static int rk3308_codec_alc_disable(struct rk3308_codec_priv *rk3308) --{ -- int ch = rk3308->adc_ch; -+ /* To detect jack once during startup */ -+ disable_irq_nosync(rk3308->irq); -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->hpdet_work, msecs_to_jiffies(10)); - -- /* -- * 1. Set ACODEC_ALC_DIG_CON9[6] to 0x0, to disable the ALC module, -- * then the ALC output gain will keep to the last value -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_DIS); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_DIS); -+ dev_info(rk3308->plat_dev, "%s: Request detect hp jack once\n", -+ __func__); -+} - -- /* -- * 2. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -- * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -- * to 0x0, to disable the ALC module to control the gain of PGA. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -- RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -- RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); -+static const struct regmap_config rk3308_codec_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = RK3308_DAC_ANA_CON15, -+ .writeable_reg = rk3308_codec_write_read_reg, -+ .readable_reg = rk3308_codec_write_read_reg, -+ .volatile_reg = rk3308_codec_volatile_reg, -+ .reg_defaults = rk3308_codec_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), -+ .cache_type = REGCACHE_FLAT, -+}; - -- return 0; -+static ssize_t pm_state_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ -+ return sprintf(buf, "pm_state: %d\n", rk3308->pm_state); - } - --static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308) -+static ssize_t pm_state_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- unsigned int adc_aif1 = 0, adc_aif2 = 0; -- unsigned int agc_func_en; -- int ch = rk3308->adc_ch; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long pm_state; -+ int ret = kstrtoul(buf, 10, &pm_state); - -- /* -- * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], -- * to select the line-in or microphone as input of ADC -- * -- * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, -- * ADC6, ADC7, and ADC8 -- */ -- if (ch == 0) { -- if (rk3308->adc_ch0_using_linein) { -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH1_IN_SEL_MSK, -- RK3308_ADC_CH1_IN_LINEIN); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH2_IN_SEL_MSK, -- RK3308_ADC_CH2_IN_LINEIN); -- } else { -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH1_IN_SEL_MSK, -- RK3308_ADC_CH1_IN_MIC); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH2_IN_SEL_MSK, -- RK3308_ADC_CH2_IN_MIC); -- } -+ if (ret < 0) { -+ dev_err(dev, "Invalid pm_state: %ld, ret: %d\n", -+ pm_state, ret); -+ return -EINVAL; - } - -- /* -- * 2. Set ACODEC_ADC_ANA_CON0[7:0] to 0xff, to end the mute station -- * of ADC, to enable the MIC module, to enable the reference voltage -- * buffer, and to end the initialization of MIC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -- RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -- RK3308_ADC_CH1_CH2_MIC_ALL); -+ rk3308_codec_set_pm_state(rk3308, pm_state); - -- /* -- * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source -- * of audio -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -- RK3308_ADC_CURRENT_MSK, -- RK3308_ADC_CURRENT_EN); -+ dev_info(dev, "Store pm_state: %d\n", rk3308->pm_state); - -- /* -- * 4. Set ACODEC_ADC_ANA_CON2[7:0] to 0x77, to enable the ALC module, -- * to enable the zero-crossing detection function, and to end the -- * initialization of ALC -- * -- * Note2. Please set ACODEC_ADC_ANA_CON2[7:0] to 0x33 in step4 -- * if the AGC function is closed -- */ -+ return count; -+} - -- adc_aif1 = RK3308_ADC_CH1_ALC_EN | RK3308_ADC_CH1_ALC_WORK; -- regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -- if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -- adc_aif1 |= RK3308_ADC_CH1_ZEROCROSS_DET_EN; -+static ssize_t adc_grps_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ u32 grp; -+ int type = ADC_TYPE_NORMAL, count = 0; -+ int idx; -+ -+ count += sprintf(buf + count, "current used adc_grps:\n"); -+ count += sprintf(buf + count, "- normal:"); -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) -+ count += sprintf(buf + count, " %d", grp); -+ count += sprintf(buf + count, "\n"); -+ count += sprintf(buf + count, "- loopback: %d\n", -+ rk3308->loopback_grp); - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH1_ALC_ZC_MSK, -- adc_aif1); -+ return count; -+} - -- adc_aif2 = RK3308_ADC_CH2_ALC_EN | RK3308_ADC_CH2_ALC_WORK; -- regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -- if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -- adc_aif2 |= RK3308_ADC_CH2_ZEROCROSS_DET_EN; -+static ssize_t adc_grps_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ char adc_type; -+ int grps, ret; -+ -+ ret = sscanf(buf, "%c,%d", &adc_type, &grps); -+ if (ret != 2) { -+ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", -+ __func__, ret); -+ return -EFAULT; -+ } - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH2_ALC_ZC_MSK, -- adc_aif2); -+ if (adc_type == 'n') -+ rk3308->used_adc_grps = grps; -+ else if (adc_type == 'l') -+ rk3308->loopback_grp = grps; - -- /* -- * 5. Set ACODEC_ADC_ANA_CON5[7:0] to 0x77, to enable the clock and -- * ADC module, and to end the initialization of ADC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH1_ADC_CLK_MSK, -- RK3308_ADC_CH1_CLK_EN | -- RK3308_ADC_CH1_ADC_EN | -- RK3308_ADC_CH1_ADC_WORK); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH2_ADC_CLK_MSK, -- RK3308_ADC_CH2_CLK_EN | -- RK3308_ADC_CH2_ADC_EN | -- RK3308_ADC_CH2_ADC_WORK); -+ return count; -+} - -- /* -- * 6. Set ACODEC_ADC_ANA_CON1[5:4] and ACODEC_ADC_ANA_CON1[1:0], -- * to select the gain of the MIC -- * -- * By default is 0db. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH1_MIC_GAIN_MSK, -- RK3308_ADC_CH1_MIC_GAIN_0DB); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH2_MIC_GAIN_MSK, -- RK3308_ADC_CH2_MIC_GAIN_0DB); -+static ssize_t adc_grps_route_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ char which_i2s[32] = {0}; -+ int count = 0; -+ u32 grp; - -- /* -- * 7.Set ACODEC_ADC_ANA_CON3[4:0] and ACODEC_ADC_ANA_CON4[3:0] to -- * select the gain of ALC -- * -- * By default is 0db. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(ch), -- RK3308_ADC_CH1_ALC_GAIN_MSK, -- RK3308_ADC_CH1_ALC_GAIN_0DB); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(ch), -- RK3308_ADC_CH2_ALC_GAIN_MSK, -- RK3308_ADC_CH2_ALC_GAIN_0DB); -+ switch (rk3308->which_i2s) { -+ case ACODEC_TO_I2S1_2CH: -+ strcpy(which_i2s, "i2s1_2ch"); -+ break; -+ case ACODEC_TO_I2S3_4CH: -+ strcpy(which_i2s, "i2s3_4ch"); -+ break; -+ default: -+ strcpy(which_i2s, "i2s2_8ch"); -+ break; -+ } - -- /* 8.Begin recording */ -+ count += sprintf(buf + count, "%s from acodec route mapping:\n", -+ which_i2s); -+ for (grp = 0; grp < rk3308->to_i2s_grps; grp++) { -+ count += sprintf(buf + count, "* sdi_%d <-- sdo_%d\n", -+ grp, rk3308->i2s_sdis[grp]); -+ } - -- return 0; -+ return count; - } - --static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308) -+static ssize_t adc_grps_route_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- int ch = rk3308->adc_ch; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ int which_i2s, idx, i2s_sdis[ADC_LR_GROUP_MAX]; -+ int ret; - -- /* -- * 1. Set ACODEC_ADC_ANA_CON2[7:0] to 0x0, to disable the ALC module, -- * to disable the zero-crossing detection function, and to begin the -- * initialization of ALC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH1_ALC_ZC_MSK, -- 0); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH2_ALC_ZC_MSK, -- 0); -+ ret = sscanf(buf, "%d,%d,%d,%d,%d", &which_i2s, -+ &i2s_sdis[0], &i2s_sdis[1], &i2s_sdis[2], &i2s_sdis[3]); -+ if (ret != 5) { -+ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", -+ __func__, ret); -+ goto err; -+ } - -- /* -- * 2. Set ACODEC_ADC_ANA_CON5[7:0] to 0x0, to disable the clock and -- * ADC module, and to begin the initialization of ADC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH1_ADC_CLK_MSK, -- 0); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH2_ADC_CLK_MSK, -- 0); -+ if (which_i2s < ACODEC_TO_I2S2_8CH || -+ which_i2s > ACODEC_TO_I2S1_2CH) { -+ dev_err(rk3308->plat_dev, "Invalid i2s type: %d\n", which_i2s); -+ goto err; -+ } - -- /* -- * 3. Set ACODEC_ADC_ANA_CON0[7:0] to 0x88, to disable the MIC module, -- * to disable the reference voltage buffer, and to begin the -- * initialization of MIC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -- RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -- RK3308_ADC_CH1_MIC_UNMUTE | -- RK3308_ADC_CH2_MIC_UNMUTE); -+ rk3308->which_i2s = which_i2s; - -- /* -- * 4. Set ACODEC_ADC_ANA_CON6[0] to 0x0, to disable the current -- * source of audio -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -- RK3308_ADC_CURRENT_MSK, -- RK3308_ADC_CURRENT_DIS); -+ switch (rk3308->which_i2s) { -+ case ACODEC_TO_I2S1_2CH: -+ rk3308->to_i2s_grps = 1; -+ break; -+ case ACODEC_TO_I2S3_4CH: -+ rk3308->to_i2s_grps = 2; -+ break; -+ default: -+ rk3308->to_i2s_grps = 4; -+ break; -+ } - -- return 0; -+ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) -+ rk3308->i2s_sdis[idx] = i2s_sdis[idx]; -+ -+ rk3308_codec_adc_grps_route_config(rk3308); -+ -+err: -+ return count; - } - --static int rk3308_codec_open_capture(struct snd_soc_codec *codec) -+static ssize_t adc_grp0_in_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- -- rk3308_codec_alc_enable(rk3308); -- rk3308_codec_adc_ana_enable(rk3308); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); - -- return 0; -+ return sprintf(buf, "adc ch0 using: %s\n", -+ rk3308->adc_grp0_using_linein ? "line in" : "mic in"); - } - --static int rk3308_codec_close_capture(struct snd_soc_codec *codec) -+static ssize_t adc_grp0_in_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long using_linein; -+ int ret = kstrtoul(buf, 10, &using_linein); -+ -+ if (ret < 0 || using_linein > 1) { -+ dev_err(dev, "Invalid input status: %ld, ret: %d\n", -+ using_linein, ret); -+ return -EINVAL; -+ } - -- rk3308_codec_alc_disable(rk3308); -- rk3308_codec_adc_ana_disable(rk3308); -+ rk3308->adc_grp0_using_linein = using_linein; - -- return 0; -+ dev_info(dev, "store using_linein: %d\n", -+ rk3308->adc_grp0_using_linein); -+ -+ return count; - } - --static int rk3308_codec_open_playback(struct snd_soc_codec *codec) -+static ssize_t adc_zerocross_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- -- rk3308_codec_dac_enable(rk3308); -- rk3308_speaker_ctl(rk3308, 1); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); - -- return 0; -+ return sprintf(buf, "adc zerocross: %s\n", -+ rk3308->adc_zerocross ? "enabled" : "disabled"); - } - --static int rk3308_codec_close_playback(struct snd_soc_codec *codec) -+static ssize_t adc_zerocross_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long zerocross; -+ int ret = kstrtoul(buf, 10, &zerocross); - -- rk3308_speaker_ctl(rk3308, 0); -- rk3308_codec_dac_disable(rk3308); -+ if (ret < 0 || zerocross > 1) { -+ dev_err(dev, "Invalid zerocross: %ld, ret: %d\n", -+ zerocross, ret); -+ return -EINVAL; -+ } - -- return 0; -+ rk3308->adc_zerocross = zerocross; -+ -+ dev_info(dev, "store adc zerocross: %d\n", rk3308->adc_zerocross); -+ -+ return count; - } - --static int rk3308_pcm_startup(struct snd_pcm_substream *substream, -- struct snd_soc_dai *dai) -+static ssize_t adc_grps_endisable_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct snd_soc_codec *codec = dai->codec; -- int ret = 0; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ int count = 0, i; - -- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- ret = rk3308_codec_open_playback(codec); -- else -- ret = rk3308_codec_open_capture(codec); -+ count += sprintf(buf + count, "enabled adc grps:"); -+ for (i = 0; i < ADC_LR_GROUP_MAX; i++) -+ count += sprintf(buf + count, "%d ", -+ rk3308->adc_grps_endisable[i]); - -- return ret; -+ count += sprintf(buf + count, "\n"); -+ return count; - } - --static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, -- struct snd_soc_dai *dai) -+static ssize_t adc_grps_endisable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ int grp, endisable, ret; - -- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- rk3308_codec_close_playback(codec); -- else -- rk3308_codec_close_capture(codec); --} -+ ret = sscanf(buf, "%d,%d", &grp, &endisable); -+ if (ret != 2) { -+ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", -+ __func__, ret); -+ return -EFAULT; -+ } - --static struct snd_soc_dai_ops rk3308_dai_ops = { -- .hw_params = rk3308_hw_params, -- .set_fmt = rk3308_set_dai_fmt, -- .digital_mute = rk3308_digital_mute, -- .startup = rk3308_pcm_startup, -- .shutdown = rk3308_pcm_shutdown, --}; -+ rk3308->cur_dbg_grp = grp; - --static struct snd_soc_dai_driver rk3308_dai[] = { -- { -- .name = "rk3308-hifi", -- .id = RK3308_HIFI, -- .playback = { -- .stream_name = "HiFi Playback", -- .channels_min = 2, -- .channels_max = 2, -- .rates = SNDRV_PCM_RATE_8000_96000, -- .formats = (SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S20_3LE | -- SNDRV_PCM_FMTBIT_S24_LE | -- SNDRV_PCM_FMTBIT_S32_LE), -- }, -- .capture = { -- .stream_name = "HiFi Capture", -- .channels_min = 1, -- .channels_max = 8, -- .rates = SNDRV_PCM_RATE_8000_96000, -- .formats = (SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S20_3LE | -- SNDRV_PCM_FMTBIT_S24_LE | -- SNDRV_PCM_FMTBIT_S32_LE), -- }, -- .ops = &rk3308_dai_ops, -- }, --}; -+ if (endisable) -+ rk3308_codec_open_dbg_capture(rk3308); -+ else -+ rk3308_codec_close_dbg_capture(rk3308); - --static int rk3308_suspend(struct snd_soc_codec *codec) --{ -- rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ dev_info(dev, "ADC grp %d endisable: %d\n", grp, endisable); - -- return 0; -+ return count; - } - --static int rk3308_resume(struct snd_soc_codec *codec) -+static ssize_t dac_endisable_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); - -- return 0; -+ return sprintf(buf, "%d\n", rk3308->dac_endisable); - } - --static int rk3308_probe(struct snd_soc_codec *codec) -+static ssize_t dac_endisable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long endisable; -+ int ret = kstrtoul(buf, 10, &endisable); - -- rk3308_codec_reset(codec); -- rk3308_codec_power_on(codec); -+ if (ret < 0) { -+ dev_err(dev, "Invalid endisable: %ld, ret: %d\n", -+ endisable, ret); -+ return -EINVAL; -+ } -+ -+ if (endisable) -+ rk3308_codec_open_playback(rk3308); -+ else -+ rk3308_codec_close_playback(rk3308); - -- rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_7); -+ dev_info(dev, "DAC endisable: %ld\n", endisable); - -- return 0; -+ return count; - } - --static int rk3308_remove(struct snd_soc_codec *codec) -+static ssize_t dac_output_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ ssize_t ret = 0; - -- rk3308_speaker_ctl(rk3308, 0); -- rk3308_codec_micbias_disable(rk3308); -- rk3308_codec_power_off(codec); -+ switch (rk3308->dac_output) { -+ case DAC_LINEOUT: -+ ret = sprintf(buf, "dac path: %s\n", "line out"); -+ break; -+ case DAC_HPOUT: -+ ret = sprintf(buf, "dac path: %s\n", "hp out"); -+ break; -+ case DAC_LINEOUT_HPOUT: -+ ret = sprintf(buf, "dac path: %s\n", -+ "both line out and hp out"); -+ break; -+ default: -+ pr_err("Invalid dac path: %d ?\n", rk3308->dac_output); -+ break; -+ } - -- return 0; -+ return ret; - } - --static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -- .probe = rk3308_probe, -- .remove = rk3308_remove, -- .suspend = rk3308_suspend, -- .resume = rk3308_resume, -- .set_bias_level = rk3308_set_bias_level, -- .controls = rk3308_codec_dapm_controls, -- .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), --}; -- --static const struct reg_default rk3308_codec_reg_defaults[] = { -- { RK3308_GLB_CON, 0x07 }, --}; -- --static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) -+static ssize_t dac_output_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- /* All registers can be read / write */ -- return true; --} -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long dac_output; -+ int ret = kstrtoul(buf, 10, &dac_output); - --static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) --{ -- switch (reg) { -- case RK3308_GLB_CON: -- return true; -- default: -- return false; -+ if (ret < 0) { -+ dev_err(dev, "Invalid input status: %ld, ret: %d\n", -+ dac_output, ret); -+ return -EINVAL; - } --} - --static const struct regmap_config rk3308_codec_regmap_config = { -- .reg_bits = 32, -- .reg_stride = 4, -- .val_bits = 32, -- .max_register = RK3308_DAC_ANA_CON13, -- .writeable_reg = rk3308_codec_write_read_reg, -- .readable_reg = rk3308_codec_write_read_reg, -- .volatile_reg = rk3308_codec_volatile_reg, -- .reg_defaults = rk3308_codec_reg_defaults, -- .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), -- .cache_type = REGCACHE_FLAT, --}; -+ rk3308_codec_dac_switch(rk3308, dac_output); - --static ssize_t adc_ch_show(struct device *dev, -- struct device_attribute *attr, -- char *buf) -+ dev_info(dev, "Store dac_output: %d\n", rk3308->dac_output); -+ -+ return count; -+} -+ -+static ssize_t enable_all_adcs_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { - struct rk3308_codec_priv *rk3308 = - container_of(dev, struct rk3308_codec_priv, dev); - -- return sprintf(buf, "adc_ch: %d\n", rk3308->adc_ch); -+ return sprintf(buf, "%d\n", rk3308->enable_all_adcs); - } - --static ssize_t adc_ch_store(struct device *dev, -- struct device_attribute *attr, -- const char *buf, size_t count) -+static ssize_t enable_all_adcs_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { - struct rk3308_codec_priv *rk3308 = - container_of(dev, struct rk3308_codec_priv, dev); -- unsigned long ch; -- int ret = kstrtoul(buf, 10, &ch); -+ unsigned long enable; -+ int ret = kstrtoul(buf, 10, &enable); - -- if (ret < 0 || ch > 4) { -- dev_err(dev, "Invalid ch: %ld, ret: %d\n", ch, ret); -+ if (ret < 0) { -+ dev_err(dev, "Invalid enable value: %ld, ret: %d\n", -+ enable, ret); - return -EINVAL; - } - -- rk3308->adc_ch = ch; -- -- dev_info(dev, "Store ch: %d\n", rk3308->adc_ch); -+ rk3308->enable_all_adcs = enable; - - return count; - } - --static const struct device_attribute adc_ch_attrs[] = { -- __ATTR(adc_ch, 0644, adc_ch_show, adc_ch_store), -+static const struct device_attribute acodec_attrs[] = { -+ __ATTR_RW(adc_grps), -+ __ATTR_RW(adc_grps_endisable), -+ __ATTR_RW(adc_grps_route), -+ __ATTR_RW(adc_grp0_in), -+ __ATTR_RW(adc_zerocross), -+ __ATTR_RW(dac_endisable), -+ __ATTR_RW(dac_output), -+ __ATTR_RW(enable_all_adcs), -+ __ATTR_RW(pm_state), - }; - - static void rk3308_codec_device_release(struct device *dev) -@@ -1468,8 +4747,8 @@ static int rk3308_codec_sysfs_init(struct platform_device *pdev, - return -ENOMEM; - } - -- for (i = 0; i < ARRAY_SIZE(adc_ch_attrs); i++) { -- if (device_create_file(dev, &adc_ch_attrs[i])) { -+ for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++) { -+ if (device_create_file(dev, &acodec_attrs[i])) { - dev_err(&pdev->dev, - "Create 'rk3308-acodec-dev' attr failed\n"); - device_unregister(dev); -@@ -1480,32 +4759,136 @@ static int rk3308_codec_sysfs_init(struct platform_device *pdev, - return 0; - } - -+#if defined(CONFIG_DEBUG_FS) -+static int rk3308_codec_debugfs_reg_show(struct seq_file *s, void *v) -+{ -+ struct rk3308_codec_priv *rk3308 = s->private; -+ unsigned int i; -+ unsigned int val; -+ -+ for (i = RK3308_GLB_CON; i <= RK3308_DAC_ANA_CON13; i += 4) { -+ regmap_read(rk3308->regmap, i, &val); -+ if (!(i % 16)) -+ seq_printf(s, "\nR:%04x: ", i); -+ seq_printf(s, "%08x ", val); -+ } -+ -+ seq_puts(s, "\n"); -+ -+ return 0; -+} -+ -+static ssize_t rk3308_codec_debugfs_reg_operate(struct file *file, -+ const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ ((struct seq_file *)file->private_data)->private; -+ unsigned int reg, val; -+ char op; -+ char kbuf[32]; -+ int ret; -+ -+ if (count >= sizeof(kbuf)) -+ return -EINVAL; -+ -+ if (copy_from_user(kbuf, buf, count)) -+ return -EFAULT; -+ kbuf[count] = '\0'; -+ -+ ret = sscanf(kbuf, "%c,%x,%x", &op, ®, &val); -+ if (ret != 3) { -+ pr_err("sscanf failed: %d\n", ret); -+ return -EFAULT; -+ } -+ -+ if (op == 'w') { -+ pr_info("Write reg: 0x%04x with val: 0x%08x\n", reg, val); -+ regmap_write(rk3308->regmap, reg, val); -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ pr_info("Read back reg: 0x%04x with val: 0x%08x\n", reg, val); -+ } else if (op == 'r') { -+ regmap_read(rk3308->regmap, reg, &val); -+ pr_info("Read reg: 0x%04x with val: 0x%08x\n", reg, val); -+ } else { -+ pr_err("This is an invalid operation: %c\n", op); -+ } -+ -+ return count; -+} -+ -+static int rk3308_codec_debugfs_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, -+ rk3308_codec_debugfs_reg_show, inode->i_private); -+} -+ -+static const struct file_operations rk3308_codec_reg_debugfs_fops = { -+ .owner = THIS_MODULE, -+ .open = rk3308_codec_debugfs_open, -+ .read = seq_read, -+ .write = rk3308_codec_debugfs_reg_operate, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+#endif /* CONFIG_DEBUG_FS */ -+ -+static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int chip_id; -+ -+ regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id); -+ switch (chip_id) { -+ case 3306: -+ rk3308->codec_ver = ACODEC_VERSION_A; -+ break; -+ case 0x3308: -+ rk3308->codec_ver = ACODEC_VERSION_B; -+ break; -+ default: -+ pr_err("Unknown chip_id: %d / 0x%x\n", chip_id, chip_id); -+ return -EFAULT; -+ } -+ -+ pr_info("The acodec version is: %x\n", rk3308->codec_ver); -+ return 0; -+} -+ - static int rk3308_platform_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; - struct rk3308_codec_priv *rk3308; - struct resource *res; - void __iomem *base; -- int ret = 0; -- struct regmap *grf; -- -- grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); -- if (IS_ERR(grf)) { -- dev_err(&pdev->dev, -- "Missing 'rockchip,grf' property\n"); -- return PTR_ERR(grf); -- } -+ int ret; - - rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); - if (!rk3308) - return -ENOMEM; - -+ rk3308->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); -+ if (IS_ERR(rk3308->grf)) { -+ dev_err(&pdev->dev, -+ "Missing 'rockchip,grf' property\n"); -+ return PTR_ERR(rk3308->grf); -+ } -+ - ret = rk3308_codec_sysfs_init(pdev, rk3308); - if (ret < 0) { - dev_err(&pdev->dev, "Sysfs init failed\n"); - return ret; - } - -+#if defined(CONFIG_DEBUG_FS) -+ rk3308->dbg_codec = debugfs_create_dir(CODEC_DRV_NAME, NULL); -+ if (IS_ERR(rk3308->dbg_codec)) -+ dev_err(&pdev->dev, -+ "Failed to create debugfs dir for rk3308!\n"); -+ else -+ debugfs_create_file("reg", 0644, rk3308->dbg_codec, -+ rk3308, &rk3308_codec_reg_debugfs_fops); -+#endif - rk3308->plat_dev = &pdev->dev; - - rk3308->reset = devm_reset_control_get(&pdev->dev, "acodec-reset"); -@@ -1518,27 +4901,146 @@ static int rk3308_platform_probe(struct platform_device *pdev) - rk3308->reset = NULL; - } - -- /* GPIO0_A5 control speaker on RK3308 EVB */ -- rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk_ctl", -- GPIOD_OUT_HIGH); -- if (IS_ERR(rk3308->spk_ctl_gpio)) { -+ rk3308->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-ctl", -+ GPIOD_OUT_LOW); -+ if (!rk3308->hp_ctl_gpio) { -+ dev_info(&pdev->dev, "Don't need hp-ctl gpio\n"); -+ } else if (IS_ERR(rk3308->hp_ctl_gpio)) { -+ ret = PTR_ERR(rk3308->hp_ctl_gpio); -+ dev_err(&pdev->dev, "Unable to claim gpio hp-ctl\n"); -+ return ret; -+ } -+ -+ rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-ctl", -+ GPIOD_OUT_LOW); -+ -+ if (!rk3308->spk_ctl_gpio) { -+ dev_info(&pdev->dev, "Don't need spk-ctl gpio\n"); -+ } else if (IS_ERR(rk3308->spk_ctl_gpio)) { - ret = PTR_ERR(rk3308->spk_ctl_gpio); -- dev_err(&pdev->dev, "Unable to claim gpio spk_ctl\n"); -+ dev_err(&pdev->dev, "Unable to claim gpio spk-ctl\n"); -+ return ret; -+ } -+ -+ rk3308->pa_drv_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-drv", -+ GPIOD_OUT_LOW); -+ -+ if (!rk3308->pa_drv_gpio) { -+ dev_info(&pdev->dev, "Don't need pa-drv gpio\n"); -+ } else if (IS_ERR(rk3308->pa_drv_gpio)) { -+ ret = PTR_ERR(rk3308->pa_drv_gpio); -+ dev_err(&pdev->dev, "Unable to claim gpio pa-drv\n"); - return ret; - } - -+ if (rk3308->pa_drv_gpio) { -+ rk3308->delay_pa_drv_ms = PA_DRV_MS; -+ ret = of_property_read_u32(np, "rockchip,delay-pa-drv-ms", -+ &rk3308->delay_pa_drv_ms); -+ } -+ -+#if DEBUG_POP_ALWAYS -+ dev_info(&pdev->dev, "Enable all ctl gpios always for debugging pop\n"); -+ rk3308_headphone_ctl(rk3308, 1); -+ rk3308_speaker_ctl(rk3308, 1); -+#else -+ dev_info(&pdev->dev, "De-pop as much as possible\n"); -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 0); -+#endif -+ - rk3308->pclk = devm_clk_get(&pdev->dev, "acodec"); - if (IS_ERR(rk3308->pclk)) { - dev_err(&pdev->dev, "Can't get acodec pclk\n"); - return PTR_ERR(rk3308->pclk); - } - -+ rk3308->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx"); -+ if (IS_ERR(rk3308->mclk_rx)) { -+ dev_err(&pdev->dev, "Can't get acodec mclk_rx\n"); -+ return PTR_ERR(rk3308->mclk_rx); -+ } -+ -+ rk3308->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx"); -+ if (IS_ERR(rk3308->mclk_tx)) { -+ dev_err(&pdev->dev, "Can't get acodec mclk_tx\n"); -+ return PTR_ERR(rk3308->mclk_tx); -+ } -+ - ret = clk_prepare_enable(rk3308->pclk); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret); - return ret; - } - -+ ret = clk_prepare_enable(rk3308->mclk_rx); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to enable i2s mclk_rx: %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_tx); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to enable i2s mclk_tx: %d\n", ret); -+ return ret; -+ } -+ -+ rk3308_codec_check_micbias(rk3308, np); -+ -+ rk3308->enable_all_adcs = -+ of_property_read_bool(np, "rockchip,enable-all-adcs"); -+ -+ rk3308->hp_jack_reversed = -+ of_property_read_bool(np, "rockchip,hp-jack-reversed"); -+ -+ rk3308->no_deep_low_power = -+ of_property_read_bool(np, "rockchip,no-deep-low-power"); -+ -+ rk3308->no_hp_det = -+ of_property_read_bool(np, "rockchip,no-hp-det"); -+ -+ rk3308->delay_loopback_handle_ms = LOOPBACK_HANDLE_MS; -+ ret = of_property_read_u32(np, "rockchip,delay-loopback-handle-ms", -+ &rk3308->delay_loopback_handle_ms); -+ -+ rk3308->delay_start_play_ms = 0; -+ ret = of_property_read_u32(np, "rockchip,delay-start-play-ms", -+ &rk3308->delay_start_play_ms); -+ -+ rk3308->loopback_grp = NOT_USED; -+ ret = of_property_read_u32(np, "rockchip,loopback-grp", -+ &rk3308->loopback_grp); -+ /* -+ * If there is no loopback on some board, the -EINVAL indicates that -+ * we don't need add the node, and it is not an error. -+ */ -+ if (ret < 0 && ret != -EINVAL) { -+ dev_err(&pdev->dev, "Failed to read loopback property: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_adc_grps_route(rk3308, np); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to route ADC groups: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_setup_en_always_adcs(rk3308, np); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to setup enabled always ADCs: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_get_version(rk3308); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to get acodec version: %d\n", -+ ret); -+ return ret; -+ } -+ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) { -@@ -1555,10 +5057,65 @@ static int rk3308_platform_probe(struct platform_device *pdev) - goto failed; - } - -+ if (!rk3308->no_hp_det) { -+ int index = 0; -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) -+ index = 1; -+ -+ rk3308->irq = platform_get_irq(pdev, index); -+ if (rk3308->irq < 0) { -+ dev_err(&pdev->dev, "Can not get codec irq\n"); -+ goto failed; -+ } -+ -+ INIT_DELAYED_WORK(&rk3308->hpdet_work, rk3308_codec_hpdetect_work); -+ -+ ret = devm_request_irq(&pdev->dev, rk3308->irq, -+ rk3308_codec_hpdet_isr, -+ 0, -+ "acodec-hpdet", -+ rk3308); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret); -+ goto failed; -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ rk3308->detect_grf = -+ syscon_regmap_lookup_by_phandle(np, "rockchip,detect-grf"); -+ if (IS_ERR(rk3308->detect_grf)) { -+ dev_err(&pdev->dev, -+ "Missing 'rockchip,detect-grf' property\n"); -+ return PTR_ERR(rk3308->detect_grf); -+ } -+ -+ /* Configure filter count and enable hpdet irq. */ -+ regmap_write(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_COUNTER, -+ DEFAULT_HPDET_COUNT); -+ regmap_write(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_CON, -+ (HPDET_BOTH_NEG_POS << 16) | -+ HPDET_BOTH_NEG_POS); -+ } -+ -+ rk3308_codec_set_jack_detect_cb = rk3308_codec_set_jack_detect; -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_A) -+ INIT_DELAYED_WORK(&rk3308->loopback_work, -+ rk3308_codec_loopback_work); -+ -+ rk3308->adc_grp0_using_linein = ADC_GRP0_MICIN; -+ rk3308->dac_output = DAC_LINEOUT; -+ rk3308->adc_zerocross = 1; -+ rk3308->pm_state = PM_NORMAL; -+ - platform_set_drvdata(pdev, rk3308); - - ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3308, -- rk3308_dai, ARRAY_SIZE(rk3308_dai)); -+ rk3308_dai, ARRAY_SIZE(rk3308_dai)); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); - goto failed; -@@ -1567,7 +5124,10 @@ static int rk3308_platform_probe(struct platform_device *pdev) - return ret; - - failed: -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); - clk_disable_unprepare(rk3308->pclk); -+ device_unregister(&rk3308->dev); - - return ret; - } -@@ -1577,8 +5137,11 @@ static int rk3308_platform_remove(struct platform_device *pdev) - struct rk3308_codec_priv *rk3308 = - (struct rk3308_codec_priv *)platform_get_drvdata(pdev); - -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); - clk_disable_unprepare(rk3308->pclk); - snd_soc_unregister_codec(&pdev->dev); -+ device_unregister(&rk3308->dev); - - return 0; - } -@@ -1591,7 +5154,7 @@ MODULE_DEVICE_TABLE(of, rk3308codec_of_match); - - static struct platform_driver rk3308_codec_driver = { - .driver = { -- .name = "rk3308-acodec", -+ .name = CODEC_DRV_NAME, - .of_match_table = of_match_ptr(rk3308codec_of_match), - }, - .probe = rk3308_platform_probe, -diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h -index 6cfa69157785..93e089dae081 100644 ---- a/sound/soc/codecs/rk3308_codec.h -+++ b/sound/soc/codecs/rk3308_codec.h -@@ -26,7 +26,8 @@ - #define ACODEC_ADC_I2S_CTL0 0x04 /* REG 0x01 */ - #define ACODEC_ADC_I2S_CTL1 0x08 /* REG 0x02 */ - #define ACODEC_ADC_BIST_MODE_SEL 0x0c /* REG 0x03 */ --/* Resevred REG 0x04 ~ 0x06 */ -+#define ACODEC_ADC_HPF_PATH 0x10 /* REG 0x04 */ -+/* Resevred REG 0x05 ~ 0x06 */ - #define ACODEC_ADC_DATA_PATH 0x1c /* REG 0x07 */ - /* Resevred REG 0x08 ~ 0x0f */ - -@@ -62,12 +63,15 @@ - #define ACODEC_DAC_I2S_CTL0 0x04 /* REG 0x01 */ - #define ACODEC_DAC_I2S_CTL1 0x08 /* REG 0x02 */ - #define ACODEC_DAC_BIST_MODE_SEL 0x0c /* REG 0x03 */ --/* Resevred REG 0x04 */ -+#define ACODEC_DAC_DIGITAL_GAIN 0x10 /* REG 0x04 */ - #define ACODEC_DAC_DATA_SEL 0x14 /* REG 0x05 */ - /* Resevred REG 0x06 ~ 0x09 */ - #define ACODEC_DAC_DATA_HI 0x28 /* REG 0x0a */ - #define ACODEC_DAC_DATA_LO 0x2c /* REG 0x0b */ --/* Resevred REG 0x0c ~ 0x0f */ -+/* Resevred REG 0x0c */ -+#define ACODEC_DAC_HPDET_DELAYTIME 0x34 /* REG 0x0d */ -+#define ACODEC_DAC_HPDET_STATUS 0x38 /* REG 0x0e, Read-only */ -+/* Resevred REG 0x0f */ - - /* ADC ANALOG REGISTERS */ - #define ACODEC_ADC_ANA_MIC_CTL 0x00 /* REG 0x00 */ -@@ -92,10 +96,13 @@ - #define ACODEC_DAC_ANA_LINEOUT 0x10 /* REG 0x04 */ - #define ACODEC_DAC_ANA_L_HPOUT_GAIN 0x14 /* REG 0x05 */ - #define ACODEC_DAC_ANA_R_HPOUT_GAIN 0x18 /* REG 0x06 */ -+#define ACODEC_DAC_ANA_DRV_HPOUT 0x1c /* REG 0x07 */ -+#define ACODEC_DAC_ANA_DRV_LINEOUT 0x20 /* REG 0x08 */ - /* Resevred REG 0x07 ~ 0x0b */ - #define ACODEC_DAC_ANA_HPMIX_CTL0 0x30 /* REG 0x0c */ - #define ACODEC_DAC_ANA_HPMIX_CTL1 0x34 /* REG 0x0d */ --/* Resevred REG 0x0e ~ 0x0f */ -+#define ACODEC_DAC_ANA_LINEOUT_CTL0 0x38 /* REG 0x0e */ -+#define ACODEC_DAC_ANA_LINEOUT_CTL1 0x3c /* REG 0x0f */ - - /* - * These registers are referenced by codec driver -@@ -106,7 +113,7 @@ - /* ADC DIGITAL REGISTERS */ - - /* -- * The ADC chanel are 0 ~ 3, that control: -+ * The ADC group are 0 ~ 3, that control: - * - * CH0: left_0(ADC1) and right_0(ADC2) - * CH1: left_1(ADC3) and right_1(ADC4) -@@ -118,6 +125,7 @@ - #define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL0) - #define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL1) - #define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_BIST_MODE_SEL) -+#define RK3308_ADC_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_HPF_PATH) - #define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_DATA_PATH) - - #define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL0) -@@ -150,13 +158,16 @@ - #define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL0) - #define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL1) - #define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_BIST_MODE_SEL) -+#define RK3308_DAC_DIG_CON04 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DIGITAL_GAIN) - #define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_SEL) - #define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_HI) - #define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_LO) -+#define RK3308_DAC_DIG_CON13 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_DELAYTIME) -+#define RK3308_DAC_DIG_CON14 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_STATUS) - - /* ADC ANALOG REGISTERS */ - /* -- * The ADC chanel are 0 ~ 3, that control: -+ * The ADC group are 0 ~ 3, that control: - * - * CH0: left_0(ADC1) and right_0(ADC2) - * CH1: left_1(ADC3) and right_1(ADC4) -@@ -179,7 +190,6 @@ - - /* DAC ANALOG REGISTERS */ - #define RK3308_DAC_ANA_OFFSET 0x440 -- - #define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL0) - #define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_POP_VOLT) - #define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL1) -@@ -187,8 +197,12 @@ - #define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT) - #define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_L_HPOUT_GAIN) - #define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_R_HPOUT_GAIN) -+#define RK3308_DAC_ANA_CON07 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_DRV_HPOUT) -+#define RK3308_DAC_ANA_CON08 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_DRV_LINEOUT) - #define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL0) - #define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL1) -+#define RK3308_DAC_ANA_CON14 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT_CTL0) -+#define RK3308_DAC_ANA_CON15 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT_CTL1) - - /* - * These are the bits for registers -@@ -199,6 +213,12 @@ - #define RK3308_ADC_BIST_RESET (0 << 7) - #define RK3308_DAC_BIST_WORK (1 << 6) - #define RK3308_DAC_BIST_RESET (0 << 6) -+#define RK3308_ADC_MCLK_MSK (1 << 5) -+#define RK3308_ADC_MCLK_DIS (1 << 5) -+#define RK3308_ADC_MCLK_EN (0 << 5) -+#define RK3308_DAC_MCLK_MSK (1 << 4) -+#define RK3308_DAC_MCLK_DIS (1 << 4) -+#define RK3308_DAC_MCLK_EN (0 << 4) - #define RK3308_CODEC_RST_MSK (0x7 << 0) - #define RK3308_ADC_DIG_WORK (1 << 2) - #define RK3308_ADC_DIG_RESET (0 << 2) -@@ -253,16 +273,27 @@ - /* RK3308_ADC_DIG_CON03 - REG: 0x000c */ - #define RK3308_ADC_L_CH_BIST_SFT 2 - #define RK3308_ADC_L_CH_BIST_MSK (0x3 << RK3308_ADC_L_CH_BIST_SFT) --#define RK3308_ADC_L_CH_BIST_LEFT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ --#define RK3308_ADC_L_CH_BIST_SINE (0x2 << RK3308_ADC_L_CH_BIST_SFT) --#define RK3308_ADC_L_CH_BIST_CUBE (0x1 << RK3308_ADC_L_CH_BIST_SFT) --#define RK3308_ADC_L_CH_BIST_RIGHT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_L_CH_NORMAL_RIGHT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_L_CH_BIST_CUBE (0x2 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_SINE (0x1 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_NORMAL_LEFT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ - #define RK3308_ADC_R_CH_BIST_SFT 0 - #define RK3308_ADC_R_CH_BIST_MSK (0x3 << RK3308_ADC_R_CH_BIST_SFT) --#define RK3308_ADC_R_CH_BIST_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ --#define RK3308_ADC_R_CH_BIST_SINE (0x2 << RK3308_ADC_R_CH_BIST_SFT) --#define RK3308_ADC_R_CH_BIST_CUBE (0x1 << RK3308_ADC_R_CH_BIST_SFT) --#define RK3308_ADC_R_CH_BIST_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_NORMAL_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_BIST_CUBE (0x2 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_SINE (0x1 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_NORMAL_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+ -+/* RK3308_ADC_DIG_CON04 - REG: 0x0010 */ -+#define RK3308_ADC_HPF_PATH_SFT 2 -+#define RK3308_ADC_HPF_PATH_MSK (1 << RK3308_ADC_HPF_PATH_SFT) -+#define RK3308_ADC_HPF_PATH_DIS (1 << RK3308_ADC_HPF_PATH_SFT) -+#define RK3308_ADC_HPF_PATH_EN (0 << RK3308_ADC_HPF_PATH_SFT) -+#define RK3308_ADC_HPF_CUTOFF_SFT 0 -+#define RK3308_ADC_HPF_CUTOFF_MSK (0x3 << RK3308_ADC_HPF_CUTOFF_SFT) -+#define RK3308_ADC_HPF_CUTOFF_612HZ (0x2 << RK3308_ADC_HPF_CUTOFF_SFT) -+#define RK3308_ADC_HPF_CUTOFF_245HZ (0x1 << RK3308_ADC_HPF_CUTOFF_SFT) -+#define RK3308_ADC_HPF_CUTOFF_20HZ (0x0 << RK3308_ADC_HPF_CUTOFF_SFT) - - /* RK3308_ADC_DIG_CON07 - REG: 0x001c */ - #define RK3308_ADCL_DATA_SFT 4 -@@ -391,6 +422,8 @@ - */ - #define RK3308_AGC_PGA_ZERO_CRO_EN (0x1 << 5) - #define RK3308_AGC_PGA_ZERO_CRO_DIS (0x0 << 5) -+#define RK3308_AGC_PGA_GAIN_MAX 0x1f -+#define RK3308_AGC_PGA_GAIN_MIN 0 - #define RK3308_AGC_PGA_GAIN_SFT 0 - #define RK3308_AGC_PGA_GAIN_MSK (0x1f << RK3308_AGC_PGA_GAIN_SFT) - #define RK3308_AGC_PGA_GAIN_PDB_28_5 (0x1f << RK3308_AGC_PGA_GAIN_SFT) -@@ -474,6 +507,8 @@ - #define RK3308_AGC_FUNC_SEL_MSK (0x1 << 6) - #define RK3308_AGC_FUNC_SEL_EN (0x1 << 6) - #define RK3308_AGC_FUNC_SEL_DIS (0x0 << 6) -+#define RK3308_AGC_MAX_GAIN_PGA_MAX 0x7 -+#define RK3308_AGC_MAX_GAIN_PGA_MIN 0 - #define RK3308_AGC_MAX_GAIN_PGA_SFT 3 - #define RK3308_AGC_MAX_GAIN_PGA_MSK (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) - #define RK3308_AGC_MAX_GAIN_PGA_PDB_28_5 (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) -@@ -484,6 +519,8 @@ - #define RK3308_AGC_MAX_GAIN_PGA_NDB_1_5 (0x2 << RK3308_AGC_MAX_GAIN_PGA_SFT) - #define RK3308_AGC_MAX_GAIN_PGA_NDB_7_5 (0x1 << RK3308_AGC_MAX_GAIN_PGA_SFT) - #define RK3308_AGC_MAX_GAIN_PGA_NDB_13_5 (0x0 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_MAX 0x7 -+#define RK3308_AGC_MIN_GAIN_PGA_MIN 0 - #define RK3308_AGC_MIN_GAIN_PGA_SFT 0 - #define RK3308_AGC_MIN_GAIN_PGA_MSK (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) - #define RK3308_AGC_MIN_GAIN_PGA_PDB_24 (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) -@@ -555,6 +592,18 @@ - #define RK3308_DAC_R_CH_BIST_SINE (0x1 << RK3308_DAC_R_CH_BIST_SFT) - #define RK3308_DAC_R_CH_BIST_RIGHT (0x0 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ - -+/* RK3308_DAC_DIG_CON04 - REG: 0x0310 */ -+#define RK3308_DAC_MODULATOR_GAIN_SFT 4 -+#define RK3308_DAC_MODULATOR_GAIN_MSK (0x7 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_4_8DB (0x5 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_4_2DB (0x4 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_3_5DB (0x3 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_2_8DB (0x2 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_2DB (0x1 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_0DB (0x0 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_CIC_IF_GAIN_SFT 0 -+#define RK3308_DAC_CIC_IF_GAIN_MSK (0x7 << RK3308_DAC_CIC_IF_GAIN_SFT) -+ - /* RK3308_DAC_DIG_CON05 - REG: 0x0314 */ - #define RK3308_DAC_L_REG_CTL_INDATA (0x1 << 2) - #define RK3308_DAC_L_NORMAL_DATA (0x0 << 2) -@@ -587,18 +636,30 @@ - #define RK3308_ADC_CH1_BUF_REF_EN (0x1 << 0) - #define RK3308_ADC_CH1_BUF_REF_DIS (0x0 << 0) - --/* RK3308_ADC_ANA_CON01 - REG: 0x0344 */ -+/* RK3308_ADC_ANA_CON01 - REG: 0x0344 -+ * -+ * The PGA of MIC-INs: -+ * 0x0 - MIC1~MIC8 0dB -+ * 0x1 - MIC1~MIC8 6.6dB -+ * 0x2 - MIC1~MIC8 13dB -+ * 0x3 - MIC1~MIC8 20dB -+ */ -+#define RK3308_ADC_CH2_MIC_GAIN_MAX 0x3 -+#define RK3308_ADC_CH2_MIC_GAIN_MIN 0 - #define RK3308_ADC_CH2_MIC_GAIN_SFT 4 - #define RK3308_ADC_CH2_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) --#define RK3308_ADC_CH2_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) --#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) --#define RK3308_ADC_CH2_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) /* TRM: only used for version B */ -+#define RK3308_ADC_CH2_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) /* TRM: only used for version B */ - #define RK3308_ADC_CH2_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+ -+#define RK3308_ADC_CH1_MIC_GAIN_MAX 0x3 -+#define RK3308_ADC_CH1_MIC_GAIN_MIN 0 - #define RK3308_ADC_CH1_MIC_GAIN_SFT 0 - #define RK3308_ADC_CH1_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) --#define RK3308_ADC_CH1_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) --#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) --#define RK3308_ADC_CH1_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) /* TRM: only used for version B */ -+#define RK3308_ADC_CH1_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) /* TRM: only used for version B */ - #define RK3308_ADC_CH1_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH1_MIC_GAIN_SFT) - - /* RK3308_ADC_ANA_CON02 - REG: 0x0348 */ -@@ -619,6 +680,8 @@ - #define RK3308_ADC_CH1_ALC_DIS (0x0 << 0) - - /* RK3308_ADC_ANA_CON03 - REG: 0x034c */ -+#define RK3308_ADC_CH1_ALC_GAIN_MAX 0x1f -+#define RK3308_ADC_CH1_ALC_GAIN_MIN 0 - #define RK3308_ADC_CH1_ALC_GAIN_SFT 0 - #define RK3308_ADC_CH1_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) - #define RK3308_ADC_CH1_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) -@@ -655,6 +718,8 @@ - #define RK3308_ADC_CH1_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH1_ALC_GAIN_SFT) - - /* RK3308_ADC_ANA_CON04 - REG: 0x0350 */ -+#define RK3308_ADC_CH2_ALC_GAIN_MAX 0x1f -+#define RK3308_ADC_CH2_ALC_GAIN_MIN 0 - #define RK3308_ADC_CH2_ALC_GAIN_SFT 0 - #define RK3308_ADC_CH2_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) - #define RK3308_ADC_CH2_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) -@@ -728,10 +793,16 @@ - #define RK3308_ADC_CH1_IN_MIC (0x1 << RK3308_ADC_CH1_IN_SEL_SFT) - #define RK3308_ADC_CH1_IN_NONE (0x0 << RK3308_ADC_CH1_IN_SEL_SFT) - --#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << 3) --#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << 3) -+#define RK3308_ADC_MIC_BIAS_BUF_SFT 3 -+#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << RK3308_ADC_MIC_BIAS_BUF_SFT) -+#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << RK3308_ADC_MIC_BIAS_BUF_SFT) - #define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 - #define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+/* -+ * The follow MICBIAS_VOLTs are based on the external reference voltage(Vref). -+ * For example, the Vref == 3.3V, the MICBIAS_VOLT_0_85 is equal: -+ * 3.3V * 0.85 = 2.805V. -+ */ - #define RK3308_ADC_MICBIAS_VOLT_0_85 (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) - #define RK3308_ADC_MICBIAS_VOLT_0_8 (0x6 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) - #define RK3308_ADC_MICBIAS_VOLT_0_75 (0x5 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -@@ -751,18 +822,11 @@ - #define RK3308_ADC_REF_DIS (0x0 << 7) - #define RK3308_ADC_CURRENT_CHARGE_SFT 0 - #define RK3308_ADC_CURRENT_CHARGE_MSK (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) --#define RK3308_ADC_DONT_SEL_ALL (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) - /* -- * 0: Choose the current I -- * 1: Don't choose the current I -+ * 1: Choose the current I -+ * 0: Don't choose the current I - */ --#define RK3308_ADC_SEL_I_1(x) ((x & 0x1) << 6) --#define RK3308_ADC_SEL_I_2(x) ((x & 0x1) << 5) --#define RK3308_ADC_SEL_I_4(x) ((x & 0x1) << 4) --#define RK3308_ADC_SEL_I_8(x) ((x & 0x1) << 3) --#define RK3308_ADC_SEL_I_16(x) ((x & 0x1) << 2) --#define RK3308_ADC_SEL_I_32(x) ((x & 0x1) << 1) --#define RK3308_ADC_SEL_I_64(x) ((x & 0x1) << 0) -+#define RK3308_ADC_SEL_I(x) (x & 0x7f) - - /* RK3308_ADC_ANA_CON11 - REG: 0x036c */ - #define RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK (0x1 << 1) -@@ -773,6 +837,7 @@ - #define RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS (0x0 << 0) - - /* RK3308_DAC_ANA_CON00 - REG: 0x0440 */ -+#define RK3308_DAC_HEADPHONE_DET_MSK (0x1 << 1) - #define RK3308_DAC_HEADPHONE_DET_EN (0x1 << 1) - #define RK3308_DAC_HEADPHONE_DET_DIS (0x0 << 1) - #define RK3308_DAC_CURRENT_MSK (0x1 << 0) -@@ -783,17 +848,17 @@ - #define RK3308_DAC_BUF_REF_R_MSK (0x1 << 6) - #define RK3308_DAC_BUF_REF_R_EN (0x1 << 6) - #define RK3308_DAC_BUF_REF_R_DIS (0x0 << 6) --#define RK3308_DAC_POP_SOUND_R_SFT 4 --#define RK3308_DAC_POP_SOUND_R_MSK (0x3 << RK3308_DAC_POP_SOUND_R_SFT) --#define RK3308_DAC_POP_SOUND_R_WORK (0x2 << RK3308_DAC_POP_SOUND_R_SFT) --#define RK3308_DAC_POP_SOUND_R_INIT (0x1 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_R_SFT 4 -+#define RK3308_DAC_HPOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_R_WORK (0x2 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_R_INIT (0x1 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) - #define RK3308_DAC_BUF_REF_L_MSK (0x1 << 2) - #define RK3308_DAC_BUF_REF_L_EN (0x1 << 2) - #define RK3308_DAC_BUF_REF_L_DIS (0x0 << 2) --#define RK3308_DAC_POP_SOUND_L_SFT 0 --#define RK3308_DAC_POP_SOUND_L_MSK (0x3 << RK3308_DAC_POP_SOUND_L_SFT) --#define RK3308_DAC_POP_SOUND_L_WORK (0x2 << RK3308_DAC_POP_SOUND_L_SFT) --#define RK3308_DAC_POP_SOUND_L_INIT (0x1 << RK3308_DAC_POP_SOUND_L_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_L_SFT 0 -+#define RK3308_DAC_HPOUT_POP_SOUND_L_MSK (0x3 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_L_WORK (0x2 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_L_INIT (0x1 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) - - /* RK3308_DAC_ANA_CON02 - REG: 0x0448 */ - #define RK3308_DAC_R_DAC_WORK (0x1 << 7) -@@ -828,28 +893,31 @@ - #define RK3308_DAC_L_HPOUT_MUTE (0x0 << 0) - - /* RK3308_DAC_ANA_CON04 - REG: 0x0450 */ --#define RK3308_DAC_R_GAIN_SFT 6 --#define RK3308_DAC_R_GAIN_MSK (0x3 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_0DB (0x3 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_PDB_1_5 (0x2 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_PDB_3 (0x1 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_PDB_6 (0x0 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_MAX 0x3 -+#define RK3308_DAC_R_LINEOUT_GAIN_SFT 6 -+#define RK3308_DAC_R_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_R_LINEOUT_GAIN_SFT) - #define RK3308_DAC_R_LINEOUT_UNMUTE (0x1 << 5) - #define RK3308_DAC_R_LINEOUT_MUTE (0x0 << 5) - #define RK3308_DAC_R_LINEOUT_EN (0x1 << 4) - #define RK3308_DAC_R_LINEOUT_DIS (0x0 << 4) --#define RK3308_DAC_L_GAIN_SFT 2 --#define RK3308_DAC_L_GAIN_MSK (0x3 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_0DB (0x3 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_PDB_1_5 (0x2 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_PDB_3 (0x1 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_PDB_6 (0x0 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_MAX 0x3 -+#define RK3308_DAC_L_LINEOUT_GAIN_SFT 2 -+#define RK3308_DAC_L_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_L_LINEOUT_GAIN_SFT) - #define RK3308_DAC_L_LINEOUT_UNMUTE (0x1 << 1) - #define RK3308_DAC_L_LINEOUT_MUTE (0x0 << 1) - #define RK3308_DAC_L_LINEOUT_EN (0x1 << 0) - #define RK3308_DAC_L_LINEOUT_DIS (0x0 << 0) - - /* RK3308_DAC_ANA_CON05 - REG: 0x0454, step is 1.5db */ -+#define RK3308_DAC_L_HPOUT_GAIN_MAX 0x1e - #define RK3308_DAC_L_HPOUT_GAIN_SFT 0 - #define RK3308_DAC_L_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_L_HPOUT_GAIN_SFT) - #define RK3308_DAC_L_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_L_HPOUT_GAIN_SFT) -@@ -885,6 +953,7 @@ - #define RK3308_DAC_L_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_L_HPOUT_GAIN_SFT) - - /* RK3308_DAC_ANA_CON06 - REG: 0x0458, step is 1.5db */ -+#define RK3308_DAC_R_HPOUT_GAIN_MAX 0x1e - #define RK3308_DAC_R_HPOUT_GAIN_SFT 0 - #define RK3308_DAC_R_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_R_HPOUT_GAIN_SFT) - #define RK3308_DAC_R_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_R_HPOUT_GAIN_SFT) -@@ -919,6 +988,18 @@ - #define RK3308_DAC_R_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_R_HPOUT_GAIN_SFT) - #define RK3308_DAC_R_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_R_HPOUT_GAIN_SFT) - -+/* RK3308_DAC_ANA_CON07 - REG: 0x045c */ -+#define RK3308_DAC_R_HPOUT_DRV_SFT 4 -+#define RK3308_DAC_R_HPOUT_DRV_MSK (0xf << RK3308_DAC_R_HPOUT_DRV_SFT) -+#define RK3308_DAC_L_HPOUT_DRV_SFT 0 -+#define RK3308_DAC_L_HPOUT_DRV_MSK (0xf << RK3308_DAC_L_HPOUT_DRV_SFT) -+ -+/* RK3308_DAC_ANA_CON08 - REG: 0x0460 */ -+#define RK3308_DAC_R_LINEOUT_DRV_SFT 4 -+#define RK3308_DAC_R_LINEOUT_DRV_MSK (0xf << RK3308_DAC_R_LINEOUT_DRV_SFT) -+#define RK3308_DAC_L_LINEOUT_DRV_SFT 0 -+#define RK3308_DAC_L_LINEOUT_DRV_MSK (0xf << RK3308_DAC_L_LINEOUT_DRV_SFT) -+ - /* RK3308_DAC_ANA_CON12 - REG: 0x0470 */ - #define RK3308_DAC_R_HPMIX_SEL_SFT 6 - #define RK3308_DAC_R_HPMIX_SEL_MSK (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) -@@ -926,6 +1007,8 @@ - #define RK3308_DAC_R_HPMIX_LINEIN (0x2 << RK3308_DAC_R_HPMIX_SEL_SFT) - #define RK3308_DAC_R_HPMIX_I2S (0x1 << RK3308_DAC_R_HPMIX_SEL_SFT) - #define RK3308_DAC_R_HPMIX_NONE (0x0 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_MIN 0x1 -+#define RK3308_DAC_R_HPMIX_GAIN_MAX 0x2 - #define RK3308_DAC_R_HPMIX_GAIN_SFT 4 - #define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) - #define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) -@@ -936,6 +1019,8 @@ - #define RK3308_DAC_L_HPMIX_LINEIN (0x2 << RK3308_DAC_L_HPMIX_SEL_SFT) - #define RK3308_DAC_L_HPMIX_I2S (0x1 << RK3308_DAC_L_HPMIX_SEL_SFT) - #define RK3308_DAC_L_HPMIX_NONE (0x0 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_MIN 0x1 -+#define RK3308_DAC_L_HPMIX_GAIN_MAX 0x2 - #define RK3308_DAC_L_HPMIX_GAIN_SFT 0 - #define RK3308_DAC_L_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_L_HPMIX_GAIN_SFT) - #define RK3308_DAC_L_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_L_HPMIX_GAIN_SFT) -@@ -955,6 +1040,30 @@ - #define RK3308_DAC_L_HPMIX_EN (0x1 << 0) - #define RK3308_DAC_L_HPMIX_DIS (0x0 << 0) - -+/* RK3308_DAC_ANA_CON14 - REG: 0x0478 */ -+#define RK3308_DAC_VCM_LINEOUT_EN (0x1 << 4) -+#define RK3308_DAC_VCM_LINEOUT_DIS (0x0 << 4) -+#define RK3308_DAC_CURRENT_CHARGE_SFT 0 -+#define RK3308_DAC_CURRENT_CHARGE_MSK (0xf << RK3308_DAC_CURRENT_CHARGE_SFT) -+ -+/* -+ * 1: Choose the current I -+ * 0: Don't choose the current I -+ */ -+#define RK3308_DAC_SEL_I(x) (x & 0xf) -+ -+/* RK3308_DAC_ANA_CON15 - REG: 0x047C */ -+#define RK3308_DAC_LINEOUT_POP_SOUND_R_SFT 4 -+#define RK3308_DAC_LINEOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_R_SEL_DC_FROM_INTERNAL (0x2 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_R_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_LINEOUT_POP_SOUND_L_SFT 0 -+#define RK3308_DAC_LINEOUT_POP_SOUND_L_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_L_SEL_DC_FROM_INTERNAL (0x2 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_L_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+ - #define RK3308_HIFI 0x0 - - #endif /* __RK3308_CODEC_H__ */ -diff --git a/sound/soc/codecs/rk3308_codec_provider.h b/sound/soc/codecs/rk3308_codec_provider.h -new file mode 100644 -index 000000000000..68042b1328dc ---- /dev/null -+++ b/sound/soc/codecs/rk3308_codec_provider.h -@@ -0,0 +1,28 @@ -+/* -+ * rk3308_codec_provider.h -- RK3308 ALSA Soc Audio Driver -+ * -+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#ifndef __RK3308_CODEC_PROVIDER_H__ -+#define __RK3308_CODEC_PROVIDER_H__ -+ -+#ifdef CONFIG_SND_SOC_RK3308 -+extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+ struct snd_soc_jack *hpdet_jack); -+#endif -+ -+#endif /* __RK3308_CODEC_PROVIDER_H__ */ --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch b/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch deleted file mode 100644 index 0223222..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch +++ /dev/null @@ -1,459 +0,0 @@ -From b882c2185ab561ec88c2540623cfa49e2cb56956 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 19:35:42 +0100 -Subject: [PATCH 22/23] ASoC: rk3308_codec: replace codec to component - ---- - sound/soc/codecs/rk3308_codec.c | 159 ++++++++++++----------- - sound/soc/codecs/rk3308_codec_provider.h | 2 +- - 2 files changed, 84 insertions(+), 77 deletions(-) - -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -index 815e22fc346c..16bfb215586e 100644 ---- a/sound/soc/codecs/rk3308_codec.c -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -31,7 +31,7 @@ - #include - #include - #include --#include -+// #include - #include - #include - #include -@@ -156,7 +156,7 @@ struct rk3308_codec_priv { - struct gpio_desc *hp_ctl_gpio; - struct gpio_desc *spk_ctl_gpio; - struct gpio_desc *pa_drv_gpio; -- struct snd_soc_codec *codec; -+ struct snd_soc_component *component; - struct snd_soc_jack *hpdet_jack; - struct regulator *vcc_micbias; - u32 codec_ver; -@@ -883,8 +883,8 @@ static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { - static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - - if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -@@ -904,8 +904,8 @@ static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value = ucontrol->value.integer.value[0]; - int grp = e->reg; -@@ -970,8 +970,8 @@ static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -998,8 +998,8 @@ static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -1032,8 +1032,8 @@ static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -1064,8 +1064,8 @@ static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -1098,8 +1098,8 @@ static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - ucontrol->value.integer.value[0] = rk3308->micbias_volt; - -@@ -1109,8 +1109,8 @@ static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int volt = ucontrol->value.integer.value[0]; - int ret; - -@@ -1133,8 +1133,8 @@ static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - ucontrol->value.integer.value[0] = rk3308->enable_micbias; - -@@ -1144,8 +1144,8 @@ static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int on = ucontrol->value.integer.value[0]; - - if (on) { -@@ -1168,8 +1168,8 @@ static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int gain = ucontrol->value.integer.value[0]; - - if (gain > RK3308_ADC_CH1_MIC_GAIN_MAX) { -@@ -1197,8 +1197,8 @@ static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - -@@ -1222,8 +1222,8 @@ static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value = ucontrol->value.integer.value[0]; - -@@ -1259,8 +1259,8 @@ static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int dgain = ucontrol->value.integer.value[0]; - - if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) { -@@ -1283,8 +1283,8 @@ static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int dgain = ucontrol->value.integer.value[0]; - - if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) { -@@ -1408,9 +1408,9 @@ static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) - } - } - --static int rk3308_codec_reset(struct snd_soc_codec *codec) -+static int rk3308_codec_reset(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - reset_control_assert(rk3308->reset); - usleep_range(2000, 2500); /* estimated value */ -@@ -1452,10 +1452,10 @@ static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308) - return 0; - } - --static int rk3308_set_bias_level(struct snd_soc_codec *codec, -+static int rk3308_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - switch (level) { - case SND_SOC_BIAS_ON: -@@ -1473,11 +1473,11 @@ static int rk3308_set_bias_level(struct snd_soc_codec *codec, - return 0; - } - --static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -+static int rk3308_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) - { -- struct snd_soc_codec *codec = codec_dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; - int idx, grp, is_master; - int type = ADC_TYPE_ALL; -@@ -1721,8 +1721,8 @@ static int rk3308_codec_update_adc_grps(struct rk3308_codec_priv *rk3308, - - static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - int dgain; -@@ -3630,8 +3630,8 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct snd_pcm_str *playback_str = - &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; - int type = ADC_TYPE_LOOPBACK; -@@ -3705,8 +3705,8 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, - static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - int type = ADC_TYPE_LOOPBACK; - int idx, grp; - -@@ -3749,8 +3749,8 @@ static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, - static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - rk3308_codec_close_playback(rk3308); -@@ -3809,9 +3809,9 @@ static struct snd_soc_dai_driver rk3308_dai[] = { - }, - }; - --static int rk3308_suspend(struct snd_soc_codec *codec) -+static int rk3308_suspend(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - if (rk3308->no_deep_low_power) - goto out; -@@ -3822,13 +3822,13 @@ static int rk3308_suspend(struct snd_soc_codec *codec) - clk_disable_unprepare(rk3308->pclk); - - out: -- rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ rk3308_set_bias_level(component, SND_SOC_BIAS_OFF); - return 0; - } - --static int rk3308_resume(struct snd_soc_codec *codec) -+static int rk3308_resume(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - int ret = 0; - - if (rk3308->no_deep_low_power) -@@ -3857,7 +3857,7 @@ static int rk3308_resume(struct snd_soc_codec *codec) - - rk3308_codec_dlp_up(rk3308); - out: -- rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ rk3308_set_bias_level(component, SND_SOC_BIAS_STANDBY); - return ret; - } - -@@ -3972,7 +3972,7 @@ static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) - int ret; - - if (rk3308->codec_ver == ACODEC_VERSION_B) { -- ret = snd_soc_add_codec_controls(rk3308->codec, -+ ret = snd_soc_add_component_controls(rk3308->component, - mic_gains_b, - ARRAY_SIZE(mic_gains_b)); - if (ret) { -@@ -3982,7 +3982,7 @@ static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) - return ret; - } - } else { -- ret = snd_soc_add_codec_controls(rk3308->codec, -+ ret = snd_soc_add_component_controls(rk3308->component, - mic_gains_a, - ARRAY_SIZE(mic_gains_a)); - if (ret) { -@@ -4081,15 +4081,15 @@ static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308) - return 0; - } - --static int rk3308_probe(struct snd_soc_codec *codec) -+static int rk3308_probe(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - int ext_micbias; - -- rk3308->codec = codec; -+ rk3308->component = component; - rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); - -- rk3308_codec_reset(codec); -+ rk3308_codec_reset(component); - rk3308_codec_power_on(rk3308); - - /* From vendor recommend, disable micbias at first. */ -@@ -4108,9 +4108,9 @@ static int rk3308_probe(struct snd_soc_codec *codec) - return 0; - } - --static int rk3308_remove(struct snd_soc_codec *codec) -+static void rk3308_remove(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - rk3308_headphone_ctl(rk3308, 0); - rk3308_speaker_ctl(rk3308, 0); -@@ -4124,17 +4124,25 @@ static int rk3308_remove(struct snd_soc_codec *codec) - regcache_cache_only(rk3308->regmap, false); - regcache_sync(rk3308->regmap); - -- return 0; - } - --static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -- .probe = rk3308_probe, -- .remove = rk3308_remove, -- .suspend = rk3308_suspend, -- .resume = rk3308_resume, -- .set_bias_level = rk3308_set_bias_level, -- .controls = rk3308_codec_dapm_controls, -- .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+static const struct snd_soc_component_driver soc_codec_dev_rk3308_component = { -+ .probe = rk3308_probe, -+ .remove = rk3308_remove, -+ .resume = rk3308_resume, -+ .suspend = rk3308_suspend, -+ .set_bias_level = rk3308_set_bias_level, -+ .controls = rk3308_codec_dapm_controls, -+ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+ // .dapm_widgets = rk3308_dapm_widgets, -+ // .num_dapm_widgets = ARRAY_SIZE(rk3308_dapm_widgets), -+ // .dapm_routes = rk3308_dapm_routes, -+ // .num_dapm_routes = ARRAY_SIZE(rk3308_dapm_routes), -+ // .suspend_bias_off = 1, -+ // .idle_bias_on = 1, -+ // .use_pmdown_time = 1, -+ .endianness = 1, -+ .non_legacy_dai_naming = 1, - }; - - static const struct reg_default rk3308_codec_reg_defaults[] = { -@@ -4299,14 +4307,14 @@ static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data) - return IRQ_HANDLED; - } - --void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_component *component, - struct snd_soc_jack *hpdet_jack); - EXPORT_SYMBOL_GPL(rk3308_codec_set_jack_detect_cb); - --static void rk3308_codec_set_jack_detect(struct snd_soc_codec *codec, -+static void rk3308_codec_set_jack_detect(struct snd_soc_component *component, - struct snd_soc_jack *hpdet_jack) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - rk3308->hpdet_jack = hpdet_jack; - -@@ -5114,10 +5122,10 @@ static int rk3308_platform_probe(struct platform_device *pdev) - - platform_set_drvdata(pdev, rk3308); - -- ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3308, -+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3308_component, - rk3308_dai, ARRAY_SIZE(rk3308_dai)); - if (ret < 0) { -- dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); -+ dev_err(&pdev->dev, "Failed to register component: %d\n", ret); - goto failed; - } - -@@ -5140,7 +5148,6 @@ static int rk3308_platform_remove(struct platform_device *pdev) - clk_disable_unprepare(rk3308->mclk_rx); - clk_disable_unprepare(rk3308->mclk_tx); - clk_disable_unprepare(rk3308->pclk); -- snd_soc_unregister_codec(&pdev->dev); - device_unregister(&rk3308->dev); - - return 0; -diff --git a/sound/soc/codecs/rk3308_codec_provider.h b/sound/soc/codecs/rk3308_codec_provider.h -index 68042b1328dc..34c1ef86a507 100644 ---- a/sound/soc/codecs/rk3308_codec_provider.h -+++ b/sound/soc/codecs/rk3308_codec_provider.h -@@ -21,7 +21,7 @@ - #define __RK3308_CODEC_PROVIDER_H__ - - #ifdef CONFIG_SND_SOC_RK3308 --extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_component *component, - struct snd_soc_jack *hpdet_jack); - #endif - --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.13/general-emmc-hs400es-init-tweak.patch b/sys-kernel/decade-sources/files/patches-5.13/general-emmc-hs400es-init-tweak.patch deleted file mode 100644 index 03144ff..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/general-emmc-hs400es-init-tweak.patch +++ /dev/null @@ -1,22 +0,0 @@ -This patch is required to boot some Rock Pi 4 and NanoPC T4 units -with kernel 5.3+ and is on par with how it is done in Rockchip's BSP. - -diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c -index de8fbc396..95858e554 100644 ---- a/drivers/mmc/core/mmc.c -+++ b/drivers/mmc/core/mmc.c -@@ -1371,12 +1371,12 @@ static int mmc_select_hs400es(struct mmc_card *card) - } - - mmc_set_timing(host, MMC_TIMING_MMC_HS); -+ mmc_set_clock(host, card->ext_csd.hs_max_dtr); -+ - err = mmc_switch_status(card, true); - if (err) - goto out_err; - -- mmc_set_clock(host, card->ext_csd.hs_max_dtr); -- - /* Switch card to DDR with strobe bit */ - val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE; - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, diff --git a/sys-kernel/decade-sources/files/patches-5.13/general-fix-es8316-kernel-panic.patch b/sys-kernel/decade-sources/files/patches-5.13/general-fix-es8316-kernel-panic.patch deleted file mode 100644 index 3a27c0c..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/general-fix-es8316-kernel-panic.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/sound/soc/codecs/es8316.c 2020-04-09 19:13:08.268473737 +0000 -+++ b/sound/soc/codecs/es8316.c 2020-04-09 19:14:00.535995842 +0000 -@@ -687,7 +687,7 @@ - snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE, - ES8316_GPIO_ENABLE_INTERRUPT, 0); - -- if (es8316->jack->status & SND_JACK_MICROPHONE) { -+ if (es8316->jack && (es8316->jack->status & SND_JACK_MICROPHONE)) { - es8316_disable_micbias_for_mic_gnd_short_detect(component); - snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0); - } diff --git a/sys-kernel/decade-sources/files/patches-5.13/general-increasing_DMA_block_memory_allocation_to_2048.patch b/sys-kernel/decade-sources/files/patches-5.13/general-increasing_DMA_block_memory_allocation_to_2048.patch deleted file mode 100644 index fc6c248..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/general-increasing_DMA_block_memory_allocation_to_2048.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c -index 6bc74a2d5..e3827da51 100644 ---- a/kernel/dma/pool.c -+++ b/kernel/dma/pool.c -@@ -164,13 +164,11 @@ static int __init dma_atomic_pool_init(void) - int ret = 0; - - /* -- * If coherent_pool was not used on the command line, default the pool -- * sizes to 128KB per 1GB of memory, min 128KB, max MAX_ORDER-1. -+ * Always use 2MiB as default pool size. -+ * See: https://forum.armbian.com/topic/4811-uas-mainline-kernel-coherent-pool-memory-size/ - */ - if (!atomic_pool_size) { -- unsigned long pages = totalram_pages() / (SZ_1G / SZ_128K); -- pages = min_t(unsigned long, pages, MAX_ORDER_NR_PAGES); -- atomic_pool_size = max_t(size_t, pages << PAGE_SHIFT, SZ_128K); -+ atomic_pool_size = SZ_2M; - } - INIT_WORK(&atomic_pool_work, atomic_pool_work_fn); - diff --git a/sys-kernel/decade-sources/files/patches-5.13/general-rt5651-add-mclk.patch b/sys-kernel/decade-sources/files/patches-5.13/general-rt5651-add-mclk.patch deleted file mode 100644 index 26c6320..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/general-rt5651-add-mclk.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c -index c506c9305..41a08b320 100644 ---- a/sound/soc/codecs/rt5651.c -+++ b/sound/soc/codecs/rt5651.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #include "rl6231.h" - #include "rt5651.h" -@@ -1511,6 +1512,7 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, - static int rt5651_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) - { -+ struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); - switch (level) { - case SND_SOC_BIAS_PREPARE: - if (SND_SOC_BIAS_STANDBY == snd_soc_component_get_bias_level(component)) { -@@ -1518,6 +1520,13 @@ static int rt5651_set_bias_level(struct snd_soc_component *component, - snd_soc_component_update_bits(component, RT5651_D_MISC, - 0xc00, 0xc00); - } -+ if (!IS_ERR(rt5651->mclk)){ -+ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) { -+ clk_disable_unprepare(rt5651->mclk); -+ } else { -+ clk_prepare_enable(rt5651->mclk); -+ } -+ } - break; - case SND_SOC_BIAS_STANDBY: - if (SND_SOC_BIAS_OFF == snd_soc_component_get_bias_level(component)) { -@@ -2059,6 +2068,13 @@ static int rt5651_probe(struct snd_soc_component *component) - { - struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); - -+ /* Check if MCLK provided */ -+ rt5651->mclk = devm_clk_get(component->dev, "mclk"); -+ if (PTR_ERR(rt5651->mclk) == -EPROBE_DEFER){ -+ dev_err(component->dev, "unable to get mclk\n"); -+ return -EPROBE_DEFER; -+ } -+ - rt5651->component = component; - - snd_soc_component_update_bits(component, RT5651_PWR_ANLG1, -diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h -index 20c33a3ec..17524fa9f 100644 ---- a/sound/soc/codecs/rt5651.h -+++ b/sound/soc/codecs/rt5651.h -@@ -2097,6 +2097,7 @@ struct rt5651_priv { - - int dmic_en; - bool hp_mute; -+ struct clk *mclk; - }; - - #endif /* __RT5651_H__ */ diff --git a/sys-kernel/decade-sources/files/patches-5.13/rk3399-add-sclk-i2sout-src-clock.patch b/sys-kernel/decade-sources/files/patches-5.13/rk3399-add-sclk-i2sout-src-clock.patch deleted file mode 100644 index 5573ece..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/rk3399-add-sclk-i2sout-src-clock.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c -index ce1d2446f..38447441b 100644 ---- a/drivers/clk/rockchip/clk-rk3399.c -+++ b/drivers/clk/rockchip/clk-rk3399.c -@@ -620,7 +620,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { - GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT, - RK3399_CLKGATE_CON(8), 11, GFLAGS), - -- MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, -+ MUX(SCLK_I2SOUT_SRC, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, - RK3399_CLKSEL_CON(31), 0, 2, MFLAGS), - COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT, - RK3399_CLKSEL_CON(31), 2, 1, MFLAGS, -diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h -index 44e0a319f..b7b07dfda 100644 ---- a/include/dt-bindings/clock/rk3399-cru.h -+++ b/include/dt-bindings/clock/rk3399-cru.h -@@ -19,6 +19,7 @@ - #define ARMCLKB 9 - - /* sclk gates (special clocks) */ -+#define SCLK_I2SOUT_SRC 64 - #define SCLK_I2C1 65 - #define SCLK_I2C2 66 - #define SCLK_I2C3 67 diff --git a/sys-kernel/decade-sources/files/patches-5.13/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch b/sys-kernel/decade-sources/files/patches-5.13/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch deleted file mode 100644 index 8ca2079..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index bcd31e9d6..91f1aa809 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -396,6 +396,7 @@ usbdrd_dwc3_0: usb@fe800000 { - snps,dis_u2_susphy_quirk; - snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; -+ snps,xhci-trb-ent-quirk; - power-domains = <&power RK3399_PD_USB3>; - status = "disabled"; - }; -@@ -461,6 +462,7 @@ usbdrd_dwc3_1: usb@fe900000 { - snps,dis_u2_susphy_quirk; - snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; -+ snps,xhci-trb-ent-quirk; - power-domains = <&power RK3399_PD_USB3>; - status = "disabled"; - }; diff --git a/sys-kernel/decade-sources/files/patches-5.13/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch b/sys-kernel/decade-sources/files/patches-5.13/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch deleted file mode 100644 index 662969f..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 9de42a7ce7b821596a151cfaa0aca79d53c2170f Mon Sep 17 00:00:00 2001 -From: Igor Pecovnik -Date: Sun, 7 Mar 2021 15:24:02 +0100 -Subject: [PATCH] oo - -Signed-off-by: Aditya Prayoga -Changed by: Igor Pecovnik ---- - drivers/pci/controller/pcie-rockchip.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c -index 990a00e08..193d26562 100644 ---- a/drivers/pci/controller/pcie-rockchip.c -+++ b/drivers/pci/controller/pcie-rockchip.c -@@ -118,8 +118,7 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) - } - - if (rockchip->is_rc) { -- rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", -- GPIOD_OUT_HIGH); -+ rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", GPIOD_OUT_HIGH); - if (IS_ERR(rockchip->ep_gpio)) - return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio), - "failed to get ep GPIO\n"); --- -Created with Armbian build tools https://github.com/armbian/build - diff --git a/sys-kernel/decade-sources/files/patches-5.13/rk3399-sd-drive-level-8ma.patch b/sys-kernel/decade-sources/files/patches-5.13/rk3399-sd-drive-level-8ma.patch deleted file mode 100644 index cac129a..0000000 --- a/sys-kernel/decade-sources/files/patches-5.13/rk3399-sd-drive-level-8ma.patch +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index 6eb9dda..d6fc676 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -2285,35 +2285,35 @@ - sdmmc { - sdmmc_bus1: sdmmc-bus1 { - rockchip,pins = -- <4 RK_PB0 1 &pcfg_pull_up>; -+ <4 RK_PB0 1 &pcfg_pull_up_8ma>; - }; - - sdmmc_bus4: sdmmc-bus4 { - rockchip,pins = -- <4 RK_PB0 1 &pcfg_pull_up>, -- <4 RK_PB1 1 &pcfg_pull_up>, -- <4 RK_PB2 1 &pcfg_pull_up>, -- <4 RK_PB3 1 &pcfg_pull_up>; -+ <4 RK_PB0 1 &pcfg_pull_up_8ma>, -+ <4 RK_PB1 1 &pcfg_pull_up_8ma>, -+ <4 RK_PB2 1 &pcfg_pull_up_8ma>, -+ <4 RK_PB3 1 &pcfg_pull_up_8ma>; - }; - - sdmmc_clk: sdmmc-clk { - rockchip,pins = -- <4 RK_PB4 1 &pcfg_pull_none>; -+ <4 RK_PB4 1 &pcfg_pull_none_12ma>; - }; - - sdmmc_cmd: sdmmc-cmd { - rockchip,pins = -- <4 RK_PB5 1 &pcfg_pull_up>; -+ <4 RK_PB5 1 &pcfg_pull_up_8ma>; - }; - - sdmmc_cd: sdmmc-cd { - rockchip,pins = -- <0 RK_PA7 1 &pcfg_pull_up>; -+ <0 RK_PA7 1 &pcfg_pull_up>; - }; - - sdmmc_wp: sdmmc-wp { - rockchip,pins = -- <0 RK_PB0 1 &pcfg_pull_up>; -+ <0 RK_PB0 1 &pcfg_pull_up_8ma>; - }; - }; - diff --git a/sys-kernel/decade-sources/files/patches-5.14/add-board-nanopi-m4v2.patch b/sys-kernel/decade-sources/files/patches-5.14/add-board-nanopi-m4v2.patch deleted file mode 100644 index bd49039..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/add-board-nanopi-m4v2.patch +++ /dev/null @@ -1,95 +0,0 @@ ---- a/arch/arm64/boot/dts/rockchip/Makefile 2021-09-20 23:45:28.127697569 +0200 -+++ b/arch/arm64/boot/dts/rockchip/Makefile 2021-09-20 23:45:13.637825192 +0200 -@@ -34,6 +34,7 @@ - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-leez-p710.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4v2.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4b.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-neo4.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-r4s.dtb - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -new file mode 100644 -index 000000000..60358ab8c ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * FriendlyElec NanoPi M4V2 board device tree source -+ * -+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * Copyright (c) 2018 Collabora Ltd. -+ * Copyright (c) 2019 Arm Ltd. -+ */ -+ -+/dts-v1/; -+#include "rk3399-nanopi4.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi M4 Ver2.0"; -+ compatible = "friendlyarm,nanopi-m4", "rockchip,rk3399"; -+ -+ vdd_5v: vdd-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "vdd_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vcc5v0_core: vcc5v0-core { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_core"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vdd_5v>; -+ }; -+ -+ vcc5v0_usb1: vcc5v0-usb1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_usb1"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vcc5v0_usb2: vcc5v0-usb2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_usb2"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vdd_log: vdd-log { -+ compatible = "pwm-regulator"; -+ pwms = <&pwm2 0 25000 1>; -+ regulator-name = "vdd_log"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-init-microvolt = <900000>; -+ vin-supply = <&vcc5v0_core>; -+ }; -+}; -+ -+&vcc3v3_sys { -+ vin-supply = <&vcc5v0_core>; -+}; -+ -+&u2phy0_host { -+ phy-supply = <&vcc5v0_usb1>; -+}; -+ -+&u2phy1_host { -+ phy-supply = <&vcc5v0_usb2>; -+}; -+ -+&vbus_typec { -+ regulator-always-on; -+ vin-supply = <&vdd_5v>; -+}; diff --git a/sys-kernel/decade-sources/files/patches-5.14/add-csgpio-to-rockchip-spi.patch b/sys-kernel/decade-sources/files/patches-5.14/add-csgpio-to-rockchip-spi.patch deleted file mode 100644 index b65a5b1..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/add-csgpio-to-rockchip-spi.patch +++ /dev/null @@ -1,83 +0,0 @@ -diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c -index 2cc6d99..19e05ad 100644 ---- a/drivers/spi/spi-rockchip.c -+++ b/drivers/spi/spi-rockchip.c -@@ -6,6 +6,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -185,6 +186,10 @@ struct rockchip_spi { - bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; - }; - -+struct rockchip_spi_data { -+ bool cs_gpio_requested; -+}; -+ - static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable) - { - writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR); -@@ -455,6 +460,50 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs, - return 1; - } - -+static int rockchip_spi_setup(struct spi_device *spi) -+{ -+ int ret = 0; -+ unsigned long flags = (spi->mode & SPI_CS_HIGH) ? -+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; -+ struct rockchip_spi_data *data = spi_get_ctldata(spi); -+ -+ if (!gpio_is_valid(spi->cs_gpio)) -+ return 0; -+ -+ if (!data) { -+ data = kzalloc(sizeof(*data), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ spi_set_ctldata(spi, data); -+ } -+ -+ if (!data->cs_gpio_requested) { -+ ret = gpio_request_one(spi->cs_gpio, flags, -+ dev_name(&spi->dev)); -+ if (!ret) -+ data->cs_gpio_requested = 1; -+ } else -+ ret = gpio_direction_output(spi->cs_gpio, flags); -+ -+ if (ret < 0) -+ dev_err(&spi->dev, "Failed to setup cs gpio(%d): %d\n", -+ spi->cs_gpio, ret); -+ -+ return ret; -+} -+ -+static void rockchip_spi_cleanup(struct spi_device *spi) -+{ -+ struct rockchip_spi_data *data = spi_get_ctldata(spi); -+ -+ if (data) { -+ if (data->cs_gpio_requested) -+ gpio_free(spi->cs_gpio); -+ kfree(data); -+ spi_set_ctldata(spi, NULL); -+ } -+} -+ - static int rockchip_spi_config(struct rockchip_spi *rs, - struct spi_device *spi, struct spi_transfer *xfer, - bool use_dma) -@@ -683,6 +732,8 @@ static int rockchip_spi_probe(struct platform_device *pdev) - ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT); - - ctlr->set_cs = rockchip_spi_set_cs; -+ ctlr->setup = rockchip_spi_setup; -+ ctlr->cleanup = rockchip_spi_cleanup; - ctlr->transfer_one = rockchip_spi_transfer_one; - ctlr->max_transfer_size = rockchip_spi_max_transfer_size; - ctlr->handle_err = rockchip_spi_handle_err; diff --git a/sys-kernel/decade-sources/files/patches-5.14/add-fusb30x-driver.patch b/sys-kernel/decade-sources/files/patches-5.14/add-fusb30x-driver.patch deleted file mode 100644 index 67233f0..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/add-fusb30x-driver.patch +++ /dev/null @@ -1,4047 +0,0 @@ -diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig -index 1abf76be2..7ad8b090c 100644 ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -92,6 +92,8 @@ source "drivers/staging/fbtft/Kconfig" - - source "drivers/staging/fsl-dpaa2/Kconfig" - -+source "drivers/staging/fusb30x/Kconfig" -+ - source "drivers/staging/most/Kconfig" - - source "drivers/staging/ks7010/Kconfig" -diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile -index ab0cbe881..2e308d901 100644 ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -36,6 +36,7 @@ obj-$(CONFIG_UNISYSSPAR) += unisys/ - obj-$(CONFIG_UNISYSSPAR) += unisys/ - obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ - obj-$(CONFIG_FB_TFT) += fbtft/ -+obj-$(CONFIG_FUSB_30X) += fusb30x/ - obj-$(CONFIG_MOST) += most/ - obj-$(CONFIG_KS7010) += ks7010/ - obj-$(CONFIG_GREYBUS) += greybus/ -diff --git a/drivers/staging/fusb30x/Kconfig b/drivers/staging/fusb30x/Kconfig -new file mode 100644 -index 000000000..5bb75270f ---- /dev/null -+++ b/drivers/staging/fusb30x/Kconfig -@@ -0,0 +1,10 @@ -+config FUSB_30X -+ tristate "Fairchild FUSB30X Type-C chip driver" -+ depends on I2C -+ help -+ This is a driver for the Fairchild FUSB302 Type-C chip. It supports -+ USB Type-C PD functionality controlled using I2C. -+ -+ This driver supports extcon reporting not yet implemented in the -+ mainline FUSB302 driver. -+ -diff --git a/drivers/staging/fusb30x/Makefile b/drivers/staging/fusb30x/Makefile -new file mode 100644 -index 000000000..1c8e35df3 ---- /dev/null -+++ b/drivers/staging/fusb30x/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_FUSB_30X) += fusb30x.o -diff --git a/drivers/staging/fusb30x/fusb30x.c b/drivers/staging/fusb30x/fusb30x.c -new file mode 100644 -index 000000000..56d22648c ---- /dev/null -+++ b/drivers/staging/fusb30x/fusb30x.c -@@ -0,0 +1,3434 @@ -+/* -+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd -+ * Author: Zain Wang -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * Some ideas are from chrome ec and fairchild GPL fusb302 driver. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "fusb30x.h" -+ -+#define FUSB302_MAX_REG (FUSB_REG_FIFO + 50) -+#define FUSB_MS_TO_NS(x) ((s64)x * 1000 * 1000) -+ -+#define TYPEC_CC_VOLT_OPEN 0 -+#define TYPEC_CC_VOLT_RA 1 -+#define TYPEC_CC_VOLT_RD 2 -+#define TYPEC_CC_VOLT_RP 3 -+ -+#define EVENT_CC BIT(0) -+#define EVENT_RX BIT(1) -+#define EVENT_TX BIT(2) -+#define EVENT_REC_RESET BIT(3) -+#define EVENT_WORK_CONTINUE BIT(5) -+#define EVENT_TIMER_MUX BIT(6) -+#define EVENT_TIMER_STATE BIT(7) -+#define EVENT_DELAY_CC BIT(8) -+#define FLAG_EVENT (EVENT_RX | EVENT_TIMER_MUX | \ -+ EVENT_TIMER_STATE) -+ -+#define PACKET_IS_CONTROL_MSG(header, type) \ -+ (PD_HEADER_CNT(header) == 0 && \ -+ PD_HEADER_TYPE(header) == type) -+ -+#define PACKET_IS_DATA_MSG(header, type) \ -+ (PD_HEADER_CNT(header) != 0 && \ -+ PD_HEADER_TYPE(header) == type) -+ -+/* -+ * DisplayPort modes capabilities -+ * ------------------------------- -+ * <31:24> : Reserved (always 0). -+ * <23:16> : UFP_D pin assignment supported -+ * <15:8> : DFP_D pin assignment supported -+ * <7> : USB 2.0 signaling (0b=yes, 1b=no) -+ * <6> : Plug | Receptacle (0b == plug, 1b == receptacle) -+ * <5:2> : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling -+ * Other bits are reserved. -+ * <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both ) -+ */ -+#define PD_DP_PIN_CAPS(x) ((((x) >> 6) & 0x1) ? (((x) >> 16) & 0x3f) \ -+ : (((x) >> 8) & 0x3f)) -+#define PD_DP_SIGNAL_GEN2(x) (((x) >> 3) & 0x1) -+ -+#define MODE_DP_PIN_A BIT(0) -+#define MODE_DP_PIN_B BIT(1) -+#define MODE_DP_PIN_C BIT(2) -+#define MODE_DP_PIN_D BIT(3) -+#define MODE_DP_PIN_E BIT(4) -+#define MODE_DP_PIN_F BIT(5) -+ -+/* Pin configs B/D/F support multi-function */ -+#define MODE_DP_PIN_MF_MASK (MODE_DP_PIN_B | MODE_DP_PIN_D | MODE_DP_PIN_F) -+/* Pin configs A/B support BR2 signaling levels */ -+#define MODE_DP_PIN_BR2_MASK (MODE_DP_PIN_A | MODE_DP_PIN_B) -+/* Pin configs C/D/E/F support DP signaling levels */ -+#define MODE_DP_PIN_DP_MASK (MODE_DP_PIN_C | MODE_DP_PIN_D | \ -+ MODE_DP_PIN_E | MODE_DP_PIN_F) -+ -+/* -+ * DisplayPort Status VDO -+ * ---------------------- -+ * <31:9> : Reserved (always 0). -+ * <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0. -+ * <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH -+ * <6> : Exit DP Alt mode: 0 == maintain, 1 == exit -+ * <5> : USB config : 0 == maintain current, 1 == switch to USB from DP -+ * <4> : Multi-function preference : 0 == no pref, 1 == MF preferred. -+ * <3> : enabled : is DPout on/off. -+ * <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM -+ * <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled. -+ * 01b == DFP_D connected, 10b == UFP_D connected, 11b == both. -+ */ -+#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 0x1) -+#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 0x1) -+#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 0x1) -+ -+static u8 fusb30x_port_used; -+static struct fusb30x_chip *fusb30x_port_info[256]; -+ -+static bool is_write_reg(struct device *dev, unsigned int reg) -+{ -+ if (reg >= FUSB_REG_FIFO) -+ return true; -+ else -+ return ((reg < (FUSB_REG_CONTROL4 + 1)) && (reg > 0x01)) ? -+ true : false; -+} -+ -+static bool is_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ if (reg > FUSB_REG_CONTROL4) -+ return true; -+ -+ switch (reg) { -+ case FUSB_REG_CONTROL0: -+ case FUSB_REG_CONTROL1: -+ case FUSB_REG_CONTROL3: -+ case FUSB_REG_RESET: -+ return true; -+ } -+ return false; -+} -+ -+struct regmap_config fusb302_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .writeable_reg = is_write_reg, -+ .volatile_reg = is_volatile_reg, -+ .max_register = FUSB302_MAX_REG, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ -+static void dump_notify_info(struct fusb30x_chip *chip) -+{ -+ dev_dbg(chip->dev, "port %d\n", chip->port_num); -+ dev_dbg(chip->dev, "orientation %d\n", chip->notify.orientation); -+ dev_dbg(chip->dev, "power_role %d\n", chip->notify.power_role); -+ dev_dbg(chip->dev, "data_role %d\n", chip->notify.data_role); -+ dev_dbg(chip->dev, "cc %d\n", chip->notify.is_cc_connected); -+ dev_dbg(chip->dev, "pd %d\n", chip->notify.is_pd_connected); -+ dev_dbg(chip->dev, "enter_mode %d\n", chip->notify.is_enter_mode); -+ dev_dbg(chip->dev, "pin support %d\n", -+ chip->notify.pin_assignment_support); -+ dev_dbg(chip->dev, "pin def %d\n", chip->notify.pin_assignment_def); -+ dev_dbg(chip->dev, "attention %d\n", chip->notify.attention); -+} -+ -+static const unsigned int fusb302_cable[] = { -+ EXTCON_USB, -+ EXTCON_USB_HOST, -+ EXTCON_CHG_USB_SDP, -+ EXTCON_CHG_USB_CDP, -+ EXTCON_CHG_USB_DCP, -+ EXTCON_CHG_USB_SLOW, -+ EXTCON_CHG_USB_FAST, -+ EXTCON_DISP_DP, -+ EXTCON_NONE, -+}; -+ -+static void fusb_set_pos_power(struct fusb30x_chip *chip, int max_vol, -+ int max_cur) -+{ -+ int i; -+ int pos_find; -+ int tmp; -+ -+ pos_find = 0; -+ for (i = PD_HEADER_CNT(chip->rec_head) - 1; i >= 0; i--) { -+ switch (CAP_POWER_TYPE(chip->rec_load[i])) { -+ case 0: -+ /* Fixed Supply */ -+ if ((CAP_FPDO_VOLTAGE(chip->rec_load[i]) * 50) <= -+ max_vol && -+ (CAP_FPDO_CURRENT(chip->rec_load[i]) * 10) <= -+ max_cur) { -+ chip->pos_power = i + 1; -+ tmp = CAP_FPDO_VOLTAGE(chip->rec_load[i]); -+ chip->pd_output_vol = tmp * 50; -+ tmp = CAP_FPDO_CURRENT(chip->rec_load[i]); -+ chip->pd_output_cur = tmp * 10; -+ pos_find = 1; -+ } -+ break; -+ case 1: -+ /* Battery */ -+ if ((CAP_VPDO_VOLTAGE(chip->rec_load[i]) * 50) <= -+ max_vol && -+ (CAP_VPDO_CURRENT(chip->rec_load[i]) * 10) <= -+ max_cur) { -+ chip->pos_power = i + 1; -+ tmp = CAP_VPDO_VOLTAGE(chip->rec_load[i]); -+ chip->pd_output_vol = tmp * 50; -+ tmp = CAP_VPDO_CURRENT(chip->rec_load[i]); -+ chip->pd_output_cur = tmp * 10; -+ pos_find = 1; -+ } -+ break; -+ default: -+ /* not meet battery caps */ -+ break; -+ } -+ if (pos_find) -+ break; -+ } -+} -+ -+static int fusb302_set_pos_power_by_charge_ic(struct fusb30x_chip *chip) -+{ -+ struct power_supply *psy = NULL; -+ union power_supply_propval val; -+ enum power_supply_property psp; -+ int max_vol, max_cur; -+ -+ max_vol = 0; -+ max_cur = 0; -+ psy = power_supply_get_by_phandle(chip->dev->of_node, "charge-dev"); -+ if (!psy || IS_ERR(psy)) -+ return -1; -+ -+ psp = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX; -+ if (power_supply_get_property(psy, psp, &val) == 0) -+ max_vol = val.intval / 1000; -+ -+ psp = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT; -+ if (power_supply_get_property(psy, psp, &val) == 0) -+ max_cur = val.intval / 1000; -+ -+ if (max_vol > 0 && max_cur > 0) -+ fusb_set_pos_power(chip, max_vol, max_cur); -+ -+ return 0; -+} -+ -+void fusb_irq_disable(struct fusb30x_chip *chip) -+{ -+ unsigned long irqflags = 0; -+ -+ spin_lock_irqsave(&chip->irq_lock, irqflags); -+ if (chip->enable_irq) { -+ disable_irq_nosync(chip->gpio_int_irq); -+ chip->enable_irq = 0; -+ } else { -+ dev_warn(chip->dev, "irq have already disabled\n"); -+ } -+ spin_unlock_irqrestore(&chip->irq_lock, irqflags); -+} -+ -+void fusb_irq_enable(struct fusb30x_chip *chip) -+{ -+ unsigned long irqflags = 0; -+ -+ spin_lock_irqsave(&chip->irq_lock, irqflags); -+ if (!chip->enable_irq) { -+ enable_irq(chip->gpio_int_irq); -+ chip->enable_irq = 1; -+ } -+ spin_unlock_irqrestore(&chip->irq_lock, irqflags); -+} -+ -+static void platform_fusb_notify(struct fusb30x_chip *chip) -+{ -+ bool plugged = false, flip = false, dfp = false, ufp = false, -+ dp = false, usb_ss = false, hpd = false; -+ union extcon_property_value property; -+ -+ if (chip->notify.is_cc_connected) -+ chip->notify.orientation = -+ (chip->cc_polarity == TYPEC_POLARITY_CC1) ? -+ CC1 : CC2; -+ -+ /* avoid notify repeated */ -+ if (memcmp(&chip->notify, &chip->notify_cmp, -+ sizeof(struct notify_info))) { -+ dump_notify_info(chip); -+ chip->notify.attention = false; -+ memcpy(&chip->notify_cmp, &chip->notify, -+ sizeof(struct notify_info)); -+ -+ plugged = chip->notify.is_cc_connected || -+ chip->notify.is_pd_connected; -+ if (chip->notify.orientation != NONE) -+ flip = (chip->notify.orientation == CC1) ? false : true; -+ dp = chip->notify.is_enter_mode; -+ -+ if (dp) { -+ dfp = true; -+ usb_ss = (chip->notify.pin_assignment_def & -+ MODE_DP_PIN_MF_MASK) ? true : false; -+ hpd = GET_DP_STATUS_HPD(chip->notify.dp_status); -+ } else if (chip->notify.data_role) { -+ dfp = true; -+ usb_ss = true; -+ } else if (plugged) { -+ ufp = true; -+ usb_ss = true; -+ } -+ -+ property.intval = flip; -+ extcon_set_property(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_TYPEC_POLARITY, property); -+ extcon_set_property(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_TYPEC_POLARITY, property); -+ extcon_set_property(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_TYPEC_POLARITY, property); -+ -+ property.intval = usb_ss; -+ extcon_set_property(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_SS, property); -+ extcon_set_property(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_SS, property); -+ extcon_set_property(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_SS, property); -+ extcon_set_state(chip->extcon, EXTCON_USB, ufp); -+ extcon_set_state(chip->extcon, EXTCON_USB_HOST, dfp); -+ extcon_set_state(chip->extcon, EXTCON_DISP_DP, dp && hpd); -+ extcon_sync(chip->extcon, EXTCON_USB); -+ extcon_sync(chip->extcon, EXTCON_USB_HOST); -+ extcon_sync(chip->extcon, EXTCON_DISP_DP); -+ if (chip->notify.power_role == POWER_ROLE_SINK && -+ chip->notify.is_pd_connected && -+ chip->pd_output_vol > 0 && chip->pd_output_cur > 0) { -+ extcon_set_state(chip->extcon, EXTCON_CHG_USB_FAST, true); -+ property.intval = -+ (chip->pd_output_cur << 15 | -+ chip->pd_output_vol); -+ extcon_set_property(chip->extcon, EXTCON_CHG_USB_FAST, -+ EXTCON_PROP_USB_TYPEC_POLARITY, -+ property); -+ extcon_sync(chip->extcon, EXTCON_CHG_USB_FAST); -+ } -+ } -+} -+ -+static bool platform_get_device_irq_state(struct fusb30x_chip *chip) -+{ -+ return !gpiod_get_value(chip->gpio_int); -+} -+ -+static void fusb_timer_start(struct hrtimer *timer, int ms) -+{ -+ ktime_t ktime; -+ -+ ktime = ktime_set(0, FUSB_MS_TO_NS(ms)); -+ hrtimer_start(timer, ktime, HRTIMER_MODE_REL); -+} -+ -+static void platform_set_vbus_lvl_enable(struct fusb30x_chip *chip, int vbus_5v, -+ int vbus_other) -+{ -+ bool gpio_vbus_value = false; -+ -+ gpio_vbus_value = gpiod_get_value(chip->gpio_vbus_5v); -+ if (chip->gpio_vbus_5v) { -+ gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_5v); -+ } -+ -+ if (chip->gpio_vbus_other) -+ gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_other); -+ -+ if (chip->gpio_discharge && !vbus_5v && gpio_vbus_value) { -+ gpiod_set_value(chip->gpio_discharge, 1); -+ msleep(20); -+ gpiod_set_value(chip->gpio_discharge, 0); -+ } -+} -+ -+static void set_state(struct fusb30x_chip *chip, enum connection_state state) -+{ -+ dev_dbg(chip->dev, "port %d, state %d\n", chip->port_num, state); -+ if (!state) -+ dev_info(chip->dev, "PD disabled\n"); -+ chip->conn_state = state; -+ chip->sub_state = 0; -+ chip->val_tmp = 0; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+} -+ -+static int tcpm_get_message(struct fusb30x_chip *chip) -+{ -+ u8 buf[32]; -+ int len; -+ -+ do { -+ regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, 3); -+ chip->rec_head = (buf[1] & 0xff) | ((buf[2] << 8) & 0xff00); -+ -+ len = PD_HEADER_CNT(chip->rec_head) << 2; -+ regmap_raw_read(chip->regmap, FUSB_REG_FIFO, buf, len + 4); -+ /* ignore good_crc message */ -+ } while (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_GOODCRC)); -+ -+ memcpy(chip->rec_load, buf, len); -+ -+ return 0; -+} -+ -+static void fusb302_flush_rx_fifo(struct fusb30x_chip *chip) -+{ -+ regmap_write(chip->regmap, FUSB_REG_CONTROL1, CONTROL1_RX_FLUSH); -+} -+ -+static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2) -+{ -+ u32 val; -+ int *CC_MEASURE; -+ u32 store; -+ -+ *CC1 = TYPEC_CC_VOLT_OPEN; -+ *CC2 = TYPEC_CC_VOLT_OPEN; -+ -+ if (chip->cc_state & CC_STATE_TOGSS_CC1) -+ CC_MEASURE = CC1; -+ else -+ CC_MEASURE = CC2; -+ -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) { -+ regmap_read(chip->regmap, FUSB_REG_SWITCHES0, &store); -+ /* measure cc1 first */ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2 | -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2, -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2 | -+ SWITCHES0_MEAS_CC1); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ val &= STATUS0_BC_LVL; -+ *CC1 = val ? TYPEC_CC_VOLT_RP : TYPEC_CC_VOLT_OPEN; -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2 | -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2, -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2 | -+ SWITCHES0_MEAS_CC2); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ val &= STATUS0_BC_LVL; -+ *CC2 = val ? TYPEC_CC_VOLT_RP : TYPEC_CC_VOLT_OPEN; -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2, -+ store); -+ } else { -+ regmap_read(chip->regmap, FUSB_REG_SWITCHES0, &store); -+ val = store; -+ val &= ~(SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2); -+ if (chip->cc_state & CC_STATE_TOGSS_CC1) { -+ val |= SWITCHES0_MEAS_CC1 | SWITCHES0_PU_EN1; -+ } else { -+ val |= SWITCHES0_MEAS_CC2 | SWITCHES0_PU_EN2; -+ } -+ regmap_write(chip->regmap, FUSB_REG_SWITCHES0, val); -+ -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, chip->cc_meas_high); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ if (val & STATUS0_COMP) { -+ int retry = 3; -+ int comp_times = 0; -+ -+ while (retry--) { -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, chip->cc_meas_high); -+ usleep_range(250, 300); -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ if (val & STATUS0_COMP) { -+ comp_times++; -+ if (comp_times == 3) { -+ *CC_MEASURE = TYPEC_CC_VOLT_OPEN; -+ regmap_write(chip->regmap, FUSB_REG_SWITCHES0, store); -+ } -+ } -+ } -+ } else { -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, chip->cc_meas_low); -+ regmap_read(chip->regmap, FUSB_REG_MEASURE, &val); -+ usleep_range(250, 300); -+ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ -+ if (val & STATUS0_COMP) -+ *CC_MEASURE = TYPEC_CC_VOLT_RD; -+ else -+ *CC_MEASURE = TYPEC_CC_VOLT_RA; -+ } -+ regmap_write(chip->regmap, FUSB_REG_SWITCHES0, store); -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, -+ chip->cc_meas_high); -+ } -+ -+ return 0; -+} -+ -+static void tcpm_set_cc_pull_mode(struct fusb30x_chip *chip, enum CC_MODE mode) -+{ -+ u8 val; -+ -+ switch (mode) { -+ case CC_PULL_UP: -+ if (chip->cc_polarity == TYPEC_POLARITY_CC1) -+ val = SWITCHES0_PU_EN1; -+ else -+ val = SWITCHES0_PU_EN2; -+ break; -+ case CC_PULL_DOWN: -+ val = SWITCHES0_PDWN1 | SWITCHES0_PDWN2; -+ break; -+ default: -+ val = 0; -+ break; -+ } -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2 | -+ SWITCHES0_PDWN1 | SWITCHES0_PDWN2, -+ val); -+ -+ if (chip->cc_meas_high && mode == CC_PULL_UP) -+ regmap_write(chip->regmap, FUSB_REG_MEASURE, -+ chip->cc_meas_high); -+} -+ -+static int tcpm_set_cc(struct fusb30x_chip *chip, enum role_mode mode) -+{ -+ switch (mode) { -+ case ROLE_MODE_DFP: -+ tcpm_set_cc_pull_mode(chip, CC_PULL_UP); -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_MODE | CONTROL2_TOG_RD_ONLY, -+ CONTROL2_MODE_DFP | CONTROL2_TOG_RD_ONLY); -+ break; -+ case ROLE_MODE_UFP: -+ tcpm_set_cc_pull_mode(chip, CC_PULL_UP); -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_MODE | CONTROL2_TOG_RD_ONLY, -+ CONTROL2_MODE_UFP); -+ break; -+ case ROLE_MODE_DRP: -+ tcpm_set_cc_pull_mode(chip, CC_PULL_NONE); -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_MODE | CONTROL2_TOG_RD_ONLY, -+ CONTROL2_MODE_DRP | CONTROL2_TOG_RD_ONLY); -+ break; -+ default: -+ dev_err(chip->dev, "%s: Unsupport cc mode %d\n", -+ __func__, mode); -+ return -EINVAL; -+ break; -+ } -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, CONTROL2_TOGGLE, -+ CONTROL2_TOGGLE); -+ -+ return 0; -+} -+ -+static int tcpm_set_rx_enable(struct fusb30x_chip *chip, int enable) -+{ -+ u8 val = 0; -+ -+ if (enable) { -+ if (chip->cc_polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES0_MEAS_CC1; -+ else -+ val |= SWITCHES0_MEAS_CC2; -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2, -+ val); -+ fusb302_flush_rx_fifo(chip); -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_AUTO_CRC, SWITCHES1_AUTO_CRC); -+ } else { -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2, -+ 0); -+ regmap_update_bits(chip->regmap, -+ FUSB_REG_SWITCHES1, SWITCHES1_AUTO_CRC, 0); -+ } -+ -+ return 0; -+} -+ -+static int tcpm_set_msg_header(struct fusb30x_chip *chip) -+{ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_POWERROLE | SWITCHES1_DATAROLE, -+ (chip->notify.power_role << 7) | -+ (chip->notify.data_role << 4)); -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_SPECREV, 2 << 5); -+ return 0; -+} -+ -+static int tcpm_set_polarity(struct fusb30x_chip *chip, -+ enum typec_cc_polarity polarity) -+{ -+ u8 val = 0; -+ -+ if (chip->vconn_enabled) { -+ if (polarity) -+ val |= SWITCHES0_VCONN_CC1; -+ else -+ val |= SWITCHES0_VCONN_CC2; -+ } -+ -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) { -+ if (polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES0_MEAS_CC1; -+ else -+ val |= SWITCHES0_MEAS_CC2; -+ } else { -+ if (polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES0_MEAS_CC1 | SWITCHES0_PU_EN1; -+ else -+ val |= SWITCHES0_MEAS_CC2 | SWITCHES0_PU_EN2; -+ } -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_VCONN_CC1 | SWITCHES0_VCONN_CC2 | -+ SWITCHES0_MEAS_CC1 | SWITCHES0_MEAS_CC2 | -+ SWITCHES0_PU_EN1 | SWITCHES0_PU_EN2, -+ val); -+ -+ val = 0; -+ if (polarity == TYPEC_POLARITY_CC1) -+ val |= SWITCHES1_TXCC1; -+ else -+ val |= SWITCHES1_TXCC2; -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES1, -+ SWITCHES1_TXCC1 | SWITCHES1_TXCC2, -+ val); -+ -+ chip->cc_polarity = polarity; -+ -+ return 0; -+} -+ -+static int tcpm_set_vconn(struct fusb30x_chip *chip, int enable) -+{ -+ u8 val = 0; -+ -+ if (enable) { -+ if (chip->cc_polarity == TYPEC_POLARITY_CC1) -+ val = SWITCHES0_VCONN_CC2; -+ else -+ val = SWITCHES0_VCONN_CC1; -+ } -+ regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0, -+ SWITCHES0_VCONN_CC1 | SWITCHES0_VCONN_CC2, -+ val); -+ chip->vconn_enabled = (bool)enable; -+ return 0; -+} -+ -+static void fusb302_pd_reset(struct fusb30x_chip *chip) -+{ -+ regmap_write(chip->regmap, FUSB_REG_RESET, RESET_PD_RESET); -+ regmap_reinit_cache(chip->regmap, &fusb302_regmap_config); -+} -+ -+static void tcpm_select_rp_value(struct fusb30x_chip *chip, u32 rp) -+{ -+ u32 control0_reg; -+ -+ regmap_read(chip->regmap, FUSB_REG_CONTROL0, &control0_reg); -+ -+ control0_reg &= ~CONTROL0_HOST_CUR; -+ /* -+ * according to the host current, the compare value is different -+ * Fusb302 datasheet Table 3 -+ */ -+ switch (rp) { -+ /* -+ * host pull up current is 80ua , high voltage is 1.596v, -+ * low is 0.21v -+ */ -+ case TYPEC_RP_USB: -+ chip->cc_meas_high = 0x26; -+ chip->cc_meas_low = 0x5; -+ control0_reg |= CONTROL0_HOST_CUR_USB; -+ break; -+ /* -+ * host pull up current is 330ua , high voltage is 2.604v, -+ * low is 0.798v -+ */ -+ case TYPEC_RP_3A0: -+ chip->cc_meas_high = 0x3e; -+ chip->cc_meas_low = 0x13; -+ control0_reg |= CONTROL0_HOST_CUR_3A0; -+ break; -+ /* -+ * host pull up current is 180ua , high voltage is 1.596v, -+ * low is 0.42v -+ */ -+ case TYPEC_RP_1A5: -+ default: -+ chip->cc_meas_high = 0x26; -+ chip->cc_meas_low = 0xa; -+ control0_reg |= CONTROL0_HOST_CUR_1A5; -+ break; -+ } -+ -+ regmap_write(chip->regmap, FUSB_REG_CONTROL0, control0_reg); -+} -+ -+static int tcpm_check_vbus(struct fusb30x_chip *chip) -+{ -+ u32 val; -+ -+ /* Read status register */ -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ -+ return (val & STATUS0_VBUSOK) ? 1 : 0; -+} -+ -+static void tcpm_init(struct fusb30x_chip *chip) -+{ -+ u8 val; -+ u32 tmp; -+ -+ regmap_read(chip->regmap, FUSB_REG_DEVICEID, &tmp); -+ chip->chip_id = (u8)tmp; -+ platform_set_vbus_lvl_enable(chip, 0, 0); -+ chip->notify.is_cc_connected = false; -+ chip->cc_state = 0; -+ -+ /* restore default settings */ -+ regmap_update_bits(chip->regmap, FUSB_REG_RESET, RESET_SW_RESET, -+ RESET_SW_RESET); -+ fusb302_pd_reset(chip); -+ /* set auto_retry and number of retries */ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL3, -+ CONTROL3_AUTO_RETRY | CONTROL3_N_RETRIES, -+ CONTROL3_AUTO_RETRY | CONTROL3_N_RETRIES), -+ -+ /* set interrupts */ -+ val = 0xff; -+ val &= ~(MASK_M_COLLISION | MASK_M_ALERT | MASK_M_VBUSOK); -+ regmap_write(chip->regmap, FUSB_REG_MASK, val); -+ -+ val = 0xff; -+ val &= ~(MASKA_M_RETRYFAIL | MASKA_M_HARDSENT | MASKA_M_TXSENT | -+ MASKA_M_HARDRST | MASKA_M_TOGDONE); -+ regmap_write(chip->regmap, FUSB_REG_MASKA, val); -+ -+ val = ~MASKB_M_GCRCSEND; -+ regmap_write(chip->regmap, FUSB_REG_MASKB, val); -+ -+ tcpm_select_rp_value(chip, TYPEC_RP_1A5); -+ /* Interrupts Enable */ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL0, CONTROL0_INT_MASK, -+ ~CONTROL0_INT_MASK); -+ -+ tcpm_set_vconn(chip, 0); -+ -+ regmap_write(chip->regmap, FUSB_REG_POWER, 0xf); -+} -+ -+static void pd_execute_hard_reset(struct fusb30x_chip *chip) -+{ -+ chip->msg_id = 0; -+ chip->vdm_state = VDM_STATE_DISCOVERY_ID; -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_transition_default); -+ else -+ set_state(chip, policy_snk_transition_default); -+} -+ -+static void tcpc_alert(struct fusb30x_chip *chip, u32 *evt) -+{ -+ int interrupt, interrupta, interruptb; -+ u32 val; -+ static int retry; -+ -+ regmap_read(chip->regmap, FUSB_REG_INTERRUPT, &interrupt); -+ regmap_read(chip->regmap, FUSB_REG_INTERRUPTA, &interrupta); -+ regmap_read(chip->regmap, FUSB_REG_INTERRUPTB, &interruptb); -+ -+ if ((interrupt & INTERRUPT_COMP_CHNG) && -+ (!(chip->cc_state & CC_STATE_TOGSS_IS_UFP))) { -+ regmap_read(chip->regmap, FUSB_REG_STATUS0, &val); -+ if (val & STATUS0_COMP) -+ *evt |= EVENT_CC; -+ } -+ -+ if (interrupt & INTERRUPT_VBUSOK) { -+ if (chip->notify.is_cc_connected) -+ *evt |= EVENT_CC; -+ } -+ -+ if (interrupta & INTERRUPTA_TOGDONE) { -+ *evt |= EVENT_CC; -+ regmap_read(chip->regmap, FUSB_REG_STATUS1A, &val); -+ chip->cc_state = ((u8)val >> 3) & 0x07; -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL2, -+ CONTROL2_TOGGLE, -+ 0); -+ } -+ -+ if (interrupta & INTERRUPTA_TXSENT) { -+ *evt |= EVENT_TX; -+ chip->tx_state = tx_success; -+ } -+ -+ if (interruptb & INTERRUPTB_GCRCSENT) -+ *evt |= EVENT_RX; -+ -+ if (interrupta & INTERRUPTA_HARDRST) { -+ fusb302_pd_reset(chip); -+ pd_execute_hard_reset(chip); -+ *evt |= EVENT_REC_RESET; -+ } -+ -+ if (interrupta & INTERRUPTA_RETRYFAIL) { -+ *evt |= EVENT_TX; -+ chip->tx_state = tx_failed; -+ } -+ -+ if (interrupta & INTERRUPTA_HARDSENT) { -+ /* -+ * The fusb PD should be reset once to sync adapter PD -+ * signal after fusb sent hard reset cmd.This is not PD -+ * device if reset failed. -+ */ -+ if (!retry) { -+ retry = 1; -+ fusb302_pd_reset(chip); -+ pd_execute_hard_reset(chip); -+ } else { -+ retry = 0; -+ chip->tx_state = tx_success; -+ chip->timer_state = T_DISABLED; -+ *evt |= EVENT_TX; -+ } -+ } -+} -+ -+static void mux_alert(struct fusb30x_chip *chip, u32 *evt) -+{ -+ if (!chip->timer_mux) { -+ *evt |= EVENT_TIMER_MUX; -+ chip->timer_mux = T_DISABLED; -+ } -+ -+ if (!chip->timer_state) { -+ *evt |= EVENT_TIMER_STATE; -+ chip->timer_state = T_DISABLED; -+ } -+ -+ if (chip->work_continue) { -+ *evt |= chip->work_continue; -+ chip->work_continue = 0; -+ } -+} -+ -+static void set_state_unattached(struct fusb30x_chip *chip) -+{ -+ dev_info(chip->dev, "connection has disconnected\n"); -+ tcpm_init(chip); -+ tcpm_set_rx_enable(chip, 0); -+ set_state(chip, unattached); -+ tcpm_set_cc(chip, chip->role); -+ -+ /* claer notify_info */ -+ memset(&chip->notify, 0, sizeof(struct notify_info)); -+ platform_fusb_notify(chip); -+ -+ if (chip->gpio_discharge) -+ gpiod_set_value(chip->gpio_discharge, 1); -+ msleep(100); -+ if (chip->gpio_discharge) -+ gpiod_set_value(chip->gpio_discharge, 0); -+ -+ regmap_update_bits(chip->regmap, FUSB_REG_MASK, -+ MASK_M_COMP_CHNG, MASK_M_COMP_CHNG); -+ chip->try_role_complete = false; -+} -+ -+static void set_mesg(struct fusb30x_chip *chip, int cmd, int is_DMT) -+{ -+ int i; -+ struct PD_CAP_INFO *pd_cap_info = &chip->pd_cap_info; -+ -+ chip->send_head = ((chip->msg_id & 0x7) << 9) | -+ ((chip->notify.power_role & 0x1) << 8) | -+ (1 << 6) | -+ ((chip->notify.data_role & 0x1) << 5); -+ -+ if (is_DMT) { -+ switch (cmd) { -+ case DMT_SOURCECAPABILITIES: -+ chip->send_head |= ((chip->n_caps_used & 0x3) << 12) | (cmd & 0xf); -+ -+ for (i = 0; i < chip->n_caps_used; i++) { -+ chip->send_load[i] = (pd_cap_info->supply_type << 30) | -+ (pd_cap_info->dual_role_power << 29) | -+ (pd_cap_info->usb_suspend_support << 28) | -+ (pd_cap_info->externally_powered << 27) | -+ (pd_cap_info->usb_communications_cap << 26) | -+ (pd_cap_info->data_role_swap << 25) | -+ (pd_cap_info->peak_current << 20) | -+ (chip->source_power_supply[i] << 10) | -+ (chip->source_max_current[i]); -+ } -+ break; -+ case DMT_REQUEST: -+ chip->send_head |= ((1 << 12) | (cmd & 0xf)); -+ /* send request with FVRDO */ -+ chip->send_load[0] = (chip->pos_power << 28) | -+ (0 << 27) | -+ (1 << 26) | -+ (0 << 25) | -+ (0 << 24); -+ -+ switch (CAP_POWER_TYPE(chip->rec_load[chip->pos_power - 1])) { -+ case 0: -+ /* Fixed Supply */ -+ chip->send_load[0] |= ((CAP_FPDO_VOLTAGE(chip->rec_load[chip->pos_power - 1]) << 10) & 0x3ff); -+ chip->send_load[0] |= (CAP_FPDO_CURRENT(chip->rec_load[chip->pos_power - 1]) & 0x3ff); -+ break; -+ case 1: -+ /* Battery */ -+ chip->send_load[0] |= ((CAP_VPDO_VOLTAGE(chip->rec_load[chip->pos_power - 1]) << 10) & 0x3ff); -+ chip->send_load[0] |= (CAP_VPDO_CURRENT(chip->rec_load[chip->pos_power - 1]) & 0x3ff); -+ break; -+ default: -+ /* not meet battery caps */ -+ break; -+ } -+ break; -+ case DMT_SINKCAPABILITIES: -+ break; -+ case DMT_VENDERDEFINED: -+ break; -+ default: -+ break; -+ } -+ } else { -+ chip->send_head |= (cmd & 0xf); -+ } -+} -+ -+/* -+ * This algorithm defaults to choosing higher pin config over lower ones in -+ * order to prefer multi-function if desired. -+ * -+ * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG -+ * ------------------------------------------------------------- -+ * A | USB G2 | ? | no | 00_0001 -+ * B | USB G2 | ? | yes | 00_0010 -+ * C | DP | CONVERTED | no | 00_0100 -+ * D | PD | CONVERTED | yes | 00_1000 -+ * E | DP | DP | no | 01_0000 -+ * F | PD | DP | yes | 10_0000 -+ * -+ * if UFP has NOT asserted multi-function preferred code masks away B/D/F -+ * leaving only A/C/E. For single-output dongles that should leave only one -+ * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP -+ * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C -+ * receptacle must always choose C/D in those cases. -+ */ -+static int pd_dfp_dp_get_pin_assignment(struct fusb30x_chip *chip, -+ uint32_t caps, uint32_t status) -+{ -+ uint32_t pin_caps; -+ -+ /* revisit with DFP that can be a sink */ -+ pin_caps = PD_DP_PIN_CAPS(caps); -+ -+ /* if don't want multi-function then ignore those pin configs */ -+ if (!PD_VDO_DPSTS_MF_PREF(status)) -+ pin_caps &= ~MODE_DP_PIN_MF_MASK; -+ -+ /* revisit if DFP drives USB Gen 2 signals */ -+ if (PD_DP_SIGNAL_GEN2(caps)) -+ pin_caps &= ~MODE_DP_PIN_DP_MASK; -+ else -+ pin_caps &= ~MODE_DP_PIN_BR2_MASK; -+ -+ /* if C/D present they have precedence over E/F for USB-C->USB-C */ -+ if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) -+ pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); -+ -+ /* returns undefined for zero */ -+ if (!pin_caps) -+ return 0; -+ -+ /* choosing higher pin config over lower ones */ -+ return 1 << (31 - __builtin_clz(pin_caps)); -+} -+ -+static void set_vdm_mesg(struct fusb30x_chip *chip, int cmd, int type, int mode) -+{ -+ chip->send_head = (chip->msg_id & 0x7) << 9; -+ chip->send_head |= (chip->notify.power_role & 0x1) << 8; -+ -+ chip->send_head = ((chip->msg_id & 0x7) << 9) | -+ ((chip->notify.power_role & 0x1) << 8) | -+ (1 << 6) | -+ ((chip->notify.data_role & 0x1) << 5) | -+ (DMT_VENDERDEFINED & 0xf); -+ -+ chip->send_load[0] = (1 << 15) | -+ (0 << 13) | -+ (type << 6) | -+ (cmd); -+ -+ switch (cmd) { -+ case VDM_DISCOVERY_ID: -+ case VDM_DISCOVERY_SVIDS: -+ case VDM_ATTENTION: -+ chip->send_load[0] |= (0xff00 << 16); -+ chip->send_head |= (1 << 12); -+ break; -+ case VDM_DISCOVERY_MODES: -+ chip->send_load[0] |= -+ (chip->vdm_svid[chip->val_tmp >> 1] << 16); -+ chip->send_head |= (1 << 12); -+ break; -+ case VDM_ENTER_MODE: -+ chip->send_head |= (1 << 12); -+ chip->send_load[0] |= (mode << 8) | (0xff01 << 16); -+ break; -+ case VDM_EXIT_MODE: -+ chip->send_head |= (1 << 12); -+ chip->send_load[0] |= (0x0f << 8) | (0xff01 << 16); -+ break; -+ case VDM_DP_STATUS_UPDATE: -+ chip->send_head |= (2 << 12); -+ chip->send_load[0] |= (1 << 8) | (0xff01 << 16); -+ chip->send_load[1] = 5; -+ break; -+ case VDM_DP_CONFIG: -+ chip->send_head |= (2 << 12); -+ chip->send_load[0] |= (1 << 8) | (0xff01 << 16); -+ -+ chip->notify.pin_assignment_def = -+ pd_dfp_dp_get_pin_assignment(chip, chip->notify.dp_caps, -+ chip->notify.dp_status); -+ -+ chip->send_load[1] = (chip->notify.pin_assignment_def << 8) | -+ (1 << 2) | 2; -+ dev_dbg(chip->dev, "DisplayPort Configurations: 0x%08x\n", -+ chip->send_load[1]); -+ break; -+ default: -+ break; -+ } -+} -+ -+static enum tx_state policy_send_hardrst(struct fusb30x_chip *chip, u32 evt) -+{ -+ switch (chip->tx_state) { -+ case 0: -+ regmap_update_bits(chip->regmap, FUSB_REG_CONTROL3, -+ CONTROL3_SEND_HARDRESET, -+ CONTROL3_SEND_HARDRESET); -+ chip->tx_state = tx_busy; -+ chip->timer_state = T_BMC_TIMEOUT; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ break; -+ default: -+ if (evt & EVENT_TIMER_STATE) -+ chip->tx_state = tx_success; -+ break; -+ } -+ return chip->tx_state; -+} -+ -+static enum tx_state policy_send_data(struct fusb30x_chip *chip) -+{ -+ u8 senddata[40]; -+ int pos = 0; -+ u8 len; -+ -+ switch (chip->tx_state) { -+ case 0: -+ senddata[pos++] = FUSB_TKN_SYNC1; -+ senddata[pos++] = FUSB_TKN_SYNC1; -+ senddata[pos++] = FUSB_TKN_SYNC1; -+ senddata[pos++] = FUSB_TKN_SYNC2; -+ -+ len = PD_HEADER_CNT(chip->send_head) << 2; -+ senddata[pos++] = FUSB_TKN_PACKSYM | ((len + 2) & 0x1f); -+ -+ senddata[pos++] = chip->send_head & 0xff; -+ senddata[pos++] = (chip->send_head >> 8) & 0xff; -+ -+ memcpy(&senddata[pos], chip->send_load, len); -+ pos += len; -+ -+ senddata[pos++] = FUSB_TKN_JAMCRC; -+ senddata[pos++] = FUSB_TKN_EOP; -+ senddata[pos++] = FUSB_TKN_TXOFF; -+ senddata[pos++] = FUSB_TKN_TXON; -+ -+ regmap_raw_write(chip->regmap, FUSB_REG_FIFO, senddata, pos); -+ chip->tx_state = tx_busy; -+ break; -+ -+ default: -+ /* wait Tx result */ -+ break; -+ } -+ -+ return chip->tx_state; -+} -+ -+static void process_vdm_msg(struct fusb30x_chip *chip) -+{ -+ u32 vdm_header = chip->rec_load[0]; -+ int i; -+ u32 tmp; -+ -+ /* can't procee unstructed vdm msg */ -+ if (!GET_VDMHEAD_STRUCT_TYPE(vdm_header)) { -+ dev_warn(chip->dev, "unknown unstructed vdm message\n"); -+ return; -+ } -+ -+ switch (GET_VDMHEAD_CMD_TYPE(vdm_header)) { -+ case VDM_TYPE_INIT: -+ switch (GET_VDMHEAD_CMD(vdm_header)) { -+ case VDM_ATTENTION: -+ chip->notify.dp_status = GET_DP_STATUS(chip->rec_load[1]); -+ dev_info(chip->dev, "attention, dp_status %x\n", -+ chip->rec_load[1]); -+ chip->notify.attention = true; -+ platform_fusb_notify(chip); -+ break; -+ default: -+ dev_warn(chip->dev, "rec unknown init vdm msg\n"); -+ break; -+ } -+ break; -+ case VDM_TYPE_ACK: -+ switch (GET_VDMHEAD_CMD(vdm_header)) { -+ case VDM_DISCOVERY_ID: -+ chip->vdm_id = chip->rec_load[1]; -+ break; -+ case VDM_DISCOVERY_SVIDS: -+ for (i = 0; i < 6; i++) { -+ tmp = (chip->rec_load[i + 1] >> 16) & -+ 0x0000ffff; -+ if (tmp) { -+ chip->vdm_svid[i * 2] = tmp; -+ chip->vdm_svid_num++; -+ } else { -+ break; -+ } -+ -+ tmp = (chip->rec_load[i + 1] & 0x0000ffff); -+ if (tmp) { -+ chip->vdm_svid[i * 2 + 1] = tmp; -+ chip->vdm_svid_num++; -+ } else { -+ break; -+ } -+ } -+ break; -+ case VDM_DISCOVERY_MODES: -+ /* indicate there are some vdo modes */ -+ if (PD_HEADER_CNT(chip->rec_head) > 1) { -+ /* -+ * store mode config, -+ * enter first mode default -+ */ -+ tmp = chip->rec_load[1]; -+ -+ if ((!((tmp >> 8) & 0x3f)) && -+ (!((tmp >> 16) & 0x3f))) { -+ chip->val_tmp |= 1; -+ break; -+ } -+ chip->notify.dp_caps = chip->rec_load[1]; -+ chip->notify.pin_assignment_def = 0; -+ chip->notify.pin_assignment_support = -+ PD_DP_PIN_CAPS(tmp); -+ chip->val_tmp |= 1; -+ dev_dbg(chip->dev, -+ "DisplayPort Capabilities: 0x%08x\n", -+ chip->rec_load[1]); -+ } -+ break; -+ case VDM_ENTER_MODE: -+ chip->val_tmp = 1; -+ break; -+ case VDM_DP_STATUS_UPDATE: -+ chip->notify.dp_status = GET_DP_STATUS(chip->rec_load[1]); -+ dev_dbg(chip->dev, "DisplayPort Status: 0x%08x\n", -+ chip->rec_load[1]); -+ chip->val_tmp = 1; -+ break; -+ case VDM_DP_CONFIG: -+ chip->val_tmp = 1; -+ dev_info(chip->dev, -+ "DP config successful, pin_assignment 0x%x\n", -+ chip->notify.pin_assignment_def); -+ chip->notify.is_enter_mode = true; -+ break; -+ default: -+ break; -+ } -+ break; -+ case VDM_TYPE_NACK: -+ dev_warn(chip->dev, "REC NACK for 0x%x\n", -+ GET_VDMHEAD_CMD(vdm_header)); -+ /* disable vdm */ -+ chip->vdm_state = VDM_STATE_ERR; -+ break; -+ } -+} -+ -+static int vdm_send_discoveryid(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DISCOVERY_ID, VDM_TYPE_INIT, 0); -+ chip->vdm_id = 0; -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_ID send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->vdm_id) { -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_ID time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_discoverysvid(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DISCOVERY_SVIDS, VDM_TYPE_INIT, 0); -+ memset(chip->vdm_svid, 0, sizeof(chip->vdm_svid)); -+ chip->vdm_svid_num = 0; -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_SVIDS send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->vdm_svid_num) { -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_DISCOVERY_SVIDS time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_discoverymodes(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ if ((chip->val_tmp >> 1) != chip->vdm_svid_num) { -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DISCOVERY_MODES, -+ VDM_TYPE_INIT, 0); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, -+ "VDM_DISCOVERY_MODES send failed\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp & 1) { -+ chip->val_tmp &= 0xfe; -+ chip->val_tmp += 2; -+ chip->vdm_send_state = 0; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, -+ "VDM_DISCOVERY_MODES time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ } else { -+ chip->val_tmp = 0; -+ return 0; -+ } -+ -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_entermode(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_ENTER_MODE, VDM_TYPE_INIT, 1); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ chip->notify.is_enter_mode = false; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "VDM_ENTER_MODE send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp) { -+ chip->val_tmp = 0; -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_ENTER_MODE time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_getdpstatus(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DP_STATUS_UPDATE, VDM_TYPE_INIT, 1); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, -+ "VDM_DP_STATUS_UPDATE send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp) { -+ chip->val_tmp = 0; -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "VDM_DP_STATUS_UPDATE time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+static int vdm_send_dpconfig(struct fusb30x_chip *chip, u32 evt) -+{ -+ int tmp; -+ -+ switch (chip->vdm_send_state) { -+ case 0: -+ set_vdm_mesg(chip, VDM_DP_CONFIG, VDM_TYPE_INIT, 0); -+ chip->tx_state = 0; -+ chip->vdm_send_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->vdm_send_state++; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ dev_warn(chip->dev, "vdm_send_dpconfig send failed\n"); -+ /* disable auto_vdm_machine */ -+ chip->vdm_state = VDM_STATE_ERR; -+ return -EPIPE; -+ } -+ -+ if (chip->vdm_send_state != 2) -+ break; -+ default: -+ if (chip->val_tmp) { -+ chip->val_tmp = 0; -+ chip->vdm_send_state = 0; -+ return 0; -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "vdm_send_dpconfig time out\n"); -+ chip->vdm_state = VDM_STATE_ERR; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ return -ETIMEDOUT; -+ } -+ break; -+ } -+ return -EINPROGRESS; -+} -+ -+/* without break if success */ -+#define AUTO_VDM_HANDLE(func, chip, evt, conditions) \ -+do { \ -+ conditions = func(chip, evt); \ -+ if (!conditions) { \ -+ chip->vdm_state++; \ -+ chip->work_continue |= EVENT_WORK_CONTINUE; \ -+ } else { \ -+ if (conditions != -EINPROGRESS) \ -+ chip->vdm_state = VDM_STATE_ERR; \ -+ } \ -+} while (0) -+ -+static void auto_vdm_machine(struct fusb30x_chip *chip, u32 evt) -+{ -+ int conditions; -+ -+ switch (chip->vdm_state) { -+ case VDM_STATE_DISCOVERY_ID: -+ AUTO_VDM_HANDLE(vdm_send_discoveryid, chip, evt, conditions); -+ break; -+ case VDM_STATE_DISCOVERY_SVID: -+ AUTO_VDM_HANDLE(vdm_send_discoverysvid, chip, evt, conditions); -+ break; -+ case VDM_STATE_DISCOVERY_MODES: -+ AUTO_VDM_HANDLE(vdm_send_discoverymodes, chip, evt, conditions); -+ break; -+ case VDM_STATE_ENTER_MODE: -+ AUTO_VDM_HANDLE(vdm_send_entermode, chip, evt, conditions); -+ break; -+ case VDM_STATE_UPDATE_STATUS: -+ AUTO_VDM_HANDLE(vdm_send_getdpstatus, chip, evt, conditions); -+ break; -+ case VDM_STATE_DP_CONFIG: -+ AUTO_VDM_HANDLE(vdm_send_dpconfig, chip, evt, conditions); -+ break; -+ case VDM_STATE_NOTIFY: -+ platform_fusb_notify(chip); -+ chip->vdm_state = VDM_STATE_READY; -+ break; -+ default: -+ break; -+ } -+} -+ -+static void fusb_state_disabled(struct fusb30x_chip *chip, u32 evt) -+{ -+ /* Do nothing */ -+} -+ -+static void fusb_state_unattached(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.is_cc_connected = false; -+ chip->is_pd_support = false; -+ -+ if ((evt & EVENT_CC) && chip->cc_state) { -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) -+ set_state(chip, attach_wait_sink); -+ else -+ set_state(chip, attach_wait_source); -+ -+ chip->vbus_begin = tcpm_check_vbus(chip); -+ -+ tcpm_set_polarity(chip, (chip->cc_state & CC_STATE_TOGSS_CC1) ? -+ TYPEC_POLARITY_CC1 : -+ TYPEC_POLARITY_CC2); -+ tcpm_get_cc(chip, &chip->cc1, &chip->cc2); -+ chip->debounce_cnt = 0; -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, chip->timer_mux); -+ } -+} -+ -+static void fusb_state_try_attach_set(struct fusb30x_chip *chip, -+ enum role_mode mode) -+{ -+ if (mode == ROLE_MODE_NONE || mode == ROLE_MODE_DRP || -+ mode == ROLE_MODE_ASS) -+ return; -+ -+ tcpm_init(chip); -+ tcpm_set_cc(chip, (mode == ROLE_MODE_DFP) ? -+ ROLE_MODE_DFP : ROLE_MODE_UFP); -+ chip->timer_mux = T_PD_TRY_DRP; -+ fusb_timer_start(&chip->timer_mux_machine, chip->timer_mux); -+ set_state(chip, (mode == ROLE_MODE_DFP) ? -+ attach_try_src : attach_try_snk); -+} -+ -+static void fusb_state_attach_wait_sink(struct fusb30x_chip *chip, u32 evt) -+{ -+ int cc1, cc2; -+ -+ if (evt & EVENT_TIMER_MUX) { -+ if (tcpm_check_vbus(chip)) { -+ chip->timer_mux = T_DISABLED; -+ if (chip->role == ROLE_MODE_DRP && -+ chip->try_role == ROLE_MODE_DFP && -+ !chip->try_role_complete) { -+ fusb_state_try_attach_set(chip, ROLE_MODE_DFP); -+ return; -+ } else if (chip->try_role_complete) { -+ chip->timer_mux = T_PD_SOURCE_ON; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ set_state(chip, attached_sink); -+ return; -+ } -+ } -+ -+ tcpm_get_cc(chip, &cc1, &cc2); -+ -+ if ((chip->cc1 == cc1) && (chip->cc2 == cc2)) { -+ chip->debounce_cnt++; -+ } else { -+ chip->cc1 = cc1; -+ chip->cc2 = cc2; -+ chip->debounce_cnt = 0; -+ } -+ -+ if (chip->debounce_cnt > N_DEBOUNCE_CNT) { -+ chip->timer_mux = T_DISABLED; -+ if ((chip->cc1 == TYPEC_CC_VOLT_RP && -+ chip->cc2 == TYPEC_CC_VOLT_OPEN) || -+ (chip->cc2 == TYPEC_CC_VOLT_RP && -+ chip->cc1 == TYPEC_CC_VOLT_OPEN)) { -+ chip->timer_mux = T_PD_SOURCE_ON; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ set_state(chip, attached_sink); -+ } else { -+ set_state_unattached(chip); -+ } -+ return; -+ } -+ -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ } -+} -+ -+static void fusb_state_attach_wait_source(struct fusb30x_chip *chip, u32 evt) -+{ -+ int cc1, cc2; -+ -+ if (evt & EVENT_TIMER_MUX) { -+ tcpm_get_cc(chip, &cc1, &cc2); -+ -+ if ((chip->cc1 == cc1) && (chip->cc2 == cc2)) { -+ chip->debounce_cnt++; -+ } else { -+ chip->cc1 = cc1; -+ chip->cc2 = cc2; -+ chip->debounce_cnt = 0; -+ } -+ -+ if (chip->debounce_cnt > N_DEBOUNCE_CNT) { -+ if (((!chip->cc1) || (!chip->cc2)) && -+ ((chip->cc1 == TYPEC_CC_VOLT_RD) || -+ (chip->cc2 == TYPEC_CC_VOLT_RD))) { -+ if (chip->role == ROLE_MODE_DRP && -+ chip->try_role == ROLE_MODE_UFP && -+ !chip->try_role_complete) -+ fusb_state_try_attach_set(chip, -+ ROLE_MODE_UFP); -+ else -+ set_state(chip, attached_source); -+ } else { -+ set_state_unattached(chip); -+ } -+ return; -+ } -+ -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ } -+} -+ -+static void fusb_state_attached_source(struct fusb30x_chip *chip, u32 evt) -+{ -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ tcpm_set_polarity(chip, (chip->cc_state & CC_STATE_TOGSS_CC1) ? -+ TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2); -+ tcpm_set_vconn(chip, 1); -+ -+ chip->notify.is_cc_connected = true; -+ -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ chip->notify.data_role = DATA_ROLE_DFP; -+ chip->hardrst_count = 0; -+ set_state(chip, policy_src_startup); -+ regmap_update_bits(chip->regmap, FUSB_REG_MASK, MASK_M_COMP_CHNG, 0); -+ dev_info(chip->dev, "CC connected in %s as DFP\n", -+ chip->cc_polarity ? "CC1" : "CC2"); -+} -+ -+static void fusb_state_attached_sink(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (tcpm_check_vbus(chip)) { -+ chip->timer_mux = T_DISABLED; -+ chip->timer_state = T_DISABLED; -+ if (!chip->try_role_complete && -+ chip->try_role == ROLE_MODE_DFP && -+ chip->role == ROLE_MODE_DRP) { -+ fusb_state_try_attach_set(chip, ROLE_MODE_DFP); -+ return; -+ } -+ -+ chip->try_role_complete = true; -+ chip->notify.is_cc_connected = true; -+ chip->notify.power_role = POWER_ROLE_SINK; -+ chip->notify.data_role = DATA_ROLE_UFP; -+ chip->hardrst_count = 0; -+ set_state(chip, policy_snk_startup); -+ dev_info(chip->dev, "CC connected in %s as UFP\n", -+ chip->cc_polarity ? "CC1" : "CC2"); -+ return; -+ } else if (evt & EVENT_TIMER_MUX) { -+ set_state_unattached(chip); -+ return; -+ } -+ -+ chip->timer_state = 2; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+} -+ -+static void fusb_state_try_attach(struct fusb30x_chip *chip, u32 evt, -+ enum role_mode mode) -+{ -+ if ((evt & EVENT_CC) && chip->cc_state) { -+ chip->try_role_complete = true; -+ if (chip->cc_state & CC_STATE_TOGSS_IS_UFP) -+ set_state(chip, (mode == ROLE_MODE_UFP) ? -+ attach_wait_sink : error_recovery); -+ else -+ set_state(chip, (mode == ROLE_MODE_DFP) ? -+ attach_wait_source : error_recovery); -+ -+ tcpm_set_polarity(chip, (chip->cc_state & CC_STATE_TOGSS_CC1) ? -+ TYPEC_POLARITY_CC1 : -+ TYPEC_POLARITY_CC2); -+ tcpm_get_cc(chip, &chip->cc1, &chip->cc2); -+ chip->debounce_cnt = 0; -+ chip->timer_mux = 2; -+ fusb_timer_start(&chip->timer_mux_machine, chip->timer_mux); -+ } else if (evt & EVENT_TIMER_MUX) { -+ if (!chip->try_role_complete) { -+ chip->try_role_complete = true; -+ fusb_state_try_attach_set(chip, -+ (mode == ROLE_MODE_DFP) ? -+ ROLE_MODE_UFP : -+ ROLE_MODE_DFP); -+ } else { -+ set_state(chip, error_recovery); -+ } -+ } -+} -+ -+static void fusb_soft_reset_parameter(struct fusb30x_chip *chip) -+{ -+ chip->caps_counter = 0; -+ chip->msg_id = 0; -+ chip->vdm_state = VDM_STATE_DISCOVERY_ID; -+ chip->vdm_substate = 0; -+ chip->vdm_send_state = 0; -+ chip->val_tmp = 0; -+ chip->pos_power = 0; -+} -+ -+static void fusb_state_src_startup(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.is_pd_connected = false; -+ fusb_soft_reset_parameter(chip); -+ -+ memset(chip->partner_cap, 0, sizeof(chip->partner_cap)); -+ -+ tcpm_set_msg_header(chip); -+ tcpm_set_polarity(chip, chip->cc_polarity); -+ tcpm_set_rx_enable(chip, 1); -+ -+ set_state(chip, policy_src_send_caps); -+ platform_fusb_notify(chip); -+} -+ -+static void fusb_state_src_discovery(struct fusb30x_chip *chip, u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->caps_counter++; -+ -+ if (chip->caps_counter < N_CAPS_COUNT) { -+ chip->timer_state = T_TYPEC_SEND_SOURCECAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state = 1; -+ } else { -+ set_state(chip, disabled); -+ } -+ break; -+ default: -+ if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_src_send_caps); -+ } else if (evt & EVENT_TIMER_MUX) { -+ if (!chip->is_pd_support) -+ set_state(chip, disabled); -+ else if (chip->hardrst_count > N_HARDRESET_COUNT) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_send_caps(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, DMT_SOURCECAPABILITIES, DATAMESSAGE); -+ chip->sub_state = 1; -+ chip->tx_state = tx_idle; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ -+ if (tmp == tx_success) { -+ chip->hardrst_count = 0; -+ chip->caps_counter = 0; -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->timer_mux = T_DISABLED; -+ chip->sub_state++; -+ chip->is_pd_support = true; -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_discovery); -+ break; -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_REQUEST)) { -+ set_state(chip, policy_src_negotiate_cap); -+ } else { -+ set_state(chip, policy_src_send_softrst); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->hardrst_count <= N_HARDRESET_COUNT) -+ set_state(chip, policy_src_send_hardrst); -+ else -+ set_state(chip, disabled); -+ } else if (evt & EVENT_TIMER_MUX) { -+ if (!chip->is_pd_support) -+ set_state(chip, disabled); -+ else if (chip->hardrst_count > N_HARDRESET_COUNT) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_negotiate_cap(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ /* base on evb1 */ -+ tmp = (chip->rec_load[0] >> 28) & 0x07; -+ if (tmp > chip->n_caps_used) -+ set_state(chip, policy_src_cap_response); -+ else -+ set_state(chip, policy_src_transition_supply); -+} -+ -+static void fusb_state_src_transition_supply(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_ACCEPT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SRC_TRANSITION; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ break; -+ case 2: -+ if (evt & EVENT_TIMER_STATE) { -+ chip->notify.is_pd_connected = true; -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ set_mesg(chip, CMT_PS_RDY, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ } -+ break; -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ dev_info(chip->dev, -+ "PD connected as DFP, supporting 5V\n"); -+ set_state(chip, policy_src_ready); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_cap_response(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_REJECT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ if (chip->notify.is_pd_connected) { -+ dev_info(chip->dev, -+ "PD connected as DFP, supporting 5V\n"); -+ set_state(chip, policy_src_ready); -+ } else { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_transition_default(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->notify.is_pd_connected = false; -+ platform_set_vbus_lvl_enable(chip, 0, 0); -+ if (chip->notify.data_role) -+ regmap_update_bits(chip->regmap, -+ FUSB_REG_SWITCHES1, -+ SWITCHES1_DATAROLE, -+ SWITCHES1_DATAROLE); -+ else -+ regmap_update_bits(chip->regmap, -+ FUSB_REG_SWITCHES1, -+ SWITCHES1_DATAROLE, -+ 0); -+ -+ chip->timer_state = T_SRC_RECOVER; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ break; -+ default: -+ if (evt & EVENT_TIMER_STATE) { -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ chip->timer_mux = T_NO_RESPONSE; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ set_state(chip, policy_src_startup); -+ dev_dbg(chip->dev, "reset over-> src startup\n"); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_vcs_ufp_evaluate_swap(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (chip->vconn_supported) -+ set_state(chip, policy_vcs_ufp_accept); -+ else -+ set_state(chip, policy_vcs_ufp_reject); -+} -+ -+static void fusb_state_swap_msg_process(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_PR_SWAP)) { -+ set_state(chip, policy_src_prs_evaluate); -+ } else if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_VCONN_SWAP)) { -+ if (chip->notify.data_role) -+ set_state(chip, chip->conn_state); -+ else -+ set_state(chip, policy_vcs_ufp_evaluate_swap); -+ } else if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_DR_SWAP)) { -+ if (chip->notify.data_role) -+ set_state(chip, policy_drs_dfp_evaluate); -+ else -+ set_state(chip, policy_drs_ufp_evaluate); -+ } -+ } -+} -+ -+#define VDM_IS_ACTIVE(chip) \ -+ (chip->notify.data_role && chip->vdm_state < VDM_STATE_READY) -+ -+static void fusb_state_src_ready(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_VENDERDEFINED)) { -+ process_vdm_msg(chip); -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ chip->timer_state = T_DISABLED; -+ } else if (!VDM_IS_ACTIVE(chip)) { -+ fusb_state_swap_msg_process(chip, evt); -+ } -+ } -+ -+ if (!chip->partner_cap[0]) -+ set_state(chip, policy_src_get_sink_caps); -+ else if (VDM_IS_ACTIVE(chip)) -+ auto_vdm_machine(chip, evt); -+} -+ -+static void fusb_state_prs_evaluate(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (chip->role == ROLE_MODE_DRP) -+ set_state(chip, policy_src_prs_accept); -+ else -+ set_state(chip, policy_src_prs_reject); -+} -+ -+static void fusb_state_send_simple_msg(struct fusb30x_chip *chip, u32 evt, -+ int cmd, int is_DMT, -+ enum connection_state state_success, -+ enum connection_state state_failed) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, cmd, is_DMT); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) -+ set_state(chip, state_success); -+ else if (tmp == tx_failed) -+ set_state(chip, state_failed); -+ } -+} -+ -+static void fusb_state_prs_reject(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_REJECT, CONTROLMESSAGE, -+ (chip->notify.power_role) ? -+ policy_src_ready : policy_snk_ready, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_prs_accept(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_ACCEPT, CONTROLMESSAGE, -+ (chip->notify.power_role) ? -+ policy_src_prs_transition_to_off : -+ policy_snk_prs_transition_to_off, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_vcs_ufp_accept(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_ACCEPT, CONTROLMESSAGE, -+ (chip->vconn_enabled) ? -+ policy_vcs_ufp_wait_for_dfp_vconn : -+ policy_vcs_ufp_turn_on_vconn, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_vcs_set_vconn(struct fusb30x_chip *chip, -+ u32 evt, bool on) -+{ -+ if (on) { -+ tcpm_set_vconn(chip, 1); -+ set_state(chip, chip->notify.data_role ? -+ policy_vcs_dfp_send_ps_rdy : -+ policy_vcs_ufp_send_ps_rdy); -+ } else { -+ tcpm_set_vconn(chip, 0); -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_ready); -+ else -+ set_state(chip, policy_snk_ready); -+ } -+} -+ -+static void fusb_state_vcs_send_ps_rdy(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_PS_RDY, CONTROLMESSAGE, -+ (chip->notify.power_role) ? -+ policy_src_ready : policy_snk_ready, -+ (chip->notify.power_role) ? -+ policy_src_send_softrst : -+ policy_snk_send_softrst); -+} -+ -+static void fusb_state_vcs_wait_for_vconn(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->timer_state = T_PD_VCONN_SRC_ON; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_PS_RDY)) -+ set_state(chip, chip->notify.data_role ? -+ policy_vcs_dfp_turn_off_vconn : -+ policy_vcs_ufp_turn_off_vconn); -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_send_hardrst); -+ else -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ } -+} -+ -+static void fusb_state_src_prs_transition_to_off(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->timer_state = T_SRC_TRANSITION; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ break; -+ case 1: -+ if (evt & EVENT_TIMER_STATE) { -+ platform_set_vbus_lvl_enable(chip, 0, 0); -+ chip->notify.power_role = POWER_ROLE_SINK; -+ tcpm_set_msg_header(chip); -+ if (chip->role == ROLE_MODE_DRP) -+ set_state(chip, policy_src_prs_assert_rd); -+ else -+ set_state(chip, policy_src_prs_source_off); -+ } -+ } -+} -+ -+static void fusb_state_src_prs_assert_rd(struct fusb30x_chip *chip, u32 evt) -+{ -+ tcpm_set_cc_pull_mode(chip, CC_PULL_DOWN); -+ set_state(chip, policy_src_prs_source_off); -+} -+ -+static void fusb_state_src_prs_source_off(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_PS_RDY, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_PD_SOURCE_ON; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_src_send_hardrst); -+ } -+ if (chip->sub_state != 3) -+ break; -+ case 2: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_PS_RDY)) { -+ chip->timer_state = T_DISABLED; -+ /* snk startup */ -+ chip->notify.is_pd_connected = false; -+ chip->cc_state |= CC_STATE_TOGSS_IS_UFP; -+ tcpm_set_polarity(chip, chip->cc_polarity); -+ tcpm_set_rx_enable(chip, 1); -+ set_state(chip, policy_snk_discovery); -+ } else { -+ dev_dbg(chip->dev, -+ "rec careless msg: head %x\n", -+ chip->rec_head); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_src_send_hardrst); -+ } -+ } -+} -+ -+static void fusb_state_drs_evaluate(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (chip->pd_cap_info.data_role_swap) -+ /* -+ * TODO: -+ * NOW REJECT swap when the port is DFP -+ * since we should work together with USB part -+ */ -+ set_state(chip, chip->notify.data_role ? -+ policy_drs_dfp_reject : policy_drs_ufp_accept); -+ else -+ set_state(chip, chip->notify.data_role ? -+ policy_drs_dfp_reject : policy_drs_ufp_reject); -+} -+ -+static void fusb_state_drs_send_accept(struct fusb30x_chip *chip, u32 evt) -+{ -+ fusb_state_send_simple_msg(chip, evt, CMT_ACCEPT, CONTROLMESSAGE, -+ chip->notify.power_role ? -+ policy_drs_dfp_change : -+ policy_drs_ufp_change, -+ error_recovery); -+} -+ -+static void fusb_state_drs_role_change(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.data_role = chip->notify.data_role ? -+ DATA_ROLE_UFP : DATA_ROLE_DFP; -+ tcpm_set_msg_header(chip); -+ set_state(chip, chip->notify.power_role ? policy_src_ready : -+ policy_snk_ready); -+} -+ -+static void fusb_state_src_get_sink_cap(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_GETSINKCAP, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_softrst); -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, -+ DMT_SINKCAPABILITIES)) { -+ for (tmp = 0; -+ tmp < PD_HEADER_CNT(chip->rec_head); -+ tmp++) { -+ chip->partner_cap[tmp] = -+ chip->rec_load[tmp]; -+ } -+ set_state(chip, policy_src_ready); -+ } else { -+ chip->partner_cap[0] = 0xffffffff; -+ set_state(chip, policy_src_ready); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ dev_warn(chip->dev, "Get sink cap time out\n"); -+ chip->partner_cap[0] = 0xffffffff; -+ set_state(chip, policy_src_ready); -+ } -+ } -+} -+ -+static void fusb_state_src_send_hardreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_hardrst(chip, evt); -+ if (tmp == tx_success) { -+ chip->hardrst_count++; -+ set_state(chip, policy_src_transition_default); -+ } else if (tmp == tx_failed) { -+ /* can't reach here */ -+ set_state(chip, error_recovery); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_softreset(struct fusb30x_chip *chip) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_ACCEPT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ fusb_soft_reset_parameter(chip); -+ set_state(chip, policy_src_send_caps); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_src_send_softreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_SOFTRESET, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_ACCEPT)) { -+ fusb_soft_reset_parameter(chip); -+ set_state(chip, policy_src_send_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_src_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_startup(struct fusb30x_chip *chip, u32 evt) -+{ -+ chip->notify.is_pd_connected = false; -+ fusb_soft_reset_parameter(chip); -+ -+ memset(chip->partner_cap, 0, sizeof(chip->partner_cap)); -+ -+ tcpm_set_msg_header(chip); -+ tcpm_set_polarity(chip, chip->cc_polarity); -+ tcpm_set_rx_enable(chip, 1); -+ set_state(chip, policy_snk_discovery); -+ platform_fusb_notify(chip); -+} -+ -+static void fusb_state_snk_discovery(struct fusb30x_chip *chip, u32 evt) -+{ -+ set_state(chip, policy_snk_wait_caps); -+ chip->timer_state = T_TYPEC_SINK_WAIT_CAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+} -+ -+static void fusb_state_snk_wait_caps(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, -+ DMT_SOURCECAPABILITIES)) { -+ chip->is_pd_support = true; -+ chip->timer_mux = T_DISABLED; -+ set_state(chip, policy_snk_evaluate_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->hardrst_count <= N_HARDRESET_COUNT) { -+ if (chip->vbus_begin) { -+ chip->vbus_begin = false; -+ set_state(chip, policy_snk_send_softrst); -+ } else { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ } else { -+ if (chip->is_pd_support) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, disabled); -+ } -+ } else if ((evt & EVENT_TIMER_MUX) && -+ (chip->hardrst_count > N_HARDRESET_COUNT)) { -+ if (chip->is_pd_support) -+ set_state(chip, error_recovery); -+ else -+ set_state(chip, disabled); -+ } -+} -+ -+static void fusb_state_snk_evaluate_caps(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ chip->hardrst_count = 0; -+ chip->pos_power = 0; -+ -+ for (tmp = 0; tmp < PD_HEADER_CNT(chip->rec_head); tmp++) { -+ switch (CAP_POWER_TYPE(chip->rec_load[tmp])) { -+ case 0: -+ /* Fixed Supply */ -+ if (CAP_FPDO_VOLTAGE(chip->rec_load[tmp]) <= 100) -+ chip->pos_power = tmp + 1; -+ break; -+ case 1: -+ /* Battery */ -+ if (CAP_VPDO_VOLTAGE(chip->rec_load[tmp]) <= 100) -+ chip->pos_power = tmp + 1; -+ break; -+ default: -+ /* not meet battery caps */ -+ break; -+ } -+ } -+ fusb302_set_pos_power_by_charge_ic(chip); -+ -+ if ((!chip->pos_power) || (chip->pos_power > 7)) { -+ chip->pos_power = 0; -+ set_state(chip, policy_snk_wait_caps); -+ } else { -+ set_state(chip, policy_snk_select_cap); -+ } -+} -+ -+static void fusb_state_snk_select_cap(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, DMT_REQUEST, DATAMESSAGE); -+ chip->sub_state = 1; -+ chip->tx_state = tx_idle; -+ /* without break */ -+ case 1: -+ tmp = policy_send_data(chip); -+ -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_snk_discovery); -+ break; -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if (!PD_HEADER_CNT(chip->rec_head)) { -+ switch (PD_HEADER_TYPE(chip->rec_head)) { -+ case CMT_ACCEPT: -+ set_state(chip, -+ policy_snk_transition_sink); -+ chip->timer_state = T_PS_TRANSITION; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ break; -+ case CMT_WAIT: -+ case CMT_REJECT: -+ if (chip->notify.is_pd_connected) { -+ dev_info(chip->dev, -+ "PD connected as UFP, fetching 5V\n"); -+ set_state(chip, -+ policy_snk_ready); -+ } else { -+ set_state(chip, -+ policy_snk_wait_caps); -+ /* -+ * make sure don't send -+ * hard reset to prevent -+ * infinite loop -+ */ -+ chip->hardrst_count = -+ N_HARDRESET_COUNT + 1; -+ } -+ break; -+ default: -+ break; -+ } -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_transition_sink(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_PS_RDY)) { -+ chip->notify.is_pd_connected = true; -+ dev_info(chip->dev, -+ "PD connected as UFP, fetching 5V\n"); -+ set_state(chip, policy_snk_ready); -+ } else if (PACKET_IS_DATA_MSG(chip->rec_head, -+ DMT_SOURCECAPABILITIES)) { -+ set_state(chip, policy_snk_evaluate_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+} -+ -+static void fusb_state_snk_transition_default(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->notify.is_pd_connected = false; -+ chip->timer_mux = T_NO_RESPONSE; -+ fusb_timer_start(&chip->timer_mux_machine, -+ chip->timer_mux); -+ chip->timer_state = T_PS_HARD_RESET_MAX + T_SAFE_0V; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ if (chip->notify.data_role) -+ tcpm_set_msg_header(chip); -+ -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ if (!tcpm_check_vbus(chip)) { -+ chip->sub_state++; -+ chip->timer_state = T_SRC_RECOVER_MAX + T_SRC_TURN_ON; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_startup); -+ } -+ break; -+ default: -+ if (tcpm_check_vbus(chip)) { -+ chip->timer_state = T_DISABLED; -+ set_state(chip, policy_snk_startup); -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_startup); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_ready(struct fusb30x_chip *chip, u32 evt) -+{ -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_VENDERDEFINED)) { -+ process_vdm_msg(chip); -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ chip->timer_state = T_DISABLED; -+ } else if (!VDM_IS_ACTIVE(chip)) { -+ fusb_state_swap_msg_process(chip, evt); -+ } -+ } -+ -+ if (VDM_IS_ACTIVE(chip)) -+ auto_vdm_machine(chip, evt); -+ -+ fusb_state_swap_msg_process(chip, evt); -+ platform_fusb_notify(chip); -+} -+ -+static void fusb_state_snk_send_hardreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ default: -+ tmp = policy_send_hardrst(chip, evt); -+ if (tmp == tx_success) { -+ chip->hardrst_count++; -+ set_state(chip, policy_snk_transition_default); -+ } else if (tmp == tx_failed) { -+ set_state(chip, error_recovery); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_send_swap(struct fusb30x_chip *chip, u32 evt, int cmd) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, cmd, CONTROLMESSAGE); -+ chip->sub_state = 1; -+ chip->tx_state = tx_idle; -+ /* fallthrough */ -+ case 1: -+ tmp = policy_send_data(chip); -+ -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ if (cmd == CMT_DR_SWAP) { -+ set_state(chip, error_recovery); -+ return; -+ } -+ -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_send_softrst); -+ else -+ set_state(chip, policy_snk_send_softrst); -+ } -+ break; -+ case 2: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_ACCEPT)) { -+ chip->timer_state = T_DISABLED; -+ if (cmd == CMT_VCONN_SWAP) { -+ set_state(chip, chip->vconn_enabled ? -+ policy_vcs_dfp_wait_for_ufp_vconn : -+ policy_vcs_dfp_turn_on_vconn); -+ } else if (cmd == CMT_PR_SWAP) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_prs_transition_to_off); -+ else -+ set_state(chip, policy_snk_prs_transition_to_off); -+ chip->notify.power_role = POWER_ROLE_SOURCE; -+ tcpm_set_msg_header(chip); -+ } else if (cmd == CMT_DR_SWAP) { -+ set_state(chip, chip->notify.data_role ? -+ policy_drs_dfp_change : -+ policy_drs_ufp_change); -+ } -+ } else if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_REJECT) || -+ PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_WAIT)) { -+ chip->timer_state = T_DISABLED; -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_ready); -+ else -+ set_state(chip, policy_snk_ready); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_ready); -+ else -+ set_state(chip, policy_snk_ready); -+ } -+ } -+} -+ -+static void fusb_state_snk_prs_transition_to_off(struct fusb30x_chip *chip, -+ u32 evt) -+{ -+ switch (chip->sub_state) { -+ case 0: -+ chip->timer_state = T_PD_SOURCE_OFF; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ /* fallthrough */ -+ case 1: -+ if (evt & EVENT_RX) { -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, -+ CMT_PS_RDY)) { -+ if (chip->role == ROLE_MODE_DRP) -+ set_state(chip, -+ policy_snk_prs_assert_rp); -+ else -+ set_state(chip, -+ policy_snk_prs_source_on); -+ } else { -+ dev_dbg(chip->dev, -+ "rec careless msg: head %x\n", -+ chip->rec_head); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ chip->notify.power_role = POWER_ROLE_SINK; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_prs_assert_rp(struct fusb30x_chip *chip, u32 evt) -+{ -+ tcpm_set_cc_pull_mode(chip, CC_PULL_UP); -+ set_state(chip, policy_snk_prs_source_on); -+} -+ -+static void fusb_state_snk_prs_source_on(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ /* supply power in 50ms */ -+ platform_set_vbus_lvl_enable(chip, 1, 0); -+ chip->sub_state++; -+ chip->work_continue |= EVENT_WORK_CONTINUE; -+ break; -+ case 1: -+ set_mesg(chip, CMT_PS_RDY, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* fallthrough */ -+ case 2: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ /* PD spe 6.5.10.2 */ -+ chip->timer_state = T_PD_SWAP_SOURCE_START; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ chip->sub_state++; -+ } else if (tmp == tx_failed) { -+ chip->notify.power_role = POWER_ROLE_SINK; -+ tcpm_set_msg_header(chip); -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ case 3: -+ if (evt & EVENT_TIMER_STATE) { -+ chip->cc_state &= ~CC_STATE_TOGSS_IS_UFP; -+ regmap_update_bits(chip->regmap, FUSB_REG_MASK, -+ MASK_M_COMP_CHNG, 0); -+ set_state(chip, policy_src_send_caps); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_softreset(struct fusb30x_chip *chip) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_ACCEPT, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ /* without break */ -+ default: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ fusb_soft_reset_parameter(chip); -+ chip->timer_state = T_TYPEC_SINK_WAIT_CAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ set_state(chip, policy_snk_wait_caps); -+ } else if (tmp == tx_failed) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_state_snk_send_softreset(struct fusb30x_chip *chip, u32 evt) -+{ -+ u32 tmp; -+ -+ switch (chip->sub_state) { -+ case 0: -+ set_mesg(chip, CMT_SOFTRESET, CONTROLMESSAGE); -+ chip->tx_state = tx_idle; -+ chip->sub_state++; -+ case 1: -+ tmp = policy_send_data(chip); -+ if (tmp == tx_success) { -+ chip->timer_state = T_SENDER_RESPONSE; -+ chip->sub_state++; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ } else if (tmp == tx_failed) { -+ /* can't reach here */ -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ -+ if (!(evt & FLAG_EVENT)) -+ break; -+ default: -+ if (evt & EVENT_RX) { -+ if ((!PD_HEADER_CNT(chip->rec_head)) && -+ (PD_HEADER_TYPE(chip->rec_head) == CMT_ACCEPT)) { -+ fusb_soft_reset_parameter(chip); -+ chip->timer_state = T_TYPEC_SINK_WAIT_CAP; -+ fusb_timer_start(&chip->timer_state_machine, -+ chip->timer_state); -+ set_state(chip, policy_snk_wait_caps); -+ } -+ } else if (evt & EVENT_TIMER_STATE) { -+ set_state(chip, policy_snk_send_hardrst); -+ } -+ break; -+ } -+} -+ -+static void fusb_try_detach(struct fusb30x_chip *chip) -+{ -+ int cc1, cc2; -+ -+ if ((chip->cc_state & CC_STATE_TOGSS_IS_UFP) && -+ (chip->conn_state != -+ policy_snk_transition_default) && -+ (chip->conn_state != -+ policy_src_prs_source_off) && -+ (chip->conn_state != policy_snk_prs_send_swap) && -+ (chip->conn_state != policy_snk_prs_assert_rp) && -+ (chip->conn_state != policy_snk_prs_source_on) && -+ (chip->conn_state != policy_snk_prs_transition_to_off)) { -+ if (!tcpm_check_vbus(chip)) -+ set_state_unattached(chip); -+ } else if ((chip->conn_state != -+ policy_src_transition_default) && -+ (chip->conn_state != -+ policy_src_prs_source_off) && -+ (chip->conn_state != policy_snk_prs_source_on)) { -+ tcpm_get_cc(chip, &cc1, &cc2); -+ if (chip->cc_state & CC_STATE_TOGSS_CC2) -+ cc1 = cc2; -+ if (cc1 == TYPEC_CC_VOLT_OPEN) -+ set_state_unattached(chip); -+ } else { -+ /* -+ * Detached may occurred at swap operations. So, DON'T ignore -+ * the EVENT_CC during swapping at all, check the connection -+ * after it. -+ */ -+ chip->work_continue |= EVENT_DELAY_CC; -+ } -+} -+ -+static void state_machine_typec(struct fusb30x_chip *chip) -+{ -+ u32 evt = 0; -+ -+ tcpc_alert(chip, &evt); -+ mux_alert(chip, &evt); -+ if (!evt) -+ goto BACK; -+ -+ if (chip->notify.is_cc_connected) -+ if (evt & (EVENT_CC | EVENT_DELAY_CC)) -+ fusb_try_detach(chip); -+ -+ if (evt & EVENT_RX) { -+ tcpm_get_message(chip); -+ if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_SOFTRESET)) { -+ if (chip->notify.power_role) -+ set_state(chip, policy_src_softrst); -+ else -+ set_state(chip, policy_snk_softrst); -+ } -+ } -+ -+ if (evt & EVENT_TX) { -+ if (chip->tx_state == tx_success) -+ chip->msg_id++; -+ } -+ switch (chip->conn_state) { -+ case disabled: -+ fusb_state_disabled(chip, evt); -+ break; -+ case error_recovery: -+ set_state_unattached(chip); -+ break; -+ case unattached: -+ fusb_state_unattached(chip, evt); -+ break; -+ case attach_wait_sink: -+ fusb_state_attach_wait_sink(chip, evt); -+ break; -+ case attach_wait_source: -+ fusb_state_attach_wait_source(chip, evt); -+ break; -+ case attached_source: -+ fusb_state_attached_source(chip, evt); -+ break; -+ case attached_sink: -+ fusb_state_attached_sink(chip, evt); -+ break; -+ case attach_try_src: -+ fusb_state_try_attach(chip, evt, ROLE_MODE_DFP); -+ break; -+ case attach_try_snk: -+ fusb_state_try_attach(chip, evt, ROLE_MODE_UFP); -+ break; -+ -+ /* POWER DELIVERY */ -+ case policy_src_startup: -+ fusb_state_src_startup(chip, evt); -+ break; -+ case policy_src_discovery: -+ fusb_state_src_discovery(chip, evt); -+ break; -+ case policy_src_send_caps: -+ fusb_state_src_send_caps(chip, evt); -+ if (chip->conn_state != policy_src_negotiate_cap) -+ break; -+ case policy_src_negotiate_cap: -+ fusb_state_src_negotiate_cap(chip, evt); -+ -+ case policy_src_transition_supply: -+ fusb_state_src_transition_supply(chip, evt); -+ break; -+ case policy_src_cap_response: -+ fusb_state_src_cap_response(chip, evt); -+ break; -+ case policy_src_transition_default: -+ fusb_state_src_transition_default(chip, evt); -+ break; -+ case policy_src_ready: -+ fusb_state_src_ready(chip, evt); -+ break; -+ case policy_src_get_sink_caps: -+ fusb_state_src_get_sink_cap(chip, evt); -+ break; -+ case policy_src_send_hardrst: -+ fusb_state_src_send_hardreset(chip, evt); -+ break; -+ case policy_src_send_softrst: -+ fusb_state_src_send_softreset(chip, evt); -+ break; -+ case policy_src_softrst: -+ fusb_state_src_softreset(chip); -+ break; -+ -+ /* UFP */ -+ case policy_snk_startup: -+ fusb_state_snk_startup(chip, evt); -+ break; -+ case policy_snk_discovery: -+ fusb_state_snk_discovery(chip, evt); -+ break; -+ case policy_snk_wait_caps: -+ fusb_state_snk_wait_caps(chip, evt); -+ break; -+ case policy_snk_evaluate_caps: -+ fusb_state_snk_evaluate_caps(chip, evt); -+ /* without break */ -+ case policy_snk_select_cap: -+ fusb_state_snk_select_cap(chip, evt); -+ break; -+ case policy_snk_transition_sink: -+ fusb_state_snk_transition_sink(chip, evt); -+ break; -+ case policy_snk_transition_default: -+ fusb_state_snk_transition_default(chip, evt); -+ break; -+ case policy_snk_ready: -+ fusb_state_snk_ready(chip, evt); -+ break; -+ case policy_snk_send_hardrst: -+ fusb_state_snk_send_hardreset(chip, evt); -+ break; -+ case policy_snk_send_softrst: -+ fusb_state_snk_send_softreset(chip, evt); -+ break; -+ case policy_snk_softrst: -+ fusb_state_snk_softreset(chip); -+ break; -+ -+ /* -+ * PD Spec 1.0: PR SWAP: chap 8.3.3.6.3.1/2 -+ * VC SWAP: chap 8.3.3.7.1/2 -+ */ -+ case policy_src_prs_evaluate: -+ case policy_snk_prs_evaluate: -+ fusb_state_prs_evaluate(chip, evt); -+ break; -+ case policy_snk_prs_accept: -+ case policy_src_prs_accept: -+ fusb_state_prs_accept(chip, evt); -+ break; -+ case policy_snk_prs_reject: -+ case policy_src_prs_reject: -+ case policy_vcs_ufp_reject: -+ case policy_drs_dfp_reject: -+ case policy_drs_ufp_reject: -+ fusb_state_prs_reject(chip, evt); -+ break; -+ case policy_src_prs_transition_to_off: -+ fusb_state_src_prs_transition_to_off(chip, evt); -+ break; -+ case policy_src_prs_assert_rd: -+ fusb_state_src_prs_assert_rd(chip, evt); -+ break; -+ case policy_src_prs_source_off: -+ fusb_state_src_prs_source_off(chip, evt); -+ break; -+ case policy_snk_prs_send_swap: -+ case policy_src_prs_send_swap: -+ fusb_state_send_swap(chip, evt, CMT_PR_SWAP); -+ break; -+ case policy_snk_prs_transition_to_off: -+ fusb_state_snk_prs_transition_to_off(chip, evt); -+ break; -+ case policy_snk_prs_assert_rp: -+ fusb_state_snk_prs_assert_rp(chip, evt); -+ break; -+ case policy_snk_prs_source_on: -+ fusb_state_snk_prs_source_on(chip, evt); -+ break; -+ case policy_vcs_ufp_evaluate_swap: -+ fusb_state_vcs_ufp_evaluate_swap(chip, evt); -+ break; -+ case policy_vcs_ufp_accept: -+ fusb_state_vcs_ufp_accept(chip, evt); -+ break; -+ case policy_vcs_ufp_wait_for_dfp_vconn: -+ case policy_vcs_dfp_wait_for_ufp_vconn: -+ fusb_state_vcs_wait_for_vconn(chip, evt); -+ break; -+ case policy_vcs_ufp_turn_off_vconn: -+ case policy_vcs_dfp_turn_off_vconn: -+ fusb_state_vcs_set_vconn(chip, evt, false); -+ break; -+ case policy_vcs_ufp_turn_on_vconn: -+ case policy_vcs_dfp_turn_on_vconn: -+ fusb_state_vcs_set_vconn(chip, evt, true); -+ break; -+ case policy_vcs_ufp_send_ps_rdy: -+ case policy_vcs_dfp_send_ps_rdy: -+ fusb_state_vcs_send_ps_rdy(chip, evt); -+ break; -+ case policy_vcs_dfp_send_swap: -+ fusb_state_send_swap(chip, evt, CMT_VCONN_SWAP); -+ break; -+ case policy_drs_ufp_evaluate: -+ case policy_drs_dfp_evaluate: -+ fusb_state_drs_evaluate(chip, evt); -+ break; -+ case policy_drs_dfp_accept: -+ case policy_drs_ufp_accept: -+ fusb_state_drs_send_accept(chip, evt); -+ break; -+ case policy_drs_dfp_change: -+ case policy_drs_ufp_change: -+ fusb_state_drs_role_change(chip, evt); -+ break; -+ case policy_drs_ufp_send_swap: -+ case policy_drs_dfp_send_swap: -+ fusb_state_send_swap(chip, evt, CMT_DR_SWAP); -+ break; -+ -+ default: -+ break; -+ } -+ -+BACK: -+ if (chip->work_continue) { -+ queue_work(chip->fusb30x_wq, &chip->work); -+ return; -+ } -+ -+ if (!platform_get_device_irq_state(chip)) -+ fusb_irq_enable(chip); -+ else -+ queue_work(chip->fusb30x_wq, &chip->work); -+} -+ -+static irqreturn_t cc_interrupt_handler(int irq, void *dev_id) -+{ -+ struct fusb30x_chip *chip = dev_id; -+ -+ queue_work(chip->fusb30x_wq, &chip->work); -+ fusb_irq_disable(chip); -+ return IRQ_HANDLED; -+} -+ -+static int fusb_initialize_gpio(struct fusb30x_chip *chip) -+{ -+ chip->gpio_int = devm_gpiod_get_optional(chip->dev, "int-n", GPIOD_IN); -+ if (IS_ERR(chip->gpio_int)) -+ return PTR_ERR(chip->gpio_int); -+ -+ /* some board support vbus with other ways */ -+ chip->gpio_vbus_5v = devm_gpiod_get_optional(chip->dev, "vbus-5v", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(chip->gpio_vbus_5v)) -+ dev_warn(chip->dev, -+ "Could not get named GPIO for VBus5V!\n"); -+ else -+ gpiod_set_raw_value(chip->gpio_vbus_5v, 0); -+ -+ chip->gpio_vbus_other = devm_gpiod_get_optional(chip->dev, -+ "vbus-other", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(chip->gpio_vbus_other)) -+ dev_warn(chip->dev, -+ "Could not get named GPIO for VBusOther!\n"); -+ else -+ gpiod_set_raw_value(chip->gpio_vbus_other, 0); -+ -+ chip->gpio_discharge = devm_gpiod_get_optional(chip->dev, "discharge", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(chip->gpio_discharge)) { -+ dev_warn(chip->dev, -+ "Could not get named GPIO for discharge!\n"); -+ chip->gpio_discharge = NULL; -+ } -+ -+ return 0; -+} -+ -+static enum hrtimer_restart fusb_timer_handler(struct hrtimer *timer) -+{ -+ int i; -+ -+ for (i = 0; i < fusb30x_port_used; i++) { -+ if (timer == &fusb30x_port_info[i]->timer_state_machine) { -+ if (fusb30x_port_info[i]->timer_state != T_DISABLED) -+ fusb30x_port_info[i]->timer_state = 0; -+ break; -+ } -+ -+ if (timer == &fusb30x_port_info[i]->timer_mux_machine) { -+ if (fusb30x_port_info[i]->timer_mux != T_DISABLED) -+ fusb30x_port_info[i]->timer_mux = 0; -+ break; -+ } -+ } -+ -+ if (i != fusb30x_port_used) -+ queue_work(fusb30x_port_info[i]->fusb30x_wq, -+ &fusb30x_port_info[i]->work); -+ -+ return HRTIMER_NORESTART; -+} -+ -+static void fusb_initialize_timer(struct fusb30x_chip *chip) -+{ -+ hrtimer_init(&chip->timer_state_machine, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ chip->timer_state_machine.function = fusb_timer_handler; -+ -+ hrtimer_init(&chip->timer_mux_machine, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ chip->timer_mux_machine.function = fusb_timer_handler; -+ -+ chip->timer_state = T_DISABLED; -+ chip->timer_mux = T_DISABLED; -+} -+ -+static void fusb302_work_func(struct work_struct *work) -+{ -+ struct fusb30x_chip *chip; -+ -+ chip = container_of(work, struct fusb30x_chip, work); -+ state_machine_typec(chip); -+} -+ -+static int fusb30x_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct fusb30x_chip *chip; -+ struct PD_CAP_INFO *pd_cap_info; -+ int ret; -+ char *string[2]; -+ -+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); -+ if (!chip) -+ return -ENOMEM; -+ -+ if (fusb30x_port_used == 0xff) -+ return -1; -+ -+ chip->port_num = fusb30x_port_used++; -+ fusb30x_port_info[chip->port_num] = chip; -+ -+ chip->dev = &client->dev; -+ chip->regmap = devm_regmap_init_i2c(client, &fusb302_regmap_config); -+ if (IS_ERR(chip->regmap)) { -+ dev_err(&client->dev, "Failed to allocate regmap!\n"); -+ return PTR_ERR(chip->regmap); -+ } -+ -+ ret = fusb_initialize_gpio(chip); -+ if (ret) -+ return ret; -+ -+ fusb_initialize_timer(chip); -+ -+ chip->fusb30x_wq = create_workqueue("fusb302_wq"); -+ INIT_WORK(&chip->work, fusb302_work_func); -+ -+ chip->role = ROLE_MODE_NONE; -+ chip->try_role = ROLE_MODE_NONE; -+ if (!of_property_read_string(chip->dev->of_node, "fusb302,role", -+ (const char **)&string[0])) { -+ if (!strcmp(string[0], "ROLE_MODE_DRP")) -+ chip->role = ROLE_MODE_DRP; -+ else if (!strcmp(string[0], "ROLE_MODE_DFP")) -+ chip->role = ROLE_MODE_DFP; -+ else if (!strcmp(string[0], "ROLE_MODE_UFP")) -+ chip->role = ROLE_MODE_UFP; -+ } -+ -+ if (chip->role == ROLE_MODE_NONE) { -+ dev_warn(chip->dev, -+ "Can't get property of role, set role to default DRP\n"); -+ chip->role = ROLE_MODE_DRP; -+ string[0] = "ROLE_MODE_DRP"; -+ } -+ -+ if (!of_property_read_string(chip->dev->of_node, "fusb302,try_role", -+ (const char **)&string[1])) { -+ if (!strcmp(string[1], "ROLE_MODE_DFP")) -+ chip->try_role = ROLE_MODE_DFP; -+ else if (!strcmp(string[1], "ROLE_MODE_UFP")) -+ chip->try_role = ROLE_MODE_UFP; -+ } -+ -+ if (chip->try_role == ROLE_MODE_NONE) -+ string[1] = "ROLE_MODE_NONE"; -+ -+ chip->vconn_supported = true; -+ tcpm_init(chip); -+ tcpm_set_rx_enable(chip, 0); -+ chip->conn_state = unattached; -+ tcpm_set_cc(chip, chip->role); -+ -+ chip->n_caps_used = 1; -+ chip->source_power_supply[0] = 0x64; -+ chip->source_max_current[0] = 0x96; -+ -+ pd_cap_info = &chip->pd_cap_info; -+ pd_cap_info->dual_role_power = 1; -+ pd_cap_info->data_role_swap = 1; -+ -+ pd_cap_info->externally_powered = 1; -+ pd_cap_info->usb_suspend_support = 0; -+ pd_cap_info->usb_communications_cap = 0; -+ pd_cap_info->supply_type = 0; -+ pd_cap_info->peak_current = 0; -+ -+ chip->extcon = devm_extcon_dev_allocate(&client->dev, fusb302_cable); -+ if (IS_ERR(chip->extcon)) { -+ dev_err(&client->dev, "allocat extcon failed\n"); -+ return PTR_ERR(chip->extcon); -+ } -+ -+ ret = devm_extcon_dev_register(&client->dev, chip->extcon); -+ if (ret) { -+ dev_err(&client->dev, "failed to register extcon: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB_HOST property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set DISP_DP property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB, -+ EXTCON_PROP_USB_SS); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB USB_SS property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST, -+ EXTCON_PROP_USB_SS); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB_HOST USB_SS property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP, -+ EXTCON_PROP_USB_SS); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set DISP_DP USB_SS property capability: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = extcon_set_property_capability(chip->extcon, EXTCON_CHG_USB_FAST, -+ EXTCON_PROP_USB_TYPEC_POLARITY); -+ if (ret) { -+ dev_err(&client->dev, -+ "failed to set USB_PD property capability: %d\n", ret); -+ return ret; -+ } -+ -+ i2c_set_clientdata(client, chip); -+ -+ spin_lock_init(&chip->irq_lock); -+ chip->enable_irq = 1; -+ -+ chip->gpio_int_irq = gpiod_to_irq(chip->gpio_int); -+ if (chip->gpio_int_irq < 0) { -+ dev_err(&client->dev, -+ "Unable to request IRQ for INT_N GPIO! %d\n", -+ ret); -+ ret = chip->gpio_int_irq; -+ goto IRQ_ERR; -+ } -+ -+ ret = devm_request_threaded_irq(&client->dev, -+ chip->gpio_int_irq, -+ NULL, -+ cc_interrupt_handler, -+ IRQF_ONESHOT | IRQF_TRIGGER_LOW, -+ client->name, -+ chip); -+ if (ret) { -+ dev_err(&client->dev, "irq request failed\n"); -+ goto IRQ_ERR; -+ } -+ -+ dev_info(chip->dev, -+ "port %d probe success with role %s, try_role %s\n", -+ chip->port_num, string[0], string[1]); -+ -+ return 0; -+ -+IRQ_ERR: -+ destroy_workqueue(chip->fusb30x_wq); -+ return ret; -+} -+ -+static int fusb30x_remove(struct i2c_client *client) -+{ -+ struct fusb30x_chip *chip = i2c_get_clientdata(client); -+ -+ destroy_workqueue(chip->fusb30x_wq); -+ return 0; -+} -+ -+static void fusb30x_shutdown(struct i2c_client *client) -+{ -+ struct fusb30x_chip *chip = i2c_get_clientdata(client); -+ -+ if (chip->gpio_vbus_5v) -+ gpiod_set_value(chip->gpio_vbus_5v, 0); -+ if (chip->gpio_discharge) { -+ gpiod_set_value(chip->gpio_discharge, 1); -+ msleep(100); -+ gpiod_set_value(chip->gpio_discharge, 0); -+ } -+} -+ -+static const struct of_device_id fusb30x_dt_match[] = { -+ { .compatible = FUSB30X_I2C_DEVICETREE_NAME }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, fusb30x_dt_match); -+ -+static const struct i2c_device_id fusb30x_i2c_device_id[] = { -+ { FUSB30X_I2C_DRIVER_NAME, 0 }, -+ {} -+}; -+MODULE_DEVICE_TABLE(i2c, fusb30x_i2c_device_id); -+ -+static struct i2c_driver fusb30x_driver = { -+ .driver = { -+ .name = FUSB30X_I2C_DRIVER_NAME, -+ .of_match_table = of_match_ptr(fusb30x_dt_match), -+ }, -+ .probe = fusb30x_probe, -+ .remove = fusb30x_remove, -+ .shutdown = fusb30x_shutdown, -+ .id_table = fusb30x_i2c_device_id, -+}; -+ -+module_i2c_driver(fusb30x_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("zain wang "); -+MODULE_DESCRIPTION("fusb302 typec pd driver"); -diff --git a/drivers/staging/fusb30x/fusb30x.h b/drivers/staging/fusb30x/fusb30x.h -new file mode 100644 -index 000000000..4f5ca64f7 ---- /dev/null -+++ b/drivers/staging/fusb30x/fusb30x.h -@@ -0,0 +1,552 @@ -+/* -+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd -+ * Author: Zain Wang -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * Some ideas are from chrome ec and fairchild GPL fusb302 driver. -+ */ -+ -+#ifndef FUSB302_H -+#define FUSB302_H -+ -+#include -+#include -+ -+const char *FUSB_DT_INTERRUPT_INTN = "fsc_interrupt_int_n"; -+#define FUSB_DT_GPIO_INTN "fairchild,int_n" -+#define FUSB_DT_GPIO_VBUS_5V "fairchild,vbus5v" -+#define FUSB_DT_GPIO_VBUS_OTHER "fairchild,vbusOther" -+ -+#define FUSB30X_I2C_DRIVER_NAME "fusb302" -+#define FUSB30X_I2C_DEVICETREE_NAME "fairchild,fusb302" -+ -+/* FUSB300 Register Addresses */ -+#define FUSB_REG_DEVICEID 0x01 -+#define FUSB_REG_SWITCHES0 0x02 -+#define FUSB_REG_SWITCHES1 0x03 -+#define FUSB_REG_MEASURE 0x04 -+#define FUSB_REG_SLICE 0x05 -+#define FUSB_REG_CONTROL0 0x06 -+#define FUSB_REG_CONTROL1 0x07 -+#define FUSB_REG_CONTROL2 0x08 -+#define FUSB_REG_CONTROL3 0x09 -+#define FUSB_REG_MASK 0x0A -+#define FUSB_REG_POWER 0x0B -+#define FUSB_REG_RESET 0x0C -+#define FUSB_REG_OCPREG 0x0D -+#define FUSB_REG_MASKA 0x0E -+#define FUSB_REG_MASKB 0x0F -+#define FUSB_REG_CONTROL4 0x10 -+#define FUSB_REG_STATUS0A 0x3C -+#define FUSB_REG_STATUS1A 0x3D -+#define FUSB_REG_INTERRUPTA 0x3E -+#define FUSB_REG_INTERRUPTB 0x3F -+#define FUSB_REG_STATUS0 0x40 -+#define FUSB_REG_STATUS1 0x41 -+#define FUSB_REG_INTERRUPT 0x42 -+#define FUSB_REG_FIFO 0x43 -+ -+enum connection_state { -+ disabled = 0, -+ error_recovery, -+ unattached, -+ attach_wait_sink, -+ attach_wait_source, -+ attached_source, -+ attached_sink, -+ -+ policy_src_startup, -+ policy_src_send_caps, -+ policy_src_discovery, -+ policy_src_negotiate_cap, -+ policy_src_cap_response, -+ policy_src_transition_supply, -+ policy_src_transition_default, -+ -+ policy_src_ready, -+ policy_src_get_sink_caps, -+ -+ policy_src_send_softrst, -+ policy_src_softrst, -+ policy_src_send_hardrst, -+ -+ policy_snk_startup, -+ policy_snk_discovery, -+ policy_snk_wait_caps, -+ policy_snk_evaluate_caps, -+ policy_snk_select_cap, -+ policy_snk_transition_sink, -+ policy_snk_ready, -+ -+ policy_snk_send_softrst, -+ policy_snk_softrst, -+ policy_snk_send_hardrst, -+ -+ policy_snk_transition_default, -+ -+ /* PR SWAP */ -+ policy_src_prs_evaluate, -+ policy_src_prs_accept, -+ policy_src_prs_transition_to_off, -+ policy_src_prs_source_off, -+ policy_src_prs_assert_rd, -+ policy_src_prs_reject, -+ policy_src_prs_send_swap, -+ -+ policy_snk_prs_evaluate, -+ policy_snk_prs_accept, -+ policy_snk_prs_transition_to_off, -+ policy_snk_prs_source_on, -+ policy_snk_prs_assert_rp, -+ policy_snk_prs_reject, -+ policy_snk_prs_send_swap, -+ -+ /* VC SWAP */ -+ policy_vcs_dfp_send_swap, -+ policy_vcs_dfp_wait_for_ufp_vconn, -+ policy_vcs_dfp_turn_off_vconn, -+ policy_vcs_dfp_turn_on_vconn, -+ policy_vcs_dfp_send_ps_rdy, -+ -+ policy_vcs_ufp_evaluate_swap, -+ policy_vcs_ufp_reject, -+ policy_vcs_ufp_accept, -+ policy_vcs_ufp_wait_for_dfp_vconn, -+ policy_vcs_ufp_turn_off_vconn, -+ policy_vcs_ufp_turn_on_vconn, -+ policy_vcs_ufp_send_ps_rdy, -+ -+ policy_drs_ufp_evaluate, -+ policy_drs_ufp_accept, -+ policy_drs_ufp_reject, -+ policy_drs_ufp_change, -+ policy_drs_ufp_send_swap, -+ -+ policy_drs_dfp_evaluate, -+ policy_drs_dfp_accept, -+ policy_drs_dfp_reject, -+ policy_drs_dfp_change, -+ policy_drs_dfp_send_swap, -+ -+ attach_try_src, -+ attach_try_snk, -+}; -+ -+enum vdm_state { -+ VDM_STATE_DISCOVERY_ID, -+ VDM_STATE_DISCOVERY_SVID, -+ VDM_STATE_DISCOVERY_MODES, -+ VDM_STATE_ENTER_MODE, -+ VDM_STATE_UPDATE_STATUS, -+ VDM_STATE_DP_CONFIG, -+ VDM_STATE_NOTIFY, -+ VDM_STATE_READY, -+ VDM_STATE_ERR, -+}; -+ -+enum tcpm_rp_value { -+ TYPEC_RP_USB = 0, -+ TYPEC_RP_1A5 = 1, -+ TYPEC_RP_3A0 = 2, -+ TYPEC_RP_RESERVED = 3, -+}; -+ -+enum role_mode { -+ ROLE_MODE_NONE, -+ ROLE_MODE_DRP, -+ ROLE_MODE_UFP, -+ ROLE_MODE_DFP, -+ ROLE_MODE_ASS, -+}; -+ -+#define SBF(s, v) ((s) << (v)) -+#define SWITCHES0_PDWN1 SBF(1, 0) -+#define SWITCHES0_PDWN2 SBF(1, 1) -+#define SWITCHES0_MEAS_CC1 SBF(1, 2) -+#define SWITCHES0_MEAS_CC2 SBF(1, 3) -+#define SWITCHES0_VCONN_CC1 SBF(1, 4) -+#define SWITCHES0_VCONN_CC2 SBF(1, 5) -+#define SWITCHES0_PU_EN1 SBF(1, 6) -+#define SWITCHES0_PU_EN2 SBF(1, 7) -+ -+#define SWITCHES1_TXCC1 SBF(1, 0) -+#define SWITCHES1_TXCC2 SBF(1, 1) -+#define SWITCHES1_AUTO_CRC SBF(1, 2) -+#define SWITCHES1_DATAROLE SBF(1, 4) -+#define SWITCHES1_SPECREV SBF(3, 5) -+#define SWITCHES1_POWERROLE SBF(1, 7) -+ -+#define MEASURE_MDAC SBF(0x3f, 0) -+#define MEASURE_VBUS SBF(1, 6) -+ -+#define SLICE_SDAC SBF(0x3f, 0) -+#define SLICE_SDAC_HYS SBF(3, 6) -+ -+#define CONTROL0_TX_START SBF(1, 0) -+#define CONTROL0_AUTO_PRE SBF(1, 1) -+#define CONTROL0_HOST_CUR SBF(3, 2) -+#define CONTROL0_HOST_CUR_USB SBF(1, 2) -+#define CONTROL0_HOST_CUR_1A5 SBF(2, 2) -+#define CONTROL0_HOST_CUR_3A0 SBF(3, 2) -+#define CONTROL0_INT_MASK SBF(1, 5) -+#define CONTROL0_TX_FLUSH SBF(1, 6) -+ -+#define CONTROL1_ENSOP1 SBF(1, 0) -+#define CONTROL1_ENSOP2 SBF(1, 1) -+#define CONTROL1_RX_FLUSH SBF(1, 2) -+#define CONTROL1_BIST_MODE2 SBF(1, 4) -+#define CONTROL1_ENSOP1DB SBF(1, 5) -+#define CONTROL1_ENSOP2DB SBF(1, 6) -+ -+#define CONTROL2_TOGGLE SBF(1, 0) -+#define CONTROL2_MODE SBF(3, 1) -+#define CONTROL2_MODE_NONE 0 -+#define CONTROL2_MODE_DFP SBF(3, 1) -+#define CONTROL2_MODE_UFP SBF(2, 1) -+#define CONTROL2_MODE_DRP SBF(1, 1) -+#define CONTROL2_WAKE_EN SBF(1, 3) -+#define CONTROL2_TOG_RD_ONLY SBF(1, 5) -+#define CONTROL2_TOG_SAVE_PWR1 SBF(1, 6) -+#define CONTROL2_TOG_SAVE_PWR2 SBF(1, 7) -+ -+#define CONTROL3_AUTO_RETRY SBF(1, 0) -+#define CONTROL3_N_RETRIES SBF(3, 1) -+#define CONTROL3_AUTO_SOFTRESET SBF(1, 3) -+#define CONTROL3_AUTO_HARDRESET SBF(1, 4) -+#define CONTROL3_SEND_HARDRESET SBF(1, 6) -+ -+#define MASK_M_BC_LVL SBF(1, 0) -+#define MASK_M_COLLISION SBF(1, 1) -+#define MASK_M_WAKE SBF(1, 2) -+#define MASK_M_ALERT SBF(1, 3) -+#define MASK_M_CRC_CHK SBF(1, 4) -+#define MASK_M_COMP_CHNG SBF(1, 5) -+#define MASK_M_ACTIVITY SBF(1, 6) -+#define MASK_M_VBUSOK SBF(1, 7) -+ -+#define POWER_PWR SBF(0xf, 0) -+ -+#define RESET_SW_RESET SBF(1, 0) -+#define RESET_PD_RESET SBF(1, 1) -+ -+#define MASKA_M_HARDRST SBF(1, 0) -+#define MASKA_M_SOFTRST SBF(1, 1) -+#define MASKA_M_TXSENT SBF(1, 2) -+#define MASKA_M_HARDSENT SBF(1, 3) -+#define MASKA_M_RETRYFAIL SBF(1, 4) -+#define MASKA_M_SOFTFAIL SBF(1, 5) -+#define MASKA_M_TOGDONE SBF(1, 6) -+#define MASKA_M_OCP_TEMP SBF(1, 7) -+ -+#define MASKB_M_GCRCSEND SBF(1, 0) -+ -+#define CONTROL4_TOG_USRC_EXIT SBF(1, 0) -+ -+#define MDAC_1P6V 0x26 -+ -+#define STATUS0A_HARDRST SBF(1, 0) -+#define STATUS0A_SOFTRST SBF(1, 1) -+#define STATUS0A_POWER23 SBF(3, 2) -+#define STATUS0A_RETRYFAIL SBF(1, 4) -+#define STATUS0A_SOFTFAIL SBF(1, 5) -+#define STATUS0A_TOGDONE SBF(1, 6) -+#define STATUS0A_M_OCP_TEMP SBF(1, 7) -+ -+#define STATUS1A_RXSOP SBF(1, 0) -+#define STATUS1A_RXSOP1DB SBF(1, 1) -+#define STATUS1A_RXSOP2DB SBF(1, 2) -+#define STATUS1A_TOGSS SBF(7, 3) -+#define CC_STATE_TOGSS_CC1 SBF(1, 0) -+#define CC_STATE_TOGSS_CC2 SBF(1, 1) -+#define CC_STATE_TOGSS_IS_UFP SBF(1, 2) -+ -+#define INTERRUPTA_HARDRST SBF(1, 0) -+#define INTERRUPTA_SOFTRST SBF(1, 1) -+#define INTERRUPTA_TXSENT SBF(1, 2) -+#define INTERRUPTA_HARDSENT SBF(1, 3) -+#define INTERRUPTA_RETRYFAIL SBF(1, 4) -+#define INTERRUPTA_SOFTFAIL SBF(1, 5) -+#define INTERRUPTA_TOGDONE SBF(1, 6) -+#define INTERRUPTA_OCP_TEMP SBF(1, 7) -+ -+#define INTERRUPTB_GCRCSENT SBF(1, 0) -+ -+#define STATUS0_BC_LVL SBF(3, 0) -+#define STATUS0_WAKE SBF(1, 2) -+#define STATUS0_ALERT SBF(1, 3) -+#define STATUS0_CRC_CHK SBF(1, 4) -+#define STATUS0_COMP SBF(1, 5) -+#define STATUS0_ACTIVITY SBF(1, 6) -+#define STATUS0_VBUSOK SBF(1, 7) -+ -+#define STATUS1_OCP SBF(1, 0) -+#define STATUS1_OVRTEMP SBF(1, 1) -+#define STATUS1_TX_FULL SBF(1, 2) -+#define STATUS1_TX_EMPTY SBF(1, 3) -+#define STATUS1_RX_FULL SBF(1, 4) -+#define STATUS1_RX_EMPTY SBF(1, 5) -+#define STATUS1_RXSOP1 SBF(1, 6) -+#define STATUS1_RXSOP2 SBF(1, 7) -+ -+#define INTERRUPT_BC_LVL SBF(1, 0) -+#define INTERRUPT_COLLISION SBF(1, 1) -+#define INTERRUPT_WAKE SBF(1, 2) -+#define INTERRUPT_ALERT SBF(1, 3) -+#define INTERRUPT_CRC_CHK SBF(1, 4) -+#define INTERRUPT_COMP_CHNG SBF(1, 5) -+#define INTERRUPT_ACTIVITY SBF(1, 6) -+#define INTERRUPT_VBUSOK SBF(1, 7) -+ -+#define FUSB_TKN_TXON 0xa1 -+#define FUSB_TKN_SYNC1 0x12 -+#define FUSB_TKN_SYNC2 0x13 -+#define FUSB_TKN_SYNC3 0x1b -+#define FUSB_TKN_RST1 0x15 -+#define FUSB_TKN_RST2 0x16 -+#define FUSB_TKN_PACKSYM 0x80 -+#define FUSB_TKN_JAMCRC 0xff -+#define FUSB_TKN_EOP 0x14 -+#define FUSB_TKN_TXOFF 0xfe -+ -+/* USB PD Control Message Types */ -+#define CONTROLMESSAGE 0 -+#define CMT_GOODCRC 1 -+#define CMT_GOTOMIN 2 -+#define CMT_ACCEPT 3 -+#define CMT_REJECT 4 -+#define CMT_PING 5 -+#define CMT_PS_RDY 6 -+#define CMT_GETSOURCECAP 7 -+#define CMT_GETSINKCAP 8 -+#define CMT_DR_SWAP 9 -+#define CMT_PR_SWAP 10 -+#define CMT_VCONN_SWAP 11 -+#define CMT_WAIT 12 -+#define CMT_SOFTRESET 13 -+ -+/* USB PD Data Message Types */ -+#define DATAMESSAGE 1 -+#define DMT_SOURCECAPABILITIES 1 -+#define DMT_REQUEST 2 -+#define DMT_BIST 3 -+#define DMT_SINKCAPABILITIES 4 -+#define DMT_VENDERDEFINED 15 -+ -+/* VDM Command Types */ -+#define VDM_DISCOVERY_ID 0X01 -+#define VDM_DISCOVERY_SVIDS 0X02 -+#define VDM_DISCOVERY_MODES 0X03 -+#define VDM_ENTER_MODE 0X04 -+#define VDM_EXIT_MODE 0X05 -+#define VDM_ATTENTION 0X06 -+#define VDM_DP_STATUS_UPDATE 0X10 -+#define VDM_DP_CONFIG 0X11 -+ -+#define VDM_TYPE_INIT 0 -+#define VDM_TYPE_ACK 1 -+#define VDM_TYPE_NACK 2 -+#define VDM_TYPE_BUSY 3 -+ -+/* 200ms at least, 1 cycle about 6ms */ -+#define N_DEBOUNCE_CNT 33 -+#define N_CAPS_COUNT 50 -+#define N_HARDRESET_COUNT 0 -+ -+#define T_NO_RESPONSE 5000 -+#define T_SRC_RECOVER 830 -+#define T_TYPEC_SEND_SOURCECAP 100 -+#define T_SENDER_RESPONSE 30 -+#define T_SRC_TRANSITION 30 -+#define T_TYPEC_SINK_WAIT_CAP 500 -+#define T_PS_TRANSITION 500 -+#define T_BMC_TIMEOUT 5 -+#define T_PS_HARD_RESET_MAX 35 -+#define T_SAFE_0V 650 -+#define T_SRC_TURN_ON 275 -+#define T_SRC_RECOVER_MAX 1000 -+#define T_PD_SOURCE_OFF 920 -+#define T_PD_SOURCE_ON 480 -+#define T_PD_SWAP_SOURCE_START 20 -+#define T_PD_VCONN_SRC_ON 100 -+#define T_PD_TRY_DRP 75 -+ -+#define T_NO_TRIGGER 500 -+#define T_DISABLED 0xffff -+ -+#define PD_HEADER_CNT(header) (((header) >> 12) & 7) -+#define PD_HEADER_TYPE(header) ((header) & 0xF) -+#define PD_HEADER_ID(header) (((header) >> 9) & 7) -+ -+#define VDM_HEADER_TYPE(header) (((header) >> 6) & 3) -+#define VDMHEAD_CMD_TYPE_MASK (3 << 6) -+#define VDMHEAD_CMD_MASK (0x1f << 0) -+#define VDMHEAD_STRUCT_TYPE_MASK BIT(15) -+ -+#define GET_VDMHEAD_CMD_TYPE(head) ((head & VDMHEAD_CMD_TYPE_MASK) >> 6) -+#define GET_VDMHEAD_CMD(head) (head & VDMHEAD_CMD_MASK) -+#define GET_VDMHEAD_STRUCT_TYPE(head) ((head & VDMHEAD_STRUCT_TYPE_MASK) >> 15) -+ -+#define DP_STATUS_MASK 0x000000ff -+#define DP_STATUS_HPD_STATE BIT(7) -+ -+#define GET_DP_STATUS(status) (status & DP_STATUS_MASK) -+#define GET_DP_STATUS_HPD(status) ((status & DP_STATUS_HPD_STATE) >> 7) -+ -+#define VDM_IDHEAD_USBVID_MASK (0xffff << 0) -+#define VDM_IDHEAD_MODALSUPPORT_MASK BIT(26) -+#define VDM_IDHEAD_PRODUCTTYPE (7 << 27) -+#define VDM_IDHEAD_USBDEVICE BIT(30) -+#define VDM_IDHEAD_USBHOST BIT(30) -+ -+#define CAP_POWER_TYPE(PDO) ((PDO >> 30) & 3) -+#define CAP_FPDO_VOLTAGE(PDO) ((PDO >> 10) & 0x3ff) -+#define CAP_VPDO_VOLTAGE(PDO) ((PDO >> 20) & 0x3ff) -+#define CAP_FPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff) -+#define CAP_VPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff) -+ -+enum CC_ORIENTATION { -+ NONE, -+ CC1, -+ CC2, -+}; -+ -+enum typec_cc_polarity { -+ TYPEC_POLARITY_CC1, -+ TYPEC_POLARITY_CC2, -+}; -+ -+enum CC_MODE { -+ CC_PULL_UP, -+ CC_PULL_DOWN, -+ CC_PULL_NONE, -+}; -+ -+enum typec_power_role { -+ POWER_ROLE_SINK = 0, -+ POWER_ROLE_SOURCE, -+}; -+ -+enum typec_data_role { -+ DATA_ROLE_UFP = 0, -+ DATA_ROLE_DFP, -+}; -+ -+struct notify_info { -+ enum CC_ORIENTATION orientation; -+ /* 0 UFP : 1 DFP */ -+ enum typec_power_role power_role; -+ enum typec_data_role data_role; -+ -+ bool is_cc_connected; -+ bool is_pd_connected; -+ -+ bool is_enter_mode; -+ int pin_assignment_support; -+ int pin_assignment_def; -+ bool attention; -+ u32 dp_status; -+ u32 dp_caps; -+}; -+ -+enum tx_state { -+ tx_idle, -+ tx_busy, -+ tx_failed, -+ tx_success -+}; -+ -+struct PD_CAP_INFO { -+ u32 peak_current; -+ u32 specification_revision; -+ u32 externally_powered; -+ u32 usb_suspend_support; -+ u32 usb_communications_cap; -+ u32 dual_role_power; -+ u32 data_role_swap; -+ u32 supply_type; -+}; -+ -+struct fusb30x_chip { -+ struct i2c_client *client; -+ struct device *dev; -+ struct regmap *regmap; -+ struct work_struct work; -+ struct workqueue_struct *fusb30x_wq; -+ struct hrtimer timer_state_machine; -+ struct hrtimer timer_mux_machine; -+ struct PD_CAP_INFO pd_cap_info; -+ struct notify_info notify; -+ struct notify_info notify_cmp; -+ struct extcon_dev *extcon; -+ enum connection_state conn_state; -+ struct gpio_desc *gpio_vbus_5v; -+ struct gpio_desc *gpio_vbus_other; -+ struct gpio_desc *gpio_int; -+ struct gpio_desc *gpio_discharge; -+ int timer_state; -+ int timer_mux; -+ int port_num; -+ u32 work_continue; -+ spinlock_t irq_lock; -+ int gpio_int_irq; -+ int enable_irq; -+ -+ /* -+ * --------------------------------- -+ * | role 0x03 << 2, | cc_use 0x03 | -+ * | src 1 << 2, | cc1 1 | -+ * | snk 2 << 2, | cc2 2 | -+ * --------------------------------- -+ */ -+ u8 cc_state; -+ int cc1; -+ int cc2; -+ enum typec_cc_polarity cc_polarity; -+ u8 val_tmp; -+ u8 debounce_cnt; -+ int sub_state; -+ int caps_counter; -+ u32 send_load[7]; -+ u32 rec_load[7]; -+ u16 send_head; -+ u16 rec_head; -+ int msg_id; -+ enum tx_state tx_state; -+ int hardrst_count; -+ u32 source_power_supply[7]; -+ /* 50mv unit */ -+ u32 source_max_current[7]; -+ /* 10ma uint*/ -+ int pos_power; -+ /* -+ * if PartnerCap[0] == 0xffffffff -+ * show Partner Device do not support supply -+ */ -+ u32 partner_cap[7]; -+ int n_caps_used; -+ int vdm_state; -+ int vdm_substate; -+ int vdm_send_state; -+ u16 vdm_svid[12]; -+ int vdm_svid_num; -+ u32 vdm_id; -+ u8 chip_id; -+ bool vconn_enabled; -+ bool is_pd_support; -+ int pd_output_vol; -+ int pd_output_cur; -+ int cc_meas_high; -+ int cc_meas_low; -+ bool vbus_begin; -+ -+ enum role_mode role; -+ bool vconn_supported; -+ bool try_role_complete; -+ enum role_mode try_role; -+}; -+ -+#endif /* FUSB302_H */ -+ diff --git a/sys-kernel/decade-sources/files/patches-5.14/add-maker-friendlyarm.patch b/sys-kernel/decade-sources/files/patches-5.14/add-maker-friendlyarm.patch deleted file mode 100644 index f48596b..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/add-maker-friendlyarm.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 2fc2cbaaaf0dcebdeffa6e87bbc9ad843a5470dd Mon Sep 17 00:00:00 2001 -From: hmz007 -Date: Sat, 11 Jan 2020 19:35:03 +0800 -Subject: [PATCH] soc: friendlyelec: Add board info driver - -Change-Id: I122adb4f99c816b5c177f16392fb2df9c10a47be -Signed-off-by: hmz007 ---- - drivers/soc/Kconfig | 1 + - drivers/soc/Makefile | 1 + - drivers/soc/friendlyelec/Kconfig | 11 ++ - drivers/soc/friendlyelec/Makefile | 1 + - drivers/soc/friendlyelec/board.c | 143 ++++++++++++++++++ - 8 files changed, 161 insertions(+) - create mode 100644 drivers/soc/friendlyelec/Kconfig - create mode 100644 drivers/soc/friendlyelec/Makefile - create mode 100644 drivers/soc/friendlyelec/board.c - -diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig -index 833e04a7835c..9ddbd976395d 100644 ---- a/drivers/soc/Kconfig -+++ b/drivers/soc/Kconfig -@@ -21,5 +21,6 @@ source "drivers/soc/ux500/Kconfig" - source "drivers/soc/ux500/Kconfig" - source "drivers/soc/versatile/Kconfig" - source "drivers/soc/xilinx/Kconfig" -+source "drivers/soc/friendlyelec/Kconfig" - - endmenu -diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile -index f678e4d9e..cfc815a7e 100644 ---- a/drivers/soc/Makefile -+++ b/drivers/soc/Makefile -@@ -29,3 +29,4 @@ obj-y += ti/ - obj-$(CONFIG_ARCH_U8500) += ux500/ - obj-$(CONFIG_PLAT_VERSATILE) += versatile/ - obj-y += xilinx/ -+obj-$(CONFIG_VENDOR_FRIENDLYELEC) += friendlyelec/ -diff --git a/drivers/soc/friendlyelec/Kconfig b/drivers/soc/friendlyelec/Kconfig -new file mode 100644 -index 000000000000..9e21c663e6c8 ---- /dev/null -+++ b/drivers/soc/friendlyelec/Kconfig -@@ -0,0 +1,11 @@ -+# -+# Machine drivers -+# -+ -+if ARCH_ROCKCHIP -+ -+config VENDOR_FRIENDLYELEC -+ bool "FriendlyElec board based on RK33XX SoCs" -+ default n -+ -+endif -diff --git a/drivers/soc/friendlyelec/Makefile b/drivers/soc/friendlyelec/Makefile -new file mode 100644 -index 000000000000..870542f05177 ---- /dev/null -+++ b/drivers/soc/friendlyelec/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_VENDOR_FRIENDLYELEC) += board.o -diff --git a/drivers/soc/friendlyelec/board.c b/drivers/soc/friendlyelec/board.c -new file mode 100644 -index 000000000000..886a8e1f7dc0 ---- /dev/null -+++ b/drivers/soc/friendlyelec/board.c -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) Guangzhou FriendlyELEC Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, you can access it online at -+ * http://www.gnu.org/licenses/gpl-2.0.html. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define BOARD_MANF "FriendlyELEC Computer Tech. Co., Ltd." -+ -+static const char *board_mach; -+static const char *board_name; -+static u32 board_rev; -+static u32 board_serial_high, board_serial_low; -+ -+static ssize_t board_sys_info_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ char *s = buf; -+ -+ s += sprintf(s, "Hardware\t: %s\n", board_mach); -+ s += sprintf(s, "Revision\t: %04x\n", board_rev); -+ s += sprintf(s, "Serial\t\t: %08x%08x\n", -+ board_serial_high, board_serial_low); -+ s += sprintf(s, "\nModel\t\t: %s\n", board_name); -+ s += sprintf(s, "Manufacturer\t: %s\n", BOARD_MANF); -+ -+ return (s - buf); -+} -+ -+static struct device_attribute board_attr_info = -+ __ATTR(info, S_IRUGO, board_sys_info_show, NULL); -+ -+static int rockchip_cpuinfo_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct nvmem_cell *cell; -+ unsigned char *efuse_buf, buf[16]; -+ size_t len; -+ int i; -+ -+ cell = nvmem_cell_get(dev, "id"); -+ if (IS_ERR(cell)) { -+ dev_err(dev, "failed to get id cell: %ld\n", PTR_ERR(cell)); -+ return PTR_ERR(cell); -+ } -+ -+ efuse_buf = nvmem_cell_read(cell, &len); -+ nvmem_cell_put(cell); -+ -+ if (len != 16) { -+ kfree(efuse_buf); -+ dev_err(dev, "invalid id len: %zu\n", len); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < 8; i++) { -+ buf[i] = efuse_buf[1 + (i << 1)]; -+ buf[i + 8] = efuse_buf[i << 1]; -+ } -+ -+ kfree(efuse_buf); -+ -+ board_serial_low = crc32(0, buf, 8); -+ board_serial_high = crc32(board_serial_low, buf + 8, 8); -+ -+ dev_info(dev, "Serial\t\t: %08x%08x\n", -+ board_serial_high, board_serial_low); -+ -+ return 0; -+} -+ -+static int board_sys_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *root; -+ -+ root = of_find_node_by_path("/"); -+ -+ of_property_read_u32(np, "hwrev", &board_rev); -+ -+ if (of_property_read_string(np, "machine", &board_mach)) -+ of_property_read_string(root, "compatible", &board_mach); -+ -+ if (of_property_read_string(np, "model", &board_name)) -+ of_property_read_string(root, "model", &board_name); -+ -+ of_node_put(root); -+ -+ rockchip_cpuinfo_probe(pdev); -+ -+ device_create_file(&pdev->dev, &board_attr_info); -+ -+ return 0; -+} -+ -+static const struct of_device_id board_sys_of_match[] = { -+ { .compatible = "friendlyelec,board" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, board_sys_of_match); -+ -+static struct platform_driver board_sys_driver = { -+ .probe = board_sys_probe, -+ .driver = { -+ .name = "friendlyelec-board", -+ .of_match_table = board_sys_of_match, -+ }, -+}; -+ -+static int __init board_sys_init(void) -+{ -+ return platform_driver_register(&board_sys_driver); -+} -+late_initcall(board_sys_init); -+ -+MODULE_AUTHOR("support@friendlyarm.com"); -+MODULE_DESCRIPTION("FriendlyElec NanoPi Series Machine Driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-add-sound-card.patch b/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-add-sound-card.patch deleted file mode 100644 index 6f5c6c6..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-add-sound-card.patch +++ /dev/null @@ -1,106 +0,0 @@ -diff -u a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi 2019-10-17 23:47:33.000000000 +0300 -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi 2019-10-27 22:34:55.988303874 +0300 -@@ -105,6 +105,27 @@ - }; - }; - -+ rt5651-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "realtek,rt5651-codec"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <256>; -+ simple-audio-card,widgets = -+ "Microphone", "Mic Jack", -+ "Headphone", "Headphone Jack"; -+ simple-audio-card,routing = -+ "Mic Jack", "micbias1", -+ "IN1P", "Mic Jack", -+ "Headphone Jack", "HPOL", -+ "Headphone Jack", "HPOR"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s1>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&rt5651>; -+ }; -+ }; -+ - sdio_pwrseq: sdio-pwrseq { - compatible = "mmc-pwrseq-simple"; - clocks = <&rk808 1>; -@@ -184,6 +205,10 @@ - status = "okay"; - }; - -+&hdmi_sound { -+ status = "okay"; -+}; -+ - &i2c0 { - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <160>; -@@ -432,6 +457,16 @@ - i2c-scl-rising-time-ns = <150>; - i2c-scl-falling-time-ns = <30>; - status = "okay"; -+ -+ rt5651: rt5651@1a { -+ compatible = "realtek,rt5651"; -+ reg = <0x1a>; -+ clocks = <&cru SCLK_I2S_8CH_OUT>; -+ clock-names = "mclk"; -+ hp-det-gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; -+ // spk-con-gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; -+ #sound-dai-cells = <0>; -+ }; - }; - - &i2c2 { -@@ -459,6 +494,16 @@ - status = "okay"; - }; - -+&i2s1 { -+ rockchip,playback-channels = <8>; -+ rockchip,capture-channels = <8>; -+ status = "okay"; -+}; -+ -+&i2s2 { -+ status = "okay"; -+}; -+ - &io_domains { - bt656-supply = <&vcc_1v8>; - audio-supply = <&vcca1v8_codec>; -@@ -724,3 +769,9 @@ - &vopl_mmu { - status = "okay"; - }; -+ -+&spdif { -+ i2c-scl-rising-time-ns = <450>; -+ i2c-scl-falling-time-ns = <15>; -+ status = "okay"; -+}; -diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig -index b43657e6e..fb75c425e 100644 ---- a/sound/soc/rockchip/Kconfig -+++ b/sound/soc/rockchip/Kconfig -@@ -53,6 +53,15 @@ config SND_SOC_ROCKCHIP_RT5645 - Say Y or M here if you want to add support for SoC audio on Rockchip - boards using the RT5645/RT5650 codec, such as Veyron. - -+config SND_SOC_ROCKCHIP_RT5651 -+ tristate "ASoC support for Rockchip boards using a RT5651 codec" -+ depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP -+ select SND_SOC_ROCKCHIP_I2S -+ select SND_SOC_RT5651 -+ help -+ Say Y or M here if you want to add support for SoC audio on Rockchip -+ boards using the RT5651 codec, such as FriendlyARM's Nano{Pi,PC} family. -+ - config SND_SOC_RK3288_HDMI_ANALOG - tristate "ASoC support multiple codecs for Rockchip RK3288 boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-ethernet-tweak.patch b/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-ethernet-tweak.patch deleted file mode 100644 index bb2cef9..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-ethernet-tweak.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -index 60358ab8c..057045ca3 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -@@ -48,6 +48,10 @@ - }; - }; - -+&gmac { -+ rx_delay = <0x16>; -+}; -+ - &vcc3v3_sys { - vin-supply = <&vcc5v0_core>; - }; diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-fix-stability-issues.patch b/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-fix-stability-issues.patch deleted file mode 100644 index d666555..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-m4v2-dts-fix-stability-issues.patch +++ /dev/null @@ -1,29 +0,0 @@ -By default rk808's buck regulators switch voltage in multiple 100mV jumps. -This seems to be too much for NanoPi M4V2 and makes it unstable. - -Shortening the steps to 50mV (4 multiple of base buck step which is 12.5mV) -makes the NanoPi M4V2 stable. -Tested with multiple hours of running memtester without a single failure. - -Signed-off-by: Piotr Szczepanik - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -index 2dcaf497c..094440ce3 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4v2.dts -@@ -64,6 +64,10 @@ &gmac { - rx_delay = <0x16>; - }; - -+&rk808 { -+ max-buck-steps-per-change = <4>; -+}; -+ - &vcc3v3_sys { - vin-supply = <&vcc5v0_core>; - }; -@@ -80,3 +84,4 @@ &vbus_typec { - regulator-always-on; - vin-supply = <&vdd_5v>; - }; -+ diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-r2s-r8152-mac-from-dt.patch b/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-r2s-r8152-mac-from-dt.patch deleted file mode 100644 index 4040e88..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-nanopi-r2s-r8152-mac-from-dt.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 27dfe6f4347e883fd618d5a37500c7f6d3652fb9 Mon Sep 17 00:00:00 2001 -From: hmz007 -Date: Fri, 22 Nov 2019 19:03:00 +0800 -Subject: [PATCH] r8152: support to get MAC address from device tree - -Signed-off-by: hmz007 ---- - drivers/net/usb/r8152.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c -index b2507c59ba8b..eb78f6d9390c 100644 ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1298,6 +1299,17 @@ static int determine_ethernet_addr(struct r8152 *tp, struct sockaddr *sa) - if (ret < 0) { - netif_err(tp, probe, dev, "Get ether addr fail\n"); - } else if (!is_valid_ether_addr(sa->sa_data)) { -+ /* try to get MAC address from DT */ -+ if (tp->udev->dev.of_node) { -+ const u8 *mac = of_get_mac_address(tp->udev->dev.of_node); -+ if (!IS_ERR(mac) && is_valid_ether_addr(mac)) { -+ ether_addr_copy(sa->sa_data, mac); -+ netif_info(tp, probe, dev, "DT mac addr %pM\n", -+ sa->sa_data); -+ return 0; -+ } -+ } -+ - netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - sa->sa_data); - eth_hw_addr_random(dev); diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-roc-rk3399-pc-fix-fusb302-compatible.patch b/sys-kernel/decade-sources/files/patches-5.14/board-roc-rk3399-pc-fix-fusb302-compatible.patch deleted file mode 100644 index 5f41dd4..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-roc-rk3399-pc-fix-fusb302-compatible.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -index 9f225e9c3..057c938be 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi -@@ -506,7 +506,7 @@ - status = "okay"; - - fusb1: usb-typec@22 { -- compatible = "fcs,fusb302"; -+ compatible = "fairchild,fusb302"; - reg = <0x22>; - interrupt-parent = <&gpio1>; - interrupts = <1 IRQ_TYPE_LEVEL_LOW>; -@@ -523,7 +523,7 @@ - status = "okay"; - - fusb0: usb-typec@22 { -- compatible = "fcs,fusb302"; -+ compatible = "fairchild,fusb302"; - reg = <0x22>; - interrupt-parent = <&gpio1>; - interrupts = <2 IRQ_TYPE_LEVEL_LOW>; diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch b/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch deleted file mode 100644 index efd39da..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0008-thermal-rockchip-add-tsadc-support-for-rk3308.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 498c9f200325f0397fd03163a98e053430b80aa4 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Fri, 17 Jan 2020 15:58:20 +0100 -Subject: [PATCH 08/23] thermal: rockchip: add tsadc support for rk3308 - -From a231e9c68e5f5e6cf5a82a40828cfd1df4ad1f3e Mon Sep 17 00:00:00 2001 -From: Rocky Hao -Date: Fri, 9 Mar 2018 17:36:39 +0800 -Subject: [PATCH] thermal: rockchip: add tsadc support for rk3308 - -Change-Id: Ibf1782ca471c8ad4b14d6fd64eeb123181903adc -Signed-off-by: Rocky Hao ---- - .../bindings/thermal/rockchip-thermal.yaml | 1 + - drivers/thermal/rockchip_thermal.c | 28 +++++++++++++++++++ - 2 files changed, 29 insertions(+) - -diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml -index c6aac9bcacf1..3a0a9556680e 100644 ---- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml -+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml -@@ -16,6 +16,7 @@ - - rockchip,rv1108-tsadc # RV1108 SoCs - - rockchip,rk3228-tsadc # RK3228 SoCs - - rockchip,rk3288-tsadc # RK3288 SoCs -+ - rockchip,rk3308-tsadc # RK3308 SoCs - - rockchip,rk3328-tsadc # RK3328 SoCs - - rockchip,rk3368-tsadc # RK3368 SoCs - - rockchip,rk3399-tsadc # RK3399 SoCs -diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c -index 343c2f5c5a25..d4d66724535a 100644 ---- a/drivers/thermal/rockchip_thermal.c -+++ b/drivers/thermal/rockchip_thermal.c -@@ -821,6 +821,30 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, - writel_relaxed(val, regs + TSADCV2_INT_EN); - } - -+static const struct rockchip_tsadc_chip rk3308_tsadc_data = { -+ .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ -+ .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ -+ .chn_num = 2, /* 2 channels for tsadc */ -+ -+ .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ -+ .tshut_temp = 95000, -+ -+ .initialize = rk_tsadcv4_initialize, -+ .irq_ack = rk_tsadcv3_irq_ack, -+ .control = rk_tsadcv3_control, -+ .get_temp = rk_tsadcv2_get_temp, -+ .set_alarm_temp = rk_tsadcv2_alarm_temp, -+ .set_tshut_temp = rk_tsadcv2_tshut_temp, -+ .set_tshut_mode = rk_tsadcv2_tshut_mode, -+ -+ .table = { -+ .id = rk3328_code_table, -+ .length = ARRAY_SIZE(rk3328_code_table), -+ .data_mask = TSADCV2_DATA_MASK, -+ .mode = ADC_INCREMENT, -+ }, -+}; -+ - static const struct rockchip_tsadc_chip px30_tsadc_data = { - .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ - .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ -@@ -1032,6 +1056,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = { - .compatible = "rockchip,rk3288-tsadc", - .data = (void *)&rk3288_tsadc_data, - }, -+ { -+ .compatible = "rockchip,rk3308-tsadc", -+ .data = (void *)&rk3308_tsadc_data, -+ }, - { - .compatible = "rockchip,rk3328-tsadc", - .data = (void *)&rk3328_tsadc_data, --- -2.25.1 diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch b/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch deleted file mode 100644 index 8509312..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0016-ASoC-rockchip-add-support-for-rockchip-i2s-tdm-contr.patch +++ /dev/null @@ -1,1083 +0,0 @@ -From e07dd04b6af66325e3dee7a88aa8c6be5a8cb472 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 15:26:23 +0100 -Subject: [PATCH 16/23] ASoC: rockchip: add support for rockchip i2s/tdm - controller - -From 018d1c86c16617eaae1b9fd0d07cc2c70c11006f Mon Sep 17 00:00:00 2001 -From: Sugar Zhang -Date: Sat, 24 Mar 2018 17:01:49 +0800 -Subject: [PATCH] ASoC: rockchip: add support for rockchip i2s/tdm controller - -This patch is add for rockchip i2s/tdm controller. - -Change-Id: I428e311402220ff14441c48e13fa51356ced46e8 -Signed-off-by: Sugar Zhang ---- - .../bindings/sound/rockchip,i2s-tdm.txt | 42 ++ - sound/soc/rockchip/Kconfig | 9 + - sound/soc/rockchip/Makefile | 2 + - sound/soc/rockchip/rockchip_i2s_tdm.c | 700 ++++++++++++++++++ - sound/soc/rockchip/rockchip_i2s_tdm.h | 256 +++++++ - 5 files changed, 1009 insertions(+) - create mode 100644 Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt - create mode 100644 sound/soc/rockchip/rockchip_i2s_tdm.c - create mode 100644 sound/soc/rockchip/rockchip_i2s_tdm.h - -diff --git a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -new file mode 100644 -index 000000000000..e26e72e3315f ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -@@ -0,0 +1,42 @@ -+* Rockchip I2S/TDM controller -+ -+Required properties: -+ -+- compatible: should be one of the following -+ - "rockchip,rk3308-i2s-tdm": for rk3308 -+- reg: physical base address of the controller and length of memory mapped -+ region. -+- interrupts: should contain the I2S interrupt. -+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding, -+ Documentation/devicetree/bindings/dma/dma.txt -+- dma-names: should include "tx" and "rx". -+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. -+- clock-names: clock names. -+- rockchip,bclk-fs: configure the bclk fs. -+ -+Example for rk3308 I2S/TDM controller: -+ -+i2s_8ch_0: i2s@ff300000 { -+ compatible = "rockchip,rk3308-i2s-tdm"; -+ reg = <0x0 0xff300000 0x0 0x1000>; -+ interrupts = ; -+ clocks = <&cru SCLK_I2S0_8CH_TX>, <&cru SCLK_I2S0_8CH_RX>, <&cru HCLK_I2S0_8CH>; -+ clock-names = "mclk_tx", "mclk_rx", "hclk"; -+ dmas = <&dmac1 0>, <&dmac1 1>; -+ dma-names = "tx", "rx"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_8ch_0_sclktx -+ &i2s_8ch_0_sclkrx -+ &i2s_8ch_0_lrcktx -+ &i2s_8ch_0_lrckrx -+ &i2s_8ch_0_sdi0 -+ &i2s_8ch_0_sdi1 -+ &i2s_8ch_0_sdi2 -+ &i2s_8ch_0_sdi3 -+ &i2s_8ch_0_sdo0 -+ &i2s_8ch_0_sdo1 -+ &i2s_8ch_0_sdo2 -+ &i2s_8ch_0_sdo3 -+ &i2s_8ch_0_mclk>; -+ status = "disabled"; -+}; -diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig -index d610b553ea3b..25e26d85c2d1 100644 ---- a/sound/soc/rockchip/Kconfig -+++ b/sound/soc/rockchip/Kconfig -@@ -16,6 +16,15 @@ config SND_SOC_ROCKCHIP_I2S - Rockchip I2S device. The device supports upto maximum of - 8 channels each for play and record. - -+config SND_SOC_ROCKCHIP_I2S_TDM -+ tristate "Rockchip I2S/TDM Device Driver" -+ depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP -+ select SND_SOC_GENERIC_DMAENGINE_PCM -+ help -+ Say Y or M if you want to add support for I2S/TDM driver for -+ Rockchip I2S/TDM device. The device supports up to maximum of -+ 8 channels each for play and record. -+ - config SND_SOC_ROCKCHIP_PDM - tristate "Rockchip PDM Controller Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP -diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile -index 65e814d46006..b10f5e7b136d 100644 ---- a/sound/soc/rockchip/Makefile -+++ b/sound/soc/rockchip/Makefile -@@ -1,11 +1,13 @@ - # SPDX-License-Identifier: GPL-2.0 - # ROCKCHIP Platform Support - snd-soc-rockchip-i2s-objs := rockchip_i2s.o -+snd-soc-rockchip-i2s-tdm-objs := rockchip_i2s_tdm.o - snd-soc-rockchip-pcm-objs := rockchip_pcm.o - snd-soc-rockchip-pdm-objs := rockchip_pdm.o - snd-soc-rockchip-spdif-objs := rockchip_spdif.o - - obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o snd-soc-rockchip-pcm.o -+obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S_TDM) += snd-soc-rockchip-i2s-tdm.o - obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o - obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o - -diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c -new file mode 100644 -index 000000000000..39c1b98f9593 ---- /dev/null -+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c -@@ -0,0 +1,700 @@ -+/* sound/soc/rockchip/rockchip_i2s_tdm.c -+ * -+ * ALSA SoC Audio Layer - Rockchip I2S/TDM Controller driver -+ * -+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd. -+ * Author: Sugar Zhang -+ * -+ * 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 "rockchip_i2s_tdm.h" -+ -+#define DRV_NAME "rockchip-i2s-tdm" -+ -+struct rk_i2s_tdm_dev { -+ struct device *dev; -+ struct clk *hclk; -+ struct clk *mclk_tx; -+ struct clk *mclk_rx; -+ struct regmap *regmap; -+ struct snd_dmaengine_dai_dma_data capture_dma_data; -+ struct snd_dmaengine_dai_dma_data playback_dma_data; -+ -+ bool is_master_mode; -+ unsigned int bclk_fs; -+}; -+ -+static int i2s_tdm_runtime_suspend(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ -+ regcache_cache_only(i2s_tdm->regmap, true); -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_disable_unprepare(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_disable_unprepare(i2s_tdm->mclk_rx); -+ -+ return 0; -+} -+ -+static int i2s_tdm_runtime_resume(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ int ret; -+ -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_prepare_enable(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_prepare_enable(i2s_tdm->mclk_rx); -+ -+ regcache_cache_only(i2s_tdm->regmap, false); -+ regcache_mark_dirty(i2s_tdm->regmap); -+ -+ ret = regcache_sync(i2s_tdm->regmap); -+ if (ret) { -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_disable_unprepare(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_disable_unprepare(i2s_tdm->mclk_rx); -+ } -+ -+ return ret; -+} -+ -+static inline struct rk_i2s_tdm_dev *to_info(struct snd_soc_dai *dai) -+{ -+ return snd_soc_dai_get_drvdata(dai); -+} -+ -+static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) -+{ -+ unsigned int val = 0; -+ int retry = 10; -+ -+ if (on) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START, -+ I2S_XFER_TXS_START); -+ } else { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START, -+ I2S_XFER_TXS_STOP); -+ -+ udelay(150); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, -+ I2S_CLR_TXC, -+ I2S_CLR_TXC); -+ -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ -+ /* Should wait for clear operation to finish */ -+ while (val) { -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ retry--; -+ if (!retry) { -+ dev_warn(i2s_tdm->dev, "fail to clear\n"); -+ break; -+ } -+ } -+ } -+} -+ -+static void rockchip_snd_rxctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) -+{ -+ unsigned int val = 0; -+ int retry = 10; -+ -+ if (on) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_RXS_START, -+ I2S_XFER_RXS_START); -+ } else { -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_RXS_START, -+ I2S_XFER_RXS_STOP); -+ -+ udelay(150); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, -+ I2S_CLR_RXC, -+ I2S_CLR_RXC); -+ -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ -+ /* Should wait for clear operation to finish */ -+ while (val) { -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ retry--; -+ if (!retry) { -+ dev_warn(i2s_tdm->dev, "fail to clear\n"); -+ break; -+ } -+ } -+ } -+} -+ -+static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai, -+ unsigned int fmt) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai); -+ unsigned int mask = 0, val = 0; -+ int ret = 0; -+ -+ pm_runtime_get_sync(cpu_dai->dev); -+ mask = I2S_CKR_MSS_MASK; -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* Set source clock in Master mode */ -+ val = I2S_CKR_MSS_MASTER; -+ i2s_tdm->is_master_mode = true; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ val = I2S_CKR_MSS_SLAVE; -+ i2s_tdm->is_master_mode = false; -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, mask, val); -+ -+ mask = I2S_CKR_CKP_MASK; -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ val = I2S_CKR_CKP_NEG; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ val = I2S_CKR_CKP_POS; -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, mask, val); -+ -+ mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK; -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_RIGHT_J: -+ val = I2S_TXCR_IBM_RSJM; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ val = I2S_TXCR_IBM_LSJM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ val = I2S_TXCR_IBM_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ -+ val = I2S_TXCR_TFS_PCM; -+ break; -+ case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ -+ val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1); -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, mask, val); -+ -+ mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK; -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_RIGHT_J: -+ val = I2S_RXCR_IBM_RSJM; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ val = I2S_RXCR_IBM_LSJM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ val = I2S_RXCR_IBM_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ -+ val = I2S_RXCR_TFS_PCM; -+ break; -+ case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ -+ val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1); -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val); -+ -+err_pm_put: -+ pm_runtime_put(cpu_dai->dev); -+ -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct clk *mclk; -+ unsigned int val = 0; -+ unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ mclk = i2s_tdm->mclk_tx; -+ else -+ mclk = i2s_tdm->mclk_rx; -+ -+ if (i2s_tdm->is_master_mode) { -+ mclk_rate = clk_get_rate(mclk); -+ bclk_rate = i2s_tdm->bclk_fs * params_rate(params); -+ if (!bclk_rate) -+ return -EINVAL; -+ -+ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); -+ div_lrck = bclk_rate / params_rate(params); -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, -+ I2S_CLKDIV_TXM_MASK, -+ I2S_CLKDIV_TXM(div_bclk)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_TSD_MASK, -+ I2S_CKR_TSD(div_lrck)); -+ } else { -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, -+ I2S_CLKDIV_RXM_MASK, -+ I2S_CLKDIV_RXM(div_bclk)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_RSD_MASK, -+ I2S_CKR_RSD(div_lrck)); -+ } -+ } -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S8: -+ val |= I2S_TXCR_VDW(8); -+ break; -+ case SNDRV_PCM_FORMAT_S16_LE: -+ val |= I2S_TXCR_VDW(16); -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ val |= I2S_TXCR_VDW(20); -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ val |= I2S_TXCR_VDW(24); -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ val |= I2S_TXCR_VDW(32); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 8: -+ val |= I2S_CHN_8; -+ break; -+ case 6: -+ val |= I2S_CHN_6; -+ break; -+ case 4: -+ val |= I2S_CHN_4; -+ break; -+ case 2: -+ val |= I2S_CHN_2; -+ break; -+ default: -+ dev_err(i2s_tdm->dev, "invalid channel: %d\n", -+ params_channels(params)); -+ return -EINVAL; -+ } -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, -+ I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK, -+ val); -+ else -+ regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, -+ I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK, -+ val); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, -+ I2S_DMACR_TDL(16)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, -+ I2S_DMACR_RDL(16)); -+ -+ val = I2S_CKR_TRCM_TXRX; -+ if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates) -+ val = I2S_CKR_TRCM_TXONLY; -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_TRCM_MASK, -+ val); -+ return 0; -+} -+ -+static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, -+ int cmd, struct snd_soc_dai *dai) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); -+ int ret = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ rockchip_snd_rxctrl(i2s_tdm, 1); -+ else -+ rockchip_snd_txctrl(i2s_tdm, 1); -+ break; -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ rockchip_snd_rxctrl(i2s_tdm, 0); -+ else -+ rockchip_snd_txctrl(i2s_tdm, 0); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, -+ unsigned int freq, int dir) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai); -+ int ret; -+ -+ ret = clk_set_rate(i2s_tdm->mclk_tx, freq); -+ if (ret) -+ dev_err(i2s_tdm->dev, "Fail to set mclk_tx %d\n", ret); -+ -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ ret = clk_set_rate(i2s_tdm->mclk_rx, freq); -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); -+ -+ dai->capture_dma_data = &i2s_tdm->capture_dma_data; -+ dai->playback_dma_data = &i2s_tdm->playback_dma_data; -+ -+ return 0; -+} -+ -+static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { -+ .hw_params = rockchip_i2s_tdm_hw_params, -+ .set_sysclk = rockchip_i2s_tdm_set_sysclk, -+ .set_fmt = rockchip_i2s_tdm_set_fmt, -+ .trigger = rockchip_i2s_tdm_trigger, -+}; -+ -+static struct snd_soc_dai_driver rockchip_i2s_tdm_dai = { -+ .probe = rockchip_i2s_tdm_dai_probe, -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "Capture", -+ .channels_min = 2, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rockchip_i2s_tdm_dai_ops, -+ .symmetric_rates = 1, -+}; -+ -+static const struct snd_soc_component_driver rockchip_i2s_tdm_component = { -+ .name = DRV_NAME, -+}; -+ -+static bool rockchip_i2s_tdm_wr_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_TXCR: -+ case I2S_RXCR: -+ case I2S_CKR: -+ case I2S_DMACR: -+ case I2S_INTCR: -+ case I2S_XFER: -+ case I2S_CLR: -+ case I2S_TXDR: -+ case I2S_TDM_TXCR: -+ case I2S_TDM_RXCR: -+ case I2S_CLKDIV: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_TXCR: -+ case I2S_RXCR: -+ case I2S_CKR: -+ case I2S_DMACR: -+ case I2S_INTCR: -+ case I2S_XFER: -+ case I2S_CLR: -+ case I2S_RXDR: -+ case I2S_FIFOLR: -+ case I2S_INTSR: -+ case I2S_TDM_TXCR: -+ case I2S_TDM_RXCR: -+ case I2S_CLKDIV: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_INTSR: -+ case I2S_CLR: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool rockchip_i2s_tdm_precious_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ default: -+ return false; -+ } -+} -+ -+static const struct reg_default rockchip_i2s_tdm_reg_defaults[] = { -+ {0x00, 0x7200000f}, -+ {0x04, 0x01c8000f}, -+ {0x08, 0x00001f1f}, -+ {0x10, 0x001f0000}, -+ {0x14, 0x01f00000}, -+ {0x30, 0x00003eff}, -+ {0x34, 0x00003eff}, -+ {0x38, 0x00000707}, -+}; -+ -+static const struct regmap_config rockchip_i2s_tdm_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = I2S_CLKDIV, -+ .reg_defaults = rockchip_i2s_tdm_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(rockchip_i2s_tdm_reg_defaults), -+ .writeable_reg = rockchip_i2s_tdm_wr_reg, -+ .readable_reg = rockchip_i2s_tdm_rd_reg, -+ .volatile_reg = rockchip_i2s_tdm_volatile_reg, -+ .precious_reg = rockchip_i2s_tdm_precious_reg, -+ .cache_type = REGCACHE_FLAT, -+}; -+ -+static const struct of_device_id rockchip_i2s_tdm_match[] = { -+ { .compatible = "rockchip,rk3308-i2s-tdm", }, -+ {}, -+}; -+ -+static int rockchip_i2s_tdm_probe(struct platform_device *pdev) -+{ -+ struct device_node *node = pdev->dev.of_node; -+ struct rk_i2s_tdm_dev *i2s_tdm; -+ struct resource *res; -+ void __iomem *regs; -+ int ret; -+ int val; -+ -+ i2s_tdm = devm_kzalloc(&pdev->dev, sizeof(*i2s_tdm), GFP_KERNEL); -+ if (!i2s_tdm) -+ return -ENOMEM; -+ -+ i2s_tdm->dev = &pdev->dev; -+ -+ i2s_tdm->hclk = devm_clk_get(&pdev->dev, "hclk"); -+ if (IS_ERR(i2s_tdm->hclk)) -+ return PTR_ERR(i2s_tdm->hclk); -+ -+ ret = clk_prepare_enable(i2s_tdm->hclk); -+ if (ret) -+ return ret; -+ -+ i2s_tdm->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx"); -+ if (IS_ERR(i2s_tdm->mclk_tx)) -+ return PTR_ERR(i2s_tdm->mclk_tx); -+ -+ i2s_tdm->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx"); -+ if (IS_ERR(i2s_tdm->mclk_rx)) -+ return PTR_ERR(i2s_tdm->mclk_rx); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(regs)) -+ return PTR_ERR(regs); -+ -+ i2s_tdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs, -+ &rockchip_i2s_tdm_regmap_config); -+ if (IS_ERR(i2s_tdm->regmap)) -+ return PTR_ERR(i2s_tdm->regmap); -+ -+ i2s_tdm->playback_dma_data.addr = res->start + I2S_TXDR; -+ i2s_tdm->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ i2s_tdm->playback_dma_data.maxburst = 8; -+ -+ i2s_tdm->capture_dma_data.addr = res->start + I2S_RXDR; -+ i2s_tdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ i2s_tdm->capture_dma_data.maxburst = 8; -+ -+ dev_set_drvdata(&pdev->dev, i2s_tdm); -+ -+ pm_runtime_enable(&pdev->dev); -+ if (!pm_runtime_enabled(&pdev->dev)) { -+ ret = i2s_tdm_runtime_resume(&pdev->dev); -+ if (ret) -+ goto err_pm_disable; -+ } -+ -+ i2s_tdm->bclk_fs = 64; -+ if (!of_property_read_u32(node, "rockchip,bclk-fs", &val)) { -+ if ((val >= 32) && (val % 2 == 0)) -+ i2s_tdm->bclk_fs = val; -+ } -+ -+ ret = devm_snd_soc_register_component(&pdev->dev, -+ &rockchip_i2s_tdm_component, -+ &rockchip_i2s_tdm_dai, 1); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register DAI\n"); -+ goto err_suspend; -+ } -+ -+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register PCM\n"); -+ return ret; -+ } -+ -+ return 0; -+ -+err_suspend: -+ if (!pm_runtime_status_suspended(&pdev->dev)) -+ i2s_tdm_runtime_suspend(&pdev->dev); -+err_pm_disable: -+ pm_runtime_disable(&pdev->dev); -+ -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_remove(struct platform_device *pdev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(&pdev->dev); -+ -+ pm_runtime_disable(&pdev->dev); -+ if (!pm_runtime_status_suspended(&pdev->dev)) -+ i2s_tdm_runtime_suspend(&pdev->dev); -+ -+ if (!IS_ERR(i2s_tdm->mclk_tx)) -+ clk_prepare_enable(i2s_tdm->mclk_tx); -+ if (!IS_ERR(i2s_tdm->mclk_rx)) -+ clk_prepare_enable(i2s_tdm->mclk_rx); -+ if (!IS_ERR(i2s_tdm->hclk)) -+ clk_disable_unprepare(i2s_tdm->hclk); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int rockchip_i2s_tdm_suspend(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ -+ regcache_mark_dirty(i2s_tdm->regmap); -+ -+ return 0; -+} -+ -+static int rockchip_i2s_tdm_resume(struct device *dev) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ ret = regcache_sync(i2s_tdm->regmap); -+ pm_runtime_put(dev); -+ -+ return ret; -+} -+#endif -+ -+static const struct dev_pm_ops rockchip_i2s_tdm_pm_ops = { -+ SET_RUNTIME_PM_OPS(i2s_tdm_runtime_suspend, i2s_tdm_runtime_resume, -+ NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_tdm_suspend, -+ rockchip_i2s_tdm_resume) -+}; -+ -+static struct platform_driver rockchip_i2s_tdm_driver = { -+ .probe = rockchip_i2s_tdm_probe, -+ .remove = rockchip_i2s_tdm_remove, -+ .driver = { -+ .name = DRV_NAME, -+ .of_match_table = of_match_ptr(rockchip_i2s_tdm_match), -+ .pm = &rockchip_i2s_tdm_pm_ops, -+ }, -+}; -+module_platform_driver(rockchip_i2s_tdm_driver); -+ -+MODULE_DESCRIPTION("ROCKCHIP I2S/TDM ASoC Interface"); -+MODULE_AUTHOR("Sugar Zhang "); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:" DRV_NAME); -+MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match); -diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.h b/sound/soc/rockchip/rockchip_i2s_tdm.h -new file mode 100644 -index 000000000000..1a28523cfd82 ---- /dev/null -+++ b/sound/soc/rockchip/rockchip_i2s_tdm.h -@@ -0,0 +1,256 @@ -+/* -+ * sound/soc/rockchip/rockchip_i2s_tdm.h -+ * -+ * ALSA SoC Audio Layer - Rockchip I2S_TDM Controller driver -+ * -+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd. -+ * Author: Sugar Zhang -+ * -+ * 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 _ROCKCHIP_I2S_TDM_H -+#define _ROCKCHIP_I2S_TDM_H -+ -+/* -+ * TXCR -+ * transmit operation control register -+ */ -+#define I2S_TXCR_RCNT_SHIFT 17 -+#define I2S_TXCR_RCNT_MASK (0x3f << I2S_TXCR_RCNT_SHIFT) -+#define I2S_TXCR_CSR_SHIFT 15 -+#define I2S_TXCR_CSR(x) (x << I2S_TXCR_CSR_SHIFT) -+#define I2S_TXCR_CSR_MASK (3 << I2S_TXCR_CSR_SHIFT) -+#define I2S_TXCR_HWT BIT(14) -+#define I2S_TXCR_SJM_SHIFT 12 -+#define I2S_TXCR_SJM_R (0 << I2S_TXCR_SJM_SHIFT) -+#define I2S_TXCR_SJM_L (1 << I2S_TXCR_SJM_SHIFT) -+#define I2S_TXCR_FBM_SHIFT 11 -+#define I2S_TXCR_FBM_MSB (0 << I2S_TXCR_FBM_SHIFT) -+#define I2S_TXCR_FBM_LSB (1 << I2S_TXCR_FBM_SHIFT) -+#define I2S_TXCR_IBM_SHIFT 9 -+#define I2S_TXCR_IBM_NORMAL (0 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_IBM_LSJM (1 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_IBM_RSJM (2 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_IBM_MASK (3 << I2S_TXCR_IBM_SHIFT) -+#define I2S_TXCR_PBM_SHIFT 7 -+#define I2S_TXCR_PBM_MODE(x) (x << I2S_TXCR_PBM_SHIFT) -+#define I2S_TXCR_PBM_MASK (3 << I2S_TXCR_PBM_SHIFT) -+#define I2S_TXCR_TFS_SHIFT 5 -+#define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_MASK (1 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_VDW_SHIFT 0 -+#define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) -+#define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) -+ -+/* -+ * RXCR -+ * receive operation control register -+ */ -+#define I2S_RXCR_CSR_SHIFT 15 -+#define I2S_RXCR_CSR(x) (x << I2S_RXCR_CSR_SHIFT) -+#define I2S_RXCR_CSR_MASK (3 << I2S_RXCR_CSR_SHIFT) -+#define I2S_RXCR_HWT BIT(14) -+#define I2S_RXCR_SJM_SHIFT 12 -+#define I2S_RXCR_SJM_R (0 << I2S_RXCR_SJM_SHIFT) -+#define I2S_RXCR_SJM_L (1 << I2S_RXCR_SJM_SHIFT) -+#define I2S_RXCR_FBM_SHIFT 11 -+#define I2S_RXCR_FBM_MSB (0 << I2S_RXCR_FBM_SHIFT) -+#define I2S_RXCR_FBM_LSB (1 << I2S_RXCR_FBM_SHIFT) -+#define I2S_RXCR_IBM_SHIFT 9 -+#define I2S_RXCR_IBM_NORMAL (0 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_IBM_LSJM (1 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_IBM_RSJM (2 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_IBM_MASK (3 << I2S_RXCR_IBM_SHIFT) -+#define I2S_RXCR_PBM_SHIFT 7 -+#define I2S_RXCR_PBM_MODE(x) (x << I2S_RXCR_PBM_SHIFT) -+#define I2S_RXCR_PBM_MASK (3 << I2S_RXCR_PBM_SHIFT) -+#define I2S_RXCR_TFS_SHIFT 5 -+#define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_MASK (1 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_VDW_SHIFT 0 -+#define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) -+#define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) -+ -+/* -+ * CKR -+ * clock generation register -+ */ -+#define I2S_CKR_TRCM_SHIFT 28 -+#define I2S_CKR_TRCM(x) (x << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_TXRX (0 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_TXONLY (1 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_RXONLY (2 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_TRCM_MASK (3 << I2S_CKR_TRCM_SHIFT) -+#define I2S_CKR_MSS_SHIFT 27 -+#define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT) -+#define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT) -+#define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT) -+#define I2S_CKR_CKP_SHIFT 26 -+#define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) -+#define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) -+#define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT) -+#define I2S_CKR_RLP_SHIFT 25 -+#define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) -+#define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) -+#define I2S_CKR_TLP_SHIFT 24 -+#define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT) -+#define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT) -+#define I2S_CKR_MDIV_SHIFT 16 -+#define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT) -+#define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT) -+#define I2S_CKR_RSD_SHIFT 8 -+#define I2S_CKR_RSD(x) ((x - 1) << I2S_CKR_RSD_SHIFT) -+#define I2S_CKR_RSD_MASK (0xff << I2S_CKR_RSD_SHIFT) -+#define I2S_CKR_TSD_SHIFT 0 -+#define I2S_CKR_TSD(x) ((x - 1) << I2S_CKR_TSD_SHIFT) -+#define I2S_CKR_TSD_MASK (0xff << I2S_CKR_TSD_SHIFT) -+ -+/* -+ * FIFOLR -+ * FIFO level register -+ */ -+#define I2S_FIFOLR_RFL_SHIFT 24 -+#define I2S_FIFOLR_RFL_MASK (0x3f << I2S_FIFOLR_RFL_SHIFT) -+#define I2S_FIFOLR_TFL3_SHIFT 18 -+#define I2S_FIFOLR_TFL3_MASK (0x3f << I2S_FIFOLR_TFL3_SHIFT) -+#define I2S_FIFOLR_TFL2_SHIFT 12 -+#define I2S_FIFOLR_TFL2_MASK (0x3f << I2S_FIFOLR_TFL2_SHIFT) -+#define I2S_FIFOLR_TFL1_SHIFT 6 -+#define I2S_FIFOLR_TFL1_MASK (0x3f << I2S_FIFOLR_TFL1_SHIFT) -+#define I2S_FIFOLR_TFL0_SHIFT 0 -+#define I2S_FIFOLR_TFL0_MASK (0x3f << I2S_FIFOLR_TFL0_SHIFT) -+ -+/* -+ * DMACR -+ * DMA control register -+ */ -+#define I2S_DMACR_RDE_SHIFT 24 -+#define I2S_DMACR_RDE_DISABLE (0 << I2S_DMACR_RDE_SHIFT) -+#define I2S_DMACR_RDE_ENABLE (1 << I2S_DMACR_RDE_SHIFT) -+#define I2S_DMACR_RDL_SHIFT 16 -+#define I2S_DMACR_RDL(x) ((x - 1) << I2S_DMACR_RDL_SHIFT) -+#define I2S_DMACR_RDL_MASK (0x1f << I2S_DMACR_RDL_SHIFT) -+#define I2S_DMACR_TDE_SHIFT 8 -+#define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT) -+#define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT) -+#define I2S_DMACR_TDL_SHIFT 0 -+#define I2S_DMACR_TDL(x) ((x) << I2S_DMACR_TDL_SHIFT) -+#define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT) -+ -+/* -+ * INTCR -+ * interrupt control register -+ */ -+#define I2S_INTCR_RFT_SHIFT 20 -+#define I2S_INTCR_RFT(x) ((x - 1) << I2S_INTCR_RFT_SHIFT) -+#define I2S_INTCR_RXOIC BIT(18) -+#define I2S_INTCR_RXOIE_SHIFT 17 -+#define I2S_INTCR_RXOIE_DISABLE (0 << I2S_INTCR_RXOIE_SHIFT) -+#define I2S_INTCR_RXOIE_ENABLE (1 << I2S_INTCR_RXOIE_SHIFT) -+#define I2S_INTCR_RXFIE_SHIFT 16 -+#define I2S_INTCR_RXFIE_DISABLE (0 << I2S_INTCR_RXFIE_SHIFT) -+#define I2S_INTCR_RXFIE_ENABLE (1 << I2S_INTCR_RXFIE_SHIFT) -+#define I2S_INTCR_TFT_SHIFT 4 -+#define I2S_INTCR_TFT(x) ((x - 1) << I2S_INTCR_TFT_SHIFT) -+#define I2S_INTCR_TFT_MASK (0x1f << I2S_INTCR_TFT_SHIFT) -+#define I2S_INTCR_TXUIC BIT(2) -+#define I2S_INTCR_TXUIE_SHIFT 1 -+#define I2S_INTCR_TXUIE_DISABLE (0 << I2S_INTCR_TXUIE_SHIFT) -+#define I2S_INTCR_TXUIE_ENABLE (1 << I2S_INTCR_TXUIE_SHIFT) -+ -+/* -+ * INTSR -+ * interrupt status register -+ */ -+#define I2S_INTSR_TXEIE_SHIFT 0 -+#define I2S_INTSR_TXEIE_DISABLE (0 << I2S_INTSR_TXEIE_SHIFT) -+#define I2S_INTSR_TXEIE_ENABLE (1 << I2S_INTSR_TXEIE_SHIFT) -+#define I2S_INTSR_RXOI_SHIFT 17 -+#define I2S_INTSR_RXOI_INA (0 << I2S_INTSR_RXOI_SHIFT) -+#define I2S_INTSR_RXOI_ACT (1 << I2S_INTSR_RXOI_SHIFT) -+#define I2S_INTSR_RXFI_SHIFT 16 -+#define I2S_INTSR_RXFI_INA (0 << I2S_INTSR_RXFI_SHIFT) -+#define I2S_INTSR_RXFI_ACT (1 << I2S_INTSR_RXFI_SHIFT) -+#define I2S_INTSR_TXUI_SHIFT 1 -+#define I2S_INTSR_TXUI_INA (0 << I2S_INTSR_TXUI_SHIFT) -+#define I2S_INTSR_TXUI_ACT (1 << I2S_INTSR_TXUI_SHIFT) -+#define I2S_INTSR_TXEI_SHIFT 0 -+#define I2S_INTSR_TXEI_INA (0 << I2S_INTSR_TXEI_SHIFT) -+#define I2S_INTSR_TXEI_ACT (1 << I2S_INTSR_TXEI_SHIFT) -+ -+/* -+ * XFER -+ * Transfer start register -+ */ -+#define I2S_XFER_RXS_SHIFT 1 -+#define I2S_XFER_RXS_STOP (0 << I2S_XFER_RXS_SHIFT) -+#define I2S_XFER_RXS_START (1 << I2S_XFER_RXS_SHIFT) -+#define I2S_XFER_TXS_SHIFT 0 -+#define I2S_XFER_TXS_STOP (0 << I2S_XFER_TXS_SHIFT) -+#define I2S_XFER_TXS_START (1 << I2S_XFER_TXS_SHIFT) -+ -+/* -+ * CLR -+ * clear SCLK domain logic register -+ */ -+#define I2S_CLR_RXC BIT(1) -+#define I2S_CLR_TXC BIT(0) -+ -+/* -+ * TXDR -+ * Transimt FIFO data register, write only. -+ */ -+#define I2S_TXDR_MASK (0xff) -+ -+/* -+ * RXDR -+ * Receive FIFO data register, write only. -+ */ -+#define I2S_RXDR_MASK (0xff) -+ -+/* -+ * CLKDIV -+ * Mclk div register -+ */ -+#define I2S_CLKDIV_TXM_SHIFT 0 -+#define I2S_CLKDIV_TXM(x) ((x - 1) << I2S_CLKDIV_TXM_SHIFT) -+#define I2S_CLKDIV_TXM_MASK (0xff << I2S_CLKDIV_TXM_SHIFT) -+#define I2S_CLKDIV_RXM_SHIFT 8 -+#define I2S_CLKDIV_RXM(x) ((x - 1) << I2S_CLKDIV_RXM_SHIFT) -+#define I2S_CLKDIV_RXM_MASK (0xff << I2S_CLKDIV_RXM_SHIFT) -+ -+/* Clock divider id */ -+enum { -+ ROCKCHIP_DIV_MCLK = 0, -+ ROCKCHIP_DIV_BCLK, -+}; -+ -+/* channel select */ -+#define I2S_CSR_SHIFT 15 -+#define I2S_CHN_2 (0 << I2S_CSR_SHIFT) -+#define I2S_CHN_4 (1 << I2S_CSR_SHIFT) -+#define I2S_CHN_6 (2 << I2S_CSR_SHIFT) -+#define I2S_CHN_8 (3 << I2S_CSR_SHIFT) -+ -+/* I2S REGS */ -+#define I2S_TXCR (0x0000) -+#define I2S_RXCR (0x0004) -+#define I2S_CKR (0x0008) -+#define I2S_FIFOLR (0x000c) -+#define I2S_DMACR (0x0010) -+#define I2S_INTCR (0x0014) -+#define I2S_INTSR (0x0018) -+#define I2S_XFER (0x001c) -+#define I2S_CLR (0x0020) -+#define I2S_TXDR (0x0024) -+#define I2S_RXDR (0x0028) -+#define I2S_TDM_TXCR (0x0030) -+#define I2S_TDM_RXCR (0x0034) -+#define I2S_CLKDIV (0x0038) -+ -+#endif /* _ROCKCHIP_I2S_TDM_H */ --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0017-WIP-Sync-rockchip_i2s_tdm-to-BSP-tree.patch b/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0017-WIP-Sync-rockchip_i2s_tdm-to-BSP-tree.patch deleted file mode 100644 index 6f9fea8..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0017-WIP-Sync-rockchip_i2s_tdm-to-BSP-tree.patch +++ /dev/null @@ -1,1981 +0,0 @@ -From 7d997d4fe8ee4756f63ea6188f091759bca01b20 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 16:31:07 +0100 -Subject: [PATCH 17/23] [WIP] Sync `rockchip_i2s_tdm` to BSP tree - ---- - .../bindings/sound/rockchip,i2s-tdm.txt | 50 + - sound/soc/rockchip/rockchip_i2s.c | 167 ++- - sound/soc/rockchip/rockchip_i2s_tdm.c | 1136 ++++++++++++++++- - sound/soc/rockchip/rockchip_i2s_tdm.h | 138 +- - 4 files changed, 1379 insertions(+), 112 deletions(-) - -diff --git a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -index e26e72e3315f..db130be87d47 100644 ---- a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -+++ b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.txt -@@ -3,6 +3,8 @@ - Required properties: - - - compatible: should be one of the following -+ - "rockchip,px30-i2s-tdm": for px30 -+ - "rockchip,rk1808-i2s-tdm": for rk1808 - - "rockchip,rk3308-i2s-tdm": for rk3308 - - reg: physical base address of the controller and length of memory mapped - region. -@@ -13,6 +15,50 @@ Required properties: - - clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. - - clock-names: clock names. - - rockchip,bclk-fs: configure the bclk fs. -+- resets: a list of phandle + reset-specifer paris, one for each entry in reset-names. -+- reset-names: reset names, should include "tx-m", "rx-m". -+- rockchip,cru: cru phandle. -+- rockchip,grf: the phandle of the syscon node for GRF register. -+- rockchip,mclk-calibrate: enable mclk source calibration. -+- rockchip,clk-trcm: tx and rx lrck/bclk common use. -+ - 0: both tx_lrck/bclk and rx_lrck/bclk are used -+ - 1: only tx_lrck/bclk is used -+ - 2: only rx_lrck/bclk is used -+- rockchip,no-dmaengine: This is a boolean property. If present, driver will do not -+ register pcm dmaengine, only just register dai. if the dai is part of multi-dais, -+ the property should be present. Please refer to rockchip,multidais.txt about -+ multi-dais usage. -+ -+Optional properties: -+- rockchip,i2s-rx-route: This is a variable length array, that shows the mapping -+ route of i2s rx sdis to I2S data bus. By default, they are one-to-one mapping: -+ * sdi_0 <-- data_0 -+ * sdi_1 <-- data_1 -+ * sdi_2 <-- data_2 -+ * sdi_3 <-- data_3 -+ If you would like to change the order of I2S RX data, the route mapping may -+ like this: -+ * sdi_3 <-- data_0 -+ * sdi_1 <-- data_1 -+ * sdi_2 <-- data_2 -+ * sdi_0 <-- data_3 -+ You need to add the property for i2s node on dts: -+ - rockchip,i2s-rx-route = <3 1 2 0>; -+ -+- rockchip,i2s-tx-route: This is a variable length array, that shows the mapping -+ route of i2s tx sdos to I2S data bus. By default, they are one-to-one mapping: -+ * sdo_0 --> data_0 -+ * sdo_1 --> data_1 -+ * sdo_2 --> data_2 -+ * sdo_3 --> data_3 -+ If you would like to change the order of I2S TX data, the route mapping may -+ like this: -+ * sdo_2 --> data_0 -+ * sdo_1 --> data_1 -+ * sdo_0 --> data_2 -+ * sdo_3 --> data_3 -+ You need to add the property for i2s node on dts: -+ - rockchip,i2s-tx-route = <2 1 0 3>; - - Example for rk3308 I2S/TDM controller: - -@@ -24,6 +70,10 @@ i2s_8ch_0: i2s@ff300000 { - clock-names = "mclk_tx", "mclk_rx", "hclk"; - dmas = <&dmac1 0>, <&dmac1 1>; - dma-names = "tx", "rx"; -+ resets = <&cru SRST_I2S0_8CH_TX_M>, <&cru SRST_I2S0_8CH_RX_M>; -+ reset-names = "tx-m", "rx-m"; -+ rockchip,cru = <&cru>; -+ rockchip,clk-trcm = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s_8ch_0_sclktx - &i2s_8ch_0_sclkrx -diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c -index 61c984f10d8e..e6125ebfe5a9 100644 ---- a/sound/soc/rockchip/rockchip_i2s.c -+++ b/sound/soc/rockchip/rockchip_i2s.c -@@ -1,4 +1,3 @@ --// SPDX-License-Identifier: GPL-2.0-only - /* sound/soc/rockchip/rockchip_i2s.c - * - * ALSA SoC Audio Layer - Rockchip I2S Controller driver -@@ -15,11 +14,12 @@ - #include - #include - #include -+#include -+#include - #include - #include - - #include "rockchip_i2s.h" --#include "rockchip_pcm.h" - - #define DRV_NAME "rockchip-i2s" - -@@ -39,6 +39,8 @@ struct rk_i2s_dev { - - struct regmap *regmap; - struct regmap *grf; -+ struct reset_control *reset_m; -+ struct reset_control *reset_h; - - /* - * Used to indicate the tx/rx status. -@@ -49,8 +51,13 @@ struct rk_i2s_dev { - bool rx_start; - bool is_master_mode; - const struct rk_i2s_pins *pins; -+ unsigned int bclk_fs; -+ unsigned int clk_trcm; - }; - -+/* txctrl/rxctrl lock */ -+static DEFINE_SPINLOCK(lock); -+ - static int i2s_runtime_suspend(struct device *dev) - { - struct rk_i2s_dev *i2s = dev_get_drvdata(dev); -@@ -87,11 +94,27 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) - return snd_soc_dai_get_drvdata(dai); - } - -+static void rockchip_i2s_reset(struct rk_i2s_dev *i2s) -+{ -+ if (!IS_ERR(i2s->reset_m)) -+ reset_control_assert(i2s->reset_m); -+ if (!IS_ERR(i2s->reset_h)) -+ reset_control_assert(i2s->reset_h); -+ udelay(1); -+ if (!IS_ERR(i2s->reset_m)) -+ reset_control_deassert(i2s->reset_m); -+ if (!IS_ERR(i2s->reset_h)) -+ reset_control_deassert(i2s->reset_h); -+ regcache_mark_dirty(i2s->regmap); -+ regcache_sync(i2s->regmap); -+} -+ - static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) - { - unsigned int val = 0; - int retry = 10; - -+ spin_lock(&lock); - if (on) { - regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); -@@ -126,12 +149,14 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) - regmap_read(i2s->regmap, I2S_CLR, &val); - retry--; - if (!retry) { -- dev_warn(i2s->dev, "fail to clear\n"); -+ dev_warn(i2s->dev, "reset\n"); -+ rockchip_i2s_reset(i2s); - break; - } - } - } - } -+ spin_unlock(&lock); - } - - static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) -@@ -139,6 +164,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) - unsigned int val = 0; - int retry = 10; - -+ spin_lock(&lock); - if (on) { - regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); -@@ -173,12 +199,14 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) - regmap_read(i2s->regmap, I2S_CLR, &val); - retry--; - if (!retry) { -- dev_warn(i2s->dev, "fail to clear\n"); -+ dev_warn(i2s->dev, "reset\n"); -+ rockchip_i2s_reset(i2s); - break; - } - } - } - } -+ spin_unlock(&lock); - } - - static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, -@@ -272,17 +309,16 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - { - struct rk_i2s_dev *i2s = to_info(dai); -- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - unsigned int val = 0; - unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; - - if (i2s->is_master_mode) { - mclk_rate = clk_get_rate(i2s->mclk); -- bclk_rate = 2 * 32 * params_rate(params); -- if (bclk_rate == 0 || mclk_rate % bclk_rate) -+ bclk_rate = i2s->bclk_fs * params_rate(params); -+ if (!bclk_rate) - return -EINVAL; - -- div_bclk = mclk_rate / bclk_rate; -+ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - div_lrck = bclk_rate / params_rate(params); - regmap_update_bits(i2s->regmap, I2S_CKR, - I2S_CKR_MDIV_MASK, -@@ -408,13 +408,6 @@ - regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, - I2S_DMACR_RDL(16)); - -- val = I2S_CKR_TRCM_TXRX; -- if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate) -- val = I2S_CKR_TRCM_TXONLY; -- -- regmap_update_bits(i2s->regmap, I2S_CKR, -- I2S_CKR_TRCM_MASK, -- val); - return 0; - } - -@@ -419,9 +448,6 @@ static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, - struct rk_i2s_dev *i2s = to_info(cpu_dai); - int ret; - -- if (freq == 0) -- return 0; -- - ret = clk_set_rate(i2s->mclk, freq); - if (ret) - dev_err(i2s->dev, "Fail to set mclk %d\n", ret); -@@ -504,7 +497,6 @@ - SNDRV_PCM_FMTBIT_S32_LE), - }, - .ops = &rockchip_i2s_dai_ops, -- .symmetric_rate = 1, - }; - - static const struct snd_soc_component_driver rockchip_i2s_component = { -@@ -567,9 +592,16 @@ static const struct rk_i2s_pins rk3399_i2s_pins = { - }; - - static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { -+ { .compatible = "rockchip,px30-i2s", }, -+ { .compatible = "rockchip,rk1808-i2s", }, -+ { .compatible = "rockchip,rk3036-i2s", }, - { .compatible = "rockchip,rk3066-i2s", }, -+ { .compatible = "rockchip,rk3128-i2s", }, - { .compatible = "rockchip,rk3188-i2s", }, - { .compatible = "rockchip,rk3288-i2s", }, -+ { .compatible = "rockchip,rk3308-i2s", }, -+ { .compatible = "rockchip,rk3328-i2s", }, -+ { .compatible = "rockchip,rk3368-i2s", }, - { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins }, - {}, - }; -@@ -586,8 +618,10 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - int val; - - i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); -- if (!i2s) -+ if (!i2s) { -+ dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n"); - return -ENOMEM; -+ } - - i2s->dev = &pdev->dev; - -@@ -600,6 +634,9 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - i2s->pins = of_id->data; - } - -+ i2s->reset_m = devm_reset_control_get(&pdev->dev, "reset-m"); -+ i2s->reset_h = devm_reset_control_get(&pdev->dev, "reset-h"); -+ - /* try to prepare related clocks */ - i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); - if (IS_ERR(i2s->hclk)) { -@@ -633,11 +670,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - - i2s->playback_dma_data.addr = res->start + I2S_TXDR; - i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -- i2s->playback_dma_data.maxburst = 4; -+ i2s->playback_dma_data.maxburst = 8; - - i2s->capture_dma_data.addr = res->start + I2S_RXDR; - i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -- i2s->capture_dma_data.maxburst = 4; -+ i2s->capture_dma_data.maxburst = 8; - - dev_set_drvdata(&pdev->dev, i2s); - -@@ -648,13 +685,12 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - goto err_pm_disable; - } - -- soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, -+ soc_dai = devm_kzalloc(&pdev->dev, - sizeof(*soc_dai), GFP_KERNEL); -- if (!soc_dai) { -- ret = -ENOMEM; -- goto err_pm_disable; -- } -+ if (!soc_dai) -+ return -ENOMEM; - -+ memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai)); - if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { - if (val >= 2 && val <= 8) - soc_dai->playback.channels_max = val; -@@ -665,6 +701,24 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - soc_dai->capture.channels_max = val; - } - -+ i2s->bclk_fs = 64; -+ if (!of_property_read_u32(node, "rockchip,bclk-fs", &val)) { -+ if ((val >= 32) && (val % 2 == 0)) -+ i2s->bclk_fs = val; -+ } -+ -+ i2s->clk_trcm = I2S_CKR_TRCM_TXRX; -+ if (!of_property_read_u32(node, "rockchip,clk-trcm", &val)) { -+ if (val >= 0 && val <= 2) { -+ i2s->clk_trcm = val << I2S_CKR_TRCM_SHIFT; -+ if (i2s->clk_trcm) -+ soc_dai->symmetric_rate = 1; -+ } -+ } -+ -+ regmap_update_bits(i2s->regmap, I2S_CKR, -+ I2S_CKR_TRCM_MASK, i2s->clk_trcm); -+ - ret = devm_snd_soc_register_component(&pdev->dev, - &rockchip_i2s_component, - soc_dai, 1); -@@ -674,10 +728,12 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - goto err_suspend; - } - -- ret = rockchip_pcm_platform_register(&pdev->dev); -+ if (of_property_read_bool(node, "rockchip,no-dmaengine")) -+ return ret; -+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); - if (ret) { - dev_err(&pdev->dev, "Could not register PCM\n"); -- goto err_suspend; -+ return ret; - } - - return 0; -@@ -699,14 +755,41 @@ static int rockchip_i2s_remove(struct platform_device *pdev) - if (!pm_runtime_status_suspended(&pdev->dev)) - i2s_runtime_suspend(&pdev->dev); - -+ clk_disable_unprepare(i2s->mclk); - clk_disable_unprepare(i2s->hclk); - - return 0; - } - -+#ifdef CONFIG_PM_SLEEP -+static int rockchip_i2s_suspend(struct device *dev) -+{ -+ struct rk_i2s_dev *i2s = dev_get_drvdata(dev); -+ -+ regcache_mark_dirty(i2s->regmap); -+ -+ return 0; -+} -+ -+static int rockchip_i2s_resume(struct device *dev) -+{ -+ struct rk_i2s_dev *i2s = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ ret = regcache_sync(i2s->regmap); -+ pm_runtime_put(dev); -+ -+ return ret; -+} -+#endif -+ - static const struct dev_pm_ops rockchip_i2s_pm_ops = { - SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, - NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_suspend, rockchip_i2s_resume) - }; - - static struct platform_driver rockchip_i2s_driver = { -diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c -index 39c1b98f9593..499b991c3c1a 100644 ---- a/sound/soc/rockchip/rockchip_i2s_tdm.c -+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c -@@ -15,9 +15,13 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include -+#include -+#include - #include - #include - -@@ -25,19 +29,91 @@ - - #define DRV_NAME "rockchip-i2s-tdm" - -+#define DEFAULT_MCLK_FS 256 -+#define CH_GRP_MAX 4 /* The max channel 8 / 2 */ -+#define MULTIPLEX_CH_MAX 10 -+ -+struct txrx_config { -+ u32 addr; -+ u32 reg; -+ u32 txonly; -+ u32 rxonly; -+}; -+ -+struct rk_i2s_soc_data { -+ u32 softrst_offset; -+ u32 grf_reg_offset; -+ u32 grf_shift; -+ int config_count; -+ const struct txrx_config *configs; -+ int (*init)(struct device *dev, u32 addr); -+}; -+ - struct rk_i2s_tdm_dev { - struct device *dev; - struct clk *hclk; - struct clk *mclk_tx; - struct clk *mclk_rx; -+ /* The mclk_tx_src is parent of mclk_tx */ -+ struct clk *mclk_tx_src; -+ /* The mclk_rx_src is parent of mclk_rx */ -+ struct clk *mclk_rx_src; -+ /* -+ * The mclk_root0 and mclk_root1 are root parent and supplies for -+ * the different FS. -+ * -+ * e.g: -+ * mclk_root0 is VPLL0, used for FS=48000Hz -+ * mclk_root0 is VPLL1, used for FS=44100Hz -+ */ -+ struct clk *mclk_root0; -+ struct clk *mclk_root1; - struct regmap *regmap; -+ struct regmap *grf; - struct snd_dmaengine_dai_dma_data capture_dma_data; - struct snd_dmaengine_dai_dma_data playback_dma_data; -- -+ struct reset_control *tx_reset; -+ struct reset_control *rx_reset; -+ struct rk_i2s_soc_data *soc_data; -+ void __iomem *cru_base; - bool is_master_mode; -+ bool io_multiplex; -+ bool mclk_calibrate; -+ bool tdm_mode; -+ unsigned int mclk_rx_freq; -+ unsigned int mclk_tx_freq; - unsigned int bclk_fs; -+ unsigned int clk_trcm; -+ unsigned int i2s_sdis[CH_GRP_MAX]; -+ unsigned int i2s_sdos[CH_GRP_MAX]; -+ int tx_reset_id; -+ int rx_reset_id; -+ atomic_t refcount; -+ spinlock_t lock; /* xfer lock */ - }; - -+static int to_ch_num(unsigned int val) -+{ -+ int chs; -+ -+ switch (val) { -+ case I2S_CHN_4: -+ chs = 4; -+ break; -+ case I2S_CHN_6: -+ chs = 6; -+ break; -+ case I2S_CHN_8: -+ chs = 8; -+ break; -+ default: -+ chs = 2; -+ break; -+ } -+ -+ return chs; -+} -+ - static int i2s_tdm_runtime_suspend(struct device *dev) - { - struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -@@ -80,6 +156,205 @@ static inline struct rk_i2s_tdm_dev *to_info(struct snd_soc_dai *dai) - return snd_soc_dai_get_drvdata(dai); - } - -+#if defined(CONFIG_ARM) && !defined(writeq) -+static inline void __raw_writeq(u64 val, volatile void __iomem *addr) -+{ -+ asm volatile("strd %0, %H0, [%1]" : : "r" (val), "r" (addr)); -+} -+#define writeq(v,c) ({ __iowmb(); __raw_writeq((__force u64) cpu_to_le64(v), c); }) -+#endif -+ -+static void rockchip_snd_xfer_reset_assert(struct rk_i2s_tdm_dev *i2s_tdm, -+ int tx_bank, int tx_offset, -+ int rx_bank, int rx_offset) -+{ -+ void __iomem *cru_reset, *addr; -+ unsigned long flags; -+ u64 val; -+ -+ cru_reset = i2s_tdm->cru_base + i2s_tdm->soc_data->softrst_offset; -+ -+ switch (abs(tx_bank - rx_bank)) { -+ case 0: -+ writel(BIT(tx_offset) | BIT(rx_offset) | -+ (BIT(tx_offset) << 16) | (BIT(rx_offset) << 16), -+ cru_reset + (tx_bank * 4)); -+ break; -+ case 1: -+ if (tx_bank < rx_bank) { -+ val = BIT(rx_offset) | (BIT(rx_offset) << 16); -+ val <<= 32; -+ val |= BIT(tx_offset) | (BIT(tx_offset) << 16); -+ addr = cru_reset + (tx_bank * 4); -+ } else { -+ val = BIT(tx_offset) | (BIT(tx_offset) << 16); -+ val <<= 32; -+ val |= BIT(rx_offset) | (BIT(rx_offset) << 16); -+ addr = cru_reset + (rx_bank * 4); -+ } -+ -+ if (IS_ALIGNED((uintptr_t)addr, 8)) { -+ writeq(val, addr); -+ break; -+ } -+ /* fall through */ -+ default: -+ local_irq_save(flags); -+ writel(BIT(tx_offset) | (BIT(tx_offset) << 16), -+ cru_reset + (tx_bank * 4)); -+ writel(BIT(rx_offset) | (BIT(rx_offset) << 16), -+ cru_reset + (rx_bank * 4)); -+ local_irq_restore(flags); -+ break; -+ } -+} -+ -+static void rockchip_snd_xfer_reset_deassert(struct rk_i2s_tdm_dev *i2s_tdm, -+ int tx_bank, int tx_offset, -+ int rx_bank, int rx_offset) -+{ -+ void __iomem *cru_reset, *addr; -+ unsigned long flags; -+ u64 val; -+ -+ cru_reset = i2s_tdm->cru_base + i2s_tdm->soc_data->softrst_offset; -+ -+ switch (abs(tx_bank - rx_bank)) { -+ case 0: -+ writel((BIT(tx_offset) << 16) | (BIT(rx_offset) << 16), -+ cru_reset + (tx_bank * 4)); -+ break; -+ case 1: -+ if (tx_bank < rx_bank) { -+ val = (BIT(rx_offset) << 16); -+ val <<= 32; -+ val |= (BIT(tx_offset) << 16); -+ addr = cru_reset + (tx_bank * 4); -+ } else { -+ val = (BIT(tx_offset) << 16); -+ val <<= 32; -+ val |= (BIT(rx_offset) << 16); -+ addr = cru_reset + (rx_bank * 4); -+ } -+ -+ if (IS_ALIGNED((uintptr_t)addr, 8)) { -+ writeq(val, addr); -+ break; -+ } -+ /* fall through */ -+ default: -+ local_irq_save(flags); -+ writel((BIT(tx_offset) << 16), -+ cru_reset + (tx_bank * 4)); -+ writel((BIT(rx_offset) << 16), -+ cru_reset + (rx_bank * 4)); -+ local_irq_restore(flags); -+ break; -+ } -+} -+ -+/* -+ * to make sure tx/rx reset at the same time when clk_trcm > 0 -+ * if not, will lead lrck is abnormal. -+ */ -+static void rockchip_snd_xfer_sync_reset(struct rk_i2s_tdm_dev *i2s_tdm) -+{ -+ int tx_id, rx_id; -+ int tx_bank, rx_bank, tx_offset, rx_offset; -+ -+ if (!i2s_tdm->cru_base || !i2s_tdm->soc_data) -+ return; -+ -+ tx_id = i2s_tdm->tx_reset_id; -+ rx_id = i2s_tdm->rx_reset_id; -+ if (tx_id < 0 || rx_id < 0) { -+ dev_err(i2s_tdm->dev, "invalid reset id\n"); -+ return; -+ } -+ -+ tx_bank = tx_id / 16; -+ tx_offset = tx_id % 16; -+ rx_bank = rx_id / 16; -+ rx_offset = rx_id % 16; -+ dev_dbg(i2s_tdm->dev, -+ "tx_bank: %d, rx_bank: %d,tx_offset: %d, rx_offset: %d\n", -+ tx_bank, rx_bank, tx_offset, rx_offset); -+ -+ rockchip_snd_xfer_reset_assert(i2s_tdm, tx_bank, tx_offset, -+ rx_bank, rx_offset); -+ -+ udelay(150); -+ -+ rockchip_snd_xfer_reset_deassert(i2s_tdm, tx_bank, tx_offset, -+ rx_bank, rx_offset); -+} -+ -+/* only used when clk_trcm > 0 */ -+static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai, int on) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); -+ unsigned int val = 0; -+ int retry = 10; -+ -+ spin_lock(&i2s_tdm->lock); -+ if (on) { -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, -+ I2S_DMACR_TDE_ENABLE); -+ else -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, -+ I2S_DMACR_RDE_ENABLE); -+ -+ if (atomic_inc_return(&i2s_tdm->refcount) == 1) { -+ rockchip_snd_xfer_sync_reset(i2s_tdm); -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START | -+ I2S_XFER_RXS_START, -+ I2S_XFER_TXS_START | -+ I2S_XFER_RXS_START); -+ } -+ } else { -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, -+ I2S_DMACR_TDE_DISABLE); -+ else -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, -+ I2S_DMACR_RDE_DISABLE); -+ -+ if (atomic_dec_and_test(&i2s_tdm->refcount)) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START | -+ I2S_XFER_RXS_START, -+ I2S_XFER_TXS_STOP | -+ I2S_XFER_RXS_STOP); -+ -+ udelay(150); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, -+ I2S_CLR_TXC | I2S_CLR_RXC, -+ I2S_CLR_TXC | I2S_CLR_RXC); -+ -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ -+ /* Should wait for clear operation to finish */ -+ while (val) { -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ retry--; -+ if (!retry) { -+ dev_info(i2s_tdm->dev, "reset txrx\n"); -+ rockchip_snd_xfer_sync_reset(i2s_tdm); -+ break; -+ } -+ } -+ } -+ } -+ spin_unlock(&i2s_tdm->lock); -+} -+ - static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) - { - unsigned int val = 0; -@@ -112,7 +387,10 @@ static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) - regmap_read(i2s_tdm->regmap, I2S_CLR, &val); - retry--; - if (!retry) { -- dev_warn(i2s_tdm->dev, "fail to clear\n"); -+ dev_warn(i2s_tdm->dev, "reset tx\n"); -+ reset_control_assert(i2s_tdm->tx_reset); -+ udelay(1); -+ reset_control_deassert(i2s_tdm->tx_reset); - break; - } - } -@@ -151,7 +429,10 @@ static void rockchip_snd_rxctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) - regmap_read(i2s_tdm->regmap, I2S_CLR, &val); - retry--; - if (!retry) { -- dev_warn(i2s_tdm->dev, "fail to clear\n"); -+ dev_warn(i2s_tdm->dev, "reset rx\n"); -+ reset_control_assert(i2s_tdm->rx_reset); -+ udelay(1); -+ reset_control_deassert(i2s_tdm->rx_reset); - break; - } - } -@@ -162,8 +443,9 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) - { - struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai); -- unsigned int mask = 0, val = 0; -+ unsigned int mask = 0, val = 0, tdm_val = 0; - int ret = 0; -+ bool is_tdm = i2s_tdm->tdm_mode; - - pm_runtime_get_sync(cpu_dai->dev); - mask = I2S_CKR_MSS_MASK; -@@ -247,36 +529,283 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai, - - regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val); - -+ if (is_tdm) { -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_RIGHT_J: -+ val = I2S_TXCR_TFS_TDM_I2S; -+ tdm_val = TDM_SHIFT_CTRL(2); -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ val = I2S_TXCR_TFS_TDM_I2S; -+ tdm_val = TDM_SHIFT_CTRL(1); -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ val = I2S_TXCR_TFS_TDM_I2S; -+ tdm_val = TDM_SHIFT_CTRL(0); -+ break; -+ case SND_SOC_DAIFMT_DSP_A: -+ val = I2S_TXCR_TFS_TDM_PCM; -+ tdm_val = TDM_SHIFT_CTRL(0); -+ break; -+ case SND_SOC_DAIFMT_DSP_B: -+ val = I2S_TXCR_TFS_TDM_PCM; -+ tdm_val = TDM_SHIFT_CTRL(2); -+ break; -+ default: -+ ret = -EINVAL; -+ goto err_pm_put; -+ } -+ -+ tdm_val |= TDM_FSYNC_WIDTH_SEL1(1); -+ tdm_val |= TDM_FSYNC_WIDTH_ONE_FRAME; -+ -+ mask = I2S_TXCR_TFS_MASK; -+ regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, mask, val); -+ regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val); -+ -+ mask = TDM_FSYNC_WIDTH_SEL1_MSK | TDM_FSYNC_WIDTH_SEL0_MSK | -+ TDM_SHIFT_CTRL_MSK; -+ regmap_update_bits(i2s_tdm->regmap, I2S_TDM_TXCR, -+ mask, tdm_val); -+ regmap_update_bits(i2s_tdm->regmap, I2S_TDM_RXCR, -+ mask, tdm_val); -+ } -+ - err_pm_put: - pm_runtime_put(cpu_dai->dev); - - return ret; - } - -+static void rockchip_i2s_tdm_xfer_pause(struct snd_pcm_substream *substream, -+ struct rk_i2s_tdm_dev *i2s_tdm) -+{ -+ int stream; -+ unsigned int val = 0; -+ int retry = 10; -+ -+ stream = SNDRV_PCM_STREAM_LAST - substream->stream; -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, -+ I2S_DMACR_TDE_DISABLE); -+ else -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, -+ I2S_DMACR_RDE_DISABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START | -+ I2S_XFER_RXS_START, -+ I2S_XFER_TXS_STOP | -+ I2S_XFER_RXS_STOP); -+ -+ udelay(150); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, -+ I2S_CLR_TXC | I2S_CLR_RXC, -+ I2S_CLR_TXC | I2S_CLR_RXC); -+ -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ -+ /* Should wait for clear operation to finish */ -+ while (val) { -+ regmap_read(i2s_tdm->regmap, I2S_CLR, &val); -+ retry--; -+ if (!retry) { -+ dev_info(i2s_tdm->dev, "reset txrx\n"); -+ rockchip_snd_xfer_sync_reset(i2s_tdm); -+ break; -+ } -+ } -+} -+ -+static void rockchip_i2s_tdm_xfer_resume(struct snd_pcm_substream *substream, -+ struct rk_i2s_tdm_dev *i2s_tdm) -+{ -+ int stream; -+ -+ stream = SNDRV_PCM_STREAM_LAST - substream->stream; -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_TDE_ENABLE, -+ I2S_DMACR_TDE_ENABLE); -+ else -+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, -+ I2S_DMACR_RDE_ENABLE, -+ I2S_DMACR_RDE_ENABLE); -+ -+ regmap_update_bits(i2s_tdm->regmap, I2S_XFER, -+ I2S_XFER_TXS_START | -+ I2S_XFER_RXS_START, -+ I2S_XFER_TXS_START | -+ I2S_XFER_RXS_START); -+} -+ -+static int rockchip_i2s_tdm_calibrate_mclk(struct rk_i2s_tdm_dev *i2s_tdm, -+ struct snd_pcm_substream *substream, -+ unsigned int lrck_freq) -+{ -+ struct clk *mclk_root; -+ struct clk *mclk_parent; -+ /* It's 256 times higher than a high sample rate */ -+ unsigned int mclk_parent_freq; -+ int ret; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ mclk_parent = i2s_tdm->mclk_tx_src; -+ else -+ mclk_parent = i2s_tdm->mclk_rx_src; -+ -+ switch (lrck_freq) { -+ case 8000: -+ case 16000: -+ case 24000: -+ case 32000: -+ case 48000: -+ case 64000: -+ case 96000: -+ case 192000: -+ mclk_root = i2s_tdm->mclk_root0; -+ mclk_parent_freq = DEFAULT_MCLK_FS * 192000; -+ break; -+ case 11025: -+ case 22050: -+ case 44100: -+ case 88200: -+ case 176400: -+ mclk_root = i2s_tdm->mclk_root1; -+ mclk_parent_freq = DEFAULT_MCLK_FS * 176400; -+ break; -+ default: -+ dev_err(i2s_tdm->dev, "Invalid LRCK freq: %u Hz\n", -+ lrck_freq); -+ return -EINVAL; -+ } -+ -+ ret = clk_set_parent(mclk_parent, mclk_root); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, "parent: %s set root: %s failed: %d\n", -+ __clk_get_name(mclk_parent), -+ __clk_get_name(mclk_root), -+ ret); -+ goto out; -+ } -+ -+ ret = clk_set_rate(mclk_parent, mclk_parent_freq); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, "parent: %s set freq: %d failed: %d\n", -+ __clk_get_name(mclk_parent), -+ mclk_parent_freq, -+ ret); -+ goto out; -+ } -+ -+out: -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm, -+ struct snd_pcm_substream *substream, -+ struct clk **mclk) -+{ -+ unsigned int mclk_freq; -+ int ret; -+ -+ if (i2s_tdm->clk_trcm) { -+ if (i2s_tdm->mclk_tx_freq != i2s_tdm->mclk_rx_freq) { -+ dev_err(i2s_tdm->dev, -+ "clk_trcm, tx: %d and rx: %d should be same\n", -+ i2s_tdm->mclk_tx_freq, -+ i2s_tdm->mclk_rx_freq); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ ret = clk_set_rate(i2s_tdm->mclk_tx, i2s_tdm->mclk_tx_freq); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, -+ "Set mclk_tx: %s freq: %d failed: %d\n", -+ __clk_get_name(i2s_tdm->mclk_tx), -+ i2s_tdm->mclk_tx_freq, ret); -+ goto err; -+ } -+ -+ ret = clk_set_rate(i2s_tdm->mclk_rx, i2s_tdm->mclk_rx_freq); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, -+ "Set mclk_rx: %s freq: %d failed: %d\n", -+ __clk_get_name(i2s_tdm->mclk_rx), -+ i2s_tdm->mclk_rx_freq, ret); -+ goto err; -+ } -+ -+ /* Using mclk_rx is ok. */ -+ *mclk = i2s_tdm->mclk_tx; -+ } else { -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ *mclk = i2s_tdm->mclk_tx; -+ mclk_freq = i2s_tdm->mclk_tx_freq; -+ } else { -+ *mclk = i2s_tdm->mclk_rx; -+ mclk_freq = i2s_tdm->mclk_rx_freq; -+ } -+ -+ ret = clk_set_rate(*mclk, mclk_freq); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, "Set mclk_%s: %s freq: %d failed: %d\n", -+ substream->stream ? "rx" : "tx", -+ __clk_get_name(*mclk), mclk_freq, ret); -+ goto err; -+ } -+ } -+ -+ return 0; -+ -+err: -+ return ret; -+} -+ - static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) - { - struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); -- struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct clk *mclk; -+ int ret = 0; - unsigned int val = 0; - unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; - -- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- mclk = i2s_tdm->mclk_tx; -- else -- mclk = i2s_tdm->mclk_rx; -+ if (i2s_tdm->mclk_calibrate) -+ rockchip_i2s_tdm_calibrate_mclk(i2s_tdm, substream, -+ params_rate(params)); -+ -+ ret = rockchip_i2s_tdm_set_mclk(i2s_tdm, substream, &mclk); -+ if (ret) -+ return ret; -+ -+ if (i2s_tdm->clk_trcm) { -+ spin_lock(&i2s_tdm->lock); -+ if (atomic_read(&i2s_tdm->refcount)) -+ rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm); -+ } - - if (i2s_tdm->is_master_mode) { - mclk_rate = clk_get_rate(mclk); - bclk_rate = i2s_tdm->bclk_fs * params_rate(params); -- if (!bclk_rate) -- return -EINVAL; -- -+ if (!bclk_rate) { -+ ret = -EINVAL; -+ goto err; -+ } - div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - div_lrck = bclk_rate / params_rate(params); -- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ if (i2s_tdm->clk_trcm) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, -+ I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK, -+ I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk)); -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK, -+ I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck)); -+ } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, - I2S_CLKDIV_TXM_MASK, - I2S_CLKDIV_TXM(div_bclk)); -@@ -310,7 +839,8 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, - val |= I2S_TXCR_VDW(32); - break; - default: -- return -EINVAL; -+ ret = -EINVAL; -+ goto err; - } - - switch (params_channels(params)) { -@@ -329,7 +859,8 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, - default: - dev_err(i2s_tdm->dev, "invalid channel: %d\n", - params_channels(params)); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err; - } - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -@@ -341,19 +872,103 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, - I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK, - val); - -+ if (i2s_tdm->io_multiplex) { -+ int usable_chs = MULTIPLEX_CH_MAX; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { -+ struct snd_pcm_str *playback_str = -+ &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; -+ -+ if (playback_str->substream_opened) { -+ regmap_read(i2s_tdm->regmap, I2S_TXCR, &val); -+ val &= I2S_TXCR_CSR_MASK; -+ usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val); -+ } -+ -+ regmap_read(i2s_tdm->regmap, I2S_RXCR, &val); -+ val &= I2S_RXCR_CSR_MASK; -+ -+ if (to_ch_num(val) > usable_chs) { -+ dev_err(i2s_tdm->dev, -+ "Capture chs(%d) > usable chs(%d)\n", -+ to_ch_num(val), usable_chs); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ switch (val) { -+ case I2S_CHN_4: -+ val = I2S_IO_6CH_OUT_4CH_IN; -+ break; -+ case I2S_CHN_6: -+ val = I2S_IO_4CH_OUT_6CH_IN; -+ break; -+ case I2S_CHN_8: -+ val = I2S_IO_2CH_OUT_8CH_IN; -+ break; -+ default: -+ val = I2S_IO_8CH_OUT_2CH_IN; -+ break; -+ } -+ } else { -+ struct snd_pcm_str *capture_str = -+ &substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; -+ -+ if (capture_str->substream_opened) { -+ regmap_read(i2s_tdm->regmap, I2S_RXCR, &val); -+ val &= I2S_RXCR_CSR_MASK; -+ usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val); -+ } -+ -+ regmap_read(i2s_tdm->regmap, I2S_TXCR, &val); -+ val &= I2S_TXCR_CSR_MASK; -+ -+ if (to_ch_num(val) > usable_chs) { -+ dev_err(i2s_tdm->dev, -+ "Playback chs(%d) > usable chs(%d)\n", -+ to_ch_num(val), usable_chs); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ switch (val) { -+ case I2S_CHN_4: -+ val = I2S_IO_4CH_OUT_6CH_IN; -+ break; -+ case I2S_CHN_6: -+ val = I2S_IO_6CH_OUT_4CH_IN; -+ break; -+ case I2S_CHN_8: -+ val = I2S_IO_8CH_OUT_2CH_IN; -+ break; -+ default: -+ val = I2S_IO_2CH_OUT_8CH_IN; -+ break; -+ } -+ } -+ -+ val <<= i2s_tdm->soc_data->grf_shift; -+ val |= (I2S_IO_DIRECTION_MASK << i2s_tdm->soc_data->grf_shift) << 16; -+ regmap_write(i2s_tdm->grf, i2s_tdm->soc_data->grf_reg_offset, val); -+ } -+ - regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, - I2S_DMACR_TDL(16)); - regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, - I2S_DMACR_RDL(16)); - -- val = I2S_CKR_TRCM_TXRX; -- if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates) -- val = I2S_CKR_TRCM_TXONLY; -+ if (i2s_tdm->clk_trcm) { -+ if (atomic_read(&i2s_tdm->refcount)) -+ rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm); -+ spin_unlock(&i2s_tdm->lock); -+ } - -- regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -- I2S_CKR_TRCM_MASK, -- val); - return 0; -+ -+err: -+ if (i2s_tdm->clk_trcm) -+ spin_unlock(&i2s_tdm->lock); -+ return ret; - } - - static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, -@@ -366,7 +981,9 @@ static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ if (i2s_tdm->clk_trcm) -+ rockchip_snd_txrxctrl(substream, dai, 1); -+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s_tdm, 1); - else - rockchip_snd_txctrl(i2s_tdm, 1); -@@ -374,7 +991,9 @@ static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ if (i2s_tdm->clk_trcm) -+ rockchip_snd_txrxctrl(substream, dai, 0); -+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s_tdm, 0); - else - rockchip_snd_txctrl(i2s_tdm, 0); -@@ -387,19 +1006,26 @@ static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, - return ret; - } - --static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, -+static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream, - unsigned int freq, int dir) - { - struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai); -- int ret; - -- ret = clk_set_rate(i2s_tdm->mclk_tx, freq); -- if (ret) -- dev_err(i2s_tdm->dev, "Fail to set mclk_tx %d\n", ret); -+ /* Put set mclk rate into rockchip_i2s_tdm_set_mclk() */ -+ if (i2s_tdm->clk_trcm) { -+ i2s_tdm->mclk_tx_freq = freq; -+ i2s_tdm->mclk_rx_freq = freq; -+ } else { -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) -+ i2s_tdm->mclk_tx_freq = freq; -+ else -+ i2s_tdm->mclk_rx_freq = freq; -+ } - -- if (!IS_ERR(i2s_tdm->mclk_rx)) -- ret = clk_set_rate(i2s_tdm->mclk_rx, freq); -- return ret; -+ dev_dbg(i2s_tdm->dev, "The target mclk_%s freq is: %d\n", -+ stream ? "rx" : "tx", freq); -+ -+ return 0; - } - - static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai) -@@ -412,41 +1038,34 @@ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai) - return 0; - } - -+static int rockchip_dai_tdm_slot(struct snd_soc_dai *dai, -+ unsigned int tx_mask, unsigned int rx_mask, -+ int slots, int slot_width) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); -+ unsigned int mask, val; -+ -+ i2s_tdm->tdm_mode = true; -+ i2s_tdm->bclk_fs = slots * slot_width; -+ mask = TDM_SLOT_BIT_WIDTH_MSK | TDM_FRAME_WIDTH_MSK; -+ val = TDM_SLOT_BIT_WIDTH(slot_width) | -+ TDM_FRAME_WIDTH(slots * slot_width); -+ regmap_update_bits(i2s_tdm->regmap, I2S_TDM_TXCR, -+ mask, val); -+ regmap_update_bits(i2s_tdm->regmap, I2S_TDM_RXCR, -+ mask, val); -+ -+ return 0; -+} -+ - static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { - .hw_params = rockchip_i2s_tdm_hw_params, - .set_sysclk = rockchip_i2s_tdm_set_sysclk, - .set_fmt = rockchip_i2s_tdm_set_fmt, -+ .set_tdm_slot = rockchip_dai_tdm_slot, - .trigger = rockchip_i2s_tdm_trigger, - }; - --static struct snd_soc_dai_driver rockchip_i2s_tdm_dai = { -- .probe = rockchip_i2s_tdm_dai_probe, -- .playback = { -- .stream_name = "Playback", -- .channels_min = 2, -- .channels_max = 8, -- .rates = SNDRV_PCM_RATE_8000_192000, -- .formats = (SNDRV_PCM_FMTBIT_S8 | -- SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S20_3LE | -- SNDRV_PCM_FMTBIT_S24_LE | -- SNDRV_PCM_FMTBIT_S32_LE), -- }, -- .capture = { -- .stream_name = "Capture", -- .channels_min = 2, -- .channels_max = 8, -- .rates = SNDRV_PCM_RATE_8000_192000, -- .formats = (SNDRV_PCM_FMTBIT_S8 | -- SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S20_3LE | -- SNDRV_PCM_FMTBIT_S24_LE | -- SNDRV_PCM_FMTBIT_S32_LE), -- }, -- .ops = &rockchip_i2s_tdm_dai_ops, -- .symmetric_rates = 1, --}; -- - static const struct snd_soc_component_driver rockchip_i2s_tdm_component = { - .name = DRV_NAME, - }; -@@ -481,9 +1100,11 @@ static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg) - case I2S_INTCR: - case I2S_XFER: - case I2S_CLR: -+ case I2S_TXDR: - case I2S_RXDR: -- case I2S_FIFOLR: -+ case I2S_TXFIFOLR: - case I2S_INTSR: -+ case I2S_RXFIFOLR: - case I2S_TDM_TXCR: - case I2S_TDM_RXCR: - case I2S_CLKDIV: -@@ -496,8 +1117,12 @@ static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg) - static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg) - { - switch (reg) { -+ case I2S_TXFIFOLR: - case I2S_INTSR: - case I2S_CLR: -+ case I2S_TXDR: -+ case I2S_RXDR: -+ case I2S_RXFIFOLR: - return true; - default: - return false; -@@ -507,6 +1132,8 @@ static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg) - static bool rockchip_i2s_tdm_precious_reg(struct device *dev, unsigned int reg) - { - switch (reg) { -+ case I2S_RXDR: -+ return true; - default: - return false; - } -@@ -537,26 +1164,363 @@ static const struct regmap_config rockchip_i2s_tdm_regmap_config = { - .cache_type = REGCACHE_FLAT, - }; - -+static int common_soc_init(struct device *dev, u32 addr) -+{ -+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); -+ const struct txrx_config *configs = i2s_tdm->soc_data->configs; -+ u32 reg = 0, val = 0, trcm = i2s_tdm->clk_trcm; -+ int i; -+ -+ switch (trcm) { -+ case I2S_CKR_TRCM_TXONLY: -+ /* fall through */ -+ case I2S_CKR_TRCM_RXONLY: -+ break; -+ default: -+ return 0; -+ } -+ -+ for (i = 0; i < i2s_tdm->soc_data->config_count; i++) { -+ if (addr != configs[i].addr) -+ continue; -+ reg = configs[i].reg; -+ if (trcm == I2S_CKR_TRCM_TXONLY) -+ val = configs[i].txonly; -+ else -+ val = configs[i].rxonly; -+ } -+ -+ if (reg) -+ regmap_write(i2s_tdm->grf, reg, val); -+ -+ return 0; -+} -+ -+static const struct txrx_config px30_txrx_config[] = { -+ { 0xff060000, 0x184, PX30_I2S0_CLK_TXONLY, PX30_I2S0_CLK_RXONLY }, -+}; -+ -+static const struct txrx_config rk1808_txrx_config[] = { -+ { 0xff7e0000, 0x190, RK1808_I2S0_CLK_TXONLY, RK1808_I2S0_CLK_RXONLY }, -+}; -+ -+static const struct txrx_config rk3308_txrx_config[] = { -+ { 0xff300000, 0x308, RK3308_I2S0_CLK_TXONLY, RK3308_I2S0_CLK_RXONLY }, -+ { 0xff310000, 0x308, RK3308_I2S1_CLK_TXONLY, RK3308_I2S1_CLK_RXONLY }, -+}; -+ -+static struct rk_i2s_soc_data px30_i2s_soc_data = { -+ .softrst_offset = 0x0300, -+ .configs = px30_txrx_config, -+ .config_count = ARRAY_SIZE(px30_txrx_config), -+ .init = common_soc_init, -+}; -+ -+static struct rk_i2s_soc_data rk1808_i2s_soc_data = { -+ .softrst_offset = 0x0300, -+ .configs = rk1808_txrx_config, -+ .config_count = ARRAY_SIZE(rk1808_txrx_config), -+ .init = common_soc_init, -+}; -+ -+static struct rk_i2s_soc_data rk3308_i2s_soc_data = { -+ .softrst_offset = 0x0400, -+ .grf_reg_offset = 0x0308, -+ .grf_shift = 5, -+ .configs = rk3308_txrx_config, -+ .config_count = ARRAY_SIZE(rk3308_txrx_config), -+ .init = common_soc_init, -+}; -+ - static const struct of_device_id rockchip_i2s_tdm_match[] = { -- { .compatible = "rockchip,rk3308-i2s-tdm", }, -+ { .compatible = "rockchip,px30-i2s-tdm", .data = &px30_i2s_soc_data }, -+ { .compatible = "rockchip,rk1808-i2s-tdm", .data = &rk1808_i2s_soc_data }, -+ { .compatible = "rockchip,rk3308-i2s-tdm", .data = &rk3308_i2s_soc_data }, - {}, - }; - -+static int of_i2s_resetid_get(struct device_node *node, -+ const char *id) -+{ -+ struct of_phandle_args args; -+ int index = 0; -+ int ret; -+ -+ if (id) -+ index = of_property_match_string(node, -+ "reset-names", id); -+ ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", -+ index, &args); -+ if (ret) -+ return ret; -+ -+ return args.args[0]; -+} -+ -+static int rockchip_i2s_tdm_dai_prepare(struct platform_device *pdev, -+ struct snd_soc_dai_driver **soc_dai) -+{ -+ struct snd_soc_dai_driver rockchip_i2s_tdm_dai = { -+ .probe = rockchip_i2s_tdm_dai_probe, -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "Capture", -+ .channels_min = 2, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rockchip_i2s_tdm_dai_ops, -+ }; -+ -+ *soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_tdm_dai, -+ sizeof(rockchip_i2s_tdm_dai), GFP_KERNEL); -+ if (!(*soc_dai)) { -+ dev_err(&pdev->dev, "Failed to duplicate i2s_tdm_dai\n"); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm, -+ int num, -+ bool is_rx_path) -+{ -+ unsigned int *i2s_data; -+ int i, j, ret = 0; -+ -+ if (is_rx_path) -+ i2s_data = i2s_tdm->i2s_sdis; -+ else -+ i2s_data = i2s_tdm->i2s_sdos; -+ -+ for (i = 0; i < num; i++) { -+ if (i2s_data[i] > CH_GRP_MAX - 1) { -+ dev_err(i2s_tdm->dev, -+ "%s path i2s_data[%d]: %d is overflow, max is: %d\n", -+ is_rx_path ? "RX" : "TX", -+ i, i2s_data[i], CH_GRP_MAX); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ for (j = 0; j < num; j++) { -+ if (i == j) -+ continue; -+ -+ if (i2s_data[i] == i2s_data[j]) { -+ dev_err(i2s_tdm->dev, -+ "%s path invalid routed i2s_data: [%d]%d == [%d]%d\n", -+ is_rx_path ? "RX" : "TX", -+ i, i2s_data[i], -+ j, i2s_data[j]); -+ ret = -EINVAL; -+ goto err; -+ } -+ } -+ } -+ -+err: -+ return ret; -+} -+ -+static void rockchip_i2s_tdm_tx_path_config(struct rk_i2s_tdm_dev *i2s_tdm, -+ int num) -+{ -+ int idx; -+ -+ for (idx = 0; idx < num; idx++) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, -+ I2S_TXCR_PATH_MASK(idx), -+ I2S_TXCR_PATH(idx, i2s_tdm->i2s_sdos[idx])); -+ } -+} -+ -+static void rockchip_i2s_tdm_rx_path_config(struct rk_i2s_tdm_dev *i2s_tdm, -+ int num) -+{ -+ int idx; -+ -+ for (idx = 0; idx < num; idx++) { -+ regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, -+ I2S_RXCR_PATH_MASK(idx), -+ I2S_RXCR_PATH(idx, i2s_tdm->i2s_sdis[idx])); -+ } -+} -+ -+static void rockchip_i2s_tdm_path_config(struct rk_i2s_tdm_dev *i2s_tdm, -+ int num, bool is_rx_path) -+{ -+ if (is_rx_path) -+ rockchip_i2s_tdm_rx_path_config(i2s_tdm, num); -+ else -+ rockchip_i2s_tdm_tx_path_config(i2s_tdm, num); -+} -+ -+static int rockchip_i2s_tdm_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm, -+ struct device_node *np, -+ bool is_rx_path) -+{ -+ char *i2s_tx_path_prop = "rockchip,i2s-tx-route"; -+ char *i2s_rx_path_prop = "rockchip,i2s-rx-route"; -+ char *i2s_path_prop; -+ unsigned int *i2s_data; -+ int num, ret = 0; -+ -+ if (is_rx_path) { -+ i2s_path_prop = i2s_rx_path_prop; -+ i2s_data = i2s_tdm->i2s_sdis; -+ } else { -+ i2s_path_prop = i2s_tx_path_prop; -+ i2s_data = i2s_tdm->i2s_sdos; -+ } -+ -+ num = of_count_phandle_with_args(np, i2s_path_prop, NULL); -+ if (num < 0) { -+ if (num != -ENOENT) { -+ dev_err(i2s_tdm->dev, -+ "Failed to read '%s' num: %d\n", -+ i2s_path_prop, num); -+ ret = num; -+ } -+ goto out; -+ } else if (num != CH_GRP_MAX) { -+ dev_err(i2s_tdm->dev, -+ "The num: %d should be: %d\n", num, CH_GRP_MAX); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ret = of_property_read_u32_array(np, i2s_path_prop, -+ i2s_data, num); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, -+ "Failed to read '%s': %d\n", -+ i2s_path_prop, ret); -+ goto out; -+ } -+ -+ ret = rockchip_i2s_tdm_path_check(i2s_tdm, num, is_rx_path); -+ if (ret < 0) { -+ dev_err(i2s_tdm->dev, -+ "Failed to check i2s data bus: %d\n", ret); -+ goto out; -+ } -+ -+ rockchip_i2s_tdm_path_config(i2s_tdm, num, is_rx_path); -+ -+out: -+ return ret; -+} -+ -+static int rockchip_i2s_tdm_tx_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm, -+ struct device_node *np) -+{ -+ return rockchip_i2s_tdm_path_prepare(i2s_tdm, np, 0); -+} -+ -+static int rockchip_i2s_tdm_rx_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm, -+ struct device_node *np) -+{ -+ return rockchip_i2s_tdm_path_prepare(i2s_tdm, np, 1); -+} -+ - static int rockchip_i2s_tdm_probe(struct platform_device *pdev) - { - struct device_node *node = pdev->dev.of_node; -+ struct device_node *cru_node; -+ const struct of_device_id *of_id; - struct rk_i2s_tdm_dev *i2s_tdm; -+ struct snd_soc_dai_driver *soc_dai; - struct resource *res; - void __iomem *regs; - int ret; - int val; - -+ ret = rockchip_i2s_tdm_dai_prepare(pdev, &soc_dai); -+ if (ret < 0) -+ return ret; -+ - i2s_tdm = devm_kzalloc(&pdev->dev, sizeof(*i2s_tdm), GFP_KERNEL); - if (!i2s_tdm) - return -ENOMEM; - - i2s_tdm->dev = &pdev->dev; - -+ of_id = of_match_device(rockchip_i2s_tdm_match, &pdev->dev); -+ if (!of_id || !of_id->data) -+ return -EINVAL; -+ -+ spin_lock_init(&i2s_tdm->lock); -+ i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data; -+ -+ i2s_tdm->bclk_fs = 64; -+ if (!of_property_read_u32(node, "rockchip,bclk-fs", &val)) { -+ if ((val >= 32) && (val % 2 == 0)) -+ i2s_tdm->bclk_fs = val; -+ } -+ -+ i2s_tdm->clk_trcm = I2S_CKR_TRCM_TXRX; -+ if (!of_property_read_u32(node, "rockchip,clk-trcm", &val)) { -+ if (val >= 0 && val <= 2) { -+ i2s_tdm->clk_trcm = val << I2S_CKR_TRCM_SHIFT; -+ if (i2s_tdm->clk_trcm) -+ soc_dai->symmetric_rate = 1; -+ } -+ } -+ -+ if (of_property_read_bool(node, "rockchip,playback-only")) -+ soc_dai->capture.channels_min = 0; -+ else if (of_property_read_bool(node, "rockchip,capture-only")) -+ soc_dai->playback.channels_min = 0; -+ -+ i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); -+ if (IS_ERR(i2s_tdm->grf)) -+ return PTR_ERR(i2s_tdm->grf); -+ -+ if (i2s_tdm->clk_trcm) { -+ cru_node = of_parse_phandle(node, "rockchip,cru", 0); -+ i2s_tdm->cru_base = of_iomap(cru_node, 0); -+ if (!i2s_tdm->cru_base) -+ return -ENOENT; -+ -+ i2s_tdm->tx_reset_id = of_i2s_resetid_get(node, "tx-m"); -+ if (i2s_tdm->tx_reset_id < 0) -+ return -EINVAL; -+ i2s_tdm->rx_reset_id = of_i2s_resetid_get(node, "rx-m"); -+ if (i2s_tdm->rx_reset_id < 0) -+ return -EINVAL; -+ } -+ -+ i2s_tdm->tx_reset = devm_reset_control_get(&pdev->dev, "tx-m"); -+ if (IS_ERR(i2s_tdm->tx_reset)) { -+ ret = PTR_ERR(i2s_tdm->tx_reset); -+ if (ret != -ENOENT) -+ return ret; -+ } -+ -+ i2s_tdm->rx_reset = devm_reset_control_get(&pdev->dev, "rx-m"); -+ if (IS_ERR(i2s_tdm->rx_reset)) { -+ ret = PTR_ERR(i2s_tdm->rx_reset); -+ if (ret != -ENOENT) -+ return ret; -+ } -+ - i2s_tdm->hclk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(i2s_tdm->hclk)) - return PTR_ERR(i2s_tdm->hclk); -@@ -573,6 +1537,29 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) - if (IS_ERR(i2s_tdm->mclk_rx)) - return PTR_ERR(i2s_tdm->mclk_rx); - -+ i2s_tdm->io_multiplex = -+ of_property_read_bool(node, "rockchip,io-multiplex"); -+ -+ i2s_tdm->mclk_calibrate = -+ of_property_read_bool(node, "rockchip,mclk-calibrate"); -+ if (i2s_tdm->mclk_calibrate) { -+ i2s_tdm->mclk_tx_src = devm_clk_get(&pdev->dev, "mclk_tx_src"); -+ if (IS_ERR(i2s_tdm->mclk_tx_src)) -+ return PTR_ERR(i2s_tdm->mclk_tx_src); -+ -+ i2s_tdm->mclk_rx_src = devm_clk_get(&pdev->dev, "mclk_rx_src"); -+ if (IS_ERR(i2s_tdm->mclk_rx_src)) -+ return PTR_ERR(i2s_tdm->mclk_rx_src); -+ -+ i2s_tdm->mclk_root0 = devm_clk_get(&pdev->dev, "mclk_root0"); -+ if (IS_ERR(i2s_tdm->mclk_root0)) -+ return PTR_ERR(i2s_tdm->mclk_root0); -+ -+ i2s_tdm->mclk_root1 = devm_clk_get(&pdev->dev, "mclk_root1"); -+ if (IS_ERR(i2s_tdm->mclk_root1)) -+ return PTR_ERR(i2s_tdm->mclk_root1); -+ } -+ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) -@@ -591,6 +1578,19 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) - i2s_tdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - i2s_tdm->capture_dma_data.maxburst = 8; - -+ ret = rockchip_i2s_tdm_tx_path_prepare(i2s_tdm, node); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "I2S TX path prepare failed: %d\n", ret); -+ return ret; -+ } -+ -+ ret = rockchip_i2s_tdm_rx_path_prepare(i2s_tdm, node); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "I2S RX path prepare failed: %d\n", ret); -+ return ret; -+ } -+ -+ atomic_set(&i2s_tdm->refcount, 0); - dev_set_drvdata(&pdev->dev, i2s_tdm); - - pm_runtime_enable(&pdev->dev); -@@ -600,21 +1600,23 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) - goto err_pm_disable; - } - -- i2s_tdm->bclk_fs = 64; -- if (!of_property_read_u32(node, "rockchip,bclk-fs", &val)) { -- if ((val >= 32) && (val % 2 == 0)) -- i2s_tdm->bclk_fs = val; -- } -+ regmap_update_bits(i2s_tdm->regmap, I2S_CKR, -+ I2S_CKR_TRCM_MASK, i2s_tdm->clk_trcm); -+ -+ if (i2s_tdm->soc_data && i2s_tdm->soc_data->init) -+ i2s_tdm->soc_data->init(&pdev->dev, res->start); - - ret = devm_snd_soc_register_component(&pdev->dev, - &rockchip_i2s_tdm_component, -- &rockchip_i2s_tdm_dai, 1); -+ soc_dai, 1); - - if (ret) { - dev_err(&pdev->dev, "Could not register DAI\n"); - goto err_suspend; - } - -+ if (of_property_read_bool(node, "rockchip,no-dmaengine")) -+ return ret; - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); - if (ret) { - dev_err(&pdev->dev, "Could not register PCM\n"); -diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.h b/sound/soc/rockchip/rockchip_i2s_tdm.h -index 1a28523cfd82..3a69fa276f8f 100644 ---- a/sound/soc/rockchip/rockchip_i2s_tdm.h -+++ b/sound/soc/rockchip/rockchip_i2s_tdm.h -@@ -18,6 +18,9 @@ - * TXCR - * transmit operation control register - */ -+#define I2S_TXCR_PATH_SHIFT(x) (23 + (x) * 2) -+#define I2S_TXCR_PATH_MASK(x) (0x3 << I2S_TXCR_PATH_SHIFT(x)) -+#define I2S_TXCR_PATH(x, v) ((v) << I2S_TXCR_PATH_SHIFT(x)) - #define I2S_TXCR_RCNT_SHIFT 17 - #define I2S_TXCR_RCNT_MASK (0x3f << I2S_TXCR_RCNT_SHIFT) - #define I2S_TXCR_CSR_SHIFT 15 -@@ -41,7 +44,9 @@ - #define I2S_TXCR_TFS_SHIFT 5 - #define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) - #define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) --#define I2S_TXCR_TFS_MASK (1 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_TDM_PCM (2 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_TDM_I2S (3 << I2S_TXCR_TFS_SHIFT) -+#define I2S_TXCR_TFS_MASK (3 << I2S_TXCR_TFS_SHIFT) - #define I2S_TXCR_VDW_SHIFT 0 - #define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) - #define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) -@@ -50,6 +55,9 @@ - * RXCR - * receive operation control register - */ -+#define I2S_RXCR_PATH_SHIFT(x) (17 + (x) * 2) -+#define I2S_RXCR_PATH_MASK(x) (0x3 << I2S_RXCR_PATH_SHIFT(x)) -+#define I2S_RXCR_PATH(x, v) ((v) << I2S_RXCR_PATH_SHIFT(x)) - #define I2S_RXCR_CSR_SHIFT 15 - #define I2S_RXCR_CSR(x) (x << I2S_RXCR_CSR_SHIFT) - #define I2S_RXCR_CSR_MASK (3 << I2S_RXCR_CSR_SHIFT) -@@ -71,7 +79,9 @@ - #define I2S_RXCR_TFS_SHIFT 5 - #define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) - #define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) --#define I2S_RXCR_TFS_MASK (1 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_TDM_PCM (2 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_TDM_I2S (3 << I2S_RXCR_TFS_SHIFT) -+#define I2S_RXCR_TFS_MASK (3 << I2S_RXCR_TFS_SHIFT) - #define I2S_RXCR_VDW_SHIFT 0 - #define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) - #define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) -@@ -213,6 +223,22 @@ - */ - #define I2S_RXDR_MASK (0xff) - -+/* -+ * TDM_CTRL -+ * TDM ctrl register -+ */ -+#define TDM_FSYNC_WIDTH_SEL1_MSK GENMASK(20, 18) -+#define TDM_FSYNC_WIDTH_SEL1(x) ((x - 1) << 18) -+#define TDM_FSYNC_WIDTH_SEL0_MSK BIT(17) -+#define TDM_FSYNC_WIDTH_HALF_FRAME 0 -+#define TDM_FSYNC_WIDTH_ONE_FRAME BIT(17) -+#define TDM_SHIFT_CTRL_MSK GENMASK(16, 14) -+#define TDM_SHIFT_CTRL(x) ((x) << 14) -+#define TDM_SLOT_BIT_WIDTH_MSK GENMASK(13, 9) -+#define TDM_SLOT_BIT_WIDTH(x) ((x - 1) << 9) -+#define TDM_FRAME_WIDTH_MSK GENMASK(8, 0) -+#define TDM_FRAME_WIDTH(x) ((x - 1) << 0) -+ - /* - * CLKDIV - * Mclk div register -@@ -237,11 +263,18 @@ enum { - #define I2S_CHN_6 (2 << I2S_CSR_SHIFT) - #define I2S_CHN_8 (3 << I2S_CSR_SHIFT) - -+/* io direction cfg register */ -+#define I2S_IO_DIRECTION_MASK (7) -+#define I2S_IO_8CH_OUT_2CH_IN (7) -+#define I2S_IO_6CH_OUT_4CH_IN (3) -+#define I2S_IO_4CH_OUT_6CH_IN (1) -+#define I2S_IO_2CH_OUT_8CH_IN (0) -+ - /* I2S REGS */ - #define I2S_TXCR (0x0000) - #define I2S_RXCR (0x0004) - #define I2S_CKR (0x0008) --#define I2S_FIFOLR (0x000c) -+#define I2S_TXFIFOLR (0x000c) - #define I2S_DMACR (0x0010) - #define I2S_INTCR (0x0014) - #define I2S_INTSR (0x0018) -@@ -249,8 +282,107 @@ enum { - #define I2S_CLR (0x0020) - #define I2S_TXDR (0x0024) - #define I2S_RXDR (0x0028) -+#define I2S_RXFIFOLR (0x002c) - #define I2S_TDM_TXCR (0x0030) - #define I2S_TDM_RXCR (0x0034) - #define I2S_CLKDIV (0x0038) - -+/* PX30 GRF CONFIGS*/ -+#define PX30_I2S0_CLK_IN_SRC_MASK GENMASK(13, 12) -+#define PX30_I2S0_CLK_IN_SRC_FROM_TX (0x1 << 12) -+#define PX30_I2S0_CLK_IN_SRC_FROM_RX (0x2 << 12) -+#define PX30_I2S0_MCLK_OUT_SRC_MSK BIT(5) -+#define PX30_I2S0_MCLK_OUT_SRC_FROM_TX BIT(5) -+#define PX30_I2S0_MCLK_OUT_SRC_FROM_RX 0 -+ -+#define PX30_I2S0_CLK_MSK \ -+ (PX30_I2S0_MCLK_OUT_SRC_MSK | \ -+ PX30_I2S0_CLK_IN_SRC_MASK) -+ -+#define PX30_I2S0_CLK_TXONLY \ -+ (PX30_I2S0_MCLK_OUT_SRC_FROM_TX | \ -+ PX30_I2S0_CLK_IN_SRC_FROM_TX | \ -+ (PX30_I2S0_CLK_MSK << 16)) -+ -+#define PX30_I2S0_CLK_RXONLY \ -+ (PX30_I2S0_MCLK_OUT_SRC_FROM_RX | \ -+ PX30_I2S0_CLK_IN_SRC_FROM_RX | \ -+ (PX30_I2S0_CLK_MSK << 16)) -+ -+/* RK1808 GRF CONFIGS*/ -+#define RK1808_I2S0_MCLK_OUT_SRC_MSK BIT(2) -+#define RK1808_I2S0_MCLK_OUT_SRC_FROM_RX BIT(2) -+#define RK1808_I2S0_MCLK_OUT_SRC_FROM_TX 0 -+#define RK1808_I2S0_CLK_IN_SRC_MASK GENMASK(1, 0) -+#define RK1808_I2S0_CLK_IN_SRC_FROM_TX (0x1 << 0) -+#define RK1808_I2S0_CLK_IN_SRC_FROM_RX (0x2 << 0) -+ -+#define RK1808_I2S0_CLK_MSK \ -+ (RK1808_I2S0_MCLK_OUT_SRC_MSK | \ -+ RK1808_I2S0_CLK_IN_SRC_MASK) -+ -+#define RK1808_I2S0_CLK_TXONLY \ -+ (RK1808_I2S0_MCLK_OUT_SRC_FROM_TX | \ -+ RK1808_I2S0_CLK_IN_SRC_FROM_TX | \ -+ (RK1808_I2S0_CLK_MSK << 16)) -+ -+#define RK1808_I2S0_CLK_RXONLY \ -+ (RK1808_I2S0_MCLK_OUT_SRC_FROM_RX | \ -+ RK1808_I2S0_CLK_IN_SRC_FROM_RX | \ -+ (RK1808_I2S0_CLK_MSK << 16)) -+ -+/* RK3308 GRF CONFIGS*/ -+#define RK3308_I2S0_8CH_MCLK_OUT_SRC_MSK BIT(10) -+#define RK3308_I2S0_8CH_MCLK_OUT_SRC_FROM_RX BIT(10) -+#define RK3308_I2S0_8CH_MCLK_OUT_SRC_FROM_TX 0 -+#define RK3308_I2S0_8CH_CLK_IN_RX_SRC_MSK BIT(9) -+#define RK3308_I2S0_8CH_CLK_IN_RX_SRC_FROM_TX BIT(9) -+#define RK3308_I2S0_8CH_CLK_IN_RX_SRC_FROM_RX 0 -+#define RK3308_I2S0_8CH_CLK_IN_TX_SRC_MSK BIT(8) -+#define RK3308_I2S0_8CH_CLK_IN_TX_SRC_FROM_RX BIT(8) -+#define RK3308_I2S0_8CH_CLK_IN_TX_SRC_FROM_TX 0 -+#define RK3308_I2S1_8CH_MCLK_OUT_SRC_MSK BIT(2) -+#define RK3308_I2S1_8CH_MCLK_OUT_SRC_FROM_RX BIT(2) -+#define RK3308_I2S1_8CH_MCLK_OUT_SRC_FROM_TX 0 -+#define RK3308_I2S1_8CH_CLK_IN_RX_SRC_MSK BIT(1) -+#define RK3308_I2S1_8CH_CLK_IN_RX_SRC_FROM_TX BIT(1) -+#define RK3308_I2S1_8CH_CLK_IN_RX_SRC_FROM_RX 0 -+#define RK3308_I2S1_8CH_CLK_IN_TX_SRC_MSK BIT(0) -+#define RK3308_I2S1_8CH_CLK_IN_TX_SRC_FROM_RX BIT(0) -+#define RK3308_I2S1_8CH_CLK_IN_TX_SRC_FROM_TX 0 -+ -+#define RK3308_I2S0_CLK_MSK \ -+ (RK3308_I2S0_8CH_MCLK_OUT_SRC_MSK | \ -+ RK3308_I2S0_8CH_CLK_IN_RX_SRC_MSK | \ -+ RK3308_I2S0_8CH_CLK_IN_TX_SRC_MSK) -+ -+#define RK3308_I2S0_CLK_TXONLY \ -+ (RK3308_I2S0_8CH_MCLK_OUT_SRC_FROM_TX | \ -+ RK3308_I2S0_8CH_CLK_IN_RX_SRC_FROM_TX | \ -+ RK3308_I2S0_8CH_CLK_IN_TX_SRC_FROM_TX | \ -+ (RK3308_I2S0_CLK_MSK << 16)) -+ -+#define RK3308_I2S0_CLK_RXONLY \ -+ (RK3308_I2S0_8CH_MCLK_OUT_SRC_FROM_RX | \ -+ RK3308_I2S0_8CH_CLK_IN_RX_SRC_FROM_RX | \ -+ RK3308_I2S0_8CH_CLK_IN_TX_SRC_FROM_RX | \ -+ (RK3308_I2S0_CLK_MSK << 16)) -+ -+#define RK3308_I2S1_CLK_MSK \ -+ (RK3308_I2S1_8CH_MCLK_OUT_SRC_MSK | \ -+ RK3308_I2S1_8CH_CLK_IN_RX_SRC_MSK | \ -+ RK3308_I2S1_8CH_CLK_IN_TX_SRC_MSK) -+ -+#define RK3308_I2S1_CLK_TXONLY \ -+ (RK3308_I2S1_8CH_MCLK_OUT_SRC_FROM_TX | \ -+ RK3308_I2S1_8CH_CLK_IN_RX_SRC_FROM_TX | \ -+ RK3308_I2S1_8CH_CLK_IN_TX_SRC_FROM_TX | \ -+ (RK3308_I2S1_CLK_MSK << 16)) -+ -+#define RK3308_I2S1_CLK_RXONLY \ -+ (RK3308_I2S1_8CH_MCLK_OUT_SRC_FROM_RX | \ -+ RK3308_I2S1_8CH_CLK_IN_RX_SRC_FROM_RX | \ -+ RK3308_I2S1_8CH_CLK_IN_TX_SRC_FROM_RX | \ -+ (RK3308_I2S1_CLK_MSK << 16)) -+ - #endif /* _ROCKCHIP_I2S_TDM_H */ --- -2.25.1 diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch b/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch deleted file mode 100644 index 1e280ec..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0018-ASoC-codecs-Add-RK3308-internal-codec-driver.patch +++ /dev/null @@ -1,2645 +0,0 @@ -From 76f98b4d0be07417ab9bc4a5669d185299f54cdf Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 17:09:38 +0100 -Subject: [PATCH 18/23] ASoC: codecs: Add RK3308 internal codec driver - -From b9d097610177b7117a09ea74ed00476a2105f169 Mon Sep 17 00:00:00 2001 -From: Xing Zheng -Date: Sun, 11 Mar 2018 11:37:28 +0800 -Subject: [PATCH] ASoC: codecs: Add RK3308 internal codec driver - -This adds support for the RK3308 audio codec. - -Change-Id: Ieccdebaa27f4a46f6de9406046a6e02e20398013 -Signed-off-by: Xing Zheng ---- - sound/soc/codecs/Kconfig | 5 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/rk3308_codec.c | 1604 +++++++++++++++++++++++++++++++ - sound/soc/codecs/rk3308_codec.h | 960 ++++++++++++++++++ - 4 files changed, 2571 insertions(+) - create mode 100644 sound/soc/codecs/rk3308_codec.c - create mode 100644 sound/soc/codecs/rk3308_codec.h - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 030f500f3bc8..1f4675a59014 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -144,6 +144,7 @@ config SND_SOC_ALL_CODECS - imply SND_SOC_PCM5102A - imply SND_SOC_PCM512x_I2C - imply SND_SOC_PCM512x_SPI -+ imply SND_SOC_RK3308 - imply SND_SOC_RK3328 - imply SND_SOC_RT274 - imply SND_SOC_RT286 -@@ -931,6 +932,10 @@ config SND_SOC_PCM512x_SPI - select SND_SOC_PCM512x - select REGMAP_SPI - -+config SND_SOC_RK3308 -+ select REGMAP_MMIO -+ tristate "Rockchip RK3308 CODEC" -+ - config SND_SOC_RK3328 - tristate "Rockchip RK3328 audio CODEC" - select REGMAP_MMIO -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index ddfd07071925..9a35df4862dc 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -148,6 +148,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-pcm512x-objs := pcm512x.o - snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o - snd-soc-pcm512x-spi-objs := pcm512x-spi.o -+snd-soc-rk3308-objs := rk3308_codec.o - snd-soc-rk3328-objs := rk3328_codec.o - snd-soc-rl6231-objs := rl6231.o - snd-soc-rl6347a-objs := rl6347a.o -@@ -437,6 +438,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o - obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o - obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o -+obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o - obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o - obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o - obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -new file mode 100644 -index 000000000000..106f09738dd0 ---- /dev/null -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -0,0 +1,1604 @@ -+/* -+ * rk3308_codec.c -- RK3308 ALSA Soc Audio Driver -+ * -+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "rk3308_codec.h" -+ -+struct rk3308_codec_priv { -+ const struct device *plat_dev; -+ struct device dev; -+ struct reset_control *reset; -+ struct regmap *regmap; -+ struct clk *pclk; -+ struct gpio_desc *spk_ctl_gpio; -+ int adc_ch; /* To select ADCs for channel */ -+ int adc_ch0_using_linein; -+}; -+ -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_gain_tlv, -+ -1800, 150, 2850); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_max_gain_tlv, -+ -1350, 600, 2850); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_min_gain_tlv, -+ -1800, 600, 2400); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_mic_gain_tlv, -+ 0, 600, 3000); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, -+ -1800, 150, 2850); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_gain_tlv, -+ 0, 150, 600); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, -+ -3900, 150, 600); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, -+ -600, 600, 0); -+ -+static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { -+ /* ALC AGC Channel*/ -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Volume", -+ RK3308_ALC_L_DIG_CON03(0), -+ RK3308_ALC_R_DIG_CON03(0), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Volume", -+ RK3308_ALC_L_DIG_CON03(1), -+ RK3308_ALC_R_DIG_CON03(1), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Volume", -+ RK3308_ALC_L_DIG_CON03(2), -+ RK3308_ALC_R_DIG_CON03(2), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Volume", -+ RK3308_ALC_L_DIG_CON03(3), -+ RK3308_ALC_R_DIG_CON03(3), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_NDB_18, -+ RK3308_AGC_PGA_GAIN_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ -+ /* ALC AGC MAX */ -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Max Volume", -+ RK3308_ALC_L_DIG_CON09(0), -+ RK3308_ALC_R_DIG_CON09(0), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Max Volume", -+ RK3308_ALC_L_DIG_CON09(1), -+ RK3308_ALC_R_DIG_CON09(1), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Max Volume", -+ RK3308_ALC_L_DIG_CON09(2), -+ RK3308_ALC_R_DIG_CON09(2), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Max Volume", -+ RK3308_ALC_L_DIG_CON09(3), -+ RK3308_ALC_R_DIG_CON09(3), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -+ RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -+ 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ -+ /* ALC AGC MIN */ -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Min Volume", -+ RK3308_ALC_L_DIG_CON09(0), -+ RK3308_ALC_R_DIG_CON09(0), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Min Volume", -+ RK3308_ALC_L_DIG_CON09(1), -+ RK3308_ALC_R_DIG_CON09(1), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Min Volume", -+ RK3308_ALC_L_DIG_CON09(2), -+ RK3308_ALC_R_DIG_CON09(2), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Min Volume", -+ RK3308_ALC_L_DIG_CON09(3), -+ RK3308_ALC_R_DIG_CON09(3), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_NDB_18, -+ RK3308_AGC_MIN_GAIN_PGA_PDB_24, -+ 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -+ -+ /* ADC MIC */ -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Left Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Right Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Left Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Right Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Left Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Right Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Left Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_0DB, -+ RK3308_ADC_CH1_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Right Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_0DB, -+ RK3308_ADC_CH2_MIC_GAIN_30DB, -+ 0, rk3308_codec_adc_mic_gain_tlv), -+ -+ /* ADC ALC */ -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Left Volume", -+ RK3308_ADC_ANA_CON03(0), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Right Volume", -+ RK3308_ADC_ANA_CON04(0), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Left Volume", -+ RK3308_ADC_ANA_CON03(1), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Right Volume", -+ RK3308_ADC_ANA_CON04(1), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Left Volume", -+ RK3308_ADC_ANA_CON03(2), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Right Volume", -+ RK3308_ADC_ANA_CON04(2), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Left Volume", -+ RK3308_ADC_ANA_CON03(3), -+ RK3308_ADC_CH1_ALC_GAIN_SFT, -+ RK3308_ADC_CH1_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Right Volume", -+ RK3308_ADC_ANA_CON04(3), -+ RK3308_ADC_CH2_ALC_GAIN_SFT, -+ RK3308_ADC_CH2_ALC_GAIN_NDB_18, -+ RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ 0, rk3308_codec_adc_alc_gain_tlv), -+ -+ /* DAC */ -+ SOC_SINGLE_RANGE_TLV("DAC Left Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_GAIN_SFT, -+ RK3308_DAC_L_GAIN_0DB, -+ RK3308_DAC_L_GAIN_PDB_6, -+ 0, rk3308_codec_dac_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("DAC Right Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_R_GAIN_SFT, -+ RK3308_DAC_R_GAIN_0DB, -+ RK3308_DAC_R_GAIN_PDB_6, -+ 0, rk3308_codec_dac_gain_tlv), -+ -+ /* DAC HPOUT */ -+ SOC_SINGLE_RANGE_TLV("DAC HPOUT Left Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_SFT, -+ RK3308_DAC_L_HPOUT_GAIN_NDB_39, -+ RK3308_DAC_L_HPOUT_GAIN_PDB_6, -+ 0, rk3308_codec_dac_hpout_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("DAC HPOUT Right Volume", -+ RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_SFT, -+ RK3308_DAC_R_HPOUT_GAIN_NDB_39, -+ RK3308_DAC_R_HPOUT_GAIN_PDB_6, -+ 0, rk3308_codec_dac_hpout_gain_tlv), -+ -+ /* DAC HPMIX */ -+ SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPMIX_GAIN_SFT, -+ RK3308_DAC_L_HPMIX_GAIN_NDB_6, -+ RK3308_DAC_L_HPMIX_GAIN_0DB, -+ 0, rk3308_codec_dac_hpmix_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("DAC HPMIX Right Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_R_HPMIX_GAIN_SFT, -+ RK3308_DAC_R_HPMIX_GAIN_NDB_6, -+ RK3308_DAC_R_HPMIX_GAIN_0DB, -+ 0, rk3308_codec_dac_hpmix_gain_tlv), -+}; -+ -+static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) -+{ -+ gpiod_direction_output(rk3308->spk_ctl_gpio, on); -+} -+ -+static int rk3308_codec_reset(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ reset_control_assert(rk3308->reset); -+ usleep_range(200, 300); /* estimated value */ -+ reset_control_deassert(rk3308->reset); -+ -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); -+ usleep_range(200, 300); /* estimated value */ -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_SYS_WORK | -+ RK3308_DAC_DIG_WORK | -+ RK3308_ADC_DIG_WORK); -+ -+ return 0; -+} -+ -+static int rk3308_set_bias_level(struct snd_soc_codec *codec, -+ 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: -+ case SND_SOC_BIAS_OFF: -+ break; -+ } -+ -+ snd_soc_codec_force_bias_level(codec, level); -+ -+ return 0; -+} -+ -+static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -+ unsigned int fmt) -+{ -+ struct snd_soc_codec *codec = codec_dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -+ int ch = rk3308->adc_ch; -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; -+ adc_aif2 |= RK3308_ADC_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_MODE_SLAVE; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; -+ adc_aif2 |= RK3308_ADC_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_MODE_MASTER; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_DSP_A: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -+ RK3308_ADC_I2S_LRC_POL_MSK | -+ RK3308_ADC_I2S_MODE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -+ RK3308_ADC_IO_MODE_MSK | -+ RK3308_ADC_MODE_MSK | -+ RK3308_ADC_I2S_BIT_CLK_POL_MSK, -+ adc_aif2); -+ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_LRC_POL_MSK | -+ RK3308_DAC_I2S_MODE_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_IO_MODE_MSK | -+ RK3308_DAC_MODE_MSK | -+ RK3308_DAC_I2S_BIT_CLK_POL_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -+ int ch = rk3308->adc_ch; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 1: -+ adc_aif1 |= RK3308_ADC_I2S_MONO; -+ break; -+ case 2: -+ adc_aif1 |= RK3308_ADC_I2S_STEREO; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_WORK; -+ dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_WORK; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -+ RK3308_ADC_I2S_VALID_LEN_MSK | -+ RK3308_ADC_I2S_LR_MSK | -+ RK3308_ADC_I2S_TYPE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -+ RK3308_ADC_I2S_MSK, -+ adc_aif2); -+ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_VALID_LEN_MSK | -+ RK3308_DAC_I2S_LR_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_I2S_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_digital_mute(struct snd_soc_dai *dai, int mute) -+{ -+ return 0; -+} -+ -+static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 01 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_MSK, -+ RK3308_DAC_CURRENT_EN); -+ -+ /* Step 02 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_MSK | -+ RK3308_DAC_BUF_REF_R_MSK, -+ RK3308_DAC_BUF_REF_L_EN | -+ RK3308_DAC_BUF_REF_R_EN); -+ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_L_MSK | -+ RK3308_DAC_POP_SOUND_R_MSK, -+ RK3308_DAC_POP_SOUND_L_WORK | -+ RK3308_DAC_POP_SOUND_R_WORK); -+ -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN); -+ -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK); -+ -+ /* Step 06 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN); -+ -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN); -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_I2S | -+ RK3308_DAC_R_HPMIX_I2S); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE); -+ -+ /* Step 15 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_GAIN_MSK | -+ RK3308_DAC_R_HPMIX_GAIN_MSK, -+ RK3308_DAC_L_HPMIX_GAIN_0DB | -+ RK3308_DAC_R_HPMIX_GAIN_0DB); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE); -+ -+ /* Step 17 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ RK3308_DAC_L_HPOUT_GAIN_0DB); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ RK3308_DAC_R_HPOUT_GAIN_0DB); -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -+ RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 01 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -+ RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -+ -+ /* -+ * Step 02 -+ * -+ * Note1. In the step2, adjusting the register step by step to the -+ * appropriate value and taking 20ms as time step -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ RK3308_DAC_L_HPOUT_GAIN_NDB_39); -+ -+ /* Step 02 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ RK3308_DAC_R_HPOUT_GAIN_NDB_39); -+ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_MUTE | -+ RK3308_DAC_R_HPMIX_MUTE); -+ -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_NONE | -+ RK3308_DAC_R_HPMIX_NONE); -+ -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_MUTE | -+ RK3308_DAC_R_HPOUT_MUTE); -+ -+ /* Step 06 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_INIT | RK3308_DAC_R_DAC_INIT); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_DIS | RK3308_DAC_R_HPOUT_DIS); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_MUTE | -+ RK3308_DAC_R_LINEOUT_MUTE); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_DIS | RK3308_DAC_R_LINEOUT_DIS); -+ -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_DIS | RK3308_DAC_R_HPMIX_DIS); -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_DIS | RK3308_DAC_R_DAC_DIS); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_DIS | RK3308_DAC_R_CLK_DIS); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_DIS | RK3308_DAC_R_REF_DIS); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_L_MSK | -+ RK3308_DAC_POP_SOUND_R_MSK, -+ RK3308_DAC_POP_SOUND_L_INIT | -+ RK3308_DAC_POP_SOUND_R_INIT); -+ -+ /* Step 15 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_EN | RK3308_DAC_BUF_REF_R_EN, -+ RK3308_DAC_BUF_REF_L_DIS | RK3308_DAC_BUF_REF_R_DIS); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_EN, -+ RK3308_DAC_CURRENT_DIS); -+ -+ /* Step 17 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_INIT | RK3308_DAC_R_HPOUT_INIT); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_INIT | RK3308_DAC_R_HPMIX_INIT); -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_GAIN_MSK | -+ RK3308_DAC_R_HPMIX_GAIN_MSK, -+ RK3308_DAC_L_HPMIX_GAIN_NDB_6 | -+ RK3308_DAC_R_HPMIX_GAIN_NDB_6); -+ -+ /* -+ * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -+ * is set to 0x1, add the steps from the section Disable DAC -+ * Configuration Standard Usage Flow after complete the step 19 -+ */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_on(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ /* 1. Supply the power of digital part and reset the Audio Codec */ -+ /* Do nothing */ -+ -+ /* -+ * 2. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] -+ * to 0x1, to setup dc voltage of the DAC channel output -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_L_MSK, RK3308_DAC_POP_SOUND_L_INIT); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_POP_SOUND_R_MSK, RK3308_DAC_POP_SOUND_R_INIT); -+ -+ /* -+ * 3. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 -+ * -+ * Note: Only the reg (ADC_ANA_CON10+0x0)[6:0] represent the control -+ * signal to select current to pre-charge/dis_charge -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ -+ /* 4. Supply the power of the analog part(AVDD,AVDDRV) */ -+ -+ /* -+ * 5. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup -+ * reference voltage -+ * -+ * Note: Only the reg (ADC_ANA_CON10+0x0)[7] represent the enable -+ * signal of reference voltage module -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); -+ -+ /* -+ * 6. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to -+ * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to -+ * 0x7f directly. The suggestion slot time of the step is 20ms. -+ */ -+ mdelay(20); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_DONT_SEL_ALL); -+ -+ /* 7. Wait until the voltage of VCM keeps stable at the AVDD/2 */ -+ usleep_range(200, 300); /* estimated value */ -+ -+ /* -+ * 8. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the -+ * appropriate value(expect 0x0) for reducing power. -+ */ -+ -+ /* TODO: choose an appropriate charge value */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_off(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ /* -+ * 1. Keep the power on and disable the DAC and ADC path according to -+ * the section power on configuration standard usage flow. -+ */ -+ -+ /* 2. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ -+ /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, RK3308_ADC_REF_DIS); -+ -+ /* -+ * 4.Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f -+ * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f -+ * directly. The suggestion slot time of the step is 20ms -+ */ -+ mdelay(20); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_DONT_SEL_ALL); -+ -+ /* 5. Wait until the voltage of VCM keeps stable at the AGND */ -+ usleep_range(200, 300); /* estimated value */ -+ -+ /* 6. Power off the analog power supply */ -+ /* 7. Power off the digital power supply */ -+ -+ /* Do something via hardware */ -+ -+ return 0; -+} -+ -+static int check_micbias(int micbias) -+{ -+ switch (micbias) { -+ case RK3308_ADC_MICBIAS_VOLT_0_85: -+ case RK3308_ADC_MICBIAS_VOLT_0_8: -+ case RK3308_ADC_MICBIAS_VOLT_0_75: -+ case RK3308_ADC_MICBIAS_VOLT_0_7: -+ case RK3308_ADC_MICBIAS_VOLT_0_65: -+ case RK3308_ADC_MICBIAS_VOLT_0_6: -+ case RK3308_ADC_MICBIAS_VOLT_0_55: -+ case RK3308_ADC_MICBIAS_VOLT_0_5: -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -+ int micbias) -+{ -+ int ch = rk3308->adc_ch; -+ int ret; -+ -+ if (ch != 1 && ch != 2) { -+ dev_err(rk3308->plat_dev, -+ "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -+ __func__, ch); -+ return -EINVAL; -+ } -+ -+ /* 1. Power up the ACODEC and keep the AVDDH stable */ -+ -+ /* 2. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ -+ ret = check_micbias(micbias); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", -+ micbias); -+ return ret; -+ } -+ -+ /* -+ * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range -+ * control signal of MICBIAS voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -+ micbias); -+ -+ /* 3. Wait until the VCMH keep stable */ -+ usleep_range(200, 300); /* estimated value */ -+ -+ /* 4. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_EN); -+ -+ /* -+ * 5. Configure the (ADC_ANA_CON7+0x40)[3] or (ADC_ANA_CON7+0x80)[3] -+ * to 0x1. -+ * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and -+ * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 -+ */ -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_EN); -+ -+ return 0; -+} -+ -+static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ if (ch != 1 && ch != 2) { -+ dev_err(rk3308->plat_dev, -+ "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -+ __func__, ch); -+ return -EINVAL; -+ } -+ -+ /* 1. Enable the MICBIAS and keep the Audio Codec stable */ -+ /* Do nothing */ -+ -+ /* -+ * 2. Configure the (ADC_ANA_CON7+0x40)[3] or -+ * (ADC_ANA_CON7+0x80)[3] to 0x0 -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_DIS); -+ -+ /* 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set he max level and min level of the ALC need to control. -+ * -+ * These values are estimated -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -+ RK3308_AGC_LO_8BITS_AGC_MIN_MSK, -+ 0x16); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -+ RK3308_AGC_HI_8BITS_AGC_MIN_MSK, -+ 0x40); -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -+ RK3308_AGC_LO_8BITS_AGC_MAX_MSK, -+ 0x26); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -+ RK3308_AGC_HI_8BITS_AGC_MAX_MSK, -+ 0x40); -+ -+ /* -+ * 2. Set ACODEC_ALC_DIG_CON4[2:0] according to the sample rate -+ * -+ * By default is 44.1KHz for sample. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(ch), -+ RK3308_AGC_APPROX_RATE_MSK, -+ RK3308_AGC_APPROX_RATE_44_1K); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(ch), -+ RK3308_AGC_APPROX_RATE_MSK, -+ RK3308_AGC_APPROX_RATE_44_1K); -+ -+ /* 3. Set ACODEC_ALC_DIG_CON9[6] to 0x1, to enable the ALC module */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ -+ /* -+ * 4. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -+ * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -+ * to 0x3, to enable the ALC module to control the gain of PGA. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_EN | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); -+ -+ /* -+ * 5.Observe the current ALC output gain by reading -+ * ACODEC_ALC_DIG_CON12[4:0] -+ * -+ * The default GAIN is 0x0c -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON12(ch), -+ RK3308_AGC_GAIN_MSK, -+ 0x0c); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON12(ch), -+ RK3308_AGC_GAIN_MSK, -+ 0x0c); -+ -+ return 0; -+} -+ -+static int rk3308_codec_alc_disable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set ACODEC_ALC_DIG_CON9[6] to 0x0, to disable the ALC module, -+ * then the ALC output gain will keep to the last value -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -+ * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -+ * to 0x0, to disable the ALC module to control the gain of PGA. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS | -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int adc_aif1 = 0, adc_aif2 = 0; -+ unsigned int agc_func_en; -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], -+ * to select the line-in or microphone as input of ADC -+ * -+ * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, -+ * ADC6, ADC7, and ADC8 -+ */ -+ if (ch == 0) { -+ if (rk3308->adc_ch0_using_linein) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH1_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_LINEIN); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH2_IN_LINEIN); -+ } else { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH1_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_MIC); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH2_IN_MIC); -+ } -+ } -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON0[7:0] to 0xff, to end the mute station -+ * of ADC, to enable the MIC module, to enable the reference voltage -+ * buffer, and to end the initialization of MIC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -+ RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -+ RK3308_ADC_CH1_CH2_MIC_ALL); -+ -+ /* -+ * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source -+ * of audio -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_EN); -+ -+ /* -+ * 4. Set ACODEC_ADC_ANA_CON2[7:0] to 0x77, to enable the ALC module, -+ * to enable the zero-crossing detection function, and to end the -+ * initialization of ALC -+ * -+ * Note2. Please set ACODEC_ADC_ANA_CON2[7:0] to 0x33 in step4 -+ * if the AGC function is closed -+ */ -+ -+ adc_aif1 = RK3308_ADC_CH1_ALC_EN | RK3308_ADC_CH1_ALC_WORK; -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -+ if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -+ adc_aif1 |= RK3308_ADC_CH1_ZEROCROSS_DET_EN; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH1_ALC_ZC_MSK, -+ adc_aif1); -+ -+ adc_aif2 = RK3308_ADC_CH2_ALC_EN | RK3308_ADC_CH2_ALC_WORK; -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -+ if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -+ adc_aif2 |= RK3308_ADC_CH2_ZEROCROSS_DET_EN; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH2_ALC_ZC_MSK, -+ adc_aif2); -+ -+ /* -+ * 5. Set ACODEC_ADC_ANA_CON5[7:0] to 0x77, to enable the clock and -+ * ADC module, and to end the initialization of ADC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH1_ADC_CLK_MSK, -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH1_ADC_WORK); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH2_ADC_CLK_MSK, -+ RK3308_ADC_CH2_CLK_EN | -+ RK3308_ADC_CH2_ADC_EN | -+ RK3308_ADC_CH2_ADC_WORK); -+ -+ /* -+ * 6. Set ACODEC_ADC_ANA_CON1[5:4] and ACODEC_ADC_ANA_CON1[1:0], -+ * to select the gain of the MIC -+ * -+ * By default is 0db. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH1_MIC_GAIN_MSK, -+ RK3308_ADC_CH1_MIC_GAIN_0DB); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH2_MIC_GAIN_MSK, -+ RK3308_ADC_CH2_MIC_GAIN_0DB); -+ -+ /* -+ * 7.Set ACODEC_ADC_ANA_CON3[4:0] and ACODEC_ADC_ANA_CON4[3:0] to -+ * select the gain of ALC -+ * -+ * By default is 0db. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(ch), -+ RK3308_ADC_CH1_ALC_GAIN_MSK, -+ RK3308_ADC_CH1_ALC_GAIN_0DB); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(ch), -+ RK3308_ADC_CH2_ALC_GAIN_MSK, -+ RK3308_ADC_CH2_ALC_GAIN_0DB); -+ -+ /* 8.Begin recording */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308) -+{ -+ int ch = rk3308->adc_ch; -+ -+ /* -+ * 1. Set ACODEC_ADC_ANA_CON2[7:0] to 0x0, to disable the ALC module, -+ * to disable the zero-crossing detection function, and to begin the -+ * initialization of ALC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH1_ALC_ZC_MSK, -+ 0); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -+ RK3308_ADC_CH2_ALC_ZC_MSK, -+ 0); -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON5[7:0] to 0x0, to disable the clock and -+ * ADC module, and to begin the initialization of ADC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH1_ADC_CLK_MSK, -+ 0); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -+ RK3308_ADC_CH2_ADC_CLK_MSK, -+ 0); -+ -+ /* -+ * 3. Set ACODEC_ADC_ANA_CON0[7:0] to 0x88, to disable the MIC module, -+ * to disable the reference voltage buffer, and to begin the -+ * initialization of MIC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -+ RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -+ RK3308_ADC_CH1_MIC_UNMUTE | -+ RK3308_ADC_CH2_MIC_UNMUTE); -+ -+ /* -+ * 4. Set ACODEC_ADC_ANA_CON6[0] to 0x0, to disable the current -+ * source of audio -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_capture(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_alc_enable(rk3308); -+ rk3308_codec_adc_ana_enable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_capture(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_alc_disable(rk3308); -+ rk3308_codec_adc_ana_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_playback(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_dac_enable(rk3308); -+ rk3308_speaker_ctl(rk3308, 1); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_playback(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_speaker_ctl(rk3308, 0); -+ rk3308_codec_dac_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_pcm_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ int ret = 0; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ ret = rk3308_codec_open_playback(codec); -+ else -+ ret = rk3308_codec_open_capture(codec); -+ -+ return ret; -+} -+ -+static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ rk3308_codec_close_playback(codec); -+ else -+ rk3308_codec_close_capture(codec); -+} -+ -+static struct snd_soc_dai_ops rk3308_dai_ops = { -+ .hw_params = rk3308_hw_params, -+ .set_fmt = rk3308_set_dai_fmt, -+ .digital_mute = rk3308_digital_mute, -+ .startup = rk3308_pcm_startup, -+ .shutdown = rk3308_pcm_shutdown, -+}; -+ -+static struct snd_soc_dai_driver rk3308_dai[] = { -+ { -+ .name = "rk3308-hifi", -+ .id = RK3308_HIFI, -+ .playback = { -+ .stream_name = "HiFi Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_96000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "HiFi Capture", -+ .channels_min = 1, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_96000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rk3308_dai_ops, -+ }, -+}; -+ -+static int rk3308_suspend(struct snd_soc_codec *codec) -+{ -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ -+ return 0; -+} -+ -+static int rk3308_resume(struct snd_soc_codec *codec) -+{ -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ -+ return 0; -+} -+ -+static int rk3308_probe(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_codec_reset(codec); -+ rk3308_codec_power_on(codec); -+ -+ rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_7); -+ -+ return 0; -+} -+ -+static int rk3308_remove(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_speaker_ctl(rk3308, 0); -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308_codec_power_off(codec); -+ -+ return 0; -+} -+ -+static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -+ .probe = rk3308_probe, -+ .remove = rk3308_remove, -+ .suspend = rk3308_suspend, -+ .resume = rk3308_resume, -+ .set_bias_level = rk3308_set_bias_level, -+ .controls = rk3308_codec_dapm_controls, -+ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+}; -+ -+static const struct reg_default rk3308_codec_reg_defaults[] = { -+ { RK3308_GLB_CON, 0x07 }, -+}; -+ -+static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) -+{ -+ /* All registers can be read / write */ -+ return true; -+} -+ -+static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case RK3308_GLB_CON: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static const struct regmap_config rk3308_codec_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = RK3308_DAC_ANA_CON13, -+ .writeable_reg = rk3308_codec_write_read_reg, -+ .readable_reg = rk3308_codec_write_read_reg, -+ .volatile_reg = rk3308_codec_volatile_reg, -+ .reg_defaults = rk3308_codec_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), -+ .cache_type = REGCACHE_FLAT, -+}; -+ -+static ssize_t adc_ch_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ -+ return sprintf(buf, "adc_ch: %d\n", rk3308->adc_ch); -+} -+ -+static ssize_t adc_ch_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long ch; -+ int ret = kstrtoul(buf, 10, &ch); -+ -+ if (ret < 0 || ch > 4) { -+ dev_err(dev, "Invalid ch: %ld, ret: %d\n", ch, ret); -+ return -EINVAL; -+ } -+ -+ rk3308->adc_ch = ch; -+ -+ dev_info(dev, "Store ch: %d\n", rk3308->adc_ch); -+ -+ return count; -+} -+ -+static const struct device_attribute adc_ch_attrs[] = { -+ __ATTR(adc_ch, 0644, adc_ch_show, adc_ch_store), -+}; -+ -+static void rk3308_codec_device_release(struct device *dev) -+{ -+ /* Do nothing */ -+} -+ -+static int rk3308_codec_sysfs_init(struct platform_device *pdev, -+ struct rk3308_codec_priv *rk3308) -+{ -+ struct device *dev = &rk3308->dev; -+ int i; -+ -+ dev->release = rk3308_codec_device_release; -+ dev->parent = &pdev->dev; -+ set_dev_node(dev, dev_to_node(&pdev->dev)); -+ dev_set_name(dev, "rk3308-acodec-dev"); -+ -+ if (device_register(dev)) { -+ dev_err(&pdev->dev, -+ "Register 'rk3308-acodec-dev' failed\n"); -+ dev->parent = NULL; -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(adc_ch_attrs); i++) { -+ if (device_create_file(dev, &adc_ch_attrs[i])) { -+ dev_err(&pdev->dev, -+ "Create 'rk3308-acodec-dev' attr failed\n"); -+ device_unregister(dev); -+ return -ENOMEM; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_platform_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct rk3308_codec_priv *rk3308; -+ struct resource *res; -+ void __iomem *base; -+ int ret = 0; -+ struct regmap *grf; -+ -+ grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); -+ if (IS_ERR(grf)) { -+ dev_err(&pdev->dev, -+ "Missing 'rockchip,grf' property\n"); -+ return PTR_ERR(grf); -+ } -+ -+ rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); -+ if (!rk3308) -+ return -ENOMEM; -+ -+ ret = rk3308_codec_sysfs_init(pdev, rk3308); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Sysfs init failed\n"); -+ return ret; -+ } -+ -+ rk3308->plat_dev = &pdev->dev; -+ -+ rk3308->reset = devm_reset_control_get(&pdev->dev, "acodec-reset"); -+ if (IS_ERR(rk3308->reset)) { -+ ret = PTR_ERR(rk3308->reset); -+ if (ret != -ENOENT) -+ return ret; -+ -+ dev_dbg(&pdev->dev, "No reset control found\n"); -+ rk3308->reset = NULL; -+ } -+ -+ /* GPIO0_A5 control speaker on RK3308 EVB */ -+ rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk_ctl", -+ GPIOD_OUT_HIGH); -+ if (IS_ERR(rk3308->spk_ctl_gpio)) { -+ ret = PTR_ERR(rk3308->spk_ctl_gpio); -+ dev_err(&pdev->dev, "Unable to claim gpio spk_ctl\n"); -+ return ret; -+ } -+ -+ rk3308->pclk = devm_clk_get(&pdev->dev, "acodec"); -+ if (IS_ERR(rk3308->pclk)) { -+ dev_err(&pdev->dev, "Can't get acodec pclk\n"); -+ return PTR_ERR(rk3308->pclk); -+ } -+ -+ ret = clk_prepare_enable(rk3308->pclk); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret); -+ return ret; -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) { -+ ret = PTR_ERR(base); -+ dev_err(&pdev->dev, "Failed to ioremap resource\n"); -+ goto failed; -+ } -+ -+ rk3308->regmap = devm_regmap_init_mmio(&pdev->dev, base, -+ &rk3308_codec_regmap_config); -+ if (IS_ERR(rk3308->regmap)) { -+ ret = PTR_ERR(rk3308->regmap); -+ dev_err(&pdev->dev, "Failed to regmap mmio\n"); -+ goto failed; -+ } -+ -+ platform_set_drvdata(pdev, rk3308); -+ -+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3308, -+ rk3308_dai, ARRAY_SIZE(rk3308_dai)); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); -+ goto failed; -+ } -+ -+ return ret; -+ -+failed: -+ clk_disable_unprepare(rk3308->pclk); -+ -+ return ret; -+} -+ -+static int rk3308_platform_remove(struct platform_device *pdev) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ (struct rk3308_codec_priv *)platform_get_drvdata(pdev); -+ -+ clk_disable_unprepare(rk3308->pclk); -+ snd_soc_unregister_codec(&pdev->dev); -+ -+ return 0; -+} -+ -+static const struct of_device_id rk3308codec_of_match[] = { -+ { .compatible = "rockchip,rk3308-codec", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rk3308codec_of_match); -+ -+static struct platform_driver rk3308_codec_driver = { -+ .driver = { -+ .name = "rk3308-acodec", -+ .of_match_table = of_match_ptr(rk3308codec_of_match), -+ }, -+ .probe = rk3308_platform_probe, -+ .remove = rk3308_platform_remove, -+}; -+module_platform_driver(rk3308_codec_driver); -+ -+MODULE_AUTHOR("Xing Zheng "); -+MODULE_DESCRIPTION("ASoC RK3308 Codec Driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h -new file mode 100644 -index 000000000000..6cfa69157785 ---- /dev/null -+++ b/sound/soc/codecs/rk3308_codec.h -@@ -0,0 +1,960 @@ -+/* -+ * rk3308_codec.h -- RK3308 ALSA Soc Audio Driver -+ * -+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#ifndef __RK3308_CODEC_H__ -+#define __RK3308_CODEC_H__ -+ -+#define ACODEC_RESET_CTL 0x00 /* REG 0x00 */ -+ -+/* ADC DIGITAL REGISTERS */ -+#define ACODEC_ADC_I2S_CTL0 0x04 /* REG 0x01 */ -+#define ACODEC_ADC_I2S_CTL1 0x08 /* REG 0x02 */ -+#define ACODEC_ADC_BIST_MODE_SEL 0x0c /* REG 0x03 */ -+/* Resevred REG 0x04 ~ 0x06 */ -+#define ACODEC_ADC_DATA_PATH 0x1c /* REG 0x07 */ -+/* Resevred REG 0x08 ~ 0x0f */ -+ -+/* REG 0x10 ~ 0x1c are used to configure AGC of Left channel (ALC1) */ -+#define ACODEC_ADC_PGA_AGC_L_CTL0 0x40 /* REG 0x10 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL1 0x44 /* REG 0x11 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL2 0x48 /* REG 0x12 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL3 0x4c /* REG 0x13 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL4 0x50 /* REG 0x14 */ -+#define ACODEC_ADC_PGA_AGC_L_LO_MAX 0x54 /* REG 0x15 */ -+#define ACODEC_ADC_PGA_AGC_L_HI_MAX 0x58 /* REG 0x16 */ -+#define ACODEC_ADC_PGA_AGC_L_LO_MIN 0x5c /* REG 0x17 */ -+#define ACODEC_ADC_PGA_AGC_L_HI_MIN 0x60 /* REG 0x18 */ -+#define ACODEC_ADC_PGA_AGC_L_CTL5 0x64 /* REG 0x19 */ -+/* Resevred REG 0x1a ~ 0x1b */ -+#define ACODEC_ADC_AGC_L_RO_GAIN 0x70 /* REG 0x1c */ -+ -+/* REG 0x20 ~ 0x2c are used to configure AGC of Right channel (ALC2) */ -+#define ACODEC_ADC_PGA_AGC_R_CTL0 0x80 /* REG 0x20 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL1 0x84 /* REG 0x21 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL2 0x88 /* REG 0x22 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL3 0x8c /* REG 0x23 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL4 0x90 /* REG 0x24 */ -+#define ACODEC_ADC_PGA_AGC_R_LO_MAX 0x94 /* REG 0x25 */ -+#define ACODEC_ADC_PGA_AGC_R_HI_MAX 0x98 /* REG 0x26 */ -+#define ACODEC_ADC_PGA_AGC_R_LO_MIN 0x9c /* REG 0x27 */ -+#define ACODEC_ADC_PGA_AGC_R_HI_MIN 0xa0 /* REG 0x28 */ -+#define ACODEC_ADC_PGA_AGC_R_CTL5 0xa4 /* REG 0x29 */ -+/* Resevred REG 0x2a ~ 0x2b */ -+#define ACODEC_ADC_AGC_R_RO_GAIN 0xb0 /* REG 0x2c */ -+ -+/* DAC DIGITAL REGISTERS */ -+#define ACODEC_DAC_I2S_CTL0 0x04 /* REG 0x01 */ -+#define ACODEC_DAC_I2S_CTL1 0x08 /* REG 0x02 */ -+#define ACODEC_DAC_BIST_MODE_SEL 0x0c /* REG 0x03 */ -+/* Resevred REG 0x04 */ -+#define ACODEC_DAC_DATA_SEL 0x14 /* REG 0x05 */ -+/* Resevred REG 0x06 ~ 0x09 */ -+#define ACODEC_DAC_DATA_HI 0x28 /* REG 0x0a */ -+#define ACODEC_DAC_DATA_LO 0x2c /* REG 0x0b */ -+/* Resevred REG 0x0c ~ 0x0f */ -+ -+/* ADC ANALOG REGISTERS */ -+#define ACODEC_ADC_ANA_MIC_CTL 0x00 /* REG 0x00 */ -+#define ACODEC_ADC_ANA_MIC_GAIN 0x04 /* REG 0x01 */ -+#define ACODEC_ADC_ANA_ALC_CTL 0x08 /* REG 0x02 */ -+#define ACODEC_ADC_ANA_ALC_GAIN1 0x0c /* REG 0x03 */ -+#define ACODEC_ADC_ANA_ALC_GAIN2 0x10 /* REG 0x04 */ -+#define ACODEC_ADC_ANA_CTL0 0x14 /* REG 0x05 */ -+#define ACODEC_ADC_ANA_CTL1 0x18 /* REG 0x06 */ -+#define ACODEC_ADC_ANA_CTL2 0x1c /* REG 0x07 */ -+#define ACODEC_ADC_ANA_CTL3 0x20 /* REG 0x08 */ -+/* Resevred REG 0x09 */ -+#define ACODEC_ADC_ANA_CTL4 0x28 /* REG 0x0a */ -+#define ACODEC_ADC_ANA_ALC_PGA 0x2c /* REG 0x0b */ -+/* Resevred REG 0x0c ~ 0x0f */ -+ -+/* DAC ANALOG REGISTERS */ -+#define ACODEC_DAC_ANA_CTL0 0x00 /* REG 0x00 */ -+#define ACODEC_DAC_ANA_POP_VOLT 0x04 /* REG 0x01 */ -+#define ACODEC_DAC_ANA_CTL1 0x08 /* REG 0x02 */ -+#define ACODEC_DAC_ANA_HPOUT 0x0c /* REG 0x03 */ -+#define ACODEC_DAC_ANA_LINEOUT 0x10 /* REG 0x04 */ -+#define ACODEC_DAC_ANA_L_HPOUT_GAIN 0x14 /* REG 0x05 */ -+#define ACODEC_DAC_ANA_R_HPOUT_GAIN 0x18 /* REG 0x06 */ -+/* Resevred REG 0x07 ~ 0x0b */ -+#define ACODEC_DAC_ANA_HPMIX_CTL0 0x30 /* REG 0x0c */ -+#define ACODEC_DAC_ANA_HPMIX_CTL1 0x34 /* REG 0x0d */ -+/* Resevred REG 0x0e ~ 0x0f */ -+ -+/* -+ * These registers are referenced by codec driver -+ */ -+ -+#define RK3308_GLB_CON ACODEC_RESET_CTL -+ -+/* ADC DIGITAL REGISTERS */ -+ -+/* -+ * The ADC chanel are 0 ~ 3, that control: -+ * -+ * CH0: left_0(ADC1) and right_0(ADC2) -+ * CH1: left_1(ADC3) and right_1(ADC4) -+ * CH2: left_2(ADC5) and right_2(ADC6) -+ * CH3: left_3(ADC7) and right_3(ADC8) -+ */ -+#define RK3308_ADC_DIG_OFFSET(ch) ((ch & 0x3) * 0xc0 + 0x0) -+ -+#define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL0) -+#define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL1) -+#define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_BIST_MODE_SEL) -+#define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_DATA_PATH) -+ -+#define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL0) -+#define RK3308_ALC_L_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL1) -+#define RK3308_ALC_L_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL2) -+#define RK3308_ALC_L_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL3) -+#define RK3308_ALC_L_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL4) -+#define RK3308_ALC_L_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_LO_MAX) -+#define RK3308_ALC_L_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_HI_MAX) -+#define RK3308_ALC_L_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_LO_MIN) -+#define RK3308_ALC_L_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_HI_MIN) -+#define RK3308_ALC_L_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL5) -+#define RK3308_ALC_L_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_AGC_L_RO_GAIN) -+ -+#define RK3308_ALC_R_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL0) -+#define RK3308_ALC_R_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL1) -+#define RK3308_ALC_R_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL2) -+#define RK3308_ALC_R_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL3) -+#define RK3308_ALC_R_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL4) -+#define RK3308_ALC_R_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_LO_MAX) -+#define RK3308_ALC_R_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_HI_MAX) -+#define RK3308_ALC_R_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_LO_MIN) -+#define RK3308_ALC_R_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_HI_MIN) -+#define RK3308_ALC_R_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL5) -+#define RK3308_ALC_R_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_AGC_R_RO_GAIN) -+ -+/* DAC DIGITAL REGISTERS */ -+#define RK3308_DAC_DIG_OFFSET 0x300 -+ -+#define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL0) -+#define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL1) -+#define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_BIST_MODE_SEL) -+#define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_SEL) -+#define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_HI) -+#define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_LO) -+ -+/* ADC ANALOG REGISTERS */ -+/* -+ * The ADC chanel are 0 ~ 3, that control: -+ * -+ * CH0: left_0(ADC1) and right_0(ADC2) -+ * CH1: left_1(ADC3) and right_1(ADC4) -+ * CH2: left_2(ADC5) and right_2(ADC6) -+ * CH3: left_3(ADC7) and right_3(ADC8) -+ */ -+#define RK3308_ADC_ANA_OFFSET(ch) ((ch & 0x3) * 0x40 + 0x340) -+ -+#define RK3308_ADC_ANA_CON00(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_MIC_CTL) -+#define RK3308_ADC_ANA_CON01(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_MIC_GAIN) -+#define RK3308_ADC_ANA_CON02(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_CTL) -+#define RK3308_ADC_ANA_CON03(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_GAIN1) -+#define RK3308_ADC_ANA_CON04(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_GAIN2) -+#define RK3308_ADC_ANA_CON05(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL0) -+#define RK3308_ADC_ANA_CON06(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL1) -+#define RK3308_ADC_ANA_CON07(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL2) -+#define RK3308_ADC_ANA_CON08(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL3) -+#define RK3308_ADC_ANA_CON10(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL4) -+#define RK3308_ADC_ANA_CON11(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_PGA) -+ -+/* DAC ANALOG REGISTERS */ -+#define RK3308_DAC_ANA_OFFSET 0x440 -+ -+#define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL0) -+#define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_POP_VOLT) -+#define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL1) -+#define RK3308_DAC_ANA_CON03 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPOUT) -+#define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT) -+#define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_L_HPOUT_GAIN) -+#define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_R_HPOUT_GAIN) -+#define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL0) -+#define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL1) -+ -+/* -+ * These are the bits for registers -+ */ -+ -+/* RK3308_GLB_CON - REG: 0x0000 */ -+#define RK3308_ADC_BIST_WORK (1 << 7) -+#define RK3308_ADC_BIST_RESET (0 << 7) -+#define RK3308_DAC_BIST_WORK (1 << 6) -+#define RK3308_DAC_BIST_RESET (0 << 6) -+#define RK3308_CODEC_RST_MSK (0x7 << 0) -+#define RK3308_ADC_DIG_WORK (1 << 2) -+#define RK3308_ADC_DIG_RESET (0 << 2) -+#define RK3308_DAC_DIG_WORK (1 << 1) -+#define RK3308_DAC_DIG_RESET (0 << 1) -+#define RK3308_SYS_WORK (1 << 0) -+#define RK3308_SYS_RESET (0 << 0) -+ -+/* RK3308_ADC_DIG_CON01 - REG: 0x0004 */ -+#define RK3308_ADC_I2S_LRC_POL_MSK (1 << 0) -+#define RK3308_ADC_I2S_LRC_POL_REVERSAL (1 << 0) -+#define RK3308_ADC_I2S_LRC_POL_NORMAL (0 << 0) -+#define RK3308_ADC_I2S_VALID_LEN_SFT 5 -+#define RK3308_ADC_I2S_VALID_LEN_MSK (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_32BITS (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_24BITS (0x2 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_20BITS (0x1 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_VALID_LEN_16BITS (0x0 << RK3308_ADC_I2S_VALID_LEN_SFT) -+#define RK3308_ADC_I2S_MODE_SFT 3 -+#define RK3308_ADC_I2S_MODE_MSK (0x3 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_PCM (0x3 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_I2S (0x2 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_LJ (0x1 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_MODE_RJ (0x0 << RK3308_ADC_I2S_MODE_SFT) -+#define RK3308_ADC_I2S_LR_MSK (1 << 1) -+#define RK3308_ADC_I2S_LR_SWAP (1 << 1) -+#define RK3308_ADC_I2S_LR_NORMAL (0 << 1) -+#define RK3308_ADC_I2S_TYPE_MSK (1 << 0) -+#define RK3308_ADC_I2S_MONO (1 << 0) -+#define RK3308_ADC_I2S_STEREO (0 << 0) -+ -+/* RK3308_ADC_DIG_CON02 - REG: 0x0008 */ -+#define RK3308_ADC_IO_MODE_MSK (1 << 5) -+#define RK3308_ADC_IO_MODE_MASTER (1 << 5) -+#define RK3308_ADC_IO_MODE_SLAVE (0 << 5) -+#define RK3308_ADC_MODE_MSK (1 << 4) -+#define RK3308_ADC_MODE_MASTER (1 << 4) -+#define RK3308_ADC_MODE_SLAVE (0 << 4) -+#define RK3308_ADC_I2S_FRAME_LEN_SFT 2 -+#define RK3308_ADC_I2S_FRAME_LEN_MSK (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_32BITS (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_24BITS (0x2 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_20BITS (0x1 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_FRAME_16BITS (0x0 << RK3308_ADC_I2S_FRAME_LEN_SFT) -+#define RK3308_ADC_I2S_MSK (0x1 << 1) -+#define RK3308_ADC_I2S_WORK (0x1 << 1) -+#define RK3308_ADC_I2S_RESET (0x0 << 1) -+#define RK3308_ADC_I2S_BIT_CLK_POL_MSK (0x1 << 0) -+#define RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0) -+#define RK3308_ADC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0) -+ -+/* RK3308_ADC_DIG_CON03 - REG: 0x000c */ -+#define RK3308_ADC_L_CH_BIST_SFT 2 -+#define RK3308_ADC_L_CH_BIST_MSK (0x3 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_LEFT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_L_CH_BIST_SINE (0x2 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_CUBE (0x1 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_RIGHT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_BIST_SFT 0 -+#define RK3308_ADC_R_CH_BIST_MSK (0x3 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_BIST_SINE (0x2 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_CUBE (0x1 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+ -+/* RK3308_ADC_DIG_CON07 - REG: 0x001c */ -+#define RK3308_ADCL_DATA_SFT 4 -+#define RK3308_ADCL_DATA(x) (x << RK3308_ADCL_DATA_SFT) -+#define RK3308_ADCR_DATA_SFT 2 -+#define RK3308_ADCR_DATA(x) (x << RK3308_ADCR_DATA_SFT) -+#define RK3308_ADCL_DATA_SEL_ADCL (0x1 << 1) -+#define RK3308_ADCL_DATA_SEL_NORMAL (0x0 << 1) -+#define RK3308_ADCR_DATA_SEL_ADCR (0x1 << 0) -+#define RK3308_ADCR_DATA_SEL_NORMAL (0x0 << 0) -+ -+/* -+ * RK3308_ALC_L_DIG_CON00 - REG: 0x0040 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON00 - REG: 0x0080 + ch * 0xc0 -+ */ -+#define RK3308_GAIN_ATTACK_JACK (0x1 << 6) -+#define RK3308_GAIN_ATTACK_NORMAL (0x0 << 6) -+#define RK3308_CTRL_GEN_SFT 4 -+#define RK3308_CTRL_GEN_MSK (0x3 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_JACK3 (0x3 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_JACK2 (0x2 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_JACK1 (0x1 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_CTRL_GEN_NORMAL (0x0 << RK3308_ALC_CTRL_GEN_SFT) -+#define RK3308_AGC_HOLD_TIME_SFT 0 -+#define RK3308_AGC_HOLD_TIME_MSK (0xf << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_1S (0xa << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_512MS (0x9 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_256MS (0x8 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_128MS (0x7 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_64MS (0x6 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_32MS (0x5 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_16MS (0x4 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_8MS (0x3 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_4MS (0x2 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_2MS (0x1 << RK3308_AGC_HOLD_TIME_SFT) -+#define RK3308_AGC_HOLD_TIME_0MS (0x0 << RK3308_AGC_HOLD_TIME_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON01 - REG: 0x0044 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON01 - REG: 0x0084 + ch * 0xc0 -+ */ -+#define RK3308_AGC_DECAY_TIME_SFT 4 -+/* Normal mode (reg_agc_mode = 0) */ -+#define RK3308_AGC_DECAY_NORMAL_MSK (0xf << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_512MS (0xa << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_256MS (0x9 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_128MS (0x8 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_64MS (0x7 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_32MS (0x6 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_16MS (0x5 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_8MS (0x4 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_4MS (0x3 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_2MS (0x2 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_1MS (0x1 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_NORMAL_0MS (0x0 << RK3308_AGC_DECAY_TIME_SFT) -+/* Limiter mode (reg_agc_mode = 1) */ -+#define RK3308_AGC_DECAY_LIMITER_MSK (0xf << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_128MS (0xa << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_64MS (0x9 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_32MS (0x8 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_16MS (0x7 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_8MS (0x6 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_4MS (0x5 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_2MS (0x4 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_1MS (0x3 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_500US (0x2 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_250US (0x1 << RK3308_AGC_DECAY_TIME_SFT) -+#define RK3308_AGC_DECAY_LIMITER_125US (0x0 << RK3308_AGC_DECAY_TIME_SFT) -+ -+#define RK3308_AGC_ATTACK_TIME_SFT 0 -+/* Normal mode (reg_agc_mode = 0) */ -+#define RK3308_AGC_ATTACK_NORMAL_MSK (0xf << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_128MS (0xa << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_64MS (0x9 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_32MS (0x8 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_16MS (0x7 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_8MS (0x6 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_4MS (0x5 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_2MS (0x4 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_1MS (0x3 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_500US (0x2 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_250US (0x1 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_NORMAL_125US (0x0 << RK3308_AGC_ATTACK_TIME_SFT) -+/* Limiter mode (reg_agc_mode = 1) */ -+#define RK3308_AGC_ATTACK_LIMITER_MSK (0xf << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_32MS (0xa << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_16MS (0x9 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_8MS (0x8 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_4MS (0x7 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_2MS (0x6 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_1MS (0x5 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_500US (0x4 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_250US (0x3 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_125US (0x2 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_64US (0x1 << RK3308_AGC_ATTACK_TIME_SFT) -+#define RK3308_AGC_ATTACK_LIMITER_32US (0x0 << RK3308_AGC_ATTACK_TIME_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON02 - REG: 0x0048 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON02 - REG: 0x0088 + ch * 0xc0 -+ */ -+#define RK3308_AGC_MODE_LIMITER (0x1 << 7) -+#define RK3308_AGC_MODE_NORMAL (0x0 << 7) -+#define RK3308_AGC_ZERO_CRO_EN (0x1 << 6) -+#define RK3308_AGC_ZERO_CRO_DIS (0x0 << 6) -+#define RK3308_AGC_AMP_RECOVER_GAIN (0x1 << 5) -+#define RK3308_AGC_AMP_RECOVER_LVOL (0x0 << 5) -+#define RK3308_AGC_FAST_DEC_EN (0x1 << 4) -+#define RK3308_AGC_FAST_DEC_DIS (0x0 << 4) -+#define RK3308_AGC_NOISE_GATE_EN (0x1 << 3) -+#define RK3308_AGC_NOISE_GATE_DIS (0x0 << 3) -+#define RK3308_AGC_NOISE_GATE_THRESH_SFT 0 -+#define RK3308_AGC_NOISE_GATE_THRESH_MSK (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N81DB (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N75DB (0x6 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N69DB (0x5 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N63DB (0x4 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N57DB (0x3 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N51DB (0x2 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N45DB (0x1 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+#define RK3308_AGC_NOISE_GATE_THRESH_N39DB (0x0 << RK3308_AGC_NOISE_GATE_THRESH_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON03 - REG: 0x004c + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON03 - REG: 0x008c + ch * 0xc0 -+ */ -+#define RK3308_AGC_PGA_ZERO_CRO_EN (0x1 << 5) -+#define RK3308_AGC_PGA_ZERO_CRO_DIS (0x0 << 5) -+#define RK3308_AGC_PGA_GAIN_SFT 0 -+#define RK3308_AGC_PGA_GAIN_MSK (0x1f << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_28_5 (0x1f << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_27 (0x1e << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_25_5 (0x1d << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_24 (0x1c << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_22_5 (0x1b << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_21 (0x1a << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_19_5 (0x19 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_18 (0x18 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_16_5 (0x17 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_15 (0x16 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_13_5 (0x15 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_12 (0x14 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_10_5 (0x13 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_9 (0x12 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_7_5 (0x11 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_6 (0x10 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_4_5 (0x0f << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_3 (0x0e << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_PDB_1_5 (0x0d << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_0DB (0x0c << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_1_5 (0x0b << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_3 (0x0a << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_4_5 (0x09 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_6 (0x08 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_7_5 (0x07 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_9 (0x06 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_10_5 (0x05 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_12 (0x04 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_13_5 (0x03 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_15 (0x02 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_16_5 (0x01 << RK3308_AGC_PGA_GAIN_SFT) -+#define RK3308_AGC_PGA_GAIN_NDB_18 (0x00 << RK3308_AGC_PGA_GAIN_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON04 - REG: 0x0050 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON04 - REG: 0x0090 + ch * 0xc0 -+ */ -+#define RK3308_AGC_SLOW_CLK_EN (0x1 << 3) -+#define RK3308_AGC_SLOW_CLK_DIS (0x0 << 3) -+#define RK3308_AGC_APPROX_RATE_SFT 0 -+#define RK3308_AGC_APPROX_RATE_MSK (0x7 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_8K (0x7 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_12K (0x6 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_16K (0x5 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_24K (0x4 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_32K (0x3 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_44_1K (0x2 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_48K (0x1 << RK3308_AGC_APPROX_RATE_SFT) -+#define RK3308_AGC_APPROX_RATE_96K (0x0 << RK3308_AGC_APPROX_RATE_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON05 - REG: 0x0054 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON05 - REG: 0x0094 + ch * 0xc0 -+ */ -+#define RK3308_AGC_LO_8BITS_AGC_MAX_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON06 - REG: 0x0058 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON06 - REG: 0x0098 + ch * 0xc0 -+ */ -+#define RK3308_AGC_HI_8BITS_AGC_MAX_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON07 - REG: 0x005c + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON07 - REG: 0x009c + ch * 0xc0 -+ */ -+#define RK3308_AGC_LO_8BITS_AGC_MIN_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON08 - REG: 0x0060 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON08 - REG: 0x00a0 + ch * 0xc0 -+ */ -+#define RK3308_AGC_HI_8BITS_AGC_MIN_MSK 0xff -+ -+/* -+ * RK3308_ALC_L_DIG_CON09 - REG: 0x0064 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON09 - REG: 0x00a4 + ch * 0xc0 -+ */ -+#define RK3308_AGC_FUNC_SEL_MSK (0x1 << 6) -+#define RK3308_AGC_FUNC_SEL_EN (0x1 << 6) -+#define RK3308_AGC_FUNC_SEL_DIS (0x0 << 6) -+#define RK3308_AGC_MAX_GAIN_PGA_SFT 3 -+#define RK3308_AGC_MAX_GAIN_PGA_MSK (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_28_5 (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_22_5 (0x6 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_16_5 (0x5 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_10_5 (0x4 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_PDB_4_5 (0x3 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_NDB_1_5 (0x2 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_NDB_7_5 (0x1 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MAX_GAIN_PGA_NDB_13_5 (0x0 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_SFT 0 -+#define RK3308_AGC_MIN_GAIN_PGA_MSK (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_24 (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_18 (0x6 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_12 (0x5 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_PDB_6 (0x4 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_0DB (0x3 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_NDB_6 (0x2 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_NDB_12 (0x1 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_NDB_18 (0x0 << RK3308_AGC_MIN_GAIN_PGA_SFT) -+ -+/* -+ * RK3308_ALC_L_DIG_CON12 - REG: 0x0068 + ch * 0xc0 -+ * RK3308_ALC_R_DIG_CON12 - REG: 0x00a8 + ch * 0xc0 -+ */ -+#define RK3308_AGC_GAIN_MSK 0x1f -+ -+/* RK3308_DAC_DIG_CON01 - REG: 0x0304 */ -+#define RK3308_DAC_I2S_LRC_POL_MSK (0x1 << 7) -+#define RK3308_DAC_I2S_LRC_POL_REVERSAL (0x1 << 7) -+#define RK3308_DAC_I2S_LRC_POL_NORMAL (0x0 << 7) -+#define RK3308_DAC_I2S_VALID_LEN_SFT 5 -+#define RK3308_DAC_I2S_VALID_LEN_MSK (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_32BITS (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_24BITS (0x2 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_20BITS (0x1 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_VALID_LEN_16BITS (0x0 << RK3308_DAC_I2S_VALID_LEN_SFT) -+#define RK3308_DAC_I2S_MODE_SFT 3 -+#define RK3308_DAC_I2S_MODE_MSK (0x3 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_PCM (0x3 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_I2S (0x2 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_LJ (0x1 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_MODE_RJ (0x0 << RK3308_DAC_I2S_MODE_SFT) -+#define RK3308_DAC_I2S_LR_MSK (0x1 << 2) -+#define RK3308_DAC_I2S_LR_SWAP (0x1 << 2) -+#define RK3308_DAC_I2S_LR_NORMAL (0x0 << 2) -+ -+/* RK3308_DAC_DIG_CON02 - REG: 0x0308 */ -+#define RK3308_DAC_IO_MODE_MSK (0x1 << 5) -+#define RK3308_DAC_IO_MODE_MASTER (0x1 << 5) -+#define RK3308_DAC_IO_MODE_SLAVE (0x0 << 5) -+#define RK3308_DAC_MODE_MSK (0x1 << 4) -+#define RK3308_DAC_MODE_MASTER (0x1 << 4) -+#define RK3308_DAC_MODE_SLAVE (0x0 << 4) -+#define RK3308_DAC_I2S_FRAME_LEN_SFT 2 -+#define RK3308_DAC_I2S_FRAME_LEN_MSK (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_32BITS (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_24BITS (0x2 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_20BITS (0x1 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_FRAME_16BITS (0x0 << RK3308_DAC_I2S_FRAME_LEN_SFT) -+#define RK3308_DAC_I2S_MSK (0x1 << 1) -+#define RK3308_DAC_I2S_WORK (0x1 << 1) -+#define RK3308_DAC_I2S_RESET (0x0 << 1) -+#define RK3308_DAC_I2S_BIT_CLK_POL_MSK (0x1 << 0) -+#define RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0) -+#define RK3308_DAC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0) -+ -+/* RK3308_DAC_DIG_CON03 - REG: 0x030C */ -+#define RK3308_DAC_L_CH_BIST_SFT 2 -+#define RK3308_DAC_L_CH_BIST_MSK (0x3 << RK3308_DAC_L_CH_BIST_SFT) -+#define RK3308_DAC_L_CH_BIST_LEFT (0x3 << RK3308_DAC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_DAC_L_CH_BIST_CUBE (0x2 << RK3308_DAC_L_CH_BIST_SFT) -+#define RK3308_DAC_L_CH_BIST_SINE (0x1 << RK3308_DAC_L_CH_BIST_SFT) -+#define RK3308_DAC_L_CH_BIST_RIGHT (0x0 << RK3308_DAC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_DAC_R_CH_BIST_SFT 0 -+#define RK3308_DAC_R_CH_BIST_MSK (0x3 << RK3308_DAC_R_CH_BIST_SFT) -+#define RK3308_DAC_R_CH_BIST_LEFT (0x3 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_DAC_R_CH_BIST_CUBE (0x2 << RK3308_DAC_R_CH_BIST_SFT) -+#define RK3308_DAC_R_CH_BIST_SINE (0x1 << RK3308_DAC_R_CH_BIST_SFT) -+#define RK3308_DAC_R_CH_BIST_RIGHT (0x0 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ -+ -+/* RK3308_DAC_DIG_CON05 - REG: 0x0314 */ -+#define RK3308_DAC_L_REG_CTL_INDATA (0x1 << 2) -+#define RK3308_DAC_L_NORMAL_DATA (0x0 << 2) -+#define RK3308_DAC_R_REG_CTL_INDATA (0x1 << 1) -+#define RK3308_DAC_R_NORMAL_DATA (0x0 << 1) -+ -+/* RK3308_DAC_DIG_CON10 - REG: 0x0328 */ -+#define RK3308_DAC_DATA_HI4(x) (x & 0xf) /* Need to RK3308_DAC_x_REG_CTL_INDATA */ -+ -+/* RK3308_DAC_DIG_CON11 - REG: 0x032c */ -+#define RK3308_DAC_DATA_LO8(x) (x & 0xff) /* Need to RK3308_DAC_x_REG_CTL_INDATA */ -+ -+/* RK3308_ADC_ANA_CON00 - REG: 0x0340 */ -+#define RK3308_ADC_CH1_CH2_MIC_ALL_MSK (0xff << 0) -+#define RK3308_ADC_CH1_CH2_MIC_ALL 0xff -+#define RK3308_ADC_CH2_MIC_UNMUTE (0x1 << 7) -+#define RK3308_ADC_CH2_MIC_MUTE (0x0 << 7) -+#define RK3308_ADC_CH2_MIC_WORK (0x1 << 6) -+#define RK3308_ADC_CH2_MIC_INIT (0x0 << 6) -+#define RK3308_ADC_CH2_MIC_EN (0x1 << 5) -+#define RK3308_ADC_CH2_MIC_DIS (0x0 << 5) -+#define RK3308_ADC_CH2_BUF_REF_EN (0x1 << 4) -+#define RK3308_ADC_CH2_BUF_REF_DIS (0x0 << 4) -+#define RK3308_ADC_CH1_MIC_UNMUTE (0x1 << 3) -+#define RK3308_ADC_CH1_MIC_MUTE (0x0 << 3) -+#define RK3308_ADC_CH1_MIC_WORK (0x1 << 2) -+#define RK3308_ADC_CH1_MIC_INIT (0x0 << 2) -+#define RK3308_ADC_CH1_MIC_EN (0x1 << 1) -+#define RK3308_ADC_CH1_MIC_DIS (0x0 << 1) -+#define RK3308_ADC_CH1_BUF_REF_EN (0x1 << 0) -+#define RK3308_ADC_CH1_BUF_REF_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON01 - REG: 0x0344 */ -+#define RK3308_ADC_CH2_MIC_GAIN_SFT 4 -+#define RK3308_ADC_CH2_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_SFT 0 -+#define RK3308_ADC_CH1_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+ -+/* RK3308_ADC_ANA_CON02 - REG: 0x0348 */ -+#define RK3308_ADC_CH2_ALC_ZC_MSK (0x7 << 4) -+#define RK3308_ADC_CH2_ZEROCROSS_DET_EN (0x1 << 6) -+#define RK3308_ADC_CH2_ZEROCROSS_DET_DIS (0x0 << 6) -+#define RK3308_ADC_CH2_ALC_WORK (0x1 << 5) -+#define RK3308_ADC_CH2_ALC_INIT (0x0 << 5) -+#define RK3308_ADC_CH2_ALC_EN (0x1 << 4) -+#define RK3308_ADC_CH2_ALC_DIS (0x0 << 4) -+ -+#define RK3308_ADC_CH1_ALC_ZC_MSK (0x7 << 0) -+#define RK3308_ADC_CH1_ZEROCROSS_DET_EN (0x1 << 2) -+#define RK3308_ADC_CH1_ZEROCROSS_DET_DIS (0x0 << 2) -+#define RK3308_ADC_CH1_ALC_WORK (0x1 << 1) -+#define RK3308_ADC_CH1_ALC_INIT (0x0 << 1) -+#define RK3308_ADC_CH1_ALC_EN (0x1 << 0) -+#define RK3308_ADC_CH1_ALC_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON03 - REG: 0x034c */ -+#define RK3308_ADC_CH1_ALC_GAIN_SFT 0 -+#define RK3308_ADC_CH1_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_27 (0x1e << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_25_5 (0x1d << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_24 (0x1c << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_22_5 (0x1b << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_21 (0x1a << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_19_5 (0x19 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_18 (0x18 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_16_5 (0x17 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_15 (0x16 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_13_5 (0x15 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_12 (0x14 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_10_5 (0x13 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_9 (0x12 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_7_5 (0x11 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_6 (0x10 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_4_5 (0x0f << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_3 (0x0e << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_PDB_1_5 (0x0d << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_1_5 (0x0b << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_3 (0x0a << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_4_5 (0x09 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_6 (0x08 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_7_5 (0x07 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_9 (0x06 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_10_5 (0x05 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_12 (0x04 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_13_5 (0x03 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_15 (0x02 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_16_5 (0x01 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+#define RK3308_ADC_CH1_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH1_ALC_GAIN_SFT) -+ -+/* RK3308_ADC_ANA_CON04 - REG: 0x0350 */ -+#define RK3308_ADC_CH2_ALC_GAIN_SFT 0 -+#define RK3308_ADC_CH2_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_27 (0x1e << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_25_5 (0x1d << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_24 (0x1c << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_22_5 (0x1b << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_21 (0x1a << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_19_5 (0x19 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_18 (0x18 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_16_5 (0x17 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_15 (0x16 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_13_5 (0x15 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_12 (0x14 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_10_5 (0x13 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_9 (0x12 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_7_5 (0x11 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_6 (0x10 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_4_5 (0x0f << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_3 (0x0e << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_PDB_1_5 (0x0d << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_1_5 (0x0b << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_3 (0x0a << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_4_5 (0x09 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_6 (0x08 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_7_5 (0x07 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_9 (0x06 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_10_5 (0x05 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_12 (0x04 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_13_5 (0x03 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_15 (0x02 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_16_5 (0x01 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+#define RK3308_ADC_CH2_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH2_ALC_GAIN_SFT) -+ -+/* RK3308_ADC_ANA_CON05 - REG: 0x0354 */ -+#define RK3308_ADC_CH2_ADC_CLK_MSK (0x7 << 4) -+#define RK3308_ADC_CH2_ADC_WORK (0x1 << 6) -+#define RK3308_ADC_CH2_ADC_INIT (0x0 << 6) -+#define RK3308_ADC_CH2_ADC_EN (0x1 << 5) -+#define RK3308_ADC_CH2_ADC_DIS (0x0 << 5) -+#define RK3308_ADC_CH2_CLK_EN (0x1 << 4) -+#define RK3308_ADC_CH2_CLK_DIS (0x0 << 4) -+ -+#define RK3308_ADC_CH1_ADC_CLK_MSK (0x7 << 0) -+#define RK3308_ADC_CH1_ADC_WORK (0x1 << 2) -+#define RK3308_ADC_CH1_ADC_INIT (0x0 << 2) -+#define RK3308_ADC_CH1_ADC_EN (0x1 << 1) -+#define RK3308_ADC_CH1_ADC_DIS (0x0 << 1) -+#define RK3308_ADC_CH1_CLK_EN (0x1 << 0) -+#define RK3308_ADC_CH1_CLK_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON06 - REG: 0x0358 */ -+#define RK3308_ADC_CURRENT_MSK (0x1 << 0) -+#define RK3308_ADC_CURRENT_EN (0x1 << 0) -+#define RK3308_ADC_CURRENT_DIS (0x0 << 0) -+ -+/* RK3308_ADC_ANA_CON07 - REG: 0x035c */ -+/* Note: The register configuration is only valid for ADC2 */ -+#define RK3308_ADC_CH2_IN_SEL_SFT 6 -+#define RK3308_ADC_CH2_IN_SEL_MSK (0x3 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_LINEIN_MIC (0x3 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_LINEIN (0x2 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_MIC (0x1 << RK3308_ADC_CH2_IN_SEL_SFT) -+#define RK3308_ADC_CH2_IN_NONE (0x0 << RK3308_ADC_CH2_IN_SEL_SFT) -+/* Note: The register configuration is only valid for ADC1 */ -+#define RK3308_ADC_CH1_IN_SEL_SFT 4 -+#define RK3308_ADC_CH1_IN_SEL_MSK (0x3 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_LINEIN_MIC (0x3 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_LINEIN (0x2 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_MIC (0x1 << RK3308_ADC_CH1_IN_SEL_SFT) -+#define RK3308_ADC_CH1_IN_NONE (0x0 << RK3308_ADC_CH1_IN_SEL_SFT) -+ -+#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << 3) -+#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << 3) -+#define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 -+#define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_85 (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_8 (0x6 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_75 (0x5 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_7 (0x4 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_65 (0x3 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_6 (0x2 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_55 (0x1 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+#define RK3308_ADC_MICBIAS_VOLT_0_5 (0x0 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+ -+/* RK3308_ADC_ANA_CON08 - REG: 0x0360 */ -+#define RK3308_ADC_MICBIAS_CURRENT_MSK (0x1 << 4) -+#define RK3308_ADC_MICBIAS_CURRENT_EN (0x1 << 4) -+#define RK3308_ADC_MICBIAS_CURRENT_DIS (0x0 << 4) -+ -+/* RK3308_ADC_ANA_CON10 - REG: 0x0368 */ -+#define RK3308_ADC_REF_EN (0x1 << 7) -+#define RK3308_ADC_REF_DIS (0x0 << 7) -+#define RK3308_ADC_CURRENT_CHARGE_SFT 0 -+#define RK3308_ADC_CURRENT_CHARGE_MSK (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) -+#define RK3308_ADC_DONT_SEL_ALL (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) -+/* -+ * 0: Choose the current I -+ * 1: Don't choose the current I -+ */ -+#define RK3308_ADC_SEL_I_1(x) ((x & 0x1) << 6) -+#define RK3308_ADC_SEL_I_2(x) ((x & 0x1) << 5) -+#define RK3308_ADC_SEL_I_4(x) ((x & 0x1) << 4) -+#define RK3308_ADC_SEL_I_8(x) ((x & 0x1) << 3) -+#define RK3308_ADC_SEL_I_16(x) ((x & 0x1) << 2) -+#define RK3308_ADC_SEL_I_32(x) ((x & 0x1) << 1) -+#define RK3308_ADC_SEL_I_64(x) ((x & 0x1) << 0) -+ -+/* RK3308_ADC_ANA_CON11 - REG: 0x036c */ -+#define RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK (0x1 << 1) -+#define RK3308_ADC_ALCR_CON_GAIN_PGAR_EN (0x1 << 1) -+#define RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS (0x0 << 1) -+#define RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK (0x1 << 0) -+#define RK3308_ADC_ALCL_CON_GAIN_PGAL_EN (0x1 << 0) -+#define RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON00 - REG: 0x0440 */ -+#define RK3308_DAC_HEADPHONE_DET_EN (0x1 << 1) -+#define RK3308_DAC_HEADPHONE_DET_DIS (0x0 << 1) -+#define RK3308_DAC_CURRENT_MSK (0x1 << 0) -+#define RK3308_DAC_CURRENT_EN (0x1 << 0) -+#define RK3308_DAC_CURRENT_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON01 - REG: 0x0444 */ -+#define RK3308_DAC_BUF_REF_R_MSK (0x1 << 6) -+#define RK3308_DAC_BUF_REF_R_EN (0x1 << 6) -+#define RK3308_DAC_BUF_REF_R_DIS (0x0 << 6) -+#define RK3308_DAC_POP_SOUND_R_SFT 4 -+#define RK3308_DAC_POP_SOUND_R_MSK (0x3 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_POP_SOUND_R_WORK (0x2 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_POP_SOUND_R_INIT (0x1 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_BUF_REF_L_MSK (0x1 << 2) -+#define RK3308_DAC_BUF_REF_L_EN (0x1 << 2) -+#define RK3308_DAC_BUF_REF_L_DIS (0x0 << 2) -+#define RK3308_DAC_POP_SOUND_L_SFT 0 -+#define RK3308_DAC_POP_SOUND_L_MSK (0x3 << RK3308_DAC_POP_SOUND_L_SFT) -+#define RK3308_DAC_POP_SOUND_L_WORK (0x2 << RK3308_DAC_POP_SOUND_L_SFT) -+#define RK3308_DAC_POP_SOUND_L_INIT (0x1 << RK3308_DAC_POP_SOUND_L_SFT) -+ -+/* RK3308_DAC_ANA_CON02 - REG: 0x0448 */ -+#define RK3308_DAC_R_DAC_WORK (0x1 << 7) -+#define RK3308_DAC_R_DAC_INIT (0x0 << 7) -+#define RK3308_DAC_R_DAC_EN (0x1 << 6) -+#define RK3308_DAC_R_DAC_DIS (0x0 << 6) -+#define RK3308_DAC_R_CLK_EN (0x1 << 5) -+#define RK3308_DAC_R_CLK_DIS (0x0 << 5) -+#define RK3308_DAC_R_REF_EN (0x1 << 4) -+#define RK3308_DAC_R_REF_DIS (0x0 << 4) -+#define RK3308_DAC_L_DAC_WORK (0x1 << 3) -+#define RK3308_DAC_L_DAC_INIT (0x0 << 3) -+#define RK3308_DAC_L_DAC_EN (0x1 << 2) -+#define RK3308_DAC_L_DAC_DIS (0x0 << 2) -+#define RK3308_DAC_L_CLK_EN (0x1 << 1) -+#define RK3308_DAC_L_CLK_DIS (0x0 << 1) -+#define RK3308_DAC_L_REF_EN (0x1 << 0) -+#define RK3308_DAC_L_REF_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON03 - REG: 0x044c */ -+#define RK3308_DAC_R_HPOUT_WORK (0x1 << 6) -+#define RK3308_DAC_R_HPOUT_INIT (0x0 << 6) -+#define RK3308_DAC_R_HPOUT_EN (0x1 << 5) -+#define RK3308_DAC_R_HPOUT_DIS (0x0 << 5) -+#define RK3308_DAC_R_HPOUT_UNMUTE (0x1 << 4) -+#define RK3308_DAC_R_HPOUT_MUTE (0x0 << 4) -+#define RK3308_DAC_L_HPOUT_WORK (0x1 << 2) -+#define RK3308_DAC_L_HPOUT_INIT (0x0 << 2) -+#define RK3308_DAC_L_HPOUT_EN (0x1 << 1) -+#define RK3308_DAC_L_HPOUT_DIS (0x0 << 1) -+#define RK3308_DAC_L_HPOUT_UNMUTE (0x1 << 0) -+#define RK3308_DAC_L_HPOUT_MUTE (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON04 - REG: 0x0450 */ -+#define RK3308_DAC_R_GAIN_SFT 6 -+#define RK3308_DAC_R_GAIN_MSK (0x3 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_0DB (0x3 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_PDB_1_5 (0x2 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_PDB_3 (0x1 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_GAIN_PDB_6 (0x0 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_UNMUTE (0x1 << 5) -+#define RK3308_DAC_R_LINEOUT_MUTE (0x0 << 5) -+#define RK3308_DAC_R_LINEOUT_EN (0x1 << 4) -+#define RK3308_DAC_R_LINEOUT_DIS (0x0 << 4) -+#define RK3308_DAC_L_GAIN_SFT 2 -+#define RK3308_DAC_L_GAIN_MSK (0x3 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_0DB (0x3 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_PDB_1_5 (0x2 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_PDB_3 (0x1 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_GAIN_PDB_6 (0x0 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_UNMUTE (0x1 << 1) -+#define RK3308_DAC_L_LINEOUT_MUTE (0x0 << 1) -+#define RK3308_DAC_L_LINEOUT_EN (0x1 << 0) -+#define RK3308_DAC_L_LINEOUT_DIS (0x0 << 0) -+ -+/* RK3308_DAC_ANA_CON05 - REG: 0x0454, step is 1.5db */ -+#define RK3308_DAC_L_HPOUT_GAIN_SFT 0 -+#define RK3308_DAC_L_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_4_5 (0x1d << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_3 (0x1c << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_PDB_1_5 (0x1b << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_0DB (0x1a << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_1_5 (0x19 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_3 (0x18 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_4_5 (0x17 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_6 (0x16 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_7_5 (0x15 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_9 (0x14 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_10_5 (0x13 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_12 (0x12 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_13_5 (0x11 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_15 (0x10 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_16_5 (0x0f << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_18 (0x0e << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_19_5 (0x0d << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_21 (0x0c << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_22_5 (0x0b << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_24 (0x0a << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_25_5 (0x09 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_27 (0x08 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_28_5 (0x07 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_30 (0x06 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_31_5 (0x05 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_33 (0x04 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_34_5 (0x03 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_36 (0x02 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+#define RK3308_DAC_L_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_L_HPOUT_GAIN_SFT) -+ -+/* RK3308_DAC_ANA_CON06 - REG: 0x0458, step is 1.5db */ -+#define RK3308_DAC_R_HPOUT_GAIN_SFT 0 -+#define RK3308_DAC_R_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_4_5 (0x1d << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_3 (0x1c << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_PDB_1_5 (0x1b << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_0DB (0x1a << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_1_5 (0x19 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_3 (0x18 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_4_5 (0x17 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_6 (0x16 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_7_5 (0x15 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_9 (0x14 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_10_5 (0x13 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_12 (0x12 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_13_5 (0x11 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_15 (0x10 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_16_5 (0x0f << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_18 (0x0e << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_19_5 (0x0d << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_21 (0x0c << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_22_5 (0x0b << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_24 (0x0a << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_25_5 (0x09 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_27 (0x08 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_28_5 (0x07 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_30 (0x06 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_31_5 (0x05 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_33 (0x04 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_34_5 (0x03 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_36 (0x02 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+#define RK3308_DAC_R_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_R_HPOUT_GAIN_SFT) -+ -+/* RK3308_DAC_ANA_CON12 - REG: 0x0470 */ -+#define RK3308_DAC_R_HPMIX_SEL_SFT 6 -+#define RK3308_DAC_R_HPMIX_SEL_MSK (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_LINEIN (0x2 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_I2S (0x1 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_NONE (0x0 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_SFT 4 -+#define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_R_HPMIX_GAIN_SFT) -+#define RK3308_DAC_L_HPMIX_SEL_SFT 2 -+#define RK3308_DAC_L_HPMIX_SEL_MSK (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_LINEIN (0x2 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_I2S (0x1 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_NONE (0x0 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_SFT 0 -+#define RK3308_DAC_L_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_L_HPMIX_GAIN_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_L_HPMIX_GAIN_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_L_HPMIX_GAIN_SFT) -+ -+/* RK3308_DAC_ANA_CON13 - REG: 0x0474 */ -+#define RK3308_DAC_R_HPMIX_UNMUTE (0x1 << 6) -+#define RK3308_DAC_R_HPMIX_MUTE (0x0 << 6) -+#define RK3308_DAC_R_HPMIX_WORK (0x1 << 5) -+#define RK3308_DAC_R_HPMIX_INIT (0x0 << 5) -+#define RK3308_DAC_R_HPMIX_EN (0x1 << 4) -+#define RK3308_DAC_R_HPMIX_DIS (0x0 << 4) -+#define RK3308_DAC_L_HPMIX_UNMUTE (0x1 << 2) -+#define RK3308_DAC_L_HPMIX_MUTE (0x0 << 2) -+#define RK3308_DAC_L_HPMIX_WORK (0x1 << 1) -+#define RK3308_DAC_L_HPMIX_INIT (0x0 << 1) -+#define RK3308_DAC_L_HPMIX_EN (0x1 << 0) -+#define RK3308_DAC_L_HPMIX_DIS (0x0 << 0) -+ -+#define RK3308_HIFI 0x0 -+ -+#endif /* __RK3308_CODEC_H__ */ --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch b/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch deleted file mode 100644 index 0cb1086..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0019-Sync-rk3308_codec-to-BSP-tree.patch +++ /dev/null @@ -1,6740 +0,0 @@ -From 26d61ff64d9a61425d017846db61e9a06de07286 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 17:13:59 +0100 -Subject: [PATCH 19/23] Sync `rk3308_codec` to BSP tree - ---- - .../bindings/sound/rockchip,rk3308-codec.txt | 78 + - sound/soc/codecs/rk3308_codec.c | 5687 ++++++++++++++--- - sound/soc/codecs/rk3308_codec.h | 217 +- - sound/soc/codecs/rk3308_codec_provider.h | 28 + - 4 files changed, 4894 insertions(+), 1116 deletions(-) - create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt - create mode 100644 sound/soc/codecs/rk3308_codec_provider.h - -diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt -new file mode 100644 -index 000000000000..e20bbd73e37e ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.txt -@@ -0,0 +1,78 @@ -+* Rockchip RK3308 Internal Codec -+ -+Required properties: -+ -+- compatible: "rockchip,rk3308-codec" -+- reg: The physical base address of the controller and length of memory -+ mapped region. -+- rockchip,grf: The phandle of the syscon node for GRF register. -+- clocks: A list of phandle + clock-specifer pairs, one for each entry in -+ clock-names. -+- clock-names: It should be "acodec". -+- resets : Must contain an entry for each entry in reset-names. -+- reset-names : Must include the following entries: "acodec-reset". -+ -+Optional properties: -+- rockchip,enable-all-adcs: This is a boolean type property, that shows whether -+ force enable all of ADCs. The following shows the relationship between grps -+ and ADC: -+ * grp 0 -- select ADC1 / ADC2 -+ * grp 1 -- select ADC3 / ADC4 -+ * grp 2 -- select ADC5 / ADC6 -+ * grp 3 -- select ADC7 / ADC8 -+ If the property is not used, the enabled ADC groups refer to needed channels -+ via configure hw_params. -+ -+- rockchip,adc-grps-route: This is a variable length array, that shows the -+ mapping route of ACODEC sdo to I2S sdi. By default, they are one-to-one -+ mapping: -+ * sdi_0 <-- sdo_0 -+ * sdi_1 <-- sdo_1 -+ * sdi_2 <-- sdo_2 -+ * sdi_3 <-- sdo_3 -+ If you would like to change the route mapping like this: -+ * sdi_0 <-- sdo_3 -+ * sdi_1 <-- sdo_0 -+ * sdi_2 <-- sdo_2 -+ * sdi_3 <-- sdo_1 -+ You need to add the property on dts: -+ - rockchip,adc-grps-route = <3 0 2 1>; -+ -+- rockchip,delay-loopback-handle-ms: This property points out that the delay for -+ handling ADC after enable PAs during loopback. -+- rockchip,delay-start-play-ms: This property points out the delay ms of start -+ playback according to different amplifier performance. -+- rockchip,en-always-grps: This property will keep the needed ADCs enabled -+ always after enabling once. -+- rockchip,loopback-grp: It points out the ADC group which is the loopback used. -+- rockchip,no-deep-low-power: The codec will not enter deep low power mode -+ during suspend. -+- rockchip,no-hp-det: If there is no headphone on boards, we don't need to -+ enable headphone detection. -+- rockchip,micbias1: Using internal micbias1 supply which are from codec. -+- rockchip,micbias2: Using internal micbias2 supply which are from codec. -+- rockchip,hp-jack-reversed;: To detect headphone via the reversed jack. -+- hp-ctl-gpios: The gpio of head phone controller. -+- pa-drv-gpios: The gpio of poweramplifier controller -+- rockchip,delay-pa-drv-ms: This property points out that the delay for -+ power on amplifier -+- spk-ctl-gpios: The gpio of speak controller. -+- micbias-en-gpios: The GPIO to enable external micbias. -+- vmicbias-supply: The phandle to the regulator to handle external micbias. -+ -+Example for rk3308 internal codec: -+ -+acodec: acodec@ff560000 { -+ compatible = "rockchip,rk3308-codec"; -+ reg = <0x0 0xff560000 0x0 0x10000>; -+ rockchip,grf = <&grf>; -+ clocks = <&cru PCLK_ACODEC>; -+ clock-names = "acodec"; -+ resets = <&cru SRST_ACODEC_P>; -+ reset-names = "acodec-reset"; -+ rockchip,loopback-grp = <0>; -+ hp-ctl-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; -+ pa-drv-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; -+ spk-ctl-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -index 106f09738dd0..815e22fc346c 100644 ---- a/sound/soc/codecs/rk3308_codec.c -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -29,1420 +29,4699 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include -+#include - #include - #include - - #include "rk3308_codec.h" -+#include "rk3308_codec_provider.h" -+ -+#if defined(CONFIG_DEBUG_FS) -+#include -+#include -+#include -+#endif -+ -+#define CODEC_DRV_NAME "rk3308-acodec" -+ -+#define ADC_GRP_SKIP_MAGIC 0x1001 -+#define ADC_LR_GROUP_MAX 4 -+#define ADC_STABLE_MS 200 -+#define DEBUG_POP_ALWAYS 0 -+#define HPDET_POLL_MS 2000 -+#define NOT_USED 255 -+#define LOOPBACK_HANDLE_MS 100 -+#define PA_DRV_MS 5 -+ -+#define GRF_SOC_CON1 0x304 -+#define GRF_CHIP_ID 0x800 -+#define GRF_I2S2_8CH_SDI_SFT 0 -+#define GRF_I2S3_4CH_SDI_SFT 8 -+#define GRF_I2S1_2CH_SDI_SFT 12 -+ -+#define GRF_I2S2_8CH_SDI_R_MSK(i, v) ((v >> (i * 2 + GRF_I2S2_8CH_SDI_SFT)) & 0x3) -+#define GRF_I2S2_8CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S2_8CH_SDI_SFT + 16)) -+#define GRF_I2S2_8CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S2_8CH_SDI_SFT)) |\ -+ GRF_I2S2_8CH_SDI_W_MSK(i)) -+ -+#define GRF_I2S3_4CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S3_4CH_SDI_SFT + 16)) -+#define GRF_I2S3_4CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S3_4CH_SDI_SFT)) |\ -+ GRF_I2S3_4CH_SDI_W_MSK(i)) -+ -+#define GRF_I2S1_2CH_SDI_W_MSK (0x3 << (GRF_I2S1_2CH_SDI_SFT + 16)) -+#define GRF_I2S1_2CH_SDI(v) (((v & 0x3) << GRF_I2S1_2CH_SDI_SFT) |\ -+ GRF_I2S1_2CH_SDI_W_MSK) -+ -+#define DETECT_GRF_ACODEC_HPDET_COUNTER 0x0030 -+#define DETECT_GRF_ACODEC_HPDET_CON 0x0034 -+#define DETECT_GRF_ACODEC_HPDET_STATUS 0x0038 -+#define DETECT_GRF_ACODEC_HPDET_STATUS_CLR 0x003c -+ -+/* 200ms based on pclk is 100MHz */ -+#define DEFAULT_HPDET_COUNT 20000000 -+#define HPDET_NEG_IRQ_SFT 1 -+#define HPDET_POS_IRQ_SFT 0 -+#define HPDET_BOTH_NEG_POS ((1 << HPDET_NEG_IRQ_SFT) |\ -+ (1 << HPDET_POS_IRQ_SFT)) -+ -+#define ACODEC_VERSION_A 0xa -+#define ACODEC_VERSION_B 0xb -+ -+enum { -+ ACODEC_TO_I2S2_8CH = 0, -+ ACODEC_TO_I2S3_4CH, -+ ACODEC_TO_I2S1_2CH, -+}; -+ -+enum { -+ ADC_GRP0_MICIN = 0, -+ ADC_GRP0_LINEIN -+}; -+ -+enum { -+ ADC_TYPE_NORMAL = 0, -+ ADC_TYPE_LOOPBACK, -+ ADC_TYPE_DBG, -+ ADC_TYPE_ALL, -+}; -+ -+enum { -+ DAC_LINEOUT = 0, -+ DAC_HPOUT = 1, -+ DAC_LINEOUT_HPOUT = 11, -+}; -+ -+enum { -+ EXT_MICBIAS_NONE = 0, -+ EXT_MICBIAS_FUNC1, /* enable external micbias via GPIO */ -+ EXT_MICBIAS_FUNC2, /* enable external micbias via regulator */ -+}; -+ -+enum { -+ PATH_IDLE = 0, -+ PATH_BUSY, -+}; -+ -+enum { -+ PM_NORMAL = 0, -+ PM_LLP_DOWN, /* light low power down */ -+ PM_LLP_UP, -+ PM_DLP_DOWN, /* deep low power down */ -+ PM_DLP_UP, -+ PM_DLP_DOWN2, -+ PM_DLP_UP2, -+}; - - struct rk3308_codec_priv { - const struct device *plat_dev; - struct device dev; - struct reset_control *reset; - struct regmap *regmap; -+ struct regmap *grf; -+ struct regmap *detect_grf; - struct clk *pclk; -+ struct clk *mclk_rx; -+ struct clk *mclk_tx; -+ struct gpio_desc *micbias_en_gpio; -+ struct gpio_desc *hp_ctl_gpio; - struct gpio_desc *spk_ctl_gpio; -- int adc_ch; /* To select ADCs for channel */ -- int adc_ch0_using_linein; -+ struct gpio_desc *pa_drv_gpio; -+ struct snd_soc_codec *codec; -+ struct snd_soc_jack *hpdet_jack; -+ struct regulator *vcc_micbias; -+ u32 codec_ver; -+ -+ /* -+ * To select ADCs for groups: -+ * -+ * grp 0 -- select ADC1 / ADC2 -+ * grp 1 -- select ADC3 / ADC4 -+ * grp 2 -- select ADC5 / ADC6 -+ * grp 3 -- select ADC7 / ADC8 -+ */ -+ u32 used_adc_grps; -+ /* The ADC group which is used for loop back */ -+ u32 loopback_grp; -+ u32 cur_dbg_grp; -+ u32 en_always_grps[ADC_LR_GROUP_MAX]; -+ u32 en_always_grps_num; -+ u32 skip_grps[ADC_LR_GROUP_MAX]; -+ u32 i2s_sdis[ADC_LR_GROUP_MAX]; -+ u32 to_i2s_grps; -+ u32 delay_loopback_handle_ms; -+ u32 delay_start_play_ms; -+ u32 delay_pa_drv_ms; -+ u32 micbias_num; -+ u32 micbias_volt; -+ int which_i2s; -+ int irq; -+ int adc_grp0_using_linein; -+ int adc_zerocross; -+ /* 0: line out, 1: hp out, 11: lineout and hpout */ -+ int dac_output; -+ int dac_path_state; -+ -+ int ext_micbias; -+ int pm_state; -+ -+ /* AGC L/R Off/on */ -+ unsigned int agc_l[ADC_LR_GROUP_MAX]; -+ unsigned int agc_r[ADC_LR_GROUP_MAX]; -+ -+ /* AGC L/R Approximate Sample Rate */ -+ unsigned int agc_asr_l[ADC_LR_GROUP_MAX]; -+ unsigned int agc_asr_r[ADC_LR_GROUP_MAX]; -+ -+ /* ADC MIC Mute/Work */ -+ unsigned int mic_mute_l[ADC_LR_GROUP_MAX]; -+ unsigned int mic_mute_r[ADC_LR_GROUP_MAX]; -+ -+ /* For the high pass filter */ -+ unsigned int hpf_cutoff[ADC_LR_GROUP_MAX]; -+ -+ /* Only hpout do fade-in and fade-out */ -+ unsigned int hpout_l_dgain; -+ unsigned int hpout_r_dgain; -+ -+ bool adc_grps_endisable[ADC_LR_GROUP_MAX]; -+ bool dac_endisable; -+ bool enable_all_adcs; -+ bool enable_micbias; -+ bool micbias1; -+ bool micbias2; -+ bool hp_jack_reversed; -+ bool hp_plugged; -+ bool loopback_dacs_enabled; -+ bool no_deep_low_power; -+ bool no_hp_det; -+ struct delayed_work hpdet_work; -+ struct delayed_work loopback_work; -+ -+#if defined(CONFIG_DEBUG_FS) -+ struct dentry *dbg_codec; -+#endif - }; - --static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_gain_tlv, -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_gain_tlv, - -1800, 150, 2850); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_max_gain_tlv, -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_max_gain_tlv, - -1350, 600, 2850); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_ch_min_gain_tlv, -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_min_gain_tlv, - -1800, 600, 2400); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_mic_gain_tlv, -- 0, 600, 3000); - static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, - -1800, 150, 2850); --static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_gain_tlv, -- 0, 150, 600); -+static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_lineout_gain_tlv, -+ -600, 150, 0); - static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, - -3900, 150, 600); - static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, - -600, 600, 0); - -+static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_a, -+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), -+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), -+); -+ -+static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_b, -+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), -+ 1, 1, TLV_DB_SCALE_ITEM(660, 0, 0), -+ 2, 2, TLV_DB_SCALE_ITEM(1300, 0, 0), -+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), -+); -+ -+static bool handle_loopback(struct rk3308_codec_priv *rk3308); -+ -+static int check_micbias(int micbias); -+ -+static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -+ int micbias); -+static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308); -+ -+static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol); -+ -+static const char *offon_text[2] = { -+ [0] = "Off", -+ [1] = "On", -+}; -+ -+static const char *mute_text[2] = { -+ [0] = "Work", -+ [1] = "Mute", -+}; -+ -+/* ADC MICBIAS Volt */ -+#define MICBIAS_VOLT_NUM 8 -+ -+#define MICBIAS_VREFx0_5 0 -+#define MICBIAS_VREFx0_55 1 -+#define MICBIAS_VREFx0_6 2 -+#define MICBIAS_VREFx0_65 3 -+#define MICBIAS_VREFx0_7 4 -+#define MICBIAS_VREFx0_75 5 -+#define MICBIAS_VREFx0_8 6 -+#define MICBIAS_VREFx0_85 7 -+ -+static const char *micbias_volts_enum_array[MICBIAS_VOLT_NUM] = { -+ [MICBIAS_VREFx0_5] = "VREFx0_5", -+ [MICBIAS_VREFx0_55] = "VREFx0_55", -+ [MICBIAS_VREFx0_6] = "VREFx0_6", -+ [MICBIAS_VREFx0_65] = "VREFx0_65", -+ [MICBIAS_VREFx0_7] = "VREFx0_7", -+ [MICBIAS_VREFx0_75] = "VREFx0_75", -+ [MICBIAS_VREFx0_8] = "VREFx0_8", -+ [MICBIAS_VREFx0_85] = "VREFx0_85", -+}; -+ -+static const struct soc_enum rk3308_micbias_volts_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(micbias_volts_enum_array), micbias_volts_enum_array), -+}; -+ -+/* ADC MICBIAS1 and MICBIAS2 Main Switch */ -+static const struct soc_enum rk3308_main_micbias_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), -+}; -+ -+static const struct soc_enum rk3308_hpf_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text), -+}; -+ -+/* ALC AGC Switch */ -+static const struct soc_enum rk3308_agc_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text), -+ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(offon_text), offon_text), -+}; -+ -+/* ADC MIC Mute/Work Switch */ -+static const struct soc_enum rk3308_mic_mute_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(mute_text), mute_text), -+ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(mute_text), mute_text), -+}; -+ -+/* ALC AGC Approximate Sample Rate */ -+#define AGC_ASR_NUM 8 -+ -+#define AGC_ASR_96KHZ 0 -+#define AGC_ASR_48KHZ 1 -+#define AGC_ASR_44_1KHZ 2 -+#define AGC_ASR_32KHZ 3 -+#define AGC_ASR_24KHZ 4 -+#define AGC_ASR_16KHZ 5 -+#define AGC_ASR_12KHZ 6 -+#define AGC_ASR_8KHZ 7 -+ -+static const char *agc_asr_text[AGC_ASR_NUM] = { -+ [AGC_ASR_96KHZ] = "96KHz", -+ [AGC_ASR_48KHZ] = "48KHz", -+ [AGC_ASR_44_1KHZ] = "44.1KHz", -+ [AGC_ASR_32KHZ] = "32KHz", -+ [AGC_ASR_24KHZ] = "24KHz", -+ [AGC_ASR_16KHZ] = "16KHz", -+ [AGC_ASR_12KHZ] = "12KHz", -+ [AGC_ASR_8KHZ] = "8KHz", -+}; -+ -+static const struct soc_enum rk3308_agc_asr_enum_array[] = { -+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), -+}; -+ -+static const struct snd_kcontrol_new mic_gains_a[] = { -+ /* ADC MIC */ -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_a), -+}; -+ -+static const struct snd_kcontrol_new mic_gains_b[] = { -+ /* ADC MIC */ -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Volume", -+ RK3308_ADC_ANA_CON01(0), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Volume", -+ RK3308_ADC_ANA_CON01(1), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Volume", -+ RK3308_ADC_ANA_CON01(2), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH1_MIC_GAIN_SFT, -+ RK3308_ADC_CH1_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Volume", -+ RK3308_ADC_ANA_CON01(3), -+ RK3308_ADC_CH2_MIC_GAIN_SFT, -+ RK3308_ADC_CH2_MIC_GAIN_MAX, -+ 0, -+ rk3308_codec_mic_gain_get, -+ rk3308_codec_mic_gain_put, -+ rk3308_codec_adc_mic_gain_tlv_b), -+}; -+ - static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { -- /* ALC AGC Channel*/ -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Volume", -+ /* ALC AGC Group */ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Volume", - RK3308_ALC_L_DIG_CON03(0), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Volume", - RK3308_ALC_R_DIG_CON03(0), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Volume", -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Volume", - RK3308_ALC_L_DIG_CON03(1), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Volume", - RK3308_ALC_R_DIG_CON03(1), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Volume", -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Volume", - RK3308_ALC_L_DIG_CON03(2), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Volume", - RK3308_ALC_R_DIG_CON03(2), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Volume", -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Volume", - RK3308_ALC_L_DIG_CON03(3), -+ RK3308_AGC_PGA_GAIN_SFT, -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Volume", - RK3308_ALC_R_DIG_CON03(3), - RK3308_AGC_PGA_GAIN_SFT, -- RK3308_AGC_PGA_GAIN_NDB_18, -- RK3308_AGC_PGA_GAIN_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_gain_tlv), -+ RK3308_AGC_PGA_GAIN_MIN, -+ RK3308_AGC_PGA_GAIN_MAX, -+ 0, rk3308_codec_alc_agc_grp_gain_tlv), - - /* ALC AGC MAX */ -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Max Volume", -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Max Volume", - RK3308_ALC_L_DIG_CON09(0), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Max Volume", - RK3308_ALC_R_DIG_CON09(0), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Max Volume", -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Max Volume", - RK3308_ALC_L_DIG_CON09(1), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Max Volume", - RK3308_ALC_R_DIG_CON09(1), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Max Volume", -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Max Volume", - RK3308_ALC_L_DIG_CON09(2), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Max Volume", - RK3308_ALC_R_DIG_CON09(2), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Max Volume", -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Max Volume", - RK3308_ALC_L_DIG_CON09(3), -+ RK3308_AGC_MAX_GAIN_PGA_SFT, -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Max Volume", - RK3308_ALC_R_DIG_CON09(3), - RK3308_AGC_MAX_GAIN_PGA_SFT, -- RK3308_AGC_MAX_GAIN_PGA_NDB_13_5, -- RK3308_AGC_MAX_GAIN_PGA_PDB_28_5, -- 0, rk3308_codec_alc_agc_ch_max_gain_tlv), -+ RK3308_AGC_MAX_GAIN_PGA_MIN, -+ RK3308_AGC_MAX_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), - - /* ALC AGC MIN */ -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 0 Min Volume", -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Min Volume", - RK3308_ALC_L_DIG_CON09(0), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Min Volume", - RK3308_ALC_R_DIG_CON09(0), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 1 Min Volume", -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Min Volume", - RK3308_ALC_L_DIG_CON09(1), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Min Volume", - RK3308_ALC_R_DIG_CON09(1), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 2 Min Volume", -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Min Volume", - RK3308_ALC_L_DIG_CON09(2), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Min Volume", - RK3308_ALC_R_DIG_CON09(2), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- SOC_DOUBLE_R_RANGE_TLV("ALC AGC Channel 3 Min Volume", -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Min Volume", - RK3308_ALC_L_DIG_CON09(3), -+ RK3308_AGC_MIN_GAIN_PGA_SFT, -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Min Volume", - RK3308_ALC_R_DIG_CON09(3), - RK3308_AGC_MIN_GAIN_PGA_SFT, -- RK3308_AGC_MIN_GAIN_PGA_NDB_18, -- RK3308_AGC_MIN_GAIN_PGA_PDB_24, -- 0, rk3308_codec_alc_agc_ch_min_gain_tlv), -- -- /* ADC MIC */ -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Left Volume", -- RK3308_ADC_ANA_CON01(0), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 0 Right Volume", -- RK3308_ADC_ANA_CON01(0), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Left Volume", -- RK3308_ADC_ANA_CON01(1), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 1 Right Volume", -- RK3308_ADC_ANA_CON01(1), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Left Volume", -- RK3308_ADC_ANA_CON01(2), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 2 Right Volume", -- RK3308_ADC_ANA_CON01(2), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Left Volume", -- RK3308_ADC_ANA_CON01(3), -- RK3308_ADC_CH1_MIC_GAIN_SFT, -- RK3308_ADC_CH1_MIC_GAIN_0DB, -- RK3308_ADC_CH1_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC MIC Channel 3 Right Volume", -- RK3308_ADC_ANA_CON01(3), -- RK3308_ADC_CH2_MIC_GAIN_SFT, -- RK3308_ADC_CH2_MIC_GAIN_0DB, -- RK3308_ADC_CH2_MIC_GAIN_30DB, -- 0, rk3308_codec_adc_mic_gain_tlv), -+ RK3308_AGC_MIN_GAIN_PGA_MIN, -+ RK3308_AGC_MIN_GAIN_PGA_MAX, -+ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), -+ -+ /* ALC AGC Switch */ -+ SOC_ENUM_EXT("ALC AGC Group 0 Left Switch", rk3308_agc_enum_array[0], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 0 Right Switch", rk3308_agc_enum_array[1], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 1 Left Switch", rk3308_agc_enum_array[2], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 1 Right Switch", rk3308_agc_enum_array[3], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 2 Left Switch", rk3308_agc_enum_array[4], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 2 Right Switch", rk3308_agc_enum_array[5], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 3 Left Switch", rk3308_agc_enum_array[6], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ SOC_ENUM_EXT("ALC AGC Group 3 Right Switch", rk3308_agc_enum_array[7], -+ rk3308_codec_agc_get, rk3308_codec_agc_put), -+ -+ /* ALC AGC Approximate Sample Rate */ -+ SOC_ENUM_EXT("AGC Group 0 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[0], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 0 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[1], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 1 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[2], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 1 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[3], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 2 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[4], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 2 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[5], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 3 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[6], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ SOC_ENUM_EXT("AGC Group 3 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[7], -+ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), -+ -+ /* ADC MICBIAS Voltage */ -+ SOC_ENUM_EXT("ADC MICBIAS Voltage", rk3308_micbias_volts_enum_array[0], -+ rk3308_codec_micbias_volts_get, rk3308_codec_micbias_volts_put), -+ -+ /* ADC Main MICBIAS Switch */ -+ SOC_ENUM_EXT("ADC Main MICBIAS", rk3308_main_micbias_enum_array[0], -+ rk3308_codec_main_micbias_get, rk3308_codec_main_micbias_put), -+ -+ /* ADC MICBIAS1 and MICBIAS2 Switch */ -+ SOC_SINGLE("ADC MICBIAS1", RK3308_ADC_ANA_CON07(1), -+ RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0), -+ SOC_SINGLE("ADC MICBIAS2", RK3308_ADC_ANA_CON07(2), -+ RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0), -+ -+ /* ADC MIC Mute/Work Switch */ -+ SOC_ENUM_EXT("ADC MIC Group 0 Left Switch", rk3308_mic_mute_enum_array[0], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 0 Right Switch", rk3308_mic_mute_enum_array[1], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 1 Left Switch", rk3308_mic_mute_enum_array[2], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 1 Right Switch", rk3308_mic_mute_enum_array[3], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 2 Left Switch", rk3308_mic_mute_enum_array[4], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 2 Right Switch", rk3308_mic_mute_enum_array[5], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 3 Left Switch", rk3308_mic_mute_enum_array[6], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), -+ SOC_ENUM_EXT("ADC MIC Group 3 Right Switch", rk3308_mic_mute_enum_array[7], -+ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), - - /* ADC ALC */ -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Left Volume", - RK3308_ADC_ANA_CON03(0), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 0 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Right Volume", - RK3308_ADC_ANA_CON04(0), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Left Volume", - RK3308_ADC_ANA_CON03(1), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 1 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Right Volume", - RK3308_ADC_ANA_CON04(1), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Left Volume", - RK3308_ADC_ANA_CON03(2), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 2 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Right Volume", - RK3308_ADC_ANA_CON04(2), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Left Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Left Volume", - RK3308_ADC_ANA_CON03(3), - RK3308_ADC_CH1_ALC_GAIN_SFT, -- RK3308_ADC_CH1_ALC_GAIN_NDB_18, -- RK3308_ADC_CH1_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH1_ALC_GAIN_MIN, -+ RK3308_ADC_CH1_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), -- SOC_SINGLE_RANGE_TLV("ADC ALC Channel 3 Right Volume", -+ SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Right Volume", - RK3308_ADC_ANA_CON04(3), - RK3308_ADC_CH2_ALC_GAIN_SFT, -- RK3308_ADC_CH2_ALC_GAIN_NDB_18, -- RK3308_ADC_CH2_ALC_GAIN_PDB_28_5, -+ RK3308_ADC_CH2_ALC_GAIN_MIN, -+ RK3308_ADC_CH2_ALC_GAIN_MAX, - 0, rk3308_codec_adc_alc_gain_tlv), - -- /* DAC */ -- SOC_SINGLE_RANGE_TLV("DAC Left Volume", -- RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_GAIN_SFT, -- RK3308_DAC_L_GAIN_0DB, -- RK3308_DAC_L_GAIN_PDB_6, -- 0, rk3308_codec_dac_gain_tlv), -- SOC_SINGLE_RANGE_TLV("DAC Right Volume", -- RK3308_DAC_ANA_CON04, -- RK3308_DAC_R_GAIN_SFT, -- RK3308_DAC_R_GAIN_0DB, -- RK3308_DAC_R_GAIN_PDB_6, -- 0, rk3308_codec_dac_gain_tlv), -+ /* ADC High Pass Filter */ -+ SOC_ENUM_EXT("ADC Group 0 HPF Cut-off", rk3308_hpf_enum_array[0], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ SOC_ENUM_EXT("ADC Group 1 HPF Cut-off", rk3308_hpf_enum_array[1], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ SOC_ENUM_EXT("ADC Group 2 HPF Cut-off", rk3308_hpf_enum_array[2], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ SOC_ENUM_EXT("ADC Group 3 HPF Cut-off", rk3308_hpf_enum_array[3], -+ rk3308_codec_hpf_get, rk3308_codec_hpf_put), -+ -+ /* DAC LINEOUT */ -+ SOC_SINGLE_TLV("DAC LINEOUT Left Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_GAIN_SFT, -+ RK3308_DAC_L_LINEOUT_GAIN_MAX, -+ 0, rk3308_codec_dac_lineout_gain_tlv), -+ SOC_SINGLE_TLV("DAC LINEOUT Right Volume", -+ RK3308_DAC_ANA_CON04, -+ RK3308_DAC_R_LINEOUT_GAIN_SFT, -+ RK3308_DAC_R_LINEOUT_GAIN_MAX, -+ 0, rk3308_codec_dac_lineout_gain_tlv), - - /* DAC HPOUT */ -- SOC_SINGLE_RANGE_TLV("DAC HPOUT Left Volume", -- RK3308_DAC_ANA_CON05, -- RK3308_DAC_L_HPOUT_GAIN_SFT, -- RK3308_DAC_L_HPOUT_GAIN_NDB_39, -- RK3308_DAC_L_HPOUT_GAIN_PDB_6, -- 0, rk3308_codec_dac_hpout_gain_tlv), -- SOC_SINGLE_RANGE_TLV("DAC HPOUT Right Volume", -- RK3308_DAC_ANA_CON06, -- RK3308_DAC_R_HPOUT_GAIN_SFT, -- RK3308_DAC_R_HPOUT_GAIN_NDB_39, -- RK3308_DAC_R_HPOUT_GAIN_PDB_6, -- 0, rk3308_codec_dac_hpout_gain_tlv), -+ SOC_SINGLE_EXT_TLV("DAC HPOUT Left Volume", -+ RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_SFT, -+ RK3308_DAC_L_HPOUT_GAIN_MAX, -+ 0, -+ rk3308_codec_hpout_l_get_tlv, -+ rk3308_codec_hpout_l_put_tlv, -+ rk3308_codec_dac_hpout_gain_tlv), -+ SOC_SINGLE_EXT_TLV("DAC HPOUT Right Volume", -+ RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_SFT, -+ RK3308_DAC_R_HPOUT_GAIN_MAX, -+ 0, -+ rk3308_codec_hpout_r_get_tlv, -+ rk3308_codec_hpout_r_put_tlv, -+ rk3308_codec_dac_hpout_gain_tlv), - - /* DAC HPMIX */ - SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume", -- RK3308_DAC_ANA_CON05, -+ RK3308_DAC_ANA_CON12, - RK3308_DAC_L_HPMIX_GAIN_SFT, -- RK3308_DAC_L_HPMIX_GAIN_NDB_6, -- RK3308_DAC_L_HPMIX_GAIN_0DB, -+ RK3308_DAC_L_HPMIX_GAIN_MIN, -+ RK3308_DAC_L_HPMIX_GAIN_MAX, - 0, rk3308_codec_dac_hpmix_gain_tlv), - SOC_SINGLE_RANGE_TLV("DAC HPMIX Right Volume", -- RK3308_DAC_ANA_CON05, -+ RK3308_DAC_ANA_CON12, - RK3308_DAC_R_HPMIX_GAIN_SFT, -- RK3308_DAC_R_HPMIX_GAIN_NDB_6, -- RK3308_DAC_R_HPMIX_GAIN_0DB, -+ RK3308_DAC_R_HPMIX_GAIN_MIN, -+ RK3308_DAC_R_HPMIX_GAIN_MAX, - 0, rk3308_codec_dac_hpmix_gain_tlv), - }; - --static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) -+static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- gpiod_direction_output(rk3308->spk_ctl_gpio, on); -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } -+ -+ if (e->shift_l) -+ ucontrol->value.integer.value[0] = rk3308->agc_r[e->reg]; -+ else -+ ucontrol->value.integer.value[0] = rk3308->agc_l[e->reg]; -+ -+ return 0; - } - --static int rk3308_codec_reset(struct snd_soc_codec *codec) -+static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.integer.value[0]; -+ int grp = e->reg; - -- reset_control_assert(rk3308->reset); -- usleep_range(200, 300); /* estimated value */ -- reset_control_deassert(rk3308->reset); -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } - -- regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); -- usleep_range(200, 300); /* estimated value */ -- regmap_write(rk3308->regmap, RK3308_GLB_CON, -- RK3308_SYS_WORK | -- RK3308_DAC_DIG_WORK | -- RK3308_ADC_DIG_WORK); -+ if (value) { -+ /* ALC AGC On */ -+ if (e->shift_l) { -+ /* ALC AGC Right On */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); -+ -+ rk3308->agc_r[e->reg] = 1; -+ } else { -+ /* ALC AGC Left On */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_EN); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_EN); -+ -+ rk3308->agc_l[e->reg] = 1; -+ } -+ } else { -+ /* ALC AGC Off */ -+ if (e->shift_l) { -+ /* ALC AGC Right Off */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -+ RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); -+ -+ rk3308->agc_r[e->reg] = 0; -+ } else { -+ /* ALC AGC Left Off */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), -+ RK3308_AGC_FUNC_SEL_MSK, -+ RK3308_AGC_FUNC_SEL_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK, -+ RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS); -+ -+ rk3308->agc_l[e->reg] = 0; -+ } -+ } - - return 0; - } - --static int rk3308_set_bias_level(struct snd_soc_codec *codec, -- enum snd_soc_bias_level level) -+static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- switch (level) { -- case SND_SOC_BIAS_ON: -- break; -- -- case SND_SOC_BIAS_PREPARE: -- break; -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; - -- case SND_SOC_BIAS_STANDBY: -- case SND_SOC_BIAS_OFF: -- break; -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; - } - -- snd_soc_codec_force_bias_level(codec, level); -+ if (e->shift_l) { -+ regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON04(grp), &value); -+ rk3308->agc_asr_r[e->reg] = value >> RK3308_AGC_APPROX_RATE_SFT; -+ ucontrol->value.integer.value[0] = rk3308->agc_asr_r[e->reg]; -+ } else { -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp), &value); -+ rk3308->agc_asr_l[e->reg] = value >> RK3308_AGC_APPROX_RATE_SFT; -+ ucontrol->value.integer.value[0] = rk3308->agc_asr_l[e->reg]; -+ } - - return 0; - } - --static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -- unsigned int fmt) -+static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = codec_dai->codec; -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -- int ch = rk3308->adc_ch; -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; - -- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -- case SND_SOC_DAIFMT_CBS_CFS: -- adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; -- adc_aif2 |= RK3308_ADC_MODE_SLAVE; -- dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; -- dac_aif2 |= RK3308_DAC_MODE_SLAVE; -- break; -- case SND_SOC_DAIFMT_CBM_CFM: -- adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; -- adc_aif2 |= RK3308_ADC_MODE_MASTER; -- dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; -- dac_aif2 |= RK3308_DAC_MODE_MASTER; -- break; -- default: -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); - return -EINVAL; - } - -- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -- case SND_SOC_DAIFMT_DSP_A: -- adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; -- dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; -- break; -- case SND_SOC_DAIFMT_I2S: -- adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; -- dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; -- break; -- case SND_SOC_DAIFMT_RIGHT_J: -- adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -- dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; -- break; -- case SND_SOC_DAIFMT_LEFT_J: -- adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -- dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; -- break; -- default: -- return -EINVAL; -+ value = ucontrol->value.integer.value[0] << RK3308_AGC_APPROX_RATE_SFT; -+ -+ if (e->shift_l) { -+ /* ALC AGC Right Approximate Sample Rate */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(grp), -+ RK3308_AGC_APPROX_RATE_MSK, -+ value); -+ rk3308->agc_asr_r[e->reg] = ucontrol->value.integer.value[0]; -+ } else { -+ /* ALC AGC Left Approximate Sample Rate */ -+ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp), -+ RK3308_AGC_APPROX_RATE_MSK, -+ value); -+ rk3308->agc_asr_l[e->reg] = ucontrol->value.integer.value[0]; - } - -- switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -- case SND_SOC_DAIFMT_NB_NF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -- break; -- case SND_SOC_DAIFMT_IB_IF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -- break; -- case SND_SOC_DAIFMT_IB_NF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -- break; -- case SND_SOC_DAIFMT_NB_IF: -- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -- break; -- default: -+ return 0; -+} -+ -+static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; -+ -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); - return -EINVAL; - } - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -- RK3308_ADC_I2S_LRC_POL_MSK | -- RK3308_ADC_I2S_MODE_MSK, -- adc_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -- RK3308_ADC_IO_MODE_MSK | -- RK3308_ADC_MODE_MSK | -- RK3308_ADC_I2S_BIT_CLK_POL_MSK, -- adc_aif2); -- -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -- RK3308_DAC_I2S_LRC_POL_MSK | -- RK3308_DAC_I2S_MODE_MSK, -- dac_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -- RK3308_DAC_IO_MODE_MSK | -- RK3308_DAC_MODE_MSK | -- RK3308_DAC_I2S_BIT_CLK_POL_MSK, -- dac_aif2); -+ if (e->shift_l) { -+ /* ADC MIC Right Mute/Work Infos */ -+ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value); -+ rk3308->mic_mute_r[e->reg] = (value & RK3308_ADC_R_CH_BIST_SINE) >> -+ RK3308_ADC_R_CH_BIST_SFT; -+ ucontrol->value.integer.value[0] = rk3308->mic_mute_r[e->reg]; -+ } else { -+ /* ADC MIC Left Mute/Work Infos */ -+ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value); -+ rk3308->mic_mute_l[e->reg] = (value & RK3308_ADC_L_CH_BIST_SINE) >> -+ RK3308_ADC_L_CH_BIST_SFT; -+ ucontrol->value.integer.value[0] = rk3308->mic_mute_l[e->reg]; -+ } - - return 0; - } - --static int rk3308_hw_params(struct snd_pcm_substream *substream, -- struct snd_pcm_hw_params *params, -- struct snd_soc_dai *dai) -+static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = dai->codec; -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -- int ch = rk3308->adc_ch; -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; -+ int grp = e->reg; - -- switch (params_format(params)) { -- case SNDRV_PCM_FORMAT_S16_LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; -- break; -- case SNDRV_PCM_FORMAT_S20_3LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; -- break; -- case SNDRV_PCM_FORMAT_S24_LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; -- break; -- case SNDRV_PCM_FORMAT_S32_LE: -- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; -- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; -- break; -- default: -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); - return -EINVAL; - } - -- switch (params_channels(params)) { -- case 1: -- adc_aif1 |= RK3308_ADC_I2S_MONO; -- break; -- case 2: -- adc_aif1 |= RK3308_ADC_I2S_STEREO; -- break; -- default: -- return -EINVAL; -+ if (e->shift_l) { -+ /* ADC MIC Right Mute/Work Configuration */ -+ value = ucontrol->value.integer.value[0] << RK3308_ADC_R_CH_BIST_SFT; -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_SINE, -+ value); -+ rk3308->mic_mute_r[e->reg] = ucontrol->value.integer.value[0]; -+ } else { -+ /* ADC MIC Left Mute/Work Configuration */ -+ value = ucontrol->value.integer.value[0] << RK3308_ADC_L_CH_BIST_SFT; -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_SINE, -+ value); -+ rk3308->mic_mute_l[e->reg] = ucontrol->value.integer.value[0]; - } - -- adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; -- adc_aif2 |= RK3308_ADC_I2S_WORK; -- dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; -- dac_aif2 |= RK3308_DAC_I2S_WORK; -+ return 0; -+} - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(ch), -- RK3308_ADC_I2S_VALID_LEN_MSK | -- RK3308_ADC_I2S_LR_MSK | -- RK3308_ADC_I2S_TYPE_MSK, -- adc_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(ch), -- RK3308_ADC_I2S_MSK, -- adc_aif2); -+static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -- RK3308_DAC_I2S_VALID_LEN_MSK | -- RK3308_DAC_I2S_LR_MSK, -- dac_aif1); -- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -- RK3308_DAC_I2S_MSK, -- dac_aif2); -+ ucontrol->value.integer.value[0] = rk3308->micbias_volt; - - return 0; - } - --static int rk3308_digital_mute(struct snd_soc_dai *dai, int mute) -+static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int volt = ucontrol->value.integer.value[0]; -+ int ret; -+ -+ ret = check_micbias(volt); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, "The invalid micbias volt: %d\n", -+ volt); -+ return ret; -+ } -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -+ volt); -+ -+ rk3308->micbias_volt = volt; -+ - return 0; - } - --static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) -+static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- /* Step 01 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -- RK3308_DAC_CURRENT_MSK, -- RK3308_DAC_CURRENT_EN); -- -- /* Step 02 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_BUF_REF_L_MSK | -- RK3308_DAC_BUF_REF_R_MSK, -- RK3308_DAC_BUF_REF_L_EN | -- RK3308_DAC_BUF_REF_R_EN); -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- /* Step 03 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_L_MSK | -- RK3308_DAC_POP_SOUND_R_MSK, -- RK3308_DAC_POP_SOUND_L_WORK | -- RK3308_DAC_POP_SOUND_R_WORK); -+ ucontrol->value.integer.value[0] = rk3308->enable_micbias; - -- /* Step 04 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -- RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN); -+ return 0; -+} - -- /* Step 05 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -- RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK); -+static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int on = ucontrol->value.integer.value[0]; -+ -+ if (on) { -+ if (!rk3308->enable_micbias) -+ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); -+ } else { -+ if (rk3308->enable_micbias) -+ rk3308_codec_micbias_disable(rk3308); -+ } - -- /* Step 06 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -- RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN); -+ return 0; -+} - -- /* Step 07 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -- RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN); -+static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ return snd_soc_get_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 08 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -- RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK); -+static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int gain = ucontrol->value.integer.value[0]; - -- /* Step 09 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -- RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN); -+ if (gain > RK3308_ADC_CH1_MIC_GAIN_MAX) { -+ dev_err(rk3308->plat_dev, "%s: invalid mic gain: %d\n", -+ __func__, gain); -+ return -EINVAL; -+ } - -- /* Step 10 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -- RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN); -+ if (rk3308->codec_ver == ACODEC_VERSION_A) { -+ /* -+ * From the TRM, there are only suupport 0dB(gain==0) and -+ * 20dB(gain==3) on the codec version A. -+ */ -+ if (!(gain == 0 || gain == RK3308_ADC_CH1_MIC_GAIN_MAX)) { -+ dev_err(rk3308->plat_dev, -+ "version A doesn't supported: %d, expect: 0,%d\n", -+ gain, RK3308_ADC_CH1_MIC_GAIN_MAX); -+ return 0; -+ } -+ } - -- /* Step 11 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); -+ return snd_soc_put_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 12 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -- RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK); -+static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value; - -- /* Step 13 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_SEL_MSK | -- RK3308_DAC_R_HPMIX_SEL_MSK, -- RK3308_DAC_L_HPMIX_I2S | -- RK3308_DAC_R_HPMIX_I2S); -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } - -- /* Step 14 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_UNMUTE | -- RK3308_DAC_R_HPMIX_UNMUTE, -- RK3308_DAC_L_HPMIX_UNMUTE | -- RK3308_DAC_R_HPMIX_UNMUTE); -+ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), &value); -+ if (value & RK3308_ADC_HPF_PATH_MSK) -+ rk3308->hpf_cutoff[e->reg] = 0; -+ else -+ rk3308->hpf_cutoff[e->reg] = 1; - -- /* Step 15 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_GAIN_MSK | -- RK3308_DAC_R_HPMIX_GAIN_MSK, -- RK3308_DAC_L_HPMIX_GAIN_0DB | -- RK3308_DAC_R_HPMIX_GAIN_0DB); -+ ucontrol->value.integer.value[0] = rk3308->hpf_cutoff[e->reg]; - -- /* Step 16 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_UNMUTE | -- RK3308_DAC_R_HPOUT_UNMUTE, -- RK3308_DAC_L_HPOUT_UNMUTE | -- RK3308_DAC_R_HPOUT_UNMUTE); -+ return 0; -+} - -- /* Step 17 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_UNMUTE | -- RK3308_DAC_R_LINEOUT_UNMUTE, -- RK3308_DAC_L_LINEOUT_UNMUTE | -- RK3308_DAC_R_LINEOUT_UNMUTE); -+static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.integer.value[0]; - -- /* Step 18 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -- RK3308_DAC_L_HPOUT_GAIN_MSK, -- RK3308_DAC_L_HPOUT_GAIN_0DB); -+ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "%s: Invalid ADC grp: %d\n", __func__, e->reg); -+ return -EINVAL; -+ } - -- /* Step 18 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -- RK3308_DAC_R_HPOUT_GAIN_MSK, -- RK3308_DAC_R_HPOUT_GAIN_0DB); -+ if (value) { -+ /* Enable high pass filter for ADCs */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), -+ RK3308_ADC_HPF_PATH_MSK, -+ RK3308_ADC_HPF_PATH_EN); -+ } else { -+ /* Disable high pass filter for ADCs. */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), -+ RK3308_ADC_HPF_PATH_MSK, -+ RK3308_ADC_HPF_PATH_DIS); -+ } - -- /* Step 19 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -- RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -+ rk3308->hpf_cutoff[e->reg] = value; - - return 0; - } - --static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) -+static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- /* Step 01 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_GAIN_MSK | RK3308_DAC_R_GAIN_MSK, -- RK3308_DAC_L_GAIN_0DB | RK3308_DAC_R_GAIN_0DB); -- -- /* -- * Step 02 -- * -- * Note1. In the step2, adjusting the register step by step to the -- * appropriate value and taking 20ms as time step -- */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -- RK3308_DAC_L_HPOUT_GAIN_MSK, -- RK3308_DAC_L_HPOUT_GAIN_NDB_39); -- -- /* Step 02 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -- RK3308_DAC_R_HPOUT_GAIN_MSK, -- RK3308_DAC_R_HPOUT_GAIN_NDB_39); -+ return snd_soc_get_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 03 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_UNMUTE | -- RK3308_DAC_R_HPMIX_UNMUTE, -- RK3308_DAC_L_HPMIX_MUTE | -- RK3308_DAC_R_HPMIX_MUTE); -+static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int dgain = ucontrol->value.integer.value[0]; - -- /* Step 04 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_SEL_MSK | -- RK3308_DAC_R_HPMIX_SEL_MSK, -- RK3308_DAC_L_HPMIX_NONE | -- RK3308_DAC_R_HPMIX_NONE); -+ if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) { -+ dev_err(rk3308->plat_dev, "%s: invalid l_dgain: %d\n", -+ __func__, dgain); -+ return -EINVAL; -+ } - -- /* Step 05 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_UNMUTE | -- RK3308_DAC_R_HPOUT_UNMUTE, -- RK3308_DAC_L_HPOUT_MUTE | -- RK3308_DAC_R_HPOUT_MUTE); -+ rk3308->hpout_l_dgain = dgain; - -- /* Step 06 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK, -- RK3308_DAC_L_DAC_INIT | RK3308_DAC_R_DAC_INIT); -+ return snd_soc_put_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 07 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_EN | RK3308_DAC_R_HPOUT_EN, -- RK3308_DAC_L_HPOUT_DIS | RK3308_DAC_R_HPOUT_DIS); -+static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ return snd_soc_get_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 08 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_UNMUTE | -- RK3308_DAC_R_LINEOUT_UNMUTE, -- RK3308_DAC_L_LINEOUT_MUTE | -- RK3308_DAC_R_LINEOUT_MUTE); -+static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int dgain = ucontrol->value.integer.value[0]; - -- /* Step 09 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -- RK3308_DAC_L_LINEOUT_EN | RK3308_DAC_R_LINEOUT_EN, -- RK3308_DAC_L_LINEOUT_DIS | RK3308_DAC_R_LINEOUT_DIS); -+ if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) { -+ dev_err(rk3308->plat_dev, "%s: invalid r_dgain: %d\n", -+ __func__, dgain); -+ return -EINVAL; -+ } - -- /* Step 10 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_EN | RK3308_DAC_R_HPMIX_EN, -- RK3308_DAC_L_HPMIX_DIS | RK3308_DAC_R_HPMIX_DIS); -+ rk3308->hpout_r_dgain = dgain; - -- /* Step 11 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN, -- RK3308_DAC_L_DAC_DIS | RK3308_DAC_R_DAC_DIS); -+ return snd_soc_put_volsw_range(kcontrol, ucontrol); -+} - -- /* Step 12 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN, -- RK3308_DAC_L_CLK_DIS | RK3308_DAC_R_CLK_DIS); -+static u32 to_mapped_grp(struct rk3308_codec_priv *rk3308, int idx) -+{ -+ return rk3308->i2s_sdis[idx]; -+} - -- /* Step 13 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -- RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN, -- RK3308_DAC_L_REF_DIS | RK3308_DAC_R_REF_DIS); -+static bool adc_for_each_grp(struct rk3308_codec_priv *rk3308, -+ int type, int idx, u32 *grp) -+{ -+ if (type == ADC_TYPE_NORMAL) { -+ u32 mapped_grp = to_mapped_grp(rk3308, idx); -+ int max_grps; -+ -+ if (rk3308->enable_all_adcs) -+ max_grps = ADC_LR_GROUP_MAX; -+ else -+ max_grps = rk3308->used_adc_grps; -+ -+ if (idx >= max_grps) -+ return false; -+ -+ if ((!rk3308->loopback_dacs_enabled) && -+ handle_loopback(rk3308) && -+ rk3308->loopback_grp == mapped_grp) { -+ /* -+ * Ths loopback DACs are closed, and specify the -+ * loopback ADCs. -+ */ -+ *grp = ADC_GRP_SKIP_MAGIC; -+ } else if (rk3308->en_always_grps_num && -+ rk3308->skip_grps[mapped_grp]) { -+ /* To set the skip flag if the ADC GRP is enabled. */ -+ *grp = ADC_GRP_SKIP_MAGIC; -+ } else { -+ *grp = mapped_grp; -+ } - -- /* Step 14 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_L_MSK | -- RK3308_DAC_POP_SOUND_R_MSK, -- RK3308_DAC_POP_SOUND_L_INIT | -- RK3308_DAC_POP_SOUND_R_INIT); -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_NORMAL, idx: %d, mapped_grp: %d, get grp: %d,\n", -+ idx, mapped_grp, *grp); -+ } else if (type == ADC_TYPE_ALL) { -+ if (idx >= ADC_LR_GROUP_MAX) -+ return false; -+ -+ *grp = idx; -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_ALL, idx: %d, get grp: %d\n", -+ idx, *grp); -+ } else if (type == ADC_TYPE_DBG) { -+ if (idx >= ADC_LR_GROUP_MAX) -+ return false; -+ -+ if (idx == (int)rk3308->cur_dbg_grp) -+ *grp = idx; -+ else -+ *grp = ADC_GRP_SKIP_MAGIC; -+ -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_DBG, idx: %d, get grp: %d\n", -+ idx, *grp); -+ } else { -+ if (idx >= 1) -+ return false; -+ -+ *grp = rk3308->loopback_grp; -+ dev_dbg(rk3308->plat_dev, -+ "ADC_TYPE_LOOPBACK, idx: %d, get grp: %d\n", -+ idx, *grp); -+ } - -- /* Step 15 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_BUF_REF_L_EN | RK3308_DAC_BUF_REF_R_EN, -- RK3308_DAC_BUF_REF_L_DIS | RK3308_DAC_BUF_REF_R_DIS); -+ return true; -+} - -- /* Step 16 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -- RK3308_DAC_CURRENT_EN, -- RK3308_DAC_CURRENT_DIS); -+static int rk3308_codec_get_dac_path_state(struct rk3308_codec_priv *rk3308) -+{ -+ return rk3308->dac_path_state; -+} - -- /* Step 17 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -- RK3308_DAC_L_HPOUT_WORK | RK3308_DAC_R_HPOUT_WORK, -- RK3308_DAC_L_HPOUT_INIT | RK3308_DAC_R_HPOUT_INIT); -+static void rk3308_codec_set_dac_path_state(struct rk3308_codec_priv *rk3308, -+ int state) -+{ -+ rk3308->dac_path_state = state; -+} - -- /* Step 18 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -- RK3308_DAC_L_HPMIX_WORK | RK3308_DAC_R_HPMIX_WORK, -- RK3308_DAC_L_HPMIX_INIT | RK3308_DAC_R_HPMIX_INIT); -+static void rk3308_headphone_ctl(struct rk3308_codec_priv *rk3308, int on) -+{ -+ if (rk3308->hp_ctl_gpio) -+ gpiod_direction_output(rk3308->hp_ctl_gpio, on); -+} - -- /* Step 19 */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -- RK3308_DAC_L_HPMIX_GAIN_MSK | -- RK3308_DAC_R_HPMIX_GAIN_MSK, -- RK3308_DAC_L_HPMIX_GAIN_NDB_6 | -- RK3308_DAC_R_HPMIX_GAIN_NDB_6); -+static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) -+{ -+ if (on) { -+ if (rk3308->pa_drv_gpio) { -+ gpiod_direction_output(rk3308->pa_drv_gpio, on); -+ msleep(rk3308->delay_pa_drv_ms); -+ } - -- /* -- * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -- * is set to 0x1, add the steps from the section Disable DAC -- * Configuration Standard Usage Flow after complete the step 19 -- */ -+ if (rk3308->spk_ctl_gpio) -+ gpiod_direction_output(rk3308->spk_ctl_gpio, on); -+ } else { -+ if (rk3308->spk_ctl_gpio) -+ gpiod_direction_output(rk3308->spk_ctl_gpio, on); - -- return 0; -+ if (rk3308->pa_drv_gpio) { -+ msleep(rk3308->delay_pa_drv_ms); -+ gpiod_direction_output(rk3308->pa_drv_gpio, on); -+ } -+ } - } - --static int rk3308_codec_power_on(struct snd_soc_codec *codec) -+static int rk3308_codec_reset(struct snd_soc_codec *codec) - { - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- /* 1. Supply the power of digital part and reset the Audio Codec */ -- /* Do nothing */ -+ reset_control_assert(rk3308->reset); -+ usleep_range(2000, 2500); /* estimated value */ -+ reset_control_deassert(rk3308->reset); - -- /* -- * 2. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] -- * to 0x1, to setup dc voltage of the DAC channel output -- */ -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_L_MSK, RK3308_DAC_POP_SOUND_L_INIT); -- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -- RK3308_DAC_POP_SOUND_R_MSK, RK3308_DAC_POP_SOUND_R_INIT); -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); -+ usleep_range(200, 300); /* estimated value */ -+ regmap_write(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_SYS_WORK | -+ RK3308_DAC_DIG_WORK | -+ RK3308_ADC_DIG_WORK); - -- /* -- * 3. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 -- * -- * Note: Only the reg (ADC_ANA_CON10+0x0)[6:0] represent the control -- * signal to select current to pre-charge/dis_charge -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ return 0; -+} - -- /* 4. Supply the power of the analog part(AVDD,AVDDRV) */ -+static int rk3308_codec_adc_dig_reset(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_RESET); -+ udelay(50); -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_WORK); - -- /* -- * 5. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup -- * reference voltage -- * -- * Note: Only the reg (ADC_ANA_CON10+0x0)[7] represent the enable -- * signal of reference voltage module -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); -+ return 0; -+} - -- /* -- * 6. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to -- * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to -- * 0x7f directly. The suggestion slot time of the step is 20ms. -- */ -- mdelay(20); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, -- RK3308_ADC_DONT_SEL_ALL); -+static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_DIG_WORK, -+ RK3308_DAC_DIG_RESET); -+ udelay(50); -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_DIG_WORK, -+ RK3308_DAC_DIG_WORK); - -- /* 7. Wait until the voltage of VCM keeps stable at the AVDD/2 */ -- usleep_range(200, 300); /* estimated value */ -+ return 0; -+} - -- /* -- * 8. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the -- * appropriate value(expect 0x0) for reducing power. -- */ -+static int rk3308_set_bias_level(struct snd_soc_codec *codec, -+ enum snd_soc_bias_level level) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- /* TODO: choose an appropriate charge value */ -+ switch (level) { -+ case SND_SOC_BIAS_ON: -+ break; -+ case SND_SOC_BIAS_PREPARE: -+ break; -+ case SND_SOC_BIAS_STANDBY: -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ break; -+ case SND_SOC_BIAS_OFF: -+ break; -+ } - - return 0; - } - --static int rk3308_codec_power_off(struct snd_soc_codec *codec) -+static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -+ unsigned int fmt) - { -+ struct snd_soc_codec *codec = codec_dai->codec; - struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; -+ int idx, grp, is_master; -+ int type = ADC_TYPE_ALL; -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; -+ adc_aif2 |= RK3308_ADC_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; -+ dac_aif2 |= RK3308_DAC_MODE_SLAVE; -+ is_master = 0; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; -+ adc_aif2 |= RK3308_ADC_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; -+ dac_aif2 |= RK3308_DAC_MODE_MASTER; -+ is_master = 1; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_DSP_A: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; -+ break; -+ case SND_SOC_DAIFMT_I2S: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; -+ break; -+ case SND_SOC_DAIFMT_LEFT_J: -+ adc_aif1 |= RK3308_ADC_I2S_MODE_LJ; -+ dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; -+ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; -+ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; -+ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; -+ break; -+ default: -+ return -EINVAL; -+ } - - /* -- * 1. Keep the power on and disable the DAC and ADC path according to -- * the section power on configuration standard usage flow. -+ * Hold ADC Digital registers start at master mode -+ * -+ * There are 8 ADCs and use the same SCLK and LRCK internal for master -+ * mode, We need to make sure that they are in effect at the same time, -+ * otherwise they will cause the abnormal clocks. - */ -+ if (is_master) -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_RESET); -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), -+ RK3308_ADC_I2S_LRC_POL_MSK | -+ RK3308_ADC_I2S_MODE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), -+ RK3308_ADC_IO_MODE_MSK | -+ RK3308_ADC_MODE_MSK | -+ RK3308_ADC_I2S_BIT_CLK_POL_MSK, -+ adc_aif2); -+ } - -- /* 2. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 0x1 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, RK3308_ADC_SEL_I_64(1)); -+ /* Hold ADC Digital registers end at master mode */ -+ if (is_master) -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_DIG_WORK, -+ RK3308_ADC_DIG_WORK); - -- /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_REF_EN, RK3308_ADC_REF_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_LRC_POL_MSK | -+ RK3308_DAC_I2S_MODE_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_IO_MODE_MSK | -+ RK3308_DAC_MODE_MSK | -+ RK3308_DAC_I2S_BIT_CLK_POL_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308, -+ struct snd_pcm_hw_params *params) -+{ -+ unsigned int dac_aif1 = 0, dac_aif2 = 0; -+ -+ /* Clear the status of DAC DIG Digital reigisters */ -+ rk3308_codec_dac_dig_reset(rk3308); -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; -+ dac_aif2 |= RK3308_DAC_I2S_WORK; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, -+ RK3308_DAC_I2S_VALID_LEN_MSK | -+ RK3308_DAC_I2S_LR_MSK, -+ dac_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, -+ RK3308_DAC_I2S_MSK, -+ dac_aif2); -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308, -+ struct snd_pcm_hw_params *params) -+{ -+ unsigned int adc_aif1 = 0, adc_aif2 = 0; -+ int type = ADC_TYPE_NORMAL; -+ int idx, grp; -+ -+ /* Clear the status of ADC DIG Digital reigisters */ -+ rk3308_codec_adc_dig_reset(rk3308); -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 1: -+ adc_aif1 |= RK3308_ADC_I2S_MONO; -+ break; -+ case 2: -+ case 4: -+ case 6: -+ case 8: -+ adc_aif1 |= RK3308_ADC_I2S_STEREO; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; -+ adc_aif2 |= RK3308_ADC_I2S_WORK; -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), -+ RK3308_ADC_I2S_VALID_LEN_MSK | -+ RK3308_ADC_I2S_LR_MSK | -+ RK3308_ADC_I2S_TYPE_MSK, -+ adc_aif1); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), -+ RK3308_ADC_I2S_MSK, -+ adc_aif2); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_update_adc_grps(struct rk3308_codec_priv *rk3308, -+ struct snd_pcm_hw_params *params) -+{ -+ switch (params_channels(params)) { -+ case 1: -+ rk3308->used_adc_grps = 1; -+ break; -+ case 2: -+ case 4: -+ case 6: -+ case 8: -+ rk3308->used_adc_grps = params_channels(params) / 2; -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Invalid channels: %d\n", -+ params_channels(params)); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ int dgain; -+ -+ if (mute) { -+ for (dgain = 0x2; dgain <= 0x7; dgain++) { -+ /* -+ * Keep the max -> min digital CIC interpolation -+ * filter gain step by step. -+ * -+ * loud: 0x2; whisper: 0x7 -+ */ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_DAC_DIG_CON04, -+ RK3308_DAC_CIC_IF_GAIN_MSK, -+ dgain); -+ usleep_range(200, 300); /* estimated value */ -+ } -+ -+#if !DEBUG_POP_ALWAYS -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 0); -+#endif -+ } else { -+#if !DEBUG_POP_ALWAYS -+ if (rk3308->dac_output == DAC_LINEOUT) -+ rk3308_speaker_ctl(rk3308, 1); -+ else if (rk3308->dac_output == DAC_HPOUT) -+ rk3308_headphone_ctl(rk3308, 1); -+ -+ if (rk3308->delay_start_play_ms) -+ msleep(rk3308->delay_start_play_ms); -+#endif -+ for (dgain = 0x7; dgain >= 0x2; dgain--) { -+ /* -+ * Keep the min -> max digital CIC interpolation -+ * filter gain step by step -+ * -+ * loud: 0x2; whisper: 0x7 -+ */ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_DAC_DIG_CON04, -+ RK3308_DAC_CIC_IF_GAIN_MSK, -+ dgain); -+ usleep_range(200, 300); /* estimated value */ -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_digital_fadein(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int dgain, dgain_ref; -+ -+ if (rk3308->hpout_l_dgain != rk3308->hpout_r_dgain) { -+ pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n", -+ rk3308->hpout_l_dgain, rk3308->hpout_r_dgain); -+ dgain_ref = min(rk3308->hpout_l_dgain, rk3308->hpout_r_dgain); -+ } else { -+ dgain_ref = rk3308->hpout_l_dgain; -+ } - - /* -- * 4.Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f -- * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f -- * directly. The suggestion slot time of the step is 20ms -+ * We'd better change the gain of the left and right channels -+ * at the same time to avoid different listening - */ -- mdelay(20); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -- RK3308_ADC_CURRENT_CHARGE_MSK, -- RK3308_ADC_DONT_SEL_ALL); -+ for (dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39; -+ dgain <= dgain_ref; dgain++) { -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ dgain); -+ -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ dgain); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_digital_fadeout(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int l_dgain, r_dgain; -+ -+ /* -+ * Note. In the step2, adjusting the register step by step to -+ * the appropriate value and taking 20ms as time step -+ */ -+ regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON05, &l_dgain); -+ l_dgain &= RK3308_DAC_L_HPOUT_GAIN_MSK; -+ -+ regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON06, &r_dgain); -+ r_dgain &= RK3308_DAC_R_HPOUT_GAIN_MSK; -+ -+ if (l_dgain != r_dgain) { -+ pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n", -+ l_dgain, r_dgain); -+ l_dgain = min(l_dgain, r_dgain); -+ } -+ -+ /* -+ * We'd better change the gain of the left and right channels -+ * at the same time to avoid different listening -+ */ -+ while (l_dgain >= RK3308_DAC_L_HPOUT_GAIN_NDB_39) { -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ l_dgain); -+ -+ /* Step 02 decrease dgains for de-pop */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ l_dgain); -+ -+ usleep_range(200, 300); /* estimated value */ -+ -+ if (l_dgain == RK3308_DAC_L_HPOUT_GAIN_NDB_39) -+ break; -+ -+ l_dgain--; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_lineout_enable(struct rk3308_codec_priv *rk3308) -+{ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_DC_FROM_INTERNAL); -+ } -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN); -+ -+ udelay(20); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL); -+ -+ udelay(20); -+ } -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE); -+ udelay(20); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_lineout_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_MUTE | -+ RK3308_DAC_R_LINEOUT_MUTE); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_DIS | -+ RK3308_DAC_R_LINEOUT_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_hpout_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_WORK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_WORK); -+ -+ udelay(20); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN); -+ -+ udelay(20); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK); -+ -+ udelay(20); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE); -+ -+ udelay(20); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_hpout_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_INIT | -+ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_DIS | -+ RK3308_DAC_R_HPOUT_DIS); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_INIT | -+ RK3308_DAC_R_HPOUT_INIT); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_MUTE | -+ RK3308_DAC_R_HPOUT_MUTE); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_switch(struct rk3308_codec_priv *rk3308, -+ int dac_output) -+{ int ret = 0; -+ -+ if (rk3308->dac_output == dac_output) { -+ dev_info(rk3308->plat_dev, -+ "Don't need to change dac_output: %d\n", dac_output); -+ goto out; -+ } -+ -+ switch (dac_output) { -+ case DAC_LINEOUT: -+ case DAC_HPOUT: -+ case DAC_LINEOUT_HPOUT: -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Unknown value: %d\n", dac_output); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (rk3308_codec_get_dac_path_state(rk3308) == PATH_BUSY) { -+ /* -+ * We can only switch the audio path to LINEOUT or HPOUT on -+ * codec during playbacking, otherwise, just update the -+ * dac_output flag. -+ */ -+ switch (dac_output) { -+ case DAC_LINEOUT: -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 1); -+ rk3308_codec_dac_hpout_disable(rk3308); -+ rk3308_codec_dac_lineout_enable(rk3308); -+ break; -+ case DAC_HPOUT: -+ rk3308_speaker_ctl(rk3308, 0); -+ rk3308_headphone_ctl(rk3308, 1); -+ rk3308_codec_dac_lineout_disable(rk3308); -+ rk3308_codec_dac_hpout_enable(rk3308); -+ break; -+ case DAC_LINEOUT_HPOUT: -+ rk3308_speaker_ctl(rk3308, 1); -+ rk3308_headphone_ctl(rk3308, 1); -+ rk3308_codec_dac_lineout_enable(rk3308); -+ rk3308_codec_dac_hpout_enable(rk3308); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ rk3308->dac_output = dac_output; -+out: -+ dev_dbg(rk3308->plat_dev, "switch dac_output to: %d\n", -+ rk3308->dac_output); -+ -+ return ret; -+} -+ -+static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Note1. If the ACODEC_DAC_ANA_CON12[6] or ACODEC_DAC_ANA_CON12[2] -+ * is set to 0x1, ignoring the step9~12. -+ */ -+ -+ /* -+ * Note2. If the ACODEC_ DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -+ * is set to 0x1, the ADC0 or ADC1 should be enabled firstly, and -+ * please refer to Enable ADC Configuration Standard Usage Flow(expect -+ * step7~step9,step14). -+ */ -+ -+ /* -+ * Note3. If no opening the line out, ignoring the step6, step17 and -+ * step19. -+ */ -+ -+ /* -+ * Note4. If no opening the headphone out, ignoring the step3,step7~8, -+ * step16 and step18. -+ */ -+ -+ /* -+ * Note5. In the step18, adjust the register step by step to the -+ * appropriate value and taking 10ms as one time step -+ */ -+ -+ /* -+ * 1. Set the ACODEC_DAC_ANA_CON0[0] to 0x1, to enable the current -+ * source of DAC -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_MSK, -+ RK3308_DAC_CURRENT_EN); -+ -+ udelay(20); -+ -+ /* -+ * 2. Set the ACODEC_DAC_ANA_CON1[6] and ACODEC_DAC_ANA_CON1[2] to 0x1, -+ * to enable the reference voltage buffer -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_MSK | -+ RK3308_DAC_BUF_REF_R_MSK, -+ RK3308_DAC_BUF_REF_L_EN | -+ RK3308_DAC_BUF_REF_R_EN); -+ -+ /* Waiting the stable reference voltage */ -+ mdelay(1); -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_WORK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_WORK); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B && -+ (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT)) { -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_DC_FROM_INTERNAL); -+ -+ udelay(20); -+ } -+ -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | -+ RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_EN | -+ RK3308_DAC_R_HPMIX_EN); -+ -+ /* Waiting the stable HPMIX */ -+ mdelay(1); -+ -+ /* Step 06. Reset HPMIX and recover HPMIX gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_INIT | -+ RK3308_DAC_R_HPMIX_INIT); -+ udelay(50); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK); -+ -+ udelay(20); -+ -+ if (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN); -+ -+ udelay(20); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL | -+ RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL); -+ -+ udelay(20); -+ } -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | -+ RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_EN | -+ RK3308_DAC_R_REF_EN); -+ -+ udelay(20); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | -+ RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_EN | -+ RK3308_DAC_R_CLK_EN); -+ -+ udelay(20); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | -+ RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_EN | -+ RK3308_DAC_R_DAC_EN); -+ -+ udelay(20); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | -+ RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_WORK | -+ RK3308_DAC_R_DAC_WORK); -+ -+ udelay(20); -+ -+ /* Step 15 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_I2S | -+ RK3308_DAC_R_HPMIX_I2S); -+ -+ udelay(20); -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE); -+ -+ udelay(20); -+ -+ /* Step 17: Put configuration HPMIX Gain to DAPM */ -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE); -+ -+ udelay(20); -+ } -+ -+ if (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE); -+ udelay(20); -+ } -+ -+ /* Step 20, put configuration HPOUT gain to DAPM control */ -+ /* Step 21, put configuration LINEOUT gain to DAPM control */ -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Just for HPOUT */ -+ rk3308_codec_digital_fadein(rk3308); -+ } -+ -+ rk3308->dac_endisable = true; -+ -+ /* TODO: TRY TO TEST DRIVE STRENGTH */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Step 00 skipped. Keep the DAC channel work and input the mute signal. -+ */ -+ -+ /* Step 01 skipped. May set the min gain for LINEOUT. */ -+ -+ /* Step 02 skipped. May set the min gain for HPOUT. */ -+ -+ if (rk3308->dac_output == DAC_HPOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT) { -+ /* Just for HPOUT */ -+ rk3308_codec_digital_fadeout(rk3308); -+ } -+ -+ /* Step 03 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE, -+ RK3308_DAC_L_HPMIX_UNMUTE | -+ RK3308_DAC_R_HPMIX_UNMUTE); -+ -+ /* Step 04 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_SEL_MSK | -+ RK3308_DAC_R_HPMIX_SEL_MSK, -+ RK3308_DAC_L_HPMIX_NONE | -+ RK3308_DAC_R_HPMIX_NONE); -+ /* Step 05 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_UNMUTE | -+ RK3308_DAC_R_HPOUT_UNMUTE, -+ RK3308_DAC_L_HPOUT_MUTE | -+ RK3308_DAC_R_HPOUT_MUTE); -+ -+ /* Step 06 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_WORK | -+ RK3308_DAC_R_DAC_WORK, -+ RK3308_DAC_L_DAC_INIT | -+ RK3308_DAC_R_DAC_INIT); -+ -+ /* Step 07 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_EN | -+ RK3308_DAC_R_HPOUT_EN, -+ RK3308_DAC_L_HPOUT_DIS | -+ RK3308_DAC_R_HPOUT_DIS); -+ -+ /* Step 08 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_UNMUTE | -+ RK3308_DAC_R_LINEOUT_UNMUTE, -+ RK3308_DAC_L_LINEOUT_MUTE | -+ RK3308_DAC_R_LINEOUT_MUTE); -+ -+ /* Step 09 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_EN | -+ RK3308_DAC_R_LINEOUT_EN, -+ RK3308_DAC_L_LINEOUT_DIS | -+ RK3308_DAC_R_LINEOUT_DIS); -+ -+ /* Step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_EN | -+ RK3308_DAC_R_HPMIX_EN, -+ RK3308_DAC_L_HPMIX_DIS | -+ RK3308_DAC_R_HPMIX_DIS); -+ -+ /* Step 11 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_DAC_EN | -+ RK3308_DAC_R_DAC_EN, -+ RK3308_DAC_L_DAC_DIS | -+ RK3308_DAC_R_DAC_DIS); -+ -+ /* Step 12 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_CLK_EN | -+ RK3308_DAC_R_CLK_EN, -+ RK3308_DAC_L_CLK_DIS | -+ RK3308_DAC_R_CLK_DIS); -+ -+ /* Step 13 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, -+ RK3308_DAC_L_REF_EN | -+ RK3308_DAC_R_REF_EN, -+ RK3308_DAC_L_REF_DIS | -+ RK3308_DAC_R_REF_DIS); -+ -+ /* Step 14 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_INIT | -+ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); -+ -+ /* Step 15 */ -+ if (rk3308->codec_ver == ACODEC_VERSION_B && -+ (rk3308->dac_output == DAC_LINEOUT || -+ rk3308->dac_output == DAC_LINEOUT_HPOUT)) { -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_VCM | -+ RK3308_DAC_R_SEL_DC_FROM_VCM); -+ } -+ -+ /* Step 16 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_BUF_REF_L_EN | -+ RK3308_DAC_BUF_REF_R_EN, -+ RK3308_DAC_BUF_REF_L_DIS | -+ RK3308_DAC_BUF_REF_R_DIS); -+ -+ /* Step 17 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_CURRENT_EN, -+ RK3308_DAC_CURRENT_DIS); -+ -+ /* Step 18 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, -+ RK3308_DAC_L_HPOUT_WORK | -+ RK3308_DAC_R_HPOUT_WORK, -+ RK3308_DAC_L_HPOUT_INIT | -+ RK3308_DAC_R_HPOUT_INIT); -+ -+ /* Step 19 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK, -+ RK3308_DAC_L_HPMIX_WORK | -+ RK3308_DAC_R_HPMIX_WORK); -+ -+ /* Step 20 skipped, may set the min gain for HPOUT. */ -+ -+ /* -+ * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] -+ * is set to 0x1, add the steps from the section Disable ADC -+ * Configuration Standard Usage Flow after complete the step 19 -+ * -+ * IF USING LINE-IN -+ * rk3308_codec_adc_ana_disable(rk3308, type); -+ */ -+ -+ rk3308->dac_endisable = false; -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_on(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int v; -+ -+ /* 0. Supply the power of digital part and reset the Audio Codec */ -+ /* Do nothing */ -+ -+ /* -+ * 1. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] -+ * to 0x1, to setup dc voltage of the DAC channel output. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_L_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_L_INIT); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, -+ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 2. Configure ACODEC_DAC_ANA_CON15[1:0] and -+ * ACODEC_DAC_ANA_CON15[5:4] to 0x1, to setup dc voltage of -+ * the DAC channel output. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK, -+ RK3308_DAC_L_SEL_DC_FROM_VCM); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, -+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, -+ RK3308_DAC_R_SEL_DC_FROM_VCM); -+ } -+ -+ /* -+ * 3. Configure the register ACODEC_ADC_ANA_CON10[3:0] to 7’b000_0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_SEL_I(0x1)); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 4. Configure the register ACODEC_ADC_ANA_CON14[3:0] to -+ * 4’b0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, -+ RK3308_DAC_SEL_I(0x1)); -+ } -+ -+ /* 5. Supply the power of the analog part(AVDD,AVDDRV) */ -+ -+ /* -+ * 6. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup -+ * reference voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 7. Configure the register ACODEC_ADC_ANA_CON14[4] to 0x1 to -+ * setup reference voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_VCM_LINEOUT_EN, -+ RK3308_DAC_VCM_LINEOUT_EN); -+ } -+ -+ /* -+ * 8. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to -+ * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to -+ * 0x7f directly. Here the slot time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0x7f; v++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 9. Change the register ACODEC_ADC_ANA_CON14[3:0] from the 0x1 -+ * to 0xf step by step or configure the -+ * ACODEC_ADC_ANA_CON14[3:0] to 0xf directly. Here the slot -+ * time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0xf; v++) { -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ } -+ -+ /* 10. Wait until the voltage of VCM keeps stable at the AVDD/2 */ -+ msleep(20); /* estimated value */ -+ -+ /* -+ * 11. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the -+ * appropriate value(expect 0x0) for reducing power. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, 0x7c); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 12. Configure the register ACODEC_DAC_ANA_CON14[6:0] to the -+ * appropriate value(expect 0x0) for reducing power. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, 0xf); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_power_off(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int v; -+ -+ /* -+ * 0. Keep the power on and disable the DAC and ADC path according to -+ * the section power on configuration standard usage flow. -+ */ -+ -+ /* -+ * 1. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 7’b000_0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ RK3308_ADC_SEL_I(0x1)); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 2. Configure the register ACODEC_DAC_ANA_CON14[3:0] to -+ * 4’b0001. -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_CURRENT_CHARGE_MSK, -+ RK3308_DAC_SEL_I(0x1)); -+ } -+ -+ /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_REF_EN, -+ RK3308_ADC_REF_DIS); -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* 4. Configure the register ACODEC_DAC_ANA_CON14[7] to 0x0 */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, -+ RK3308_DAC_VCM_LINEOUT_EN, -+ RK3308_DAC_VCM_LINEOUT_DIS); -+ } -+ -+ /* -+ * 5. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f -+ * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f -+ * directly. Here the slot time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0x7f; v++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* -+ * 6. Change the register ACODEC_DAC_ANA_CON14[3:0] from the 0x1 -+ * to 0xf step by step or configure the -+ * ACODEC_DAC_ANA_CON14[3:0] to 0xf directly. Here the slot -+ * time of the step is 200us. -+ */ -+ for (v = 0x1; v <= 0x7f; v++) { -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON10(0), -+ RK3308_ADC_CURRENT_CHARGE_MSK, -+ v); -+ udelay(200); -+ } -+ } -+ -+ /* 7. Wait until the voltage of VCM keeps stable at the AGND */ -+ msleep(20); /* estimated value */ -+ -+ /* 8. Power off the analog power supply */ -+ /* 9. Power off the digital power supply */ -+ -+ /* Do something via hardware */ -+ -+ return 0; -+} -+ -+static int rk3308_codec_headset_detect_enable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Set ACODEC_DAC_ANA_CON0[1] to 0x1, to enable the headset insert -+ * detection -+ * -+ * Note. When the voltage of PAD HPDET> 8*AVDD/9, the output value of -+ * the pin_hpdet will be set to 0x1 and assert a interrupt -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_HEADPHONE_DET_MSK, -+ RK3308_DAC_HEADPHONE_DET_EN); -+ -+ return 0; -+} -+ -+static int rk3308_codec_headset_detect_disable(struct rk3308_codec_priv *rk3308) -+{ -+ /* -+ * Set ACODEC_DAC_ANA_CON0[1] to 0x0, to disable the headset insert -+ * detection -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, -+ RK3308_DAC_HEADPHONE_DET_MSK, -+ RK3308_DAC_HEADPHONE_DET_DIS); -+ -+ return 0; -+} -+ -+static int rk3308_codec_check_i2s_sdis(struct rk3308_codec_priv *rk3308, -+ int num) -+{ -+ int i, j, ret = 0; -+ -+ switch (num) { -+ case 1: -+ rk3308->which_i2s = ACODEC_TO_I2S1_2CH; -+ break; -+ case 2: -+ rk3308->which_i2s = ACODEC_TO_I2S3_4CH; -+ break; -+ case 4: -+ rk3308->which_i2s = ACODEC_TO_I2S2_8CH; -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Invalid i2s sdis num: %d\n", num); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ for (i = 0; i < num; i++) { -+ if (rk3308->i2s_sdis[i] > ADC_LR_GROUP_MAX - 1) { -+ dev_err(rk3308->plat_dev, -+ "i2s_sdis[%d]: %d is overflow\n", -+ i, rk3308->i2s_sdis[i]); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ for (j = 0; j < num; j++) { -+ if (i == j) -+ continue; -+ -+ if (rk3308->i2s_sdis[i] == rk3308->i2s_sdis[j]) { -+ dev_err(rk3308->plat_dev, -+ "Invalid i2s_sdis: [%d]%d == [%d]%d\n", -+ i, rk3308->i2s_sdis[i], -+ j, rk3308->i2s_sdis[j]); -+ ret = -EINVAL; -+ goto err; -+ } -+ } -+ } -+ -+err: -+ return ret; -+} -+ -+static int rk3308_codec_adc_grps_route_config(struct rk3308_codec_priv *rk3308) -+{ -+ int idx = 0; -+ -+ if (rk3308->which_i2s == ACODEC_TO_I2S2_8CH) { -+ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S2_8CH_SDI(idx, rk3308->i2s_sdis[idx])); -+ } -+ } else if (rk3308->which_i2s == ACODEC_TO_I2S3_4CH) { -+ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S3_4CH_SDI(idx, rk3308->i2s_sdis[idx])); -+ } -+ } else if (rk3308->which_i2s == ACODEC_TO_I2S1_2CH) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S1_2CH_SDI(rk3308->i2s_sdis[idx])); -+ } -+ -+ return 0; -+} -+ -+/* Put default one-to-one mapping */ -+static int rk3308_codec_adc_grps_route_default(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int idx; -+ -+ /* -+ * The GRF values may be kept the previous status after hot reboot, -+ * if the property 'rockchip,adc-grps-route' is not set, we need to -+ * recover default the order of sdi/sdo for i2s2_8ch/i2s3_8ch/i2s1_2ch. -+ */ -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S1_2CH_SDI(0)); -+ -+ for (idx = 0; idx < 2; idx++) { -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S3_4CH_SDI(idx, idx)); -+ } -+ -+ /* Using i2s2_8ch by default. */ -+ rk3308->which_i2s = ACODEC_TO_I2S2_8CH; -+ rk3308->to_i2s_grps = ADC_LR_GROUP_MAX; -+ -+ for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) { -+ rk3308->i2s_sdis[idx] = idx; -+ regmap_write(rk3308->grf, GRF_SOC_CON1, -+ GRF_I2S2_8CH_SDI(idx, idx)); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_grps_route(struct rk3308_codec_priv *rk3308, -+ struct device_node *np) -+{ -+ int num, ret; -+ -+ num = of_count_phandle_with_args(np, "rockchip,adc-grps-route", NULL); -+ if (num < 0) { -+ if (num == -ENOENT) { -+ /* Not use 'rockchip,adc-grps-route' property here */ -+ rk3308_codec_adc_grps_route_default(rk3308); -+ ret = 0; -+ } else { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,adc-grps-route' num: %d\n", -+ num); -+ ret = num; -+ } -+ return ret; -+ } -+ -+ ret = of_property_read_u32_array(np, "rockchip,adc-grps-route", -+ rk3308->i2s_sdis, num); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,adc-grps-route': %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_check_i2s_sdis(rk3308, num); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to check i2s_sdis: %d\n", ret); -+ return ret; -+ } -+ -+ rk3308->to_i2s_grps = num; -+ -+ rk3308_codec_adc_grps_route_config(rk3308); -+ -+ return 0; -+} -+ -+static int check_micbias(int micbias) -+{ -+ switch (micbias) { -+ case RK3308_ADC_MICBIAS_VOLT_0_85: -+ case RK3308_ADC_MICBIAS_VOLT_0_8: -+ case RK3308_ADC_MICBIAS_VOLT_0_75: -+ case RK3308_ADC_MICBIAS_VOLT_0_7: -+ case RK3308_ADC_MICBIAS_VOLT_0_65: -+ case RK3308_ADC_MICBIAS_VOLT_0_6: -+ case RK3308_ADC_MICBIAS_VOLT_0_55: -+ case RK3308_ADC_MICBIAS_VOLT_0_5: -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static bool handle_loopback(struct rk3308_codec_priv *rk3308) -+{ -+ /* The version B doesn't need to handle loopback. */ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) -+ return false; -+ -+ switch (rk3308->loopback_grp) { -+ case 0: -+ case 1: -+ case 2: -+ case 3: -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool has_en_always_grps(struct rk3308_codec_priv *rk3308) -+{ -+ int idx; -+ -+ if (rk3308->en_always_grps_num) { -+ for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) { -+ if (rk3308->en_always_grps[idx] >= 0 && -+ rk3308->en_always_grps[idx] <= ADC_LR_GROUP_MAX - 1) -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -+ int micbias) -+{ -+ int ret; -+ -+ if (rk3308->ext_micbias != EXT_MICBIAS_NONE) -+ return 0; -+ -+ /* 0. Power up the ACODEC and keep the AVDDH stable */ -+ -+ /* Step 1. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ -+ ret = check_micbias(micbias); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", -+ micbias); -+ return ret; -+ } -+ -+ /* -+ * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range -+ * control signal of MICBIAS voltage -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -+ micbias); -+ -+ /* Step 2. Wait until the VCMH keep stable */ -+ msleep(20); /* estimated value */ -+ -+ /* -+ * Step 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 -+ * -+ * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable -+ * signal of current source for MICBIAS -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_EN); -+ -+ /* -+ * Step 4. Configure the (ADC_ANA_CON7+0x40)[3] or -+ * (ADC_ANA_CON7+0x80)[3] to 0x1. -+ * -+ * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and -+ * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 -+ */ -+ if (rk3308->micbias1) -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_EN); -+ -+ if (rk3308->micbias2) -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_EN); -+ -+ /* waiting micbias stabled*/ -+ mdelay(50); -+ -+ rk3308->enable_micbias = true; -+ -+ return 0; -+} -+ -+static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) -+{ -+ if (rk3308->ext_micbias != EXT_MICBIAS_NONE) -+ return 0; -+ -+ /* Step 0. Enable the MICBIAS and keep the Audio Codec stable */ -+ /* Do nothing */ -+ -+ /* -+ * Step 1. Configure the (ADC_ANA_CON7+0x40)[3] or -+ * (ADC_ANA_CON7+0x80)[3] to 0x0 -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_DIS); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2), -+ RK3308_ADC_MIC_BIAS_BUF_EN, -+ RK3308_ADC_MIC_BIAS_BUF_DIS); -+ -+ /* -+ * Step 2. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 -+ * -+ * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable -+ * signal of current source for MICBIAS -+ */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0), -+ RK3308_ADC_MICBIAS_CURRENT_MSK, -+ RK3308_ADC_MICBIAS_CURRENT_DIS); -+ -+ rk3308->enable_micbias = false; -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308, -+ int type) -+{ -+ int idx, grp; -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_INIT | -+ RK3308_ADC_CH2_ADC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 2 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_INIT | -+ RK3308_ADC_CH2_ALC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 3 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_INIT | -+ RK3308_ADC_CH2_MIC_INIT); -+ } -+ -+ usleep_range(200, 250); /* estimated value */ -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 2 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 3 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308, -+ int type) -+{ -+ unsigned int agc_func_en; -+ int idx, grp; -+ -+ /* -+ * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], -+ * to select the line-in or microphone as input of ADC -+ * -+ * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, -+ * ADC6, ADC7, and ADC8 -+ */ -+ if (rk3308->adc_grp0_using_linein) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -+ RK3308_ADC_CH1_IN_SEL_MSK | -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_LINEIN | -+ RK3308_ADC_CH2_IN_LINEIN); -+ -+ /* Keep other ADCs as MIC-IN */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ /* The groups without line-in are >= 1 */ -+ if (grp < 1 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON07(grp), -+ RK3308_ADC_CH1_IN_SEL_MSK | -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_MIC | -+ RK3308_ADC_CH2_IN_MIC); -+ } -+ } else { -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON07(grp), -+ RK3308_ADC_CH1_IN_SEL_MSK | -+ RK3308_ADC_CH2_IN_SEL_MSK, -+ RK3308_ADC_CH1_IN_MIC | -+ RK3308_ADC_CH2_IN_MIC); -+ } -+ } -+ -+ /* -+ * 2. Set ACODEC_ADC_ANA_CON0[7] and [3] to 0x1, to end the mute station -+ * of ADC, to enable the MIC module, to enable the reference voltage -+ * buffer, and to end the initialization of MIC -+ */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_UNMUTE | -+ RK3308_ADC_CH2_MIC_UNMUTE, -+ RK3308_ADC_CH1_MIC_UNMUTE | -+ RK3308_ADC_CH2_MIC_UNMUTE); -+ } -+ -+ /* -+ * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source -+ * of audio -+ */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_EN); -+ } -+ -+ /* -+ * This is mainly used for BIST mode that wait ADCs are stable. -+ * -+ * By tested results, the type delay is >40us, but we need to leave -+ * enough delay margin. -+ */ -+ usleep_range(400, 500); -+ -+ /* vendor step 4*/ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_BUF_REF_EN | -+ RK3308_ADC_CH2_BUF_REF_EN, -+ RK3308_ADC_CH1_BUF_REF_EN | -+ RK3308_ADC_CH2_BUF_REF_EN); -+ } -+ -+ /* vendor step 5 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_EN | -+ RK3308_ADC_CH2_MIC_EN, -+ RK3308_ADC_CH1_MIC_EN | -+ RK3308_ADC_CH2_MIC_EN); -+ } -+ -+ /* vendor step 6 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_EN | -+ RK3308_ADC_CH2_ALC_EN, -+ RK3308_ADC_CH1_ALC_EN | -+ RK3308_ADC_CH2_ALC_EN); -+ } -+ -+ /* vendor step 7 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH2_CLK_EN, -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH2_CLK_EN); -+ } -+ -+ /* vendor step 8 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH2_ADC_EN, -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH2_ADC_EN); -+ } -+ -+ /* vendor step 9 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK); -+ } -+ -+ /* vendor step 10 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK); -+ } -+ -+ /* vendor step 11 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK); -+ } -+ -+ /* vendor step 12 */ -+ -+ /* vendor step 13 */ -+ -+ /* vendor step 14 */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), -+ &agc_func_en); -+ if (rk3308->adc_zerocross || -+ agc_func_en & RK3308_AGC_FUNC_SEL_EN) { -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ZEROCROSS_DET_EN, -+ RK3308_ADC_CH1_ZEROCROSS_DET_EN); -+ } -+ regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), -+ &agc_func_en); -+ if (rk3308->adc_zerocross || -+ agc_func_en & RK3308_AGC_FUNC_SEL_EN) { -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH2_ZEROCROSS_DET_EN, -+ RK3308_ADC_CH2_ZEROCROSS_DET_EN); -+ } -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ rk3308->adc_grps_endisable[grp] = true; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308, -+ int type) -+{ -+ int idx, grp; -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 1 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ZEROCROSS_DET_EN | -+ RK3308_ADC_CH2_ZEROCROSS_DET_EN, -+ RK3308_ADC_CH1_ZEROCROSS_DET_DIS | -+ RK3308_ADC_CH2_ZEROCROSS_DET_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 2 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_EN | -+ RK3308_ADC_CH2_ADC_EN, -+ RK3308_ADC_CH1_ADC_DIS | -+ RK3308_ADC_CH2_ADC_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 3 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_CLK_EN | -+ RK3308_ADC_CH2_CLK_EN, -+ RK3308_ADC_CH1_CLK_DIS | -+ RK3308_ADC_CH2_CLK_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 4 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_EN | -+ RK3308_ADC_CH2_ALC_EN, -+ RK3308_ADC_CH1_ALC_DIS | -+ RK3308_ADC_CH2_ALC_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 5 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_EN | -+ RK3308_ADC_CH2_MIC_EN, -+ RK3308_ADC_CH1_MIC_DIS | -+ RK3308_ADC_CH2_MIC_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 6 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_BUF_REF_EN | -+ RK3308_ADC_CH2_BUF_REF_EN, -+ RK3308_ADC_CH1_BUF_REF_DIS | -+ RK3308_ADC_CH2_BUF_REF_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 7 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp), -+ RK3308_ADC_CURRENT_MSK, -+ RK3308_ADC_CURRENT_DIS); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 8 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), -+ RK3308_ADC_CH1_ADC_WORK | -+ RK3308_ADC_CH2_ADC_WORK, -+ RK3308_ADC_CH1_ADC_INIT | -+ RK3308_ADC_CH2_ADC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 9 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), -+ RK3308_ADC_CH1_ALC_WORK | -+ RK3308_ADC_CH2_ALC_WORK, -+ RK3308_ADC_CH1_ALC_INIT | -+ RK3308_ADC_CH2_ALC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ /* vendor step 10 */ -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), -+ RK3308_ADC_CH1_MIC_WORK | -+ RK3308_ADC_CH2_MIC_WORK, -+ RK3308_ADC_CH1_MIC_INIT | -+ RK3308_ADC_CH2_MIC_INIT); -+ } -+ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ rk3308->adc_grps_endisable[grp] = false; -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_capture(struct rk3308_codec_priv *rk3308) -+{ -+ int idx, grp = 0; -+ int type = ADC_TYPE_NORMAL; -+ -+ rk3308_codec_adc_ana_enable(rk3308, type); -+ rk3308_codec_adc_reinit_mics(rk3308, type); -+ -+ if (rk3308->adc_grp0_using_linein) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_RIGHT); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_LEFT); -+ } else { -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (handle_loopback(rk3308) && -+ idx == rk3308->loopback_grp && -+ grp == ADC_GRP_SKIP_MAGIC) { -+ /* -+ * Switch to dummy BIST mode (BIST keep reset -+ * now) to keep the zero input data in I2S bus. -+ * -+ * It may cause the glitch if we hold the ADC -+ * digtital i2s module in codec. -+ * -+ * Then, the grp which is set from loopback_grp. -+ */ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(rk3308->loopback_grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_BIST_SINE); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(rk3308->loopback_grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_BIST_SINE); -+ } else { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_LEFT); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_RIGHT); -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static void rk3308_codec_adc_mclk_disable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_MCLK_MSK, -+ RK3308_ADC_MCLK_DIS); -+} -+ -+static void rk3308_codec_adc_mclk_enable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_ADC_MCLK_MSK, -+ RK3308_ADC_MCLK_EN); -+ udelay(20); -+} -+ -+static void rk3308_codec_dac_mclk_disable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_MCLK_MSK, -+ RK3308_DAC_MCLK_DIS); -+} -+ -+static void rk3308_codec_dac_mclk_enable(struct rk3308_codec_priv *rk3308) -+{ -+ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, -+ RK3308_DAC_MCLK_MSK, -+ RK3308_DAC_MCLK_EN); -+ udelay(20); -+} -+ -+static int rk3308_codec_open_dbg_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_enable(rk3308, ADC_TYPE_DBG); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_dbg_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_DBG); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_all_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_ALL); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_capture(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_NORMAL); -+ -+ return 0; -+} -+ -+static int rk3308_codec_open_playback(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_dac_enable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_close_playback(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_dac_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_llp_down(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_mclk_disable(rk3308); -+ rk3308_codec_dac_mclk_disable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_llp_up(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_adc_mclk_enable(rk3308); -+ rk3308_codec_dac_mclk_enable(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dlp_down(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308_codec_power_off(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dlp_up(struct rk3308_codec_priv *rk3308) -+{ -+ rk3308_codec_power_on(rk3308); -+ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); -+ -+ return 0; -+} -+ -+/* Just used for debug and trace power state */ -+static void rk3308_codec_set_pm_state(struct rk3308_codec_priv *rk3308, -+ int pm_state) -+{ -+ int ret; -+ -+ switch (pm_state) { -+ case PM_LLP_DOWN: -+ rk3308_codec_llp_down(rk3308); -+ break; -+ case PM_LLP_UP: -+ rk3308_codec_llp_up(rk3308); -+ break; -+ case PM_DLP_DOWN: -+ rk3308_codec_dlp_down(rk3308); -+ break; -+ case PM_DLP_UP: -+ rk3308_codec_dlp_up(rk3308); -+ break; -+ case PM_DLP_DOWN2: -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); -+ clk_disable_unprepare(rk3308->pclk); -+ break; -+ case PM_DLP_UP2: -+ ret = clk_prepare_enable(rk3308->pclk); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable acodec pclk: %d\n", ret); -+ goto err; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_rx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_rx: %d\n", ret); -+ goto err; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_tx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_tx: %d\n", ret); -+ goto err; -+ } -+ break; -+ default: -+ dev_err(rk3308->plat_dev, "Invalid pm_state: %d\n", pm_state); -+ goto err; -+ } -+ -+ rk3308->pm_state = pm_state; -+ -+err: -+ return; -+} -+ -+static void rk3308_codec_update_adcs_status(struct rk3308_codec_priv *rk3308, -+ int state) -+{ -+ int idx, grp; -+ -+ /* Update skip_grps flags if the ADCs need to be enabled always. */ -+ if (state == PATH_BUSY) { -+ for (idx = 0; idx < rk3308->used_adc_grps; idx++) { -+ u32 mapped_grp = to_mapped_grp(rk3308, idx); -+ -+ for (grp = 0; grp < rk3308->en_always_grps_num; grp++) { -+ u32 en_always_grp = rk3308->en_always_grps[grp]; -+ -+ if (mapped_grp == en_always_grp) -+ rk3308->skip_grps[en_always_grp] = 1; -+ } -+ } -+ } -+} -+ -+static int rk3308_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_pcm_str *playback_str = -+ &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; -+ int type = ADC_TYPE_LOOPBACK; -+ int idx, grp; -+ int ret; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ /* DAC only supports 2 channels */ -+ rk3308_codec_dac_mclk_enable(rk3308); -+ rk3308_codec_open_playback(rk3308); -+ rk3308_codec_dac_dig_config(rk3308, params); -+ rk3308_codec_set_dac_path_state(rk3308, PATH_BUSY); -+ } else { -+ if (rk3308->micbias_num && -+ !rk3308->enable_micbias) -+ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); -+ -+ rk3308_codec_adc_mclk_enable(rk3308); -+ ret = rk3308_codec_update_adc_grps(rk3308, params); -+ if (ret < 0) -+ return ret; -+ -+ if (handle_loopback(rk3308)) { -+ if (rk3308->micbias_num && -+ (params_channels(params) == 2) && -+ to_mapped_grp(rk3308, 0) == rk3308->loopback_grp) -+ rk3308_codec_micbias_disable(rk3308); -+ -+ /* Check the DACs are opened */ -+ if (playback_str->substream_opened) { -+ rk3308->loopback_dacs_enabled = true; -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_LEFT); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_RIGHT); -+ } -+ } else { -+ rk3308->loopback_dacs_enabled = false; -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_BIST_SINE); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_BIST_SINE); -+ } -+ } -+ } -+ -+ rk3308_codec_open_capture(rk3308); -+ rk3308_codec_adc_dig_config(rk3308, params); -+ rk3308_codec_update_adcs_status(rk3308, PATH_BUSY); -+ } -+ -+ return 0; -+} -+ -+static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, -+ int cmd, struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ int type = ADC_TYPE_LOOPBACK; -+ int idx, grp; -+ -+ if (handle_loopback(rk3308) && -+ rk3308->dac_output == DAC_LINEOUT && -+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ if (cmd == SNDRV_PCM_TRIGGER_START) { -+ struct snd_pcm_str *capture_str = -+ &substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; -+ -+ if (capture_str->substream_opened) -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->loopback_work, -+ msecs_to_jiffies(rk3308->delay_loopback_handle_ms)); -+ } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { -+ /* -+ * Switch to dummy bist mode to kick the glitch during disable -+ * ADCs and keep zero input data -+ */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_BIST_SINE); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_BIST_SINE); -+ } -+ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_LOOPBACK); -+ } -+ } -+ -+ return 0; -+} -+ -+static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ rk3308_codec_close_playback(rk3308); -+ rk3308_codec_dac_mclk_disable(rk3308); -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); -+ } else { -+ rk3308_codec_close_capture(rk3308); -+ if (!has_en_always_grps(rk3308)) { -+ rk3308_codec_adc_mclk_disable(rk3308); -+ rk3308_codec_update_adcs_status(rk3308, PATH_IDLE); -+ if (rk3308->micbias_num && -+ rk3308->enable_micbias) -+ rk3308_codec_micbias_disable(rk3308); -+ } -+ -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ } -+} -+ -+static struct snd_soc_dai_ops rk3308_dai_ops = { -+ .hw_params = rk3308_hw_params, -+ .set_fmt = rk3308_set_dai_fmt, -+ .mute_stream = rk3308_mute_stream, -+ .trigger = rk3308_pcm_trigger, -+ .shutdown = rk3308_pcm_shutdown, -+}; -+ -+static struct snd_soc_dai_driver rk3308_dai[] = { -+ { -+ .name = "rk3308-hifi", -+ .id = RK3308_HIFI, -+ .playback = { -+ .stream_name = "HiFi Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .capture = { -+ .stream_name = "HiFi Capture", -+ .channels_min = 1, -+ .channels_max = 8, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S20_3LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE), -+ }, -+ .ops = &rk3308_dai_ops, -+ }, -+}; -+ -+static int rk3308_suspend(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ if (rk3308->no_deep_low_power) -+ goto out; -+ -+ rk3308_codec_dlp_down(rk3308); -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); -+ clk_disable_unprepare(rk3308->pclk); -+ -+out: -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ return 0; -+} -+ -+static int rk3308_resume(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ int ret = 0; -+ -+ if (rk3308->no_deep_low_power) -+ goto out; -+ -+ ret = clk_prepare_enable(rk3308->pclk); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable acodec pclk: %d\n", ret); -+ goto out; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_rx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_rx: %d\n", ret); -+ goto out; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_tx); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to enable i2s mclk_tx: %d\n", ret); -+ goto out; -+ } -+ -+ rk3308_codec_dlp_up(rk3308); -+out: -+ rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ return ret; -+} -+ -+static int rk3308_codec_default_gains(struct rk3308_codec_priv *rk3308) -+{ -+ int grp; -+ -+ /* Prepare ADC gains */ -+ /* vendor step 12, set MIC PGA default gains */ -+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp), -+ RK3308_ADC_CH1_MIC_GAIN_MSK | -+ RK3308_ADC_CH2_MIC_GAIN_MSK, -+ RK3308_ADC_CH1_MIC_GAIN_0DB | -+ RK3308_ADC_CH2_MIC_GAIN_0DB); -+ } -+ -+ /* vendor step 13, set ALC default gains */ -+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp), -+ RK3308_ADC_CH1_ALC_GAIN_MSK, -+ RK3308_ADC_CH1_ALC_GAIN_0DB); -+ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(grp), -+ RK3308_ADC_CH2_ALC_GAIN_MSK, -+ RK3308_ADC_CH2_ALC_GAIN_0DB); -+ } -+ -+ /* Prepare DAC gains */ -+ /* Step 15, set HPMIX default gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, -+ RK3308_DAC_L_HPMIX_GAIN_MSK | -+ RK3308_DAC_R_HPMIX_GAIN_MSK, -+ RK3308_DAC_L_HPMIX_GAIN_NDB_6 | -+ RK3308_DAC_R_HPMIX_GAIN_NDB_6); -+ -+ /* Step 18, set HPOUT default gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, -+ RK3308_DAC_L_HPOUT_GAIN_MSK, -+ RK3308_DAC_L_HPOUT_GAIN_NDB_39); -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, -+ RK3308_DAC_R_HPOUT_GAIN_MSK, -+ RK3308_DAC_R_HPOUT_GAIN_NDB_39); -+ -+ /* Using the same gain to HPOUT LR channels */ -+ rk3308->hpout_l_dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39; -+ -+ /* Step 19, set LINEOUT default gains */ -+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, -+ RK3308_DAC_L_LINEOUT_GAIN_MSK | -+ RK3308_DAC_R_LINEOUT_GAIN_MSK, -+ RK3308_DAC_L_LINEOUT_GAIN_NDB_6 | -+ RK3308_DAC_R_LINEOUT_GAIN_NDB_6); -+ -+ return 0; -+} -+ -+static int rk3308_codec_setup_en_always_adcs(struct rk3308_codec_priv *rk3308, -+ struct device_node *np) -+{ -+ int num, ret; -+ -+ num = of_count_phandle_with_args(np, "rockchip,en-always-grps", NULL); -+ if (num < 0) { -+ if (num == -ENOENT) { -+ /* -+ * If there is note use 'rockchip,en-always-grps' -+ * property, return 0 is also right. -+ */ -+ ret = 0; -+ } else { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,adc-grps-route' num: %d\n", -+ num); -+ ret = num; -+ } -+ -+ rk3308->en_always_grps_num = 0; -+ return ret; -+ } -+ -+ rk3308->en_always_grps_num = num; -+ -+ ret = of_property_read_u32_array(np, "rockchip,en-always-grps", -+ rk3308->en_always_grps, num); -+ if (ret < 0) { -+ dev_err(rk3308->plat_dev, -+ "Failed to read 'rockchip,en-always-grps': %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Clear all of skip_grps flags. */ -+ for (num = 0; num < ADC_LR_GROUP_MAX; num++) -+ rk3308->skip_grps[num] = 0; -+ -+ /* The loopback grp should not be enabled always. */ -+ for (num = 0; num < rk3308->en_always_grps_num; num++) { -+ if (rk3308->en_always_grps[num] == rk3308->loopback_grp) { -+ dev_err(rk3308->plat_dev, -+ "loopback_grp: %d should not be enabled always!\n", -+ rk3308->loopback_grp); -+ ret = -EINVAL; -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) -+{ -+ int ret; -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ ret = snd_soc_add_codec_controls(rk3308->codec, -+ mic_gains_b, -+ ARRAY_SIZE(mic_gains_b)); -+ if (ret) { -+ dev_err(rk3308->plat_dev, -+ "%s: add mic_gains_b failed: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ } else { -+ ret = snd_soc_add_codec_controls(rk3308->codec, -+ mic_gains_a, -+ ARRAY_SIZE(mic_gains_a)); -+ if (ret) { -+ dev_err(rk3308->plat_dev, -+ "%s: add mic_gains_a failed: %d\n", -+ __func__, ret); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk3308_codec_check_micbias(struct rk3308_codec_priv *rk3308, -+ struct device_node *np) -+{ -+ struct device *dev = (struct device *)rk3308->plat_dev; -+ int num = 0, ret; -+ -+ /* Check internal micbias */ -+ rk3308->micbias1 = -+ of_property_read_bool(np, "rockchip,micbias1"); -+ if (rk3308->micbias1) -+ num++; -+ -+ rk3308->micbias2 = -+ of_property_read_bool(np, "rockchip,micbias2"); -+ if (rk3308->micbias2) -+ num++; -+ -+ rk3308->micbias_volt = RK3308_ADC_MICBIAS_VOLT_0_85; /* by default */ -+ rk3308->micbias_num = num; -+ -+ /* Check external micbias */ -+ rk3308->ext_micbias = EXT_MICBIAS_NONE; -+ -+ rk3308->micbias_en_gpio = devm_gpiod_get_optional(dev, -+ "micbias-en", -+ GPIOD_IN); -+ if (!rk3308->micbias_en_gpio) { -+ dev_info(dev, "Don't need micbias-en gpio\n"); -+ } else if (IS_ERR(rk3308->micbias_en_gpio)) { -+ ret = PTR_ERR(rk3308->micbias_en_gpio); -+ dev_err(dev, "Unable to claim gpio micbias-en\n"); -+ return ret; -+ } else if (gpiod_get_value(rk3308->micbias_en_gpio)) { -+ rk3308->ext_micbias = EXT_MICBIAS_FUNC1; -+ } -+ -+ rk3308->vcc_micbias = devm_regulator_get_optional(dev, -+ "vmicbias"); -+ if (IS_ERR(rk3308->vcc_micbias)) { -+ if (PTR_ERR(rk3308->vcc_micbias) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ dev_info(dev, "no vmicbias regulator found\n"); -+ } else { -+ ret = regulator_enable(rk3308->vcc_micbias); -+ if (ret) { -+ dev_err(dev, "Can't enable vmicbias: %d\n", ret); -+ return ret; -+ } -+ rk3308->ext_micbias = EXT_MICBIAS_FUNC2; -+ } -+ -+ dev_info(dev, "Check ext_micbias: %d\n", rk3308->ext_micbias); -+ -+ return 0; -+} -+ -+static int rk3308_codec_dapm_controls_prepare(struct rk3308_codec_priv *rk3308) -+{ -+ int grp; -+ -+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { -+ rk3308->hpf_cutoff[grp] = 0; -+ rk3308->agc_l[grp] = 0; -+ rk3308->agc_r[grp] = 0; -+ rk3308->agc_asr_l[grp] = AGC_ASR_96KHZ; -+ rk3308->agc_asr_r[grp] = AGC_ASR_96KHZ; -+ } -+ -+ rk3308_codec_dapm_mic_gains(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308) -+{ -+ /* Clear registers for ADC and DAC */ -+ rk3308_codec_close_playback(rk3308); -+ rk3308_codec_close_all_capture(rk3308); -+ rk3308_codec_default_gains(rk3308); -+ rk3308_codec_llp_down(rk3308); -+ rk3308_codec_dapm_controls_prepare(rk3308); -+ -+ return 0; -+} -+ -+static int rk3308_probe(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ int ext_micbias; -+ -+ rk3308->codec = codec; -+ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); -+ -+ rk3308_codec_reset(codec); -+ rk3308_codec_power_on(rk3308); -+ -+ /* From vendor recommend, disable micbias at first. */ -+ ext_micbias = rk3308->ext_micbias; -+ rk3308->ext_micbias = EXT_MICBIAS_NONE; -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308->ext_micbias = ext_micbias; -+ -+ rk3308_codec_prepare(rk3308); -+ if (!rk3308->no_hp_det) -+ rk3308_codec_headset_detect_enable(rk3308); -+ -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ -+ return 0; -+} - -- /* 5. Wait until the voltage of VCM keeps stable at the AGND */ -- usleep_range(200, 300); /* estimated value */ -+static int rk3308_remove(struct snd_soc_codec *codec) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 0); -+ if (!rk3308->no_hp_det) -+ rk3308_codec_headset_detect_disable(rk3308); -+ rk3308_codec_micbias_disable(rk3308); -+ rk3308_codec_power_off(rk3308); - -- /* 6. Power off the analog power supply */ -- /* 7. Power off the digital power supply */ -+ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); - -- /* Do something via hardware */ -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); - - return 0; - } - --static int check_micbias(int micbias) -+static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -+ .probe = rk3308_probe, -+ .remove = rk3308_remove, -+ .suspend = rk3308_suspend, -+ .resume = rk3308_resume, -+ .set_bias_level = rk3308_set_bias_level, -+ .controls = rk3308_codec_dapm_controls, -+ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+}; -+ -+static const struct reg_default rk3308_codec_reg_defaults[] = { -+ { RK3308_GLB_CON, 0x07 }, -+}; -+ -+static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) - { -- switch (micbias) { -- case RK3308_ADC_MICBIAS_VOLT_0_85: -- case RK3308_ADC_MICBIAS_VOLT_0_8: -- case RK3308_ADC_MICBIAS_VOLT_0_75: -- case RK3308_ADC_MICBIAS_VOLT_0_7: -- case RK3308_ADC_MICBIAS_VOLT_0_65: -- case RK3308_ADC_MICBIAS_VOLT_0_6: -- case RK3308_ADC_MICBIAS_VOLT_0_55: -- case RK3308_ADC_MICBIAS_VOLT_0_5: -- return 0; -- } -+ /* All registers can be read / write */ -+ return true; -+} - -- return -EINVAL; -+static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ return true; - } - --static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, -- int micbias) -+static void rk3308_codec_hpdetect_work(struct work_struct *work) - { -- int ch = rk3308->adc_ch; -- int ret; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(work, struct rk3308_codec_priv, hpdet_work.work); -+ unsigned int val; -+ int need_poll = 0, need_irq = 0; -+ int need_report = 0, report_type = 0; -+ int dac_output = DAC_LINEOUT; -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ /* Check headphone plugged/unplugged directly. */ -+ regmap_read(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_STATUS, &val); -+ regmap_write(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_STATUS_CLR, val); -+ -+ if (rk3308->hp_jack_reversed) { -+ switch (val) { -+ case 0x0: -+ case 0x2: -+ dac_output = DAC_HPOUT; -+ report_type = SND_JACK_HEADPHONE; -+ break; -+ default: -+ break; -+ } -+ } else { -+ switch (val) { -+ case 0x1: -+ dac_output = DAC_HPOUT; -+ report_type = SND_JACK_HEADPHONE; -+ break; -+ default: -+ /* Includes val == 2 or others. */ -+ break; -+ } -+ } - -- if (ch != 1 && ch != 2) { -- dev_err(rk3308->plat_dev, -- "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -- __func__, ch); -- return -EINVAL; -- } -+ rk3308_codec_dac_switch(rk3308, dac_output); -+ if (rk3308->hpdet_jack) -+ snd_soc_jack_report(rk3308->hpdet_jack, -+ report_type, -+ SND_JACK_HEADPHONE); - -- /* 1. Power up the ACODEC and keep the AVDDH stable */ -+ enable_irq(rk3308->irq); - -- /* 2. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ -- ret = check_micbias(micbias); -- if (ret < 0) { -- dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", -- micbias); -- return ret; -+ return; - } - -- /* -- * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range -- * control signal of MICBIAS voltage -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), -- RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, -- micbias); -+ /* Check headphone unplugged via poll. */ -+ regmap_read(rk3308->regmap, RK3308_DAC_DIG_CON14, &val); - -- /* 3. Wait until the VCMH keep stable */ -- usleep_range(200, 300); /* estimated value */ -+ if (rk3308->hp_jack_reversed) { -+ if (!val) { -+ rk3308->hp_plugged = true; -+ report_type = SND_JACK_HEADPHONE; - -- /* 4. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -- RK3308_ADC_MICBIAS_CURRENT_MSK, -- RK3308_ADC_MICBIAS_CURRENT_EN); -+ need_report = 1; -+ need_irq = 1; -+ } else { -+ if (rk3308->hp_plugged) { -+ rk3308->hp_plugged = false; -+ need_report = 1; -+ } -+ need_poll = 1; -+ } -+ } else { -+ if (!val) { -+ rk3308->hp_plugged = false; - -- /* -- * 5. Configure the (ADC_ANA_CON7+0x40)[3] or (ADC_ANA_CON7+0x80)[3] -- * to 0x1. -- * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and -- * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 -- */ -+ need_report = 1; -+ need_irq = 1; -+ } else { -+ if (!rk3308->hp_plugged) { -+ rk3308->hp_plugged = true; -+ report_type = SND_JACK_HEADPHONE; -+ need_report = 1; -+ } -+ need_poll = 1; -+ } -+ } - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_MIC_BIAS_BUF_EN, -- RK3308_ADC_MIC_BIAS_BUF_EN); -+ if (need_poll) -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->hpdet_work, -+ msecs_to_jiffies(HPDET_POLL_MS)); - -- return 0; --} -+ if (need_report) { -+ if (report_type) -+ dac_output = DAC_HPOUT; - --static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) --{ -- int ch = rk3308->adc_ch; -+ rk3308_codec_dac_switch(rk3308, dac_output); - -- if (ch != 1 && ch != 2) { -- dev_err(rk3308->plat_dev, -- "%s: currnet ch: %d, only ch1/2 control MICBIAS1/2\n", -- __func__, ch); -- return -EINVAL; -+ if (rk3308->hpdet_jack) -+ snd_soc_jack_report(rk3308->hpdet_jack, -+ report_type, -+ SND_JACK_HEADPHONE); - } - -- /* 1. Enable the MICBIAS and keep the Audio Codec stable */ -- /* Do nothing */ -- -- /* -- * 2. Configure the (ADC_ANA_CON7+0x40)[3] or -- * (ADC_ANA_CON7+0x80)[3] to 0x0 -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_MIC_BIAS_BUF_EN, -- RK3308_ADC_MIC_BIAS_BUF_DIS); -- -- /* 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(ch), -- RK3308_ADC_MICBIAS_CURRENT_MSK, -- RK3308_ADC_MICBIAS_CURRENT_DIS); -+ if (need_irq) -+ enable_irq(rk3308->irq); -+} - -- return 0; -+static void rk3308_codec_loopback_work(struct work_struct *work) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(work, struct rk3308_codec_priv, loopback_work.work); -+ int type = ADC_TYPE_LOOPBACK; -+ int idx, grp; -+ -+ /* Prepare loopback ADCs */ -+ rk3308_codec_adc_ana_enable(rk3308, type); -+ -+ /* Waiting ADCs are stable */ -+ msleep(ADC_STABLE_MS); -+ -+ /* Recover normal mode after enable ADCs */ -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { -+ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) -+ continue; -+ -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_L_CH_BIST_MSK, -+ RK3308_ADC_L_CH_NORMAL_LEFT); -+ regmap_update_bits(rk3308->regmap, -+ RK3308_ADC_DIG_CON03(grp), -+ RK3308_ADC_R_CH_BIST_MSK, -+ RK3308_ADC_R_CH_NORMAL_RIGHT); -+ } - } - --static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308) -+static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data) - { -- int ch = rk3308->adc_ch; -+ struct rk3308_codec_priv *rk3308 = data; - - /* -- * 1. Set he max level and min level of the ALC need to control. -- * -- * These values are estimated -+ * For the high level irq trigger, disable irq and avoid a lot of -+ * repeated irq handlers entry. - */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -- RK3308_AGC_LO_8BITS_AGC_MIN_MSK, -- 0x16); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(ch), -- RK3308_AGC_HI_8BITS_AGC_MIN_MSK, -- 0x40); -- -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -- RK3308_AGC_LO_8BITS_AGC_MAX_MSK, -- 0x26); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON05(ch), -- RK3308_AGC_HI_8BITS_AGC_MAX_MSK, -- 0x40); -+ disable_irq_nosync(rk3308->irq); -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->hpdet_work, msecs_to_jiffies(10)); - -- /* -- * 2. Set ACODEC_ALC_DIG_CON4[2:0] according to the sample rate -- * -- * By default is 44.1KHz for sample. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(ch), -- RK3308_AGC_APPROX_RATE_MSK, -- RK3308_AGC_APPROX_RATE_44_1K); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(ch), -- RK3308_AGC_APPROX_RATE_MSK, -- RK3308_AGC_APPROX_RATE_44_1K); -- -- /* 3. Set ACODEC_ALC_DIG_CON9[6] to 0x1, to enable the ALC module */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_EN); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_EN); -+ return IRQ_HANDLED; -+} - -- /* -- * 4. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -- * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -- * to 0x3, to enable the ALC module to control the gain of PGA. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -- RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -- RK3308_ADC_ALCL_CON_GAIN_PGAL_EN | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); -+void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+ struct snd_soc_jack *hpdet_jack); -+EXPORT_SYMBOL_GPL(rk3308_codec_set_jack_detect_cb); - -- /* -- * 5.Observe the current ALC output gain by reading -- * ACODEC_ALC_DIG_CON12[4:0] -- * -- * The default GAIN is 0x0c -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON12(ch), -- RK3308_AGC_GAIN_MSK, -- 0x0c); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON12(ch), -- RK3308_AGC_GAIN_MSK, -- 0x0c); -+static void rk3308_codec_set_jack_detect(struct snd_soc_codec *codec, -+ struct snd_soc_jack *hpdet_jack) -+{ -+ struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); - -- return 0; --} -+ rk3308->hpdet_jack = hpdet_jack; - --static int rk3308_codec_alc_disable(struct rk3308_codec_priv *rk3308) --{ -- int ch = rk3308->adc_ch; -+ /* To detect jack once during startup */ -+ disable_irq_nosync(rk3308->irq); -+ queue_delayed_work(system_power_efficient_wq, -+ &rk3308->hpdet_work, msecs_to_jiffies(10)); - -- /* -- * 1. Set ACODEC_ALC_DIG_CON9[6] to 0x0, to disable the ALC module, -- * then the ALC output gain will keep to the last value -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_DIS); -- regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(ch), -- RK3308_AGC_FUNC_SEL_MSK, -- RK3308_AGC_FUNC_SEL_DIS); -+ dev_info(rk3308->plat_dev, "%s: Request detect hp jack once\n", -+ __func__); -+} - -- /* -- * 2. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)[1:0], -- * (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0] -- * to 0x0, to disable the ALC module to control the gain of PGA. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(ch), -- RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, -- RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS | -- RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); -+static const struct regmap_config rk3308_codec_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = RK3308_DAC_ANA_CON15, -+ .writeable_reg = rk3308_codec_write_read_reg, -+ .readable_reg = rk3308_codec_write_read_reg, -+ .volatile_reg = rk3308_codec_volatile_reg, -+ .reg_defaults = rk3308_codec_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), -+ .cache_type = REGCACHE_FLAT, -+}; - -- return 0; -+static ssize_t pm_state_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ -+ return sprintf(buf, "pm_state: %d\n", rk3308->pm_state); - } - --static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308) -+static ssize_t pm_state_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- unsigned int adc_aif1 = 0, adc_aif2 = 0; -- unsigned int agc_func_en; -- int ch = rk3308->adc_ch; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long pm_state; -+ int ret = kstrtoul(buf, 10, &pm_state); - -- /* -- * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], -- * to select the line-in or microphone as input of ADC -- * -- * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, -- * ADC6, ADC7, and ADC8 -- */ -- if (ch == 0) { -- if (rk3308->adc_ch0_using_linein) { -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH1_IN_SEL_MSK, -- RK3308_ADC_CH1_IN_LINEIN); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH2_IN_SEL_MSK, -- RK3308_ADC_CH2_IN_LINEIN); -- } else { -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH1_IN_SEL_MSK, -- RK3308_ADC_CH1_IN_MIC); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(ch), -- RK3308_ADC_CH2_IN_SEL_MSK, -- RK3308_ADC_CH2_IN_MIC); -- } -+ if (ret < 0) { -+ dev_err(dev, "Invalid pm_state: %ld, ret: %d\n", -+ pm_state, ret); -+ return -EINVAL; - } - -- /* -- * 2. Set ACODEC_ADC_ANA_CON0[7:0] to 0xff, to end the mute station -- * of ADC, to enable the MIC module, to enable the reference voltage -- * buffer, and to end the initialization of MIC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -- RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -- RK3308_ADC_CH1_CH2_MIC_ALL); -+ rk3308_codec_set_pm_state(rk3308, pm_state); - -- /* -- * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source -- * of audio -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -- RK3308_ADC_CURRENT_MSK, -- RK3308_ADC_CURRENT_EN); -+ dev_info(dev, "Store pm_state: %d\n", rk3308->pm_state); - -- /* -- * 4. Set ACODEC_ADC_ANA_CON2[7:0] to 0x77, to enable the ALC module, -- * to enable the zero-crossing detection function, and to end the -- * initialization of ALC -- * -- * Note2. Please set ACODEC_ADC_ANA_CON2[7:0] to 0x33 in step4 -- * if the AGC function is closed -- */ -+ return count; -+} - -- adc_aif1 = RK3308_ADC_CH1_ALC_EN | RK3308_ADC_CH1_ALC_WORK; -- regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -- if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -- adc_aif1 |= RK3308_ADC_CH1_ZEROCROSS_DET_EN; -+static ssize_t adc_grps_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ u32 grp; -+ int type = ADC_TYPE_NORMAL, count = 0; -+ int idx; -+ -+ count += sprintf(buf + count, "current used adc_grps:\n"); -+ count += sprintf(buf + count, "- normal:"); -+ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) -+ count += sprintf(buf + count, " %d", grp); -+ count += sprintf(buf + count, "\n"); -+ count += sprintf(buf + count, "- loopback: %d\n", -+ rk3308->loopback_grp); - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH1_ALC_ZC_MSK, -- adc_aif1); -+ return count; -+} - -- adc_aif2 = RK3308_ADC_CH2_ALC_EN | RK3308_ADC_CH2_ALC_WORK; -- regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(ch), &agc_func_en); -- if (agc_func_en & RK3308_AGC_FUNC_SEL_EN) -- adc_aif2 |= RK3308_ADC_CH2_ZEROCROSS_DET_EN; -+static ssize_t adc_grps_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ char adc_type; -+ int grps, ret; -+ -+ ret = sscanf(buf, "%c,%d", &adc_type, &grps); -+ if (ret != 2) { -+ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", -+ __func__, ret); -+ return -EFAULT; -+ } - -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH2_ALC_ZC_MSK, -- adc_aif2); -+ if (adc_type == 'n') -+ rk3308->used_adc_grps = grps; -+ else if (adc_type == 'l') -+ rk3308->loopback_grp = grps; - -- /* -- * 5. Set ACODEC_ADC_ANA_CON5[7:0] to 0x77, to enable the clock and -- * ADC module, and to end the initialization of ADC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH1_ADC_CLK_MSK, -- RK3308_ADC_CH1_CLK_EN | -- RK3308_ADC_CH1_ADC_EN | -- RK3308_ADC_CH1_ADC_WORK); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH2_ADC_CLK_MSK, -- RK3308_ADC_CH2_CLK_EN | -- RK3308_ADC_CH2_ADC_EN | -- RK3308_ADC_CH2_ADC_WORK); -+ return count; -+} - -- /* -- * 6. Set ACODEC_ADC_ANA_CON1[5:4] and ACODEC_ADC_ANA_CON1[1:0], -- * to select the gain of the MIC -- * -- * By default is 0db. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH1_MIC_GAIN_MSK, -- RK3308_ADC_CH1_MIC_GAIN_0DB); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH2_MIC_GAIN_MSK, -- RK3308_ADC_CH2_MIC_GAIN_0DB); -+static ssize_t adc_grps_route_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ char which_i2s[32] = {0}; -+ int count = 0; -+ u32 grp; - -- /* -- * 7.Set ACODEC_ADC_ANA_CON3[4:0] and ACODEC_ADC_ANA_CON4[3:0] to -- * select the gain of ALC -- * -- * By default is 0db. -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(ch), -- RK3308_ADC_CH1_ALC_GAIN_MSK, -- RK3308_ADC_CH1_ALC_GAIN_0DB); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(ch), -- RK3308_ADC_CH2_ALC_GAIN_MSK, -- RK3308_ADC_CH2_ALC_GAIN_0DB); -+ switch (rk3308->which_i2s) { -+ case ACODEC_TO_I2S1_2CH: -+ strcpy(which_i2s, "i2s1_2ch"); -+ break; -+ case ACODEC_TO_I2S3_4CH: -+ strcpy(which_i2s, "i2s3_4ch"); -+ break; -+ default: -+ strcpy(which_i2s, "i2s2_8ch"); -+ break; -+ } - -- /* 8.Begin recording */ -+ count += sprintf(buf + count, "%s from acodec route mapping:\n", -+ which_i2s); -+ for (grp = 0; grp < rk3308->to_i2s_grps; grp++) { -+ count += sprintf(buf + count, "* sdi_%d <-- sdo_%d\n", -+ grp, rk3308->i2s_sdis[grp]); -+ } - -- return 0; -+ return count; - } - --static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308) -+static ssize_t adc_grps_route_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- int ch = rk3308->adc_ch; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ int which_i2s, idx, i2s_sdis[ADC_LR_GROUP_MAX]; -+ int ret; - -- /* -- * 1. Set ACODEC_ADC_ANA_CON2[7:0] to 0x0, to disable the ALC module, -- * to disable the zero-crossing detection function, and to begin the -- * initialization of ALC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH1_ALC_ZC_MSK, -- 0); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(ch), -- RK3308_ADC_CH2_ALC_ZC_MSK, -- 0); -+ ret = sscanf(buf, "%d,%d,%d,%d,%d", &which_i2s, -+ &i2s_sdis[0], &i2s_sdis[1], &i2s_sdis[2], &i2s_sdis[3]); -+ if (ret != 5) { -+ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", -+ __func__, ret); -+ goto err; -+ } - -- /* -- * 2. Set ACODEC_ADC_ANA_CON5[7:0] to 0x0, to disable the clock and -- * ADC module, and to begin the initialization of ADC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH1_ADC_CLK_MSK, -- 0); -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(ch), -- RK3308_ADC_CH2_ADC_CLK_MSK, -- 0); -+ if (which_i2s < ACODEC_TO_I2S2_8CH || -+ which_i2s > ACODEC_TO_I2S1_2CH) { -+ dev_err(rk3308->plat_dev, "Invalid i2s type: %d\n", which_i2s); -+ goto err; -+ } - -- /* -- * 3. Set ACODEC_ADC_ANA_CON0[7:0] to 0x88, to disable the MIC module, -- * to disable the reference voltage buffer, and to begin the -- * initialization of MIC -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(ch), -- RK3308_ADC_CH1_CH2_MIC_ALL_MSK, -- RK3308_ADC_CH1_MIC_UNMUTE | -- RK3308_ADC_CH2_MIC_UNMUTE); -+ rk3308->which_i2s = which_i2s; - -- /* -- * 4. Set ACODEC_ADC_ANA_CON6[0] to 0x0, to disable the current -- * source of audio -- */ -- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(ch), -- RK3308_ADC_CURRENT_MSK, -- RK3308_ADC_CURRENT_DIS); -+ switch (rk3308->which_i2s) { -+ case ACODEC_TO_I2S1_2CH: -+ rk3308->to_i2s_grps = 1; -+ break; -+ case ACODEC_TO_I2S3_4CH: -+ rk3308->to_i2s_grps = 2; -+ break; -+ default: -+ rk3308->to_i2s_grps = 4; -+ break; -+ } - -- return 0; -+ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) -+ rk3308->i2s_sdis[idx] = i2s_sdis[idx]; -+ -+ rk3308_codec_adc_grps_route_config(rk3308); -+ -+err: -+ return count; - } - --static int rk3308_codec_open_capture(struct snd_soc_codec *codec) -+static ssize_t adc_grp0_in_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- -- rk3308_codec_alc_enable(rk3308); -- rk3308_codec_adc_ana_enable(rk3308); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); - -- return 0; -+ return sprintf(buf, "adc ch0 using: %s\n", -+ rk3308->adc_grp0_using_linein ? "line in" : "mic in"); - } - --static int rk3308_codec_close_capture(struct snd_soc_codec *codec) -+static ssize_t adc_grp0_in_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long using_linein; -+ int ret = kstrtoul(buf, 10, &using_linein); -+ -+ if (ret < 0 || using_linein > 1) { -+ dev_err(dev, "Invalid input status: %ld, ret: %d\n", -+ using_linein, ret); -+ return -EINVAL; -+ } - -- rk3308_codec_alc_disable(rk3308); -- rk3308_codec_adc_ana_disable(rk3308); -+ rk3308->adc_grp0_using_linein = using_linein; - -- return 0; -+ dev_info(dev, "store using_linein: %d\n", -+ rk3308->adc_grp0_using_linein); -+ -+ return count; - } - --static int rk3308_codec_open_playback(struct snd_soc_codec *codec) -+static ssize_t adc_zerocross_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -- -- rk3308_codec_dac_enable(rk3308); -- rk3308_speaker_ctl(rk3308, 1); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); - -- return 0; -+ return sprintf(buf, "adc zerocross: %s\n", -+ rk3308->adc_zerocross ? "enabled" : "disabled"); - } - --static int rk3308_codec_close_playback(struct snd_soc_codec *codec) -+static ssize_t adc_zerocross_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long zerocross; -+ int ret = kstrtoul(buf, 10, &zerocross); - -- rk3308_speaker_ctl(rk3308, 0); -- rk3308_codec_dac_disable(rk3308); -+ if (ret < 0 || zerocross > 1) { -+ dev_err(dev, "Invalid zerocross: %ld, ret: %d\n", -+ zerocross, ret); -+ return -EINVAL; -+ } - -- return 0; -+ rk3308->adc_zerocross = zerocross; -+ -+ dev_info(dev, "store adc zerocross: %d\n", rk3308->adc_zerocross); -+ -+ return count; - } - --static int rk3308_pcm_startup(struct snd_pcm_substream *substream, -- struct snd_soc_dai *dai) -+static ssize_t adc_grps_endisable_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct snd_soc_codec *codec = dai->codec; -- int ret = 0; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ int count = 0, i; - -- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- ret = rk3308_codec_open_playback(codec); -- else -- ret = rk3308_codec_open_capture(codec); -+ count += sprintf(buf + count, "enabled adc grps:"); -+ for (i = 0; i < ADC_LR_GROUP_MAX; i++) -+ count += sprintf(buf + count, "%d ", -+ rk3308->adc_grps_endisable[i]); - -- return ret; -+ count += sprintf(buf + count, "\n"); -+ return count; - } - --static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, -- struct snd_soc_dai *dai) -+static ssize_t adc_grps_endisable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct snd_soc_codec *codec = dai->codec; -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ int grp, endisable, ret; - -- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- rk3308_codec_close_playback(codec); -- else -- rk3308_codec_close_capture(codec); --} -+ ret = sscanf(buf, "%d,%d", &grp, &endisable); -+ if (ret != 2) { -+ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", -+ __func__, ret); -+ return -EFAULT; -+ } - --static struct snd_soc_dai_ops rk3308_dai_ops = { -- .hw_params = rk3308_hw_params, -- .set_fmt = rk3308_set_dai_fmt, -- .digital_mute = rk3308_digital_mute, -- .startup = rk3308_pcm_startup, -- .shutdown = rk3308_pcm_shutdown, --}; -+ rk3308->cur_dbg_grp = grp; - --static struct snd_soc_dai_driver rk3308_dai[] = { -- { -- .name = "rk3308-hifi", -- .id = RK3308_HIFI, -- .playback = { -- .stream_name = "HiFi Playback", -- .channels_min = 2, -- .channels_max = 2, -- .rates = SNDRV_PCM_RATE_8000_96000, -- .formats = (SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S20_3LE | -- SNDRV_PCM_FMTBIT_S24_LE | -- SNDRV_PCM_FMTBIT_S32_LE), -- }, -- .capture = { -- .stream_name = "HiFi Capture", -- .channels_min = 1, -- .channels_max = 8, -- .rates = SNDRV_PCM_RATE_8000_96000, -- .formats = (SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S20_3LE | -- SNDRV_PCM_FMTBIT_S24_LE | -- SNDRV_PCM_FMTBIT_S32_LE), -- }, -- .ops = &rk3308_dai_ops, -- }, --}; -+ if (endisable) -+ rk3308_codec_open_dbg_capture(rk3308); -+ else -+ rk3308_codec_close_dbg_capture(rk3308); - --static int rk3308_suspend(struct snd_soc_codec *codec) --{ -- rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ dev_info(dev, "ADC grp %d endisable: %d\n", grp, endisable); - -- return 0; -+ return count; - } - --static int rk3308_resume(struct snd_soc_codec *codec) -+static ssize_t dac_endisable_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); - -- return 0; -+ return sprintf(buf, "%d\n", rk3308->dac_endisable); - } - --static int rk3308_probe(struct snd_soc_codec *codec) -+static ssize_t dac_endisable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long endisable; -+ int ret = kstrtoul(buf, 10, &endisable); - -- rk3308_codec_reset(codec); -- rk3308_codec_power_on(codec); -+ if (ret < 0) { -+ dev_err(dev, "Invalid endisable: %ld, ret: %d\n", -+ endisable, ret); -+ return -EINVAL; -+ } -+ -+ if (endisable) -+ rk3308_codec_open_playback(rk3308); -+ else -+ rk3308_codec_close_playback(rk3308); - -- rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_7); -+ dev_info(dev, "DAC endisable: %ld\n", endisable); - -- return 0; -+ return count; - } - --static int rk3308_remove(struct snd_soc_codec *codec) -+static ssize_t dac_output_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ ssize_t ret = 0; - -- rk3308_speaker_ctl(rk3308, 0); -- rk3308_codec_micbias_disable(rk3308); -- rk3308_codec_power_off(codec); -+ switch (rk3308->dac_output) { -+ case DAC_LINEOUT: -+ ret = sprintf(buf, "dac path: %s\n", "line out"); -+ break; -+ case DAC_HPOUT: -+ ret = sprintf(buf, "dac path: %s\n", "hp out"); -+ break; -+ case DAC_LINEOUT_HPOUT: -+ ret = sprintf(buf, "dac path: %s\n", -+ "both line out and hp out"); -+ break; -+ default: -+ pr_err("Invalid dac path: %d ?\n", rk3308->dac_output); -+ break; -+ } - -- return 0; -+ return ret; - } - --static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -- .probe = rk3308_probe, -- .remove = rk3308_remove, -- .suspend = rk3308_suspend, -- .resume = rk3308_resume, -- .set_bias_level = rk3308_set_bias_level, -- .controls = rk3308_codec_dapm_controls, -- .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), --}; -- --static const struct reg_default rk3308_codec_reg_defaults[] = { -- { RK3308_GLB_CON, 0x07 }, --}; -- --static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) -+static ssize_t dac_output_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { -- /* All registers can be read / write */ -- return true; --} -+ struct rk3308_codec_priv *rk3308 = -+ container_of(dev, struct rk3308_codec_priv, dev); -+ unsigned long dac_output; -+ int ret = kstrtoul(buf, 10, &dac_output); - --static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) --{ -- switch (reg) { -- case RK3308_GLB_CON: -- return true; -- default: -- return false; -+ if (ret < 0) { -+ dev_err(dev, "Invalid input status: %ld, ret: %d\n", -+ dac_output, ret); -+ return -EINVAL; - } --} - --static const struct regmap_config rk3308_codec_regmap_config = { -- .reg_bits = 32, -- .reg_stride = 4, -- .val_bits = 32, -- .max_register = RK3308_DAC_ANA_CON13, -- .writeable_reg = rk3308_codec_write_read_reg, -- .readable_reg = rk3308_codec_write_read_reg, -- .volatile_reg = rk3308_codec_volatile_reg, -- .reg_defaults = rk3308_codec_reg_defaults, -- .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), -- .cache_type = REGCACHE_FLAT, --}; -+ rk3308_codec_dac_switch(rk3308, dac_output); - --static ssize_t adc_ch_show(struct device *dev, -- struct device_attribute *attr, -- char *buf) -+ dev_info(dev, "Store dac_output: %d\n", rk3308->dac_output); -+ -+ return count; -+} -+ -+static ssize_t enable_all_adcs_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) - { - struct rk3308_codec_priv *rk3308 = - container_of(dev, struct rk3308_codec_priv, dev); - -- return sprintf(buf, "adc_ch: %d\n", rk3308->adc_ch); -+ return sprintf(buf, "%d\n", rk3308->enable_all_adcs); - } - --static ssize_t adc_ch_store(struct device *dev, -- struct device_attribute *attr, -- const char *buf, size_t count) -+static ssize_t enable_all_adcs_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) - { - struct rk3308_codec_priv *rk3308 = - container_of(dev, struct rk3308_codec_priv, dev); -- unsigned long ch; -- int ret = kstrtoul(buf, 10, &ch); -+ unsigned long enable; -+ int ret = kstrtoul(buf, 10, &enable); - -- if (ret < 0 || ch > 4) { -- dev_err(dev, "Invalid ch: %ld, ret: %d\n", ch, ret); -+ if (ret < 0) { -+ dev_err(dev, "Invalid enable value: %ld, ret: %d\n", -+ enable, ret); - return -EINVAL; - } - -- rk3308->adc_ch = ch; -- -- dev_info(dev, "Store ch: %d\n", rk3308->adc_ch); -+ rk3308->enable_all_adcs = enable; - - return count; - } - --static const struct device_attribute adc_ch_attrs[] = { -- __ATTR(adc_ch, 0644, adc_ch_show, adc_ch_store), -+static const struct device_attribute acodec_attrs[] = { -+ __ATTR_RW(adc_grps), -+ __ATTR_RW(adc_grps_endisable), -+ __ATTR_RW(adc_grps_route), -+ __ATTR_RW(adc_grp0_in), -+ __ATTR_RW(adc_zerocross), -+ __ATTR_RW(dac_endisable), -+ __ATTR_RW(dac_output), -+ __ATTR_RW(enable_all_adcs), -+ __ATTR_RW(pm_state), - }; - - static void rk3308_codec_device_release(struct device *dev) -@@ -1468,8 +4747,8 @@ static int rk3308_codec_sysfs_init(struct platform_device *pdev, - return -ENOMEM; - } - -- for (i = 0; i < ARRAY_SIZE(adc_ch_attrs); i++) { -- if (device_create_file(dev, &adc_ch_attrs[i])) { -+ for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++) { -+ if (device_create_file(dev, &acodec_attrs[i])) { - dev_err(&pdev->dev, - "Create 'rk3308-acodec-dev' attr failed\n"); - device_unregister(dev); -@@ -1480,32 +4759,136 @@ static int rk3308_codec_sysfs_init(struct platform_device *pdev, - return 0; - } - -+#if defined(CONFIG_DEBUG_FS) -+static int rk3308_codec_debugfs_reg_show(struct seq_file *s, void *v) -+{ -+ struct rk3308_codec_priv *rk3308 = s->private; -+ unsigned int i; -+ unsigned int val; -+ -+ for (i = RK3308_GLB_CON; i <= RK3308_DAC_ANA_CON13; i += 4) { -+ regmap_read(rk3308->regmap, i, &val); -+ if (!(i % 16)) -+ seq_printf(s, "\nR:%04x: ", i); -+ seq_printf(s, "%08x ", val); -+ } -+ -+ seq_puts(s, "\n"); -+ -+ return 0; -+} -+ -+static ssize_t rk3308_codec_debugfs_reg_operate(struct file *file, -+ const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct rk3308_codec_priv *rk3308 = -+ ((struct seq_file *)file->private_data)->private; -+ unsigned int reg, val; -+ char op; -+ char kbuf[32]; -+ int ret; -+ -+ if (count >= sizeof(kbuf)) -+ return -EINVAL; -+ -+ if (copy_from_user(kbuf, buf, count)) -+ return -EFAULT; -+ kbuf[count] = '\0'; -+ -+ ret = sscanf(kbuf, "%c,%x,%x", &op, ®, &val); -+ if (ret != 3) { -+ pr_err("sscanf failed: %d\n", ret); -+ return -EFAULT; -+ } -+ -+ if (op == 'w') { -+ pr_info("Write reg: 0x%04x with val: 0x%08x\n", reg, val); -+ regmap_write(rk3308->regmap, reg, val); -+ regcache_cache_only(rk3308->regmap, false); -+ regcache_sync(rk3308->regmap); -+ pr_info("Read back reg: 0x%04x with val: 0x%08x\n", reg, val); -+ } else if (op == 'r') { -+ regmap_read(rk3308->regmap, reg, &val); -+ pr_info("Read reg: 0x%04x with val: 0x%08x\n", reg, val); -+ } else { -+ pr_err("This is an invalid operation: %c\n", op); -+ } -+ -+ return count; -+} -+ -+static int rk3308_codec_debugfs_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, -+ rk3308_codec_debugfs_reg_show, inode->i_private); -+} -+ -+static const struct file_operations rk3308_codec_reg_debugfs_fops = { -+ .owner = THIS_MODULE, -+ .open = rk3308_codec_debugfs_open, -+ .read = seq_read, -+ .write = rk3308_codec_debugfs_reg_operate, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+#endif /* CONFIG_DEBUG_FS */ -+ -+static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) -+{ -+ unsigned int chip_id; -+ -+ regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id); -+ switch (chip_id) { -+ case 3306: -+ rk3308->codec_ver = ACODEC_VERSION_A; -+ break; -+ case 0x3308: -+ rk3308->codec_ver = ACODEC_VERSION_B; -+ break; -+ default: -+ pr_err("Unknown chip_id: %d / 0x%x\n", chip_id, chip_id); -+ return -EFAULT; -+ } -+ -+ pr_info("The acodec version is: %x\n", rk3308->codec_ver); -+ return 0; -+} -+ - static int rk3308_platform_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; - struct rk3308_codec_priv *rk3308; - struct resource *res; - void __iomem *base; -- int ret = 0; -- struct regmap *grf; -- -- grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); -- if (IS_ERR(grf)) { -- dev_err(&pdev->dev, -- "Missing 'rockchip,grf' property\n"); -- return PTR_ERR(grf); -- } -+ int ret; - - rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); - if (!rk3308) - return -ENOMEM; - -+ rk3308->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); -+ if (IS_ERR(rk3308->grf)) { -+ dev_err(&pdev->dev, -+ "Missing 'rockchip,grf' property\n"); -+ return PTR_ERR(rk3308->grf); -+ } -+ - ret = rk3308_codec_sysfs_init(pdev, rk3308); - if (ret < 0) { - dev_err(&pdev->dev, "Sysfs init failed\n"); - return ret; - } - -+#if defined(CONFIG_DEBUG_FS) -+ rk3308->dbg_codec = debugfs_create_dir(CODEC_DRV_NAME, NULL); -+ if (IS_ERR(rk3308->dbg_codec)) -+ dev_err(&pdev->dev, -+ "Failed to create debugfs dir for rk3308!\n"); -+ else -+ debugfs_create_file("reg", 0644, rk3308->dbg_codec, -+ rk3308, &rk3308_codec_reg_debugfs_fops); -+#endif - rk3308->plat_dev = &pdev->dev; - - rk3308->reset = devm_reset_control_get(&pdev->dev, "acodec-reset"); -@@ -1518,27 +4901,146 @@ static int rk3308_platform_probe(struct platform_device *pdev) - rk3308->reset = NULL; - } - -- /* GPIO0_A5 control speaker on RK3308 EVB */ -- rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk_ctl", -- GPIOD_OUT_HIGH); -- if (IS_ERR(rk3308->spk_ctl_gpio)) { -+ rk3308->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-ctl", -+ GPIOD_OUT_LOW); -+ if (!rk3308->hp_ctl_gpio) { -+ dev_info(&pdev->dev, "Don't need hp-ctl gpio\n"); -+ } else if (IS_ERR(rk3308->hp_ctl_gpio)) { -+ ret = PTR_ERR(rk3308->hp_ctl_gpio); -+ dev_err(&pdev->dev, "Unable to claim gpio hp-ctl\n"); -+ return ret; -+ } -+ -+ rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-ctl", -+ GPIOD_OUT_LOW); -+ -+ if (!rk3308->spk_ctl_gpio) { -+ dev_info(&pdev->dev, "Don't need spk-ctl gpio\n"); -+ } else if (IS_ERR(rk3308->spk_ctl_gpio)) { - ret = PTR_ERR(rk3308->spk_ctl_gpio); -- dev_err(&pdev->dev, "Unable to claim gpio spk_ctl\n"); -+ dev_err(&pdev->dev, "Unable to claim gpio spk-ctl\n"); -+ return ret; -+ } -+ -+ rk3308->pa_drv_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-drv", -+ GPIOD_OUT_LOW); -+ -+ if (!rk3308->pa_drv_gpio) { -+ dev_info(&pdev->dev, "Don't need pa-drv gpio\n"); -+ } else if (IS_ERR(rk3308->pa_drv_gpio)) { -+ ret = PTR_ERR(rk3308->pa_drv_gpio); -+ dev_err(&pdev->dev, "Unable to claim gpio pa-drv\n"); - return ret; - } - -+ if (rk3308->pa_drv_gpio) { -+ rk3308->delay_pa_drv_ms = PA_DRV_MS; -+ ret = of_property_read_u32(np, "rockchip,delay-pa-drv-ms", -+ &rk3308->delay_pa_drv_ms); -+ } -+ -+#if DEBUG_POP_ALWAYS -+ dev_info(&pdev->dev, "Enable all ctl gpios always for debugging pop\n"); -+ rk3308_headphone_ctl(rk3308, 1); -+ rk3308_speaker_ctl(rk3308, 1); -+#else -+ dev_info(&pdev->dev, "De-pop as much as possible\n"); -+ rk3308_headphone_ctl(rk3308, 0); -+ rk3308_speaker_ctl(rk3308, 0); -+#endif -+ - rk3308->pclk = devm_clk_get(&pdev->dev, "acodec"); - if (IS_ERR(rk3308->pclk)) { - dev_err(&pdev->dev, "Can't get acodec pclk\n"); - return PTR_ERR(rk3308->pclk); - } - -+ rk3308->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx"); -+ if (IS_ERR(rk3308->mclk_rx)) { -+ dev_err(&pdev->dev, "Can't get acodec mclk_rx\n"); -+ return PTR_ERR(rk3308->mclk_rx); -+ } -+ -+ rk3308->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx"); -+ if (IS_ERR(rk3308->mclk_tx)) { -+ dev_err(&pdev->dev, "Can't get acodec mclk_tx\n"); -+ return PTR_ERR(rk3308->mclk_tx); -+ } -+ - ret = clk_prepare_enable(rk3308->pclk); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret); - return ret; - } - -+ ret = clk_prepare_enable(rk3308->mclk_rx); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to enable i2s mclk_rx: %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(rk3308->mclk_tx); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to enable i2s mclk_tx: %d\n", ret); -+ return ret; -+ } -+ -+ rk3308_codec_check_micbias(rk3308, np); -+ -+ rk3308->enable_all_adcs = -+ of_property_read_bool(np, "rockchip,enable-all-adcs"); -+ -+ rk3308->hp_jack_reversed = -+ of_property_read_bool(np, "rockchip,hp-jack-reversed"); -+ -+ rk3308->no_deep_low_power = -+ of_property_read_bool(np, "rockchip,no-deep-low-power"); -+ -+ rk3308->no_hp_det = -+ of_property_read_bool(np, "rockchip,no-hp-det"); -+ -+ rk3308->delay_loopback_handle_ms = LOOPBACK_HANDLE_MS; -+ ret = of_property_read_u32(np, "rockchip,delay-loopback-handle-ms", -+ &rk3308->delay_loopback_handle_ms); -+ -+ rk3308->delay_start_play_ms = 0; -+ ret = of_property_read_u32(np, "rockchip,delay-start-play-ms", -+ &rk3308->delay_start_play_ms); -+ -+ rk3308->loopback_grp = NOT_USED; -+ ret = of_property_read_u32(np, "rockchip,loopback-grp", -+ &rk3308->loopback_grp); -+ /* -+ * If there is no loopback on some board, the -EINVAL indicates that -+ * we don't need add the node, and it is not an error. -+ */ -+ if (ret < 0 && ret != -EINVAL) { -+ dev_err(&pdev->dev, "Failed to read loopback property: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_adc_grps_route(rk3308, np); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to route ADC groups: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_setup_en_always_adcs(rk3308, np); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to setup enabled always ADCs: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = rk3308_codec_get_version(rk3308); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to get acodec version: %d\n", -+ ret); -+ return ret; -+ } -+ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) { -@@ -1555,10 +5057,65 @@ static int rk3308_platform_probe(struct platform_device *pdev) - goto failed; - } - -+ if (!rk3308->no_hp_det) { -+ int index = 0; -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) -+ index = 1; -+ -+ rk3308->irq = platform_get_irq(pdev, index); -+ if (rk3308->irq < 0) { -+ dev_err(&pdev->dev, "Can not get codec irq\n"); -+ goto failed; -+ } -+ -+ INIT_DELAYED_WORK(&rk3308->hpdet_work, rk3308_codec_hpdetect_work); -+ -+ ret = devm_request_irq(&pdev->dev, rk3308->irq, -+ rk3308_codec_hpdet_isr, -+ 0, -+ "acodec-hpdet", -+ rk3308); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret); -+ goto failed; -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_B) { -+ rk3308->detect_grf = -+ syscon_regmap_lookup_by_phandle(np, "rockchip,detect-grf"); -+ if (IS_ERR(rk3308->detect_grf)) { -+ dev_err(&pdev->dev, -+ "Missing 'rockchip,detect-grf' property\n"); -+ return PTR_ERR(rk3308->detect_grf); -+ } -+ -+ /* Configure filter count and enable hpdet irq. */ -+ regmap_write(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_COUNTER, -+ DEFAULT_HPDET_COUNT); -+ regmap_write(rk3308->detect_grf, -+ DETECT_GRF_ACODEC_HPDET_CON, -+ (HPDET_BOTH_NEG_POS << 16) | -+ HPDET_BOTH_NEG_POS); -+ } -+ -+ rk3308_codec_set_jack_detect_cb = rk3308_codec_set_jack_detect; -+ } -+ -+ if (rk3308->codec_ver == ACODEC_VERSION_A) -+ INIT_DELAYED_WORK(&rk3308->loopback_work, -+ rk3308_codec_loopback_work); -+ -+ rk3308->adc_grp0_using_linein = ADC_GRP0_MICIN; -+ rk3308->dac_output = DAC_LINEOUT; -+ rk3308->adc_zerocross = 1; -+ rk3308->pm_state = PM_NORMAL; -+ - platform_set_drvdata(pdev, rk3308); - - ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3308, -- rk3308_dai, ARRAY_SIZE(rk3308_dai)); -+ rk3308_dai, ARRAY_SIZE(rk3308_dai)); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); - goto failed; -@@ -1567,7 +5124,10 @@ static int rk3308_platform_probe(struct platform_device *pdev) - return ret; - - failed: -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); - clk_disable_unprepare(rk3308->pclk); -+ device_unregister(&rk3308->dev); - - return ret; - } -@@ -1577,8 +5137,11 @@ static int rk3308_platform_remove(struct platform_device *pdev) - struct rk3308_codec_priv *rk3308 = - (struct rk3308_codec_priv *)platform_get_drvdata(pdev); - -+ clk_disable_unprepare(rk3308->mclk_rx); -+ clk_disable_unprepare(rk3308->mclk_tx); - clk_disable_unprepare(rk3308->pclk); - snd_soc_unregister_codec(&pdev->dev); -+ device_unregister(&rk3308->dev); - - return 0; - } -@@ -1591,7 +5154,7 @@ MODULE_DEVICE_TABLE(of, rk3308codec_of_match); - - static struct platform_driver rk3308_codec_driver = { - .driver = { -- .name = "rk3308-acodec", -+ .name = CODEC_DRV_NAME, - .of_match_table = of_match_ptr(rk3308codec_of_match), - }, - .probe = rk3308_platform_probe, -diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h -index 6cfa69157785..93e089dae081 100644 ---- a/sound/soc/codecs/rk3308_codec.h -+++ b/sound/soc/codecs/rk3308_codec.h -@@ -26,7 +26,8 @@ - #define ACODEC_ADC_I2S_CTL0 0x04 /* REG 0x01 */ - #define ACODEC_ADC_I2S_CTL1 0x08 /* REG 0x02 */ - #define ACODEC_ADC_BIST_MODE_SEL 0x0c /* REG 0x03 */ --/* Resevred REG 0x04 ~ 0x06 */ -+#define ACODEC_ADC_HPF_PATH 0x10 /* REG 0x04 */ -+/* Resevred REG 0x05 ~ 0x06 */ - #define ACODEC_ADC_DATA_PATH 0x1c /* REG 0x07 */ - /* Resevred REG 0x08 ~ 0x0f */ - -@@ -62,12 +63,15 @@ - #define ACODEC_DAC_I2S_CTL0 0x04 /* REG 0x01 */ - #define ACODEC_DAC_I2S_CTL1 0x08 /* REG 0x02 */ - #define ACODEC_DAC_BIST_MODE_SEL 0x0c /* REG 0x03 */ --/* Resevred REG 0x04 */ -+#define ACODEC_DAC_DIGITAL_GAIN 0x10 /* REG 0x04 */ - #define ACODEC_DAC_DATA_SEL 0x14 /* REG 0x05 */ - /* Resevred REG 0x06 ~ 0x09 */ - #define ACODEC_DAC_DATA_HI 0x28 /* REG 0x0a */ - #define ACODEC_DAC_DATA_LO 0x2c /* REG 0x0b */ --/* Resevred REG 0x0c ~ 0x0f */ -+/* Resevred REG 0x0c */ -+#define ACODEC_DAC_HPDET_DELAYTIME 0x34 /* REG 0x0d */ -+#define ACODEC_DAC_HPDET_STATUS 0x38 /* REG 0x0e, Read-only */ -+/* Resevred REG 0x0f */ - - /* ADC ANALOG REGISTERS */ - #define ACODEC_ADC_ANA_MIC_CTL 0x00 /* REG 0x00 */ -@@ -92,10 +96,13 @@ - #define ACODEC_DAC_ANA_LINEOUT 0x10 /* REG 0x04 */ - #define ACODEC_DAC_ANA_L_HPOUT_GAIN 0x14 /* REG 0x05 */ - #define ACODEC_DAC_ANA_R_HPOUT_GAIN 0x18 /* REG 0x06 */ -+#define ACODEC_DAC_ANA_DRV_HPOUT 0x1c /* REG 0x07 */ -+#define ACODEC_DAC_ANA_DRV_LINEOUT 0x20 /* REG 0x08 */ - /* Resevred REG 0x07 ~ 0x0b */ - #define ACODEC_DAC_ANA_HPMIX_CTL0 0x30 /* REG 0x0c */ - #define ACODEC_DAC_ANA_HPMIX_CTL1 0x34 /* REG 0x0d */ --/* Resevred REG 0x0e ~ 0x0f */ -+#define ACODEC_DAC_ANA_LINEOUT_CTL0 0x38 /* REG 0x0e */ -+#define ACODEC_DAC_ANA_LINEOUT_CTL1 0x3c /* REG 0x0f */ - - /* - * These registers are referenced by codec driver -@@ -106,7 +113,7 @@ - /* ADC DIGITAL REGISTERS */ - - /* -- * The ADC chanel are 0 ~ 3, that control: -+ * The ADC group are 0 ~ 3, that control: - * - * CH0: left_0(ADC1) and right_0(ADC2) - * CH1: left_1(ADC3) and right_1(ADC4) -@@ -118,6 +125,7 @@ - #define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL0) - #define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL1) - #define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_BIST_MODE_SEL) -+#define RK3308_ADC_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_HPF_PATH) - #define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_DATA_PATH) - - #define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL0) -@@ -150,13 +158,16 @@ - #define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL0) - #define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL1) - #define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_BIST_MODE_SEL) -+#define RK3308_DAC_DIG_CON04 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DIGITAL_GAIN) - #define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_SEL) - #define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_HI) - #define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_LO) -+#define RK3308_DAC_DIG_CON13 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_DELAYTIME) -+#define RK3308_DAC_DIG_CON14 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_STATUS) - - /* ADC ANALOG REGISTERS */ - /* -- * The ADC chanel are 0 ~ 3, that control: -+ * The ADC group are 0 ~ 3, that control: - * - * CH0: left_0(ADC1) and right_0(ADC2) - * CH1: left_1(ADC3) and right_1(ADC4) -@@ -179,7 +190,6 @@ - - /* DAC ANALOG REGISTERS */ - #define RK3308_DAC_ANA_OFFSET 0x440 -- - #define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL0) - #define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_POP_VOLT) - #define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL1) -@@ -187,8 +197,12 @@ - #define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT) - #define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_L_HPOUT_GAIN) - #define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_R_HPOUT_GAIN) -+#define RK3308_DAC_ANA_CON07 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_DRV_HPOUT) -+#define RK3308_DAC_ANA_CON08 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_DRV_LINEOUT) - #define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL0) - #define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL1) -+#define RK3308_DAC_ANA_CON14 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT_CTL0) -+#define RK3308_DAC_ANA_CON15 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT_CTL1) - - /* - * These are the bits for registers -@@ -199,6 +213,12 @@ - #define RK3308_ADC_BIST_RESET (0 << 7) - #define RK3308_DAC_BIST_WORK (1 << 6) - #define RK3308_DAC_BIST_RESET (0 << 6) -+#define RK3308_ADC_MCLK_MSK (1 << 5) -+#define RK3308_ADC_MCLK_DIS (1 << 5) -+#define RK3308_ADC_MCLK_EN (0 << 5) -+#define RK3308_DAC_MCLK_MSK (1 << 4) -+#define RK3308_DAC_MCLK_DIS (1 << 4) -+#define RK3308_DAC_MCLK_EN (0 << 4) - #define RK3308_CODEC_RST_MSK (0x7 << 0) - #define RK3308_ADC_DIG_WORK (1 << 2) - #define RK3308_ADC_DIG_RESET (0 << 2) -@@ -253,16 +273,27 @@ - /* RK3308_ADC_DIG_CON03 - REG: 0x000c */ - #define RK3308_ADC_L_CH_BIST_SFT 2 - #define RK3308_ADC_L_CH_BIST_MSK (0x3 << RK3308_ADC_L_CH_BIST_SFT) --#define RK3308_ADC_L_CH_BIST_LEFT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ --#define RK3308_ADC_L_CH_BIST_SINE (0x2 << RK3308_ADC_L_CH_BIST_SFT) --#define RK3308_ADC_L_CH_BIST_CUBE (0x1 << RK3308_ADC_L_CH_BIST_SFT) --#define RK3308_ADC_L_CH_BIST_RIGHT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_L_CH_NORMAL_RIGHT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_L_CH_BIST_CUBE (0x2 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_BIST_SINE (0x1 << RK3308_ADC_L_CH_BIST_SFT) -+#define RK3308_ADC_L_CH_NORMAL_LEFT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ - #define RK3308_ADC_R_CH_BIST_SFT 0 - #define RK3308_ADC_R_CH_BIST_MSK (0x3 << RK3308_ADC_R_CH_BIST_SFT) --#define RK3308_ADC_R_CH_BIST_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ --#define RK3308_ADC_R_CH_BIST_SINE (0x2 << RK3308_ADC_R_CH_BIST_SFT) --#define RK3308_ADC_R_CH_BIST_CUBE (0x1 << RK3308_ADC_R_CH_BIST_SFT) --#define RK3308_ADC_R_CH_BIST_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_NORMAL_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+#define RK3308_ADC_R_CH_BIST_CUBE (0x2 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_BIST_SINE (0x1 << RK3308_ADC_R_CH_BIST_SFT) -+#define RK3308_ADC_R_CH_NORMAL_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ -+ -+/* RK3308_ADC_DIG_CON04 - REG: 0x0010 */ -+#define RK3308_ADC_HPF_PATH_SFT 2 -+#define RK3308_ADC_HPF_PATH_MSK (1 << RK3308_ADC_HPF_PATH_SFT) -+#define RK3308_ADC_HPF_PATH_DIS (1 << RK3308_ADC_HPF_PATH_SFT) -+#define RK3308_ADC_HPF_PATH_EN (0 << RK3308_ADC_HPF_PATH_SFT) -+#define RK3308_ADC_HPF_CUTOFF_SFT 0 -+#define RK3308_ADC_HPF_CUTOFF_MSK (0x3 << RK3308_ADC_HPF_CUTOFF_SFT) -+#define RK3308_ADC_HPF_CUTOFF_612HZ (0x2 << RK3308_ADC_HPF_CUTOFF_SFT) -+#define RK3308_ADC_HPF_CUTOFF_245HZ (0x1 << RK3308_ADC_HPF_CUTOFF_SFT) -+#define RK3308_ADC_HPF_CUTOFF_20HZ (0x0 << RK3308_ADC_HPF_CUTOFF_SFT) - - /* RK3308_ADC_DIG_CON07 - REG: 0x001c */ - #define RK3308_ADCL_DATA_SFT 4 -@@ -391,6 +422,8 @@ - */ - #define RK3308_AGC_PGA_ZERO_CRO_EN (0x1 << 5) - #define RK3308_AGC_PGA_ZERO_CRO_DIS (0x0 << 5) -+#define RK3308_AGC_PGA_GAIN_MAX 0x1f -+#define RK3308_AGC_PGA_GAIN_MIN 0 - #define RK3308_AGC_PGA_GAIN_SFT 0 - #define RK3308_AGC_PGA_GAIN_MSK (0x1f << RK3308_AGC_PGA_GAIN_SFT) - #define RK3308_AGC_PGA_GAIN_PDB_28_5 (0x1f << RK3308_AGC_PGA_GAIN_SFT) -@@ -474,6 +507,8 @@ - #define RK3308_AGC_FUNC_SEL_MSK (0x1 << 6) - #define RK3308_AGC_FUNC_SEL_EN (0x1 << 6) - #define RK3308_AGC_FUNC_SEL_DIS (0x0 << 6) -+#define RK3308_AGC_MAX_GAIN_PGA_MAX 0x7 -+#define RK3308_AGC_MAX_GAIN_PGA_MIN 0 - #define RK3308_AGC_MAX_GAIN_PGA_SFT 3 - #define RK3308_AGC_MAX_GAIN_PGA_MSK (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) - #define RK3308_AGC_MAX_GAIN_PGA_PDB_28_5 (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) -@@ -484,6 +519,8 @@ - #define RK3308_AGC_MAX_GAIN_PGA_NDB_1_5 (0x2 << RK3308_AGC_MAX_GAIN_PGA_SFT) - #define RK3308_AGC_MAX_GAIN_PGA_NDB_7_5 (0x1 << RK3308_AGC_MAX_GAIN_PGA_SFT) - #define RK3308_AGC_MAX_GAIN_PGA_NDB_13_5 (0x0 << RK3308_AGC_MAX_GAIN_PGA_SFT) -+#define RK3308_AGC_MIN_GAIN_PGA_MAX 0x7 -+#define RK3308_AGC_MIN_GAIN_PGA_MIN 0 - #define RK3308_AGC_MIN_GAIN_PGA_SFT 0 - #define RK3308_AGC_MIN_GAIN_PGA_MSK (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) - #define RK3308_AGC_MIN_GAIN_PGA_PDB_24 (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) -@@ -555,6 +592,18 @@ - #define RK3308_DAC_R_CH_BIST_SINE (0x1 << RK3308_DAC_R_CH_BIST_SFT) - #define RK3308_DAC_R_CH_BIST_RIGHT (0x0 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ - -+/* RK3308_DAC_DIG_CON04 - REG: 0x0310 */ -+#define RK3308_DAC_MODULATOR_GAIN_SFT 4 -+#define RK3308_DAC_MODULATOR_GAIN_MSK (0x7 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_4_8DB (0x5 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_4_2DB (0x4 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_3_5DB (0x3 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_2_8DB (0x2 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_2DB (0x1 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_MODULATOR_GAIN_0DB (0x0 << RK3308_DAC_MODULATOR_GAIN_SFT) -+#define RK3308_DAC_CIC_IF_GAIN_SFT 0 -+#define RK3308_DAC_CIC_IF_GAIN_MSK (0x7 << RK3308_DAC_CIC_IF_GAIN_SFT) -+ - /* RK3308_DAC_DIG_CON05 - REG: 0x0314 */ - #define RK3308_DAC_L_REG_CTL_INDATA (0x1 << 2) - #define RK3308_DAC_L_NORMAL_DATA (0x0 << 2) -@@ -587,18 +636,30 @@ - #define RK3308_ADC_CH1_BUF_REF_EN (0x1 << 0) - #define RK3308_ADC_CH1_BUF_REF_DIS (0x0 << 0) - --/* RK3308_ADC_ANA_CON01 - REG: 0x0344 */ -+/* RK3308_ADC_ANA_CON01 - REG: 0x0344 -+ * -+ * The PGA of MIC-INs: -+ * 0x0 - MIC1~MIC8 0dB -+ * 0x1 - MIC1~MIC8 6.6dB -+ * 0x2 - MIC1~MIC8 13dB -+ * 0x3 - MIC1~MIC8 20dB -+ */ -+#define RK3308_ADC_CH2_MIC_GAIN_MAX 0x3 -+#define RK3308_ADC_CH2_MIC_GAIN_MIN 0 - #define RK3308_ADC_CH2_MIC_GAIN_SFT 4 - #define RK3308_ADC_CH2_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) --#define RK3308_ADC_CH2_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) --#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) --#define RK3308_ADC_CH2_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+#define RK3308_ADC_CH2_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) /* TRM: only used for version B */ -+#define RK3308_ADC_CH2_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) /* TRM: only used for version B */ - #define RK3308_ADC_CH2_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH2_MIC_GAIN_SFT) -+ -+#define RK3308_ADC_CH1_MIC_GAIN_MAX 0x3 -+#define RK3308_ADC_CH1_MIC_GAIN_MIN 0 - #define RK3308_ADC_CH1_MIC_GAIN_SFT 0 - #define RK3308_ADC_CH1_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) --#define RK3308_ADC_CH1_MIC_GAIN_30DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) --#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) --#define RK3308_ADC_CH1_MIC_GAIN_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) -+#define RK3308_ADC_CH1_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) /* TRM: only used for version B */ -+#define RK3308_ADC_CH1_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) /* TRM: only used for version B */ - #define RK3308_ADC_CH1_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH1_MIC_GAIN_SFT) - - /* RK3308_ADC_ANA_CON02 - REG: 0x0348 */ -@@ -619,6 +680,8 @@ - #define RK3308_ADC_CH1_ALC_DIS (0x0 << 0) - - /* RK3308_ADC_ANA_CON03 - REG: 0x034c */ -+#define RK3308_ADC_CH1_ALC_GAIN_MAX 0x1f -+#define RK3308_ADC_CH1_ALC_GAIN_MIN 0 - #define RK3308_ADC_CH1_ALC_GAIN_SFT 0 - #define RK3308_ADC_CH1_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) - #define RK3308_ADC_CH1_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) -@@ -655,6 +718,8 @@ - #define RK3308_ADC_CH1_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH1_ALC_GAIN_SFT) - - /* RK3308_ADC_ANA_CON04 - REG: 0x0350 */ -+#define RK3308_ADC_CH2_ALC_GAIN_MAX 0x1f -+#define RK3308_ADC_CH2_ALC_GAIN_MIN 0 - #define RK3308_ADC_CH2_ALC_GAIN_SFT 0 - #define RK3308_ADC_CH2_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) - #define RK3308_ADC_CH2_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) -@@ -728,10 +793,16 @@ - #define RK3308_ADC_CH1_IN_MIC (0x1 << RK3308_ADC_CH1_IN_SEL_SFT) - #define RK3308_ADC_CH1_IN_NONE (0x0 << RK3308_ADC_CH1_IN_SEL_SFT) - --#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << 3) --#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << 3) -+#define RK3308_ADC_MIC_BIAS_BUF_SFT 3 -+#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << RK3308_ADC_MIC_BIAS_BUF_SFT) -+#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << RK3308_ADC_MIC_BIAS_BUF_SFT) - #define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 - #define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -+/* -+ * The follow MICBIAS_VOLTs are based on the external reference voltage(Vref). -+ * For example, the Vref == 3.3V, the MICBIAS_VOLT_0_85 is equal: -+ * 3.3V * 0.85 = 2.805V. -+ */ - #define RK3308_ADC_MICBIAS_VOLT_0_85 (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) - #define RK3308_ADC_MICBIAS_VOLT_0_8 (0x6 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) - #define RK3308_ADC_MICBIAS_VOLT_0_75 (0x5 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) -@@ -751,18 +822,11 @@ - #define RK3308_ADC_REF_DIS (0x0 << 7) - #define RK3308_ADC_CURRENT_CHARGE_SFT 0 - #define RK3308_ADC_CURRENT_CHARGE_MSK (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) --#define RK3308_ADC_DONT_SEL_ALL (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) - /* -- * 0: Choose the current I -- * 1: Don't choose the current I -+ * 1: Choose the current I -+ * 0: Don't choose the current I - */ --#define RK3308_ADC_SEL_I_1(x) ((x & 0x1) << 6) --#define RK3308_ADC_SEL_I_2(x) ((x & 0x1) << 5) --#define RK3308_ADC_SEL_I_4(x) ((x & 0x1) << 4) --#define RK3308_ADC_SEL_I_8(x) ((x & 0x1) << 3) --#define RK3308_ADC_SEL_I_16(x) ((x & 0x1) << 2) --#define RK3308_ADC_SEL_I_32(x) ((x & 0x1) << 1) --#define RK3308_ADC_SEL_I_64(x) ((x & 0x1) << 0) -+#define RK3308_ADC_SEL_I(x) (x & 0x7f) - - /* RK3308_ADC_ANA_CON11 - REG: 0x036c */ - #define RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK (0x1 << 1) -@@ -773,6 +837,7 @@ - #define RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS (0x0 << 0) - - /* RK3308_DAC_ANA_CON00 - REG: 0x0440 */ -+#define RK3308_DAC_HEADPHONE_DET_MSK (0x1 << 1) - #define RK3308_DAC_HEADPHONE_DET_EN (0x1 << 1) - #define RK3308_DAC_HEADPHONE_DET_DIS (0x0 << 1) - #define RK3308_DAC_CURRENT_MSK (0x1 << 0) -@@ -783,17 +848,17 @@ - #define RK3308_DAC_BUF_REF_R_MSK (0x1 << 6) - #define RK3308_DAC_BUF_REF_R_EN (0x1 << 6) - #define RK3308_DAC_BUF_REF_R_DIS (0x0 << 6) --#define RK3308_DAC_POP_SOUND_R_SFT 4 --#define RK3308_DAC_POP_SOUND_R_MSK (0x3 << RK3308_DAC_POP_SOUND_R_SFT) --#define RK3308_DAC_POP_SOUND_R_WORK (0x2 << RK3308_DAC_POP_SOUND_R_SFT) --#define RK3308_DAC_POP_SOUND_R_INIT (0x1 << RK3308_DAC_POP_SOUND_R_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_R_SFT 4 -+#define RK3308_DAC_HPOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_R_WORK (0x2 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_R_INIT (0x1 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) - #define RK3308_DAC_BUF_REF_L_MSK (0x1 << 2) - #define RK3308_DAC_BUF_REF_L_EN (0x1 << 2) - #define RK3308_DAC_BUF_REF_L_DIS (0x0 << 2) --#define RK3308_DAC_POP_SOUND_L_SFT 0 --#define RK3308_DAC_POP_SOUND_L_MSK (0x3 << RK3308_DAC_POP_SOUND_L_SFT) --#define RK3308_DAC_POP_SOUND_L_WORK (0x2 << RK3308_DAC_POP_SOUND_L_SFT) --#define RK3308_DAC_POP_SOUND_L_INIT (0x1 << RK3308_DAC_POP_SOUND_L_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_L_SFT 0 -+#define RK3308_DAC_HPOUT_POP_SOUND_L_MSK (0x3 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_L_WORK (0x2 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_HPOUT_POP_SOUND_L_INIT (0x1 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) - - /* RK3308_DAC_ANA_CON02 - REG: 0x0448 */ - #define RK3308_DAC_R_DAC_WORK (0x1 << 7) -@@ -828,28 +893,31 @@ - #define RK3308_DAC_L_HPOUT_MUTE (0x0 << 0) - - /* RK3308_DAC_ANA_CON04 - REG: 0x0450 */ --#define RK3308_DAC_R_GAIN_SFT 6 --#define RK3308_DAC_R_GAIN_MSK (0x3 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_0DB (0x3 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_PDB_1_5 (0x2 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_PDB_3 (0x1 << RK3308_DAC_R_GAIN_SFT) --#define RK3308_DAC_R_GAIN_PDB_6 (0x0 << RK3308_DAC_R_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_MAX 0x3 -+#define RK3308_DAC_R_LINEOUT_GAIN_SFT 6 -+#define RK3308_DAC_R_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_R_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_R_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_R_LINEOUT_GAIN_SFT) - #define RK3308_DAC_R_LINEOUT_UNMUTE (0x1 << 5) - #define RK3308_DAC_R_LINEOUT_MUTE (0x0 << 5) - #define RK3308_DAC_R_LINEOUT_EN (0x1 << 4) - #define RK3308_DAC_R_LINEOUT_DIS (0x0 << 4) --#define RK3308_DAC_L_GAIN_SFT 2 --#define RK3308_DAC_L_GAIN_MSK (0x3 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_0DB (0x3 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_PDB_1_5 (0x2 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_PDB_3 (0x1 << RK3308_DAC_L_GAIN_SFT) --#define RK3308_DAC_L_GAIN_PDB_6 (0x0 << RK3308_DAC_L_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_MAX 0x3 -+#define RK3308_DAC_L_LINEOUT_GAIN_SFT 2 -+#define RK3308_DAC_L_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_L_LINEOUT_GAIN_SFT) -+#define RK3308_DAC_L_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_L_LINEOUT_GAIN_SFT) - #define RK3308_DAC_L_LINEOUT_UNMUTE (0x1 << 1) - #define RK3308_DAC_L_LINEOUT_MUTE (0x0 << 1) - #define RK3308_DAC_L_LINEOUT_EN (0x1 << 0) - #define RK3308_DAC_L_LINEOUT_DIS (0x0 << 0) - - /* RK3308_DAC_ANA_CON05 - REG: 0x0454, step is 1.5db */ -+#define RK3308_DAC_L_HPOUT_GAIN_MAX 0x1e - #define RK3308_DAC_L_HPOUT_GAIN_SFT 0 - #define RK3308_DAC_L_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_L_HPOUT_GAIN_SFT) - #define RK3308_DAC_L_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_L_HPOUT_GAIN_SFT) -@@ -885,6 +953,7 @@ - #define RK3308_DAC_L_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_L_HPOUT_GAIN_SFT) - - /* RK3308_DAC_ANA_CON06 - REG: 0x0458, step is 1.5db */ -+#define RK3308_DAC_R_HPOUT_GAIN_MAX 0x1e - #define RK3308_DAC_R_HPOUT_GAIN_SFT 0 - #define RK3308_DAC_R_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_R_HPOUT_GAIN_SFT) - #define RK3308_DAC_R_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_R_HPOUT_GAIN_SFT) -@@ -919,6 +988,18 @@ - #define RK3308_DAC_R_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_R_HPOUT_GAIN_SFT) - #define RK3308_DAC_R_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_R_HPOUT_GAIN_SFT) - -+/* RK3308_DAC_ANA_CON07 - REG: 0x045c */ -+#define RK3308_DAC_R_HPOUT_DRV_SFT 4 -+#define RK3308_DAC_R_HPOUT_DRV_MSK (0xf << RK3308_DAC_R_HPOUT_DRV_SFT) -+#define RK3308_DAC_L_HPOUT_DRV_SFT 0 -+#define RK3308_DAC_L_HPOUT_DRV_MSK (0xf << RK3308_DAC_L_HPOUT_DRV_SFT) -+ -+/* RK3308_DAC_ANA_CON08 - REG: 0x0460 */ -+#define RK3308_DAC_R_LINEOUT_DRV_SFT 4 -+#define RK3308_DAC_R_LINEOUT_DRV_MSK (0xf << RK3308_DAC_R_LINEOUT_DRV_SFT) -+#define RK3308_DAC_L_LINEOUT_DRV_SFT 0 -+#define RK3308_DAC_L_LINEOUT_DRV_MSK (0xf << RK3308_DAC_L_LINEOUT_DRV_SFT) -+ - /* RK3308_DAC_ANA_CON12 - REG: 0x0470 */ - #define RK3308_DAC_R_HPMIX_SEL_SFT 6 - #define RK3308_DAC_R_HPMIX_SEL_MSK (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) -@@ -926,6 +1007,8 @@ - #define RK3308_DAC_R_HPMIX_LINEIN (0x2 << RK3308_DAC_R_HPMIX_SEL_SFT) - #define RK3308_DAC_R_HPMIX_I2S (0x1 << RK3308_DAC_R_HPMIX_SEL_SFT) - #define RK3308_DAC_R_HPMIX_NONE (0x0 << RK3308_DAC_R_HPMIX_SEL_SFT) -+#define RK3308_DAC_R_HPMIX_GAIN_MIN 0x1 -+#define RK3308_DAC_R_HPMIX_GAIN_MAX 0x2 - #define RK3308_DAC_R_HPMIX_GAIN_SFT 4 - #define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) - #define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) -@@ -936,6 +1019,8 @@ - #define RK3308_DAC_L_HPMIX_LINEIN (0x2 << RK3308_DAC_L_HPMIX_SEL_SFT) - #define RK3308_DAC_L_HPMIX_I2S (0x1 << RK3308_DAC_L_HPMIX_SEL_SFT) - #define RK3308_DAC_L_HPMIX_NONE (0x0 << RK3308_DAC_L_HPMIX_SEL_SFT) -+#define RK3308_DAC_L_HPMIX_GAIN_MIN 0x1 -+#define RK3308_DAC_L_HPMIX_GAIN_MAX 0x2 - #define RK3308_DAC_L_HPMIX_GAIN_SFT 0 - #define RK3308_DAC_L_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_L_HPMIX_GAIN_SFT) - #define RK3308_DAC_L_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_L_HPMIX_GAIN_SFT) -@@ -955,6 +1040,30 @@ - #define RK3308_DAC_L_HPMIX_EN (0x1 << 0) - #define RK3308_DAC_L_HPMIX_DIS (0x0 << 0) - -+/* RK3308_DAC_ANA_CON14 - REG: 0x0478 */ -+#define RK3308_DAC_VCM_LINEOUT_EN (0x1 << 4) -+#define RK3308_DAC_VCM_LINEOUT_DIS (0x0 << 4) -+#define RK3308_DAC_CURRENT_CHARGE_SFT 0 -+#define RK3308_DAC_CURRENT_CHARGE_MSK (0xf << RK3308_DAC_CURRENT_CHARGE_SFT) -+ -+/* -+ * 1: Choose the current I -+ * 0: Don't choose the current I -+ */ -+#define RK3308_DAC_SEL_I(x) (x & 0xf) -+ -+/* RK3308_DAC_ANA_CON15 - REG: 0x047C */ -+#define RK3308_DAC_LINEOUT_POP_SOUND_R_SFT 4 -+#define RK3308_DAC_LINEOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_R_SEL_DC_FROM_INTERNAL (0x2 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_R_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) -+#define RK3308_DAC_LINEOUT_POP_SOUND_L_SFT 0 -+#define RK3308_DAC_LINEOUT_POP_SOUND_L_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_L_SEL_DC_FROM_INTERNAL (0x2 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_L_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+#define RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) -+ - #define RK3308_HIFI 0x0 - - #endif /* __RK3308_CODEC_H__ */ -diff --git a/sound/soc/codecs/rk3308_codec_provider.h b/sound/soc/codecs/rk3308_codec_provider.h -new file mode 100644 -index 000000000000..68042b1328dc ---- /dev/null -+++ b/sound/soc/codecs/rk3308_codec_provider.h -@@ -0,0 +1,28 @@ -+/* -+ * rk3308_codec_provider.h -- RK3308 ALSA Soc Audio Driver -+ * -+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#ifndef __RK3308_CODEC_PROVIDER_H__ -+#define __RK3308_CODEC_PROVIDER_H__ -+ -+#ifdef CONFIG_SND_SOC_RK3308 -+extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+ struct snd_soc_jack *hpdet_jack); -+#endif -+ -+#endif /* __RK3308_CODEC_PROVIDER_H__ */ --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch b/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch deleted file mode 100644 index 0223222..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/board-rockpis-0022-ASoC-rk3308_codec-replace-codec-to-component.patch +++ /dev/null @@ -1,459 +0,0 @@ -From b882c2185ab561ec88c2540623cfa49e2cb56956 Mon Sep 17 00:00:00 2001 -From: ashthespy -Date: Mon, 3 Feb 2020 19:35:42 +0100 -Subject: [PATCH 22/23] ASoC: rk3308_codec: replace codec to component - ---- - sound/soc/codecs/rk3308_codec.c | 159 ++++++++++++----------- - sound/soc/codecs/rk3308_codec_provider.h | 2 +- - 2 files changed, 84 insertions(+), 77 deletions(-) - -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -index 815e22fc346c..16bfb215586e 100644 ---- a/sound/soc/codecs/rk3308_codec.c -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -31,7 +31,7 @@ - #include - #include - #include --#include -+// #include - #include - #include - #include -@@ -156,7 +156,7 @@ struct rk3308_codec_priv { - struct gpio_desc *hp_ctl_gpio; - struct gpio_desc *spk_ctl_gpio; - struct gpio_desc *pa_drv_gpio; -- struct snd_soc_codec *codec; -+ struct snd_soc_component *component; - struct snd_soc_jack *hpdet_jack; - struct regulator *vcc_micbias; - u32 codec_ver; -@@ -883,8 +883,8 @@ static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { - static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - - if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { -@@ -904,8 +904,8 @@ static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value = ucontrol->value.integer.value[0]; - int grp = e->reg; -@@ -970,8 +970,8 @@ static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -998,8 +998,8 @@ static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -1032,8 +1032,8 @@ static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -1064,8 +1064,8 @@ static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - int grp = e->reg; -@@ -1098,8 +1098,8 @@ static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - ucontrol->value.integer.value[0] = rk3308->micbias_volt; - -@@ -1109,8 +1109,8 @@ static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int volt = ucontrol->value.integer.value[0]; - int ret; - -@@ -1133,8 +1133,8 @@ static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - ucontrol->value.integer.value[0] = rk3308->enable_micbias; - -@@ -1144,8 +1144,8 @@ static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int on = ucontrol->value.integer.value[0]; - - if (on) { -@@ -1168,8 +1168,8 @@ static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int gain = ucontrol->value.integer.value[0]; - - if (gain > RK3308_ADC_CH1_MIC_GAIN_MAX) { -@@ -1197,8 +1197,8 @@ static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value; - -@@ -1222,8 +1222,8 @@ static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int value = ucontrol->value.integer.value[0]; - -@@ -1259,8 +1259,8 @@ static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int dgain = ucontrol->value.integer.value[0]; - - if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) { -@@ -1283,8 +1283,8 @@ static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, - static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int dgain = ucontrol->value.integer.value[0]; - - if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) { -@@ -1408,9 +1408,9 @@ static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) - } - } - --static int rk3308_codec_reset(struct snd_soc_codec *codec) -+static int rk3308_codec_reset(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - reset_control_assert(rk3308->reset); - usleep_range(2000, 2500); /* estimated value */ -@@ -1452,10 +1452,10 @@ static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308) - return 0; - } - --static int rk3308_set_bias_level(struct snd_soc_codec *codec, -+static int rk3308_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - switch (level) { - case SND_SOC_BIAS_ON: -@@ -1473,11 +1473,11 @@ static int rk3308_set_bias_level(struct snd_soc_codec *codec, - return 0; - } - --static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai, -+static int rk3308_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) - { -- struct snd_soc_codec *codec = codec_dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; - int idx, grp, is_master; - int type = ADC_TYPE_ALL; -@@ -1721,8 +1721,8 @@ static int rk3308_codec_update_adc_grps(struct rk3308_codec_priv *rk3308, - - static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - int dgain; -@@ -3630,8 +3630,8 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - struct snd_pcm_str *playback_str = - &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; - int type = ADC_TYPE_LOOPBACK; -@@ -3705,8 +3705,8 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, - static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - int type = ADC_TYPE_LOOPBACK; - int idx, grp; - -@@ -3749,8 +3749,8 @@ static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, - static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - { -- struct snd_soc_codec *codec = dai->codec; -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct snd_soc_component *component = dai->component; -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - rk3308_codec_close_playback(rk3308); -@@ -3809,9 +3809,9 @@ static struct snd_soc_dai_driver rk3308_dai[] = { - }, - }; - --static int rk3308_suspend(struct snd_soc_codec *codec) -+static int rk3308_suspend(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - if (rk3308->no_deep_low_power) - goto out; -@@ -3822,13 +3822,13 @@ static int rk3308_suspend(struct snd_soc_codec *codec) - clk_disable_unprepare(rk3308->pclk); - - out: -- rk3308_set_bias_level(codec, SND_SOC_BIAS_OFF); -+ rk3308_set_bias_level(component, SND_SOC_BIAS_OFF); - return 0; - } - --static int rk3308_resume(struct snd_soc_codec *codec) -+static int rk3308_resume(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - int ret = 0; - - if (rk3308->no_deep_low_power) -@@ -3857,7 +3857,7 @@ static int rk3308_resume(struct snd_soc_codec *codec) - - rk3308_codec_dlp_up(rk3308); - out: -- rk3308_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -+ rk3308_set_bias_level(component, SND_SOC_BIAS_STANDBY); - return ret; - } - -@@ -3972,7 +3972,7 @@ static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) - int ret; - - if (rk3308->codec_ver == ACODEC_VERSION_B) { -- ret = snd_soc_add_codec_controls(rk3308->codec, -+ ret = snd_soc_add_component_controls(rk3308->component, - mic_gains_b, - ARRAY_SIZE(mic_gains_b)); - if (ret) { -@@ -3982,7 +3982,7 @@ static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) - return ret; - } - } else { -- ret = snd_soc_add_codec_controls(rk3308->codec, -+ ret = snd_soc_add_component_controls(rk3308->component, - mic_gains_a, - ARRAY_SIZE(mic_gains_a)); - if (ret) { -@@ -4081,15 +4081,15 @@ static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308) - return 0; - } - --static int rk3308_probe(struct snd_soc_codec *codec) -+static int rk3308_probe(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - int ext_micbias; - -- rk3308->codec = codec; -+ rk3308->component = component; - rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); - -- rk3308_codec_reset(codec); -+ rk3308_codec_reset(component); - rk3308_codec_power_on(rk3308); - - /* From vendor recommend, disable micbias at first. */ -@@ -4108,9 +4108,9 @@ static int rk3308_probe(struct snd_soc_codec *codec) - return 0; - } - --static int rk3308_remove(struct snd_soc_codec *codec) -+static void rk3308_remove(struct snd_soc_component *component) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - rk3308_headphone_ctl(rk3308, 0); - rk3308_speaker_ctl(rk3308, 0); -@@ -4124,17 +4124,25 @@ static int rk3308_remove(struct snd_soc_codec *codec) - regcache_cache_only(rk3308->regmap, false); - regcache_sync(rk3308->regmap); - -- return 0; - } - --static struct snd_soc_codec_driver soc_codec_dev_rk3308 = { -- .probe = rk3308_probe, -- .remove = rk3308_remove, -- .suspend = rk3308_suspend, -- .resume = rk3308_resume, -- .set_bias_level = rk3308_set_bias_level, -- .controls = rk3308_codec_dapm_controls, -- .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+static const struct snd_soc_component_driver soc_codec_dev_rk3308_component = { -+ .probe = rk3308_probe, -+ .remove = rk3308_remove, -+ .resume = rk3308_resume, -+ .suspend = rk3308_suspend, -+ .set_bias_level = rk3308_set_bias_level, -+ .controls = rk3308_codec_dapm_controls, -+ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), -+ // .dapm_widgets = rk3308_dapm_widgets, -+ // .num_dapm_widgets = ARRAY_SIZE(rk3308_dapm_widgets), -+ // .dapm_routes = rk3308_dapm_routes, -+ // .num_dapm_routes = ARRAY_SIZE(rk3308_dapm_routes), -+ // .suspend_bias_off = 1, -+ // .idle_bias_on = 1, -+ // .use_pmdown_time = 1, -+ .endianness = 1, -+ .non_legacy_dai_naming = 1, - }; - - static const struct reg_default rk3308_codec_reg_defaults[] = { -@@ -4299,14 +4307,14 @@ static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data) - return IRQ_HANDLED; - } - --void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_component *component, - struct snd_soc_jack *hpdet_jack); - EXPORT_SYMBOL_GPL(rk3308_codec_set_jack_detect_cb); - --static void rk3308_codec_set_jack_detect(struct snd_soc_codec *codec, -+static void rk3308_codec_set_jack_detect(struct snd_soc_component *component, - struct snd_soc_jack *hpdet_jack) - { -- struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec); -+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); - - rk3308->hpdet_jack = hpdet_jack; - -@@ -5114,10 +5122,10 @@ static int rk3308_platform_probe(struct platform_device *pdev) - - platform_set_drvdata(pdev, rk3308); - -- ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3308, -+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3308_component, - rk3308_dai, ARRAY_SIZE(rk3308_dai)); - if (ret < 0) { -- dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); -+ dev_err(&pdev->dev, "Failed to register component: %d\n", ret); - goto failed; - } - -@@ -5140,7 +5148,6 @@ static int rk3308_platform_remove(struct platform_device *pdev) - clk_disable_unprepare(rk3308->mclk_rx); - clk_disable_unprepare(rk3308->mclk_tx); - clk_disable_unprepare(rk3308->pclk); -- snd_soc_unregister_codec(&pdev->dev); - device_unregister(&rk3308->dev); - - return 0; -diff --git a/sound/soc/codecs/rk3308_codec_provider.h b/sound/soc/codecs/rk3308_codec_provider.h -index 68042b1328dc..34c1ef86a507 100644 ---- a/sound/soc/codecs/rk3308_codec_provider.h -+++ b/sound/soc/codecs/rk3308_codec_provider.h -@@ -21,7 +21,7 @@ - #define __RK3308_CODEC_PROVIDER_H__ - - #ifdef CONFIG_SND_SOC_RK3308 --extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_codec *codec, -+extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_component *component, - struct snd_soc_jack *hpdet_jack); - #endif - --- -2.25.1 - diff --git a/sys-kernel/decade-sources/files/patches-5.14/general-emmc-hs400es-init-tweak.patch b/sys-kernel/decade-sources/files/patches-5.14/general-emmc-hs400es-init-tweak.patch deleted file mode 100644 index 03144ff..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/general-emmc-hs400es-init-tweak.patch +++ /dev/null @@ -1,22 +0,0 @@ -This patch is required to boot some Rock Pi 4 and NanoPC T4 units -with kernel 5.3+ and is on par with how it is done in Rockchip's BSP. - -diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c -index de8fbc396..95858e554 100644 ---- a/drivers/mmc/core/mmc.c -+++ b/drivers/mmc/core/mmc.c -@@ -1371,12 +1371,12 @@ static int mmc_select_hs400es(struct mmc_card *card) - } - - mmc_set_timing(host, MMC_TIMING_MMC_HS); -+ mmc_set_clock(host, card->ext_csd.hs_max_dtr); -+ - err = mmc_switch_status(card, true); - if (err) - goto out_err; - -- mmc_set_clock(host, card->ext_csd.hs_max_dtr); -- - /* Switch card to DDR with strobe bit */ - val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE; - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, diff --git a/sys-kernel/decade-sources/files/patches-5.14/general-fix-es8316-kernel-panic.patch b/sys-kernel/decade-sources/files/patches-5.14/general-fix-es8316-kernel-panic.patch deleted file mode 100644 index 3a27c0c..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/general-fix-es8316-kernel-panic.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/sound/soc/codecs/es8316.c 2020-04-09 19:13:08.268473737 +0000 -+++ b/sound/soc/codecs/es8316.c 2020-04-09 19:14:00.535995842 +0000 -@@ -687,7 +687,7 @@ - snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE, - ES8316_GPIO_ENABLE_INTERRUPT, 0); - -- if (es8316->jack->status & SND_JACK_MICROPHONE) { -+ if (es8316->jack && (es8316->jack->status & SND_JACK_MICROPHONE)) { - es8316_disable_micbias_for_mic_gnd_short_detect(component); - snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0); - } diff --git a/sys-kernel/decade-sources/files/patches-5.14/general-fix-mmc-signal-voltage-before-reboot.patch b/sys-kernel/decade-sources/files/patches-5.14/general-fix-mmc-signal-voltage-before-reboot.patch deleted file mode 100644 index cbd639d..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/general-fix-mmc-signal-voltage-before-reboot.patch +++ /dev/null @@ -1,43 +0,0 @@ -From ae85f92289509b44f291d2a95b858a36f7444aaa Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 17 Feb 2019 22:14:38 +0000 -Subject: [PATCH] mmc: core: set initial signal voltage on power off - -Some boards have SD card connectors where the power rail cannot be switched -off by the driver. If the card has not been power cycled, it may still be -using 1.8V signaling after a warm re-boot. Bootroms expecting 3.3V signaling -will fail to boot from a UHS card that continue to use 1.8V signaling. - -Set initial signal voltage in mmc_power_off() to allow re-boot to function. - -This fixes re-boot with UHS cards on Asus Tinker Board (Rockchip RK3288), -same issue have been seen on some Rockchip RK3399 boards. - -I am sending this as a RFC because I have no insights into SD/MMC subsystem, -this change fix a re-boot issue on my boards and does not break emmc/sdio. -Is this an acceptable workaround? Any advice is appreciated. - -Signed-off-by: Jonas Karlman ---- - drivers/mmc/core/core.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index d42037f0f..019dc3555 100644 ---- a/drivers/mmc/core/core.c -+++ b/drivers/mmc/core/core.c -@@ -1349,6 +1349,14 @@ void mmc_power_off(struct mmc_host *host) - if (host->ios.power_mode == MMC_POWER_OFF) - return; - -+ mmc_set_initial_signal_voltage(host); -+ -+ /* -+ * This delay should be sufficient to allow the power supply -+ * to reach the minimum voltage. -+ */ -+ mmc_delay(host->ios.power_delay_ms); -+ - mmc_pwrseq_power_off(host); - - host->ios.clock = 0; diff --git a/sys-kernel/decade-sources/files/patches-5.14/general-increasing_DMA_block_memory_allocation_to_2048.patch b/sys-kernel/decade-sources/files/patches-5.14/general-increasing_DMA_block_memory_allocation_to_2048.patch deleted file mode 100644 index fc6c248..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/general-increasing_DMA_block_memory_allocation_to_2048.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c -index 6bc74a2d5..e3827da51 100644 ---- a/kernel/dma/pool.c -+++ b/kernel/dma/pool.c -@@ -164,13 +164,11 @@ static int __init dma_atomic_pool_init(void) - int ret = 0; - - /* -- * If coherent_pool was not used on the command line, default the pool -- * sizes to 128KB per 1GB of memory, min 128KB, max MAX_ORDER-1. -+ * Always use 2MiB as default pool size. -+ * See: https://forum.armbian.com/topic/4811-uas-mainline-kernel-coherent-pool-memory-size/ - */ - if (!atomic_pool_size) { -- unsigned long pages = totalram_pages() / (SZ_1G / SZ_128K); -- pages = min_t(unsigned long, pages, MAX_ORDER_NR_PAGES); -- atomic_pool_size = max_t(size_t, pages << PAGE_SHIFT, SZ_128K); -+ atomic_pool_size = SZ_2M; - } - INIT_WORK(&atomic_pool_work, atomic_pool_work_fn); - diff --git a/sys-kernel/decade-sources/files/patches-5.14/general-rk808-configurable-switch-voltage-steps.patch b/sys-kernel/decade-sources/files/patches-5.14/general-rk808-configurable-switch-voltage-steps.patch deleted file mode 100644 index ce5ec81..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/general-rk808-configurable-switch-voltage-steps.patch +++ /dev/null @@ -1,91 +0,0 @@ -This patch allows to change the way that BUCK1 and BUCK2 of rk808 PMIC set voltage. - -It allows to change the hardcoded max. 100mV per one change -to any multiple of 12.5mV while keeping the 100mV default. - -It was observed that making the steps smaller (eg. 50mV = 4 * 12.5mV) -makes the NanoPi M4V2 running stable. - -One can configure the max number of steps per single change using -the "max-buck-steps-per-change" property of rk808 node in device tree. - -Below example ensures that voltage is not changed in jumps larger than 50mV: - -&rk808 { - max-buck-steps-per-change = <4>; -} - -Be aware that changing this parameter affects the time taken to switch between -OPPs of LiTTLE cores of rk3399. - -For overclocked LiTTLE cores with base 408MHz @ 0.825V -and max. 1.5GHz @ 1.2V it will take 7 steps of 50mV (at least 65uS each - caused by i2c), -the final 25mV step and 1uS to settle: 7 x 65uS + 1uS = 456uS. - -With default setting it would be 3 steps of 100mV (at least 65uS each - caused by i2c), -the final 75mV step and 1uS to settle: 3 x 65uS + 1uS = 196uS. - -Signed-off-by: Piotr Szczepanik - -diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c -index e926c1a85..cc3ec4803 100644 ---- a/drivers/regulator/rk808-regulator.c -+++ b/drivers/regulator/rk808-regulator.c -@@ -156,6 +156,7 @@ - - struct rk808_regulator_data { - struct gpio_desc *dvs_gpio[2]; -+ unsigned max_buck_steps_per_change; - }; - - static const int rk808_buck_config_regs[] = { -@@ -239,7 +240,8 @@ static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) - } - - static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev, -- unsigned sel) -+ unsigned sel, -+ int max_steps) - { - int ret, delta_sel; - unsigned int old_sel, tmp, val, mask = rdev->desc->vsel_mask; -@@ -258,8 +260,8 @@ static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev, - * the risk of overshoot. Put it into a multi-step, can effectively - * avoid this problem, a step is 100mv here. - */ -- while (delta_sel > MAX_STEPS_ONE_TIME) { -- old_sel += MAX_STEPS_ONE_TIME; -+ while (delta_sel > max_steps) { -+ old_sel += max_steps; - val = old_sel << (ffs(mask) - 1); - val |= tmp; - -@@ -293,12 +295,13 @@ static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev, - struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - struct gpio_desc *gpio = pdata->dvs_gpio[id]; -+ int max_steps = pdata->max_buck_steps_per_change; - unsigned int reg = rdev->desc->vsel_reg; - unsigned old_sel; - int ret, gpio_level; - - if (!gpio) -- return rk808_buck1_2_i2c_set_voltage_sel(rdev, sel); -+ return rk808_buck1_2_i2c_set_voltage_sel(rdev, sel, max_steps); - - gpio_level = gpiod_get_value(gpio); - if (gpio_level == 0) { -@@ -1292,6 +1295,12 @@ static int rk808_regulator_dt_parse_pdata(struct device *dev, - 0 : tmp); - } - -+ tmp = of_property_read_u32(client_dev->of_node, "max-buck-steps-per-change", &pdata->max_buck_steps_per_change); -+ if (tmp) { -+ pdata->max_buck_steps_per_change = MAX_STEPS_ONE_TIME; -+ } -+ dev_info(dev, "max buck steps per change: %d\n", pdata->max_buck_steps_per_change); -+ - dt_parse_end: - of_node_put(np); - return ret; - diff --git a/sys-kernel/decade-sources/files/patches-5.14/general-rt5651-add-mclk.patch b/sys-kernel/decade-sources/files/patches-5.14/general-rt5651-add-mclk.patch deleted file mode 100644 index 26c6320..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/general-rt5651-add-mclk.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c -index c506c9305..41a08b320 100644 ---- a/sound/soc/codecs/rt5651.c -+++ b/sound/soc/codecs/rt5651.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #include "rl6231.h" - #include "rt5651.h" -@@ -1511,6 +1512,7 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, - static int rt5651_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) - { -+ struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); - switch (level) { - case SND_SOC_BIAS_PREPARE: - if (SND_SOC_BIAS_STANDBY == snd_soc_component_get_bias_level(component)) { -@@ -1518,6 +1520,13 @@ static int rt5651_set_bias_level(struct snd_soc_component *component, - snd_soc_component_update_bits(component, RT5651_D_MISC, - 0xc00, 0xc00); - } -+ if (!IS_ERR(rt5651->mclk)){ -+ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) { -+ clk_disable_unprepare(rt5651->mclk); -+ } else { -+ clk_prepare_enable(rt5651->mclk); -+ } -+ } - break; - case SND_SOC_BIAS_STANDBY: - if (SND_SOC_BIAS_OFF == snd_soc_component_get_bias_level(component)) { -@@ -2059,6 +2068,13 @@ static int rt5651_probe(struct snd_soc_component *component) - { - struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); - -+ /* Check if MCLK provided */ -+ rt5651->mclk = devm_clk_get(component->dev, "mclk"); -+ if (PTR_ERR(rt5651->mclk) == -EPROBE_DEFER){ -+ dev_err(component->dev, "unable to get mclk\n"); -+ return -EPROBE_DEFER; -+ } -+ - rt5651->component = component; - - snd_soc_component_update_bits(component, RT5651_PWR_ANLG1, -diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h -index 20c33a3ec..17524fa9f 100644 ---- a/sound/soc/codecs/rt5651.h -+++ b/sound/soc/codecs/rt5651.h -@@ -2097,6 +2097,7 @@ struct rt5651_priv { - - int dmic_en; - bool hp_mute; -+ struct clk *mclk; - }; - - #endif /* __RT5651_H__ */ diff --git a/sys-kernel/decade-sources/files/patches-5.14/rk3399-add-sclk-i2sout-src-clock.patch b/sys-kernel/decade-sources/files/patches-5.14/rk3399-add-sclk-i2sout-src-clock.patch deleted file mode 100644 index 5573ece..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/rk3399-add-sclk-i2sout-src-clock.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c -index ce1d2446f..38447441b 100644 ---- a/drivers/clk/rockchip/clk-rk3399.c -+++ b/drivers/clk/rockchip/clk-rk3399.c -@@ -620,7 +620,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { - GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT, - RK3399_CLKGATE_CON(8), 11, GFLAGS), - -- MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, -+ MUX(SCLK_I2SOUT_SRC, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, - RK3399_CLKSEL_CON(31), 0, 2, MFLAGS), - COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT, - RK3399_CLKSEL_CON(31), 2, 1, MFLAGS, -diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h -index 44e0a319f..b7b07dfda 100644 ---- a/include/dt-bindings/clock/rk3399-cru.h -+++ b/include/dt-bindings/clock/rk3399-cru.h -@@ -19,6 +19,7 @@ - #define ARMCLKB 9 - - /* sclk gates (special clocks) */ -+#define SCLK_I2SOUT_SRC 64 - #define SCLK_I2C1 65 - #define SCLK_I2C2 66 - #define SCLK_I2C3 67 diff --git a/sys-kernel/decade-sources/files/patches-5.14/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch b/sys-kernel/decade-sources/files/patches-5.14/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch deleted file mode 100644 index 8ca2079..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index bcd31e9d6..91f1aa809 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -396,6 +396,7 @@ usbdrd_dwc3_0: usb@fe800000 { - snps,dis_u2_susphy_quirk; - snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; -+ snps,xhci-trb-ent-quirk; - power-domains = <&power RK3399_PD_USB3>; - status = "disabled"; - }; -@@ -461,6 +462,7 @@ usbdrd_dwc3_1: usb@fe900000 { - snps,dis_u2_susphy_quirk; - snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; -+ snps,xhci-trb-ent-quirk; - power-domains = <&power RK3399_PD_USB3>; - status = "disabled"; - }; diff --git a/sys-kernel/decade-sources/files/patches-5.14/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch b/sys-kernel/decade-sources/files/patches-5.14/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch deleted file mode 100644 index 662969f..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/rk3399-pci-rockchip-support-ep-gpio-undefined-case.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 9de42a7ce7b821596a151cfaa0aca79d53c2170f Mon Sep 17 00:00:00 2001 -From: Igor Pecovnik -Date: Sun, 7 Mar 2021 15:24:02 +0100 -Subject: [PATCH] oo - -Signed-off-by: Aditya Prayoga -Changed by: Igor Pecovnik ---- - drivers/pci/controller/pcie-rockchip.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c -index 990a00e08..193d26562 100644 ---- a/drivers/pci/controller/pcie-rockchip.c -+++ b/drivers/pci/controller/pcie-rockchip.c -@@ -118,8 +118,7 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) - } - - if (rockchip->is_rc) { -- rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", -- GPIOD_OUT_HIGH); -+ rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", GPIOD_OUT_HIGH); - if (IS_ERR(rockchip->ep_gpio)) - return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio), - "failed to get ep GPIO\n"); --- -Created with Armbian build tools https://github.com/armbian/build - diff --git a/sys-kernel/decade-sources/files/patches-5.14/rk3399-sd-drive-level-8ma.patch b/sys-kernel/decade-sources/files/patches-5.14/rk3399-sd-drive-level-8ma.patch deleted file mode 100644 index cac129a..0000000 --- a/sys-kernel/decade-sources/files/patches-5.14/rk3399-sd-drive-level-8ma.patch +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index 6eb9dda..d6fc676 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -2285,35 +2285,35 @@ - sdmmc { - sdmmc_bus1: sdmmc-bus1 { - rockchip,pins = -- <4 RK_PB0 1 &pcfg_pull_up>; -+ <4 RK_PB0 1 &pcfg_pull_up_8ma>; - }; - - sdmmc_bus4: sdmmc-bus4 { - rockchip,pins = -- <4 RK_PB0 1 &pcfg_pull_up>, -- <4 RK_PB1 1 &pcfg_pull_up>, -- <4 RK_PB2 1 &pcfg_pull_up>, -- <4 RK_PB3 1 &pcfg_pull_up>; -+ <4 RK_PB0 1 &pcfg_pull_up_8ma>, -+ <4 RK_PB1 1 &pcfg_pull_up_8ma>, -+ <4 RK_PB2 1 &pcfg_pull_up_8ma>, -+ <4 RK_PB3 1 &pcfg_pull_up_8ma>; - }; - - sdmmc_clk: sdmmc-clk { - rockchip,pins = -- <4 RK_PB4 1 &pcfg_pull_none>; -+ <4 RK_PB4 1 &pcfg_pull_none_12ma>; - }; - - sdmmc_cmd: sdmmc-cmd { - rockchip,pins = -- <4 RK_PB5 1 &pcfg_pull_up>; -+ <4 RK_PB5 1 &pcfg_pull_up_8ma>; - }; - - sdmmc_cd: sdmmc-cd { - rockchip,pins = -- <0 RK_PA7 1 &pcfg_pull_up>; -+ <0 RK_PA7 1 &pcfg_pull_up>; - }; - - sdmmc_wp: sdmmc-wp { - rockchip,pins = -- <0 RK_PB0 1 &pcfg_pull_up>; -+ <0 RK_PB0 1 &pcfg_pull_up_8ma>; - }; - }; -