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

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

Merge branch 'topic/hda-cache' into topic/hda

parents 85894077 586be3fc
Loading
Loading
Loading
Loading
+74 −40
Original line number Diff line number Diff line
@@ -175,14 +175,23 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
				unsigned int verb, unsigned int parm)
{
	struct hda_bus *bus = codec->bus;
	unsigned int res;
	unsigned int cmd, res;
	int repeated = 0;

	res = make_codec_cmd(codec, nid, direct, verb, parm);
	cmd = make_codec_cmd(codec, nid, direct, verb, parm);
	snd_hda_power_up(codec);
	mutex_lock(&bus->cmd_mutex);
	if (!bus->ops.command(bus, res))
 again:
	if (!bus->ops.command(bus, cmd)) {
		res = bus->ops.get_response(bus);
	else
		if (res == -1 && bus->rirb_error) {
			if (repeated++ < 1) {
				snd_printd(KERN_WARNING "hda_codec: "
					   "Trying verb 0x%08x again\n", cmd);
				goto again;
			}
		}
	} else
		res = (unsigned int)-1;
	mutex_unlock(&bus->cmd_mutex);
	snd_hda_power_down(codec);
@@ -1056,6 +1065,8 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
/* FIXME: more better hash key? */
#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
#define INFO_AMP_CAPS	(1<<0)
#define INFO_AMP_VOL(ch)	(1 << (1 + (ch)))

@@ -1146,19 +1157,32 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
}
EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);

u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
static unsigned int
query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
		unsigned int (*func)(struct hda_codec *, hda_nid_t))
{
	struct hda_amp_info *info;

	info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
	info = get_alloc_amp_hash(codec, key);
	if (!info)
		return 0;
	if (!info->head.val) {
		info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
		info->head.val |= INFO_AMP_CAPS;
		info->amp_caps = func(codec, nid);
	}
	return info->amp_caps;
}

static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
{
	return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
}

u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
{
	return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
			       read_pin_cap);
}
EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);

/*
@@ -2547,6 +2571,41 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
}
EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);

static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
{
	unsigned int val = 0;
	if (nid != codec->afg &&
	    (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
	if (!val || val == -1)
		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
	if (!val || val == -1)
		return 0;
	return val;
}

static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
{
	return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
			       get_pcm_param);
}

static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
{
	unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
	if (!streams || streams == -1)
		streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
	if (!streams || streams == -1)
		return 0;
	return streams;
}

static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
{
	return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
			       get_stream_param);
}

/**
 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
 * @codec: the HDA codec
@@ -2565,15 +2624,8 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
{
	unsigned int i, val, wcaps;

	val = 0;
	wcaps = get_wcaps(codec, nid);
	if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
		if (val == -1)
			return -EIO;
	}
	if (!val)
		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
	val = query_pcm_param(codec, nid);

	if (ratesp) {
		u32 rates = 0;
@@ -2595,15 +2647,9 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
		u64 formats = 0;
		unsigned int streams, bps;

		streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
		if (streams == -1)
			return -EIO;
		if (!streams) {
			streams = snd_hda_param_read(codec, codec->afg,
						     AC_PAR_STREAM);
			if (streams == -1)
		streams = query_stream_param(codec, nid);
		if (!streams)
			return -EIO;
		}

		bps = 0;
		if (streams & AC_SUPFMT_PCM) {
@@ -2677,17 +2723,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
	int i;
	unsigned int val = 0, rate, stream;

	if (nid != codec->afg &&
	    (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
		if (val == -1)
			return 0;
	}
	if (!val) {
		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
		if (val == -1)
	val = query_pcm_param(codec, nid);
	if (!val)
		return 0;
	}

	rate = format & 0xff00;
	for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
@@ -2699,12 +2737,8 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
	if (i >= AC_PAR_PCM_RATE_BITS)
		return 0;

	stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
	if (stream == -1)
		return 0;
	if (!stream && nid != codec->afg)
		stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
	if (!stream || stream == -1)
	stream = query_stream_param(codec, nid);
	if (!stream)
		return 0;

	if (stream & AC_SUPFMT_PCM) {
+1 −0
Original line number Diff line number Diff line
@@ -623,6 +623,7 @@ struct hda_bus {
	/* misc op flags */
	unsigned int needs_damn_long_delay :1;
	unsigned int shutdown :1;	/* being unloaded */
	unsigned int rirb_error:1;	/* error in codec communication */
};

/*
+10 −9
Original line number Diff line number Diff line
@@ -606,6 +606,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
		}
		if (!chip->rirb.cmds) {
			smp_rmb();
			bus->rirb_error = 0;
			return chip->rirb.res; /* the last value */
		}
		if (time_after(jiffies, timeout))
@@ -625,8 +626,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
		chip->irq = -1;
		pci_disable_msi(chip->pci);
		chip->msi = 0;
		if (azx_acquire_irq(chip, 1) < 0)
		if (azx_acquire_irq(chip, 1) < 0) {
			bus->rirb_error = 1;
			return -1;
		}
		goto again;
	}

@@ -646,14 +649,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
		return -1;
	}

	snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
		   "switching to single_cmd mode: last cmd=0x%08x\n",
		   chip->last_cmd);
	chip->rirb.rp = azx_readb(chip, RIRBWP);
	chip->rirb.cmds = 0;
	/* switch to single_cmd mode */
	chip->single_cmd = 1;
	azx_free_cmd_io(chip);
	snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): "
		   "last cmd=0x%08x\n", chip->last_cmd);
	spin_lock_irq(&chip->reg_lock);
	chip->rirb.cmds = 0; /* reset the index */
	bus->rirb_error = 1;
	spin_unlock_irq(&chip->reg_lock);
	return -1;
}

+5 −0
Original line number Diff line number Diff line
@@ -1024,6 +1024,9 @@ static void alc_subsystem_id(struct hda_codec *codec,
	if (codec->vendor_id == 0x10ec0260)
		nid = 0x17;
	ass = snd_hda_codec_get_pincfg(codec, nid);
	snd_printd("realtek: No valid SSID, "
		   "checking pincfg 0x%08x for NID 0x%x\n",
		   nid, ass);
	if (!(ass & 1) && !(ass & 0x100000))
		return;
	if ((ass >> 30) != 1)	/* no physical connection */
@@ -1038,6 +1041,8 @@ static void alc_subsystem_id(struct hda_codec *codec,
	if (((ass >> 16) & 0xf) != tmp)
		return;
do_sku:
	snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
		   ass & 0xffff, codec->vendor_id);
	/*
	 * 0 : override
	 * 1 :	Swap Jack