add sound/hda/ CONFIG_SND_HDA_PHYTIUM

This commit is contained in:
luck 2023-08-25 16:46:21 +08:00
parent edb46b6c93
commit c22439f6a7
2 changed files with 55 additions and 2 deletions

View File

@ -10,6 +10,7 @@
#include <sound/hdaudio.h>
#include <sound/hda_register.h>
#include "local.h"
#include <linux/cputypes.h>
/* clear CORB read pointer properly */
static void azx_clear_corbrp(struct hdac_bus *bus)
@ -143,6 +144,11 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val)
{
unsigned int addr = azx_command_addr(val);
unsigned int wp, rp;
#ifdef CONFIG_SND_HDA_PHYTIUM
unsigned long timeout;
unsigned int rirb_wp;
int i = 0;
#endif
spin_lock_irq(&bus->reg_lock);
@ -169,6 +175,43 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val)
bus->corb.buf[wp] = cpu_to_le32(val);
snd_hdac_chip_writew(bus, CORBWP, wp);
#ifdef CONFIG_SND_HDA_PHYTIUM
if (cpu_is_phytium()) {
timeout = jiffies + msecs_to_jiffies(1000);
udelay(80);
rirb_wp = snd_hdac_chip_readw(bus, RIRBWP);
while (rirb_wp == bus->rirb.wp) {
udelay(80);
rirb_wp = snd_hdac_chip_readw(bus, RIRBWP);
if (rirb_wp != bus->rirb.wp)
break;
if (i > 5)
break;
if (time_after(jiffies, timeout))
break;
/* add command to corb */
wp = snd_hdac_chip_readw(bus, CORBWP);
if (wp == 0xffff) {
/* something wrong, controller likely turned to D3 */
spin_unlock_irq(&bus->reg_lock);
return -EIO;
}
wp++;
wp %= AZX_MAX_CORB_ENTRIES;
rp = snd_hdac_chip_readw(bus, CORBRP);
if (wp == rp) {
/* oops, it's full */
spin_unlock_irq(&bus->reg_lock);
return -EAGAIN;
}
bus->corb.buf[wp] = cpu_to_le32(val);
snd_hdac_chip_writew(bus, CORBWP, wp);
i++;
}
}
#endif
spin_unlock_irq(&bus->reg_lock);
return 0;

View File

@ -12,6 +12,7 @@
#include <sound/hdaudio.h>
#include <sound/hda_register.h>
#include "trace.h"
#include <linux/cputypes.h>
/**
* snd_hdac_get_stream_stripe_ctl - get stripe control value
@ -87,7 +88,12 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
trace_snd_hdac_stream_start(bus, azx_dev);
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
if (cpu_is_phytium()) {
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK) / 15;
} else {
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
}
if (!fresh_start)
azx_dev->start_wallclk -= azx_dev->period_wallclk;
@ -520,7 +526,11 @@ static u64 azx_cc_read(const struct cyclecounter *cc)
{
struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc);
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
if (cpu_is_phytium()) {
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK) / 25;
} else {
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
}
}
static void azx_timecounter_init(struct hdac_stream *azx_dev,