From cd6e82b814ca73c474b1a2fa48a54b251da44655 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Tue, 7 Oct 2014 10:25:37 +0800 Subject: ASoC: rt5645: Add the workqueue of the jack detect function for the debouncing Add the workqueue of the jack detect function for the debouncing. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 3fb83bf..57ba742 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2166,11 +2166,20 @@ int rt5645_set_jack_detect(struct snd_soc_codec *codec, } EXPORT_SYMBOL_GPL(rt5645_set_jack_detect); +static void rt5645_jack_detect_work(struct work_struct *work) +{ + struct rt5645_priv *rt5645 = + container_of(work, struct rt5645_priv, jack_detect_work.work); + + rt5645_jack_detect(rt5645->codec, rt5645->jack); +} + static irqreturn_t rt5645_irq(int irq, void *data) { struct rt5645_priv *rt5645 = data; - rt5645_jack_detect(rt5645->codec, rt5645->jack); + queue_delayed_work(system_power_efficient_wq, + &rt5645->jack_detect_work, msecs_to_jiffies(250)); return IRQ_HANDLED; } @@ -2436,6 +2445,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n"); } + INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); + return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, rt5645_dai, ARRAY_SIZE(rt5645_dai)); } @@ -2447,6 +2458,8 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) if (i2c->irq) free_irq(i2c->irq, rt5645); + cancel_delayed_work_sync(&rt5645->jack_detect_work); + if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) gpio_free(rt5645->pdata.hp_det_gpio); -- cgit v1.1 From 0b2e4959ceacb26eb586698d9ceecc0a6bd30f72 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 4 Nov 2014 13:15:10 +0800 Subject: ASoC: rt5645: make bias level more reasonale This patah separate bias level off to standby and off. The standby level will provide the necessary power for JD and push button functions. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 57ba742..1423cb2 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2069,8 +2069,8 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { switch (level) { - case SND_SOC_BIAS_STANDBY: - if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) { + case SND_SOC_BIAS_PREPARE: + if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { snd_soc_update_bits(codec, RT5645_PWR_ANLG1, RT5645_PWR_VREF1 | RT5645_PWR_MB | RT5645_PWR_BG | RT5645_PWR_VREF2, @@ -2085,15 +2085,24 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, } break; + case SND_SOC_BIAS_STANDBY: + snd_soc_update_bits(codec, RT5645_PWR_ANLG1, + RT5645_PWR_VREF1 | RT5645_PWR_MB | + RT5645_PWR_BG | RT5645_PWR_VREF2, + RT5645_PWR_VREF1 | RT5645_PWR_MB | + RT5645_PWR_BG | RT5645_PWR_VREF2); + snd_soc_update_bits(codec, RT5645_PWR_ANLG1, + RT5645_PWR_FV1 | RT5645_PWR_FV2, + RT5645_PWR_FV1 | RT5645_PWR_FV2); + break; + case SND_SOC_BIAS_OFF: snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); snd_soc_write(codec, RT5645_GEN_CTRL1, 0x0128); - snd_soc_write(codec, RT5645_PWR_DIG1, 0x0000); - snd_soc_write(codec, RT5645_PWR_DIG2, 0x0000); - snd_soc_write(codec, RT5645_PWR_VOL, 0x0000); - snd_soc_write(codec, RT5645_PWR_MIXER, 0x0000); - snd_soc_write(codec, RT5645_PWR_ANLG1, 0x0000); - snd_soc_write(codec, RT5645_PWR_ANLG2, 0x0000); + snd_soc_update_bits(codec, RT5645_PWR_ANLG1, + RT5645_PWR_VREF1 | RT5645_PWR_MB | + RT5645_PWR_BG | RT5645_PWR_VREF2 | + RT5645_PWR_FV1 | RT5645_PWR_FV2, 0x0); break; default: -- cgit v1.1 From bb656add19764c7a3cf28b2b330ec0a189fe4f48 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Nov 2014 15:02:08 +0800 Subject: ASoC: rt5645: Add JD function support rt5645 codec support jack detection function. The patch will set related registers if JD function is used. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 1423cb2..286438d 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2203,6 +2203,13 @@ static int rt5645_probe(struct snd_soc_codec *codec) snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); + /* for JD function */ + if (rt5645->pdata.en_jd_func) { + snd_soc_dapm_force_enable_pin(&codec->dapm, "JD Power"); + snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); + snd_soc_dapm_sync(&codec->dapm); + } + return 0; } @@ -2436,6 +2443,19 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, } + if (rt5645->pdata.en_jd_func) { + regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, + RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU, + RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU); + regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, + RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); + regmap_update_bits(rt5645->regmap, RT5645_JD_CTRL3, + RT5645_JD_CBJ_EN | RT5645_JD_CBJ_POL, + RT5645_JD_CBJ_EN | RT5645_JD_CBJ_POL); + regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, + RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); + } + if (rt5645->i2c->irq) { ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING -- cgit v1.1 From 9e2683530d6f78b30bcf4cabb97d1b7d6b925b85 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 31 Oct 2014 15:37:55 +0800 Subject: ASoC: rt5645: Add ASRC support This patch add ASRC support for rt5645 codec. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 286438d..1dbbebc 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -441,6 +441,65 @@ static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_sel_enum, RT5645_TDM_CTRL_1, 8, rt5645_tdm_adc_data_select); +static int rt5645_clk_sel_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + unsigned int u_bit = 0, p_bit = 0; + struct soc_enum *em = + (struct soc_enum *)kcontrol->private_value; + + switch (em->reg) { + case RT5645_ASRC_2: + switch (em->shift_l) { + case 0: + u_bit = 0x8; + p_bit = RT5645_PWR_ADC_S1F; + break; + case 4: + u_bit = 0x100; + p_bit = RT5645_PWR_DAC_MF_R; + break; + case 8: + u_bit = 0x200; + p_bit = RT5645_PWR_DAC_MF_L; + break; + case 12: + u_bit = 0x400; + p_bit = RT5645_PWR_DAC_S1F; + break; + } + break; + case RT5645_ASRC_3: + switch (em->shift_l) { + case 0: + u_bit = 0x1; + p_bit = RT5645_PWR_ADC_MF_R; + break; + case 4: + u_bit = 0x2; + p_bit = RT5645_PWR_ADC_MF_L; + break; + } + break; + } + + if (u_bit || p_bit) { + switch (ucontrol->value.integer.value[0]) { + case 1 ... 4: /*enable*/ + if (snd_soc_read(codec, RT5645_PWR_DIG2) & p_bit) + snd_soc_update_bits(codec, + RT5645_ASRC_1, u_bit, u_bit); + break; + default: /*disable*/ + snd_soc_update_bits(codec, RT5645_ASRC_1, u_bit, 0); + break; + } + } + + return snd_soc_put_enum_double(kcontrol, ucontrol); +} + static const struct snd_kcontrol_new rt5645_snd_controls[] = { /* Speaker Output Volume */ SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, @@ -552,6 +611,53 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, return 0; } +static int is_using_asrc(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg, shift, val; + + switch (source->shift) { + case 0: + reg = RT5645_ASRC_3; + shift = 0; + break; + case 1: + reg = RT5645_ASRC_3; + shift = 4; + break; + case 3: + reg = RT5645_ASRC_2; + shift = 0; + break; + case 8: + reg = RT5645_ASRC_2; + shift = 4; + break; + case 9: + reg = RT5645_ASRC_2; + shift = 8; + break; + case 10: + reg = RT5645_ASRC_2; + shift = 12; + break; + default: + return 0; + } + + val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; + switch (val) { + case 1: + case 2: + case 3: + case 4: + return 1; + default: + return 0; + } + +} + /* Digital Mixer */ static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, @@ -1244,6 +1350,30 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5645_PWR_VOL, RT5645_PWR_MIC_DET_BIT, 0, NULL, 0), + /* ASRC */ + SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5645_ASRC_1, + 11, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5645_ASRC_1, + 12, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5645_ASRC_1, + 10, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DAC MONO L ASRC", 1, RT5645_ASRC_1, + 9, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5645_ASRC_1, + 8, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DMIC STO1 ASRC", 1, RT5645_ASRC_1, + 7, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DMIC MONO L ASRC", 1, RT5645_ASRC_1, + 5, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DMIC MONO R ASRC", 1, RT5645_ASRC_1, + 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5645_ASRC_1, + 3, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5645_ASRC_1, + 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5645_ASRC_1, + 0, 0, NULL, 0), + /* Input Side */ /* micbias */ SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2, @@ -1502,6 +1632,17 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { }; static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { + { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, + { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, + { "adc mono left filter", NULL, "ADC MONO L ASRC", is_using_asrc }, + { "adc mono right filter", NULL, "ADC MONO R ASRC", is_using_asrc }, + { "dac mono left filter", NULL, "DAC MONO L ASRC", is_using_asrc }, + { "dac mono right filter", NULL, "DAC MONO R ASRC", is_using_asrc }, + { "dac stereo1 filter", NULL, "DAC STO ASRC", is_using_asrc }, + + { "I2S1", NULL, "I2S1 ASRC" }, + { "I2S2", NULL, "I2S2 ASRC" }, + { "IN1P", NULL, "LDO2" }, { "IN2P", NULL, "LDO2" }, @@ -1548,12 +1689,15 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, + { "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC" }, { "Mono DMIC L Mux", "DMIC1", "DMIC L1" }, { "Mono DMIC L Mux", "DMIC2", "DMIC L2" }, + { "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC" }, { "Mono DMIC R Mux", "DMIC1", "DMIC R1" }, { "Mono DMIC R Mux", "DMIC2", "DMIC R2" }, + { "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC" }, { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" }, { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, -- cgit v1.1 From 5563502cb68d9520e13fe2350922ca88c4531c63 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 11 Nov 2014 11:31:28 +0800 Subject: ASoC: rt5645: remove unused rt5645_clk_sel_put Remove rt5645_clk_sel_put function since it is never used. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 59 ----------------------------------------------- 1 file changed, 59 deletions(-) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 1dbbebc..665f8b6 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -441,65 +441,6 @@ static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_sel_enum, RT5645_TDM_CTRL_1, 8, rt5645_tdm_adc_data_select); -static int rt5645_clk_sel_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); - unsigned int u_bit = 0, p_bit = 0; - struct soc_enum *em = - (struct soc_enum *)kcontrol->private_value; - - switch (em->reg) { - case RT5645_ASRC_2: - switch (em->shift_l) { - case 0: - u_bit = 0x8; - p_bit = RT5645_PWR_ADC_S1F; - break; - case 4: - u_bit = 0x100; - p_bit = RT5645_PWR_DAC_MF_R; - break; - case 8: - u_bit = 0x200; - p_bit = RT5645_PWR_DAC_MF_L; - break; - case 12: - u_bit = 0x400; - p_bit = RT5645_PWR_DAC_S1F; - break; - } - break; - case RT5645_ASRC_3: - switch (em->shift_l) { - case 0: - u_bit = 0x1; - p_bit = RT5645_PWR_ADC_MF_R; - break; - case 4: - u_bit = 0x2; - p_bit = RT5645_PWR_ADC_MF_L; - break; - } - break; - } - - if (u_bit || p_bit) { - switch (ucontrol->value.integer.value[0]) { - case 1 ... 4: /*enable*/ - if (snd_soc_read(codec, RT5645_PWR_DIG2) & p_bit) - snd_soc_update_bits(codec, - RT5645_ASRC_1, u_bit, u_bit); - break; - default: /*disable*/ - snd_soc_update_bits(codec, RT5645_ASRC_1, u_bit, 0); - break; - } - } - - return snd_soc_put_enum_double(kcontrol, ucontrol); -} - static const struct snd_kcontrol_new rt5645_snd_controls[] = { /* Speaker Output Volume */ SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, -- cgit v1.1 From 850577db99dbc4fdebe62d30d380de1878f77d2a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 13 Nov 2014 09:55:22 +0800 Subject: ASoC: rt5645: add register setting for TDM We need to set extra register to avoid a recording issue in TDM mode. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 665f8b6..57afa12 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2112,8 +2112,11 @@ static int rt5645_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, struct snd_soc_codec *codec = dai->codec; unsigned int val = 0; - if (rx_mask || tx_mask) + if (rx_mask || tx_mask) { val |= (1 << 14); + snd_soc_update_bits(codec, RT5645_BASS_BACK, + RT5645_G_BB_BST_MASK, RT5645_G_BB_BST_25DB); + } switch (slots) { case 4: -- cgit v1.1 From 471f208af987a3741757c169c4e2ad984359000b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 14 Nov 2014 14:25:37 +0800 Subject: ASoC: rt5645: two jacks for hp and mic Some OS need headphone and microphone to be separated. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 57afa12..ef88b50 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2201,8 +2201,7 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int rt5645_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack) +static int rt5645_jack_detect(struct snd_soc_codec *codec) { struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); int gpio_state, jack_type = 0; @@ -2245,19 +2244,19 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, snd_soc_dapm_sync(&codec->dapm); } - snd_soc_jack_report(rt5645->jack, jack_type, SND_JACK_HEADSET); - + snd_soc_jack_report(rt5645->hp_jack, jack_type, SND_JACK_HEADPHONE); + snd_soc_jack_report(rt5645->mic_jack, jack_type, SND_JACK_MICROPHONE); return 0; } int rt5645_set_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack) + struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack) { struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); - rt5645->jack = jack; - - rt5645_jack_detect(codec, rt5645->jack); + rt5645->hp_jack = hp_jack; + rt5645->mic_jack = mic_jack; + rt5645_jack_detect(codec); return 0; } @@ -2268,7 +2267,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) struct rt5645_priv *rt5645 = container_of(work, struct rt5645_priv, jack_detect_work.work); - rt5645_jack_detect(rt5645->codec, rt5645->jack); + rt5645_jack_detect(rt5645->codec); } static irqreturn_t rt5645_irq(int irq, void *data) -- cgit v1.1 From 2d4e2d020516632288e8c8d1f8be2f3042d6b8de Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 18 Nov 2014 16:50:18 +0800 Subject: ASoC: rt5645: multiple JD mode support There are 3 JD modes in RT5645. This patch configure register values according to platform data. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index ef88b50..6e9cd8e 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2239,7 +2239,8 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec) snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); - snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); + if (rt5645->pdata.jd_mode == 0) + snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); snd_soc_dapm_sync(&codec->dapm); } @@ -2543,6 +2544,38 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); } + if (rt5645->pdata.jd_mode) { + regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, + RT5645_IRQ_JD_1_1_EN, RT5645_IRQ_JD_1_1_EN); + regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, + RT5645_JD_PSV_MODE, RT5645_JD_PSV_MODE); + regmap_update_bits(rt5645->regmap, RT5645_HPO_MIXER, + RT5645_IRQ_PSV_MODE, RT5645_IRQ_PSV_MODE); + regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, + RT5645_MIC2_OVCD_EN, RT5645_MIC2_OVCD_EN); + regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, + RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ); + switch (rt5645->pdata.jd_mode) { + case 1: + regmap_update_bits(rt5645->regmap, RT5645_A_JD_CTRL1, + RT5645_JD1_MODE_MASK, + RT5645_JD1_MODE_0); + break; + case 2: + regmap_update_bits(rt5645->regmap, RT5645_A_JD_CTRL1, + RT5645_JD1_MODE_MASK, + RT5645_JD1_MODE_1); + break; + case 3: + regmap_update_bits(rt5645->regmap, RT5645_A_JD_CTRL1, + RT5645_JD1_MODE_MASK, + RT5645_JD1_MODE_2); + break; + default: + break; + } + } + if (rt5645->i2c->irq) { ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING -- cgit v1.1 From 75945896a2f4a7ebfc3402443f99ac32f629ee96 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 9 Dec 2014 10:14:45 +0800 Subject: ASoC: rt5645: Fix potential crash in jd function If no one defined the rt5645->pdata.hp_det_gpio in coreboot/bios. It will cause kernel to reboot because rt5645->pdata.hp_det_gpio is 0. So it is worth to add a check in rt5645_jack_detect. Signed-off-by: Bard Liao Signed-off-by: Fang, Yang A Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc/codecs/rt5645.c') diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index d16331e..c901ef6 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2113,6 +2113,10 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int gpio_state, jack_type = 0; unsigned int val; + if (!gpio_is_valid(rt5645->pdata.hp_det_gpio)) { + dev_err(codec->dev, "invalid gpio\n"); + return -EINVAL; + } gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio, -- cgit v1.1