Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 284203
b: refs/heads/master
c: 1835a0f
h: refs/heads/master
i:
  284201: d2e33b6
  284199: 421bf3e
v: v3
  • Loading branch information
Takashi Iwai committed Nov 16, 2011
1 parent c71a5e8 commit a2c73c2
Show file tree
Hide file tree
Showing 14 changed files with 285 additions and 118 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 04f5ade6afc4326dc6cd10d235500972fba548eb
refs/heads/master: 1835a0f9a2121ce3198dab67507d4d3e960cc09e
2 changes: 1 addition & 1 deletion trunk/sound/pci/hda/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
snd-hda-intel-objs := hda_intel.o

snd-hda-codec-y := hda_codec.o
snd-hda-codec-y := hda_codec.o hda_jack.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
Expand Down
40 changes: 3 additions & 37 deletions trunk/sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <sound/jack.h>
#include "hda_local.h"
#include "hda_beep.h"
#include "hda_jack.h"
#include <sound/hda_hwdep.h>

#define CREATE_TRACE_POINTS
Expand Down Expand Up @@ -1723,43 +1724,6 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
}
EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);

/**
* snd_hda_pin_sense - execute pin sense measurement
* @codec: the CODEC to sense
* @nid: the pin NID to sense
*
* Execute necessary pin sense measurement and return its Presence Detect,
* Impedance, ELD Valid etc. status bits.
*/
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
{
u32 pincap;

if (!codec->no_trigger_sense) {
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
snd_hda_codec_read(codec, nid, 0,
AC_VERB_SET_PIN_SENSE, 0);
}
return snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
}
EXPORT_SYMBOL_HDA(snd_hda_pin_sense);

/**
* snd_hda_jack_detect - query pin Presence Detect status
* @codec: the CODEC to sense
* @nid: the pin NID to sense
*
* Query and return the pin's Presence Detect status.
*/
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
{
u32 sense = snd_hda_pin_sense(codec, nid);
return !!(sense & AC_PINSENSE_PRESENCE);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect);

/*
* read the current volume to info
* if the cache exists, read the cache value.
Expand Down Expand Up @@ -2308,6 +2272,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
}
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
snd_hda_jack_tbl_clear(codec);
codec->proc_widget_hook = NULL;
codec->spec = NULL;
free_hda_cache(&codec->amp_cache);
Expand Down Expand Up @@ -3364,6 +3329,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
restore_pincfgs(codec); /* restore all current pin configs */
restore_shutup_pins(codec);
hda_exec_init_verbs(codec);
snd_hda_jack_set_dirty_all(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
Expand Down
3 changes: 3 additions & 0 deletions trunk/sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,9 @@ struct hda_codec {
void (*proc_widget_hook)(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid);

/* jack detection */
struct snd_array jacktbl;

#ifdef CONFIG_SND_HDA_INPUT_JACK
/* jack detection */
struct snd_array jacks;
Expand Down
148 changes: 148 additions & 0 deletions trunk/sound/pci/hda/hda_jack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Jack-detection handling for HD-audio
*
* Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#include <linux/init.h>
#include <linux/slab.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_jack.h"

/* execute pin sense measurement */
static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
{
u32 pincap;

if (!codec->no_trigger_sense) {
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
snd_hda_codec_read(codec, nid, 0,
AC_VERB_SET_PIN_SENSE, 0);
}
return snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
}

/**
* snd_hda_jack_tbl_get - query the jack-table entry for the given NID
*/
struct hda_jack_tbl *
snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_jack_tbl *jack = codec->jacktbl.list;
int i;

if (!nid || !jack)
return NULL;
for (i = 0; i < codec->jacktbl.used; i++, jack++)
if (jack->nid == nid)
return jack;
return NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);

/**
* snd_hda_jack_tbl_new - create a jack-table entry for the given NID
*/
struct hda_jack_tbl *
snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
if (jack)
return jack;
snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
jack = snd_array_new(&codec->jacktbl);
if (!jack)
return NULL;
jack->nid = nid;
jack->jack_dirty = 1;
return jack;
}

void snd_hda_jack_tbl_clear(struct hda_codec *codec)
{
snd_array_free(&codec->jacktbl);
}

/* update the cached value and notification flag if needed */
static void jack_detect_update(struct hda_codec *codec,
struct hda_jack_tbl *jack)
{
if (jack->jack_dirty) {
jack->pin_sense = read_pin_sense(codec, jack->nid);
jack->jack_dirty = 0;
}
}

/**
* snd_hda_set_dirty_all - Mark all the cached as dirty
*
* This function sets the dirty flag to all entries of jack table.
* It's called from the resume path in hda_codec.c.
*/
void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
{
struct hda_jack_tbl *jack = codec->jacktbl.list;
int i;

for (i = 0; i < codec->jacktbl.used; i++, jack++)
if (jack->nid)
jack->jack_dirty = 1;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);

