Загрузка данных
static int sgtl5000_of_xlate_dai_id(struct snd_soc_component *component,
struct device_node *endpoint)
{
/* return dai id 0, whatever the endpoint index */
return 0;
}
static const struct snd_soc_component_driver sgtl5000_driver = {
.probe = sgtl5000_probe,
.set_bias_level = sgtl5000_set_bias_level,
.controls = sgtl5000_snd_controls,
.num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
.dapm_widgets = sgtl5000_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets),
.dapm_routes = sgtl5000_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
.of_xlate_dai_id = sgtl5000_of_xlate_dai_id,
.suspend_bias_off = 1,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
};
static const struct regmap_config sgtl5000_regmap = {
.reg_bits = 16,
.val_bits = 16,
.reg_stride = 2,
.max_register = SGTL5000_MAX_REG_OFFSET,
.volatile_reg = sgtl5000_volatile,
.readable_reg = sgtl5000_readable,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = sgtl5000_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(sgtl5000_reg_defaults),
};
/*
* Write all the default values from sgtl5000_reg_defaults[] array into the
* sgtl5000 registers, to make sure we always start with the sane registers
* values as stated in the datasheet.
*
* Since sgtl5000 does not have a reset line, nor a reset command in software,
* we follow this approach to guarantee we always start from the default values
* and avoid problems like, not being able to probe after an audio playback
* followed by a system reset or a 'reboot' command in Linux
*/
static void sgtl5000_fill_defaults(struct i2c_client *client)
{
struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client);
int i, ret, val, index;
for (i = 0; i < ARRAY_SIZE(sgtl5000_reg_defaults); i++) {
val = sgtl5000_reg_defaults[i].def;
index = sgtl5000_reg_defaults[i].reg;
ret = regmap_write(sgtl5000->regmap, index, val);
if (ret)
dev_err(&client->dev,
"%s: error %d setting reg 0x%02x to 0x%04x\n",
__func__, ret, index, val);
}
}
static int sgtl5000_i2c_probe(struct i2c_client *client)
{
struct sgtl5000_priv *sgtl5000;
int ret, reg, rev;
struct device_node *np = client->dev.of_node;
u32 value;
u16 ana_pwr;
sgtl5000 = devm_kzalloc(&client->dev, sizeof(*sgtl5000), GFP_KERNEL);
if (!sgtl5000)
return -ENOMEM;
i2c_set_clientdata(client, sgtl5000);
ret = sgtl5000_enable_regulators(client);
if (ret)
return ret;
sgtl5000->regmap = devm_regmap_init_i2c(client, &sgtl5000_regmap);
if (IS_ERR(sgtl5000->regmap)) {
ret = PTR_ERR(sgtl5000->regmap);
dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret);
goto disable_regs;
}
sgtl5000->mclk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(sgtl5000->mclk)) {
ret = PTR_ERR(sgtl5000->mclk);
/* Defer the probe to see if the clk will be provided later */
if (ret == -ENOENT)
ret = -EPROBE_DEFER;
dev_err_probe(&client->dev, ret, "Failed to get mclock\n");
goto disable_regs;
}
ret = clk_prepare_enable(sgtl5000->mclk);
if (ret) {
dev_err(&client->dev, "Error enabling clock %d\n", ret);
goto disable_regs;
}
/* Need 8 clocks before I2C accesses */
udelay(1);
/* read chip information */
ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®);
if (ret) {
dev_err(&client->dev, "Error reading chip id %d\n", ret);
goto disable_clk;
}
if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
SGTL5000_PARTID_PART_ID) {
dev_err(&client->dev,
"Device with ID register %x is not a sgtl5000\n", reg);
ret = -ENODEV;
goto disable_clk;
}
rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev);
sgtl5000->revision = rev;
/* reconfigure the clocks in case we're using the PLL */
ret = regmap_write(sgtl5000->regmap,
SGTL5000_CHIP_CLK_CTRL,
SGTL5000_CHIP_CLK_CTRL_DEFAULT);
if (ret)
dev_err(&client->dev,
"Error %d initializing CHIP_CLK_CTRL\n", ret);
/* Mute everything to avoid pop from the following power-up */
ret = regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_CTRL,
SGTL5000_CHIP_ANA_CTRL_DEFAULT);
if (ret) {
dev_err(&client->dev,
"Error %d muting outputs via CHIP_ANA_CTRL\n", ret);
goto disable_clk;
}
/*
* If VAG is powered-on (e.g. from previous boot), it would be disabled
* by the write to ANA_POWER in later steps of the probe code. This
* may create a loud pop even with all outputs muted. The proper way
* to circumvent this is disabling the bit first and waiting the proper
* cool-down time.
*/
ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, &value);
if (ret) {
dev_err(&client->dev, "Failed to read ANA_POWER: %d\n", ret);
goto disable_clk;
}
if (value & SGTL5000_VAG_POWERUP) {
ret = regmap_update_bits(sgtl5000->regmap,
SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP,
0);
if (ret) {
dev_err(&client->dev, "Error %d disabling VAG\n", ret);
goto disable_clk;
}
msleep(SGTL5000_VAG_POWERDOWN_DELAY);
}
/* Follow section 2.2.1.1 of AN3663 */
ana_pwr = SGTL5000_ANA_POWER_DEFAULT;
if (sgtl5000->num_supplies <= VDDD) {
/* internal VDDD at 1.2V */
ret = regmap_update_bits(sgtl5000->regmap,
SGTL5000_CHIP_LINREG_CTRL,
SGTL5000_LINREG_VDDD_MASK,
LINREG_VDDD);
if (ret)
dev_err(&client->dev,
"Error %d setting LINREG_VDDD\n", ret);
ana_pwr |= SGTL5000_LINEREG_D_POWERUP;
dev_info(&client->dev,
"Using internal LDO instead of VDDD: check ER1 erratum\n");
} else {
/* using external LDO for VDDD
* Clear startup powerup and simple powerup
* bits to save power
*/
ana_pwr &= ~(SGTL5000_STARTUP_POWERUP
| SGTL5000_LINREG_SIMPLE_POWERUP);
dev_dbg(&client->dev, "Using external VDDD\n");
}
ret = regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, ana_pwr);
if (ret)
dev_err(&client->dev,
"Error %d setting CHIP_ANA_POWER to %04x\n",
ret, ana_pwr);
if (np) {
if (!of_property_read_u32(np,
"micbias-resistor-k-ohms", &value)) {
switch (value) {
case SGTL5000_MICBIAS_OFF:
sgtl5000->micbias_resistor = 0;
break;
case SGTL5000_MICBIAS_2K:
sgtl5000->micbias_resistor = 1;
break;
case SGTL5000_MICBIAS_4K:
sgtl5000->micbias_resistor = 2;
break;
case SGTL5000_MICBIAS_8K:
sgtl5000->micbias_resistor = 3;
break;
default:
sgtl5000->micbias_resistor = 2;
dev_err(&client->dev,
"Unsuitable MicBias resistor\n");
}
} else {
/* default is 4Kohms */
sgtl5000->micbias_resistor = 2;
}
if (!of_property_read_u32(np,
"micbias-voltage-m-volts", &value)) {
/* 1250mV => 0 */
/* steps of 250mV */
if ((value >= 1250) && (value <= 3000))
sgtl5000->micbias_voltage = (value / 250) - 5;
else {
sgtl5000->micbias_voltage = 0;
dev_err(&client->dev,
"Unsuitable MicBias voltage\n");
}
} else {
sgtl5000->micbias_voltage = 0;
}
}
sgtl5000->lrclk_strength = I2S_LRCLK_STRENGTH_LOW;
if (!of_property_read_u32(np, "lrclk-strength", &value)) {
if (value > I2S_LRCLK_STRENGTH_HIGH)
value = I2S_LRCLK_STRENGTH_LOW;
sgtl5000->lrclk_strength = value;
}
sgtl5000->sclk_strength = I2S_SCLK_STRENGTH_LOW;
if (!of_property_read_u32(np, "sclk-strength", &value)) {
if (value > I2S_SCLK_STRENGTH_HIGH)
value = I2S_SCLK_STRENGTH_LOW;
sgtl5000->sclk_strength = value;
}
/* Ensure sgtl5000 will start with sane register values */
sgtl5000_fill_defaults(client);
ret = devm_snd_soc_register_component(&client->dev,
&sgtl5000_driver, &sgtl5000_dai, 1);
if (ret)
goto disable_clk;
return 0;
disable_clk:
clk_disable_unprepare(sgtl5000->mclk);
disable_regs:
regulator_bulk_disable(sgtl5000->num_supplies, sgtl5000->supplies);
regulator_bulk_free(sgtl5000->num_supplies, sgtl5000->supplies);
return ret;
}
static void sgtl5000_i2c_remove(struct i2c_client *client)
{
struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client);
regmap_write(sgtl5000->regmap, SGTL5000_CHIP_CLK_CTRL, SGTL5000_CHIP_CLK_CTRL_DEFAULT);
regmap_write(sgtl5000->regmap, SGTL5000_CHIP_DIG_POWER, SGTL5000_DIG_POWER_DEFAULT);
regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, SGTL5000_ANA_POWER_DEFAULT);
clk_disable_unprepare(sgtl5000->mclk);
regulator_bulk_disable(sgtl5000->num_supplies, sgtl5000->supplies);
regulator_bulk_free(sgtl5000->num_supplies, sgtl5000->supplies);
}
static void sgtl5000_i2c_shutdown(struct i2c_client *client)
{
sgtl5000_i2c_remove(client);
}
static const struct i2c_device_id sgtl5000_id[] = {
{"sgtl5000"},
{},
};
MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
static const struct of_device_id sgtl5000_dt_ids[] = {
{ .compatible = "fsl,sgtl5000", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids);
static struct i2c_driver sgtl5000_i2c_driver = {
.driver = {
.name = "sgtl5000",
.of_match_table = sgtl5000_dt_ids,
},
.probe = sgtl5000_i2c_probe,
.remove = sgtl5000_i2c_remove,
.shutdown = sgtl5000_i2c_shutdown,
.id_table = sgtl5000_id,
};
module_i2c_driver(sgtl5000_i2c_driver);