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


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


STAC9200
STAC9200
========
========
+27 −0
Original line number Original line 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, and the lines after `[hint]` are parsed as `hints`
sysfs entries, respectively.
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,
The hd-audio driver reads the file via request_firmware().  Thus,
a patch file has to be located on the appropriate firmware path,
a patch file has to be located on the appropriate firmware path,
typically, /lib/firmware.  For example, when you pass the option
typically, /lib/firmware.  For example, when you pass the option
+4 −2
Original line number Original line 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,
	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
			    power_state);
			    power_state);
	/* partial workaround for "azx_get_response timeout" */
	/* 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);
		msleep(10);


	nid = codec->start_nid;
	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) {
	if (power_state == AC_PWRST_D0) {
		unsigned long end_time;
		unsigned long end_time;
		int state;
		int state;
		msleep(10);
		/* wait until the codec reachs to D0 */
		/* wait until the codec reachs to D0 */
		end_time = jiffies + msecs_to_jiffies(500);
		end_time = jiffies + msecs_to_jiffies(500);
		do {
		do {
@@ -3275,6 +3275,8 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {


/*
/*
 * get the empty PCM device number to assign
 * 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)
static int get_empty_pcm_device(struct hda_bus *bus, int type)
{
{
+3 −0
Original line number Original line Diff line number Diff line
@@ -527,6 +527,9 @@ enum {
/* max. codec address */
/* max. codec address */
#define HDA_MAX_CODEC_ADDRESS	0x0f
#define HDA_MAX_CODEC_ADDRESS	0x0f


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

/*
/*
 * generic arrays
 * generic arrays
 */
 */
+38 −15
Original line number Original line Diff line number Diff line
@@ -625,6 +625,10 @@ enum {
	LINE_MODE_PINCFG,
	LINE_MODE_PINCFG,
	LINE_MODE_VERB,
	LINE_MODE_VERB,
	LINE_MODE_HINT,
	LINE_MODE_HINT,
	LINE_MODE_VENDOR_ID,
	LINE_MODE_SUBSYSTEM_ID,
	LINE_MODE_REVISION_ID,
	LINE_MODE_CHIP_NAME,
	NUM_LINE_MODES,
	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],
/* 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)
 * just pass to the sysfs helper (only when any codec was specified)
 */
 */
static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
			      struct hda_codec **codecp)
			      struct hda_codec **codecp)
{
{
	if (!*codecp)
		return;
	parse_user_pin_configs(*codecp, buf);
	parse_user_pin_configs(*codecp, buf);
}
}


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


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


static void parse_model_mode(char *buf, struct hda_bus *bus,
static void parse_model_mode(char *buf, struct hda_bus *bus,
			     struct hda_codec **codecp)
			     struct hda_codec **codecp)
{
{
	if (!*codecp)
		return;
	kfree((*codecp)->modelname);
	kfree((*codecp)->modelname);
	(*codecp)->modelname = kstrdup(buf, GFP_KERNEL);
	(*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 {
struct hda_patch_item {
	const char *tag;
	const char *tag;
	void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
	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] = {
static struct hda_patch_item patch_items[NUM_LINE_MODES] = {
	[LINE_MODE_CODEC] = { "[codec]", parse_codec_mode },
	[LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 },
	[LINE_MODE_MODEL] = { "[model]", parse_model_mode },
	[LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 },
	[LINE_MODE_VERB] = { "[verb]", parse_verb_mode },
	[LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 },
	[LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode },
	[LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 },
	[LINE_MODE_HINT] = { "[hint]", parse_hint_mode },
	[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 */
/* 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;
			continue;
		if (*buf == '[')
		if (*buf == '[')
			line_mode = parse_line_mode(buf, bus);
			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);
			patch_items[line_mode].parser(buf, bus, &codec);
	}
	}
	release_firmware(fw);
	release_firmware(fw);
Loading