diff --git a/sound/soc/codecs/fsa8500.c b/sound/soc/codecs/fsa8500.c index d4649203644a0878f04ecd21bb0c911bab7eb95e..5ace17da1d8b7433be1b0eed2035bcd443b1f3ae 100644 --- a/sound/soc/codecs/fsa8500.c +++ b/sound/soc/codecs/fsa8500.c @@ -46,7 +46,7 @@ #define NAME "fsa8500" -#define I2C_RETRY_DELAY 5 /* ms */ +#define I2C_RETRY_DELAY 20 /* ms */ #define I2C_RETRIES 5 #define FSA8500_JACK_MASK (SND_JACK_HEADSET | SND_JACK_HEADPHONE| \ @@ -79,7 +79,7 @@ struct fsa8500_data { int button_detect_state; struct mutex lock; struct wake_lock wake_lock; - struct work_struct work_det; + struct delayed_work work_det; struct workqueue_struct *wq; }; @@ -416,9 +416,13 @@ EXPORT_SYMBOL_GPL(fsa8500_mic_event); static int fsa8500_update_device_status(struct fsa8500_data *fsa8500) { + int err; - fsa8500_i2c_read(fsa8500, FSA8500_INT_REG1, + err = fsa8500_i2c_read(fsa8500, FSA8500_INT_REG1, fsa8500->irq_status, sizeof(fsa8500->irq_status)); + if (err == -EIO) + return err; + pr_debug("%s: regs 0x%x,0x%x,0x%x,0x%x,0x%x\n", __func__, fsa8500->irq_status[0], fsa8500->irq_status[1], fsa8500->irq_status[2], fsa8500->irq_status[3], @@ -508,7 +512,10 @@ static int fsa8500_report_hs(struct fsa8500_data *fsa8500) snd_soc_jack_report_no_dapm(fsa8500->button_jack, status<<SND_JACK_BTN_SHIFT, status<<SND_JACK_BTN_SHIFT); - + /* The framework can ignore events if they came + to close to each other. Add small delay between + press and release events */ + usleep(10000); snd_soc_jack_report_no_dapm(fsa8500->button_jack, 0, status<<SND_JACK_BTN_SHIFT); } @@ -614,7 +621,7 @@ static irqreturn_t fsa8500_irq_handler(int irq, void *data) struct fsa8500_data *irq_data = data; wake_lock_timeout(&irq_data->wake_lock, HZ); - queue_work(irq_data->wq, &irq_data->work_det); + queue_work(irq_data->wq, &irq_data->work_det.work); return IRQ_HANDLED; } @@ -627,7 +634,9 @@ static void fsa8500_det_thread(struct work_struct *work) mutex_lock(&irq_data->lock); wake_lock(&irq_data->wake_lock); - fsa8500_update_device_status(irq_data); + if (fsa8500_update_device_status(irq_data)) + queue_delayed_work(irq_data->wq, &irq_data->work_det, + msecs_to_jiffies(2000)); fsa8500_report_hs(irq_data); wake_unlock(&irq_data->wake_lock); @@ -828,7 +837,7 @@ static int fsa8500_probe(struct i2c_client *client, goto wq_fail; } - INIT_WORK(&fsa8500->work_det, fsa8500_det_thread); + INIT_DELAYED_WORK(&fsa8500->work_det, fsa8500_det_thread); fsa8500->gpio_irq = gpio_to_irq(fsa8500->gpio); /* active low interrupt */