/**
* snd_hda_pin_sense - execute pin sense measurement
* @codec: the CODEC to sense
* @nid: the pin NID to sense
*
* Execute necessary pin sense measurement and return its Presence Detect,
* Impedance, ELD Valid etc. status bits.
*/
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
if (jack) {
jack_detect_update(codec, jack);
return jack->pin_sense;
}
return read_pin_sense(codec, nid);
}
EXPORT_SYMBOL_HDA(snd_hda_pin_sense);

/**
* snd_hda_jack_detect - query pin Presence Detect status
* @codec: the CODEC to sense
* @nid: the pin NID to sense
*
* Query and return the pin's Presence Detect status.
*/
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
{
u32 sense = snd_hda_pin_sense(codec, nid);
return !!(sense & AC_PINSENSE_PRESENCE);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect);

/**
* snd_hda_jack_detect_enable - enable the jack-detection
*/
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
unsigned int tag)
{
struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
if (!jack)
return -ENOMEM;
return snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | tag);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
63 changes: 63 additions & 0 deletions trunk/sound/pci/hda/hda_jack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Jack-detection handling for HD-audio
*
* Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#ifndef __SOUND_HDA_JACK_H
#define __SOUND_HDA_JACK_H

struct hda_jack_tbl {
hda_nid_t nid;
unsigned int pin_sense; /* cached pin-sense value */
unsigned int jack_dirty:1; /* needs to update? */
};

struct hda_jack_tbl *
snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);

struct hda_jack_tbl *
snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);
void snd_hda_jack_tbl_clear(struct hda_codec *codec);

/**
* snd_hda_jack_set_dirty - set the dirty flag for the given jack-entry
*
* Call this function when a pin-state may change, e.g. when the hardware
* notifies via an unsolicited event.
*/
static inline void snd_hda_jack_set_dirty(struct hda_codec *codec,
hda_nid_t nid)
{
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
if (jack)
jack->jack_dirty = 1;
}

void snd_hda_jack_set_dirty_all(struct hda_codec *codec);

int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
unsigned int tag);

u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);

static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
{
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
return false;
if (!codec->ignore_misc_bit &&
(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
AC_DEFCFG_MISC_NO_PRESENCE))
return false;
if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
return false;
return true;
}

#endif /* __SOUND_HDA_JACK_H */
15 changes: 0 additions & 15 deletions trunk/sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,21 +505,6 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
unsigned int caps);
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);

static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
{
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
return false;
if (!codec->ignore_misc_bit &&
(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
AC_DEFCFG_MISC_NO_PRESENCE))
return false;
if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
return false;
return true;
}

/* flags for hda_nid_item */
#define HDA_NID_ITEM_AMP (1<<0)
Expand Down
1 change: 1 addition & 0 deletions trunk/sound/pci/hda/patch_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_beep.h"
#include "hda_jack.h"

struct ad198x_spec {
const struct snd_kcontrol_new *mixers[6];
Expand Down
18 changes: 8 additions & 10 deletions trunk/sound/pci/hda/patch_cirrus.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_jack.h"
#include <sound/tlv.h>

/*
Expand Down Expand Up @@ -1020,9 +1021,7 @@ static void init_output(struct hda_codec *codec)
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | HP_EVENT);
snd_hda_jack_detect_enable(codec, nid, HP_EVENT);
spec->hp_detect = 1;
}
}
Expand Down Expand Up @@ -1063,9 +1062,7 @@ static void init_input(struct hda_codec *codec)
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_MUTE(spec->adc_idx[i]));
if (spec->mic_detect && spec->automic_idx == i)
snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | MIC_EVENT);
snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
}
/* specific to CS421x */
if (spec->vendor_nid == CS421X_VENDOR_NID) {
Expand Down Expand Up @@ -1227,6 +1224,8 @@ static void cs_free(struct hda_codec *codec)

static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
{
snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */

switch ((res >> 26) & 0x7f) {
case HP_EVENT:
cs_automute(codec);
Expand Down Expand Up @@ -1585,10 +1584,7 @@ static void init_cs421x_digital(struct hda_codec *codec)
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {

snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | SPDIF_EVENT);
snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT);
spec->spdif_detect = 1;
}
}
Expand Down Expand Up @@ -1806,6 +1802,8 @@ static int cs421x_build_controls(struct hda_codec *codec)

static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
{
snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */

switch ((res >> 26) & 0x3f) {
case HP_EVENT:
case SPDIF_EVENT:
Expand Down
Loading

0 comments on commit a2c73c2

Please sign in to comment.