diff options
Diffstat (limited to 'sound/soc/codecs/rt5645.c')
-rw-r--r-- | sound/soc/codecs/rt5645.c | 97 |
1 files changed, 69 insertions, 28 deletions
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 87844a45886a..9ec58166f7c4 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -34,6 +34,17 @@ | |||
34 | #include "rl6231.h" | 34 | #include "rl6231.h" |
35 | #include "rt5645.h" | 35 | #include "rt5645.h" |
36 | 36 | ||
37 | #define QUIRK_INV_JD1_1(q) ((q) & 1) | ||
38 | #define QUIRK_LEVEL_IRQ(q) (((q) >> 1) & 1) | ||
39 | #define QUIRK_IN2_DIFF(q) (((q) >> 2) & 1) | ||
40 | #define QUIRK_JD_MODE(q) (((q) >> 4) & 7) | ||
41 | #define QUIRK_DMIC1_DATA_PIN(q) (((q) >> 8) & 3) | ||
42 | #define QUIRK_DMIC2_DATA_PIN(q) (((q) >> 12) & 3) | ||
43 | |||
44 | static unsigned int quirk = -1; | ||
45 | module_param(quirk, uint, 0444); | ||
46 | MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override"); | ||
47 | |||
37 | #define RT5645_DEVICE_ID 0x6308 | 48 | #define RT5645_DEVICE_ID 0x6308 |
38 | #define RT5650_DEVICE_ID 0x6419 | 49 | #define RT5650_DEVICE_ID 0x6419 |
39 | 50 | ||
@@ -59,7 +70,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = { | |||
59 | 70 | ||
60 | static const struct reg_sequence init_list[] = { | 71 | static const struct reg_sequence init_list[] = { |
61 | {RT5645_PR_BASE + 0x3d, 0x3600}, | 72 | {RT5645_PR_BASE + 0x3d, 0x3600}, |
62 | {RT5645_PR_BASE + 0x1c, 0xfd20}, | 73 | {RT5645_PR_BASE + 0x1c, 0xfd70}, |
63 | {RT5645_PR_BASE + 0x20, 0x611f}, | 74 | {RT5645_PR_BASE + 0x20, 0x611f}, |
64 | {RT5645_PR_BASE + 0x21, 0x4040}, | 75 | {RT5645_PR_BASE + 0x21, 0x4040}, |
65 | {RT5645_PR_BASE + 0x23, 0x0004}, | 76 | {RT5645_PR_BASE + 0x23, 0x0004}, |
@@ -3151,7 +3162,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
3151 | snd_soc_dapm_sync(dapm); | 3162 | snd_soc_dapm_sync(dapm); |
3152 | rt5645->jack_type = SND_JACK_HEADPHONE; | 3163 | rt5645->jack_type = SND_JACK_HEADPHONE; |
3153 | } | 3164 | } |
3154 | if (rt5645->pdata.jd_invert) | 3165 | if (rt5645->pdata.level_trigger_irq) |
3155 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3166 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
3156 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR); | 3167 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR); |
3157 | } else { /* jack out */ | 3168 | } else { /* jack out */ |
@@ -3172,7 +3183,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
3172 | snd_soc_dapm_disable_pin(dapm, "LDO2"); | 3183 | snd_soc_dapm_disable_pin(dapm, "LDO2"); |
3173 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); | 3184 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); |
3174 | snd_soc_dapm_sync(dapm); | 3185 | snd_soc_dapm_sync(dapm); |
3175 | if (rt5645->pdata.jd_invert) | 3186 | if (rt5645->pdata.level_trigger_irq) |
3176 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3187 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
3177 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); | 3188 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); |
3178 | } | 3189 | } |
@@ -3238,24 +3249,16 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
3238 | snd_soc_jack_report(rt5645->mic_jack, | 3249 | snd_soc_jack_report(rt5645->mic_jack, |
3239 | report, SND_JACK_MICROPHONE); | 3250 | report, SND_JACK_MICROPHONE); |
3240 | return; | 3251 | return; |
3241 | case 1: /* 2 port */ | 3252 | default: /* read rt5645 jd1_1 status */ |
3242 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070; | 3253 | val = snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x1000; |
3243 | break; | ||
3244 | default: /* 1 port */ | ||
3245 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0020; | ||
3246 | break; | 3254 | break; |
3247 | 3255 | ||
3248 | } | 3256 | } |
3249 | 3257 | ||
3250 | switch (val) { | 3258 | if (!val && (rt5645->jack_type == 0)) { /* jack in */ |
3251 | /* jack in */ | 3259 | report = rt5645_jack_detect(rt5645->codec, 1); |
3252 | case 0x30: /* 2 port */ | 3260 | } else if (!val && rt5645->jack_type != 0) { |
3253 | case 0x0: /* 1 port or 2 port */ | 3261 | /* for push button and jack out */ |
3254 | if (rt5645->jack_type == 0) { | ||
3255 | report = rt5645_jack_detect(rt5645->codec, 1); | ||
3256 | /* for push button and jack out */ | ||
3257 | break; | ||
3258 | } | ||
3259 | btn_type = 0; | 3262 | btn_type = 0; |
3260 | if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) { | 3263 | if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) { |
3261 | /* button pressed */ | 3264 | /* button pressed */ |
@@ -3302,19 +3305,12 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
3302 | mod_timer(&rt5645->btn_check_timer, | 3305 | mod_timer(&rt5645->btn_check_timer, |
3303 | msecs_to_jiffies(100)); | 3306 | msecs_to_jiffies(100)); |
3304 | } | 3307 | } |
3305 | 3308 | } else { | |
3306 | break; | 3309 | /* jack out */ |
3307 | /* jack out */ | ||
3308 | case 0x70: /* 2 port */ | ||
3309 | case 0x10: /* 2 port */ | ||
3310 | case 0x20: /* 1 port */ | ||
3311 | report = 0; | 3310 | report = 0; |
3312 | snd_soc_update_bits(rt5645->codec, | 3311 | snd_soc_update_bits(rt5645->codec, |
3313 | RT5645_INT_IRQ_ST, 0x1, 0x0); | 3312 | RT5645_INT_IRQ_ST, 0x1, 0x0); |
3314 | rt5645_jack_detect(rt5645->codec, 0); | 3313 | rt5645_jack_detect(rt5645->codec, 0); |
3315 | break; | ||
3316 | default: | ||
3317 | break; | ||
3318 | } | 3314 | } |
3319 | 3315 | ||
3320 | snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); | 3316 | snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); |
@@ -3601,7 +3597,7 @@ static struct rt5645_platform_data buddy_platform_data = { | |||
3601 | .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5, | 3597 | .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5, |
3602 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, | 3598 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, |
3603 | .jd_mode = 3, | 3599 | .jd_mode = 3, |
3604 | .jd_invert = true, | 3600 | .level_trigger_irq = true, |
3605 | }; | 3601 | }; |
3606 | 3602 | ||
3607 | static struct dmi_system_id dmi_platform_intel_broadwell[] = { | 3603 | static struct dmi_system_id dmi_platform_intel_broadwell[] = { |
@@ -3614,6 +3610,33 @@ static struct dmi_system_id dmi_platform_intel_broadwell[] = { | |||
3614 | { } | 3610 | { } |
3615 | }; | 3611 | }; |
3616 | 3612 | ||
3613 | static struct rt5645_platform_data gpd_win_platform_data = { | ||
3614 | .jd_mode = 3, | ||
3615 | .inv_jd1_1 = true, | ||
3616 | }; | ||
3617 | |||
3618 | static const struct dmi_system_id dmi_platform_gpd_win[] = { | ||
3619 | { | ||
3620 | /* | ||
3621 | * Match for the GPDwin which unfortunately uses somewhat | ||
3622 | * generic dmi strings, which is why we test for 4 strings. | ||
3623 | * Comparing against 23 other byt/cht boards, board_vendor | ||
3624 | * and board_name are unique to the GPDwin, where as only one | ||
3625 | * other board has the same board_serial and 3 others have | ||
3626 | * the same default product_name. Also the GPDwin is the | ||
3627 | * only device to have both board_ and product_name not set. | ||
3628 | */ | ||
3629 | .ident = "GPD Win", | ||
3630 | .matches = { | ||
3631 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | ||
3632 | DMI_MATCH(DMI_BOARD_NAME, "Default string"), | ||
3633 | DMI_MATCH(DMI_BOARD_SERIAL, "Default string"), | ||
3634 | DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), | ||
3635 | }, | ||
3636 | }, | ||
3637 | {} | ||
3638 | }; | ||
3639 | |||
3617 | static bool rt5645_check_dp(struct device *dev) | 3640 | static bool rt5645_check_dp(struct device *dev) |
3618 | { | 3641 | { |
3619 | if (device_property_present(dev, "realtek,in2-differential") || | 3642 | if (device_property_present(dev, "realtek,in2-differential") || |
@@ -3664,6 +3687,17 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3664 | rt5645_parse_dt(rt5645, &i2c->dev); | 3687 | rt5645_parse_dt(rt5645, &i2c->dev); |
3665 | else if (dmi_check_system(dmi_platform_intel_braswell)) | 3688 | else if (dmi_check_system(dmi_platform_intel_braswell)) |
3666 | rt5645->pdata = general_platform_data; | 3689 | rt5645->pdata = general_platform_data; |
3690 | else if (dmi_check_system(dmi_platform_gpd_win)) | ||
3691 | rt5645->pdata = gpd_win_platform_data; | ||
3692 | |||
3693 | if (quirk != -1) { | ||
3694 | rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk); | ||
3695 | rt5645->pdata.level_trigger_irq = QUIRK_LEVEL_IRQ(quirk); | ||
3696 | rt5645->pdata.inv_jd1_1 = QUIRK_INV_JD1_1(quirk); | ||
3697 | rt5645->pdata.jd_mode = QUIRK_JD_MODE(quirk); | ||
3698 | rt5645->pdata.dmic1_data_pin = QUIRK_DMIC1_DATA_PIN(quirk); | ||
3699 | rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk); | ||
3700 | } | ||
3667 | 3701 | ||
3668 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", | 3702 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", |
3669 | GPIOD_IN); | 3703 | GPIOD_IN); |
@@ -3745,6 +3779,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3745 | ret); | 3779 | ret); |
3746 | } | 3780 | } |
3747 | 3781 | ||
3782 | regmap_update_bits(rt5645->regmap, RT5645_CLSD_OUT_CTRL, 0xc0, 0xc0); | ||
3783 | |||
3748 | if (rt5645->pdata.in2_diff) | 3784 | if (rt5645->pdata.in2_diff) |
3749 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, | 3785 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, |
3750 | RT5645_IN_DF2, RT5645_IN_DF2); | 3786 | RT5645_IN_DF2, RT5645_IN_DF2); |
@@ -3848,12 +3884,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3848 | default: | 3884 | default: |
3849 | break; | 3885 | break; |
3850 | } | 3886 | } |
3887 | if (rt5645->pdata.inv_jd1_1) { | ||
3888 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | ||
3889 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); | ||
3890 | } | ||
3851 | } | 3891 | } |
3852 | 3892 | ||
3853 | regmap_update_bits(rt5645->regmap, RT5645_ADDA_CLK1, | 3893 | regmap_update_bits(rt5645->regmap, RT5645_ADDA_CLK1, |
3854 | RT5645_I2S_PD1_MASK, RT5645_I2S_PD1_2); | 3894 | RT5645_I2S_PD1_MASK, RT5645_I2S_PD1_2); |
3855 | 3895 | ||
3856 | if (rt5645->pdata.jd_invert) { | 3896 | if (rt5645->pdata.level_trigger_irq) { |
3857 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3897 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
3858 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); | 3898 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); |
3859 | } | 3899 | } |
@@ -3897,6 +3937,7 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) | |||
3897 | 3937 | ||
3898 | cancel_delayed_work_sync(&rt5645->jack_detect_work); | 3938 | cancel_delayed_work_sync(&rt5645->jack_detect_work); |
3899 | cancel_delayed_work_sync(&rt5645->rcclock_work); | 3939 | cancel_delayed_work_sync(&rt5645->rcclock_work); |
3940 | del_timer_sync(&rt5645->btn_check_timer); | ||
3900 | 3941 | ||
3901 | snd_soc_unregister_codec(&i2c->dev); | 3942 | snd_soc_unregister_codec(&i2c->dev); |
3902 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); | 3943 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); |