diff options
Diffstat (limited to 'sound/soc/codecs/rt5682-i2c.c')
-rw-r--r-- | sound/soc/codecs/rt5682-i2c.c | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 85aba311bdc8..62f26ce9d476 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -11,13 +11,11 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> -#include <linux/pm_runtime.h> #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/acpi.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/mutex.h> #include <sound/core.h> #include <sound/pcm.h> @@ -47,7 +45,7 @@ static const struct regmap_config rt5682_regmap = { .max_register = RT5682_I2C_MODE, .volatile_reg = rt5682_volatile_register, .readable_reg = rt5682_readable_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = rt5682_reg, .num_reg_defaults = RT5682_REG_NUM, .use_single_read = true, @@ -59,18 +57,12 @@ static void rt5682_jd_check_handler(struct work_struct *work) struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, jd_check_work.work); - if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) - & RT5682_JDH_RS_MASK) { + if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK) /* jack out */ - rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); - - snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, - SND_JACK_HEADSET | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3); - } else { + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, 0); + else schedule_delayed_work(&rt5682->jd_check_work, 500); - } } static irqreturn_t rt5682_irq(int irq, void *data) @@ -78,7 +70,7 @@ static irqreturn_t rt5682_irq(int irq, void *data) struct rt5682_priv *rt5682 = data; mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); + &rt5682->jack_detect_work, msecs_to_jiffies(rt5682->irq_work_delay_time)); return IRQ_HANDLED; } @@ -117,8 +109,14 @@ static struct snd_soc_dai_driver rt5682_dai[] = { }, }; -static int rt5682_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static void rt5682_i2c_disable_regulators(void *data) +{ + struct rt5682_priv *rt5682 = data; + + regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies); +} + +static int rt5682_i2c_probe(struct i2c_client *i2c) { struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5682_priv *rt5682; @@ -132,6 +130,8 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, rt5682); + rt5682->i2c_dev = &i2c->dev; + rt5682->pdata = i2s_default_platform_data; if (pdata) @@ -164,11 +164,14 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, return ret; } - if (gpio_is_valid(rt5682->pdata.ldo1_en)) { - if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en, - GPIOF_OUT_INIT_HIGH, "rt5682")) - dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); - } + ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators, + rt5682); + if (ret) + return ret; + + ret = rt5682_get_ldo1(rt5682, &i2c->dev); + if (ret) + return ret; /* Sleep for 300 ms miniumum */ usleep_range(300000, 350000); @@ -221,6 +224,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK); + if (rt5682->pdata.dmic_clk_driving_high) + regmap_update_bits(rt5682->regmap, + RT5682_PAD_DRIVING_CTRL, + RT5682_PAD_DRV_GP3_MASK, + 2 << RT5682_PAD_DRV_GP3_SFT); break; default: @@ -255,10 +263,27 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "rt5682", rt5682); - if (ret) - dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); + if (!ret) + rt5682->irq = i2c->irq; + else + dev_err(&i2c->dev, "Failed to request IRQ: %d\n", ret); } +#ifdef CONFIG_COMMON_CLK + /* Check if MCLK provided */ + rt5682->mclk = devm_clk_get_optional(&i2c->dev, "mclk"); + if (IS_ERR(rt5682->mclk)) + return PTR_ERR(rt5682->mclk); + + /* Register CCF DAI clock control */ + ret = rt5682_register_dai_clks(rt5682); + if (ret) + return ret; + + /* Initial setup for CCF */ + rt5682->lrck[RT5682_AIF1] = 48000; +#endif + return devm_snd_soc_register_component(&i2c->dev, &rt5682_soc_component_dev, rt5682_dai, ARRAY_SIZE(rt5682_dai)); @@ -268,9 +293,18 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) { struct rt5682_priv *rt5682 = i2c_get_clientdata(client); + disable_irq(client->irq); + cancel_delayed_work_sync(&rt5682->jack_detect_work); + cancel_delayed_work_sync(&rt5682->jd_check_work); + rt5682_reset(rt5682); } +static void rt5682_i2c_remove(struct i2c_client *client) +{ + rt5682_i2c_shutdown(client); +} + static const struct of_device_id rt5682_of_match[] = { {.compatible = "realtek,rt5682i"}, {}, @@ -294,8 +328,10 @@ static struct i2c_driver rt5682_i2c_driver = { .name = "rt5682", .of_match_table = rt5682_of_match, .acpi_match_table = rt5682_acpi_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = rt5682_i2c_probe, + .remove = rt5682_i2c_remove, .shutdown = rt5682_i2c_shutdown, .id_table = rt5682_i2c_id, }; |