static int lt9611_hdmi_hw_params(struct device *dev, void *data,
struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms)
{
struct lt9611 *lt9611 = data;
unsigned int rate;
unsigned int len;
unsigned int val;
/* Базовая структура последовательности регистров (страница 0x84) */
struct reg_sequence seq[] = {
{ 0x8406, 0x08 }, // [0] Для I2S: 0x08, для SPDIF: 0x0c
{ 0x8407, 0x10 }, // [1]
{ 0x840f, 0x2b }, // [2] Частота сэмплирования
{ 0x8434, 0xd4 }, // [3] CTS_N
{ 0x8435, 0x00 }, // [4] N val (High)
{ 0x8436, 0x18 }, // [5] N val (Mid)
{ 0x8437, 0x00 }, // [6] N val (Low)
};
/* 1. Определяем тип аудиоинтерфейса и пишем в регистр страницы 0x82 */
switch (fmt->fmt) {
case HDMI_CODEC_I2S:
dev_dbg(dev, "LT9611: Configuring Audio Input as I2S\n");
regmap_write(lt9611->regmap, 0x82d7, 0x04); // Режим I2S 2ch
seq[0].def = 0x08; // Соответствует китайскому 0x06 -> 0x08
break;
case HDMI_CODEC_SPDIF:
dev_dbg(dev, "LT9611: Configuring Audio Input as SPDIF\n");
regmap_write(lt9611->regmap, 0x82d7, 0x80); // Режим SPDIF
seq[0].def = 0x0c; // Соответствует китайскому 0x06 -> 0x0c
break;
default:
dev_err(dev, "LT9611: Unsupported audio format %d\n", fmt->fmt);
return -EINVAL;
}
/* 2. Настройка частоты дискретизации (Sample Rate) */
switch (hparms->sample_rate) {
case 32000: rate = LT9611_SAMPLE_FREQ_32000; break;
case 44100: rate = LT9611_SAMPLE_FREQ_44100; break;
case 48000: rate = LT9611_SAMPLE_FREQ_48000; break;
case 88200: rate = LT9611_SAMPLE_FREQ_88200; break;
case 96000: rate = LT9611_SAMPLE_FREQ_96000; break;
case 176400: rate = LT9611_SAMPLE_FREQ_176400; break;
case 192000: rate = LT9611_SAMPLE_FREQ_192000; break;
default:
dev_err(dev, "LT9611: Unsupported sample rate %d\n", hparms->sample_rate);
return -EINVAL;
}
/* 3. Настройка разрядности (только для I2S, для SPDIF игнорируется чипом) */
switch (hparms->sample_width) {
case 16: len = LT9611_I2S_SAMPLE_LEN_16; break;
case 18: len = LT9611_I2S_SAMPLE_LEN_18; break;
case 20: len = LT9611_I2S_SAMPLE_LEN_20; break;
case 24: len = LT9611_I2S_SAMPLE_LEN_24; break;
default:
return -EINVAL;
}
/* Записываем маску частоты и длины слова в элемент seq[2] (регистр 0x840f) */
val = rate << 4 | len;
seq[2].def = val;
/* 4. Расчет и установка значений N для тактовой сетки HDMI аудио */
if (fmt->fmt == HDMI_CODEC_SPDIF) {
/* Для SPDIF китайский референс жестко прописывает фиксированный N-коэффициент */
seq[5].def = 0x20; // регистр 0x8436 -> 0x20
seq[4].def = 0x00; // регистр 0x8435 -> 0x00
seq[6].def = 0x00; // регистр 0x8437 -> 0x00
} else {
/* Для I2S рассчитываем динамически в зависимости от частоты потока */
lt9611_calc_n(hparms->sample_rate, &val);
seq[4].def = (val >> 16) & 0xF;
seq[5].def = (val >> 8) & 0xFF;
seq[6].def = val & 0xFF;
}
/* Отправляем всю пачку регистров страницы 0x84 за один раз */
regmap_multi_reg_write(lt9611->regmap, seq, ARRAY_SIZE(seq));
return 0;
}