#include <linux/module.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "src4xxx.h"
struct src4xxx { … };
enum { … };
static const DECLARE_TLV_DB_SCALE(src_tlv, -12750, 50, 0);
static const struct snd_kcontrol_new src4xxx_controls[] = …;
static const char * const port_out_src_text[] = …;
static SOC_ENUM_SINGLE_DECL(porta_out_src_enum, SRC4XXX_PORTA_CTL_03, 4,
port_out_src_text);
static SOC_ENUM_SINGLE_DECL(portb_out_src_enum, SRC4XXX_PORTB_CTL_05, 4,
port_out_src_text);
static const struct snd_kcontrol_new porta_out_control = …;
static const struct snd_kcontrol_new portb_out_control = …;
static const char * const dit_mux_text[] = …;
static SOC_ENUM_SINGLE_DECL(dit_mux_enum, SRC4XXX_TX_CTL_07, 3, dit_mux_text);
static const struct snd_kcontrol_new dit_mux_control = …;
static const char * const src_in_text[] = …;
static SOC_ENUM_SINGLE_DECL(src_in_enum, SRC4XXX_SCR_CTL_2D, 0, src_in_text);
static const struct snd_kcontrol_new src_in_control = …;
static const char * const dir_in_text[] = …;
static SOC_ENUM_SINGLE_DECL(dir_in_enum, SRC4XXX_RCV_CTL_0D, 0, dir_in_text);
static const struct snd_kcontrol_new dir_in_control = …;
static const struct snd_soc_dapm_widget src4xxx_dapm_widgets[] = …;
static const struct snd_soc_dapm_route src4xxx_audio_routes[] = …;
static const struct snd_soc_component_driver src4xxx_driver = …;
static int src4xxx_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{ … }
static int src4xxx_set_mclk_hz(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{ … }
static int src4xxx_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct src4xxx *src4xxx = snd_soc_component_get_drvdata(component);
unsigned int mclk_div;
int val, pj, jd, d;
int reg;
int ret;
switch (dai->id) {
case SRC4XXX_PORTB:
reg = SRC4XXX_PORTB_CTL_06;
break;
default:
reg = SRC4XXX_PORTA_CTL_04;
break;
}
if (src4xxx->master[dai->id]) {
mclk_div = src4xxx->mclk_hz/params_rate(params);
if (src4xxx->mclk_hz != mclk_div*params_rate(params)) {
dev_err(component->dev,
"mclk %d / rate %d has a remainder.\n",
src4xxx->mclk_hz, params_rate(params));
return -EINVAL;
}
val = ((int)mclk_div - 128) / 128;
if ((val < 0) | (val > 3)) {
dev_err(component->dev,
"div register setting %d is out of range\n",
val);
dev_err(component->dev,
"unsupported sample rate %d Hz for the master clock of %d Hz\n",
params_rate(params), src4xxx->mclk_hz);
return -EINVAL;
}
ret = regmap_update_bits(src4xxx->regmap,
SRC4XXX_TX_CTL_07, SRC4XXX_TX_MCLK_DIV_MASK,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
if (ret) {
dev_err(component->dev,
"Couldn't set the TX's div register to %d << %d = 0x%x\n",
val, SRC4XXX_TX_MCLK_DIV_SHIFT,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
return ret;
}
switch (src4xxx->mclk_hz) {
case 24576000:
pj = 0x22;
jd = 0x00;
d = 0x00;
break;
case 22579200:
pj = 0x22;
jd = 0x1b;
d = 0xa3;
break;
default:
dev_info(component->dev,
"Couldn't set the RCV PLL as this master clock rate is unknown. Chosen regmap values may not match real world values.\n");
pj = 0x0;
jd = 0xff;
d = 0xff;
break;
}
ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_0F, pj);
if (ret < 0)
dev_err(component->dev,
"Failed to update PLL register 0x%x\n",
SRC4XXX_RCV_PLL_0F);
ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_10, jd);
if (ret < 0)
dev_err(component->dev,
"Failed to update PLL register 0x%x\n",
SRC4XXX_RCV_PLL_10);
ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_11, d);
if (ret < 0)
dev_err(component->dev,
"Failed to update PLL register 0x%x\n",
SRC4XXX_RCV_PLL_11);
ret = regmap_update_bits(src4xxx->regmap,
SRC4XXX_TX_CTL_07, SRC4XXX_TX_MCLK_DIV_MASK,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
if (ret < 0) {
dev_err(component->dev,
"Couldn't set the TX's div register to %d << %d = 0x%x\n",
val, SRC4XXX_TX_MCLK_DIV_SHIFT,
val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
return ret;
}
return regmap_update_bits(src4xxx->regmap, reg,
SRC4XXX_MCLK_DIV_MASK, val);
} else {
dev_info(dai->dev, "not setting up MCLK as not master\n");
}
return 0;
};
static const struct snd_soc_dai_ops src4xxx_dai_ops = …;
#define SRC4XXX_FORMATS …
#define SRC4XXX_RATES …
static struct snd_soc_dai_driver src4xxx_dai_driver[] = …;
static const struct reg_default src4xxx_reg_defaults[] = …;
int src4xxx_probe(struct device *dev, struct regmap *regmap,
void (*switch_mode)(struct device *dev))
{ … }
EXPORT_SYMBOL_GPL(…);
static bool src4xxx_volatile_register(struct device *dev, unsigned int reg)
{ … }
const struct regmap_config src4xxx_regmap_config = …;
EXPORT_SYMBOL_GPL(…);
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;