static int sgtl5000_set_property(const struct device *dev, audio_property_t property,
audio_channel_t channel, audio_property_value_t val)
{
uint16_t reg_val;
switch (property) {
case AUDIO_PROPERTY_OUTPUT_VOLUME:
/* Линейно мапим шкалу Zephyr (0-100%) в аппаратные шаги SGTL5000 */
/* Аппаратная шкала: 0x3C (0dB, Максимум) вниз до 0xF0 (-90dB, Минимум) */
if (val.vol == 0) {
reg_val = (0xFC << 8) | 0xFC; /* Значение полного приглушения (Mute) */
} else {
uint8_t steps = (uint8_t)(0x3C + ((100 - val.vol) * (0xF0 - 0x3C)) / 100);
reg_val = (steps << 8) | steps;
}
return sgtl5000_write_reg(dev, SGTL5000_CHIP_DAC_VOL, reg_val);
case AUDIO_PROPERTY_OUTPUT_MUTE:
return sgtl5000_update_reg(dev, SGTL5000_CHIP_ANA_CTRL, SGTL5000_HP_MUTE,
val.mute ? SGTL5000_HP_MUTE : 0);
default:
break;
}
return -ENOTSUP;
}
static void sgtl5000_start_output(const struct device *dev) {}
static void sgtl5000_stop_output(const struct device *dev) {}
/* Базовая аппаратная последовательность включения (перенесена из Probe-рутины Linux) */
static int sgtl5000_init(const struct device *dev)
{
const struct sgtl5000_driver_config *const dev_cfg = dev->config;
uint16_t chip_id = 0;
if (!device_is_ready(dev_cfg->i2c.bus)) {
LOG_ERR("I2C Control Bus not ready");
return -ENODEV;
}
/* Чтение и верификация сигнатуры чипа (Chip ID) */
if (sgtl5000_read_reg(dev, SGTL5000_CHIP_ID, &chip_id) != 0) {
return -EIO;
}
if ((chip_id >> 8) != 0xA0) {
LOG_ERR("Device signature mismatch! Read ID: 0x%04X", chip_id);
return -ENODEV;
}
/* Конфигурация питания: предполагаем стандартные 3.3V на входах */
sgtl5000_write_reg(dev, SGTL5000_CHIP_ANA_POWER,
SGTL5000_DAC_STEREO | SGTL5000_ADC_STEREO | SGTL5000_REFTOP_POWERUP);
/* Конфигурация встроенного LDO регулятора для питания цифровой части VDDD */
sgtl5000_write_reg(dev, SGTL5000_CHIP_LINREG_CTRL, 0x0008);
/* Настройка опорного напряжения виртуальной земли VAG -> VDDA/2 (~1.65V) */
sgtl5000_write_reg(dev, SGTL5000_CHIP_REF_CTRL, 0x01FF);
sgtl5000_write_reg(dev, SGTL5000_CHIP_SHORT_CTRL, 0x0000); /* Отключаем детектор короткого замыкания */
sgtl5000_write_reg(dev, SGTL5000_CHIP_DIG_POWER, SGTL5000_ADC_EN | SGTL5000_DAC_EN);
/* Настройки плавного нарастания громкости (Ramp) по умолчанию */
sgtl5000_write_reg(dev, SGTL5000_CHIP_ADCDAC_CTRL, 0x000C);
sgtl5000_write_reg(dev, SGTL5000_CHIP_PAD_STRENGTH, 0x015F);
sgtl5000_write_reg(dev, SGTL5000_DAP_AUDIO_EQ, 0x0001); /* Включаем режим DAP GEQ */
LOG_INF("NXP SGTL5000 Codec initialized successfully. ID: 0x%02X Revision: 0x%02X",
(chip_id >> 8), (chip_id & 0xFF));
return 0;
}
static const struct audio_codec_api sgtl5000_driver_api = {
.configure = sgtl5000_configure,
.start_output = sgtl5000_start_output,
.stop_output = sgtl5000_stop_output,
.set_property = sgtl5000_set_property,
};
#define SGTL5000_INIT(n) \
static const struct sgtl5000_driver_config sgtl5000_device_config_##n = { \
.i2c = I2C_DT_SPEC_INST_GET(n), \
}; \
\
DEVICE_DT_INST_DEFINE(n, sgtl5000_init, NULL, NULL, &sgtl5000_device_config_##n, \
POST_KERNEL, CONFIG_AUDIO_CODEC_INIT_PRIORITY, &sgtl5000_driver_api);
DT_INST_FOREACH_STATUS_OKAY(SGTL5000_INIT)