ASoC: tlv320adcx140: Add GPO configuration and drive output config
Add General Purpose Output (GPO) configuration and driver output configuration. The GPOs can be configured as a GPO, IRQ, SDOUT or a PDMCLK output. In addition the output drive can be configured with various configurations. Signed-off-by: Dan Murphy <dmurphy@ti.com> Link: https://lore.kernel.org/r/20200728160833.24130-2-dmurphy@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
63b0383f3c
Коммит
6617cff6a0
|
@ -37,6 +37,13 @@ struct adcx140_priv {
|
|||
unsigned int slot_width;
|
||||
};
|
||||
|
||||
static const char * const gpo_config_names[] = {
|
||||
"ti,gpo-config-1",
|
||||
"ti,gpo-config-2",
|
||||
"ti,gpo-config-3",
|
||||
"ti,gpo-config-4",
|
||||
};
|
||||
|
||||
static const struct reg_default adcx140_reg_defaults[] = {
|
||||
{ ADCX140_PAGE_SELECT, 0x00 },
|
||||
{ ADCX140_SW_RESET, 0x00 },
|
||||
|
@ -60,10 +67,10 @@ static const struct reg_default adcx140_reg_defaults[] = {
|
|||
{ ADCX140_PDMCLK_CFG, 0x40 },
|
||||
{ ADCX140_PDM_CFG, 0x00 },
|
||||
{ ADCX140_GPIO_CFG0, 0x22 },
|
||||
{ ADCX140_GPO_CFG0, 0x00 },
|
||||
{ ADCX140_GPO_CFG1, 0x00 },
|
||||
{ ADCX140_GPO_CFG2, 0x00 },
|
||||
{ ADCX140_GPO_CFG3, 0x00 },
|
||||
{ ADCX140_GPO_CFG4, 0x00 },
|
||||
{ ADCX140_GPO_VAL, 0x00 },
|
||||
{ ADCX140_GPIO_MON, 0x00 },
|
||||
{ ADCX140_GPI_CFG0, 0x00 },
|
||||
|
@ -756,6 +763,43 @@ static const struct snd_soc_dai_ops adcx140_dai_ops = {
|
|||
.set_tdm_slot = adcx140_set_dai_tdm_slot,
|
||||
};
|
||||
|
||||
static int adcx140_configure_gpo(struct adcx140_priv *adcx140)
|
||||
{
|
||||
u32 gpo_outputs[ADCX140_NUM_GPOS];
|
||||
u32 gpo_output_val = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ADCX140_NUM_GPOS; i++) {
|
||||
ret = device_property_read_u32_array(adcx140->dev,
|
||||
gpo_config_names[i],
|
||||
gpo_outputs,
|
||||
ADCX140_NUM_GPO_CFGS);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
if (gpo_outputs[0] > ADCX140_GPO_CFG_MAX) {
|
||||
dev_err(adcx140->dev, "GPO%d config out of range\n", i + 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpo_outputs[1] > ADCX140_GPO_DRV_MAX) {
|
||||
dev_err(adcx140->dev, "GPO%d drive out of range\n", i + 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpo_output_val = gpo_outputs[0] << ADCX140_GPO_SHIFT |
|
||||
gpo_outputs[1];
|
||||
ret = regmap_write(adcx140->regmap, ADCX140_GPO_CFG1 + i,
|
||||
gpo_output_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int adcx140_codec_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
|
||||
|
@ -837,6 +881,10 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = adcx140_configure_gpo(adcx140);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = adcx140_reset(adcx140);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
|
@ -36,10 +36,10 @@
|
|||
#define ADCX140_PDMCLK_CFG 0x1f
|
||||
#define ADCX140_PDM_CFG 0x20
|
||||
#define ADCX140_GPIO_CFG0 0x21
|
||||
#define ADCX140_GPO_CFG1 0x22
|
||||
#define ADCX140_GPO_CFG2 0x23
|
||||
#define ADCX140_GPO_CFG3 0x24
|
||||
#define ADCX140_GPO_CFG4 0x25
|
||||
#define ADCX140_GPO_CFG0 0x22
|
||||
#define ADCX140_GPO_CFG1 0x23
|
||||
#define ADCX140_GPO_CFG2 0x24
|
||||
#define ADCX140_GPO_CFG3 0x25
|
||||
#define ADCX140_GPO_VAL 0x29
|
||||
#define ADCX140_GPIO_MON 0x2a
|
||||
#define ADCX140_GPI_CFG0 0x2b
|
||||
|
@ -139,4 +139,10 @@
|
|||
#define ADCX140_GPI3_INDEX 2
|
||||
#define ADCX140_GPI4_INDEX 3
|
||||
|
||||
#define ADCX140_NUM_GPOS 4
|
||||
#define ADCX140_NUM_GPO_CFGS 2
|
||||
#define ADCX140_GPO_SHIFT 4
|
||||
#define ADCX140_GPO_CFG_MAX 4
|
||||
#define ADCX140_GPO_DRV_MAX 5
|
||||
|
||||
#endif /* _TLV320ADCX140_ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче