sound/soc/codecs/wm_hubs.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/wm_hubs.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/wm_hubs.c
Extension
.c
Size
43186 bytes
Lines
1311
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct wm_hubs_dcs_cache {
	struct list_head list;
	unsigned int left;
	unsigned int right;
	u16 dcs_cfg;
};

static bool wm_hubs_dcs_cache_get(struct snd_soc_component *component,
				  struct wm_hubs_dcs_cache **entry)
{
	struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
	struct wm_hubs_dcs_cache *cache;
	unsigned int left, right;

	left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME);
	left &= WM8993_HPOUT1L_VOL_MASK;

	right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME);
	right &= WM8993_HPOUT1R_VOL_MASK;

	list_for_each_entry(cache, &hubs->dcs_cache, list) {
		if (cache->left != left || cache->right != right)
			continue;

		*entry = cache;
		return true;
	}

	return false;
}

static void wm_hubs_dcs_cache_set(struct snd_soc_component *component, u16 dcs_cfg)
{
	struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
	struct wm_hubs_dcs_cache *cache;

	if (hubs->no_cache_dac_hp_direct)
		return;

	cache = devm_kzalloc(component->dev, sizeof(*cache), GFP_KERNEL);
	if (!cache)
		return;

	cache->left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME);
	cache->left &= WM8993_HPOUT1L_VOL_MASK;

	cache->right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME);
	cache->right &= WM8993_HPOUT1R_VOL_MASK;

	cache->dcs_cfg = dcs_cfg;

	list_add_tail(&cache->list, &hubs->dcs_cache);
}

static int wm_hubs_read_dc_servo(struct snd_soc_component *component,
				  u16 *reg_l, u16 *reg_r)
{
	struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
	u16 dcs_reg, reg;
	int ret = 0;

	switch (hubs->dcs_readback_mode) {
	case 2:
		dcs_reg = WM8994_DC_SERVO_4E;
		break;
	case 1:
		dcs_reg = WM8994_DC_SERVO_READBACK;
		break;
	default:
		dcs_reg = WM8993_DC_SERVO_3;
		break;
	}

	/* Different chips in the family support different readback
	 * methods.
	 */
	switch (hubs->dcs_readback_mode) {
	case 0:
		*reg_l = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_1)
			& WM8993_DCS_INTEG_CHAN_0_MASK;
		*reg_r = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_2)
			& WM8993_DCS_INTEG_CHAN_1_MASK;
		break;
	case 2:
	case 1:
		reg = snd_soc_component_read(component, dcs_reg);
		*reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
			>> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
		*reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
		break;

Annotation

Implementation Notes