diff --git a/sound/soc/rockchip/rockchip_rt5651_tc358749x.c b/sound/soc/rockchip/rockchip_rt5651_tc358749x.c
index 21f8ee2..14acebd 100644
--- a/sound/soc/rockchip/rockchip_rt5651_tc358749x.c
+++ b/sound/soc/rockchip/rockchip_rt5651_tc358749x.c
@@ -18,12 +18,18 @@
#include
#include
+#include
+#include
+#include
+
#include "rockchip_i2s.h"
#include "../codecs/rt5651.h"
#include "../codecs/tc358749x.h"
#define DRV_NAME "rk3399-rt5651-tc358749x"
+#define INVALID_GPIO -1
+
static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_SPK("Lineout", NULL),
@@ -184,11 +190,58 @@ static struct snd_soc_card rockchip_sound_card = {
.num_controls = ARRAY_SIZE(rockchip_controls),
};
+static irqreturn_t rt5651_irq_handler(int irq, void *data)
+{
+struct snd_soc_card *card = data;
+queue_delayed_work(system_power_efficient_wq, &card->work,
+ msecs_to_jiffies(card->debounce_time));
+
+return IRQ_HANDLED;
+}
+
+static void rt5651_enable_spk(struct snd_soc_card *card, bool enable)
+{
+bool level;
+
+level = enable ? card->spk_active_level : !card->spk_active_level;
+gpio_set_value(card->spk_ctl_gpio, level);
+}
+
+static void hp_work(struct work_struct *work)
+{
+struct snd_soc_card *card;
+int enable;
+
+card = container_of(work, struct snd_soc_card, work.work);
+enable = gpio_get_value(card->hp_det_gpio);
+if(card->hp_det_invert)
+enable = !enable;
+
+card->hp_inserted = enable ? true : false;
+if(card->hp_inserted){
+//printk("hp_work rt5651_enable_spk falsen");
+rt5651_enable_spk(card, false);
+}else {
+//printk("hp_work rt5651_enable_spk truen");
+rt5651_enable_spk(card,true);
+}
+}
+
static int rockchip_sound_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &rockchip_sound_card;
struct device_node *cpu_node;
-int i, ret;
+int i;
+int ret = -1;
+
+int hp_irq;
+enum of_gpio_flags flags;
+
+card->debounce_time = 200;
+card->hp_det_invert = 0;
+card->hp_inserted = false;
+card->spk_ctl_gpio = INVALID_GPIO;
+card->hp_det_gpio = INVALID_GPIO;
dev_info(&pdev->dev, "%sn", __func__);
@@ -213,6 +266,47 @@ static int rockchip_sound_probe(struct platform_device *pdev)
}
}
+card->spk_ctl_gpio = of_get_named_gpio_flags(pdev->dev.of_node, "spk-con-gpio", 0, &flags);
+if(!gpio_is_valid(card->spk_ctl_gpio)){
+dev_err(&pdev->dev,"spk-ctl-gpio: %d is invalidn", card->spk_ctl_gpio);
+card->spk_ctl_gpio = INVALID_GPIO;
+}else {
+dev_info(&pdev->dev,"spk-ctl-gpio: %d is arrivablen", card->spk_ctl_gpio);
+card->spk_active_level = !(flags & OF_GPIO_ACTIVE_LOW);
+ret = devm_gpio_request_one(&pdev->dev, card->spk_ctl_gpio,
+GPIOF_DIR_OUT,NULL);
+if(ret) {
+dev_err(&pdev->dev,"spk_ctl_gpio: request failed!n");
+}
+rt5651_enable_spk(card, true);
+}
+
+card->hp_det_gpio = of_get_named_gpio_flags(pdev->dev.of_node,"hp-det-gpio", 0, &flags);
+if(!gpio_is_valid(card->hp_det_gpio)) {
+printk("hp-det-gpio: %d is invalidn",card->hp_det_gpio);
+card->hp_det_gpio = INVALID_GPIO;
+}else {
+INIT_DELAYED_WORK(&card->work, hp_work);
+card->hp_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW);
+ret = devm_gpio_request_one (&pdev->dev, card->hp_det_gpio,GPIOF_IN,"hp det");
+if( ret < 0)
+return ret;
+hp_irq = gpio_to_irq(card->hp_det_gpio);
+ret = devm_request_threaded_irq(&pdev->dev, hp_irq, NULL,
+rt5651_irq_handler,
+IRQF_TRIGGER_FALLING |
+IRQF_TRIGGER_RISING |
+IRQF_ONESHOT,
+"rt5651_interrupt", card);
+if( ret < 0) {
+dev_err(&pdev->dev, "request_irq: failed %dn", ret);
+return ret;
+}
+
+schedule_delayed_work(&card->work,
+msecs_to_jiffies(card->debounce_time));
+}
+
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
ret = devm_snd_soc_register_card(&pdev->dev, card);