Merge Upstream Baylibre 4.19 branch into Excelsior repo
* Update kernel to 4.19.125
* Enable USB OTG
Change-Id: Ib197c9a2e66ba31f7fedb38835c5e7deb779593b
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 509111f..0045410 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -6,6 +6,8 @@
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-coral.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-coral-evt2-overlay.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-coral-display-overlay.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt8167-coral-display-overlay.dts b/arch/arm64/boot/dts/mediatek/mt8167-coral-display-overlay.dts
new file mode 100644
index 0000000..0be0d31
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8167-coral-display-overlay.dts
@@ -0,0 +1,28 @@
+// Set display panel config
+/dts-v1/;
+/plugin/;
+
+#include "mt8167-pinfunc.h"
+
+/ {
+ compatible = "mediatek,mt8167";
+ fragment@0 {
+ target = <&pio>;
+ __overlay__ {
+ pwm0_pin_default: pwm0_pin_default {
+ pins1 {
+ pinmux = <MT8167_PIN_25_EINT25__FUNC_PWM_B>;
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target = <&pwm>;
+ __overlay__ {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_pin_default>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8167-coral-evt2-overlay.dts b/arch/arm64/boot/dts/mediatek/mt8167-coral-evt2-overlay.dts
new file mode 100644
index 0000000..a9e0b9d
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8167-coral-evt2-overlay.dts
@@ -0,0 +1,13 @@
+// Set EVT2 config
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "mediatek,mt8167";
+ fragment@0 {
+ target = <&memory>;
+ __overlay__ {
+ reg = <0 0x40000000 0 0x80000000>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8167-coral.dts b/arch/arm64/boot/dts/mediatek/mt8167-coral.dts
index 0ac8355..fec8ffb 100644
--- a/arch/arm64/boot/dts/mediatek/mt8167-coral.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8167-coral.dts
@@ -22,7 +22,7 @@
stdout-path = "serial0:921600n8";
};
- memory@40000000 {
+ memory: memory@40000000 {
device_type = "memory";
reg = <0 0x40000000 0 0x40000000>;
};
@@ -42,6 +42,54 @@
gpio = <&pio 17 GPIO_ACTIVE_LOW>;
regulator-always-on;
};
+
+ ga1600_pmic: ga1600_pmic {
+ compatible = "regulator-fixed";
+ regulator-name = "ga1600_pmic";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ gpio = <&pio 56 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <0>;
+ enable-active-high;
+ regulator-always-on;
+ };
+ ga1600_reset: ga1600_reset {
+ compatible = "regulator-fixed";
+ regulator-name = "ga1600_reset";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ gpio = <&pio 57 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <150>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ mt8167_audio_codec: mt8167_audio_codec {
+ compatible = "mediatek,mt8167-codec";
+ status = "okay";
+ clocks = <&topckgen CLK_TOP_AUDIO>;
+ clock-names = "bus";
+ mediatek,afe-regmap = <&afe>;
+ mediatek,apmixedsys-regmap = <&apmixedsys>;
+ mediatek,pwrap-regmap = <&pwrap>;
+ mediatek,dmic-wire-mode = <1>; // TWO_WIRE
+ mediatek,headphone-cap-sel = <1>; // 22uF
+ mediatek,speaker-mode = <0>; // Class D
+ };
+
+ sound: sound {
+ compatible = "mediatek,snd-soc-mt8167-excelsior";
+ status = "okay";
+ mediatek,platform = <&afe>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ mediatek,jack-detect-gpio = <&pio 40 0>;
+ };
+};
+
+&afe {
+ status = "okay";
+ mediatek,tdm-out-mode = <0>; // HDMI
};
&cpu0 {
@@ -67,11 +115,56 @@
#interrupt-cells = <2>;
};
+&mt6392_vcamaf_reg {
+ regulator-always-on;
+};
+
+&mt6392_vgp1_reg {
+ regulator-min-microvolt = <3300000>;
+ regulator-always-on;
+};
+
&uart0 {
status = "okay";
};
&pio {
+ i2c0_pins_a: i2c0 {
+ pins1 {
+ pinmux = <MT8167_PIN_58_SDA0__FUNC_SDA0_0>,
+ <MT8167_PIN_59_SCL0__FUNC_SCL0_0>;
+ bias-disable;
+ };
+ };
+
+ i2c1_pins_a: i2c1 {
+ pins1 {
+ pinmux = <MT8167_PIN_52_SDA1__FUNC_SDA1_0>,
+ <MT8167_PIN_53_SCL1__FUNC_SCL1_0>;
+ bias-disable;
+ };
+ };
+
+ i2c2_pins_a: i2c2 {
+ pins1 {
+ pinmux = <MT8167_PIN_60_SDA2__FUNC_GPIO60>,
+ <MT8167_PIN_61_SCL2__FUNC_GPIO61>;
+ bias-disable;
+ };
+ pins_a71ch_reset {
+ pinmux = <MT8516_PIN_23_EINT23__FUNC_GPIO23>;
+ output-high;
+ };
+ };
+
+ aud_pins_default: audiodefault {
+ pins1 {
+ pinmux = <MT8167_PIN_40_KPROW0__FUNC_GPIO40>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
mmc0_pins_default: mmc0default {
pins_cmd_dat {
pinmux = <MT8167_PIN_120_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
@@ -96,6 +189,11 @@
pinmux = <MT8167_PIN_114_MSDC0_RSTB__FUNC_MSDC0_RSTB>;
bias-pull-up;
};
+
+ pins_user {
+ pinmux = <MT8167_PIN_2_EINT2__FUNC_GPIO2>;
+ bias-pull-up;
+ };
};
mmc0_pins_uhs: mmc0@0{
@@ -126,6 +224,112 @@
};
};
+ mmc1_pins_default: mmc1default {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_106_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+ <MT8167_PIN_107_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+ <MT8167_PIN_108_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+ <MT8167_PIN_109_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+ <MT8167_PIN_104_MSDC1_CMD__FUNC_MSDC1_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT8167_PIN_105_MSDC1_CLK__FUNC_MSDC1_CLK>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_pmu_en {
+ pinmux = <MT8167_PIN_48_SPI_CS__FUNC_GPIO48>;
+ output-low;
+ };
+
+ pins_test_en {
+ pinmux = <MT8167_PIN_38_MRG_DI__FUNC_GPIO38>;
+ output-low;
+ };
+
+ pins_sys_rst {
+ pinmux = <MT8167_PIN_47_JTDO__FUNC_GPIO47>;
+ output-high;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1@0 {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_106_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+ <MT8167_PIN_107_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+ <MT8167_PIN_108_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+ <MT8167_PIN_109_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+ <MT8167_PIN_104_MSDC1_CMD__FUNC_MSDC1_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT8167_PIN_105_MSDC1_CLK__FUNC_MSDC1_CLK>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_pmu_en {
+ pinmux = <MT8167_PIN_48_SPI_CS__FUNC_GPIO48>;
+ output-high;
+ };
+
+ pins_test_en {
+ pinmux = <MT8167_PIN_38_MRG_DI__FUNC_GPIO38>;
+ output-low;
+ };
+
+ pins_sys_rst {
+ pinmux = <MT8167_PIN_47_JTDO__FUNC_GPIO47>;
+ output-high;
+ };
+ };
+
+ mmc2_pins_default: mmc2default {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_70_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
+ <MT8167_PIN_71_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
+ <MT8167_PIN_72_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
+ <MT8167_PIN_73_MSDC2_DAT3__FUNC_MSDC2_DAT3>,
+ <MT8167_PIN_68_MSDC2_CMD__FUNC_MSDC2_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT8167_PIN_69_MSDC2_CLK__FUNC_MSDC2_CLK>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ mmc2_pins_uhs: mmc2@0 {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_70_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
+ <MT8167_PIN_71_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
+ <MT8167_PIN_72_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
+ <MT8167_PIN_73_MSDC2_DAT3__FUNC_MSDC2_DAT3>,
+ <MT8167_PIN_68_MSDC2_CMD__FUNC_MSDC2_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT8167_PIN_69_MSDC2_CLK__FUNC_MSDC2_CLK>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
hdmi_pins_default: hdmi_pins_default {
};
@@ -135,6 +339,56 @@
bias-pull-down;
};
};
+
+ /* GA1600 GPIO start */
+ ga1600_boot_fail: boot_fail {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_55_I2S_DATA_IN__FUNC_GPIO55>;
+ slew-rate = <1>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
+ ga1600_pmic_en: pmic_en {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_56_I2S_LRCK__FUNC_GPIO56>;
+ slew-rate = <1>;
+ output-high;
+ };
+ };
+
+ ga1600_reset_n: reset_n {
+ pins_cmd_dat {
+ pinmux = <MT8167_PIN_57_I2S_BCK__FUNC_GPIO57>;
+ slew-rate = <1>;
+ output-high;
+ };
+ };
+ /* GA1600 GPIO end */
+};
+
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ clock-div = <2>;
+};
+
+&i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins_a>;
+ clock-div = <2>;
+};
+
+&i2c2 {
+ status = "okay";
+ compatible = "i2c-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_a>;
+ sda-gpios = <&pio 60 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&pio 61 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
};
&mmc0 {
@@ -152,6 +406,50 @@
non-removable;
};
+&mmc1 {
+ status = "okay";
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ vmmc-supply = <&mt6392_vemc3v3_reg>;
+ vqmmc-supply = <&mt6392_vio18_reg>;
+ bus-width = <4>;
+ max-frequency = <200000000>;
+ keep-power-in-suspend;
+ cap-sd-highspeed;
+ enable-sdio-wakeup;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ cap-sdio-irq;
+ non-removable;
+
+ mt7668 {
+ wifi: mt7668-wifi@0 {
+ compatible = "mediatek,mt8516-wifi", "mediatek,mt7668-wifi";
+ mac-address = [00 00 00 00 00 00];
+ };
+ bluetooth: mt7668-bluetooth@0 {
+ compatible = "mediatek,mt8516-bluetooth", "mediatek,mt7668-bluetooth";
+ mac-address = [00 00 00 00 00 00];
+ };
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc2_pins_default>;
+ pinctrl-1 = <&mmc2_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <200000000>;
+ cap-sd-highspeed;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ broken-cd;
+ vmmc-supply = <&mt6392_vmch_reg>;
+ vqmmc-supply = <&mt6392_vmc_reg>;
+};
+
&dpi1 {
status = "okay";
ddc-i2c-bus = <&hdmiddc>;
@@ -226,3 +524,7 @@
};
};
};
+
+&usb1 {
+ status = "okay";
+};
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 745b0d0..6551942 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -29,6 +29,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
@@ -227,6 +228,8 @@ struct mtk_i2c {
unsigned char auto_restart;
bool ignore_restart_irq;
const struct mtk_i2c_compatible *dev_comp;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_default;
};
static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
@@ -934,6 +937,19 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (irq <= 0)
return irq;
+ i2c->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(i2c->pinctrl)) {
+ dev_err(&pdev->dev, "Cannot find pinctrl!\n");
+ return PTR_ERR(i2c->pinctrl);
+ }
+
+ i2c->pins_default = pinctrl_lookup_state(i2c->pinctrl, "default");
+ if (IS_ERR(i2c->pins_default)) {
+ dev_err(&pdev->dev, "Cannot find default pinctrl group!\n");
+ return PTR_ERR(i2c->pins_default);
+ }
+ pinctrl_select_state(i2c->pinctrl, i2c->pins_default);
+
init_completion(&i2c->msg_complete);
i2c->dev_comp = of_device_get_match_data(&pdev->dev);
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 0f2a196..cf3acf8 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -36,6 +36,8 @@
#define MT6397_RTC_BASE 0xe000
#define MT6397_RTC_SIZE 0x3e
#define MT6397_RTC_WRTGR_OFFSET 0x3c
+#define MT6392_TOP_RST_MISC_SYSRSTB_MASK 0x1
+#define MT6392_TOP_RST_MISC_SYSRSTB_SHIFT 1
static const struct resource mt6358_rtc_resources[] = {
{
@@ -272,6 +274,9 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
mt6392_devs, ARRAY_SIZE(mt6392_devs),
NULL, 0, pmic->irq_domain);
+ regmap_update_bits(pmic->regmap, MT6392_TOP_RST_MISC,
+ MT6392_TOP_RST_MISC_SYSRSTB_MASK << MT6392_TOP_RST_MISC_SYSRSTB_SHIFT,
+ 1 << MT6392_TOP_RST_MISC_SYSRSTB_SHIFT);
break;
default:
diff --git a/drivers/misc/mediatek/gpu/gpu_rgx/m1.11_5516664/physmem.c b/drivers/misc/mediatek/gpu/gpu_rgx/m1.11_5516664/physmem.c
index d224eaa..88e7d18 100644
--- a/drivers/misc/mediatek/gpu/gpu_rgx/m1.11_5516664/physmem.c
+++ b/drivers/misc/mediatek/gpu/gpu_rgx/m1.11_5516664/physmem.c
@@ -565,7 +565,7 @@ PVRSRVGetMaxDevMemSizeKM( CONNECTION_DATA * psConnection,
IMG_DEVMEM_SIZE_T *puiLMASize,
IMG_DEVMEM_SIZE_T *puiUMASize )
{
- IMG_BOOL bLMA = IMG_FALSE, bUMA = IMG_FALSE;
+ IMG_BOOL bLMA = IMG_FALSE, bUMA = IMG_TRUE;
*puiLMASize = 0;
*puiUMASize = 0;
diff --git a/drivers/misc/mediatek/usb11/musbfsh_host.c b/drivers/misc/mediatek/usb11/musbfsh_host.c
index 0dd58e7..a1bc443 100644
--- a/drivers/misc/mediatek/usb11/musbfsh_host.c
+++ b/drivers/misc/mediatek/usb11/musbfsh_host.c
@@ -492,6 +492,9 @@ __releases(musbfsh->lock) __acquires(musbfsh->lock)
* urb->ep->desc.bEndpointAddress);
*/
+ if (is_dma_capable() && usb_pipein(urb->pipe) && usb_pipeendpoint(urb->pipe))
+ complete(&urb->done);
+
usb_hcd_unlink_urb_from_ep(musbfsh_to_hcd(musbfsh), urb);
spin_unlock(&musbfsh->lock);
usb_hcd_giveback_urb(musbfsh_to_hcd(musbfsh), urb, status);
@@ -720,9 +723,9 @@ u16 musbfsh_h_flush_rxfifo(struct musbfsh_hw_ep *hw_ep, u16 csr)
* leave toggle alone (may not have been saved yet)
*/
INFO("%s++\r\n", __func__);
- csr |= MUSBFSH_RXCSR_FLUSHFIFO | MUSBFSH_RXCSR_RXPKTRDY;
+ csr |= MUSBFSH_RXCSR_FLUSHFIFO;
csr &= ~(MUSBFSH_RXCSR_H_REQPKT | MUSBFSH_RXCSR_H_AUTOREQ |
- MUSBFSH_RXCSR_AUTOCLEAR);
+ MUSBFSH_RXCSR_AUTOCLEAR | MUSBFSH_RXCSR_RXPKTRDY);
/* write 2x to allow double buffering */
musbfsh_writew(hw_ep->regs, MUSBFSH_RXCSR, csr);
@@ -1748,6 +1751,12 @@ void musbfsh_host_rx(struct musbfsh *musbfsh, u8 epnum)
urb = next_urb(qh); /* current urb */
dma = is_dma_capable() ? hw_ep->rx_channel : NULL;
+
+ if (dma && (dma->status == MUSBFSH_DMA_STATUS_BUSY)) {
+ INFO("not Dma interrupt %s, @Line %d\n", __func__, __LINE__);
+ return;
+ }
+
status = 0;
xfer_len = 0;
@@ -1827,6 +1836,7 @@ void musbfsh_host_rx(struct musbfsh *musbfsh, u8 epnum)
dma->status = MUSBFSH_DMA_STATUS_CORE_ABORT;
(void)musbfsh->dma_controller->channel_abort(dma);
xfer_len = dma->actual_len;
+ dma->actual_len = 0L;
}
musbfsh_h_flush_rxfifo(hw_ep, 0);
musbfsh_writeb(epio, MUSBFSH_RXINTERVAL, 0);
@@ -1886,6 +1896,8 @@ void musbfsh_host_rx(struct musbfsh *musbfsh, u8 epnum)
urb->transfer_buffer_length ||
dma->actual_len < qh->maxpacket);
+ dma->actual_len = 0L;
+
/* send IN token for next packet, without AUTOREQ */
if (!done) {
val |= MUSBFSH_RXCSR_H_REQPKT;
@@ -2292,6 +2304,8 @@ static int musbfsh_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
urb->transfer_flags &= ~URB_DMA_MAP_SINGLE;
spin_lock_irqsave(&musbfsh->lock, flags);
+ init_completion(&urb->done);
+
/* add the urb to the ep, return 0 for no error. */
ret = usb_hcd_link_urb_to_ep(hcd, urb);
qh = ret ? NULL : hep->hcpriv;
@@ -2520,6 +2534,7 @@ static int musbfsh_cleanup_urb(struct urb *urb, struct musbfsh_qh *qh)
WARNING("abort %cX%d DMA for urb %p --> %d\n",
is_in ? 'R' : 'T', ep->epnum, urb, stat);
urb->actual_length += dma->actual_len;
+ dma->actual_len = 0L;
}
}
@@ -2609,8 +2624,18 @@ static int musbfsh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
musbfsh_host_free_ep_fifo(musbfsh, qh, is_in);
kfree(qh);
}
- } else
+ } else {
+ spin_unlock_irqrestore(&musbfsh->lock, flags);
+ if (is_dma_capable() && is_in && usb_pipeendpoint(urb->pipe)) {
+ ret = wait_for_completion_timeout(&urb->done, msecs_to_jiffies(50));
+ if (ret)
+ return status;
+
+ INFO("wait time out\n");
+ }
+ spin_lock_irqsave(&musbfsh->lock, flags);
ret = musbfsh_cleanup_urb(urb, qh);
+ }
done:
spin_unlock_irqrestore(&musbfsh->lock, flags);
return ret;
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index ca0dad3..64a9ae3 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>
@@ -75,6 +76,8 @@ struct mtk_pwm_chip {
void __iomem *regs;
struct clk *clks[MTK_CLK_MAX];
const struct mtk_pwm_platform_data *soc;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_default;
};
static const unsigned int mtk_pwm_reg_offset[] = {
@@ -256,6 +259,18 @@ static int mtk_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pc->regs))
return PTR_ERR(pc->regs);
+ pc->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(pc->pinctrl)) {
+ dev_err(&pdev->dev, "Cannot find pinctrl!\n");
+ return PTR_ERR(pc->pinctrl);
+ }
+
+ pc->pins_default = pinctrl_lookup_state(pc->pinctrl, "default");
+ if (IS_ERR(pc->pins_default)) {
+ dev_err(&pdev->dev, "Cannot find default pinctrl group!\n");
+ return PTR_ERR(pc->pins_default);
+ }
+
for (i = 0; i < data->num_pwms + 2 && pc->soc->has_clks; i++) {
pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]);
if (IS_ERR(pc->clks[i])) {
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index 4baf64f..47935e4 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -44,6 +44,11 @@
#define WDT_SWRST 0x14
#define WDT_SWRST_KEY 0x1209
+#define WDT_NONRST2 0x24
+#define REBOOT_BOOTLOADER_VALUE (1)
+#define REBOOT_BOOTLOADER_MASK (1)
+#define REBOOT_BOOTLOADER_SHIFT (2)
+
#define DRV_NAME "mtk-wdt"
#define DRV_VERSION "1.0"
@@ -135,6 +140,17 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev)
return 0;
}
+static void mtk_wdt_write_bootloader_flag(struct watchdog_device *wdt_dev) {
+ u32 reg;
+ struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
+ void __iomem *wdt_base = mtk_wdt->wdt_base;
+
+ reg = ioread32(wdt_base + WDT_NONRST2);
+ reg &= ~(REBOOT_BOOTLOADER_MASK << REBOOT_BOOTLOADER_SHIFT);
+ reg |= (REBOOT_BOOTLOADER_VALUE << REBOOT_BOOTLOADER_SHIFT);
+ iowrite32(reg, wdt_base + WDT_NONRST2);
+}
+
static const struct watchdog_info mtk_wdt_info = {
.identity = DRV_NAME,
.options = WDIOF_SETTIMEOUT |
@@ -151,6 +167,23 @@ static const struct watchdog_ops mtk_wdt_ops = {
.restart = mtk_wdt_restart,
};
+static ssize_t reset_bootloader_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+ struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev);
+
+ mtk_wdt_write_bootloader_flag(&mtk_wdt->wdt_dev);
+ return count;
+}
+
+static DEVICE_ATTR_WO(reset_bootloader);
+
+static struct attribute *mtk_wdt_attrs[] = {
+ &dev_attr_reset_bootloader.attr,
+ NULL
+};
+static const struct attribute_group mtk_wdt_attr_group = {
+ .attrs = mtk_wdt_attrs,
+};
+
static int mtk_wdt_probe(struct platform_device *pdev)
{
struct mtk_wdt_dev *mtk_wdt;
@@ -187,6 +220,10 @@ static int mtk_wdt_probe(struct platform_device *pdev)
if (unlikely(err))
return err;
+ err = sysfs_create_group(&pdev->dev.kobj, &mtk_wdt_attr_group);
+ if (unlikely(err))
+ return err;
+
dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
mtk_wdt->wdt_dev.timeout, nowayout);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index ff010d1..6e09ecfb 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1575,6 +1575,7 @@ struct urb {
int error_count; /* (return) number of ISO errors */
void *context; /* (in) context for completion */
usb_complete_t complete; /* (in) completion routine */
+ struct completion done; /* dma transfer done */
struct usb_iso_packet_descriptor iso_frame_desc[0];
/* (in) ISO ONLY */
};
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3e7badb..38b3aba 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -577,6 +577,11 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
if (hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG))
memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
+
+ if (strncmp(hdev->hw_info, "mt7668", strlen(hdev->hw_info)) == 0) {
+ hdev->commands[26] = 0x18;
+ hdev->commands[27] = 0x24;
+ }
}
static void hci_cc_read_local_features(struct hci_dev *hdev,
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 69102fd..fea676a 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -955,6 +955,12 @@ static int wireless_process_ioctl(struct net *net, struct iwreq *iwr,
else if (private)
return private(dev, iwr, cmd, info, handler);
}
+
+ /* Old driver API : call driver ioctl handler */
+ if (dev->netdev_ops->ndo_do_ioctl)
+ return dev->netdev_ops->ndo_do_ioctl(dev, (struct ifreq*)iwr, cmd);
+
+ dev_err(&dev->dev, "No handler found (wireless_process_ioctl)\n");
return -EOPNOTSUPP;
}
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index a232741..6df4ca1 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -262,6 +262,9 @@
-Wproperty_name_chars_strict
endif
+# Enable creation of __symbols__ node (used by overlay)
+DTC_FLAGS += -@
+
DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
# Generate an assembly file to wrap the output of the device tree compiler
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 99be3b3..cae5a00 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1283,6 +1283,9 @@
config SND_SOC_MT8167_CODEC
tristate
+config SND_SOC_MT6392_CODEC
+ tristate
+
# Amp
config SND_SOC_LM4857
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bd9d656..039b119 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -519,6 +519,7 @@
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o
obj-$(CONFIG_SND_SOC_MT8167_CODEC) += snd-soc-mt8167-codec.o
+obj-$(CONFIG_SND_SOC_MT6392_CODEC) += snd-soc-mt6392-codec.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
diff --git a/sound/soc/codecs/mt6392-codec.c b/sound/soc/codecs/mt6392-codec.c
index 23463f8..3f7caf9 100644
--- a/sound/soc/codecs/mt6392-codec.c
+++ b/sound/soc/codecs/mt6392-codec.c
@@ -13,11 +13,13 @@
* GNU General Public License for more details.
*/
-#include <sound/soc.h>
-#include <sound/tlv.h>
+#include "mt6392-codec.h"
#include <linux/debugfs.h>
#include <linux/delay.h>
-#include "mt6392-codec.h"
+#include <linux/module.h>
+#include <linux/of.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
/*
* Class D: has HW Trim mode and SW Trim mode
@@ -25,6 +27,32 @@
*
* The option used to choose the trim mode of Class D
*/
+static int int_spk_amp_enable_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct mt6392_codec_priv *codec_data =
+ snd_soc_component_get_drvdata(component);
+ uint32_t reg_value = snd_soc_component_read32(codec_data->codec, SPK_CON0);
+ ucontrol->value.integer.value[0] = reg_value & BIT(0) ? 1 : 0;
+ return 0;
+}
+
+static int int_spk_amp_enable_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct mt6392_codec_priv *codec_data =
+ snd_soc_component_get_drvdata(component);
+
+ if (ucontrol->value.integer.value[0] == 0)
+ mt6392_int_spk_turn_off(codec_data->codec);
+ else
+ mt6392_int_spk_turn_on(codec_data->codec);
+
+ return 0;
+}
+
#define USE_HW_TRIM_CLASS_D
/* Int Spk Amp Playback Volume
@@ -32,19 +60,37 @@
*/
static const unsigned int int_spk_amp_gain_tlv[] = {
TLV_DB_RANGE_HEAD(3),
- 0, 0, TLV_DB_SCALE_ITEM(0, 0, 1),
- 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
- 2, 15, TLV_DB_SCALE_ITEM(400, 100, 0),
+ 0,
+ 0,
+ TLV_DB_SCALE_ITEM(0, 0, 1),
+ 1,
+ 1,
+ TLV_DB_SCALE_ITEM(0, 0, 0),
+ 2,
+ 15,
+ TLV_DB_SCALE_ITEM(400, 100, 0),
};
/* Audio_Speaker_PGA_gain
* {mute, 0, 4, 5, 6, 7, 8, ..., 17} dB
*/
static const char *const int_spk_amp_gain_text[] = {
- "MUTE", "+0dB", "+4dB", "+5dB",
- "+6dB", "+7dB", "+8dB", "+9dB",
- "+10dB", "+11dB", "+12dB", "+13dB",
- "+14dB", "+15dB", "+16dB", "+17dB",
+ "MUTE",
+ "+0dB",
+ "+4dB",
+ "+5dB",
+ "+6dB",
+ "+7dB",
+ "+8dB",
+ "+9dB",
+ "+10dB",
+ "+11dB",
+ "+12dB",
+ "+13dB",
+ "+14dB",
+ "+15dB",
+ "+16dB",
+ "+17dB",
};
static const struct soc_enum int_spk_amp_gain_enum =
@@ -52,11 +98,11 @@ static const struct soc_enum int_spk_amp_gain_enum =
int_spk_amp_gain_text);
static int int_spk_amp_gain_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(component);
+ snd_soc_component_get_drvdata(component);
uint32_t value = 0;
value = codec_data->spk_amp_gain;
@@ -67,71 +113,53 @@ static int int_spk_amp_gain_get(struct snd_kcontrol *kcontrol,
}
static int int_spk_amp_gain_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(component);
+ snd_soc_component_get_drvdata(component);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
uint32_t value = ucontrol->value.integer.value[0];
if (value >= e->items)
return -EINVAL;
- snd_soc_component_update_bits(codec_data->codec, SPK_CON9,
- GENMASK(11, 8), value << 8);
+ snd_soc_component_update_bits(codec_data->codec, SPK_CON9, GENMASK(11, 8),
+ value << 8);
codec_data->spk_amp_gain = value;
- dev_dbg(codec_data->codec->dev, "%s value = %u\n",
- __func__, value);
-
- return 0;
-}
-
-static int int_spk_amp_gain_put_volsw(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int ret = 0;
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(component);
-
- ret = snd_soc_put_volsw(kcontrol, ucontrol);
- if (ret < 0)
- return ret;
-
- codec_data->spk_amp_gain = ucontrol->value.integer.value[0];
+ dev_dbg(codec_data->codec->dev, "%s value = %u\n", __func__, value);
return 0;
}
/* Internal speaker mode (AB/D) */
-static const char * const int_spk_amp_mode_texts[] = {
+static const char *const int_spk_amp_mode_texts[] = {
"Class D",
"Class AB",
};
static SOC_ENUM_SINGLE_EXT_DECL(mt6392_speaker_mode_enum,
- int_spk_amp_mode_texts);
+ int_spk_amp_mode_texts);
static int mt6392_spk_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(component);
+ snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = codec_data->speaker_mode;
return 0;
}
static int mt6392_spk_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(component);
+ snd_soc_component_get_drvdata(component);
int ret = 0;
uint32_t mode = ucontrol->value.integer.value[0];
@@ -148,7 +176,6 @@ static int mt6392_spk_mode_put(struct snd_kcontrol *kcontrol,
return ret;
}
-
/* Check OC Flag */
static const char *const mt6392_speaker_oc_flag_texts[] = {
"NoOverCurrent",
@@ -156,51 +183,46 @@ static const char *const mt6392_speaker_oc_flag_texts[] = {
};
static SOC_ENUM_SINGLE_EXT_DECL(mt6392_speaker_oc_flag_enum,
- mt6392_speaker_oc_flag_texts);
+ mt6392_speaker_oc_flag_texts);
static int mt6392_speaker_oc_flag_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(component);
- uint32_t reg_value = snd_soc_component_read32(codec_data->codec,
- SPK_CON6);
+ snd_soc_component_get_drvdata(component);
+ uint32_t reg_value = snd_soc_component_read32(codec_data->codec, SPK_CON6);
if (codec_data->speaker_mode == MT6392_CLASS_AB)
ucontrol->value.integer.value[0] =
- (reg_value & BIT(15)) ? 1 : 0;
+ (reg_value & BIT(15)) ? 1 : 0;
else
ucontrol->value.integer.value[0] =
- (reg_value & BIT(14)) ? 1 : 0;
+ (reg_value & BIT(14)) ? 1 : 0;
return 0;
}
static const struct snd_kcontrol_new mt6392_codec_controls[] = {
/* Internal speaker PGA gain control */
- SOC_SINGLE_EXT_TLV("Int Spk Amp Playback Volume",
- SPK_CON9, 8, 15, 0,
- snd_soc_get_volsw,
- int_spk_amp_gain_put_volsw,
- int_spk_amp_gain_tlv),
+ SOC_SINGLE_BOOL_EXT("Int Spk Amp Enable", 0, int_spk_amp_enable_get,
+ int_spk_amp_enable_put),
+ SOC_SINGLE_TLV("Int Spk Amp Playback Volume", SPK_CON9, 8, 15, 0,
+ int_spk_amp_gain_tlv),
/* Audio_Speaker_PGA_gain */
- SOC_ENUM_EXT("Audio_Speaker_PGA_gain",
- int_spk_amp_gain_enum,
- int_spk_amp_gain_get,
- int_spk_amp_gain_put),
+ SOC_ENUM_EXT("Audio_Speaker_PGA_gain", int_spk_amp_gain_enum,
+ int_spk_amp_gain_get, int_spk_amp_gain_put),
/* Internal speaker mode (AB/D) */
SOC_ENUM_EXT("Int Spk Amp Mode", mt6392_speaker_mode_enum,
- mt6392_spk_mode_get, mt6392_spk_mode_put),
+ mt6392_spk_mode_get, mt6392_spk_mode_put),
/* Check OC Flag */
SOC_ENUM_EXT("Speaker_OC_Flag", mt6392_speaker_oc_flag_enum,
- mt6392_speaker_oc_flag_get, NULL),
+ mt6392_speaker_oc_flag_get, NULL),
};
static void mt6392_codec_get_spk_trim_offset(struct snd_soc_component *codec)
{
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
/* turn on spk (class D) and hw trim */
snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E, 0x000E);
@@ -213,7 +235,7 @@ static void mt6392_codec_get_spk_trim_offset(struct snd_soc_component *codec)
/* save trim offset */
codec_data->spk_trim_offset =
- snd_soc_component_read32(codec, SPK_CON1) & GENMASK(4, 0);
+ snd_soc_component_read32(codec, SPK_CON1) & GENMASK(4, 0);
/* turn off trim */
snd_soc_component_update_bits(codec, SPK_CON0, 0xFFFF, 0x3401);
@@ -242,8 +264,7 @@ static void mt6392_int_spk_on_with_trim(struct snd_soc_component *codec)
snd_soc_component_update_bits(codec, SPK_CON0, 0xFFFF, 0x3401);
snd_soc_component_update_bits(codec, SPK_CON9, 0xF0FF, 0x2000);
#else
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
/* turn on spk (class D) */
snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E, 0x000E);
@@ -260,8 +281,8 @@ static void mt6392_int_spk_on_with_trim(struct snd_soc_component *codec)
snd_soc_component_update_bits(codec, SPK_CON12, 0xFFFF, 0x2A81);
snd_soc_component_update_bits(codec, SPK_CON1, 0xFFFF, 0x6000);
/* class D and class AB use the same trim offset value */
- snd_soc_component_update_bits(codec, SPK_CON1,
- GENMASK(12, 8), (codec_data->spk_trim_offset << 8));
+ snd_soc_component_update_bits(codec, SPK_CON1, GENMASK(12, 8),
+ (codec_data->spk_trim_offset << 8));
/* trim stop */
snd_soc_component_update_bits(codec, SPK_CON12, 0xFFFF, 0xAA81);
@@ -271,8 +292,7 @@ static void mt6392_int_spk_on_with_trim(struct snd_soc_component *codec)
int mt6392_int_spk_turn_on(struct snd_soc_component *codec)
{
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
int ret = 0;
dev_dbg(codec->dev, "%s\n", __func__);
@@ -282,16 +302,15 @@ int mt6392_int_spk_turn_on(struct snd_soc_component *codec)
mt6392_int_spk_on_with_trim(codec);
break;
case MT6392_CLASS_AB:
- snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E,
- 0x000E);
+ snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E, 0x000E);
snd_soc_component_update_bits(codec, SPK_CON7, 0xFFFF, 0x48F4);
snd_soc_component_update_bits(codec, SPK_CON2, 0xFFFF, 0x0414);
snd_soc_component_update_bits(codec, SPK_CON0, 0xFFFF, 0x3005);
snd_soc_component_update_bits(codec, SPK_CON9, 0xF0FF, 0x2000);
snd_soc_component_update_bits(codec, SPK_CON1, 0xFFFF, 0x6000);
/* class D and class AB use the same trim offset value */
- snd_soc_component_update_bits(codec, SPK_CON1,
- GENMASK(12, 8), (codec_data->spk_trim_offset << 8));
+ snd_soc_component_update_bits(codec, SPK_CON1, GENMASK(12, 8),
+ (codec_data->spk_trim_offset << 8));
usleep_range(2000, 3000);
break;
default:
@@ -301,12 +320,12 @@ int mt6392_int_spk_turn_on(struct snd_soc_component *codec)
return ret;
}
+
EXPORT_SYMBOL_GPL(mt6392_int_spk_turn_on);
int mt6392_int_spk_turn_off(struct snd_soc_component *codec)
{
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
int ret = 0;
dev_dbg(codec->dev, "%s\n", __func__);
@@ -315,13 +334,11 @@ int mt6392_int_spk_turn_off(struct snd_soc_component *codec)
case MT6392_CLASS_D:
snd_soc_component_update_bits(codec, SPK_CON12, 0xFFFF, 0x0000);
snd_soc_component_update_bits(codec, SPK_CON0, 0xFFFF, 0x3400);
- snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E,
- 0x0000);
+ snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E, 0x0000);
break;
case MT6392_CLASS_AB:
snd_soc_component_update_bits(codec, SPK_CON0, 0xFFFF, 0x3404);
- snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E,
- 0x0000);
+ snd_soc_component_update_bits(codec, TOP_CKPDN1_CLR, 0x000E, 0x0000);
break;
default:
ret = -EINVAL;
@@ -330,10 +347,11 @@ int mt6392_int_spk_turn_off(struct snd_soc_component *codec)
return ret;
}
+
EXPORT_SYMBOL_GPL(mt6392_int_spk_turn_off);
static int mt6392_int_spk_amp_wevent(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+ struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
@@ -363,7 +381,10 @@ struct mt6392_codec_reg_attr {
char *name;
};
-#define DUMP_REG_ENTRY(reg) {reg, #reg}
+#define DUMP_REG_ENTRY(reg) \
+ { \
+ reg, #reg \
+ }
static const struct mt6392_codec_reg_attr mt6392_codec_dump_reg_list[] = {
DUMP_REG_ENTRY(SPK_CON0),
@@ -382,8 +403,8 @@ static const struct mt6392_codec_reg_attr mt6392_codec_dump_reg_list[] = {
};
static ssize_t mt6392_codec_debug_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *pos)
+ char __user * user_buf, size_t count,
+ loff_t * pos)
{
struct mt6392_codec_priv *codec_data = file->private_data;
ssize_t ret, i;
@@ -399,9 +420,10 @@ static ssize_t mt6392_codec_debug_read(struct file *file,
for (i = 0; i < ARRAY_SIZE(mt6392_codec_dump_reg_list); i++) {
n += scnprintf(buf + n, count - n, "%s = 0x%x\n",
- mt6392_codec_dump_reg_list[i].name,
- snd_soc_component_read32(codec_data->codec,
- mt6392_codec_dump_reg_list[i].offset));
+ mt6392_codec_dump_reg_list[i].name,
+ snd_soc_component_read32(codec_data->codec,
+ mt6392_codec_dump_reg_list[i].
+ offset));
}
ret = simple_read_from_buffer(user_buf, count, pos, buf, n);
@@ -426,25 +448,24 @@ static void mt6392_codec_init_regs(struct mt6392_codec_priv *codec_data)
/* default PGA gain: 12dB */
codec_data->spk_amp_gain = 0xA;
- snd_soc_component_update_bits(codec, SPK_CON9,
- GENMASK(11, 8), (codec_data->spk_amp_gain) << 8);
+ snd_soc_component_update_bits(codec, SPK_CON9, GENMASK(11, 8),
+ (codec_data->spk_amp_gain) << 8);
}
static int mt6392_codec_parse_dt(struct snd_soc_component *codec)
{
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
struct device *dev = codec->dev;
int ret = 0;
ret = of_property_read_u32(dev->of_node, "mediatek,speaker-mode",
- &codec_data->speaker_mode);
+ &codec_data->speaker_mode);
if (ret) {
dev_warn(dev, "%s fail to read speaker-mode in node %s\n",
- __func__, dev->of_node->full_name);
+ __func__, dev->of_node->full_name);
codec_data->speaker_mode = MT6392_CLASS_D;
} else if (codec_data->speaker_mode != MT6392_CLASS_D &&
- codec_data->speaker_mode != MT6392_CLASS_AB) {
+ codec_data->speaker_mode != MT6392_CLASS_AB) {
codec_data->speaker_mode = MT6392_CLASS_D;
}
@@ -459,18 +480,17 @@ static int mt6392_codec_parse_dt(struct snd_soc_component *codec)
*/
int mt6392_codec_probe(struct snd_soc_component *codec)
{
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
int ret = 0;
ret = snd_soc_add_component_controls(codec, mt6392_codec_controls,
- ARRAY_SIZE(mt6392_codec_controls));
+ ARRAY_SIZE(mt6392_codec_controls));
if (ret < 0)
goto error_probe;
ret = snd_soc_dapm_new_controls(dapm, mt6392_codec_dapm_widgets,
- ARRAY_SIZE(mt6392_codec_dapm_widgets));
+ ARRAY_SIZE(mt6392_codec_dapm_widgets));
if (ret < 0)
goto error_probe;
@@ -484,22 +504,27 @@ int mt6392_codec_probe(struct snd_soc_component *codec)
#ifdef CONFIG_DEBUG_FS
codec_data->debugfs = debugfs_create_file("mt6392_codec_regs",
- S_IFREG | S_IRUGO,
- NULL, codec_data, &mt6392_codec_debug_ops);
+ S_IFREG | S_IRUGO, NULL,
+ codec_data,
+ &mt6392_codec_debug_ops);
#endif
error_probe:
return ret;
}
+
EXPORT_SYMBOL_GPL(mt6392_codec_probe);
int mt6392_codec_remove(struct snd_soc_component *codec)
{
#ifdef CONFIG_DEBUG_FS
- struct mt6392_codec_priv *codec_data =
- snd_soc_component_get_drvdata(codec);
+ struct mt6392_codec_priv *codec_data = snd_soc_component_get_drvdata(codec);
debugfs_remove(codec_data->debugfs);
#endif
dev_dbg(codec->dev, "%s\n", __func__);
return 0;
}
+
EXPORT_SYMBOL_GPL(mt6392_codec_remove);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE MT6392 Codec Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/mt6392-codec.h b/sound/soc/codecs/mt6392-codec.h
index 9ebb375..ba3c775 100644
--- a/sound/soc/codecs/mt6392-codec.h
+++ b/sound/soc/codecs/mt6392-codec.h
@@ -16,6 +16,8 @@
#ifndef __MT6392_CODEC_H__
#define __MT6392_CODEC_H__
+#include <linux/types.h>
+
enum mt6392_speaker_mode {
MT6392_CLASS_D = 0,
MT6392_CLASS_AB,
@@ -51,6 +53,12 @@ struct mt6392_codec_priv {
#define TOP_CKPDN1_CLR PMIC_REG(0x010C)
+#define MT6392_NOT_DEFINED 0
+#define SPK_CON0_STRUP_AUXADC_START_SW 4
+#define SPK_CON0_AUXADC_RSTB_SW 5
+#define SPK_CON0_STRUP_AUXADC_START_SEL 6
+#define SPK_CON0_STRUP_AUXADC_RSTB_SEL 7
+
int mt6392_codec_probe(struct snd_soc_component *codec);
int mt6392_codec_remove(struct snd_soc_component *codec);
int mt6392_int_spk_turn_on(struct snd_soc_component *codec);
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 8f239a4..3aedb95 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -193,3 +193,24 @@
This adds support for ASoC machine driver for Mediatek MT8516 Vesper
Select Y if you have such device.
If unsure select "N".
+
+config MTK_SPEAKER
+ bool "MTK SPEAKER AMP"
+ default n
+ help
+ If you say Y, enable MTK_SPEAKER_AMP
+ If the codec has internal speaker, enable this.
+ This is a config for mediatek internal speaker amp.
+ Generally you select "N", if unsupport it.
+
+config SND_SOC_MT8167_EXCELSIOR_MACH
+ tristate "ASoC Audio driver for MT8167 Excelsior"
+ select SND_SOC_MT8167
+ select SND_SOC_MT8167_CODEC
+ select SND_SOC_MT6392_CODEC
+ select MTK_SPEAKER
+ help
+ This adds support for ASoC machine driver for Mediatek MT8167 Excelsior
+ platforms with internal audio codec and internal speaker driver.
+ Select Y if you have such device.
+ If unsure select "N".
diff --git a/sound/soc/mediatek/mt8167/Makefile b/sound/soc/mediatek/mt8167/Makefile
index 2f37af5..902dc92 100644
--- a/sound/soc/mediatek/mt8167/Makefile
+++ b/sound/soc/mediatek/mt8167/Makefile
@@ -4,6 +4,10 @@
snd-soc-mt8167-pcm-objs := \
mt8167-afe-pcm.o mt8167-afe-util.o mt8167-afe-controls.o mt8167-afe-debug.o
+snd-soc-mt8167-excelsior-mach-objs := \
+ mt8167-excelsior.o
+
obj-$(CONFIG_SND_SOC_MT8167) += snd-soc-mt8167-pcm.o
obj-$(CONFIG_SND_SOC_MT8516_PUMPKIN_MACH) += mt8516-pumpkin.o
obj-$(CONFIG_SND_SOC_MT8516_VESPER) += mt8516-vesper.o
+obj-$(CONFIG_SND_SOC_MT8167_EXCELSIOR_MACH) += snd-soc-mt8167-excelsior-mach.o
diff --git a/sound/soc/mediatek/mt8167/mt8167-excelsior.c b/sound/soc/mediatek/mt8167/mt8167-excelsior.c
new file mode 100644
index 0000000..a2469df
--- /dev/null
+++ b/sound/soc/mediatek/mt8167/mt8167-excelsior.c
@@ -0,0 +1,388 @@
+/*
+ * ASoC Driver for the Excelsior dev board
+ *
+ * Copyright (C) 2019 Google, LLC.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+
+static struct snd_soc_jack mt8167_excelsior_jack;
+
+static struct snd_soc_jack_pin mt8167_excelsior_jack_pins[] = {
+ {
+ .pin = "Headphone",
+ .mask = SND_JACK_HEADSET,
+ },
+};
+
+static struct snd_soc_jack_gpio mt8167_excelsior_jack_gpios[] = {
+ {
+ .gpio = -1,
+ .name = "headset-gpio",
+ .report = SND_JACK_HEADSET,
+ .invert = 0,
+ .debounce_time = 200,
+ },
+};
+
+enum PINCTRL_PIN_STATE { PIN_STATE_DEFAULT = 0, PIN_STATE_MAX };
+
+struct mt8167_excelsior_priv {
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pin_states[PIN_STATE_MAX];
+ int jack_gpio;
+};
+
+static const char *const mt8167_excelsior_pinctrl_pin_str[PIN_STATE_MAX] = {
+ "default",
+};
+
+static int mt8167_excelsior_mic1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+
+ dev_dbg(card->dev, "%s, event %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mt8167_excelsior_mic2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+
+ dev_dbg(card->dev, "%s, event %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mt8167_excelsior_headset_mic_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+
+ dev_dbg(card->dev, "%s, event %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mt8167_excelsior_int_adda_init(struct snd_soc_pcm_runtime *runtime)
+{
+ int ret = 0;
+ struct mt8167_excelsior_priv *card_data;
+ struct snd_soc_card *card = runtime->card;
+ card_data = snd_soc_card_get_drvdata(card);
+
+ dev_dbg(card->dev, "%s\n", __func__);
+
+ if (gpio_is_valid(card_data->jack_gpio)) {
+ ret = snd_soc_card_jack_new(card, "Headset Jack",
+ SND_JACK_HEADSET,
+ &mt8167_excelsior_jack,
+ mt8167_excelsior_jack_pins,
+ ARRAY_SIZE
+ (mt8167_excelsior_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "Can't snd_soc_jack_new %d\n", ret);
+ return ret;
+ }
+
+ mt8167_excelsior_jack_gpios[0].gpio = card_data->jack_gpio;
+ ret = snd_soc_jack_add_gpios(&mt8167_excelsior_jack,
+ ARRAY_SIZE
+ (mt8167_excelsior_jack_gpios),
+ mt8167_excelsior_jack_gpios);
+ if (ret) {
+ dev_err(card->dev, "Can't snd_soc_jack_add_pins %d\n",
+ ret);
+ return ret;
+ }
+
+ } else {
+ dev_err(card->dev, "Invalid gpio for headphone jack.\n");
+ }
+ return ret;
+}
+
+static int mt8167_excelsior_card_remove(struct snd_soc_card *card)
+{
+ snd_soc_jack_free_gpios(&mt8167_excelsior_jack,
+ ARRAY_SIZE(mt8167_excelsior_jack_gpios),
+ mt8167_excelsior_jack_gpios);
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget mt8167_excelsior_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Mic 1", mt8167_excelsior_mic1_event),
+ SND_SOC_DAPM_MIC("Mic 2", mt8167_excelsior_mic2_event),
+ SND_SOC_DAPM_MIC("Headset Mic", mt8167_excelsior_headset_mic_event),
+};
+
+static const struct snd_soc_dapm_route mt8167_excelsior_audio_map[] = {
+ /* Uplink */
+ {"AU_VIN0", NULL, "Mic 1"},
+ {"AU_VIN1", NULL, "Headset Mic"},
+
+ /* Downlink */
+ /* use internal spk amp of MT6392 */
+ {"Int Spk Amp", NULL, "AU_LOL"},
+ {"Headphone", NULL, "AU_HPL"},
+ {"Headphone", NULL, "AU_HPR"},
+};
+
+static struct snd_soc_dai_link mt8167_excelsior_dais[] = {
+ /* Front End DAI links */
+ {
+ .name = "DL1 Playback",
+ .stream_name = "MultiMedia1_PLayback",
+ .cpu_dai_name = "DL1",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .init = mt8167_excelsior_int_adda_init,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ },
+ {
+ .name = "VUL Capture",
+ .stream_name = "MultiMedia1_Capture",
+ .cpu_dai_name = "VUL",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ },
+ {
+ .name = "AWB Capture",
+ .stream_name = "DL1_AWB_Record",
+ .cpu_dai_name = "AWB",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ },
+ {
+ .name = "DL2 Playback",
+ .stream_name = "MultiMedia2_PLayback",
+ .cpu_dai_name = "DL2",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ },
+ /* Back End DAI links */
+ {
+ .name = "MTK Codec",
+ .cpu_dai_name = "INT ADDA",
+ .no_pcm = 1,
+ .codec_name = "mt8167-codec",
+ .codec_dai_name = "mt8167-codec-dai",
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ },
+};
+
+static const struct snd_kcontrol_new mt8167_excelsior_card_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone"),
+};
+
+static struct snd_soc_card mt8167_excelsior_card = {
+ .name = "excelsior-card",
+ .owner = THIS_MODULE,
+ .remove = mt8167_excelsior_card_remove,
+ .dai_link = mt8167_excelsior_dais,
+ .num_links = ARRAY_SIZE(mt8167_excelsior_dais),
+ .dapm_widgets = mt8167_excelsior_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt8167_excelsior_dapm_widgets),
+ .controls = mt8167_excelsior_card_controls,
+ .num_controls = ARRAY_SIZE(mt8167_excelsior_card_controls),
+ .dapm_routes = mt8167_excelsior_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(mt8167_excelsior_audio_map),
+};
+
+static int mt8167_excelsior_gpio_probe(struct snd_soc_card *card)
+{
+ struct mt8167_excelsior_priv *card_data;
+ int ret = 0;
+ int i;
+
+ dev_dbg(card->dev, "%s\n", __func__);
+
+ card_data = snd_soc_card_get_drvdata(card);
+
+ card_data->pinctrl = devm_pinctrl_get(card->dev);
+ if (IS_ERR(card_data->pinctrl)) {
+ ret = PTR_ERR(card_data->pinctrl);
+ dev_err(card->dev, "%s pinctrl_get failed %d\n", __func__, ret);
+ goto exit;
+ }
+
+ for (i = 0; i < PIN_STATE_MAX; i++) {
+ card_data->pin_states[i] =
+ pinctrl_lookup_state(card_data->pinctrl,
+ mt8167_excelsior_pinctrl_pin_str[i]);
+ if (IS_ERR(card_data->pin_states[i])) {
+ ret = PTR_ERR(card_data->pin_states[i]);
+ dev_warn(card->dev,
+ "%s Can't find pinctrl state %s %d\n",
+ __func__, mt8167_excelsior_pinctrl_pin_str[i],
+ ret);
+ } else {
+ dev_warn(card->dev, "%s Set pinctrl state %s %d\n",
+ __func__, mt8167_excelsior_pinctrl_pin_str[i],
+ ret);
+ }
+ }
+
+ /* default state */
+ if (!IS_ERR(card_data->pin_states[PIN_STATE_DEFAULT])) {
+ ret = pinctrl_select_state(card_data->pinctrl,
+ card_data->
+ pin_states[PIN_STATE_DEFAULT]);
+ if (ret) {
+ dev_err(card->dev, "%s failed to select state %d\n",
+ __func__, ret);
+ goto exit;
+ }
+ }
+
+ card_data->jack_gpio =
+ of_get_named_gpio(card->dev->of_node, "mediatek,jack-detect-gpio",
+ 0);
+ dev_dbg(card->dev, "jack gpio: %d\n", card_data->jack_gpio);
+
+exit:
+ return ret;
+}
+
+static int mt8167_excelsior_dev_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &mt8167_excelsior_card;
+ struct device_node *platform_node;
+ int ret, i;
+ struct mt8167_excelsior_priv *card_data;
+
+ dev_dbg(card->dev, "%s\n", __func__);
+
+ platform_node =
+ of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
+ if (!platform_node) {
+ dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < card->num_links; i++) {
+ if (mt8167_excelsior_dais[i].platform_name)
+ continue;
+ mt8167_excelsior_dais[i].platform_of_node = platform_node;
+ }
+
+ card->dev = &pdev->dev;
+
+ card_data =
+ devm_kzalloc(&pdev->dev, sizeof(struct mt8167_excelsior_priv),
+ GFP_KERNEL);
+
+ if (!card_data) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "%s allocate card private data fail %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ snd_soc_card_set_drvdata(card, card_data);
+
+ mt8167_excelsior_gpio_probe(card);
+
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret)
+ dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+ __func__, ret);
+
+ return ret;
+}
+
+static int mt8167_excelsior_dev_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id mt8167_excelsior_dt_match[] = {
+ {
+ .compatible = "mediatek,snd-soc-mt8167-excelsior",
+ },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, mt8167_excelsior_dt_match);
+
+static struct platform_driver mt8167_excelsior_mach_driver = {
+ .driver = {
+ .name = "mt8167-excelsior",
+ .of_match_table = mt8167_excelsior_dt_match,
+#ifdef CONFIG_PM
+ .pm = &snd_soc_pm_ops,
+#endif
+ },
+ .probe = mt8167_excelsior_dev_probe,
+ .remove = mt8167_excelsior_dev_remove,
+};
+
+module_platform_driver(mt8167_excelsior_mach_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8167 Excelsior ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mt8167-excelsior");