Commit 05852448 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Support indirect execution of verbs

Add an overriding exec_verb op to struct hdac_device so that the call
via snd_hdac_exec_verb() can switch to a different route depending on
the setup.  The codec driver sets this field so that it can handle the
errors or applying quirks appropriately.  Furthermore, this mechanism
will be used for smooth transition for the regmap support in later
patches.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 3256be65
...@@ -48,6 +48,10 @@ struct hdac_device { ...@@ -48,6 +48,10 @@ struct hdac_device {
const char *vendor_name; /* codec vendor name */ const char *vendor_name; /* codec vendor name */
const char *chip_name; /* codec chip name */ const char *chip_name; /* codec chip name */
/* verb exec op override */
int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
unsigned int flags, unsigned int *res);
/* widgets */ /* widgets */
unsigned int num_nodes; unsigned int num_nodes;
hda_nid_t start_nid, end_nid; hda_nid_t start_nid, end_nid;
...@@ -82,6 +86,8 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec); ...@@ -82,6 +86,8 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec);
unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm); unsigned int verb, unsigned int parm);
int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd,
unsigned int flags, unsigned int *res);
int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm, unsigned int *res); unsigned int verb, unsigned int parm, unsigned int *res);
int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm); int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm);
......
...@@ -193,6 +193,28 @@ unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, ...@@ -193,6 +193,28 @@ unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
} }
EXPORT_SYMBOL_GPL(snd_hdac_make_cmd); EXPORT_SYMBOL_GPL(snd_hdac_make_cmd);
/**
* snd_hdac_exec_verb - execute an encoded verb
* @codec: the codec object
* @cmd: encoded verb to execute
* @flags: optional flags, pass zero for default
* @res: the pointer to store the result, NULL if running async
*
* Returns zero if successful, or a negative error code.
*
* This calls the exec_verb op when set in hdac_codec. If not,
* call the default snd_hdac_bus_exec_verb().
*/
int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd,
unsigned int flags, unsigned int *res)
{
if (codec->exec_verb)
return codec->exec_verb(codec, cmd, flags, res);
return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res);
}
EXPORT_SYMBOL_GPL(snd_hdac_exec_verb);
/** /**
* snd_hdac_read - execute a verb * snd_hdac_read - execute a verb
* @codec: the codec object * @codec: the codec object
...@@ -208,7 +230,7 @@ int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, ...@@ -208,7 +230,7 @@ int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
{ {
unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm); unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm);
return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res); return snd_hdac_exec_verb(codec, cmd, 0, res);
} }
EXPORT_SYMBOL_GPL(snd_hdac_read); EXPORT_SYMBOL_GPL(snd_hdac_read);
......
...@@ -124,11 +124,12 @@ const char *snd_hda_get_jack_type(u32 cfg) ...@@ -124,11 +124,12 @@ const char *snd_hda_get_jack_type(u32 cfg)
EXPORT_SYMBOL_GPL(snd_hda_get_jack_type); EXPORT_SYMBOL_GPL(snd_hda_get_jack_type);
/* /*
* Send and receive a verb * Send and receive a verb - passed to exec_verb override for hdac_device
*/ */
static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
int flags, unsigned int *res) unsigned int flags, unsigned int *res)
{ {
struct hda_codec *codec = container_of(dev, struct hda_codec, core);
struct hda_bus *bus = codec->bus; struct hda_bus *bus = codec->bus;
int err; int err;
...@@ -177,7 +178,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, ...@@ -177,7 +178,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
{ {
unsigned int cmd = snd_hdac_make_cmd(&codec->core, nid, verb, parm); unsigned int cmd = snd_hdac_make_cmd(&codec->core, nid, verb, parm);
unsigned int res; unsigned int res;
if (codec_exec_verb(codec, cmd, flags, &res)) if (snd_hdac_exec_verb(&codec->core, cmd, flags, &res))
return -1; return -1;
return res; return res;
} }
...@@ -199,7 +200,7 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, ...@@ -199,7 +200,7 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
unsigned int verb, unsigned int parm) unsigned int verb, unsigned int parm)
{ {
unsigned int cmd = snd_hdac_make_cmd(&codec->core, nid, verb, parm); unsigned int cmd = snd_hdac_make_cmd(&codec->core, nid, verb, parm);
return codec_exec_verb(codec, cmd, flags, NULL); return snd_hdac_exec_verb(&codec->core, cmd, flags, NULL);
} }
EXPORT_SYMBOL_GPL(snd_hda_codec_write); EXPORT_SYMBOL_GPL(snd_hda_codec_write);
...@@ -1026,6 +1027,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, ...@@ -1026,6 +1027,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
codec->core.dev.release = snd_hda_codec_dev_release; codec->core.dev.release = snd_hda_codec_dev_release;
codec->core.type = HDA_DEV_LEGACY; codec->core.type = HDA_DEV_LEGACY;
codec->core.exec_verb = codec_exec_verb;
codec->bus = bus; codec->bus = bus;
codec->card = card; codec->card = card;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment