mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 10:20:49 +07:00
ALSA: hda - Move up the fixup helper functions to the library module
Move the fixup helper functions in patch_realtek.c to hda_auto_parser.c so that they can be used in other codec drivers like patch_conexant.c. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
5536c6d693
commit
23d30f2827
@ -1,6 +1,6 @@
|
|||||||
snd-hda-intel-objs := hda_intel.o
|
snd-hda-intel-objs := hda_intel.o
|
||||||
|
|
||||||
snd-hda-codec-y := hda_codec.o hda_jack.o
|
snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o
|
||||||
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
|
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
|
||||||
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
|
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
|
||||||
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
|
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
|
||||||
|
163
sound/pci/hda/hda_auto_parser.c
Normal file
163
sound/pci/hda/hda_auto_parser.c
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* BIOS auto-parser helper functions for HD-audio
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 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/slab.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <sound/core.h>
|
||||||
|
#include "hda_codec.h"
|
||||||
|
#include "hda_auto_parser.h"
|
||||||
|
|
||||||
|
#define SFX "hda_codec: "
|
||||||
|
|
||||||
|
int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
|
||||||
|
const struct hda_verb *list)
|
||||||
|
{
|
||||||
|
const struct hda_verb **v;
|
||||||
|
snd_array_init(&spec->verbs, sizeof(struct hda_verb *), 8);
|
||||||
|
v = snd_array_new(&spec->verbs);
|
||||||
|
if (!v)
|
||||||
|
return -ENOMEM;
|
||||||
|
*v = list;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs);
|
||||||
|
|
||||||
|
void snd_hda_gen_apply_verbs(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < spec->verbs.used; i++) {
|
||||||
|
struct hda_verb **v = snd_array_elem(&spec->verbs, i);
|
||||||
|
snd_hda_sequence_write(codec, *v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs);
|
||||||
|
|
||||||
|
void snd_hda_apply_pincfgs(struct hda_codec *codec,
|
||||||
|
const struct hda_pintbl *cfg)
|
||||||
|
{
|
||||||
|
for (; cfg->nid; cfg++)
|
||||||
|
snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);
|
||||||
|
|
||||||
|
void snd_hda_apply_fixup(struct hda_codec *codec, int action)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
int id = spec->fixup_id;
|
||||||
|
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||||
|
const char *modelname = spec->fixup_name;
|
||||||
|
#endif
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
|
if (!spec->fixup_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (id >= 0) {
|
||||||
|
const struct hda_fixup *fix = spec->fixup_list + id;
|
||||||
|
|
||||||
|
switch (fix->type) {
|
||||||
|
case HDA_FIXUP_PINS:
|
||||||
|
if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
|
||||||
|
break;
|
||||||
|
snd_printdd(KERN_INFO SFX
|
||||||
|
"%s: Apply pincfg for %s\n",
|
||||||
|
codec->chip_name, modelname);
|
||||||
|
snd_hda_apply_pincfgs(codec, fix->v.pins);
|
||||||
|
break;
|
||||||
|
case HDA_FIXUP_VERBS:
|
||||||
|
if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
|
||||||
|
break;
|
||||||
|
snd_printdd(KERN_INFO SFX
|
||||||
|
"%s: Apply fix-verbs for %s\n",
|
||||||
|
codec->chip_name, modelname);
|
||||||
|
snd_hda_gen_add_verbs(codec->spec, fix->v.verbs);
|
||||||
|
break;
|
||||||
|
case HDA_FIXUP_FUNC:
|
||||||
|
if (!fix->v.func)
|
||||||
|
break;
|
||||||
|
snd_printdd(KERN_INFO SFX
|
||||||
|
"%s: Apply fix-func for %s\n",
|
||||||
|
codec->chip_name, modelname);
|
||||||
|
fix->v.func(codec, fix, action);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snd_printk(KERN_ERR SFX
|
||||||
|
"%s: Invalid fixup type %d\n",
|
||||||
|
codec->chip_name, fix->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!fix->chained)
|
||||||
|
break;
|
||||||
|
if (++depth > 10)
|
||||||
|
break;
|
||||||
|
id = fix->chain_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);
|
||||||
|
|
||||||
|
void snd_hda_pick_fixup(struct hda_codec *codec,
|
||||||
|
const struct hda_model_fixup *models,
|
||||||
|
const struct snd_pci_quirk *quirk,
|
||||||
|
const struct hda_fixup *fixlist)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
const struct snd_pci_quirk *q;
|
||||||
|
int id = -1;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
/* when model=nofixup is given, don't pick up any fixups */
|
||||||
|
if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
|
||||||
|
spec->fixup_list = NULL;
|
||||||
|
spec->fixup_id = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codec->modelname && models) {
|
||||||
|
while (models->name) {
|
||||||
|
if (!strcmp(codec->modelname, models->name)) {
|
||||||
|
id = models->id;
|
||||||
|
name = models->name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
models++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (id < 0) {
|
||||||
|
q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
|
||||||
|
if (q) {
|
||||||
|
id = q->value;
|
||||||
|
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||||
|
name = q->name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (id < 0) {
|
||||||
|
for (q = quirk; q->subvendor; q++) {
|
||||||
|
unsigned int vendorid =
|
||||||
|
q->subdevice | (q->subvendor << 16);
|
||||||
|
if (vendorid == codec->subsystem_id) {
|
||||||
|
id = q->value;
|
||||||
|
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||||
|
name = q->name;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec->fixup_id = id;
|
||||||
|
if (id >= 0) {
|
||||||
|
spec->fixup_list = fixlist;
|
||||||
|
spec->fixup_name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
|
80
sound/pci/hda/hda_auto_parser.h
Normal file
80
sound/pci/hda/hda_auto_parser.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* BIOS auto-parser helper functions for HD-audio
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 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_AUTO_PARSER_H
|
||||||
|
#define __SOUND_HDA_AUTO_PARSER_H
|
||||||
|
|
||||||
|
struct hda_gen_spec {
|
||||||
|
/* fix-up list */
|
||||||
|
int fixup_id;
|
||||||
|
const struct hda_fixup *fixup_list;
|
||||||
|
const char *fixup_name;
|
||||||
|
|
||||||
|
/* additional init verbs */
|
||||||
|
struct snd_array verbs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix-up pin default configurations and add default verbs
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct hda_pintbl {
|
||||||
|
hda_nid_t nid;
|
||||||
|
u32 val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hda_model_fixup {
|
||||||
|
const int id;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hda_fixup {
|
||||||
|
int type;
|
||||||
|
bool chained;
|
||||||
|
int chain_id;
|
||||||
|
union {
|
||||||
|
const struct hda_pintbl *pins;
|
||||||
|
const struct hda_verb *verbs;
|
||||||
|
void (*func)(struct hda_codec *codec,
|
||||||
|
const struct hda_fixup *fix,
|
||||||
|
int action);
|
||||||
|
} v;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* fixup types */
|
||||||
|
enum {
|
||||||
|
HDA_FIXUP_INVALID,
|
||||||
|
HDA_FIXUP_PINS,
|
||||||
|
HDA_FIXUP_VERBS,
|
||||||
|
HDA_FIXUP_FUNC,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* fixup action definitions */
|
||||||
|
enum {
|
||||||
|
HDA_FIXUP_ACT_PRE_PROBE,
|
||||||
|
HDA_FIXUP_ACT_PROBE,
|
||||||
|
HDA_FIXUP_ACT_INIT,
|
||||||
|
HDA_FIXUP_ACT_BUILD,
|
||||||
|
};
|
||||||
|
|
||||||
|
int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
|
||||||
|
const struct hda_verb *list);
|
||||||
|
void snd_hda_gen_apply_verbs(struct hda_codec *codec);
|
||||||
|
void snd_hda_apply_pincfgs(struct hda_codec *codec,
|
||||||
|
const struct hda_pintbl *cfg);
|
||||||
|
void snd_hda_apply_fixup(struct hda_codec *codec, int action);
|
||||||
|
void snd_hda_pick_fixup(struct hda_codec *codec,
|
||||||
|
const struct hda_model_fixup *models,
|
||||||
|
const struct snd_pci_quirk *quirk,
|
||||||
|
const struct hda_fixup *fixlist);
|
||||||
|
|
||||||
|
#endif /* __SOUND_HDA_AUTO_PARSER_H */
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
|
#include "hda_auto_parser.h"
|
||||||
#include "hda_beep.h"
|
#include "hda_beep.h"
|
||||||
#include "hda_jack.h"
|
#include "hda_jack.h"
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ struct imux_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct conexant_spec {
|
struct conexant_spec {
|
||||||
|
struct hda_gen_spec gen;
|
||||||
|
|
||||||
const struct snd_kcontrol_new *mixers[5];
|
const struct snd_kcontrol_new *mixers[5];
|
||||||
int num_mixers;
|
int num_mixers;
|
||||||
@ -4407,47 +4409,21 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
|
|||||||
/*
|
/*
|
||||||
* pin fix-up
|
* pin fix-up
|
||||||
*/
|
*/
|
||||||
struct cxt_pincfg {
|
|
||||||
hda_nid_t nid;
|
|
||||||
u32 val;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg)
|
|
||||||
{
|
|
||||||
for (; cfg->nid; cfg++)
|
|
||||||
snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CXT_PINCFG_LENOVO_X200,
|
CXT_PINCFG_LENOVO_X200,
|
||||||
CXT_PINCFG_LENOVO_TP410,
|
CXT_PINCFG_LENOVO_TP410,
|
||||||
CXT_FIXUP_STEREO_DMIC,
|
CXT_FIXUP_STEREO_DMIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void apply_fixup(struct hda_codec *codec,
|
static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
|
||||||
const struct snd_pci_quirk *quirk,
|
const struct hda_fixup *fix, int action)
|
||||||
const struct cxt_pincfg **table)
|
|
||||||
{
|
{
|
||||||
struct conexant_spec *spec = codec->spec;
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
|
||||||
quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
|
|
||||||
if (!quirk)
|
|
||||||
return;
|
|
||||||
if (table[quirk->value]) {
|
|
||||||
snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n",
|
|
||||||
quirk->name);
|
|
||||||
apply_pincfg(codec, table[quirk->value]);
|
|
||||||
}
|
|
||||||
if (quirk->value == CXT_FIXUP_STEREO_DMIC) {
|
|
||||||
snd_printdd(KERN_INFO "hda_codec: applying internal mic workaround for %s\n",
|
|
||||||
quirk->name);
|
|
||||||
spec->fixup_stereo_dmic = 1;
|
spec->fixup_stereo_dmic = 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* ThinkPad X200 & co with cxt5051 */
|
/* ThinkPad X200 & co with cxt5051 */
|
||||||
static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
|
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
|
||||||
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
|
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
|
||||||
{ 0x17, 0x21a11000 }, /* dock-mic */
|
{ 0x17, 0x21a11000 }, /* dock-mic */
|
||||||
{ 0x19, 0x2121103f }, /* dock-HP */
|
{ 0x19, 0x2121103f }, /* dock-HP */
|
||||||
@ -4456,17 +4432,26 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
|
/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
|
||||||
static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = {
|
static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
|
||||||
{ 0x19, 0x042110ff }, /* HP (seq# overridden) */
|
{ 0x19, 0x042110ff }, /* HP (seq# overridden) */
|
||||||
{ 0x1a, 0x21a190f0 }, /* dock-mic */
|
{ 0x1a, 0x21a190f0 }, /* dock-mic */
|
||||||
{ 0x1c, 0x212140ff }, /* dock-HP */
|
{ 0x1c, 0x212140ff }, /* dock-HP */
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct cxt_pincfg *cxt_pincfg_tbl[] = {
|
static const struct hda_fixup cxt_fixups[] = {
|
||||||
[CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200,
|
[CXT_PINCFG_LENOVO_X200] = {
|
||||||
[CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410,
|
.type = HDA_FIXUP_PINS,
|
||||||
[CXT_FIXUP_STEREO_DMIC] = NULL,
|
.v.pins = cxt_pincfg_lenovo_x200,
|
||||||
|
},
|
||||||
|
[CXT_PINCFG_LENOVO_TP410] = {
|
||||||
|
.type = HDA_FIXUP_PINS,
|
||||||
|
.v.pins = cxt_pincfg_lenovo_tp410,
|
||||||
|
},
|
||||||
|
[CXT_FIXUP_STEREO_DMIC] = {
|
||||||
|
.type = HDA_FIXUP_FUNC,
|
||||||
|
.v.func = cxt_fixup_stereo_dmic,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_pci_quirk cxt5051_fixups[] = {
|
static const struct snd_pci_quirk cxt5051_fixups[] = {
|
||||||
@ -4520,13 +4505,16 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|||||||
case 0x14f15051:
|
case 0x14f15051:
|
||||||
add_cx5051_fake_mutes(codec);
|
add_cx5051_fake_mutes(codec);
|
||||||
codec->pin_amp_workaround = 1;
|
codec->pin_amp_workaround = 1;
|
||||||
apply_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl);
|
snd_hda_pick_fixup(codec, NULL, cxt5051_fixups, cxt_fixups);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
codec->pin_amp_workaround = 1;
|
codec->pin_amp_workaround = 1;
|
||||||
apply_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl);
|
snd_hda_pick_fixup(codec, NULL, cxt5066_fixups, cxt_fixups);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
||||||
|
|
||||||
/* Show mute-led control only on HP laptops
|
/* Show mute-led control only on HP laptops
|
||||||
* This is a sort of white-list: on HP laptops, EAPD corresponds
|
* This is a sort of white-list: on HP laptops, EAPD corresponds
|
||||||
* only to the mute-LED without actualy amp function. Meanwhile,
|
* only to the mute-LED without actualy amp function. Meanwhile,
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <sound/jack.h>
|
#include <sound/jack.h>
|
||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
|
#include "hda_auto_parser.h"
|
||||||
#include "hda_beep.h"
|
#include "hda_beep.h"
|
||||||
#include "hda_jack.h"
|
#include "hda_jack.h"
|
||||||
|
|
||||||
@ -66,8 +67,6 @@ struct alc_customize_define {
|
|||||||
unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
|
unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alc_fixup;
|
|
||||||
|
|
||||||
struct alc_multi_io {
|
struct alc_multi_io {
|
||||||
hda_nid_t pin; /* multi-io widget pin NID */
|
hda_nid_t pin; /* multi-io widget pin NID */
|
||||||
hda_nid_t dac; /* DAC to be connected */
|
hda_nid_t dac; /* DAC to be connected */
|
||||||
@ -82,19 +81,33 @@ enum {
|
|||||||
|
|
||||||
#define MAX_VOL_NIDS 0x40
|
#define MAX_VOL_NIDS 0x40
|
||||||
|
|
||||||
|
/* make compatible with old code */
|
||||||
|
#define alc_apply_pincfgs snd_hda_apply_pincfgs
|
||||||
|
#define alc_apply_fixup snd_hda_apply_fixup
|
||||||
|
#define alc_pick_fixup snd_hda_pick_fixup
|
||||||
|
#define alc_fixup hda_fixup
|
||||||
|
#define alc_pincfg hda_pintbl
|
||||||
|
#define alc_model_fixup hda_model_fixup
|
||||||
|
|
||||||
|
#define ALC_FIXUP_PINS HDA_FIXUP_PINS
|
||||||
|
#define ALC_FIXUP_VERBS HDA_FIXUP_VERBS
|
||||||
|
#define ALC_FIXUP_FUNC HDA_FIXUP_FUNC
|
||||||
|
|
||||||
|
#define ALC_FIXUP_ACT_PRE_PROBE HDA_FIXUP_ACT_PRE_PROBE
|
||||||
|
#define ALC_FIXUP_ACT_PROBE HDA_FIXUP_ACT_PROBE
|
||||||
|
#define ALC_FIXUP_ACT_INIT HDA_FIXUP_ACT_INIT
|
||||||
|
#define ALC_FIXUP_ACT_BUILD HDA_FIXUP_ACT_BUILD
|
||||||
|
|
||||||
|
|
||||||
struct alc_spec {
|
struct alc_spec {
|
||||||
|
struct hda_gen_spec gen;
|
||||||
|
|
||||||
/* codec parameterization */
|
/* codec parameterization */
|
||||||
const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
|
const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
|
||||||
unsigned int num_mixers;
|
unsigned int num_mixers;
|
||||||
const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
|
const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
|
||||||
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
|
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
|
||||||
|
|
||||||
const struct hda_verb *init_verbs[10]; /* initialization verbs
|
|
||||||
* don't forget NULL
|
|
||||||
* termination!
|
|
||||||
*/
|
|
||||||
unsigned int num_init_verbs;
|
|
||||||
|
|
||||||
char stream_name_analog[32]; /* analog PCM stream */
|
char stream_name_analog[32]; /* analog PCM stream */
|
||||||
const struct hda_pcm_stream *stream_analog_playback;
|
const struct hda_pcm_stream *stream_analog_playback;
|
||||||
const struct hda_pcm_stream *stream_analog_capture;
|
const struct hda_pcm_stream *stream_analog_capture;
|
||||||
@ -210,11 +223,6 @@ struct alc_spec {
|
|||||||
unsigned int pll_coef_idx, pll_coef_bit;
|
unsigned int pll_coef_idx, pll_coef_bit;
|
||||||
unsigned int coef0;
|
unsigned int coef0;
|
||||||
|
|
||||||
/* fix-up list */
|
|
||||||
int fixup_id;
|
|
||||||
const struct alc_fixup *fixup_list;
|
|
||||||
const char *fixup_name;
|
|
||||||
|
|
||||||
/* multi-io */
|
/* multi-io */
|
||||||
int multi_ios;
|
int multi_ios;
|
||||||
struct alc_multi_io multi_io[4];
|
struct alc_multi_io multi_io[4];
|
||||||
@ -396,13 +404,6 @@ static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
|
|||||||
spec->mixers[spec->num_mixers++] = mix;
|
spec->mixers[spec->num_mixers++] = mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
|
|
||||||
{
|
|
||||||
if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
|
|
||||||
return;
|
|
||||||
spec->init_verbs[spec->num_init_verbs++] = verb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPIO setup tables, used in initialization
|
* GPIO setup tables, used in initialization
|
||||||
*/
|
*/
|
||||||
@ -1185,6 +1186,16 @@ static void alc_auto_check_switches(struct hda_codec *codec)
|
|||||||
*/
|
*/
|
||||||
#define ALC_FIXUP_SKU_IGNORE (2)
|
#define ALC_FIXUP_SKU_IGNORE (2)
|
||||||
|
|
||||||
|
static void alc_fixup_sku_ignore(struct hda_codec *codec,
|
||||||
|
const struct hda_fixup *fix, int action)
|
||||||
|
{
|
||||||
|
struct alc_spec *spec = codec->spec;
|
||||||
|
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||||
|
spec->cdefine.fixup = 1;
|
||||||
|
spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int alc_auto_parse_customize_define(struct hda_codec *codec)
|
static int alc_auto_parse_customize_define(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
unsigned int ass, tmp, i;
|
unsigned int ass, tmp, i;
|
||||||
@ -1387,178 +1398,6 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Fix-up pin default configurations and add default verbs
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct alc_pincfg {
|
|
||||||
hda_nid_t nid;
|
|
||||||
u32 val;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct alc_model_fixup {
|
|
||||||
const int id;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct alc_fixup {
|
|
||||||
int type;
|
|
||||||
bool chained;
|
|
||||||
int chain_id;
|
|
||||||
union {
|
|
||||||
unsigned int sku;
|
|
||||||
const struct alc_pincfg *pins;
|
|
||||||
const struct hda_verb *verbs;
|
|
||||||
void (*func)(struct hda_codec *codec,
|
|
||||||
const struct alc_fixup *fix,
|
|
||||||
int action);
|
|
||||||
} v;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ALC_FIXUP_INVALID,
|
|
||||||
ALC_FIXUP_SKU,
|
|
||||||
ALC_FIXUP_PINS,
|
|
||||||
ALC_FIXUP_VERBS,
|
|
||||||
ALC_FIXUP_FUNC,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ALC_FIXUP_ACT_PRE_PROBE,
|
|
||||||
ALC_FIXUP_ACT_PROBE,
|
|
||||||
ALC_FIXUP_ACT_INIT,
|
|
||||||
ALC_FIXUP_ACT_BUILD,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void alc_apply_pincfgs(struct hda_codec *codec,
|
|
||||||
const struct alc_pincfg *cfg)
|
|
||||||
{
|
|
||||||
for (; cfg->nid; cfg++)
|
|
||||||
snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void alc_apply_fixup(struct hda_codec *codec, int action)
|
|
||||||
{
|
|
||||||
struct alc_spec *spec = codec->spec;
|
|
||||||
int id = spec->fixup_id;
|
|
||||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
||||||
const char *modelname = spec->fixup_name;
|
|
||||||
#endif
|
|
||||||
int depth = 0;
|
|
||||||
|
|
||||||
if (!spec->fixup_list)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (id >= 0) {
|
|
||||||
const struct alc_fixup *fix = spec->fixup_list + id;
|
|
||||||
const struct alc_pincfg *cfg;
|
|
||||||
|
|
||||||
switch (fix->type) {
|
|
||||||
case ALC_FIXUP_SKU:
|
|
||||||
if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
|
|
||||||
break;
|
|
||||||
snd_printdd(KERN_INFO "hda_codec: %s: "
|
|
||||||
"Apply sku override for %s\n",
|
|
||||||
codec->chip_name, modelname);
|
|
||||||
spec->cdefine.sku_cfg = fix->v.sku;
|
|
||||||
spec->cdefine.fixup = 1;
|
|
||||||
break;
|
|
||||||
case ALC_FIXUP_PINS:
|
|
||||||
cfg = fix->v.pins;
|
|
||||||
if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
|
|
||||||
break;
|
|
||||||
snd_printdd(KERN_INFO "hda_codec: %s: "
|
|
||||||
"Apply pincfg for %s\n",
|
|
||||||
codec->chip_name, modelname);
|
|
||||||
alc_apply_pincfgs(codec, cfg);
|
|
||||||
break;
|
|
||||||
case ALC_FIXUP_VERBS:
|
|
||||||
if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
|
|
||||||
break;
|
|
||||||
snd_printdd(KERN_INFO "hda_codec: %s: "
|
|
||||||
"Apply fix-verbs for %s\n",
|
|
||||||
codec->chip_name, modelname);
|
|
||||||
add_verb(codec->spec, fix->v.verbs);
|
|
||||||
break;
|
|
||||||
case ALC_FIXUP_FUNC:
|
|
||||||
if (!fix->v.func)
|
|
||||||
break;
|
|
||||||
snd_printdd(KERN_INFO "hda_codec: %s: "
|
|
||||||
"Apply fix-func for %s\n",
|
|
||||||
codec->chip_name, modelname);
|
|
||||||
fix->v.func(codec, fix, action);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snd_printk(KERN_ERR "hda_codec: %s: "
|
|
||||||
"Invalid fixup type %d\n",
|
|
||||||
codec->chip_name, fix->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!fix->chained)
|
|
||||||
break;
|
|
||||||
if (++depth > 10)
|
|
||||||
break;
|
|
||||||
id = fix->chain_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void alc_pick_fixup(struct hda_codec *codec,
|
|
||||||
const struct alc_model_fixup *models,
|
|
||||||
const struct snd_pci_quirk *quirk,
|
|
||||||
const struct alc_fixup *fixlist)
|
|
||||||
{
|
|
||||||
struct alc_spec *spec = codec->spec;
|
|
||||||
const struct snd_pci_quirk *q;
|
|
||||||
int id = -1;
|
|
||||||
const char *name = NULL;
|
|
||||||
|
|
||||||
/* when model=nofixup is given, don't pick up any fixups */
|
|
||||||
if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
|
|
||||||
spec->fixup_list = NULL;
|
|
||||||
spec->fixup_id = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codec->modelname && models) {
|
|
||||||
while (models->name) {
|
|
||||||
if (!strcmp(codec->modelname, models->name)) {
|
|
||||||
id = models->id;
|
|
||||||
name = models->name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
models++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (id < 0) {
|
|
||||||
q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
|
|
||||||
if (q) {
|
|
||||||
id = q->value;
|
|
||||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
||||||
name = q->name;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (id < 0) {
|
|
||||||
for (q = quirk; q->subvendor; q++) {
|
|
||||||
unsigned int vendorid =
|
|
||||||
q->subdevice | (q->subvendor << 16);
|
|
||||||
if (vendorid == codec->subsystem_id) {
|
|
||||||
id = q->value;
|
|
||||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
||||||
name = q->name;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec->fixup_id = id;
|
|
||||||
if (id >= 0) {
|
|
||||||
spec->fixup_list = fixlist;
|
|
||||||
spec->fixup_name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* COEF access helper functions
|
* COEF access helper functions
|
||||||
*/
|
*/
|
||||||
@ -2050,7 +1889,6 @@ static void alc_auto_init_std(struct hda_codec *codec);
|
|||||||
static int alc_init(struct hda_codec *codec)
|
static int alc_init(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct alc_spec *spec = codec->spec;
|
struct alc_spec *spec = codec->spec;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (spec->init_hook)
|
if (spec->init_hook)
|
||||||
spec->init_hook(codec);
|
spec->init_hook(codec);
|
||||||
@ -2058,8 +1896,6 @@ static int alc_init(struct hda_codec *codec)
|
|||||||
alc_fix_pll(codec);
|
alc_fix_pll(codec);
|
||||||
alc_auto_init_amp(codec, spec->init_amp);
|
alc_auto_init_amp(codec, spec->init_amp);
|
||||||
|
|
||||||
for (i = 0; i < spec->num_init_verbs; i++)
|
|
||||||
snd_hda_sequence_write(codec, spec->init_verbs[i]);
|
|
||||||
alc_init_special_input_src(codec);
|
alc_init_special_input_src(codec);
|
||||||
alc_auto_init_std(codec);
|
alc_auto_init_std(codec);
|
||||||
|
|
||||||
@ -4885,7 +4721,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
|
|||||||
spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
|
spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
|
||||||
snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
|
snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
|
||||||
spec->unsol_event = alc_sku_unsol_event;
|
spec->unsol_event = alc_sku_unsol_event;
|
||||||
add_verb(codec->spec, alc_gpio1_init_verbs);
|
snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5216,8 +5052,8 @@ static const struct alc_fixup alc882_fixups[] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[ALC882_FIXUP_ACER_ASPIRE_7736] = {
|
[ALC882_FIXUP_ACER_ASPIRE_7736] = {
|
||||||
.type = ALC_FIXUP_SKU,
|
.type = ALC_FIXUP_FUNC,
|
||||||
.v.sku = ALC_FIXUP_SKU_IGNORE,
|
.v.func = alc_fixup_sku_ignore,
|
||||||
},
|
},
|
||||||
[ALC882_FIXUP_ASUS_W90V] = {
|
[ALC882_FIXUP_ASUS_W90V] = {
|
||||||
.type = ALC_FIXUP_PINS,
|
.type = ALC_FIXUP_PINS,
|
||||||
@ -5693,7 +5529,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
|
|||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
|
if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
|
||||||
add_mixer(spec, alc268_beep_mixer);
|
add_mixer(spec, alc268_beep_mixer);
|
||||||
add_verb(spec, alc268_beep_init_verbs);
|
snd_hda_gen_add_verbs(&spec->gen, alc268_beep_init_verbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@ -5995,8 +5831,8 @@ static const struct alc_fixup alc269_fixups[] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[ALC269_FIXUP_SKU_IGNORE] = {
|
[ALC269_FIXUP_SKU_IGNORE] = {
|
||||||
.type = ALC_FIXUP_SKU,
|
.type = ALC_FIXUP_FUNC,
|
||||||
.v.sku = ALC_FIXUP_SKU_IGNORE,
|
.v.func = alc_fixup_sku_ignore,
|
||||||
},
|
},
|
||||||
[ALC269_FIXUP_ASUS_G73JW] = {
|
[ALC269_FIXUP_ASUS_G73JW] = {
|
||||||
.type = ALC_FIXUP_PINS,
|
.type = ALC_FIXUP_PINS,
|
||||||
@ -6491,7 +6327,7 @@ static int patch_alc861vd(struct hda_codec *codec)
|
|||||||
|
|
||||||
if (codec->vendor_id == 0x10ec0660) {
|
if (codec->vendor_id == 0x10ec0660) {
|
||||||
/* always turn on EAPD */
|
/* always turn on EAPD */
|
||||||
add_verb(spec, alc660vd_eapd_verbs);
|
snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spec->no_analog) {
|
if (!spec->no_analog) {
|
||||||
@ -6604,8 +6440,8 @@ static const struct alc_fixup alc662_fixups[] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[ALC662_FIXUP_SKU_IGNORE] = {
|
[ALC662_FIXUP_SKU_IGNORE] = {
|
||||||
.type = ALC_FIXUP_SKU,
|
.type = ALC_FIXUP_FUNC,
|
||||||
.v.sku = ALC_FIXUP_SKU_IGNORE,
|
.v.func = alc_fixup_sku_ignore,
|
||||||
},
|
},
|
||||||
[ALC662_FIXUP_HP_RP5800] = {
|
[ALC662_FIXUP_HP_RP5800] = {
|
||||||
.type = ALC_FIXUP_PINS,
|
.type = ALC_FIXUP_PINS,
|
||||||
|
Loading…
Reference in New Issue
Block a user