// SPDX-License-Identifier: GPL-2.0
//
// simple-card-utils.c
//
// Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
#include <dt-bindings/sound/audio-graph.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/simple_card_utils.h>
int simple_util_get_sample_fmt(struct simple_util_data *data)
{
int i;
int val = -EINVAL;
struct {
char *fmt;
u32 val;
} of_sample_fmt_table[] = {
{ "s8", SNDRV_PCM_FORMAT_S8},
{ "s16_le", SNDRV_PCM_FORMAT_S16_LE},
{ "s24_le", SNDRV_PCM_FORMAT_S24_LE},
{ "s24_3le", SNDRV_PCM_FORMAT_S24_3LE},
{ "s32_le", SNDRV_PCM_FORMAT_S32_LE},
};
for (i = 0; i < ARRAY_SIZE(of_sample_fmt_table); i++) {
if (!strcmp(data->convert_sample_format,
of_sample_fmt_table[i].fmt)) {
val = of_sample_fmt_table[i].val;
break;
}
}
return val;
}
EXPORT_SYMBOL_GPL(simple_util_get_sample_fmt);
static void simple_fixup_sample_fmt(struct simple_util_data *data,
struct snd_pcm_hw_params *params)
{
int val;
struct snd_mask *mask = hw_param_mask(params,
SNDRV_PCM_HW_PARAM_FORMAT);
val = simple_util_get_sample_fmt(data);
if (val >= 0) {
snd_mask_none(mask);
snd_mask_set(mask, val);
}
}
void simple_util_parse_convert(struct device_node *np,
char *prefix,
struct simple_util_data *data)
{
char prop[128];
if (!np)
return;
if (!prefix)
prefix = "";
/* sampling rate convert */
snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate");
of_property_read_u32(np, prop, &data->convert_rate);
/* channels transfer */
snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels");
of_property_read_u32(np, prop, &data->convert_channels);
/* convert sample format */
snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-sample-format");
of_property_read_string(np, prop, &data->convert_sample_format);
}
EXPORT_SYMBOL_GPL(simple_util_parse_convert);
/**
* simple_util_is_convert_required() - Query if HW param conversion was requested
* @data: Link data.
*
* Returns true if any HW param conversion was requested for this DAI link with
* any "convert-xxx" properties.
*/
bool simple_util_is_convert_required(const struct simple_util_data *data)
{
return data->convert_rate ||
data->convert_channels ||
data->convert_sample_format;
}
EXPORT_SYMBOL_GPL(simple_util_is_convert_required);
int simple_util_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
char *prefix,
unsigned int *retfmt)
{
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
unsigned int daifmt;
daifmt = snd_soc_daifmt_parse_format(node, prefix);
snd_soc_daifmt_parse_clock_provider_as_phandle(node, prefix, &bitclkmaster, &framemaster);
if (!bitclkmaster && !framemaster) {
/*
* No dai-link level and master setting was not found from
* sound node level, revert back to legacy DT parsing and
* take the settings from codec node.
*/
dev_dbg(dev, "Revert to legacy daifmt parsing\n");
daifmt |= snd_soc_daifmt_parse_clock_provider_as_flag(codec, NULL);
} else {
daifmt |= snd_soc_daifmt_clock_provider_from_bitmap(
((codec == bitclkmaster)