ALSA: hda: Upgrade stream-format infrastructure
commit d24f1a090d3f2a5c86a8782afeda71c2d2539966 upstream. Introduce a set of functions that ultimately facilite SDxFMT-related calculations in atomic manner: First, introduce snd_pcm_subformat_width() and snd_pcm_hw_params_bits() helpers that separate the base functionality from the HDAudio-specific one. snd_hdac_format_normalize() - format converter. S20_LE, S24_LE and their unsigned and BE friends are invalid from HDAudio perspective but still can be specified as function argument due to compatibility reasons. snd_hdac_stream_format_bits() - obtain just the bits-per-sample value. Does not ignore subformat and msbits parameters. snd_hdac_stream_format() and snd_hdac_spdif_stream_format() - obtain the SDxFMT value given the audio format parameters. The former is stripped away of spdif-related information. Useful for users that do not care about them. Acked-by: Mark Brown <broonie@kernel.org> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Acked-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20231117120610.1755254-5-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
7bd798a923
commit
8f362f3483
|
@ -140,6 +140,11 @@ int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
|
||||||
hda_nid_t *conn_list, int max_conns);
|
hda_nid_t *conn_list, int max_conns);
|
||||||
int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
|
int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
|
||||||
hda_nid_t *start_id);
|
hda_nid_t *start_id);
|
||||||
|
unsigned int snd_hdac_stream_format_bits(snd_pcm_format_t format, snd_pcm_subformat_t subformat,
|
||||||
|
unsigned int maxbits);
|
||||||
|
unsigned int snd_hdac_stream_format(unsigned int channels, unsigned int bits, unsigned int rate);
|
||||||
|
unsigned int snd_hdac_spdif_stream_format(unsigned int channels, unsigned int bits,
|
||||||
|
unsigned int rate, unsigned short spdif_ctls);
|
||||||
unsigned int snd_hdac_calc_stream_format(unsigned int rate,
|
unsigned int snd_hdac_calc_stream_format(unsigned int rate,
|
||||||
unsigned int channels,
|
unsigned int channels,
|
||||||
snd_pcm_format_t format,
|
snd_pcm_format_t format,
|
||||||
|
|
|
@ -362,6 +362,8 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p)
|
||||||
return snd_pcm_format_physical_width(params_format(p));
|
return snd_pcm_format_physical_width(params_format(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snd_pcm_hw_params_bits(const struct snd_pcm_hw_params *p);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
|
params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1681,6 +1681,40 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_pcm_hw_param_last);
|
EXPORT_SYMBOL(snd_pcm_hw_param_last);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_pcm_hw_params_bits - Get the number of bits per the sample.
|
||||||
|
* @p: hardware parameters
|
||||||
|
*
|
||||||
|
* Return: The number of bits per sample based on the format,
|
||||||
|
* subformat and msbits the specified hw params has.
|
||||||
|
*/
|
||||||
|
int snd_pcm_hw_params_bits(const struct snd_pcm_hw_params *p)
|
||||||
|
{
|
||||||
|
snd_pcm_subformat_t subformat = params_subformat(p);
|
||||||
|
snd_pcm_format_t format = params_format(p);
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case SNDRV_PCM_FORMAT_S32_LE:
|
||||||
|
case SNDRV_PCM_FORMAT_U32_LE:
|
||||||
|
case SNDRV_PCM_FORMAT_S32_BE:
|
||||||
|
case SNDRV_PCM_FORMAT_U32_BE:
|
||||||
|
switch (subformat) {
|
||||||
|
case SNDRV_PCM_SUBFORMAT_MSBITS_20:
|
||||||
|
return 20;
|
||||||
|
case SNDRV_PCM_SUBFORMAT_MSBITS_24:
|
||||||
|
return 24;
|
||||||
|
case SNDRV_PCM_SUBFORMAT_MSBITS_MAX:
|
||||||
|
case SNDRV_PCM_SUBFORMAT_STD:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fallthrough;
|
||||||
|
default:
|
||||||
|
return snd_pcm_format_width(format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(snd_pcm_hw_params_bits);
|
||||||
|
|
||||||
static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
|
static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <sound/hdaudio.h>
|
#include <sound/hdaudio.h>
|
||||||
#include <sound/hda_regmap.h>
|
#include <sound/hda_regmap.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
|
#include <sound/pcm_params.h>
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
|
|
||||||
static void setup_fg_nodes(struct hdac_device *codec);
|
static void setup_fg_nodes(struct hdac_device *codec);
|
||||||
|
@ -724,6 +725,129 @@ static const struct hda_rate_tbl rate_bits[] = {
|
||||||
{ 0 } /* terminator */
|
{ 0 } /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static snd_pcm_format_t snd_hdac_format_normalize(snd_pcm_format_t format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case SNDRV_PCM_FORMAT_S20_LE:
|
||||||
|
case SNDRV_PCM_FORMAT_S24_LE:
|
||||||
|
return SNDRV_PCM_FORMAT_S32_LE;
|
||||||
|
|
||||||
|
case SNDRV_PCM_FORMAT_U20_LE:
|
||||||
|
case SNDRV_PCM_FORMAT_U24_LE:
|
||||||
|
return SNDRV_PCM_FORMAT_U32_LE;
|
||||||
|
|
||||||
|
case SNDRV_PCM_FORMAT_S20_BE:
|
||||||
|
case SNDRV_PCM_FORMAT_S24_BE:
|
||||||
|
return SNDRV_PCM_FORMAT_S32_BE;
|
||||||
|
|
||||||
|
case SNDRV_PCM_FORMAT_U20_BE:
|
||||||
|
case SNDRV_PCM_FORMAT_U24_BE:
|
||||||
|
return SNDRV_PCM_FORMAT_U32_BE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_hdac_stream_format_bits - obtain bits per sample value.
|
||||||
|
* @format: the PCM format.
|
||||||
|
* @subformat: the PCM subformat.
|
||||||
|
* @maxbits: the maximum bits per sample.
|
||||||
|
*
|
||||||
|
* Return: The number of bits per sample.
|
||||||
|
*/
|
||||||
|
unsigned int snd_hdac_stream_format_bits(snd_pcm_format_t format, snd_pcm_subformat_t subformat,
|
||||||
|
unsigned int maxbits)
|
||||||
|
{
|
||||||
|
struct snd_pcm_hw_params params;
|
||||||
|
unsigned int bits;
|
||||||
|
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
params_set_format(¶ms, snd_hdac_format_normalize(format));
|
||||||
|
snd_mask_set(hw_param_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT),
|
||||||
|
(__force unsigned int)subformat);
|
||||||
|
|
||||||
|
bits = snd_pcm_hw_params_bits(¶ms);
|
||||||
|
if (maxbits)
|
||||||
|
return min(bits, maxbits);
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_stream_format_bits);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_hdac_stream_format - convert format parameters to SDxFMT value.
|
||||||
|
* @channels: the number of channels.
|
||||||
|
* @bits: bits per sample.
|
||||||
|
* @rate: the sample rate.
|
||||||
|
*
|
||||||
|
* Return: The format bitset or zero if invalid.
|
||||||
|
*/
|
||||||
|
unsigned int snd_hdac_stream_format(unsigned int channels, unsigned int bits, unsigned int rate)
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; rate_bits[i].hz; i++) {
|
||||||
|
if (rate_bits[i].hz == rate) {
|
||||||
|
val = rate_bits[i].hda_fmt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rate_bits[i].hz)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (channels == 0 || channels > 8)
|
||||||
|
return 0;
|
||||||
|
val |= channels - 1;
|
||||||
|
|
||||||
|
switch (bits) {
|
||||||
|
case 8:
|
||||||
|
val |= AC_FMT_BITS_8;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
val |= AC_FMT_BITS_16;
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
val |= AC_FMT_BITS_20;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
val |= AC_FMT_BITS_24;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
val |= AC_FMT_BITS_32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_stream_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_hdac_spdif_stream_format - convert format parameters to SDxFMT value.
|
||||||
|
* @channels: the number of channels.
|
||||||
|
* @bits: bits per sample.
|
||||||
|
* @rate: the sample rate.
|
||||||
|
* @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant).
|
||||||
|
*
|
||||||
|
* Return: The format bitset or zero if invalid.
|
||||||
|
*/
|
||||||
|
unsigned int snd_hdac_spdif_stream_format(unsigned int channels, unsigned int bits,
|
||||||
|
unsigned int rate, unsigned short spdif_ctls)
|
||||||
|
{
|
||||||
|
unsigned int val = snd_hdac_stream_format(channels, bits, rate);
|
||||||
|
|
||||||
|
if (val && spdif_ctls & AC_DIG1_NONAUDIO)
|
||||||
|
val |= AC_FMT_TYPE_NON_PCM;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_spdif_stream_format);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hdac_calc_stream_format - calculate the format bitset
|
* snd_hdac_calc_stream_format - calculate the format bitset
|
||||||
* @rate: the sample rate
|
* @rate: the sample rate
|
||||||
|
|
Loading…
Reference in New Issue