Skip to content

Commit

Permalink
ALSA: hda - Add init_verbs entries
Browse files Browse the repository at this point in the history
This patch enables the additional init verbs for each codec.  The verbs
can be entered via hwdep sysfs file.  These verbs are executed at
reconfiguring the codec for non-standard setups like overriding
the pin-defcfg.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Oct 13, 2008
1 parent d7ffba1 commit 11aeff0
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
13 changes: 13 additions & 0 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
}
}

#ifdef CONFIG_SND_HDA_HWDEP
/* execute additional init verbs */
static void hda_exec_init_verbs(struct hda_codec *codec)
{
if (codec->init_verbs.list)
snd_hda_sequence_write(codec, codec->init_verbs.list);
}
#else
static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
#endif

#ifdef SND_HDA_NEEDS_RESUME
/*
* call suspend and power-down; used both from PM and power-save
Expand All @@ -1967,6 +1978,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
hda_exec_init_verbs(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
Expand Down Expand Up @@ -2008,6 +2020,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
hda_exec_init_verbs(codec);
/* continue to initialize... */
if (codec->patch_ops.init)
err = codec->patch_ops.init(codec);
Expand Down
3 changes: 3 additions & 0 deletions sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,10 @@ struct hda_codec {
unsigned int spdif_in_enable; /* SPDIF input enable? */
hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */

#ifdef CONFIG_SND_HDA_HWDEP
struct snd_hwdep *hwdep; /* assigned hwdep device */
struct snd_array init_verbs; /* additional init verbs */
#endif

/* misc flags */
unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
Expand Down
37 changes: 37 additions & 0 deletions sound/pci/hda/hda_hwdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
return 0;
}

static void clear_hwdep_elements(struct hda_codec *codec)
{
/* clear init verbs */
snd_array_free(&codec->init_verbs);
}

static void hwdep_free(struct snd_hwdep *hwdep)
{
clear_hwdep_elements(hwdep->private_data);
}

int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
{
char hwname[16];
Expand All @@ -110,6 +121,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
sprintf(hwdep->name, "HDA Codec %d", codec->addr);
hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
hwdep->private_data = codec;
hwdep->private_free = hwdep_free;
hwdep->exclusive = 1;

hwdep->ops.open = hda_hwdep_open;
Expand All @@ -118,6 +130,8 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
#endif

snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);

return 0;
}

Expand All @@ -128,6 +142,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
static int clear_codec(struct hda_codec *codec)
{
snd_hda_codec_reset(codec);
clear_hwdep_elements(codec);
return 0;
}

Expand Down Expand Up @@ -244,6 +259,27 @@ static ssize_t type##_store(struct device *dev, \
CODEC_ACTION_STORE(reconfig);
CODEC_ACTION_STORE(clear);

static ssize_t init_verbs_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
char *p;
struct hda_verb verb, *v;

verb.nid = simple_strtoul(buf, &p, 0);
verb.verb = simple_strtoul(p, &p, 0);
verb.param = simple_strtoul(p, &p, 0);
if (!verb.nid || !verb.verb || !verb.param)
return -EINVAL;
v = snd_array_new(&codec->init_verbs);
if (!v)
return -ENOMEM;
*v = verb;
return count;
}

#define CODEC_ATTR_RW(type) \
__ATTR(type, 0644, type##_show, type##_store)
#define CODEC_ATTR_RO(type) \
Expand All @@ -259,6 +295,7 @@ static struct device_attribute codec_attrs[] = {
CODEC_ATTR_RO(mfg),
CODEC_ATTR_RW(name),
CODEC_ATTR_RW(modelname),
CODEC_ATTR_WO(init_verbs),
CODEC_ATTR_WO(reconfig),
CODEC_ATTR_WO(clear),
};
Expand Down

0 comments on commit 11aeff0

Please sign in to comment.