ALSA: hda - Build PCMs and controls at codec driver probe
This makes the code flow easier -- instead of the controller driver calling snd_hda_build_pcms() and snd_hda_build_controls() explicitly, the codec driver itself builds PCMs and controls at probe time. Then the controller driver only needs to call snd_card_register(). Also, this allows us the full bind/unbind control, too. Even when a codec driver is bound later, it automatically registers the new PCM and controls by itself. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Родитель
9a6246ff78
Коммит
bcd96557bd
|
@ -106,16 +106,28 @@ static int hda_codec_driver_probe(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = codec->preset->patch(codec);
|
err = codec->preset->patch(codec);
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
module_put(owner);
|
goto error_module;
|
||||||
goto error;
|
|
||||||
|
err = snd_hda_codec_build_pcms(codec);
|
||||||
|
if (err < 0)
|
||||||
|
goto error_module;
|
||||||
|
err = snd_hda_codec_build_controls(codec);
|
||||||
|
if (err < 0)
|
||||||
|
goto error_module;
|
||||||
|
if (codec->card->registered) {
|
||||||
|
err = snd_card_register(codec->card);
|
||||||
|
if (err < 0)
|
||||||
|
goto error_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_module:
|
||||||
|
module_put(owner);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
codec->preset = NULL;
|
snd_hda_codec_cleanup_for_unbind(codec);
|
||||||
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4031,36 +4031,6 @@ const struct dev_pm_ops hda_codec_driver_pm = {
|
||||||
NULL)
|
NULL)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_hda_build_controls - build mixer controls
|
|
||||||
* @bus: the BUS
|
|
||||||
*
|
|
||||||
* Creates mixer controls for each codec included in the bus.
|
|
||||||
*
|
|
||||||
* Returns 0 if successful, otherwise a negative error code.
|
|
||||||
*/
|
|
||||||
int snd_hda_build_controls(struct hda_bus *bus)
|
|
||||||
{
|
|
||||||
struct hda_codec *codec;
|
|
||||||
|
|
||||||
list_for_each_entry(codec, &bus->codec_list, list) {
|
|
||||||
int err = snd_hda_codec_build_controls(codec);
|
|
||||||
if (err < 0) {
|
|
||||||
codec_err(codec,
|
|
||||||
"cannot build controls for #%d (error %d)\n",
|
|
||||||
codec->addr, err);
|
|
||||||
err = snd_hda_codec_reset(codec);
|
|
||||||
if (err < 0) {
|
|
||||||
codec_err(codec,
|
|
||||||
"cannot revert codec\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(snd_hda_build_controls);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add standard channel maps if not specified
|
* add standard channel maps if not specified
|
||||||
*/
|
*/
|
||||||
|
@ -4692,43 +4662,6 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_hda_build_pcms - build PCM information
|
|
||||||
* @bus: the BUS
|
|
||||||
*
|
|
||||||
* Create PCM information for each codec included in the bus.
|
|
||||||
*
|
|
||||||
* The build_pcms codec patch is requested to create and assign new
|
|
||||||
* hda_pcm objects. The codec is responsible to call snd_hda_codec_pcm_new()
|
|
||||||
* and fills the fields. Later they are instantiated by this function.
|
|
||||||
*
|
|
||||||
* At least, substreams, channels_min and channels_max must be filled for
|
|
||||||
* each stream. substreams = 0 indicates that the stream doesn't exist.
|
|
||||||
* When rates and/or formats are zero, the supported values are queried
|
|
||||||
* from the given nid. The nid is used also by the default ops.prepare
|
|
||||||
* and ops.cleanup callbacks.
|
|
||||||
*
|
|
||||||
* The driver needs to call ops.open in its open callback. Similarly,
|
|
||||||
* ops.close is supposed to be called in the close callback.
|
|
||||||
* ops.prepare should be called in the prepare or hw_params callback
|
|
||||||
* with the proper parameters for set up.
|
|
||||||
* ops.cleanup should be called in hw_free for clean up of streams.
|
|
||||||
*
|
|
||||||
* This function returns 0 if successful, or a negative error code.
|
|
||||||
*/
|
|
||||||
int snd_hda_build_pcms(struct hda_bus *bus)
|
|
||||||
{
|
|
||||||
struct hda_codec *codec;
|
|
||||||
|
|
||||||
list_for_each_entry(codec, &bus->codec_list, list) {
|
|
||||||
int err = snd_hda_codec_build_pcms(codec);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(snd_hda_build_pcms);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_add_new_ctls - create controls from the array
|
* snd_hda_add_new_ctls - create controls from the array
|
||||||
* @codec: the HDA codec
|
* @codec: the HDA codec
|
||||||
|
|
|
@ -516,13 +516,11 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid);
|
||||||
/*
|
/*
|
||||||
* Mixer
|
* Mixer
|
||||||
*/
|
*/
|
||||||
int snd_hda_build_controls(struct hda_bus *bus);
|
|
||||||
int snd_hda_codec_build_controls(struct hda_codec *codec);
|
int snd_hda_codec_build_controls(struct hda_codec *codec);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PCM
|
* PCM
|
||||||
*/
|
*/
|
||||||
int snd_hda_build_pcms(struct hda_bus *bus);
|
|
||||||
int snd_hda_codec_parse_pcms(struct hda_codec *codec);
|
int snd_hda_codec_parse_pcms(struct hda_codec *codec);
|
||||||
int snd_hda_codec_build_pcms(struct hda_codec *codec);
|
int snd_hda_codec_build_pcms(struct hda_codec *codec);
|
||||||
|
|
||||||
|
|
|
@ -1895,16 +1895,6 @@ static int azx_probe_continue(struct azx *chip)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create PCM streams */
|
|
||||||
err = snd_hda_build_pcms(chip->bus);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
/* create mixer controls */
|
|
||||||
err = snd_hda_build_controls(chip->bus);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
err = snd_card_register(chip->card);
|
err = snd_card_register(chip->card);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
|
@ -497,16 +497,6 @@ static int hda_tegra_probe(struct platform_device *pdev)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
/* create PCM streams */
|
|
||||||
err = snd_hda_build_pcms(chip->bus);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
/* create mixer controls */
|
|
||||||
err = snd_hda_build_controls(chip->bus);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
err = snd_card_register(chip->card);
|
err = snd_card_register(chip->card);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче