Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: wm8962: add .set_tdm_slot callback function

The slot_width can be different with the params_width(), for example,
DSP_A mode, slot_width = 32, but data format is S16_LE, if the word
length is configured to be 16, there is no sound on the right speaker.

So add .set_tdm_slot() callback function to configure the slot_width and
update the word length according to slot_width in hw_params().

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20260128025955.2562331-1-shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Shengjiu Wang and committed by
Mark Brown
ab3f4f0c 75ca8602

+31 -4
+31 -4
sound/soc/codecs/wm8962.c
··· 85 85 86 86 int irq; 87 87 bool master_flag; 88 + int tdm_width; 89 + int tdm_slots; 88 90 }; 89 91 90 92 /* We can't use the same notifier block for more than one supply and ··· 2614 2612 return 0; 2615 2613 } 2616 2614 2615 + static int wm8962_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 2616 + unsigned int rx_mask, int slots, int slot_width) 2617 + { 2618 + struct snd_soc_component *component = dai->component; 2619 + struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); 2620 + 2621 + wm8962->tdm_width = slot_width; 2622 + /* External is one slot one channel, but internal is one slot two channels */ 2623 + wm8962->tdm_slots = slots / 2; 2624 + 2625 + return 0; 2626 + } 2627 + 2617 2628 static const struct { 2618 2629 int rate; 2619 2630 int reg; ··· 2654 2639 int i; 2655 2640 int aif0 = 0; 2656 2641 int adctl3 = 0; 2642 + int width; 2657 2643 2658 - wm8962->bclk = snd_soc_params_to_bclk(params); 2659 - if (params_channels(params) == 1) 2660 - wm8962->bclk *= 2; 2644 + if (wm8962->tdm_width && wm8962->tdm_slots) { 2645 + wm8962->bclk = snd_soc_calc_bclk(params_rate(params), 2646 + wm8962->tdm_width, 2647 + params_channels(params), 2648 + wm8962->tdm_slots); 2649 + width = wm8962->tdm_width; 2650 + } else { 2651 + wm8962->bclk = snd_soc_params_to_bclk(params); 2652 + width = params_width(params); 2653 + 2654 + if (params_channels(params) == 1) 2655 + wm8962->bclk *= 2; 2656 + } 2661 2657 2662 2658 wm8962->lrclk = params_rate(params); 2663 2659 ··· 2686 2660 if (wm8962->lrclk % 8000 == 0) 2687 2661 adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; 2688 2662 2689 - switch (params_width(params)) { 2663 + switch (width) { 2690 2664 case 16: 2691 2665 break; 2692 2666 case 20: ··· 3065 3039 .hw_params = wm8962_hw_params, 3066 3040 .set_sysclk = wm8962_set_dai_sysclk, 3067 3041 .set_fmt = wm8962_set_dai_fmt, 3042 + .set_tdm_slot = wm8962_set_tdm_slot, 3068 3043 .mute_stream = wm8962_mute, 3069 3044 .no_capture_mute = 1, 3070 3045 };