Загрузка данных


static void lt9611_hdmi_audio_infoframe(struct device *dev, void *data, struct hdmi_codec_params *hparms)
{
	struct lt9611 *lt9611 = data;
	union hdmi_infoframe audio_frame;
	u8 audio_buf[32];
	ssize_t audio_len;
	int ret,i_frame;

	// 1. Стандартная инициализация структуры (выставит правильный type, version и length)
	ret = hdmi_audio_infoframe_init(&audio_frame.audio);
	if (ret < 0) {
		dev_err(dev, "LT9611: Failed to init audio infoframe: %d\n", ret);
	} else {
		// 2. Заполняем поля структуры вручную
		audio_frame.audio.channels = 2; // Для SPDIF всегда 2 канала PCM
		audio_frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; // Поток (для SPDIF)
		audio_frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; // Определяется потоком
		// Маппинг числовой частоты дискретизации в перечисление ядра
		switch (hparms->sample_rate) {
		case 32000:  audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_32000; break;
		case 44100:  audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_44100; break;
		case 48000:  audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000; break;
		case 88200:  audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_88200; break;
		case 96000:  audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_96000; break;
		case 176400: audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_176400; break;
		case 192000: audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_192000; break;
		default:     audio_frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; break;
		}
		// 3. Упаковываем структуру в бинарный массив по спецификации HDMI
		audio_len = hdmi_infoframe_pack(&audio_frame, audio_buf, sizeof(audio_buf));
		if (audio_len < 0) {
			dev_err(dev, "LT9611: Failed to pack audio infoframe: %ld\n", audio_len);
		} else {
			dev_info(dev, "LT9611: Writing Audio InfoFrame to 0x84b2 (%ld bytes)\n", audio_len);
			// 4. Записываем байты инфофрейма в чип последовательно, начиная с адреса 0x84b2
			for (i_frame = 0; i_frame < audio_len; i_frame++) {
				regmap_write(lt9611->regmap, 0x84b2 + i_frame, audio_buf[i_frame]);
			}
			// 5. Разрешаем чипу транслировать Audio InfoFrame в HDMI поток (включаем BIT(4) -> 0x10)
			regmap_update_bits(lt9611->regmap, 0x843d, 0x10, 0x10);
		}
	}
}

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;
	struct reg_sequence seq[] = {
	{ 0x8406, 0x08 }, // [0] for I2S: 0x08, for SPDIF: 0x0c
	{ 0x8407, 0x10 }, // [1]
	{ 0x840f, 0x2b }, // [2] Sample rate
	{ 0x8434, 0xd4 }, // [3] CTS_N
	{ 0x8435, 0x00 }, // [4] N val (High)
	{ 0x8436, 0x18 }, // [5] N val (Mid)
	{ 0x8437, 0x00 }, // [6] N val (Low)
	};

	switch (fmt->fmt) {
	case HDMI_I2S:
		dev_info(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_SPDIF:
		dev_info(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;
	}
printk("%s(%d) sample_rate=%u\n",__FUNCTION__,__LINE__,hparms->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 audio sample rate %d\n", hparms->sample_rate);
		return -EINVAL;
	}
printk("%s(%d) sample_width=%u\n",__FUNCTION__,__LINE__,hparms->sample_width);
	if (fmt->fmt == HDMI_I2S) {
	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:
		dev_err(dev, "LT9611: Unsupported audio sample width %d\n", hparms->sample_width);
		return -EINVAL;
	}
	} else {
		len = 0;
	}
printk("%s(%d)\n",__FUNCTION__,__LINE__);
//Set sample rate and len;
	val = rate << 4 | len;
	seq[2].def = val;
	if (fmt->fmt == HDMI_SPDIF) {
		/* For SPDIF fixed N-coef */
		seq[4].def = 0x00; // 0x8435 -> 0x00
		seq[5].def = 0x20; // 0x8436 -> 0x20
		seq[6].def = 0x00; // 0x8437 -> 0x00
		lt9611_hdmi_audio_infoframe(dev, data, hparms);
	} else {
		lt9611_calc_n(hparms->sample_rate, &val);
		seq[4].def = (val >> 16) & 0xF;
		seq[5].def = (val >> 8) & 0xFF;
		seq[6].def = val & 0xFF;
	}
printk("%s(%d)\n",__FUNCTION__,__LINE__);
	regmap_multi_reg_write(lt9611->regmap, seq, ARRAY_SIZE(seq));
	return 0;
}