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


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;
	}

	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:
		return -EINVAL;
	}

	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;
	}

//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
	} else {
		lt9611_calc_n(hparms->sample_rate, &val);
//Set N val
		seq[4].def = (val >> 16) & 0xF;
		seq[5].def = (val >> 8) & 0xFF;
		seq[6].def = val & 0xFF;
	}

	regmap_multi_reg_write(lt9611->regmap, seq, ARRAY_SIZE(seq));
	return 0;
}

static int lt9611_audio_startup(struct device *dev, void *data)
{
	struct lt9611 *lt9611 = data;
	return 0;
}

static void lt9611_audio_shutdown(struct device *dev, void *data)
{
	struct lt9611 *lt9611 = data;
	regmap_write(lt9611->regmap, 0x8406, 0x00);
	regmap_write(lt9611->regmap, 0x8407, 0x00);
}

static int lt9611_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
				      struct device_node *endpoint)
{
	struct of_endpoint of_ep;
	int ret;
	ret = of_graph_parse_endpoint(endpoint, &of_ep);
	if (ret < 0)
		return ret;
	/*
	 * HDMI sound should be located as reg = <2>
	 * Then, it is sound port 0
	 */
	if (of_ep.port == 2)
		return 0;
	return -EINVAL;
}

static const struct hdmi_codec_ops lt9611_codec_ops = {
	.hw_params	= lt9611_hdmi_hw_params,
	.audio_shutdown = lt9611_audio_shutdown,
	.audio_startup	= lt9611_audio_startup,
	.get_dai_id	= lt9611_hdmi_i2s_get_dai_id,
};

static struct hdmi_codec_pdata codec_data = {
	.ops = &lt9611_codec_ops,
	.max_i2s_channels = 8,
	.i2s = 1,
};

static int lt9611_audio_init(struct device *dev, struct lt9611 *lt9611)
{
	codec_data.data = lt9611;
	lt9611->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,  PLATFORM_DEVID_AUTO, &codec_data, sizeof(codec_data));
	return PTR_ERR_OR_ZERO(lt9611->audio_pdev);
}

static void lt9611_audio_exit(struct lt9611 *lt9611)
{
	if (lt9611->audio_pdev) {
		platform_device_unregister(lt9611->audio_pdev);
		lt9611->audio_pdev = NULL;
	}
}

Надо генерировать codec_data(struct hdmi_codec_pdata) в зависимости от установки(I2S,SPDIF) - возможно протянуть настройку в dts в кодеке, и  добавить параметр для функции lt9611_audio_init(bool is_i2s)