Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a91a4aa1 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/hda' into for-linus

parents 12c2a682 61c2d2b5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -124,6 +124,8 @@ ALC882/883/885/888/889
  asus-a7m	ASUS A7M
  macpro	MacPro support
  mb5		Macbook 5,1
  macmini3	Macmini 3,1
  mba21		Macbook Air 2,1
  mbp3		Macbook Pro rev3
  imac24	iMac 24'' with jack detection
  imac91	iMac 9,1
@@ -279,13 +281,16 @@ Conexant 5051
  laptop	Basic Laptop config (default)
  hp		HP Spartan laptop
  hp-dv6736	HP dv6736
  hp-f700	HP Compaq Presario F700
  lenovo-x200	Lenovo X200 laptop
  toshiba	Toshiba Satellite M300

Conexant 5066
=============
  laptop	Basic Laptop config (default)
  dell-laptop	Dell laptops
  olpc-xo-1_5	OLPC XO 1.5
  ideapad       Lenovo IdeaPad U150

STAC9200
========
+27 −0
Original line number Diff line number Diff line
@@ -452,6 +452,33 @@ Similarly, the lines after `[verb]` are parsed as `init_verbs`
sysfs entries, and the lines after `[hint]` are parsed as `hints`
sysfs entries, respectively.

Another example to override the codec vendor id from 0x12345678 to
0xdeadbeef is like below:
------------------------------------------------------------------------
  [codec]
  0x12345678 0xabcd1234 2

  [vendor_id]
  0xdeadbeef
------------------------------------------------------------------------

In the similar way, you can override the codec subsystem_id via
`[subsystem_id]`, the revision id via `[revision_id]` line.
Also, the codec chip name can be rewritten via `[chip_name]` line.
------------------------------------------------------------------------
  [codec]
  0x12345678 0xabcd1234 2

  [subsystem_id]
  0xffff1111

  [revision_id]
  0x10

  [chip_name]
  My-own NEWS-0002
------------------------------------------------------------------------

The hd-audio driver reads the file via request_firmware().  Thus,
a patch file has to be located on the appropriate firmware path,
typically, /lib/firmware.  For example, when you pass the option
+4 −2
Original line number Diff line number Diff line
@@ -2767,7 +2767,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
			    power_state);
	/* partial workaround for "azx_get_response timeout" */
	if (power_state == AC_PWRST_D0)
	if (power_state == AC_PWRST_D0 &&
	    (codec->vendor_id & 0xffff0000) == 0x14f10000)
		msleep(10);

	nid = codec->start_nid;
@@ -2801,7 +2802,6 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
	if (power_state == AC_PWRST_D0) {
		unsigned long end_time;
		int state;
		msleep(10);
		/* wait until the codec reachs to D0 */
		end_time = jiffies + msecs_to_jiffies(500);
		do {
@@ -3275,6 +3275,8 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {

/*
 * get the empty PCM device number to assign
 *
 * note the max device number is limited by HDA_MAX_PCMS, currently 10
 */
static int get_empty_pcm_device(struct hda_bus *bus, int type)
{
+3 −0
Original line number Diff line number Diff line
@@ -527,6 +527,9 @@ enum {
/* max. codec address */
#define HDA_MAX_CODEC_ADDRESS	0x0f

/* max number of PCM devics per card */
#define HDA_MAX_PCMS		10

/*
 * generic arrays
 */
+38 −15
Original line number Diff line number Diff line
@@ -625,6 +625,10 @@ enum {
	LINE_MODE_PINCFG,
	LINE_MODE_VERB,
	LINE_MODE_HINT,
	LINE_MODE_VENDOR_ID,
	LINE_MODE_SUBSYSTEM_ID,
	LINE_MODE_REVISION_ID,
	LINE_MODE_CHIP_NAME,
	NUM_LINE_MODES,
};

@@ -654,53 +658,71 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus,
}

/* parse the contents after the other command tags, [pincfg], [verb],
 * [hint] and [model]
 * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model]
 * just pass to the sysfs helper (only when any codec was specified)
 */
static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
			      struct hda_codec **codecp)
{
	if (!*codecp)
		return;
	parse_user_pin_configs(*codecp, buf);
}

static void parse_verb_mode(char *buf, struct hda_bus *bus,
			    struct hda_codec **codecp)
{
	if (!*codecp)
		return;
	parse_init_verbs(*codecp, buf);
}

static void parse_hint_mode(char *buf, struct hda_bus *bus,
			    struct hda_codec **codecp)
{
	if (!*codecp)
		return;
	parse_hints(*codecp, buf);
}

static void parse_model_mode(char *buf, struct hda_bus *bus,
			     struct hda_codec **codecp)
{
	if (!*codecp)
		return;
	kfree((*codecp)->modelname);
	(*codecp)->modelname = kstrdup(buf, GFP_KERNEL);
}

static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
				 struct hda_codec **codecp)
{
	kfree((*codecp)->chip_name);
	(*codecp)->chip_name = kstrdup(buf, GFP_KERNEL);
}

#define DEFINE_PARSE_ID_MODE(name) \
static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
				 struct hda_codec **codecp) \
{ \
	unsigned long val; \
	if (!strict_strtoul(buf, 0, &val)) \
		(*codecp)->name = val; \
}

DEFINE_PARSE_ID_MODE(vendor_id);
DEFINE_PARSE_ID_MODE(subsystem_id);
DEFINE_PARSE_ID_MODE(revision_id);


struct hda_patch_item {
	const char *tag;
	void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
	int need_codec;
};

static struct hda_patch_item patch_items[NUM_LINE_MODES] = {
	[LINE_MODE_CODEC] = { "[codec]", parse_codec_mode },
	[LINE_MODE_MODEL] = { "[model]", parse_model_mode },
	[LINE_MODE_VERB] = { "[verb]", parse_verb_mode },
	[LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode },
	[LINE_MODE_HINT] = { "[hint]", parse_hint_mode },
	[LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 },
	[LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 },
	[LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 },
	[LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 },
	[LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 },
	[LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 },
	[LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 },
	[LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 },
	[LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 },
};

/* check the line starting with '[' -- change the parser mode accodingly */
@@ -783,7 +805,8 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch)
			continue;
		if (*buf == '[')
			line_mode = parse_line_mode(buf, bus);
		else if (patch_items[line_mode].parser)
		else if (patch_items[line_mode].parser &&
			 (codec || !patch_items[line_mode].need_codec))
			patch_items[line_mode].parser(buf, bus, &codec);
	}
	release_firmware(fw);
Loading