+static int rt5640_hp_jack_change(struct notifier_block *nb,
+ unsigned long flags, void *data)
+{
+ return NOTIFY_OK;
+}
+
+static struct notifier_block rt5640_hp_jack_nb = {
+ .notifier_call = rt5640_hp_jack_change,
+};
+
+static void rt5640_jack_init(struct rt5640_priv *rt5640)
+{
+ snd_soc_card_jack_new(rt5640->codec->component.card,
+ "Headphone Jack", SND_JACK_HEADPHONE,
+ &rt5640->hp_jack, NULL, 0);
+ snd_soc_jack_notifier_register(&rt5640->hp_jack, &rt5640_hp_jack_nb);
+}
+
+static int rt5640_hp_adc_iio_read(struct rt5640_priv *rt5640)
+{
+ struct iio_channel *channel = rt5640->chan;
+ int val, ret;
+
+ if (!channel)
+ return RT5640_ADC_INVALID_ADVALUE;
+ ret = iio_read_channel_raw(channel, &val);
+ if (ret < 0) {
+ dev_err(rt5640->codec->dev,
+ "read hp_det channel() error: %d\n", ret);
+ return ret;
+ }
+ return val;
+}
+
+static void rt5640_hp_adc_poll(struct work_struct *work)
+{
+ struct rt5640_priv *rt5640;
+ int result = -1;
+
+ rt5640 = container_of(work, struct rt5640_priv, adc_poll_work.work);
+ result = rt5640_hp_adc_iio_read(rt5640);
+ if (result > RT5640_ADC_INVALID_ADVALUE &&
+ result < RT5640_ADC_EMPTY_ADVALUE) {
+ if (result < rt5640->hp_det_adc_value + RT5640_ADC_DRIFT_ADVALUE &&
+ result > rt5640->hp_det_adc_value - RT5640_ADC_DRIFT_ADVALUE){
+ if (!rt5640->hp_insert) {
+ dev_dbg(rt5640->codec->dev,
+ "headphone insert,adc=%d\n", result);
+ rt5640->hp_insert = true;
+ snd_soc_jack_report(&rt5640->hp_jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADPHONE);
+ if (!rt5640->hp_mute)
+ rt5640_hp_gpio_ctrl(rt5640, true);
+ }
+ } else{
+ if (rt5640->hp_insert) {
+ dev_dbg(rt5640->codec->dev,
+ "headphone not insert,adc=%d\n", result);
+ rt5640->hp_insert = false;
+ rt5640_hp_gpio_ctrl(rt5640, false);
+ snd_soc_jack_report(&rt5640->hp_jack, 0,
+ SND_JACK_HEADPHONE);
+ }
+ }
+ }
+
+ schedule_delayed_work(&rt5640->adc_poll_work,
+ RT5640_ADC_SAMPLE_JIFFIES);
+}
+