anolis: ALSA: hda: Fix single byte write failure issue for Hygon
ANBZ: #5455 On Hygon controller, some registers such as GCTL, SD_CTL and SD_CTL_3B should be accessed in dword. Signed-off-by: Pu Wen <puwen@hygon.cn> Reviewed-by: Artie Ding <artie.ding@linux.alibaba.com> Link: https://gitee.com/anolis/cloud-kernel/pulls/2537
This commit is contained in:
parent
b02e88d298
commit
24de3e7540
|
@ -2602,6 +2602,7 @@
|
|||
#define PCI_VENDOR_ID_ZHAOXIN 0x1d17
|
||||
|
||||
#define PCI_VENDOR_ID_HYGON 0x1d94
|
||||
#define PCI_DEVICE_ID_HYGON_18H_M05H_HDA 0x14a9
|
||||
#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3 0x14b3
|
||||
|
||||
#define PCI_VENDOR_ID_HXT 0x1dbf
|
||||
|
|
|
@ -342,6 +342,7 @@ struct hdac_bus {
|
|||
bool corbrp_self_clear:1; /* CORBRP clears itself after reset */
|
||||
bool polling_mode:1;
|
||||
bool needs_damn_long_delay:1;
|
||||
bool hygon_dword_access:1;
|
||||
|
||||
int poll_count;
|
||||
|
||||
|
|
|
@ -407,7 +407,10 @@ void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
|
|||
{
|
||||
unsigned long timeout;
|
||||
|
||||
snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
|
||||
else
|
||||
snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(100);
|
||||
while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout))
|
||||
|
@ -472,10 +475,16 @@ static void azx_int_disable(struct hdac_bus *bus)
|
|||
|
||||
/* disable interrupts in stream descriptor */
|
||||
list_for_each_entry(azx_dev, &bus->stream_list, list)
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, SD_INT_MASK, 0);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
|
||||
|
||||
/* disable SIE for all streams */
|
||||
snd_hdac_chip_writeb(bus, INTCTL, 0);
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_chip_writel(bus, INTCTL, 0);
|
||||
else
|
||||
snd_hdac_chip_writeb(bus, INTCTL, 0);
|
||||
|
||||
/* disable controller CIE and GIE */
|
||||
snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN, 0);
|
||||
|
|
|
@ -101,11 +101,19 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
|
|||
stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
|
||||
else
|
||||
stripe_ctl = 0;
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
|
||||
stripe_ctl);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
|
||||
stripe_ctl);
|
||||
}
|
||||
/* set DMA start and interrupt mask */
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL,
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL,
|
||||
0, SD_CTL_DMA_START | SD_INT_MASK);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL,
|
||||
0, SD_CTL_DMA_START | SD_INT_MASK);
|
||||
azx_dev->running = true;
|
||||
}
|
||||
|
@ -117,11 +125,21 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_start);
|
|||
*/
|
||||
void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
|
||||
{
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL,
|
||||
SD_CTL_DMA_START | SD_INT_MASK, 0);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
|
||||
if (azx_dev->stripe)
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
|
||||
struct hdac_bus *bus = azx_dev->bus;
|
||||
|
||||
if (bus->hygon_dword_access) {
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL,
|
||||
SD_CTL_DMA_START | SD_INT_MASK, 0);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
|
||||
if (azx_dev->stripe)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
|
||||
} else {
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL,
|
||||
SD_CTL_DMA_START | SD_INT_MASK, 0);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
|
||||
if (azx_dev->stripe)
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
|
||||
}
|
||||
azx_dev->running = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
|
||||
|
@ -151,12 +169,17 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
|
|||
unsigned char val;
|
||||
int timeout;
|
||||
int dma_run_state;
|
||||
struct hdac_bus *bus = azx_dev->bus;
|
||||
|
||||
snd_hdac_stream_clear(azx_dev);
|
||||
|
||||
dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
|
||||
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
|
||||
|
||||
udelay(3);
|
||||
timeout = 300;
|
||||
do {
|
||||
|
@ -170,7 +193,11 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
|
|||
udelay(azx_dev->bus->dma_stop_delay);
|
||||
|
||||
val &= ~SD_CTL_STREAM_RESET;
|
||||
snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
|
||||
if (bus->hygon_dword_access)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
|
||||
else
|
||||
snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
|
||||
|
||||
udelay(3);
|
||||
|
||||
timeout = 300;
|
||||
|
|
|
@ -1904,6 +1904,10 @@ static int azx_first_init(struct azx *chip)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (chip->driver_type == AZX_DRIVER_HYGON &&
|
||||
chip->pci->device == PCI_DEVICE_ID_HYGON_18H_M05H_HDA)
|
||||
bus->hygon_dword_access = 1;
|
||||
|
||||
err = pci_request_regions(pci, "ICH HD audio");
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
Loading…
Reference in New Issue