mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
Merge commit '10f8a9f06a7b94601400512f0f2b1b8d0612042f'
* commit '10f8a9f06a7b94601400512f0f2b1b8d0612042f': mfd: display-serdes: if route enable then no need init serdes pinctrl ARM: dts: rockchip: rk3502-evb1-v10: Add suspend io config soc: rockchip: pm_config: support sip sleep_io_config ARM: dts: rockchip: rk3502 & rk3506-pinctrl: add more descriptions and references of rkdsm pins ASoC: codecs: rk_dsm: add support iomux switching for anti-pop automatically Change-Id: I836248a06ed08fa22b2093e24130beaca86dc7fd
This commit is contained in:
@@ -410,6 +410,17 @@
|
||||
| RKPM_PWREN_SLEEP_GPIO0A0 | RKPM_PWREN_SLEEP_ACT_LOW
|
||||
)
|
||||
>;
|
||||
|
||||
#define GPIO0_IOC_GPIO0A_PULL_REG 0xff950200
|
||||
#define GPIO0_IOC_GPIO0C_PULL_REG 0xff950208
|
||||
#define GPIO0A3_PULL_DOWN 0x00c00080
|
||||
#define GPIO0C5_PULL_DOWN 0x0c000800
|
||||
|
||||
/* Note: support max 16 pairs */
|
||||
rockchip,sleep-io-config = <
|
||||
GPIO0_IOC_GPIO0C_PULL_REG GPIO0C5_PULL_DOWN /* PWM0_CH0_CPU */
|
||||
GPIO0_IOC_GPIO0A_PULL_REG GPIO0A3_PULL_DOWN /* PWM0_CH2_LCD_BL */
|
||||
>;
|
||||
};
|
||||
|
||||
&sai1 {
|
||||
|
||||
@@ -1009,11 +1009,23 @@
|
||||
resets = <&cru SRST_M_DSM>;
|
||||
reset-names = "reset" ;
|
||||
rockchip,grf = <&grf>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dsm_audm0_ln_pins
|
||||
&dsm_audm0_lp_pins
|
||||
&dsm_audm0_rn_pins
|
||||
&dsm_audm0_rp_pins>;
|
||||
/**
|
||||
* this is bitmap
|
||||
* 0x1: (1 << 0) - audm0 enabled
|
||||
* 0x2: (1 << 1) - audm1 enabled
|
||||
* 0x3: - audm0 + audm1 enabled
|
||||
* others - invalid
|
||||
*/
|
||||
rockchip,dsm-audm-en = <0x1>;
|
||||
pinctrl-names = "audm0-iodown", "audm0-pins",
|
||||
"audm1-iodown", "audm1-pins",
|
||||
"audm0m1-iodown", "audm0m1-pins";
|
||||
pinctrl-0 = <&dsm_audm0_iodown_pins>;
|
||||
pinctrl-1 = <&dsm_audm0_pins>;
|
||||
pinctrl-2 = <&dsm_audm1_iodown_pins>;
|
||||
pinctrl-3 = <&dsm_audm1_pins>;
|
||||
pinctrl-4 = <&dsm_audm0_iodown_pins>, <&dsm_audm1_iodown_pins>;
|
||||
pinctrl-5 = <&dsm_audm0_pins>, <&dsm_audm1_pins>;
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -1307,6 +1307,60 @@
|
||||
* This part is edited handly.
|
||||
*/
|
||||
&pinctrl {
|
||||
dsm_aud {
|
||||
/omit-if-no-ref/
|
||||
dsm_audm0_pins: dsm-audm0-pins {
|
||||
rockchip,pins =
|
||||
/* dsm_aud_ln_m0 */
|
||||
<1 RK_PD0 4 &pcfg_pull_none>,
|
||||
/* dsm_aud_lp_m0 */
|
||||
<1 RK_PD1 4 &pcfg_pull_none>,
|
||||
/* dsm_aud_rn_m0 */
|
||||
<1 RK_PC1 4 &pcfg_pull_none>,
|
||||
/* dsm_aud_rp_m0 */
|
||||
<1 RK_PC2 4 &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
/omit-if-no-ref/
|
||||
dsm_audm1_pins: dsm-audm1-pins {
|
||||
rockchip,pins =
|
||||
/* dsm_aud_ln_m1 */
|
||||
<2 RK_PB6 2 &pcfg_pull_none>,
|
||||
/* dsm_aud_lp_m1 */
|
||||
<2 RK_PB7 2 &pcfg_pull_none>,
|
||||
/* dsm_aud_rn_m1 */
|
||||
<2 RK_PB4 2 &pcfg_pull_none>,
|
||||
/* dsm_aud_rp_m1 */
|
||||
<2 RK_PB5 2 &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
/omit-if-no-ref/
|
||||
dsm_audm0_iodown_pins: dsm-audm0-iodown-pins {
|
||||
rockchip,pins =
|
||||
/* dsm_aud_ln_m0 */
|
||||
<1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_down>,
|
||||
/* dsm_aud_lp_m0 */
|
||||
<1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_down>,
|
||||
/* dsm_aud_rn_m0 */
|
||||
<1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>,
|
||||
/* dsm_aud_rp_m0 */
|
||||
<1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
|
||||
/omit-if-no-ref/
|
||||
dsm_audm1_iodown_pins: dsm-audm1-iodown-pins {
|
||||
rockchip,pins =
|
||||
/* dsm_aud_ln_m1 */
|
||||
<2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>,
|
||||
/* dsm_aud_lp_m1 */
|
||||
<2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>,
|
||||
/* dsm_aud_rn_m1 */
|
||||
<2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>,
|
||||
/* dsm_aud_rp_m1 */
|
||||
<2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
};
|
||||
|
||||
dsmc {
|
||||
/omit-if-no-ref/
|
||||
dsmc_csn_pull_pins: dsmc-csn-pull-pins {
|
||||
|
||||
@@ -188,10 +188,16 @@ serdes_bridge_split_detect(struct drm_bridge *bridge)
|
||||
struct serdes_bridge_split *serdes_bridge_split = to_serdes_bridge_split(bridge);
|
||||
struct serdes *serdes = serdes_bridge_split->parent;
|
||||
enum drm_connector_status status = connector_status_connected;
|
||||
enum drm_connector_status last_status = serdes->serdes_bridge_split->status;
|
||||
|
||||
if (serdes->chip_data->bridge_ops->detect)
|
||||
status = serdes->chip_data->bridge_ops->detect(serdes);
|
||||
|
||||
if (status != last_status)
|
||||
dev_info(serdes->dev, "%s: %s, %s\n", __func__, serdes->chip_data->name,
|
||||
(status == connector_status_connected) ? "connected" : "disconnect");
|
||||
|
||||
serdes->serdes_bridge_split->status = status;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ static int serdes_set_i2c_address(struct serdes *serdes, u32 reg_hw, u32 reg_use
|
||||
int ret = 0;
|
||||
struct i2c_client *client_split;
|
||||
struct serdes *serdes_split = serdes->g_serdes_bridge_split;
|
||||
unsigned int def = 0;
|
||||
|
||||
if (!serdes_split) {
|
||||
dev_info(serdes->dev, "%s serdes_split is null\n", __func__);
|
||||
@@ -72,7 +73,12 @@ static int serdes_set_i2c_address(struct serdes *serdes, u32 reg_hw, u32 reg_use
|
||||
__func__, dev_name(serdes_split->dev), client_split->name,
|
||||
client_split->addr, serdes->reg_hw, serdes->reg_use, serdes_split);
|
||||
|
||||
client_split->addr = serdes->reg_hw;
|
||||
client_split->addr = serdes->reg_use;
|
||||
ret = serdes_reg_read(serdes, serdes->serdes_init_seq->reg_sequence[0].reg, &def);
|
||||
if (ret) {
|
||||
client_split->addr = serdes->reg_hw;
|
||||
dev_info(serdes->dev, "%s try to use addr 0x%x\n", __func__, serdes->reg_hw);
|
||||
}
|
||||
|
||||
if (serdes_split && serdes_split->chip_data->split_ops &&
|
||||
serdes_split->chip_data->split_ops->select)
|
||||
@@ -410,10 +416,13 @@ static int serdes_i2c_probe(struct i2c_client *client,
|
||||
if (serdes->reg_hw) {
|
||||
SERDES_DBG_MFD("%s: %s start change i2c address from 0x%x to 0x%x\n",
|
||||
__func__, dev->of_node->name, serdes->reg_hw, serdes->reg_use);
|
||||
ret = serdes_set_i2c_address(serdes, serdes->reg_hw,
|
||||
serdes->reg_use, serdes->link_use);
|
||||
if (ret)
|
||||
dev_err(dev, "%s failed to set i2c address\n", serdes->chip_data->name);
|
||||
|
||||
if (!serdes->route_enable) {
|
||||
ret = serdes_set_i2c_address(serdes, serdes->reg_hw,
|
||||
serdes->reg_use, serdes->link_use);
|
||||
if (ret)
|
||||
dev_err(dev, "%s failed to set addr\n", serdes->chip_data->name);
|
||||
}
|
||||
}
|
||||
|
||||
serdes->use_delay_work = of_property_read_bool(dev->of_node, "use-delay-work");
|
||||
|
||||
@@ -335,7 +335,8 @@ static int serdes_pinctrl_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = pinctrl_enable(serdes_pinctrl->pctl);
|
||||
if (!serdes->route_enable)
|
||||
ret = pinctrl_enable(serdes_pinctrl->pctl);
|
||||
|
||||
ret = serdes_pinctrl_gpio_init(serdes);
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@ out:
|
||||
|
||||
static int parse_io_config(struct device *dev)
|
||||
{
|
||||
int ret = 0, cnt;
|
||||
int ret = 0, cnt, i;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct rk_sleep_config *config = &sleep_config[RK_PM_MEM];
|
||||
|
||||
@@ -456,6 +456,13 @@ static int parse_io_config(struct device *dev)
|
||||
}
|
||||
|
||||
config->sleep_io_config_cnt = cnt;
|
||||
|
||||
sip_smc_set_suspend_mode(SLEEP_IO_CONFIG, RK_PM_SLEEP_IO_CFG_CNT, cnt);
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
sip_smc_set_suspend_mode(SLEEP_IO_CONFIG,
|
||||
RK_PM_SLEEP_IO_CFG_VAL,
|
||||
config->sleep_io_config[i]);
|
||||
} else {
|
||||
dev_dbg(dev, "not set sleep-pin-config\n");
|
||||
}
|
||||
|
||||
@@ -111,6 +111,13 @@
|
||||
#define LINUX_PM_STATE 0x09
|
||||
#define SUSPEND_IO_RET_CONFIG 0x0a
|
||||
#define SLEEP_PIN_CONFIG 0x0b
|
||||
#define SLEEP_IO_CONFIG 0x0c
|
||||
|
||||
enum {
|
||||
RK_PM_SLEEP_IO_CFG_CNT = 0,
|
||||
RK_PM_SLEEP_IO_CFG_VAL = 1,
|
||||
RK_PM_SLEEP_IO_CFG_MAX,
|
||||
};
|
||||
|
||||
/* SIP_REMOTECTL_CFG call types */
|
||||
#define REMOTECTL_SET_IRQ 0xf0
|
||||
|
||||
@@ -23,15 +23,72 @@
|
||||
#include <sound/tlv.h>
|
||||
#include "rk_dsm.h"
|
||||
|
||||
#define RK3506_DSM_AUDM0_EN BIT(0)
|
||||
#define RK3506_DSM_AUDM1_EN BIT(1)
|
||||
#define RK3506_IOC1_REG_BASE (0xff660000)
|
||||
#define RK3506_GPIO1_IOC_GPIO1C_IOMUX_SEL_0 (0x0030) /* DSM_AUD_RP_M0 / DSM_AUD_RN_M0 */
|
||||
#define RK3506_GPIO1_IOC_GPIO1C2_SEL_MASK GENMASK(11, 8)
|
||||
#define RK3506_GPIO1_IOC_DSM_AUD_RP_M0 (4 << 8)
|
||||
#define RK3506_GPIO1_IOC_GPIO2C2 (0 << 8)
|
||||
#define RK3506_GPIO1_IOC_GPIO1C1_SEL_MASK GENMASK(7, 4)
|
||||
#define RK3506_GPIO1_IOC_DSM_AUD_RN_M0 (4 << 4)
|
||||
#define RK3506_GPIO1_IOC_GPIO2C1 (0 << 4)
|
||||
#define RK3506_GPIO1_IOC_GPIO1D_IOMUX_SEL_0 (0x0038) /* DSM_AUD_LP_M0 / DSM_AUD_LN_M0 */
|
||||
#define RK3506_GPIO1_IOC_GPIO1D1_SEL_MASK GENMASK(7, 4)
|
||||
#define RK3506_GPIO1_IOC_DSM_AUD_LP_M0 (4 << 4)
|
||||
#define RK3506_GPIO1_IOC_GPIO2D1 (0 << 4)
|
||||
#define RK3506_GPIO1_IOC_GPIO1D0_SEL_MASK GENMASK(3, 0)
|
||||
#define RK3506_GPIO1_IOC_DSM_AUD_LN_M0 (4 << 0)
|
||||
#define RK3506_GPIO1_IOC_GPIO2D0 (0 << 0)
|
||||
#define RK3506_IOC2_REG_BASE (0xff4d8000)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B_IOMUX_SEL_1 (0x004c) /* DSM_AUD_LP_M1 / DSM_AUD_LN_M1 / DSM_AUD_RP_M1 / DSM_AUD_RN_M1 */
|
||||
#define RK3506_GPIO2_IOC_GPIO2B7_SEL_MASK GENMASK(15, 12)
|
||||
#define RK3506_GPIO2_IOC_DSM_AUD_LP_M1 (2 << 12)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B7 (0 << 12)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B6_SEL_MASK GENMASK(11, 8)
|
||||
#define RK3506_GPIO2_IOC_DSM_AUD_LN_M1 (2 << 8)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B6 (0 << 8)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B5_SEL_MASK GENMASK(7, 4)
|
||||
#define RK3506_GPIO2_IOC_DSM_AUD_RP_M1 (2 << 4)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B5 (0 << 4)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B4_SEL_MASK GENMASK(3, 0)
|
||||
#define RK3506_GPIO2_IOC_DSM_AUD_RN_M1 (2 << 0)
|
||||
#define RK3506_GPIO2_IOC_GPIO2B4 (0 << 0)
|
||||
|
||||
#define RK3506_GRF_SOC_CON0 (0x0)
|
||||
#define RK3506_DSM_SEL (9)
|
||||
#define RK3562_GRF_PERI_AUDIO_CON (0x0070)
|
||||
#define RK3576_SYS_GRF_SOC_CON2 (0x0008)
|
||||
#define RK3576_DSM_SEL (0x0)
|
||||
|
||||
#define RKDSM_VOL_VAL_MAX (0xff)
|
||||
|
||||
enum {
|
||||
RKDSM_ON_GPIO = 0,
|
||||
RKDSM_ON_FUNC,
|
||||
};
|
||||
|
||||
struct rk_dsm_soc_data {
|
||||
int (*init)(struct device *dev);
|
||||
void (*deinit)(struct device *dev);
|
||||
int (*iomux_switch)(struct device *dev, int type);
|
||||
};
|
||||
|
||||
struct rk_dsm_vols {
|
||||
int vol_l;
|
||||
int vol_r;
|
||||
int polarity;
|
||||
};
|
||||
|
||||
struct rk_dsm_iomux_res {
|
||||
phys_addr_t regbase;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct rk_dsm_iomux {
|
||||
void __iomem **ioc;
|
||||
unsigned int audm_en;
|
||||
int res_num;
|
||||
};
|
||||
|
||||
struct rk_dsm_priv {
|
||||
@@ -43,6 +100,12 @@ struct rk_dsm_priv {
|
||||
struct gpio_desc *pa_ctl;
|
||||
struct reset_control *rc;
|
||||
const struct rk_dsm_soc_data *data;
|
||||
struct device *dev;
|
||||
struct rk_dsm_vols vols;
|
||||
struct rk_dsm_iomux iomuxes;
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pin_state;
|
||||
struct pinctrl_state *io_state;
|
||||
};
|
||||
|
||||
/* DAC digital gain */
|
||||
@@ -92,6 +155,8 @@ static int rk_dsm_dac_vol_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct rk_dsm_priv *rd =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int rreg = mc->rreg;
|
||||
unsigned int shift = mc->shift;
|
||||
@@ -116,6 +181,9 @@ static int rk_dsm_dac_vol_put(struct snd_kcontrol *kcontrol,
|
||||
snd_soc_component_update_bits(component, reg, val_mask, val);
|
||||
snd_soc_component_update_bits(component, rreg, val_mask, val);
|
||||
snd_soc_component_write(component, DACVOGP, sign);
|
||||
rd->vols.vol_l = val;
|
||||
rd->vols.vol_r = val;
|
||||
rd->vols.polarity = sign;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -355,9 +423,7 @@ static int rk_dsm_hw_params(struct snd_pcm_substream *substream,
|
||||
DSM_DACDSM_CTRL_DSM_EN_MASK,
|
||||
DSM_DACDSM_CTRL_DSM_MODE_CKE_EN |
|
||||
DSM_DACDSM_CTRL_DSM_EN);
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_update_bits(rd->regmap, I2S_XFER,
|
||||
DSM_I2S_XFER_RXS_MASK,
|
||||
DSM_I2S_XFER_RXS_START);
|
||||
@@ -366,6 +432,9 @@ static int rk_dsm_hw_params(struct snd_pcm_substream *substream,
|
||||
DSM_DACDIGEN_DACEN_L0R1_MASK,
|
||||
DSM_DACDIGEN_DAC_GLBEN_EN |
|
||||
DSM_DACDIGEN_DACEN_L0R1_EN);
|
||||
|
||||
if (rd->data && rd->data->iomux_switch)
|
||||
rd->data->iomux_switch(rd->dev, RKDSM_ON_FUNC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -377,6 +446,11 @@ static int rk_dsm_pcm_startup(struct snd_pcm_substream *substream,
|
||||
struct rk_dsm_priv *rd =
|
||||
snd_soc_component_get_drvdata(dai->component);
|
||||
|
||||
/* Recover DAC Volumes */
|
||||
regmap_write(rd->regmap, DACVOLL0, rd->vols.vol_l);
|
||||
regmap_write(rd->regmap, DACVOLR0, rd->vols.vol_r);
|
||||
regmap_write(rd->regmap, DACVOGP, rd->vols.polarity);
|
||||
|
||||
gpiod_set_value(rd->pa_ctl, 1);
|
||||
if (rd->pa_ctl_delay_ms)
|
||||
msleep(rd->pa_ctl_delay_ms);
|
||||
@@ -425,11 +499,44 @@ static void rk_dsm_pcm_shutdown(struct snd_pcm_substream *substream,
|
||||
rk_dsm_reset(rd);
|
||||
}
|
||||
|
||||
static int rk_dsm_pcm_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct rk_dsm_priv *rd =
|
||||
snd_soc_component_get_drvdata(dai->component);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
/**
|
||||
* After receiving the stop action, adjust the volume to the
|
||||
* minimum as soon as possible and switch the differential pair
|
||||
* of DSM to IO state, so that the same direction change of P/N
|
||||
* level can reduce the pop sound to the minimum.
|
||||
*/
|
||||
regmap_write(rd->regmap, DACVOLL0, RKDSM_VOL_VAL_MAX);
|
||||
regmap_write(rd->regmap, DACVOLR0, RKDSM_VOL_VAL_MAX);
|
||||
regmap_write(rd->regmap, DACVOGP, DSM_DACVOGP_VOLGPL0_NEG | DSM_DACVOGP_VOLGPR0_NEG);
|
||||
regcache_cache_only(rd->regmap, false);
|
||||
regcache_mark_dirty(rd->regmap);
|
||||
regcache_sync(rd->regmap);
|
||||
if (rd->data && rd->data->iomux_switch)
|
||||
rd->data->iomux_switch(rd->dev, RKDSM_ON_GPIO);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops rd_dai_ops = {
|
||||
.hw_params = rk_dsm_hw_params,
|
||||
.set_fmt = rk_dsm_set_dai_fmt,
|
||||
.startup = rk_dsm_pcm_startup,
|
||||
.shutdown = rk_dsm_pcm_shutdown,
|
||||
.trigger = rk_dsm_pcm_trigger,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver rd_dai[] = {
|
||||
@@ -473,7 +580,71 @@ static const struct regmap_config rd_regmap_config = {
|
||||
static int rk3506_soc_init(struct device *dev)
|
||||
{
|
||||
struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
||||
struct rk_dsm_iomux_res res[] = {
|
||||
{ .regbase = RK3506_IOC1_REG_BASE, .size = 0x100, },
|
||||
{ .regbase = RK3506_IOC2_REG_BASE, .size = 0x100, },
|
||||
};
|
||||
int c;
|
||||
|
||||
rd->iomuxes.res_num = ARRAY_SIZE(res);
|
||||
rd->iomuxes.ioc = devm_kcalloc(dev, rd->iomuxes.res_num, sizeof(void __iomem *), GFP_KERNEL);
|
||||
if (!rd->iomuxes.ioc)
|
||||
return -ENOMEM;
|
||||
|
||||
for (c = 0; c < rd->iomuxes.res_num; c++) {
|
||||
rd->iomuxes.ioc[c] = ioremap(res[c].regbase, res[c].size);
|
||||
if (!rd->iomuxes.ioc[c]) {
|
||||
int n;
|
||||
|
||||
/* iounmap previous mapped address */
|
||||
for (n = 0; n < rd->iomuxes.res_num; n++) {
|
||||
if (rd->iomuxes.ioc[n]) {
|
||||
iounmap(rd->iomuxes.ioc[n]);
|
||||
rd->iomuxes.ioc[n] = NULL;
|
||||
}
|
||||
}
|
||||
dev_err(dev, "ioremap res[%d] start: 0x%lx failed\n",
|
||||
c, (unsigned long)res[c].regbase);
|
||||
return -ENOMEM;
|
||||
}
|
||||
dev_info(dev, "ioremap ioc res[%d] start: 0x%lx success\n", c, (unsigned long)res[c].regbase);
|
||||
}
|
||||
|
||||
rd->pinctrl = devm_pinctrl_get(dev);
|
||||
if (!IS_ERR_OR_NULL(rd->pinctrl)) {
|
||||
const char *io_name;
|
||||
const char *pin_name;
|
||||
|
||||
if (rd->iomuxes.audm_en == (RK3506_DSM_AUDM0_EN | RK3506_DSM_AUDM1_EN)) {
|
||||
io_name = "audm0m1-iodown";
|
||||
pin_name = "audm0m1-pins";
|
||||
} else if (rd->iomuxes.audm_en == RK3506_DSM_AUDM1_EN) {
|
||||
io_name = "audm1-iodown";
|
||||
pin_name = "audm1-pins";
|
||||
} else {
|
||||
/* default case */
|
||||
io_name = "audm0-iodown";
|
||||
pin_name = "audm0-pins";
|
||||
rd->iomuxes.audm_en = RK3506_DSM_AUDM0_EN;
|
||||
}
|
||||
|
||||
rd->io_state = pinctrl_lookup_state(rd->pinctrl, io_name);
|
||||
if (IS_ERR(rd->io_state)) {
|
||||
rd->io_state = NULL;
|
||||
dev_err(dev, "Have no dsm pinctrl io state by: %s\n", io_name);
|
||||
}
|
||||
|
||||
rd->pin_state = pinctrl_lookup_state(rd->pinctrl, pin_name);
|
||||
if (IS_ERR(rd->pin_state)) {
|
||||
rd->pin_state = NULL;
|
||||
dev_err(dev, "Have no dsm pinctrl pin state, by: %s\n", pin_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (rd->data && rd->data->iomux_switch)
|
||||
rd->data->iomux_switch(rd->dev, RKDSM_ON_GPIO);
|
||||
|
||||
dev_info(dev, "iomuxes audm_en: 0x%x\n", rd->iomuxes.audm_en);
|
||||
/* enable internal codec to sai3 */
|
||||
return regmap_write(rd->grf, RK3506_GRF_SOC_CON0,
|
||||
BIT(RK3506_DSM_SEL) << 16 | BIT(RK3506_DSM_SEL));
|
||||
@@ -482,13 +653,102 @@ static int rk3506_soc_init(struct device *dev)
|
||||
static void rk3506_soc_deinit(struct device *dev)
|
||||
{
|
||||
struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
||||
int c;
|
||||
|
||||
regmap_write(rd->grf, RK3506_GRF_SOC_CON0, BIT(RK3506_DSM_SEL) << 16);
|
||||
for (c = 0; c < rd->iomuxes.res_num; c++) {
|
||||
if (rd->iomuxes.ioc[c]) {
|
||||
iounmap(rd->iomuxes.ioc[c]);
|
||||
rd->iomuxes.ioc[c] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rk3506_soc_iomux_switch(struct device *dev, int type)
|
||||
{
|
||||
struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
||||
struct rk_dsm_iomux *iomuxes = &rd->iomuxes;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (iomuxes->audm_en & RK3506_DSM_AUDM0_EN) {
|
||||
/**
|
||||
* DSM_AUD_RN_M0 - GPIO1_C1
|
||||
* DSM_AUD_RP_M0 - GPIO1_C2
|
||||
* DSM_AUD_LN_M0 - GPIO1_D0
|
||||
* DSM_AUD_LP_M0 - GPIO1_D1
|
||||
*/
|
||||
if (type == RKDSM_ON_FUNC) {
|
||||
writel(((RK3506_GPIO1_IOC_GPIO1C2_SEL_MASK |
|
||||
RK3506_GPIO1_IOC_GPIO1C1_SEL_MASK) << 16) |
|
||||
(RK3506_GPIO1_IOC_DSM_AUD_RP_M0 |
|
||||
RK3506_GPIO1_IOC_DSM_AUD_RN_M0),
|
||||
iomuxes->ioc[0] + RK3506_GPIO1_IOC_GPIO1C_IOMUX_SEL_0);
|
||||
writel(((RK3506_GPIO1_IOC_GPIO1D1_SEL_MASK |
|
||||
RK3506_GPIO1_IOC_GPIO1D0_SEL_MASK) << 16) |
|
||||
(RK3506_GPIO1_IOC_DSM_AUD_LP_M0 |
|
||||
RK3506_GPIO1_IOC_DSM_AUD_LN_M0),
|
||||
iomuxes->ioc[0] + RK3506_GPIO1_IOC_GPIO1D_IOMUX_SEL_0);
|
||||
} else {
|
||||
/* RKDSM_ON_GPIO */
|
||||
writel(((RK3506_GPIO1_IOC_GPIO1C2_SEL_MASK |
|
||||
RK3506_GPIO1_IOC_GPIO1C1_SEL_MASK) << 16) |
|
||||
(RK3506_GPIO1_IOC_GPIO2C2 |
|
||||
RK3506_GPIO1_IOC_GPIO2C1),
|
||||
iomuxes->ioc[0] + RK3506_GPIO1_IOC_GPIO1C_IOMUX_SEL_0);
|
||||
writel(((RK3506_GPIO1_IOC_GPIO1D1_SEL_MASK |
|
||||
RK3506_GPIO1_IOC_GPIO1D0_SEL_MASK) << 16) |
|
||||
(RK3506_GPIO1_IOC_GPIO2D1 |
|
||||
RK3506_GPIO1_IOC_GPIO2D0),
|
||||
iomuxes->ioc[0] + RK3506_GPIO1_IOC_GPIO1D_IOMUX_SEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
if (iomuxes->audm_en & RK3506_DSM_AUDM1_EN) {
|
||||
/**
|
||||
* DSM_AUD_RN_M1 - GPIO2_B4
|
||||
* DSM_AUD_RP_M1 - GPIO2_B5
|
||||
* DSM_AUD_LN_M1 - GPIO2_B6
|
||||
* DSM_AUD_LP_M1 - GPIO2_B7
|
||||
*/
|
||||
if (type == RKDSM_ON_FUNC) {
|
||||
writel(((RK3506_GPIO2_IOC_GPIO2B7_SEL_MASK |
|
||||
RK3506_GPIO2_IOC_GPIO2B6_SEL_MASK |
|
||||
RK3506_GPIO2_IOC_GPIO2B5_SEL_MASK |
|
||||
RK3506_GPIO2_IOC_GPIO2B4_SEL_MASK) << 16) |
|
||||
(RK3506_GPIO2_IOC_DSM_AUD_LP_M1 |
|
||||
RK3506_GPIO2_IOC_DSM_AUD_LN_M1 |
|
||||
RK3506_GPIO2_IOC_DSM_AUD_RP_M1 |
|
||||
RK3506_GPIO2_IOC_DSM_AUD_RN_M1),
|
||||
iomuxes->ioc[1] + RK3506_GPIO2_IOC_GPIO2B_IOMUX_SEL_1);
|
||||
} else {
|
||||
/* RKDSM_ON_GPIO */
|
||||
writel(((RK3506_GPIO2_IOC_GPIO2B7_SEL_MASK |
|
||||
RK3506_GPIO2_IOC_GPIO2B6_SEL_MASK |
|
||||
RK3506_GPIO2_IOC_GPIO2B5_SEL_MASK |
|
||||
RK3506_GPIO2_IOC_GPIO2B4_SEL_MASK) << 16) |
|
||||
(RK3506_GPIO2_IOC_GPIO2B7 |
|
||||
RK3506_GPIO2_IOC_GPIO2B6 |
|
||||
RK3506_GPIO2_IOC_GPIO2B5 |
|
||||
RK3506_GPIO2_IOC_GPIO2B4),
|
||||
iomuxes->ioc[1] + RK3506_GPIO2_IOC_GPIO2B_IOMUX_SEL_1);
|
||||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
/* Keeping sync with pinctrl framework */
|
||||
if (type == RKDSM_ON_FUNC)
|
||||
pinctrl_select_state(rd->pinctrl, rd->pin_state);
|
||||
else
|
||||
pinctrl_select_state(rd->pinctrl, rd->io_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rk_dsm_soc_data rk3506_data = {
|
||||
.init = rk3506_soc_init,
|
||||
.deinit = rk3506_soc_deinit,
|
||||
.iomux_switch = rk3506_soc_iomux_switch,
|
||||
};
|
||||
|
||||
static int rk3562_soc_init(struct device *dev)
|
||||
@@ -601,6 +861,9 @@ static int rk_dsm_platform_probe(struct platform_device *pdev)
|
||||
&rd->pa_ctl_delay_ms))
|
||||
rd->pa_ctl_delay_ms = 0;
|
||||
|
||||
if (device_property_read_u32(&pdev->dev, "rockchip,dsm-audm-en", &rd->iomuxes.audm_en))
|
||||
rd->iomuxes.audm_en = 0;
|
||||
|
||||
rd->rc = devm_reset_control_get(&pdev->dev, "reset");
|
||||
|
||||
rd->clk_dac = devm_clk_get(&pdev->dev, "dac");
|
||||
@@ -620,6 +883,7 @@ static int rk_dsm_platform_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(rd->regmap))
|
||||
return PTR_ERR(rd->regmap);
|
||||
|
||||
rd->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, rd);
|
||||
|
||||
rd->data = device_get_match_data(&pdev->dev);
|
||||
|
||||
Reference in New Issue
Block a user