lkml.org 
[lkml]   [2011]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[022/104] ALSA: hda - Fix jack-detection control of VT1708
    3.1-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Takashi Iwai <tiwai@suse.de>

    commit 187d333edc0a8e1bb507900ce89853ffe3bd2c84 upstream.

    VT1708 has no support for unsolicited events per jack-plug, the driver
    implements the workq for polling the jack-detection. The mixer element
    "Jack Detect" was supposed to control this behavior on/off, but this
    doesn't work properly as is now. The workq is always started and the
    HP automute is always enabled.

    This patch fixes the jack-detect control behavior by triggering / stopping
    the work appropriately at the state change. Also the work checks the
    internal state to continue scheduling or not.

    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    sound/pci/hda/patch_via.c | 76 ++++++++++++++++++++++++++--------------------
    1 file changed, 43 insertions(+), 33 deletions(-)

    --- a/sound/pci/hda/patch_via.c
    +++ b/sound/pci/hda/patch_via.c
    @@ -207,6 +207,7 @@ struct via_spec {
    /* work to check hp jack state */
    struct hda_codec *codec;
    struct delayed_work vt1708_hp_work;
    + int hp_work_active;
    int vt1708_jack_detect;
    int vt1708_hp_present;

    @@ -304,27 +305,35 @@ enum {
    static void analog_low_current_mode(struct hda_codec *codec);
    static bool is_aa_path_mute(struct hda_codec *codec);

    -static void vt1708_start_hp_work(struct via_spec *spec)
    +#define hp_detect_with_aa(codec) \
    + (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
    + !is_aa_path_mute(codec))
    +
    +static void vt1708_stop_hp_work(struct via_spec *spec)
    {
    if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
    return;
    - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
    - !spec->vt1708_jack_detect);
    - if (!delayed_work_pending(&spec->vt1708_hp_work))
    - schedule_delayed_work(&spec->vt1708_hp_work,
    - msecs_to_jiffies(100));
    + if (spec->hp_work_active) {
    + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1);
    + cancel_delayed_work_sync(&spec->vt1708_hp_work);
    + spec->hp_work_active = 0;
    + }
    }

    -static void vt1708_stop_hp_work(struct via_spec *spec)
    +static void vt1708_update_hp_work(struct via_spec *spec)
    {
    if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
    return;
    - if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1
    - && !is_aa_path_mute(spec->codec))
    - return;
    - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
    - !spec->vt1708_jack_detect);
    - cancel_delayed_work_sync(&spec->vt1708_hp_work);
    + if (spec->vt1708_jack_detect &&
    + (spec->active_streams || hp_detect_with_aa(spec->codec))) {
    + if (!spec->hp_work_active) {
    + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0);
    + schedule_delayed_work(&spec->vt1708_hp_work,
    + msecs_to_jiffies(100));
    + spec->hp_work_active = 1;
    + }
    + } else if (!hp_detect_with_aa(spec->codec))
    + vt1708_stop_hp_work(spec);
    }

    static void set_widgets_power_state(struct hda_codec *codec)
    @@ -342,12 +351,7 @@ static int analog_input_switch_put(struc

    set_widgets_power_state(codec);
    analog_low_current_mode(snd_kcontrol_chip(kcontrol));
    - if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
    - if (is_aa_path_mute(codec))
    - vt1708_start_hp_work(codec->spec);
    - else
    - vt1708_stop_hp_work(codec->spec);
    - }
    + vt1708_update_hp_work(codec->spec);
    return change;
    }

    @@ -1153,7 +1157,7 @@ static int via_playback_multi_pcm_prepar
    spec->cur_dac_stream_tag = stream_tag;
    spec->cur_dac_format = format;
    mutex_unlock(&spec->config_mutex);
    - vt1708_start_hp_work(spec);
    + vt1708_update_hp_work(spec);
    return 0;
    }

    @@ -1173,7 +1177,7 @@ static int via_playback_hp_pcm_prepare(s
    spec->cur_hp_stream_tag = stream_tag;
    spec->cur_hp_format = format;
    mutex_unlock(&spec->config_mutex);
    - vt1708_start_hp_work(spec);
    + vt1708_update_hp_work(spec);
    return 0;
    }

    @@ -1187,7 +1191,7 @@ static int via_playback_multi_pcm_cleanu
    snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
    spec->active_streams &= ~STREAM_MULTI_OUT;
    mutex_unlock(&spec->config_mutex);
    - vt1708_stop_hp_work(spec);
    + vt1708_update_hp_work(spec);
    return 0;
    }

    @@ -1202,7 +1206,7 @@ static int via_playback_hp_pcm_cleanup(s
    snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0);
    spec->active_streams &= ~STREAM_INDEP_HP;
    mutex_unlock(&spec->config_mutex);
    - vt1708_stop_hp_work(spec);
    + vt1708_update_hp_work(spec);
    return 0;
    }

    @@ -1632,7 +1636,8 @@ static void via_hp_automute(struct hda_c
    int nums;
    struct via_spec *spec = codec->spec;

    - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0])
    + if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] &&
    + (spec->codec_type != VT1708 || spec->vt1708_jack_detect))
    present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);

    if (spec->smart51_enabled)
    @@ -2599,8 +2604,6 @@ static int vt1708_jack_detect_get(struct

    if (spec->codec_type != VT1708)
    return 0;
    - spec->vt1708_jack_detect =
    - !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
    ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
    return 0;
    }
    @@ -2610,18 +2613,22 @@ static int vt1708_jack_detect_put(struct
    {
    struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
    struct via_spec *spec = codec->spec;
    - int change;
    + int val;

    if (spec->codec_type != VT1708)
    return 0;
    - spec->vt1708_jack_detect = ucontrol->value.integer.value[0];
    - change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
    - == !spec->vt1708_jack_detect;
    - if (spec->vt1708_jack_detect) {
    + val = !!ucontrol->value.integer.value[0];
    + if (spec->vt1708_jack_detect == val)
    + return 0;
    + spec->vt1708_jack_detect = val;
    + if (spec->vt1708_jack_detect &&
    + snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) {
    mute_aa_path(codec, 1);
    notify_aa_path_ctls(codec);
    }
    - return change;
    + via_hp_automute(codec);
    + vt1708_update_hp_work(spec);
    + return 1;
    }

    static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
    @@ -2758,6 +2765,7 @@ static int via_init(struct hda_codec *co
    via_auto_init_unsol_event(codec);

    via_hp_automute(codec);
    + vt1708_update_hp_work(spec);

    return 0;
    }
    @@ -2774,7 +2782,9 @@ static void vt1708_update_hp_jack_state(
    spec->vt1708_hp_present ^= 1;
    via_hp_automute(spec->codec);
    }
    - vt1708_start_hp_work(spec);
    + if (spec->vt1708_jack_detect)
    + schedule_delayed_work(&spec->vt1708_hp_work,
    + msecs_to_jiffies(100));
    }

    static int get_mux_nids(struct hda_codec *codec)



    \
     
     \ /
      Last update: 2011-12-07 17:37    [W:0.029 / U:180.668 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site