aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c780
1 files changed, 515 insertions, 265 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index d7c622f944f..71c3ccfcde1 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -30,17 +30,17 @@
#include <linux/pci.h>
#include <sound/core.h>
#include <sound/asoundef.h>
+#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
#include "hda_beep.h"
-#define NUM_CONTROL_ALLOC 32
-
-#define STAC_VREF_EVENT 0x00
-#define STAC_INSERT_EVENT 0x10
-#define STAC_PWR_EVENT 0x20
-#define STAC_HP_EVENT 0x30
+enum {
+ STAC_VREF_EVENT = 1,
+ STAC_INSERT_EVENT,
+ STAC_PWR_EVENT,
+ STAC_HP_EVENT,
+};
enum {
STAC_REF,
@@ -137,6 +137,19 @@ enum {
STAC_927X_MODELS
};
+struct sigmatel_event {
+ hda_nid_t nid;
+ unsigned char type;
+ unsigned char tag;
+ int data;
+};
+
+struct sigmatel_jack {
+ hda_nid_t nid;
+ int type;
+ struct snd_jack *jack;
+};
+
struct sigmatel_spec {
struct snd_kcontrol_new *mixers[4];
unsigned int num_mixers;
@@ -170,6 +183,12 @@ struct sigmatel_spec {
hda_nid_t *pwr_nids;
hda_nid_t *dac_list;
+ /* jack detection */
+ struct snd_array jacks;
+
+ /* events */
+ struct snd_array events;
+
/* playback */
struct hda_input_mux *mono_mux;
struct hda_input_mux *amp_mux;
@@ -199,7 +218,6 @@ struct sigmatel_spec {
hda_nid_t *pin_nids;
unsigned int num_pins;
unsigned int *pin_configs;
- unsigned int *bios_pin_configs;
/* codec specific stuff */
struct hda_verb *init;
@@ -227,8 +245,7 @@ struct sigmatel_spec {
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_dimux;
struct hda_input_mux private_imux;
struct hda_input_mux private_smux;
@@ -574,12 +591,12 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
else
nid = codec->slave_dig_outs[smux_idx - 1];
if (spec->cur_smux[smux_idx] == smux->num_items - 1)
- val = AMP_OUT_MUTE;
+ val = HDA_AMP_MUTE;
else
- val = AMP_OUT_UNMUTE;
+ val = 0;
/* un/mute SPDIF out */
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, val);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, val);
}
return 0;
}
@@ -1238,9 +1255,14 @@ static const char *slave_sws[] = {
NULL
};
+static void stac92xx_free_kctls(struct hda_codec *codec);
+static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type);
+
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ hda_nid_t nid;
int err;
int i;
@@ -1255,7 +1277,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
if (spec->num_dmuxes > 0) {
stac_dmux_mixer.count = spec->num_dmuxes;
- err = snd_ctl_add(codec->bus->card,
+ err = snd_hda_ctl_add(codec,
snd_ctl_new1(&stac_dmux_mixer, codec));
if (err < 0)
return err;
@@ -1310,6 +1332,37 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err;
}
+ stac92xx_free_kctls(codec); /* no longer needed */
+
+ /* create jack input elements */
+ if (spec->hp_detect) {
+ for (i = 0; i < cfg->hp_outs; i++) {
+ int type = SND_JACK_HEADPHONE;
+ nid = cfg->hp_pins[i];
+ /* jack detection */
+ if (cfg->hp_outs == i)
+ type |= SND_JACK_LINEOUT;
+ err = stac92xx_add_jack(codec, nid, type);
+ if (err < 0)
+ return err;
+ }
+ }
+ for (i = 0; i < cfg->line_outs; i++) {
+ err = stac92xx_add_jack(codec, cfg->line_out_pins[i],
+ SND_JACK_LINEOUT);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ nid = cfg->input_pins[i];
+ if (nid) {
+ err = stac92xx_add_jack(codec, nid,
+ SND_JACK_MICROPHONE);
+ if (err < 0)
+ return err;
+ }
+ }
+
return 0;
}
@@ -2200,12 +2253,11 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
int i;
struct sigmatel_spec *spec = codec->spec;
- if (! spec->bios_pin_configs) {
- spec->bios_pin_configs = kcalloc(spec->num_pins,
- sizeof(*spec->bios_pin_configs), GFP_KERNEL);
- if (! spec->bios_pin_configs)
- return -ENOMEM;
- }
+ kfree(spec->pin_configs);
+ spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs),
+ GFP_KERNEL);
+ if (!spec->pin_configs)
+ return -ENOMEM;
for (i = 0; i < spec->num_pins; i++) {
hda_nid_t nid = spec->pin_nids[i];
@@ -2215,7 +2267,7 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
AC_VERB_GET_CONFIG_DEFAULT, 0x00);
snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",
nid, pin_cfg);
- spec->bios_pin_configs[i] = pin_cfg;
+ spec->pin_configs[i] = pin_cfg;
}
return 0;
@@ -2257,6 +2309,39 @@ static void stac92xx_set_config_regs(struct hda_codec *codec)
spec->pin_configs[i]);
}
+static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ if (!pins)
+ return stac92xx_save_bios_config_regs(codec);
+
+ kfree(spec->pin_configs);
+ spec->pin_configs = kmemdup(pins,
+ spec->num_pins * sizeof(*pins),
+ GFP_KERNEL);
+ if (!spec->pin_configs)
+ return -ENOMEM;
+
+ stac92xx_set_config_regs(codec);
+ return 0;
+}
+
+static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int cfg)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->num_pins; i++) {
+ if (spec->pin_nids[i] == nid) {
+ spec->pin_configs[i] = cfg;
+ stac92xx_set_config_reg(codec, nid, cfg);
+ break;
+ }
+ }
+}
+
/*
* Analog playback callbacks
*/
@@ -2334,7 +2419,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
if (spec->powerdown_adcs) {
msleep(40);
- snd_hda_codec_write_cache(codec, nid, 0,
+ snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
}
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
@@ -2350,7 +2435,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
snd_hda_codec_cleanup_stream(codec, nid);
if (spec->powerdown_adcs)
- snd_hda_codec_write_cache(codec, nid, 0,
+ snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
return 0;
}
@@ -2482,6 +2567,9 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
return 0;
}
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char type);
+
static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2494,7 +2582,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
/* check to be sure that the ports are upto date with
* switch changes
*/
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
return 1;
}
@@ -2534,7 +2622,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
* appropriately according to the pin direction
*/
if (spec->hp_detect)
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
return 1;
}
@@ -2629,28 +2717,16 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
- if (! knew)
- return -ENOMEM;
- if (spec->kctl_alloc) {
- memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
- kfree(spec->kctl_alloc);
- }
- spec->kctl_alloc = knew;
- spec->num_kctl_alloc = num;
- }
-
- knew = &spec->kctl_alloc[spec->num_kctl_used];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = *ktemp;
knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
@@ -3527,8 +3603,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
if (dig_in && spec->autocfg.dig_in_pin)
spec->dig_in_nid = dig_in;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3635,8 +3711,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = 0x04;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3680,13 +3756,101 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
+static int stac92xx_add_jack(struct hda_codec *codec,
+ hda_nid_t nid, int type)
+{
+#ifdef CONFIG_SND_JACK
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_jack *jack;
+ int def_conf = snd_hda_codec_read(codec, nid,
+ 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ int connectivity = get_defcfg_connect(def_conf);
+ char name[32];
+
+ if (connectivity && connectivity != AC_JACK_PORT_FIXED)
+ return 0;
+
+ snd_array_init(&spec->jacks, sizeof(*jack), 32);
+ jack = snd_array_new(&spec->jacks);
+ if (!jack)
+ return -ENOMEM;
+ jack->nid = nid;
+ jack->type = type;
+
+ sprintf(name, "%s at %s %s Jack",
+ snd_hda_get_jack_type(def_conf),
+ snd_hda_get_jack_connectivity(def_conf),
+ snd_hda_get_jack_location(def_conf));
+
+ return snd_jack_new(codec->bus->card, name, type, &jack->jack);
+#else
+ return 0;
+#endif
+}
+
+static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
+ unsigned char type, int data)
+{
+ struct sigmatel_event *event;
+
+ snd_array_init(&spec->events, sizeof(*event), 32);
+ event = snd_array_new(&spec->events);
+ if (!event)
+ return -ENOMEM;
+ event->nid = nid;
+ event->type = type;
+ event->tag = spec->events.used;
+ event->data = data;
+
+ return event->tag;
+}
+
+static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
+ hda_nid_t nid, unsigned char type)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_event *event = spec->events.list;
+ int i;
+
+ for (i = 0; i < spec->events.used; i++, event++) {
+ if (event->nid == nid && event->type == type)
+ return event;
+ }
+ return NULL;
+}
+
+static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
+ unsigned char tag)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_event *event = spec->events.list;
+ int i;
+
+ for (i = 0; i < spec->events.used; i++, event++) {
+ if (event->tag == tag)
+ return event;
+ }
+ return NULL;
+}
+
static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
- unsigned int event)
+ unsigned int type)
{
- if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | event));
+ struct sigmatel_event *event;
+ int tag;
+
+ if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+ return;
+ event = stac_get_event(codec, nid, type);
+ if (event)
+ tag = event->tag;
+ else
+ tag = stac_add_event(codec->spec, nid, type, 0);
+ if (tag < 0)
+ return;
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | tag);
}
static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
@@ -3708,7 +3872,7 @@ static void stac92xx_power_down(struct hda_codec *codec)
for (dac = spec->dac_list; *dac; dac++)
if (!is_in_dac_nids(spec, *dac) &&
spec->multiout.hp_nid != *dac)
- snd_hda_codec_write_cache(codec, *dac, 0,
+ snd_hda_codec_write(codec, *dac, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
}
@@ -3727,7 +3891,7 @@ static int stac92xx_init(struct hda_codec *codec)
/* power down adcs initially */
if (spec->powerdown_adcs)
for (i = 0; i < spec->num_adcs; i++)
- snd_hda_codec_write_cache(codec,
+ snd_hda_codec_write(codec,
spec->adc_nids[i], 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
@@ -3743,37 +3907,51 @@ static int stac92xx_init(struct hda_codec *codec)
/* set up pins */
if (spec->hp_detect) {
/* Enable unsolicited responses on the HP widget */
- for (i = 0; i < cfg->hp_outs; i++)
- enable_pin_detect(codec, cfg->hp_pins[i],
- STAC_HP_EVENT);
+ for (i = 0; i < cfg->hp_outs; i++) {
+ hda_nid_t nid = cfg->hp_pins[i];
+ enable_pin_detect(codec, nid, STAC_HP_EVENT);
+ }
/* force to enable the first line-out; the others are set up
* in unsol_event
*/
stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
- AC_PINCTL_OUT_EN);
- stac92xx_auto_init_hp_out(codec);
+ AC_PINCTL_OUT_EN);
/* fake event to set up pins */
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
+ STAC_HP_EVENT);
} else {
stac92xx_auto_init_multi_out(codec);
stac92xx_auto_init_hp_out(codec);
+ for (i = 0; i < cfg->hp_outs; i++)
+ stac_toggle_power_map(codec, cfg->hp_pins[i], 1);
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = cfg->input_pins[i];
if (nid) {
- unsigned int pinctl;
+ unsigned int pinctl, conf;
if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
/* for mic pins, force to initialize */
pinctl = stac92xx_get_vref(codec, nid);
+ pinctl |= AC_PINCTL_IN_EN;
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
} else {
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* if PINCTL already set then skip */
- if (pinctl & AC_PINCTL_IN_EN)
- continue;
+ if (!(pinctl & AC_PINCTL_IN_EN)) {
+ pinctl |= AC_PINCTL_IN_EN;
+ stac92xx_auto_set_pinctl(codec, nid,
+ pinctl);
+ }
+ }
+ conf = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
+ enable_pin_detect(codec, nid,
+ STAC_INSERT_EVENT);
+ stac_issue_unsol_event(codec, nid,
+ STAC_INSERT_EVENT);
}
- pinctl |= AC_PINCTL_IN_EN;
- stac92xx_auto_set_pinctl(codec, nid, pinctl);
}
}
for (i = 0; i < spec->num_dmics; i++)
@@ -3788,7 +3966,6 @@ static int stac92xx_init(struct hda_codec *codec)
for (i = 0; i < spec->num_pwrs; i++) {
hda_nid_t nid = spec->pwr_nids[i];
int pinctl, def_conf;
- int event = STAC_PWR_EVENT;
if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
continue; /* already has an unsol event */
@@ -3811,30 +3988,54 @@ static int stac92xx_init(struct hda_codec *codec)
stac_toggle_power_map(codec, nid, 1);
continue;
}
- enable_pin_detect(codec, spec->pwr_nids[i], event | i);
- codec->patch_ops.unsol_event(codec, (event | i) << 26);
+ if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) {
+ enable_pin_detect(codec, nid, STAC_PWR_EVENT);
+ stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
+ }
}
if (spec->dac_list)
stac92xx_power_down(codec);
return 0;
}
+static void stac92xx_free_jacks(struct hda_codec *codec)
+{
+#ifdef CONFIG_SND_JACK
+ /* free jack instances manually when clearing/reconfiguring */
+ struct sigmatel_spec *spec = codec->spec;
+ if (!codec->bus->shutdown && spec->jacks.list) {
+ struct sigmatel_jack *jacks = spec->jacks.list;
+ int i;
+ for (i = 0; i < spec->jacks.used; i++)
+ snd_device_free(codec->bus->card, &jacks[i].jack);
+ }
+ snd_array_free(&spec->jacks);
+#endif
+}
+
+static void stac92xx_free_kctls(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ if (spec->kctls.list) {
+ struct snd_kcontrol_new *kctl = spec->kctls.list;
+ int i;
+ for (i = 0; i < spec->kctls.used; i++)
+ kfree(kctl[i].name);
+ }
+ snd_array_free(&spec->kctls);
+}
+
static void stac92xx_free(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- int i;
if (! spec)
return;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
-
- if (spec->bios_pin_configs)
- kfree(spec->bios_pin_configs);
+ kfree(spec->pin_configs);
+ stac92xx_free_jacks(codec);
+ snd_array_free(&spec->events);
kfree(spec);
snd_hda_detach_beep_device(codec);
@@ -3881,20 +4082,13 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
pin_ctl & ~flag);
}
-static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
+static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
{
if (!nid)
return 0;
if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00)
- & (1 << 31)) {
- unsigned int pinctl;
- pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- if (pinctl & AC_PINCTL_IN_EN)
- return 0; /* mic- or line-input */
- else
- return 1; /* HP-output */
- }
+ & (1 << 31))
+ return 1;
return 0;
}
@@ -3918,7 +4112,7 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i)
return 0;
}
-static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+static void stac92xx_hp_detect(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -3934,7 +4128,14 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
break;
if (no_hp_sensing(spec, i))
continue;
- presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
+ presence = get_pin_presence(codec, cfg->hp_pins[i]);
+ if (presence) {
+ unsigned int pinctl;
+ pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (pinctl & AC_PINCTL_IN_EN)
+ presence = 0; /* mic- or line-input */
+ }
}
if (presence) {
@@ -4011,50 +4212,145 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
{
- stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid));
+ stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
+}
+
+static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_jack *jacks = spec->jacks.list;
+
+ if (jacks) {
+ int i;
+ for (i = 0; i < spec->jacks.used; i++) {
+ if (jacks->nid == nid) {
+ unsigned int pin_ctl =
+ snd_hda_codec_read(codec, nid,
+ 0, AC_VERB_GET_PIN_WIDGET_CONTROL,
+ 0x00);
+ int type = jacks->type;
+ if (type == (SND_JACK_LINEOUT
+ | SND_JACK_HEADPHONE))
+ type = (pin_ctl & AC_PINCTL_HP_EN)
+ ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
+ snd_jack_report(jacks->jack,
+ get_pin_presence(codec, nid)
+ ? type : 0);
+ }
+ jacks++;
+ }
+ }
+}
+
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char type)
+{
+ struct sigmatel_event *event = stac_get_event(codec, nid, type);
+ if (!event)
+ return;
+ codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
}
static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
{
struct sigmatel_spec *spec = codec->spec;
- int idx = res >> 26 & 0x0f;
+ struct sigmatel_event *event;
+ int tag, data;
- switch ((res >> 26) & 0x70) {
+ tag = (res >> 26) & 0x7f;
+ event = stac_get_event_from_tag(codec, tag);
+ if (!event)
+ return;
+
+ switch (event->type) {
case STAC_HP_EVENT:
- stac92xx_hp_detect(codec, res);
+ stac92xx_hp_detect(codec);
/* fallthru */
+ case STAC_INSERT_EVENT:
case STAC_PWR_EVENT:
if (spec->num_pwrs > 0)
- stac92xx_pin_sense(codec, idx);
+ stac92xx_pin_sense(codec, event->nid);
+ stac92xx_report_jack(codec, event->nid);
break;
- case STAC_VREF_EVENT: {
- int data = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
+ case STAC_VREF_EVENT:
+ data = snd_hda_codec_read(codec, codec->afg, 0,
+ AC_VERB_GET_GPIO_DATA, 0);
/* toggle VREF state based on GPIOx status */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
- !!(data & (1 << idx)));
+ !!(data & (1 << event->data)));
break;
- }
}
}
+#ifdef CONFIG_PROC_FS
+static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid == codec->afg)
+ snd_iprintf(buffer, "Power-Map: 0x%02x\n",
+ snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0));
+}
+
+static void analog_loop_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec,
+ unsigned int verb)
+{
+ snd_iprintf(buffer, "Analog Loopback: 0x%02x\n",
+ snd_hda_codec_read(codec, codec->afg, 0, verb, 0));
+}
+
+/* stac92hd71bxx, stac92hd73xx */
+static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ stac92hd_proc_hook(buffer, codec, nid);
+ if (nid == codec->afg)
+ analog_loop_proc_hook(buffer, codec, 0xfa0);
+}
+
+static void stac9205_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid == codec->afg)
+ analog_loop_proc_hook(buffer, codec, 0xfe0);
+}
+
+static void stac927x_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid == codec->afg)
+ analog_loop_proc_hook(buffer, codec, 0xfeb);
+}
+#else
+#define stac92hd_proc_hook NULL
+#define stac92hd7x_proc_hook NULL
+#define stac9205_proc_hook NULL
+#define stac927x_proc_hook NULL
+#endif
+
#ifdef SND_HDA_NEEDS_RESUME
static int stac92xx_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
stac92xx_set_config_regs(codec);
- snd_hda_sequence_write(codec, spec->init);
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
+ stac92xx_init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
- /* power down inactive DACs */
- if (spec->dac_list)
- stac92xx_power_down(codec);
- /* invoke unsolicited event to reset the HP state */
+ /* fake event to set up pins again to override cached values */
if (spec->hp_detect)
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
+ STAC_HP_EVENT);
+ return 0;
+}
+
+static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ if (spec->eapd_mask)
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data &
+ ~spec->eapd_mask);
return 0;
}
#endif
@@ -4066,6 +4362,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
.free = stac92xx_free,
.unsol_event = stac92xx_unsol_event,
#ifdef SND_HDA_NEEDS_RESUME
+ .suspend = stac92xx_suspend,
.resume = stac92xx_resume,
#endif
};
@@ -4088,14 +4385,12 @@ static int patch_stac9200(struct hda_codec *codec)
if (spec->board_config < 0) {
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac9200_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac9200_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->multiout.max_channels = 2;
@@ -4151,14 +4446,12 @@ static int patch_stac925x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
"using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else if (stac925x_brd_tbl[spec->board_config] != NULL){
- spec->pin_configs = stac925x_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac925x_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->multiout.max_channels = 2;
@@ -4240,14 +4533,12 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD73XX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac92hd73xx_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a,
@@ -4366,6 +4657,8 @@ again:
codec->patch_ops = stac92xx_patch_ops;
+ codec->proc_widget_hook = stac92hd7x_proc_hook;
+
return 0;
}
@@ -4426,14 +4719,12 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD83XXX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac92hd83xxx_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
err = stac92xx_parse_auto_config(codec, 0x1d, 0);
@@ -4454,56 +4745,10 @@ again:
codec->patch_ops = stac92xx_patch_ops;
- return 0;
-}
-
-#ifdef SND_HDA_NEEDS_RESUME
-static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_POWER_STATE, pwr);
-
- msleep(1);
- for (i = 0; i < spec->num_adcs; i++) {
- snd_hda_codec_write_cache(codec,
- spec->adc_nids[i], 0,
- AC_VERB_SET_POWER_STATE, pwr);
- }
-};
+ codec->proc_widget_hook = stac92hd_proc_hook;
-static int stac92hd71xx_resume(struct hda_codec *codec)
-{
- stac92hd71xx_set_power_state(codec, AC_PWRST_D0);
- return stac92xx_resume(codec);
-}
-
-static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- stac92hd71xx_set_power_state(codec, AC_PWRST_D3);
- if (spec->eapd_mask)
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data &
- ~spec->eapd_mask);
return 0;
-};
-
-#endif
-
-static struct hda_codec_ops stac92hd71bxx_patch_ops = {
- .build_controls = stac92xx_build_controls,
- .build_pcms = stac92xx_build_pcms,
- .init = stac92xx_init,
- .free = stac92xx_free,
- .unsol_event = stac92xx_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
- .resume = stac92hd71xx_resume,
- .suspend = stac92hd71xx_suspend,
-#endif
-};
+}
static struct hda_input_mux stac92hd71bxx_dmux = {
.num_items = 4,
@@ -4540,14 +4785,12 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD71BXX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac92hd71bxx_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
if (spec->board_config > STAC_92HD71BXX_REF) {
@@ -4570,21 +4813,21 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */
+ err = stac_add_event(spec, codec->afg,
+ STAC_VREF_EVENT, 0x02);
+ if (err < 0)
+ return err;
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | STAC_VREF_EVENT | 0x01));
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | err);
spec->gpio_mask |= 0x02;
break;
}
if ((codec->revision_id & 0xf) == 0 ||
- (codec->revision_id & 0xf) == 1) {
-#ifdef SND_HDA_NEEDS_RESUME
- codec->patch_ops = stac92hd71bxx_patch_ops;
-#endif
+ (codec->revision_id & 0xf) == 1)
spec->stream_delay = 40; /* 40 milliseconds */
- }
/* no output amps */
spec->num_pwrs = 0;
@@ -4593,15 +4836,11 @@ again:
/* disable VSW */
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
- stac92xx_set_config_reg(codec, 0xf, 0x40f000f0);
+ stac_change_pin_config(codec, 0xf, 0x40f000f0);
break;
case 0x111d7603: /* 6 Port with Analog Mixer */
- if ((codec->revision_id & 0xf) == 1) {
-#ifdef SND_HDA_NEEDS_RESUME
- codec->patch_ops = stac92hd71bxx_patch_ops;
-#endif
+ if ((codec->revision_id & 0xf) == 1)
spec->stream_delay = 40; /* 40 milliseconds */
- }
/* no output amps */
spec->num_pwrs = 0;
@@ -4631,7 +4870,7 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
/* enable internal microphone */
- stac92xx_set_config_reg(codec, 0x0e, 0x01813040);
+ stac_change_pin_config(codec, 0x0e, 0x01813040);
stac92xx_auto_set_pinctl(codec, 0x0e,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
/* fallthru */
@@ -4676,6 +4915,8 @@ again:
return err;
}
+ codec->proc_widget_hook = stac92hd7x_proc_hook;
+
return 0;
};
@@ -4737,14 +4978,12 @@ static int patch_stac922x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
"using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else if (stac922x_brd_tbl[spec->board_config] != NULL) {
- spec->pin_configs = stac922x_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac922x_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->adc_nids = stac922x_adc_nids;
@@ -4807,14 +5046,12 @@ static int patch_stac927x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
"STAC927x, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac927x_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac927x_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->digbeep_nid = 0x23;
@@ -4844,15 +5081,15 @@ static int patch_stac927x(struct hda_codec *codec)
case 0x10280209:
case 0x1028022e:
/* correct the device field to SPDIF out */
- stac92xx_set_config_reg(codec, 0x21, 0x01442070);
+ stac_change_pin_config(codec, 0x21, 0x01442070);
break;
};
/* configure the analog microphone on some laptops */
- stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
+ stac_change_pin_config(codec, 0x0c, 0x90a79130);
/* correct the front output jack as a hp out */
- stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
+ stac_change_pin_config(codec, 0x0f, 0x0227011f);
/* correct the front input jack as a mic */
- stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
+ stac_change_pin_config(codec, 0x0e, 0x02a79130);
/* fallthru */
case STAC_DELL_3ST:
/* GPIO2 High = Enable EAPD */
@@ -4900,6 +5137,8 @@ static int patch_stac927x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
+ codec->proc_widget_hook = stac927x_proc_hook;
+
/*
* !!FIXME!!
* The STAC927x seem to require fairly long delays for certain
@@ -4938,14 +5177,12 @@ static int patch_stac9205(struct hda_codec *codec)
if (spec->board_config < 0) {
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac9205_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac9205_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->digbeep_nid = 0x23;
@@ -4972,15 +5209,18 @@ static int patch_stac9205(struct hda_codec *codec)
switch (spec->board_config){
case STAC_9205_DELL_M43:
/* Enable SPDIF in/out */
- stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
- stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
+ stac_change_pin_config(codec, 0x1f, 0x01441030);
+ stac_change_pin_config(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
+ err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
+ if (err < 0)
+ return err;
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | STAC_HP_EVENT));
+ AC_USRSP_EN | err);
spec->gpio_dir = 0x0b;
spec->eapd_mask = 0x01;
@@ -5018,6 +5258,8 @@ static int patch_stac9205(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
+ codec->proc_widget_hook = stac9205_proc_hook;
+
return 0;
}
@@ -5074,29 +5316,11 @@ static struct hda_verb vaio_ar_init[] = {
{}
};
-/* bind volumes of both NID 0x02 and 0x05 */
-static struct hda_bind_ctls vaio_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-/* bind volumes of both NID 0x02 and 0x05 */
-static struct hda_bind_ctls vaio_bind_master_sw = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
- 0,
- },
-};
-
static struct snd_kcontrol_new vaio_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -5112,8 +5336,10 @@ static struct snd_kcontrol_new vaio_mixer[] = {
};
static struct snd_kcontrol_new vaio_ar_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -5154,7 +5380,7 @@ static int stac9872_vaio_init(struct hda_codec *codec)
static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
{
- if (get_hp_pin_presence(codec, 0x0a)) {
+ if (get_pin_presence(codec, 0x0a)) {
stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
} else {
@@ -5265,7 +5491,7 @@ static int patch_stac9872(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
{ .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
{ .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
@@ -5329,3 +5555,27 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:8384*");
+MODULE_ALIAS("snd-hda-codec-id:111d*");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec");
+
+static struct hda_codec_preset_list sigmatel_list = {
+ .preset = snd_hda_preset_sigmatel,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_sigmatel_init(void)
+{
+ return snd_hda_add_codec_preset(&sigmatel_list);
+}
+
+static void __exit patch_sigmatel_exit(void)
+{
+ snd_hda_delete_codec_preset(&sigmatel_list);
+}
+
+module_init(patch_sigmatel_init)
+module_exit(patch_sigmatel_exit)