Loading asoc/codecs/core.h +2 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,7 @@ enum codec_variant { WCD9335, WCD9326, WCD934X, WCD9360, }; enum wcd9xxx_slim_slave_addr_type { Loading Loading @@ -297,6 +298,7 @@ enum wcd9xxx_chipid_major { TASHA_MAJOR = cpu_to_le16(0x0), TASHA2P0_MAJOR = cpu_to_le16(0x107), TAVIL_MAJOR = cpu_to_le16(0x108), PAHU_MAJOR = cpu_to_le16(0x109), }; enum codec_power_states { Loading asoc/codecs/wcd9xxx-core.c +4 −2 Original line number Diff line number Diff line /* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -88,6 +88,7 @@ static const int wcd9xxx_cdc_types[] = { [WCD9330] = WCD9330, [WCD9335] = WCD9335, [WCD934X] = WCD934X, [WCD9360] = WCD9360, }; static const struct of_device_id wcd9xxx_of_match[] = { Loading Loading @@ -327,7 +328,8 @@ int wcd9xxx_slim_write_repeat(struct wcd9xxx *wcd9xxx, unsigned short reg, struct slim_ele_access slim_msg; mutex_lock(&wcd9xxx->io_lock); if (wcd9xxx->type == WCD9335 || wcd9xxx->type == WCD934X) { if (wcd9xxx->type == WCD9335 || wcd9xxx->type == WCD934X || wcd9xxx->type == WCD9360) { ret = wcd9xxx_page_write(wcd9xxx, ®); if (ret) goto done; Loading asoc/codecs/wcd9xxx-regmap.h +6 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -19,6 +19,8 @@ typedef int (*regmap_patch_fptr)(struct regmap *, int); extern struct regmap_config wcd9360_regmap_config; extern struct regmap_config wcd934x_regmap_config; extern int wcd934x_regmap_register_patch(struct regmap *regmap, int version); Loading @@ -32,6 +34,9 @@ static inline struct regmap_config *wcd9xxx_get_regmap_config(int type) struct regmap_config *regmap_config; switch (type) { case WCD9360: regmap_config = &wcd9360_regmap_config; break; case WCD934X: regmap_config = &wcd934x_regmap_config; break; Loading asoc/codecs/wcd9xxx-resmgr-v2.c +64 −63 Original line number Diff line number Diff line /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,14 +17,18 @@ #include <sound/soc.h> #include "wcd9xxx-resmgr-v2.h" #include "core.h" #include "wcd9335_registers.h" #include <asoc/wcd934x_registers.h> #define WCD9XXX_RCO_CALIBRATION_DELAY_INC_US 5000 /* This register is valid only for WCD9335 */ #define WCD93XX_ANA_CLK_TOP 0x0602 #define WCD93XX_ANA_BIAS 0x0601 #define WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL 0x0d41 #define WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL 0x0d42 #define WCD93XX_CLK_SYS_MCLK_PRG 0x711 #define WCD93XX_CODEC_RPM_CLK_GATE 0x002 #define WCD93XX_ANA_RCO 0x603 #define WCD93XX_ANA_BUCK_CTL 0x606 static const char *wcd_resmgr_clk_type_to_str(enum wcd_clock_type clk_type) { Loading @@ -44,13 +48,13 @@ static int wcd_resmgr_codec_reg_update_bits(struct wcd9xxx_resmgr_v2 *resmgr, bool change; int ret; if (resmgr->codec_type == WCD934X) { /* Tavil does not support ANA_CLK_TOP register */ if (reg == WCD9335_ANA_CLK_TOP) if (resmgr->codec_type != WCD9335) { /* Tavil and Pahu does not support ANA_CLK_TOP register */ if (reg == WCD93XX_ANA_CLK_TOP) return 0; } else { /* Tasha does not support CLK_SYS_MCLK_PRG register */ if (reg == WCD934X_CLK_SYS_MCLK_PRG) if (reg == WCD93XX_CLK_SYS_MCLK_PRG) return 0; } if (resmgr->codec) { Loading @@ -74,11 +78,11 @@ static int wcd_resmgr_codec_reg_read(struct wcd9xxx_resmgr_v2 *resmgr, { int val, ret; if (resmgr->codec_type == WCD934X) { if (reg == WCD9335_ANA_CLK_TOP) if (resmgr->codec_type != WCD9335) { if (reg == WCD93XX_ANA_CLK_TOP) return 0; } else { if (reg == WCD934X_CLK_SYS_MCLK_PRG) if (reg == WCD93XX_CLK_SYS_MCLK_PRG) return 0; } if (resmgr->codec) { Loading Loading @@ -242,26 +246,26 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) if (++resmgr->clk_mclk_users == 1) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x80, 0x80); WCD93XX_ANA_CLK_TOP, 0x80, 0x80); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x08, 0x00); WCD93XX_ANA_CLK_TOP, 0x08, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x04, 0x04); if (resmgr->codec_type == WCD934X) { WCD93XX_ANA_CLK_TOP, 0x04, 0x04); if (resmgr->codec_type != WCD9335) { /* * In tavil clock contrl register is changed * to CLK_SYS_MCLK_PRG */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x80, 0x80); WCD93XX_CLK_SYS_MCLK_PRG, 0x80, 0x80); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x30, 0x10); WCD93XX_CLK_SYS_MCLK_PRG, 0x30, 0x10); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x01, 0x01); WCD93XX_CLK_SYS_MCLK_PRG, 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01); Loading @@ -269,10 +273,7 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CODEC_RPM_CLK_GATE, 0x03, 0x00); WCD93XX_CODEC_RPM_CLK_GATE, 0x03, 0x00); } else { wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, Loading Loading @@ -308,28 +309,28 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) if (resmgr->clk_rco_users > 0) { /* MCLK to RCO switch */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, WCD93XX_ANA_CLK_TOP, 0x08, 0x08); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x02); WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x02); /* Disable clock buffer */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x80, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x80, 0x00); resmgr->clk_type = WCD_CLK_RCO; } else { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, WCD93XX_ANA_CLK_TOP, 0x04, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x81, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x81, 0x00); resmgr->clk_type = WCD_CLK_OFF; } wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_CLK_TOP, 0x80, 0x00); } if ((resmgr->codec_type == WCD934X) && if ((resmgr->codec_type != WCD9335) && (resmgr->clk_type == WCD_CLK_OFF)) wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL); Loading @@ -342,15 +343,15 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) static void wcd_resmgr_set_buck_accuracy(struct wcd9xxx_resmgr_v2 *resmgr) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x02, 0x02); /* 100us sleep needed after HIGH_ACCURACY_PRE_EN1 */ usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x01, 0x01); /* 100us sleep needed after HIGH_ACCURACY_PRE_EN2 */ usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x04, 0x04); /* 100us sleep needed after HIGH_ACCURACY_EN */ usleep_range(100, 110); Loading @@ -373,9 +374,9 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) /* RCO Enable */ if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, WCD93XX_ANA_RCO, 0x80, 0x80); if (resmgr->codec_type == WCD934X) if (resmgr->codec_type != WCD9335) wcd_resmgr_set_buck_accuracy(resmgr); } Loading @@ -384,7 +385,7 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) * requirements */ usleep_range(20, 25); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x40, 0x40); /* * 20us required after RCO is enabled as per HW Loading @@ -392,20 +393,20 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) */ usleep_range(20, 25); /* RCO Calibration */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x04, 0x04); if (resmgr->codec_type == WCD934X) if (resmgr->codec_type != WCD9335) /* * For wcd934x codec, 20us sleep is needed * For wcd934x and wcd936x codecs, 20us sleep is needed * after enabling RCO calibration */ usleep_range(20, 25); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x04, 0x00); if (resmgr->codec_type == WCD934X) if (resmgr->codec_type != WCD9335) /* * For wcd934x codec, 20us sleep is needed * For wcd934x and wcd936x codecs, 20us sleep is needed * after disabling RCO calibration */ usleep_range(20, 25); Loading @@ -413,7 +414,7 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) /* RCO calibration takes app. 5ms to complete */ usleep_range(WCD9XXX_RCO_CALIBRATION_DELAY_INC_US, WCD9XXX_RCO_CALIBRATION_DELAY_INC_US + 100); if (wcd_resmgr_codec_reg_read(resmgr, WCD9335_ANA_RCO) & 0x02) if (wcd_resmgr_codec_reg_read(resmgr, WCD93XX_ANA_RCO) & 0x02) rco_cal_done = false; WARN((!rco_cal_done), "RCO Calibration failed\n"); Loading @@ -421,10 +422,10 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) /* Switch MUX to RCO */ if (resmgr->clk_mclk_users == 1) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, WCD93XX_ANA_CLK_TOP, 0x08, 0x08); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x02); resmgr->clk_type = WCD_CLK_RCO; } Loading @@ -449,35 +450,35 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) if ((resmgr->clk_rco_users == 0) && (resmgr->clk_type == WCD_CLK_RCO)) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_CLK_TOP, 0x08, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_CLK_TOP, 0x04, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x40, 0x00); if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, WCD93XX_ANA_RCO, 0x80, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, WCD93XX_CLK_SYS_MCLK_PRG, 0x01, 0x00); resmgr->clk_type = WCD_CLK_OFF; } else if ((resmgr->clk_rco_users == 0) && (resmgr->clk_mclk_users)) { /* Disable RCO while MCLK is ON */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x40, 0x00); if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, WCD93XX_ANA_RCO, 0x80, 0x00); } if ((resmgr->codec_type == WCD934X) && if ((resmgr->codec_type != WCD9335) && (resmgr->clk_type == WCD_CLK_OFF)) wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL); Loading Loading @@ -530,28 +531,28 @@ void wcd_resmgr_set_sido_input_src(struct wcd9xxx_resmgr_v2 *resmgr, return; if (sido_src == SIDO_SOURCE_INTERNAL) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x04, 0x00); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x03, 0x00); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x80, 0x00); usleep_range(100, 110); resmgr->sido_input_src = SIDO_SOURCE_INTERNAL; pr_debug("%s: sido input src to internal\n", __func__); } else if (sido_src == SIDO_SOURCE_RCO_BG) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x80, 0x80); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x02, 0x02); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x01, 0x01); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x04, 0x04); usleep_range(100, 110); resmgr->sido_input_src = SIDO_SOURCE_RCO_BG; Loading asoc/codecs/wcd9xxx-rst.c +160 −1 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -22,6 +22,8 @@ #include "wcd9335_irq.h" #include <asoc/wcd934x_registers.h> #include "wcd934x/wcd934x_irq.h" #include <asoc/wcd9360-registers.h> #include "wcd9360/wcd9360-irq.h" /* wcd9335 interrupt table */ static const struct intr_data wcd9335_intr_table[] = { Loading Loading @@ -86,6 +88,25 @@ static const struct intr_data wcd934x_intr_table[] = { {WCD934X_IRQ_VBAT_RESTORE, false}, }; static const struct intr_data wcd9360_intr_table[] = { {WCD9XXX_IRQ_SLIMBUS, false}, {WCD9360_IRQ_MISC, false}, {WCD9360_IRQ_LDO_RXTX_SCD, false}, {WCD9360_IRQ_EAR_PA_SCD, false}, {WCD9360_IRQ_AUX_PA_SCD, false}, {WCD9360_IRQ_EAR_PA_CNP_COMPLETE, false}, {WCD9360_IRQ_AUX_PA_CNP_COMPLETE, false}, {WCD9360_IRQ_RESERVED_3, false}, {WCD9360_IRQ_SOUNDWIRE, false}, {WCD9360_IRQ_RCO_ERROR, false}, {WCD9360_IRQ_CPE_ERROR, false}, {WCD9360_IRQ_MAD_AUDIO, false}, {WCD9360_IRQ_MAD_BEACON, false}, {WCD9360_IRQ_CPE1_INTR, true}, {WCD9360_IRQ_RESERVED_4, false}, {WCD9360_IRQ_MAD_ULTRASOUND, false}, }; /* * wcd9335_bring_down: Bringdown WCD Codec * Loading Loading @@ -384,11 +405,143 @@ static int wcd934x_get_cdc_info(struct wcd9xxx *wcd9xxx, return rc; } /* * wcd9360_bring_down: Bringdown WCD Codec * * @wcd9xxx: Pointer to wcd9xxx structure * * Returns 0 for success or negative error code for failure */ static int wcd9360_bring_down(struct wcd9xxx *wcd9xxx) { if (!wcd9xxx || !wcd9xxx->regmap) return -EINVAL; regmap_write(wcd9xxx->regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x04); return 0; } /* * wcd9360_bring_up: Bringup WCD Codec * * @wcd9xxx: Pointer to the wcd9xxx structure * * Returns 0 for success or negative error code for failure */ static int wcd9360_bring_up(struct wcd9xxx *wcd9xxx) { struct regmap *wcd_regmap; if (!wcd9xxx) return -EINVAL; if (!wcd9xxx->regmap) { dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n", __func__); return -EINVAL; } wcd_regmap = wcd9xxx->regmap; regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x01); regmap_write(wcd_regmap, WCD9360_SIDO_NEW_VOUT_A_STARTUP, 0x19); regmap_write(wcd_regmap, WCD9360_SIDO_NEW_VOUT_D_STARTUP, 0x15); /* Add 1msec delay for VOUT to settle */ usleep_range(1000, 1100); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x3); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x7); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3); return 0; } /* * wcd9360_get_cdc_info: Get codec specific information * * @wcd9xxx: pointer to wcd9xxx structure * @wcd_type: pointer to wcd9xxx_codec_type structure * * Returns 0 for success or negative error code for failure */ static int wcd9360_get_cdc_info(struct wcd9xxx *wcd9xxx, struct wcd9xxx_codec_type *wcd_type) { u16 id_minor, id_major; struct regmap *wcd_regmap; int rc, version = -1; if (!wcd9xxx || !wcd_type) return -EINVAL; if (!wcd9xxx->regmap) { dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__); return -EINVAL; } wcd_regmap = wcd9xxx->regmap; rc = regmap_bulk_read(wcd_regmap, WCD9360_CHIP_TIER_CTRL_CHIP_ID_BYTE0, (u8 *)&id_minor, sizeof(u16)); if (rc) return -EINVAL; rc = regmap_bulk_read(wcd_regmap, WCD9360_CHIP_TIER_CTRL_CHIP_ID_BYTE2, (u8 *)&id_major, sizeof(u16)); if (rc) return -EINVAL; dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n", __func__, id_major, id_minor); if (id_major != PAHU_MAJOR) goto version_unknown; /* * As fine version info cannot be retrieved before pahu probe. * Assign coarse versions for possible future use before Pahu probe. */ if (id_minor == cpu_to_le16(0)) version = PAHU_VERSION_1_0; version_unknown: if (version < 0) dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n", __func__); /* Fill codec type info */ wcd_type->id_major = id_major; wcd_type->id_minor = id_minor; wcd_type->num_irqs = WCD9360_NUM_IRQS; wcd_type->version = version; wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1; wcd_type->i2c_chip_status = 0x01; wcd_type->intr_tbl = wcd9360_intr_table; wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table); wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] = WCD9360_INTR_PIN1_STATUS0; wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] = WCD9360_INTR_PIN1_CLEAR0; wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] = WCD9360_INTR_PIN1_MASK0; wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] = WCD9360_INTR_LEVEL0; wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] = WCD9360_INTR_CLR_COMMIT; return rc; } codec_bringdown_fn wcd9xxx_bringdown_fn(int type) { codec_bringdown_fn cdc_bdown_fn; switch (type) { case WCD9360: cdc_bdown_fn = wcd9360_bring_down; break; case WCD934X: cdc_bdown_fn = wcd934x_bring_down; break; Loading @@ -408,6 +561,9 @@ codec_bringup_fn wcd9xxx_bringup_fn(int type) codec_bringup_fn cdc_bup_fn; switch (type) { case WCD9360: cdc_bup_fn = wcd9360_bring_up; break; case WCD934X: cdc_bup_fn = wcd934x_bring_up; break; Loading @@ -427,6 +583,9 @@ codec_type_fn wcd9xxx_get_codec_info_fn(int type) codec_type_fn cdc_type_fn; switch (type) { case WCD9360: cdc_type_fn = wcd9360_get_cdc_info; break; case WCD934X: cdc_type_fn = wcd934x_get_cdc_info; break; Loading Loading
asoc/codecs/core.h +2 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,7 @@ enum codec_variant { WCD9335, WCD9326, WCD934X, WCD9360, }; enum wcd9xxx_slim_slave_addr_type { Loading Loading @@ -297,6 +298,7 @@ enum wcd9xxx_chipid_major { TASHA_MAJOR = cpu_to_le16(0x0), TASHA2P0_MAJOR = cpu_to_le16(0x107), TAVIL_MAJOR = cpu_to_le16(0x108), PAHU_MAJOR = cpu_to_le16(0x109), }; enum codec_power_states { Loading
asoc/codecs/wcd9xxx-core.c +4 −2 Original line number Diff line number Diff line /* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -88,6 +88,7 @@ static const int wcd9xxx_cdc_types[] = { [WCD9330] = WCD9330, [WCD9335] = WCD9335, [WCD934X] = WCD934X, [WCD9360] = WCD9360, }; static const struct of_device_id wcd9xxx_of_match[] = { Loading Loading @@ -327,7 +328,8 @@ int wcd9xxx_slim_write_repeat(struct wcd9xxx *wcd9xxx, unsigned short reg, struct slim_ele_access slim_msg; mutex_lock(&wcd9xxx->io_lock); if (wcd9xxx->type == WCD9335 || wcd9xxx->type == WCD934X) { if (wcd9xxx->type == WCD9335 || wcd9xxx->type == WCD934X || wcd9xxx->type == WCD9360) { ret = wcd9xxx_page_write(wcd9xxx, ®); if (ret) goto done; Loading
asoc/codecs/wcd9xxx-regmap.h +6 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -19,6 +19,8 @@ typedef int (*regmap_patch_fptr)(struct regmap *, int); extern struct regmap_config wcd9360_regmap_config; extern struct regmap_config wcd934x_regmap_config; extern int wcd934x_regmap_register_patch(struct regmap *regmap, int version); Loading @@ -32,6 +34,9 @@ static inline struct regmap_config *wcd9xxx_get_regmap_config(int type) struct regmap_config *regmap_config; switch (type) { case WCD9360: regmap_config = &wcd9360_regmap_config; break; case WCD934X: regmap_config = &wcd934x_regmap_config; break; Loading
asoc/codecs/wcd9xxx-resmgr-v2.c +64 −63 Original line number Diff line number Diff line /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,14 +17,18 @@ #include <sound/soc.h> #include "wcd9xxx-resmgr-v2.h" #include "core.h" #include "wcd9335_registers.h" #include <asoc/wcd934x_registers.h> #define WCD9XXX_RCO_CALIBRATION_DELAY_INC_US 5000 /* This register is valid only for WCD9335 */ #define WCD93XX_ANA_CLK_TOP 0x0602 #define WCD93XX_ANA_BIAS 0x0601 #define WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL 0x0d41 #define WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL 0x0d42 #define WCD93XX_CLK_SYS_MCLK_PRG 0x711 #define WCD93XX_CODEC_RPM_CLK_GATE 0x002 #define WCD93XX_ANA_RCO 0x603 #define WCD93XX_ANA_BUCK_CTL 0x606 static const char *wcd_resmgr_clk_type_to_str(enum wcd_clock_type clk_type) { Loading @@ -44,13 +48,13 @@ static int wcd_resmgr_codec_reg_update_bits(struct wcd9xxx_resmgr_v2 *resmgr, bool change; int ret; if (resmgr->codec_type == WCD934X) { /* Tavil does not support ANA_CLK_TOP register */ if (reg == WCD9335_ANA_CLK_TOP) if (resmgr->codec_type != WCD9335) { /* Tavil and Pahu does not support ANA_CLK_TOP register */ if (reg == WCD93XX_ANA_CLK_TOP) return 0; } else { /* Tasha does not support CLK_SYS_MCLK_PRG register */ if (reg == WCD934X_CLK_SYS_MCLK_PRG) if (reg == WCD93XX_CLK_SYS_MCLK_PRG) return 0; } if (resmgr->codec) { Loading @@ -74,11 +78,11 @@ static int wcd_resmgr_codec_reg_read(struct wcd9xxx_resmgr_v2 *resmgr, { int val, ret; if (resmgr->codec_type == WCD934X) { if (reg == WCD9335_ANA_CLK_TOP) if (resmgr->codec_type != WCD9335) { if (reg == WCD93XX_ANA_CLK_TOP) return 0; } else { if (reg == WCD934X_CLK_SYS_MCLK_PRG) if (reg == WCD93XX_CLK_SYS_MCLK_PRG) return 0; } if (resmgr->codec) { Loading Loading @@ -242,26 +246,26 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) if (++resmgr->clk_mclk_users == 1) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x80, 0x80); WCD93XX_ANA_CLK_TOP, 0x80, 0x80); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x08, 0x00); WCD93XX_ANA_CLK_TOP, 0x08, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x04, 0x04); if (resmgr->codec_type == WCD934X) { WCD93XX_ANA_CLK_TOP, 0x04, 0x04); if (resmgr->codec_type != WCD9335) { /* * In tavil clock contrl register is changed * to CLK_SYS_MCLK_PRG */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x80, 0x80); WCD93XX_CLK_SYS_MCLK_PRG, 0x80, 0x80); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x30, 0x10); WCD93XX_CLK_SYS_MCLK_PRG, 0x30, 0x10); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x01, 0x01); WCD93XX_CLK_SYS_MCLK_PRG, 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01); Loading @@ -269,10 +273,7 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CODEC_RPM_CLK_GATE, 0x03, 0x00); WCD93XX_CODEC_RPM_CLK_GATE, 0x03, 0x00); } else { wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, Loading Loading @@ -308,28 +309,28 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) if (resmgr->clk_rco_users > 0) { /* MCLK to RCO switch */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, WCD93XX_ANA_CLK_TOP, 0x08, 0x08); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x02, 0x02); WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x02); /* Disable clock buffer */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x80, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x80, 0x00); resmgr->clk_type = WCD_CLK_RCO; } else { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, WCD93XX_ANA_CLK_TOP, 0x04, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, 0x81, 0x00); WCD93XX_CLK_SYS_MCLK_PRG, 0x81, 0x00); resmgr->clk_type = WCD_CLK_OFF; } wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_CLK_TOP, 0x80, 0x00); } if ((resmgr->codec_type == WCD934X) && if ((resmgr->codec_type != WCD9335) && (resmgr->clk_type == WCD_CLK_OFF)) wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL); Loading @@ -342,15 +343,15 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) static void wcd_resmgr_set_buck_accuracy(struct wcd9xxx_resmgr_v2 *resmgr) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x02, 0x02); /* 100us sleep needed after HIGH_ACCURACY_PRE_EN1 */ usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x01, 0x01); /* 100us sleep needed after HIGH_ACCURACY_PRE_EN2 */ usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x04, 0x04); /* 100us sleep needed after HIGH_ACCURACY_EN */ usleep_range(100, 110); Loading @@ -373,9 +374,9 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) /* RCO Enable */ if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, WCD93XX_ANA_RCO, 0x80, 0x80); if (resmgr->codec_type == WCD934X) if (resmgr->codec_type != WCD9335) wcd_resmgr_set_buck_accuracy(resmgr); } Loading @@ -384,7 +385,7 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) * requirements */ usleep_range(20, 25); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x40, 0x40); /* * 20us required after RCO is enabled as per HW Loading @@ -392,20 +393,20 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) */ usleep_range(20, 25); /* RCO Calibration */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x04, 0x04); if (resmgr->codec_type == WCD934X) if (resmgr->codec_type != WCD9335) /* * For wcd934x codec, 20us sleep is needed * For wcd934x and wcd936x codecs, 20us sleep is needed * after enabling RCO calibration */ usleep_range(20, 25); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x04, 0x00); if (resmgr->codec_type == WCD934X) if (resmgr->codec_type != WCD9335) /* * For wcd934x codec, 20us sleep is needed * For wcd934x and wcd936x codecs, 20us sleep is needed * after disabling RCO calibration */ usleep_range(20, 25); Loading @@ -413,7 +414,7 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) /* RCO calibration takes app. 5ms to complete */ usleep_range(WCD9XXX_RCO_CALIBRATION_DELAY_INC_US, WCD9XXX_RCO_CALIBRATION_DELAY_INC_US + 100); if (wcd_resmgr_codec_reg_read(resmgr, WCD9335_ANA_RCO) & 0x02) if (wcd_resmgr_codec_reg_read(resmgr, WCD93XX_ANA_RCO) & 0x02) rco_cal_done = false; WARN((!rco_cal_done), "RCO Calibration failed\n"); Loading @@ -421,10 +422,10 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) /* Switch MUX to RCO */ if (resmgr->clk_mclk_users == 1) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, WCD93XX_ANA_CLK_TOP, 0x08, 0x08); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x02); resmgr->clk_type = WCD_CLK_RCO; } Loading @@ -449,35 +450,35 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) if ((resmgr->clk_rco_users == 0) && (resmgr->clk_type == WCD_CLK_RCO)) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_CLK_TOP, 0x08, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, WCD93XX_CLK_SYS_MCLK_PRG, 0x02, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_CLK_TOP, 0x04, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x40, 0x00); if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, WCD93XX_ANA_RCO, 0x80, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CLK_SYS_MCLK_PRG, WCD93XX_CLK_SYS_MCLK_PRG, 0x01, 0x00); resmgr->clk_type = WCD_CLK_OFF; } else if ((resmgr->clk_rco_users == 0) && (resmgr->clk_mclk_users)) { /* Disable RCO while MCLK is ON */ wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x40, 0x00); if (resmgr->sido_input_src == SIDO_SOURCE_INTERNAL) wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, WCD93XX_ANA_RCO, 0x80, 0x00); } if ((resmgr->codec_type == WCD934X) && if ((resmgr->codec_type != WCD9335) && (resmgr->clk_type == WCD_CLK_OFF)) wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL); Loading Loading @@ -530,28 +531,28 @@ void wcd_resmgr_set_sido_input_src(struct wcd9xxx_resmgr_v2 *resmgr, return; if (sido_src == SIDO_SOURCE_INTERNAL) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x04, 0x00); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x03, 0x00); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x80, 0x00); usleep_range(100, 110); resmgr->sido_input_src = SIDO_SOURCE_INTERNAL; pr_debug("%s: sido input src to internal\n", __func__); } else if (sido_src == SIDO_SOURCE_RCO_BG) { wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_RCO, 0x80, 0x80); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x02, 0x02); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x01, 0x01); usleep_range(100, 110); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BUCK_CTL, 0x04, 0x04); usleep_range(100, 110); resmgr->sido_input_src = SIDO_SOURCE_RCO_BG; Loading
asoc/codecs/wcd9xxx-rst.c +160 −1 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -22,6 +22,8 @@ #include "wcd9335_irq.h" #include <asoc/wcd934x_registers.h> #include "wcd934x/wcd934x_irq.h" #include <asoc/wcd9360-registers.h> #include "wcd9360/wcd9360-irq.h" /* wcd9335 interrupt table */ static const struct intr_data wcd9335_intr_table[] = { Loading Loading @@ -86,6 +88,25 @@ static const struct intr_data wcd934x_intr_table[] = { {WCD934X_IRQ_VBAT_RESTORE, false}, }; static const struct intr_data wcd9360_intr_table[] = { {WCD9XXX_IRQ_SLIMBUS, false}, {WCD9360_IRQ_MISC, false}, {WCD9360_IRQ_LDO_RXTX_SCD, false}, {WCD9360_IRQ_EAR_PA_SCD, false}, {WCD9360_IRQ_AUX_PA_SCD, false}, {WCD9360_IRQ_EAR_PA_CNP_COMPLETE, false}, {WCD9360_IRQ_AUX_PA_CNP_COMPLETE, false}, {WCD9360_IRQ_RESERVED_3, false}, {WCD9360_IRQ_SOUNDWIRE, false}, {WCD9360_IRQ_RCO_ERROR, false}, {WCD9360_IRQ_CPE_ERROR, false}, {WCD9360_IRQ_MAD_AUDIO, false}, {WCD9360_IRQ_MAD_BEACON, false}, {WCD9360_IRQ_CPE1_INTR, true}, {WCD9360_IRQ_RESERVED_4, false}, {WCD9360_IRQ_MAD_ULTRASOUND, false}, }; /* * wcd9335_bring_down: Bringdown WCD Codec * Loading Loading @@ -384,11 +405,143 @@ static int wcd934x_get_cdc_info(struct wcd9xxx *wcd9xxx, return rc; } /* * wcd9360_bring_down: Bringdown WCD Codec * * @wcd9xxx: Pointer to wcd9xxx structure * * Returns 0 for success or negative error code for failure */ static int wcd9360_bring_down(struct wcd9xxx *wcd9xxx) { if (!wcd9xxx || !wcd9xxx->regmap) return -EINVAL; regmap_write(wcd9xxx->regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x04); return 0; } /* * wcd9360_bring_up: Bringup WCD Codec * * @wcd9xxx: Pointer to the wcd9xxx structure * * Returns 0 for success or negative error code for failure */ static int wcd9360_bring_up(struct wcd9xxx *wcd9xxx) { struct regmap *wcd_regmap; if (!wcd9xxx) return -EINVAL; if (!wcd9xxx->regmap) { dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n", __func__); return -EINVAL; } wcd_regmap = wcd9xxx->regmap; regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x01); regmap_write(wcd_regmap, WCD9360_SIDO_NEW_VOUT_A_STARTUP, 0x19); regmap_write(wcd_regmap, WCD9360_SIDO_NEW_VOUT_D_STARTUP, 0x15); /* Add 1msec delay for VOUT to settle */ usleep_range(1000, 1100); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x3); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x7); regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3); return 0; } /* * wcd9360_get_cdc_info: Get codec specific information * * @wcd9xxx: pointer to wcd9xxx structure * @wcd_type: pointer to wcd9xxx_codec_type structure * * Returns 0 for success or negative error code for failure */ static int wcd9360_get_cdc_info(struct wcd9xxx *wcd9xxx, struct wcd9xxx_codec_type *wcd_type) { u16 id_minor, id_major; struct regmap *wcd_regmap; int rc, version = -1; if (!wcd9xxx || !wcd_type) return -EINVAL; if (!wcd9xxx->regmap) { dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__); return -EINVAL; } wcd_regmap = wcd9xxx->regmap; rc = regmap_bulk_read(wcd_regmap, WCD9360_CHIP_TIER_CTRL_CHIP_ID_BYTE0, (u8 *)&id_minor, sizeof(u16)); if (rc) return -EINVAL; rc = regmap_bulk_read(wcd_regmap, WCD9360_CHIP_TIER_CTRL_CHIP_ID_BYTE2, (u8 *)&id_major, sizeof(u16)); if (rc) return -EINVAL; dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n", __func__, id_major, id_minor); if (id_major != PAHU_MAJOR) goto version_unknown; /* * As fine version info cannot be retrieved before pahu probe. * Assign coarse versions for possible future use before Pahu probe. */ if (id_minor == cpu_to_le16(0)) version = PAHU_VERSION_1_0; version_unknown: if (version < 0) dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n", __func__); /* Fill codec type info */ wcd_type->id_major = id_major; wcd_type->id_minor = id_minor; wcd_type->num_irqs = WCD9360_NUM_IRQS; wcd_type->version = version; wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1; wcd_type->i2c_chip_status = 0x01; wcd_type->intr_tbl = wcd9360_intr_table; wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table); wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] = WCD9360_INTR_PIN1_STATUS0; wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] = WCD9360_INTR_PIN1_CLEAR0; wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] = WCD9360_INTR_PIN1_MASK0; wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] = WCD9360_INTR_LEVEL0; wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] = WCD9360_INTR_CLR_COMMIT; return rc; } codec_bringdown_fn wcd9xxx_bringdown_fn(int type) { codec_bringdown_fn cdc_bdown_fn; switch (type) { case WCD9360: cdc_bdown_fn = wcd9360_bring_down; break; case WCD934X: cdc_bdown_fn = wcd934x_bring_down; break; Loading @@ -408,6 +561,9 @@ codec_bringup_fn wcd9xxx_bringup_fn(int type) codec_bringup_fn cdc_bup_fn; switch (type) { case WCD9360: cdc_bup_fn = wcd9360_bring_up; break; case WCD934X: cdc_bup_fn = wcd934x_bring_up; break; Loading @@ -427,6 +583,9 @@ codec_type_fn wcd9xxx_get_codec_info_fn(int type) codec_type_fn cdc_type_fn; switch (type) { case WCD9360: cdc_type_fn = wcd9360_get_cdc_info; break; case WCD934X: cdc_type_fn = wcd934x_get_cdc_info; break; Loading