diff options
Diffstat (limited to 'drivers/staging/intel_sst/intelmid_v1_control.c')
-rw-r--r-- | drivers/staging/intel_sst/intelmid_v1_control.c | 142 |
1 files changed, 131 insertions, 11 deletions
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c index 3392f08..05467ca 100644 --- a/drivers/staging/intel_sst/intelmid_v1_control.c +++ b/drivers/staging/intel_sst/intelmid_v1_control.c @@ -31,7 +31,6 @@ #include <linux/file.h> #include <asm/mrst.h> #include <sound/pcm.h> -#include "jack.h" #include <sound/pcm_params.h> #include <sound/control.h> #include <sound/initval.h> @@ -584,10 +583,6 @@ static int mx_set_selected_input_dev(u8 dev_id) } return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg); } -static int mx_set_selected_lineout_dev(u8 dev_id) -{ - return 0; -} static int mx_set_mute(int dev_id, u8 value) { @@ -835,10 +830,132 @@ static int mx_get_vol(int dev_id, int *value) return retval; } +static u8 mx_get_jack_status(void) +{ + struct sc_reg_access sc_access_read = {0,}; + + sc_access_read.reg_addr = 0x201; + sst_sc_reg_access(&sc_access_read, PMIC_READ, 1); + pr_debug("value returned = 0x%x\n", sc_access_read.value); + return sc_access_read.value; +} + +static void mx_pmic_irq_enable(void *data) +{ + struct snd_intelmad *intelmaddata = data; + + intelmaddata->jack_prev_state = 0xc0; + return; +} + +static void mx_pmic_irq_cb(void *cb_data, u8 intsts) +{ + u8 jack_cur_status, jack_prev_state = 0; + struct mad_jack *mjack = NULL; + unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0; + time_t timediff; + struct snd_intelmad *intelmaddata = cb_data; + + mjack = &intelmaddata->jack[0]; + if (intsts & 0x2) { + jack_cur_status = mx_get_jack_status(); + jack_prev_state = intelmaddata->jack_prev_state; + if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x40)) { + /*headset insert detected. */ + pr_debug("MAD headset inserted\n"); + present = 1; + jack_event_flag = 1; + mjack->jack_status = 1; + mjack->jack.type = SND_JACK_HEADSET; + } + + if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x00)) { + /* headphone insert detected. */ + pr_debug("MAD headphone inserted\n"); + present = 1; + jack_event_flag = 1; + mjack->jack.type = SND_JACK_HEADPHONE; + } + + if ((jack_prev_state == 0x40) && (jack_cur_status == 0xc0)) { + /* headset remove detected. */ + pr_debug("MAD headset removed\n"); + + present = 0; + jack_event_flag = 1; + mjack->jack_status = 0; + mjack->jack.type = SND_JACK_HEADSET; + } + + if ((jack_prev_state == 0x00) && (jack_cur_status == 0xc0)) { + /* headphone remove detected. */ + pr_debug("MAD headphone removed\n"); + present = 0; + jack_event_flag = 1; + mjack->jack.type = SND_JACK_HEADPHONE; + } + + if ((jack_prev_state == 0x40) && (jack_cur_status == 0x00)) { + /* button pressed */ + do_gettimeofday(&mjack->buttonpressed); + pr_debug("MAD button press detected\n"); + } + + if ((jack_prev_state == 0x00) && (jack_cur_status == 0x40)) { + if (mjack->jack_status) { + /*button pressed */ + do_gettimeofday( + &mjack->buttonreleased); + /*button pressed */ + pr_debug("MAD Button Released detected\n"); + timediff = mjack->buttonreleased.tv_sec - + mjack->buttonpressed.tv_sec; + buttonpressflag = 1; + + if (timediff > 1) { + pr_debug("MAD long press dtd\n"); + /* send headphone detect/undetect */ + present = 1; + jack_event_flag = 1; + mjack->jack.type = + MID_JACK_HS_LONG_PRESS; + } else { + pr_debug("MAD short press dtd\n"); + /* send headphone detect/undetect */ + present = 1; + jack_event_flag = 1; + mjack->jack.type = + MID_JACK_HS_SHORT_PRESS; + } + } else { + /***workaround for maxim + hw issue,0x00 t 0x40 is not + a valid transiton for Headset insertion */ + /*headset insert detected. */ + pr_debug("MAD headset inserted\n"); + present = 1; + jack_event_flag = 1; + mjack->jack_status = 1; + mjack->jack.type = SND_JACK_HEADSET; + } + } + intelmaddata->jack_prev_state = jack_cur_status; + pr_debug("mx_pmic_irq_cb prv_state= 0x%x\n", + intelmaddata->jack_prev_state); + } + + if (jack_event_flag) + sst_mad_send_jack_report(&mjack->jack, + buttonpressflag, present); +} +static int mx_jack_enable(void) +{ + return 0; +} + struct snd_pmic_ops snd_pmic_ops_mx = { .set_input_dev = mx_set_selected_input_dev, .set_output_dev = mx_set_selected_output_dev, - .set_lineout_dev = mx_set_selected_lineout_dev, .set_mute = mx_set_mute, .get_mute = mx_get_mute, .set_vol = mx_set_vol, @@ -848,10 +965,13 @@ struct snd_pmic_ops snd_pmic_ops_mx = { .set_pcm_voice_params = mx_set_pcm_voice_params, .set_voice_port = mx_set_voice_port, .set_audio_port = mx_set_audio_port, - .power_up_pmic_pb = mx_power_up_pb, - .power_up_pmic_cp = mx_power_up_cp, - .power_down_pmic_pb = mx_power_down_pb, - .power_down_pmic_cp = mx_power_down_cp, - .power_down_pmic = mx_power_down, + .power_up_pmic_pb = mx_power_up_pb, + .power_up_pmic_cp = mx_power_up_cp, + .power_down_pmic_pb = mx_power_down_pb, + .power_down_pmic_cp = mx_power_down_cp, + .power_down_pmic = mx_power_down, + .pmic_irq_cb = mx_pmic_irq_cb, + .pmic_irq_enable = mx_pmic_irq_enable, + .pmic_jack_enable = mx_jack_enable, }; |