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


static int sgtl5000_configure(const struct device *dev, struct audio_codec_cfg *cfg)
{
	int ret;
	bool is_master = (cfg->dai_cfg.i2s.options & I2S_OPT_FRAME_CLK_MASTER);

	if (cfg->dai_type >= AUDIO_DAI_TYPE_INVALID) {
		return -EINVAL;
	}

	/* --------------------------------------------------------------------- */
	/* DYNAMIC BIT WIDTH & SCLK RATIO CONFIGURATION (LINUX PORTED)          */
	/* --------------------------------------------------------------------- */
	uint16_t i2s_ctl = 0;

	switch (cfg->dai_cfg.i2s.word_size) {
	case 16:
		/* 16-bit data length uses 32*FS clock frequency ratio configuration */
		i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT;
		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS << SGTL5000_I2S_SCLKFREQ_SHIFT;
		break;
	case 20:
		i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT;
		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << SGTL5000_I2S_SCLKFREQ_SHIFT;
		break;
	case 24:
		i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT;
		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << SGTL5000_I2S_SCLKFREQ_SHIFT;
		break;
	case 32:
		i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT;
		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << SGTL5000_I2S_SCLKFREQ_SHIFT;
		break;
	default:
		LOG_ERR("SGTL5000: Unsupported hardware bit width %d", cfg->dai_cfg.i2s.word_size);
		return -EINVAL;
	}

	/* 
	 * Mask and update only the dynamic bit width (DLEN) and bit clock speed (SCLKFREQ) fields.
	 * This prevents destroying the Master/Slave states or frame format fields.
	 */
	ret = sgtl5000_update_reg(dev, SGTL5000_CHIP_I2S_CTRL,
				   SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK,
				   i2s_ctl);
	if (ret != 0) return ret;

	LOG_INF("SGTL5000: Applied Linux port for %d-bit data (I2S_CTRL update mask payload: 0x%04X)", 
		cfg->dai_cfg.i2s.word_size, i2s_ctl);

	/* --------------------------------------------------------------------- */
	/* CORE HARDWARE CLOCKS & ROUTING CONFIGURATION                          */
	/* --------------------------------------------------------------------- */
	
	/* Configure core clock configuration trees and internal PLL multiplier */
	ret = sgtl5000_set_clock(dev, cfg->mclk_freq, cfg->dai_cfg.i2s.frame_clk_freq, is_master);
	if (ret != 0) return ret;

	/* Program Data Bus Protocol Routing (Applies Master/Slave or custom alignment switches) */
	ret = sgtl5000_protocol_config(dev, cfg->dai_type, is_master);
	if (ret != 0) return ret;

	/* Map analog power paths and states based on target route definitions */
	switch (cfg->dai_route) {
	case AUDIO_ROUTE_PLAYBACK:
		sgtl5000_set_power(dev, true, false, true, false);
		sgtl5000_set_route_state(dev, AUDIO_ROUTE_PLAYBACK);
		break;

	case AUDIO_ROUTE_CAPTURE:
		sgtl5000_set_power(dev, false, true, false, false);
		sgtl5000_set_route_state(dev, AUDIO_ROUTE_CAPTURE);
		break;

	case AUDIO_ROUTE_PLAYBACK_CAPTURE:
		sgtl5000_set_power(dev, true, true, true, true);
		sgtl5000_set_route_state(dev, AUDIO_ROUTE_PLAYBACK_CAPTURE);
		break;

	default:
		sgtl5000_set_power(dev, false, false, false, false);
		sgtl5000_set_route_state(dev, AUDIO_ROUTE_BYPASS);
		break;
	}

	return 0;
}