HDA driver support for Phytium desktop
(cherry picked from commit 61b278c01b
)
Signed-off-by: Alex Shi <alexsshi@tencent.com>
This commit is contained in:
parent
9b68c04c3f
commit
9cd366d0b7
|
@ -343,6 +343,7 @@ struct hdac_bus {
|
|||
|
||||
int poll_count;
|
||||
|
||||
bool cmd_resend:1; /* command resend */
|
||||
int bdl_pos_adj; /* BDL position adjustment */
|
||||
|
||||
/* locks */
|
||||
|
|
|
@ -142,6 +142,9 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val)
|
|||
{
|
||||
unsigned int addr = azx_command_addr(val);
|
||||
unsigned int wp, rp;
|
||||
unsigned long timeout;
|
||||
unsigned int rirb_wp;
|
||||
int i = 0;
|
||||
|
||||
spin_lock_irq(&bus->reg_lock);
|
||||
|
||||
|
@ -168,6 +171,41 @@ 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);
|
||||
|
||||
if (bus->cmd_resend) {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&bus->reg_lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -87,7 +87,11 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
|
|||
|
||||
trace_snd_hdac_stream_start(bus, azx_dev);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PHYTIUM
|
||||
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK) / 15;
|
||||
#else
|
||||
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
|
||||
#endif
|
||||
if (!fresh_start)
|
||||
azx_dev->start_wallclk -= azx_dev->period_wallclk;
|
||||
|
||||
|
@ -514,7 +518,11 @@ static u64 azx_cc_read(const struct cyclecounter *cc)
|
|||
{
|
||||
struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PHYTIUM
|
||||
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK) / 25;
|
||||
#else
|
||||
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void azx_timecounter_init(struct hdac_stream *azx_dev,
|
||||
|
|
|
@ -23,6 +23,23 @@ config SND_HDA_INTEL
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-hda-intel.
|
||||
|
||||
config SND_HDA_PHYTIUM
|
||||
tristate "PHYTIUM HD Audio"
|
||||
depends on SOUND
|
||||
select SND_HDA
|
||||
select SND_HDA_ALIGNED_MMIO
|
||||
help
|
||||
Say Y here to support the HDA controller present in PHYTIUM
|
||||
SoCs
|
||||
|
||||
This options enables support for the HD Audio controller
|
||||
present in some PHYTIUM SoCs, used to communicate audio
|
||||
to the "High Definition Audio" codec.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-hda-phytium.
|
||||
|
||||
|
||||
config SND_HDA_INTEL_DETECT_DMIC
|
||||
bool "DMIC detection and probe abort"
|
||||
depends on SND_HDA_INTEL
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
snd-hda-intel-objs := hda_intel.o
|
||||
snd-hda-phytium-objs := hda_phytium.o
|
||||
snd-hda-tegra-objs := hda_tegra.o
|
||||
|
||||
snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
|
||||
|
@ -47,4 +48,5 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
|
|||
# otherwise the codec patches won't be hooked before the PCI probe
|
||||
# when built in kernel
|
||||
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
|
||||
obj-$(CONFIG_SND_HDA_PHYTIUM) += snd-hda-phytium.o
|
||||
obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "hda_phytium.h"
|
||||
#ifdef CONFIG_X86
|
||||
/* for art-tsc conversion */
|
||||
#include <asm/tsc.h>
|
||||
|
@ -160,6 +161,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
|
||||
unsigned short ctls = spdif ? spdif->ctls : 0;
|
||||
|
||||
struct hda_ft *hda = container_of(chip, struct hda_ft, chip);
|
||||
hda->substream = substream;
|
||||
trace_azx_pcm_prepare(chip, azx_dev);
|
||||
dsp_lock(azx_dev);
|
||||
if (dsp_is_locked(azx_dev)) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Implementation of primary ALSA driver code base for Phytium HD Audio.
|
||||
*
|
||||
* Copyright(c) 2018-2022, Phytium Technology Co., Ltd.
|
||||
*/
|
||||
#ifndef __SOUND_HDA_PHYTIUM_H__
|
||||
#define __SOUND_HDA_PHYTIUM_H__
|
||||
#include "hda_controller.h"
|
||||
struct hda_ft {
|
||||
struct azx chip;
|
||||
struct snd_pcm_substream *substream;
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
/* for pending irqs */
|
||||
struct work_struct irq_pending_work;
|
||||
/* sync probing */
|
||||
struct completion probe_wait;
|
||||
struct work_struct probe_work;
|
||||
/* card list (for power_save trigger) */
|
||||
struct list_head list;
|
||||
/* extra flags */
|
||||
unsigned int irq_pending_warned:1;
|
||||
unsigned int probe_continued:1;
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue