Skip to content

Commit 1f9d3d9

Browse files
libinyangtiwai
authored andcommitted
ALSA: hda - set intel audio clock to a proper value
On some Intel platforms, the audio clock may not be set correctly with initial setting. This will cause the audio playback/capture rates wrong. This patch checks the audio clock setting and will set it to a proper value if it is set incorrectly. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188411 Signed-off-by: Libin Yang <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent dde5bff commit 1f9d3d9

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

sound/pci/hda/hda_intel.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,98 @@ static void bxt_reduce_dma_latency(struct azx *chip)
540540
azx_writel(chip, VS_EM4L, val);
541541
}
542542

543+
/*
544+
* ML_LCAP bits:
545+
* bit 0: 6 MHz Supported
546+
* bit 1: 12 MHz Supported
547+
* bit 2: 24 MHz Supported
548+
* bit 3: 48 MHz Supported
549+
* bit 4: 96 MHz Supported
550+
* bit 5: 192 MHz Supported
551+
*/
552+
static int intel_get_lctl_scf(struct azx *chip)
553+
{
554+
struct hdac_bus *bus = azx_bus(chip);
555+
static int preferred_bits[] = { 2, 3, 1, 4, 5 };
556+
u32 val, t;
557+
int i;
558+
559+
val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCAP);
560+
561+
for (i = 0; i < ARRAY_SIZE(preferred_bits); i++) {
562+
t = preferred_bits[i];
563+
if (val & (1 << t))
564+
return t;
565+
}
566+
567+
dev_warn(chip->card->dev, "set audio clock frequency to 6MHz");
568+
return 0;
569+
}
570+
571+
static int intel_ml_lctl_set_power(struct azx *chip, int state)
572+
{
573+
struct hdac_bus *bus = azx_bus(chip);
574+
u32 val;
575+
int timeout;
576+
577+
/*
578+
* the codecs are sharing the first link setting by default
579+
* If other links are enabled for stream, they need similar fix
580+
*/
581+
val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
582+
val &= ~AZX_MLCTL_SPA;
583+
val |= state << AZX_MLCTL_SPA_SHIFT;
584+
writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
585+
/* wait for CPA */
586+
timeout = 50;
587+
while (timeout) {
588+
if (((readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL)) &
589+
AZX_MLCTL_CPA) == (state << AZX_MLCTL_CPA_SHIFT))
590+
return 0;
591+
timeout--;
592+
udelay(10);
593+
}
594+
595+
return -1;
596+
}
597+
598+
static void intel_init_lctl(struct azx *chip)
599+
{
600+
struct hdac_bus *bus = azx_bus(chip);
601+
u32 val;
602+
int ret;
603+
604+
/* 0. check lctl register value is correct or not */
605+
val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
606+
/* if SCF is already set, let's use it */
607+
if ((val & ML_LCTL_SCF_MASK) != 0)
608+
return;
609+
610+
/*
611+
* Before operating on SPA, CPA must match SPA.
612+
* Any deviation may result in undefined behavior.
613+
*/
614+
if (((val & AZX_MLCTL_SPA) >> AZX_MLCTL_SPA_SHIFT) !=
615+
((val & AZX_MLCTL_CPA) >> AZX_MLCTL_CPA_SHIFT))
616+
return;
617+
618+
/* 1. turn link down: set SPA to 0 and wait CPA to 0 */
619+
ret = intel_ml_lctl_set_power(chip, 0);
620+
udelay(100);
621+
if (ret)
622+
goto set_spa;
623+
624+
/* 2. update SCF to select a properly audio clock*/
625+
val &= ~ML_LCTL_SCF_MASK;
626+
val |= intel_get_lctl_scf(chip);
627+
writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
628+
629+
set_spa:
630+
/* 4. turn link up: set SPA to 1 and wait CPA to 1 */
631+
intel_ml_lctl_set_power(chip, 1);
632+
udelay(100);
633+
}
634+
543635
static void hda_intel_init_chip(struct azx *chip, bool full_reset)
544636
{
545637
struct hdac_bus *bus = azx_bus(chip);
@@ -565,6 +657,9 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
565657
/* reduce dma latency to avoid noise */
566658
if (IS_BXT(pci))
567659
bxt_reduce_dma_latency(chip);
660+
661+
if (bus->mlcap != NULL)
662+
intel_init_lctl(chip);
568663
}
569664

570665
/* calculate runtime delay from LPIB */

0 commit comments

Comments
 (0)