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;
|
int poll_count;
|
||||||
|
|
||||||
|
bool cmd_resend:1; /* command resend */
|
||||||
int bdl_pos_adj; /* BDL position adjustment */
|
int bdl_pos_adj; /* BDL position adjustment */
|
||||||
|
|
||||||
/* locks */
|
/* 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 addr = azx_command_addr(val);
|
||||||
unsigned int wp, rp;
|
unsigned int wp, rp;
|
||||||
|
unsigned long timeout;
|
||||||
|
unsigned int rirb_wp;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
spin_lock_irq(&bus->reg_lock);
|
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);
|
bus->corb.buf[wp] = cpu_to_le32(val);
|
||||||
snd_hdac_chip_writew(bus, CORBWP, wp);
|
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);
|
spin_unlock_irq(&bus->reg_lock);
|
||||||
|
|
||||||
return 0;
|
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);
|
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);
|
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
|
||||||
|
#endif
|
||||||
if (!fresh_start)
|
if (!fresh_start)
|
||||||
azx_dev->start_wallclk -= azx_dev->period_wallclk;
|
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);
|
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);
|
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void azx_timecounter_init(struct hdac_stream *azx_dev,
|
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
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called snd-hda-intel.
|
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
|
config SND_HDA_INTEL_DETECT_DMIC
|
||||||
bool "DMIC detection and probe abort"
|
bool "DMIC detection and probe abort"
|
||||||
depends on SND_HDA_INTEL
|
depends on SND_HDA_INTEL
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
snd-hda-intel-objs := hda_intel.o
|
snd-hda-intel-objs := hda_intel.o
|
||||||
|
snd-hda-phytium-objs := hda_phytium.o
|
||||||
snd-hda-tegra-objs := hda_tegra.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
|
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
|
# otherwise the codec patches won't be hooked before the PCI probe
|
||||||
# when built in kernel
|
# when built in kernel
|
||||||
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
|
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
|
obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "hda_phytium.h"
|
||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_X86
|
||||||
/* for art-tsc conversion */
|
/* for art-tsc conversion */
|
||||||
#include <asm/tsc.h>
|
#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);
|
snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
|
||||||
unsigned short ctls = spdif ? spdif->ctls : 0;
|
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);
|
trace_azx_pcm_prepare(chip, azx_dev);
|
||||||
dsp_lock(azx_dev);
|
dsp_lock(azx_dev);
|
||||||
if (dsp_is_locked(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