mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
ASoC: Last updates for v4.5
A bunch more updates for v4.5, mainly driver work: - More topology API enhancements from Mengdong Lin working towards making everything more component based and being able to specify PCM links via topology. - Large sets driver updates from Cirrus, Intel (mainly more Skylake support) and Renesas. - New drivers for AMD ACP, Atmel PDMIC, Dialog DA7218, Imagination Technologies SoC IPs, Rockchip RK3036 Inno CODEC and Texas Instruments PCM3168A. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJWk8EUAAoJECTWi3JdVIfQ+RwH/jid388X6x6YOa84Rs7InrIS m2rVdjDAMAbK+smhalHzvLOGnHjpygegwZ/9/1DUiSPbcXdqMkzLoaweeVUXhu27 9G3zT0Xz1XVn/+5029oIlrsyPCtM5O9PlPOO7tiQSTBADjvl+I4hl6FHZ1LGT7Sr tiOTAiOmIisELBzBF0L7fB18iBgE3VqkhG8obrMiTXVWgfZuRJL7kdH2WuHYFXpM JxBcy9VrCp0JHxg+qCD7xYyFdKLE6eP96gpLi94JBqW8I3wrwmEmUqNKs+r8I7Vj bh5/v6A2V0EaJWCKzWBARHE7BR3E2uJeoD0PcY59Kn7BKhKPjTe99g2ngTk1hIU= =BvEm -----END PGP SIGNATURE----- Merge tag 'asoc-v4.4-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next ASoC: Last updates for v4.5 A bunch more updates for v4.5, mainly driver work: - More topology API enhancements from Mengdong Lin working towards making everything more component based and being able to specify PCM links via topology. - Large sets driver updates from Cirrus, Intel (mainly more Skylake support) and Renesas. - New driver for AMD ACP - Rename PCM1792a driver to be generic pcm179x
This commit is contained in:
commit
815ad86236
@ -1,4 +1,4 @@
|
||||
Texas Instruments pcm1792a DT bindings
|
||||
Texas Instruments pcm179x DT bindings
|
||||
|
||||
This driver supports the SPI bus.
|
||||
|
41
Documentation/devicetree/bindings/sound/rt5651.txt
Normal file
41
Documentation/devicetree/bindings/sound/rt5651.txt
Normal file
@ -0,0 +1,41 @@
|
||||
RT5651 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt5651".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- realtek,in2-differential
|
||||
Boolean. Indicate MIC2 input are differential, rather than single-ended.
|
||||
|
||||
- realtek,dmic-en
|
||||
Boolean. true if dmic is used.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5651:
|
||||
|
||||
* DMIC L1
|
||||
* DMIC R1
|
||||
* IN1P
|
||||
* IN2P
|
||||
* IN2N
|
||||
* IN3P
|
||||
* HPOL
|
||||
* HPOR
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* PDML
|
||||
* PDMR
|
||||
|
||||
Example:
|
||||
|
||||
codec: rt5651@1a {
|
||||
compatible = "realtek,rt5651";
|
||||
reg = <0x1a>;
|
||||
realtek,dmic-en = "true";
|
||||
realtek,in2-diff = "false";
|
||||
};
|
@ -46,6 +46,7 @@ struct i2s_platform_data {
|
||||
u32 snd_rates;
|
||||
|
||||
#define DW_I2S_QUIRK_COMP_REG_OFFSET (1 << 0)
|
||||
#define DW_I2S_QUIRK_COMP_PARAM1 (1 << 1)
|
||||
unsigned int quirks;
|
||||
unsigned int i2s_reg_comp1;
|
||||
unsigned int i2s_reg_comp2;
|
||||
|
@ -233,6 +233,15 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
||||
#define AZX_MLCTL_SPA (1<<16)
|
||||
#define AZX_MLCTL_CPA 23
|
||||
|
||||
|
||||
/* registers for DMA Resume Capability Structure */
|
||||
#define AZX_DRSM_CAP_ID 0x5
|
||||
#define AZX_REG_DRSM_CTL 0x4
|
||||
/* Base used to calculate the iterating register offset */
|
||||
#define AZX_DRSM_BASE 0x08
|
||||
/* Interval used to calculate the iterating register offset */
|
||||
#define AZX_DRSM_INTERVAL 0x08
|
||||
|
||||
/*
|
||||
* helpers to read the stream position
|
||||
*/
|
||||
|
@ -12,6 +12,7 @@
|
||||
* @spbcap: SPIB capabilities pointer
|
||||
* @mlcap: MultiLink capabilities pointer
|
||||
* @gtscap: gts capabilities pointer
|
||||
* @drsmcap: dma resume capabilities pointer
|
||||
* @hlink_list: link list of HDA links
|
||||
*/
|
||||
struct hdac_ext_bus {
|
||||
@ -23,6 +24,7 @@ struct hdac_ext_bus {
|
||||
void __iomem *spbcap;
|
||||
void __iomem *mlcap;
|
||||
void __iomem *gtscap;
|
||||
void __iomem *drsmcap;
|
||||
|
||||
struct list_head hlink_list;
|
||||
};
|
||||
@ -72,6 +74,9 @@ enum hdac_ext_stream_type {
|
||||
* @pplc_addr: processing pipe link stream pointer
|
||||
* @spib_addr: software position in buffers stream pointer
|
||||
* @fifo_addr: software position Max fifos stream pointer
|
||||
* @dpibr_addr: DMA position in buffer resume pointer
|
||||
* @dpib: DMA position in buffer
|
||||
* @lpib: Linear position in buffer
|
||||
* @decoupled: stream host and link is decoupled
|
||||
* @link_locked: link is locked
|
||||
* @link_prepared: link is prepared
|
||||
@ -86,6 +91,10 @@ struct hdac_ext_stream {
|
||||
void __iomem *spib_addr;
|
||||
void __iomem *fifo_addr;
|
||||
|
||||
void __iomem *dpibr_addr;
|
||||
|
||||
u32 dpib;
|
||||
u32 lpib;
|
||||
bool decoupled:1;
|
||||
bool link_locked:1;
|
||||
bool link_prepared;
|
||||
@ -116,6 +125,11 @@ int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus,
|
||||
struct hdac_ext_stream *stream, u32 value);
|
||||
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus,
|
||||
struct hdac_ext_stream *stream);
|
||||
void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
|
||||
bool enable, int index);
|
||||
int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
|
||||
struct hdac_ext_stream *stream, u32 value);
|
||||
int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value);
|
||||
|
||||
void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hstream);
|
||||
void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hstream);
|
||||
@ -133,6 +147,7 @@ struct hdac_ext_link {
|
||||
|
||||
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link);
|
||||
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link);
|
||||
int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus);
|
||||
int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus);
|
||||
void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
|
||||
int stream);
|
||||
|
@ -222,6 +222,7 @@ struct snd_soc_dai_driver {
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
unsigned int base;
|
||||
struct snd_soc_dobj dobj;
|
||||
|
||||
/* DAI driver callbacks */
|
||||
int (*probe)(struct snd_soc_dai *dai);
|
||||
|
@ -798,6 +798,7 @@ struct snd_soc_component {
|
||||
unsigned int registered_as_component:1;
|
||||
|
||||
struct list_head list;
|
||||
struct list_head list_aux; /* for auxiliary component of the card */
|
||||
|
||||
struct snd_soc_dai_driver *dai_drv;
|
||||
int num_dai;
|
||||
@ -841,6 +842,9 @@ struct snd_soc_component {
|
||||
int (*probe)(struct snd_soc_component *);
|
||||
void (*remove)(struct snd_soc_component *);
|
||||
|
||||
/* machine specific init */
|
||||
int (*init)(struct snd_soc_component *component);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void (*init_debugfs)(struct snd_soc_component *component);
|
||||
const char *debugfs_prefix;
|
||||
@ -1141,8 +1145,7 @@ struct snd_soc_card {
|
||||
*/
|
||||
struct snd_soc_aux_dev *aux_dev;
|
||||
int num_aux_devs;
|
||||
struct snd_soc_pcm_runtime *rtd_aux;
|
||||
int num_aux_rtd;
|
||||
struct list_head aux_comp_list;
|
||||
|
||||
const struct snd_kcontrol_new *controls;
|
||||
int num_controls;
|
||||
@ -1550,6 +1553,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
|
||||
INIT_LIST_HEAD(&card->widgets);
|
||||
INIT_LIST_HEAD(&card->paths);
|
||||
INIT_LIST_HEAD(&card->dapm_list);
|
||||
INIT_LIST_HEAD(&card->aux_comp_list);
|
||||
}
|
||||
|
||||
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
|
||||
@ -1676,6 +1680,9 @@ int snd_soc_add_dai_link(struct snd_soc_card *card,
|
||||
void snd_soc_remove_dai_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
|
||||
int snd_soc_register_dai(struct snd_soc_component *component,
|
||||
struct snd_soc_dai_driver *dai_drv);
|
||||
|
||||
#include <sound/soc-dai.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
@ -77,6 +77,12 @@ int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *ebus)
|
||||
ebus->spbcap = bus->remap_addr + offset;
|
||||
break;
|
||||
|
||||
case AZX_DRSM_CAP_ID:
|
||||
/* DMA resume capability found, handler function */
|
||||
dev_dbg(bus->dev, "Found DRSM capability\n");
|
||||
ebus->drsmcap = bus->remap_addr + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap);
|
||||
break;
|
||||
@ -240,7 +246,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
|
||||
int mask = (1 << AZX_MLCTL_CPA);
|
||||
|
||||
udelay(3);
|
||||
timeout = 50;
|
||||
timeout = 150;
|
||||
|
||||
do {
|
||||
val = readl(link->ml_addr + AZX_REG_ML_LCTL);
|
||||
@ -281,6 +287,27 @@ int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down);
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_bus_link_power_up_all -power up all hda link
|
||||
* @ebus: HD-audio extended bus
|
||||
*/
|
||||
int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus)
|
||||
{
|
||||
struct hdac_ext_link *hlink = NULL;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(hlink, &ebus->hlink_list, list) {
|
||||
snd_hdac_updatel(hlink->ml_addr,
|
||||
AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA);
|
||||
ret = check_hdac_link_power_active(hlink, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up_all);
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_bus_link_power_down_all -power down all hda link
|
||||
* @ebus: HD-audio extended bus
|
||||
|
@ -59,6 +59,10 @@ void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus,
|
||||
AZX_SPB_MAXFIFO;
|
||||
}
|
||||
|
||||
if (ebus->drsmcap)
|
||||
stream->dpibr_addr = ebus->drsmcap + AZX_DRSM_BASE +
|
||||
AZX_DRSM_INTERVAL * idx;
|
||||
|
||||
stream->decoupled = false;
|
||||
snd_hdac_stream_init(bus, &stream->hstream, idx, direction, tag);
|
||||
}
|
||||
@ -107,6 +111,7 @@ void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus)
|
||||
while (!list_empty(&bus->stream_list)) {
|
||||
s = list_first_entry(&bus->stream_list, struct hdac_stream, list);
|
||||
stream = stream_to_hdac_ext_stream(s);
|
||||
snd_hdac_ext_stream_decouple(ebus, stream, false);
|
||||
list_del(&s->list);
|
||||
kfree(stream);
|
||||
}
|
||||
@ -497,3 +502,70 @@ void snd_hdac_ext_stop_streams(struct hdac_ext_bus *ebus)
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_stop_streams);
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_stream_drsm_enable - enable DMA resume for a stream
|
||||
* @ebus: HD-audio ext core bus
|
||||
* @enable: flag to enable/disable DRSM
|
||||
* @index: stream index for which DRSM need to be enabled
|
||||
*/
|
||||
void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
|
||||
bool enable, int index)
|
||||
{
|
||||
u32 mask = 0;
|
||||
u32 register_mask = 0;
|
||||
struct hdac_bus *bus = &ebus->bus;
|
||||
|
||||
if (!ebus->drsmcap) {
|
||||
dev_err(bus->dev, "Address of DRSM capability is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
mask |= (1 << index);
|
||||
|
||||
register_mask = readl(ebus->drsmcap + AZX_REG_SPB_SPBFCCTL);
|
||||
|
||||
mask |= register_mask;
|
||||
|
||||
if (enable)
|
||||
snd_hdac_updatel(ebus->drsmcap, AZX_REG_DRSM_CTL, 0, mask);
|
||||
else
|
||||
snd_hdac_updatel(ebus->drsmcap, AZX_REG_DRSM_CTL, mask, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable);
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_stream_set_dpibr - sets the dpibr value of a stream
|
||||
* @ebus: HD-audio ext core bus
|
||||
* @stream: hdac_ext_stream
|
||||
* @value: dpib value to set
|
||||
*/
|
||||
int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
|
||||
struct hdac_ext_stream *stream, u32 value)
|
||||
{
|
||||
struct hdac_bus *bus = &ebus->bus;
|
||||
|
||||
if (!ebus->drsmcap) {
|
||||
dev_err(bus->dev, "Address of DRSM capability is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(value, stream->dpibr_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr);
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream
|
||||
* @ebus: HD-audio ext core bus
|
||||
* @stream: hdac_ext_stream
|
||||
* @value: lpib value to set
|
||||
*/
|
||||
int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value)
|
||||
{
|
||||
snd_hdac_stream_writel(&stream->hstream, SD_LPIB, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_lpib);
|
||||
|
@ -38,6 +38,7 @@ config SND_SOC_TOPOLOGY
|
||||
|
||||
# All the supported SoCs
|
||||
source "sound/soc/adi/Kconfig"
|
||||
source "sound/soc/amd/Kconfig"
|
||||
source "sound/soc/atmel/Kconfig"
|
||||
source "sound/soc/au1x/Kconfig"
|
||||
source "sound/soc/bcm/Kconfig"
|
||||
|
@ -18,6 +18,7 @@ obj-$(CONFIG_SND_SOC) += snd-soc-core.o
|
||||
obj-$(CONFIG_SND_SOC) += codecs/
|
||||
obj-$(CONFIG_SND_SOC) += generic/
|
||||
obj-$(CONFIG_SND_SOC) += adi/
|
||||
obj-$(CONFIG_SND_SOC) += amd/
|
||||
obj-$(CONFIG_SND_SOC) += atmel/
|
||||
obj-$(CONFIG_SND_SOC) += au1x/
|
||||
obj-$(CONFIG_SND_SOC) += bcm/
|
||||
|
4
sound/soc/amd/Kconfig
Normal file
4
sound/soc/amd/Kconfig
Normal file
@ -0,0 +1,4 @@
|
||||
config SND_SOC_AMD_ACP
|
||||
tristate "AMD Audio Coprocessor support"
|
||||
help
|
||||
This option enables ACP DMA support on AMD platform.
|
3
sound/soc/amd/Makefile
Normal file
3
sound/soc/amd/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
snd-soc-acp-pcm-objs := acp-pcm-dma.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP) += snd-soc-acp-pcm.o
|
1043
sound/soc/amd/acp-pcm-dma.c
Normal file
1043
sound/soc/amd/acp-pcm-dma.c
Normal file
File diff suppressed because it is too large
Load Diff
118
sound/soc/amd/acp.h
Normal file
118
sound/soc/amd/acp.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef __ACP_HW_H
|
||||
#define __ACP_HW_H
|
||||
|
||||
#include "include/acp_2_2_d.h"
|
||||
#include "include/acp_2_2_sh_mask.h"
|
||||
|
||||
#define ACP_PAGE_SIZE_4K_ENABLE 0x02
|
||||
|
||||
#define ACP_PLAYBACK_PTE_OFFSET 10
|
||||
#define ACP_CAPTURE_PTE_OFFSET 0
|
||||
|
||||
#define ACP_GARLIC_CNTL_DEFAULT 0x00000FB4
|
||||
#define ACP_ONION_CNTL_DEFAULT 0x00000FB4
|
||||
|
||||
#define ACP_PHYSICAL_BASE 0x14000
|
||||
|
||||
/* Playback SRAM address (as a destination in dma descriptor) */
|
||||
#define ACP_SHARED_RAM_BANK_1_ADDRESS 0x4002000
|
||||
|
||||
/* Capture SRAM address (as a source in dma descriptor) */
|
||||
#define ACP_SHARED_RAM_BANK_5_ADDRESS 0x400A000
|
||||
|
||||
#define ACP_DMA_RESET_TIME 10000
|
||||
#define ACP_CLOCK_EN_TIME_OUT_VALUE 0x000000FF
|
||||
#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF
|
||||
#define ACP_DMA_COMPLETE_TIME_OUT_VALUE 0x000000FF
|
||||
|
||||
#define ACP_SRAM_BASE_ADDRESS 0x4000000
|
||||
#define ACP_DAGB_GRP_SRAM_BASE_ADDRESS 0x4001000
|
||||
#define ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET 0x1000
|
||||
#define ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS 0x00000000
|
||||
#define ACP_INTERNAL_APERTURE_WINDOW_4_ADDRESS 0x01800000
|
||||
|
||||
#define TO_ACP_I2S_1 0x2
|
||||
#define TO_ACP_I2S_2 0x4
|
||||
#define FROM_ACP_I2S_1 0xa
|
||||
#define FROM_ACP_I2S_2 0xb
|
||||
|
||||
#define ACP_TILE_ON_MASK 0x03
|
||||
#define ACP_TILE_OFF_MASK 0x02
|
||||
#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f
|
||||
#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20
|
||||
|
||||
#define ACP_TILE_P1_MASK 0x3e
|
||||
#define ACP_TILE_P2_MASK 0x3d
|
||||
#define ACP_TILE_DSP0_MASK 0x3b
|
||||
#define ACP_TILE_DSP1_MASK 0x37
|
||||
|
||||
#define ACP_TILE_DSP2_MASK 0x2f
|
||||
/* Playback DMA channels */
|
||||
#define SYSRAM_TO_ACP_CH_NUM 12
|
||||
#define ACP_TO_I2S_DMA_CH_NUM 13
|
||||
|
||||
/* Capture DMA channels */
|
||||
#define ACP_TO_SYSRAM_CH_NUM 14
|
||||
#define I2S_TO_ACP_DMA_CH_NUM 15
|
||||
|
||||
#define NUM_DSCRS_PER_CHANNEL 2
|
||||
|
||||
#define PLAYBACK_START_DMA_DESCR_CH12 0
|
||||
#define PLAYBACK_END_DMA_DESCR_CH12 1
|
||||
#define PLAYBACK_START_DMA_DESCR_CH13 2
|
||||
#define PLAYBACK_END_DMA_DESCR_CH13 3
|
||||
|
||||
#define CAPTURE_START_DMA_DESCR_CH14 4
|
||||
#define CAPTURE_END_DMA_DESCR_CH14 5
|
||||
#define CAPTURE_START_DMA_DESCR_CH15 6
|
||||
#define CAPTURE_END_DMA_DESCR_CH15 7
|
||||
|
||||
enum acp_dma_priority_level {
|
||||
/* 0x0 Specifies the DMA channel is given normal priority */
|
||||
ACP_DMA_PRIORITY_LEVEL_NORMAL = 0x0,
|
||||
/* 0x1 Specifies the DMA channel is given high priority */
|
||||
ACP_DMA_PRIORITY_LEVEL_HIGH = 0x1,
|
||||
ACP_DMA_PRIORITY_LEVEL_FORCESIZE = 0xFF
|
||||
};
|
||||
|
||||
struct audio_substream_data {
|
||||
struct page *pg;
|
||||
unsigned int order;
|
||||
u16 num_of_pages;
|
||||
u16 direction;
|
||||
uint64_t size;
|
||||
void __iomem *acp_mmio;
|
||||
};
|
||||
|
||||
enum {
|
||||
ACP_TILE_P1 = 0,
|
||||
ACP_TILE_P2,
|
||||
ACP_TILE_DSP0,
|
||||
ACP_TILE_DSP1,
|
||||
ACP_TILE_DSP2,
|
||||
};
|
||||
|
||||
enum {
|
||||
ACP_DMA_ATTRIBUTES_SHAREDMEM_TO_DAGB_ONION = 0x0,
|
||||
ACP_DMA_ATTRIBUTES_SHARED_MEM_TO_DAGB_GARLIC = 0x1,
|
||||
ACP_DMA_ATTRIBUTES_DAGB_ONION_TO_SHAREDMEM = 0x8,
|
||||
ACP_DMA_ATTRIBUTES_DAGB_GARLIC_TO_SHAREDMEM = 0x9,
|
||||
ACP_DMA_ATTRIBUTES_FORCE_SIZE = 0xF
|
||||
};
|
||||
|
||||
typedef struct acp_dma_dscr_transfer {
|
||||
/* Specifies the source memory location for the DMA data transfer. */
|
||||
u32 src;
|
||||
/* Specifies the destination memory location to where the data will
|
||||
* be transferred.
|
||||
*/
|
||||
u32 dest;
|
||||
/* Specifies the number of bytes need to be transferred
|
||||
* from source to destination memory.Transfer direction & IOC enable
|
||||
*/
|
||||
u32 xfer_val;
|
||||
/* Reserved for future use */
|
||||
u32 reserved;
|
||||
} acp_dma_dscr_transfer_t;
|
||||
|
||||
#endif /*__ACP_HW_H */
|
609
sound/soc/amd/include/acp_2_2_d.h
Normal file
609
sound/soc/amd/include/acp_2_2_d.h
Normal file
@ -0,0 +1,609 @@
|
||||
/*
|
||||
* ACP_2_2 Register documentation
|
||||
*
|
||||
* Copyright (C) 2014 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ACP_2_2_D_H
|
||||
#define ACP_2_2_D_H
|
||||
|
||||
#define mmACP_DMA_CNTL_0 0x5000
|
||||
#define mmACP_DMA_CNTL_1 0x5001
|
||||
#define mmACP_DMA_CNTL_2 0x5002
|
||||
#define mmACP_DMA_CNTL_3 0x5003
|
||||
#define mmACP_DMA_CNTL_4 0x5004
|
||||
#define mmACP_DMA_CNTL_5 0x5005
|
||||
#define mmACP_DMA_CNTL_6 0x5006
|
||||
#define mmACP_DMA_CNTL_7 0x5007
|
||||
#define mmACP_DMA_CNTL_8 0x5008
|
||||
#define mmACP_DMA_CNTL_9 0x5009
|
||||
#define mmACP_DMA_CNTL_10 0x500a
|
||||
#define mmACP_DMA_CNTL_11 0x500b
|
||||
#define mmACP_DMA_CNTL_12 0x500c
|
||||
#define mmACP_DMA_CNTL_13 0x500d
|
||||
#define mmACP_DMA_CNTL_14 0x500e
|
||||
#define mmACP_DMA_CNTL_15 0x500f
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_0 0x5010
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_1 0x5011
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_2 0x5012
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_3 0x5013
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_4 0x5014
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_5 0x5015
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_6 0x5016
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_7 0x5017
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_8 0x5018
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_9 0x5019
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_10 0x501a
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_11 0x501b
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_12 0x501c
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_13 0x501d
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_14 0x501e
|
||||
#define mmACP_DMA_DSCR_STRT_IDX_15 0x501f
|
||||
#define mmACP_DMA_DSCR_CNT_0 0x5020
|
||||
#define mmACP_DMA_DSCR_CNT_1 0x5021
|
||||
#define mmACP_DMA_DSCR_CNT_2 0x5022
|
||||
#define mmACP_DMA_DSCR_CNT_3 0x5023
|
||||
#define mmACP_DMA_DSCR_CNT_4 0x5024
|
||||
#define mmACP_DMA_DSCR_CNT_5 0x5025
|
||||
#define mmACP_DMA_DSCR_CNT_6 0x5026
|
||||
#define mmACP_DMA_DSCR_CNT_7 0x5027
|
||||
#define mmACP_DMA_DSCR_CNT_8 0x5028
|
||||
#define mmACP_DMA_DSCR_CNT_9 0x5029
|
||||
#define mmACP_DMA_DSCR_CNT_10 0x502a
|
||||
#define mmACP_DMA_DSCR_CNT_11 0x502b
|
||||
#define mmACP_DMA_DSCR_CNT_12 0x502c
|
||||
#define mmACP_DMA_DSCR_CNT_13 0x502d
|
||||
#define mmACP_DMA_DSCR_CNT_14 0x502e
|
||||
#define mmACP_DMA_DSCR_CNT_15 0x502f
|
||||
#define mmACP_DMA_PRIO_0 0x5030
|
||||
#define mmACP_DMA_PRIO_1 0x5031
|
||||
#define mmACP_DMA_PRIO_2 0x5032
|
||||
#define mmACP_DMA_PRIO_3 0x5033
|
||||
#define mmACP_DMA_PRIO_4 0x5034
|
||||
#define mmACP_DMA_PRIO_5 0x5035
|
||||
#define mmACP_DMA_PRIO_6 0x5036
|
||||
#define mmACP_DMA_PRIO_7 0x5037
|
||||
#define mmACP_DMA_PRIO_8 0x5038
|
||||
#define mmACP_DMA_PRIO_9 0x5039
|
||||
#define mmACP_DMA_PRIO_10 0x503a
|
||||
#define mmACP_DMA_PRIO_11 0x503b
|
||||
#define mmACP_DMA_PRIO_12 0x503c
|
||||
#define mmACP_DMA_PRIO_13 0x503d
|
||||
#define mmACP_DMA_PRIO_14 0x503e
|
||||
#define mmACP_DMA_PRIO_15 0x503f
|
||||
#define mmACP_DMA_CUR_DSCR_0 0x5040
|
||||
#define mmACP_DMA_CUR_DSCR_1 0x5041
|
||||
#define mmACP_DMA_CUR_DSCR_2 0x5042
|
||||
#define mmACP_DMA_CUR_DSCR_3 0x5043
|
||||
#define mmACP_DMA_CUR_DSCR_4 0x5044
|
||||
#define mmACP_DMA_CUR_DSCR_5 0x5045
|
||||
#define mmACP_DMA_CUR_DSCR_6 0x5046
|
||||
#define mmACP_DMA_CUR_DSCR_7 0x5047
|
||||
#define mmACP_DMA_CUR_DSCR_8 0x5048
|
||||
#define mmACP_DMA_CUR_DSCR_9 0x5049
|
||||
#define mmACP_DMA_CUR_DSCR_10 0x504a
|
||||
#define mmACP_DMA_CUR_DSCR_11 0x504b
|
||||
#define mmACP_DMA_CUR_DSCR_12 0x504c
|
||||
#define mmACP_DMA_CUR_DSCR_13 0x504d
|
||||
#define mmACP_DMA_CUR_DSCR_14 0x504e
|
||||
#define mmACP_DMA_CUR_DSCR_15 0x504f
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_0 0x5050
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_1 0x5051
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_2 0x5052
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_3 0x5053
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_4 0x5054
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_5 0x5055
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_6 0x5056
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_7 0x5057
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_8 0x5058
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_9 0x5059
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_10 0x505a
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_11 0x505b
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_12 0x505c
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_13 0x505d
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_14 0x505e
|
||||
#define mmACP_DMA_CUR_TRANS_CNT_15 0x505f
|
||||
#define mmACP_DMA_ERR_STS_0 0x5060
|
||||
#define mmACP_DMA_ERR_STS_1 0x5061
|
||||
#define mmACP_DMA_ERR_STS_2 0x5062
|
||||
#define mmACP_DMA_ERR_STS_3 0x5063
|
||||
#define mmACP_DMA_ERR_STS_4 0x5064
|
||||
#define mmACP_DMA_ERR_STS_5 0x5065
|
||||
#define mmACP_DMA_ERR_STS_6 0x5066
|
||||
#define mmACP_DMA_ERR_STS_7 0x5067
|
||||
#define mmACP_DMA_ERR_STS_8 0x5068
|
||||
#define mmACP_DMA_ERR_STS_9 0x5069
|
||||
#define mmACP_DMA_ERR_STS_10 0x506a
|
||||
#define mmACP_DMA_ERR_STS_11 0x506b
|
||||
#define mmACP_DMA_ERR_STS_12 0x506c
|
||||
#define mmACP_DMA_ERR_STS_13 0x506d
|
||||
#define mmACP_DMA_ERR_STS_14 0x506e
|
||||
#define mmACP_DMA_ERR_STS_15 0x506f
|
||||
#define mmACP_DMA_DESC_BASE_ADDR 0x5070
|
||||
#define mmACP_DMA_DESC_MAX_NUM_DSCR 0x5071
|
||||
#define mmACP_DMA_CH_STS 0x5072
|
||||
#define mmACP_DMA_CH_GROUP 0x5073
|
||||
#define mmACP_DSP0_CACHE_OFFSET0 0x5078
|
||||
#define mmACP_DSP0_CACHE_SIZE0 0x5079
|
||||
#define mmACP_DSP0_CACHE_OFFSET1 0x507a
|
||||
#define mmACP_DSP0_CACHE_SIZE1 0x507b
|
||||
#define mmACP_DSP0_CACHE_OFFSET2 0x507c
|
||||
#define mmACP_DSP0_CACHE_SIZE2 0x507d
|
||||
#define mmACP_DSP0_CACHE_OFFSET3 0x507e
|
||||
#define mmACP_DSP0_CACHE_SIZE3 0x507f
|
||||
#define mmACP_DSP0_CACHE_OFFSET4 0x5080
|
||||
#define mmACP_DSP0_CACHE_SIZE4 0x5081
|
||||
#define mmACP_DSP0_CACHE_OFFSET5 0x5082
|
||||
#define mmACP_DSP0_CACHE_SIZE5 0x5083
|
||||
#define mmACP_DSP0_CACHE_OFFSET6 0x5084
|
||||
#define mmACP_DSP0_CACHE_SIZE6 0x5085
|
||||
#define mmACP_DSP0_CACHE_OFFSET7 0x5086
|
||||
#define mmACP_DSP0_CACHE_SIZE7 0x5087
|
||||
#define mmACP_DSP0_CACHE_OFFSET8 0x5088
|
||||
#define mmACP_DSP0_CACHE_SIZE8 0x5089
|
||||
#define mmACP_DSP0_NONCACHE_OFFSET0 0x508a
|
||||
#define mmACP_DSP0_NONCACHE_SIZE0 0x508b
|
||||
#define mmACP_DSP0_NONCACHE_OFFSET1 0x508c
|
||||
#define mmACP_DSP0_NONCACHE_SIZE1 0x508d
|
||||
#define mmACP_DSP0_DEBUG_PC 0x508e
|
||||
#define mmACP_DSP0_NMI_SEL 0x508f
|
||||
#define mmACP_DSP0_CLKRST_CNTL 0x5090
|
||||
#define mmACP_DSP0_RUNSTALL 0x5091
|
||||
#define mmACP_DSP0_OCD_HALT_ON_RST 0x5092
|
||||
#define mmACP_DSP0_WAIT_MODE 0x5093
|
||||
#define mmACP_DSP0_VECT_SEL 0x5094
|
||||
#define mmACP_DSP0_DEBUG_REG1 0x5095
|
||||
#define mmACP_DSP0_DEBUG_REG2 0x5096
|
||||
#define mmACP_DSP0_DEBUG_REG3 0x5097
|
||||
#define mmACP_DSP1_CACHE_OFFSET0 0x509d
|
||||
#define mmACP_DSP1_CACHE_SIZE0 0x509e
|
||||
#define mmACP_DSP1_CACHE_OFFSET1 0x509f
|
||||
#define mmACP_DSP1_CACHE_SIZE1 0x50a0
|
||||
#define mmACP_DSP1_CACHE_OFFSET2 0x50a1
|
||||
#define mmACP_DSP1_CACHE_SIZE2 0x50a2
|
||||
#define mmACP_DSP1_CACHE_OFFSET3 0x50a3
|
||||
#define mmACP_DSP1_CACHE_SIZE3 0x50a4
|
||||
#define mmACP_DSP1_CACHE_OFFSET4 0x50a5
|
||||
#define mmACP_DSP1_CACHE_SIZE4 0x50a6
|
||||
#define mmACP_DSP1_CACHE_OFFSET5 0x50a7
|
||||
#define mmACP_DSP1_CACHE_SIZE5 0x50a8
|
||||
#define mmACP_DSP1_CACHE_OFFSET6 0x50a9
|
||||
#define mmACP_DSP1_CACHE_SIZE6 0x50aa
|
||||
#define mmACP_DSP1_CACHE_OFFSET7 0x50ab
|
||||
#define mmACP_DSP1_CACHE_SIZE7 0x50ac
|
||||
#define mmACP_DSP1_CACHE_OFFSET8 0x50ad
|
||||
#define mmACP_DSP1_CACHE_SIZE8 0x50ae
|
||||
#define mmACP_DSP1_NONCACHE_OFFSET0 0x50af
|
||||
#define mmACP_DSP1_NONCACHE_SIZE0 0x50b0
|
||||
#define mmACP_DSP1_NONCACHE_OFFSET1 0x50b1
|
||||
#define mmACP_DSP1_NONCACHE_SIZE1 0x50b2
|
||||
#define mmACP_DSP1_DEBUG_PC 0x50b3
|
||||
#define mmACP_DSP1_NMI_SEL 0x50b4
|
||||
#define mmACP_DSP1_CLKRST_CNTL 0x50b5
|
||||
#define mmACP_DSP1_RUNSTALL 0x50b6
|
||||
#define mmACP_DSP1_OCD_HALT_ON_RST 0x50b7
|
||||
#define mmACP_DSP1_WAIT_MODE 0x50b8
|
||||
#define mmACP_DSP1_VECT_SEL 0x50b9
|
||||
#define mmACP_DSP1_DEBUG_REG1 0x50ba
|
||||
#define mmACP_DSP1_DEBUG_REG2 0x50bb
|
||||
#define mmACP_DSP1_DEBUG_REG3 0x50bc
|
||||
#define mmACP_DSP2_CACHE_OFFSET0 0x50c2
|
||||
#define mmACP_DSP2_CACHE_SIZE0 0x50c3
|
||||
#define mmACP_DSP2_CACHE_OFFSET1 0x50c4
|
||||
#define mmACP_DSP2_CACHE_SIZE1 0x50c5
|
||||
#define mmACP_DSP2_CACHE_OFFSET2 0x50c6
|
||||
#define mmACP_DSP2_CACHE_SIZE2 0x50c7
|
||||
#define mmACP_DSP2_CACHE_OFFSET3 0x50c8
|
||||
#define mmACP_DSP2_CACHE_SIZE3 0x50c9
|
||||
#define mmACP_DSP2_CACHE_OFFSET4 0x50ca
|
||||
#define mmACP_DSP2_CACHE_SIZE4 0x50cb
|
||||
#define mmACP_DSP2_CACHE_OFFSET5 0x50cc
|
||||
#define mmACP_DSP2_CACHE_SIZE5 0x50cd
|
||||
#define mmACP_DSP2_CACHE_OFFSET6 0x50ce
|
||||
#define mmACP_DSP2_CACHE_SIZE6 0x50cf
|
||||
#define mmACP_DSP2_CACHE_OFFSET7 0x50d0
|
||||
#define mmACP_DSP2_CACHE_SIZE7 0x50d1
|
||||
#define mmACP_DSP2_CACHE_OFFSET8 0x50d2
|
||||
#define mmACP_DSP2_CACHE_SIZE8 0x50d3
|
||||
#define mmACP_DSP2_NONCACHE_OFFSET0 0x50d4
|
||||
#define mmACP_DSP2_NONCACHE_SIZE0 0x50d5
|
||||
#define mmACP_DSP2_NONCACHE_OFFSET1 0x50d6
|
||||
#define mmACP_DSP2_NONCACHE_SIZE1 0x50d7
|
||||
#define mmACP_DSP2_DEBUG_PC 0x50d8
|
||||
#define mmACP_DSP2_NMI_SEL 0x50d9
|
||||
#define mmACP_DSP2_CLKRST_CNTL 0x50da
|
||||
#define mmACP_DSP2_RUNSTALL 0x50db
|
||||
#define mmACP_DSP2_OCD_HALT_ON_RST 0x50dc
|
||||
#define mmACP_DSP2_WAIT_MODE 0x50dd
|
||||
#define mmACP_DSP2_VECT_SEL 0x50de
|
||||
#define mmACP_DSP2_DEBUG_REG1 0x50df
|
||||
#define mmACP_DSP2_DEBUG_REG2 0x50e0
|
||||
#define mmACP_DSP2_DEBUG_REG3 0x50e1
|
||||
#define mmACP_AXI2DAGB_ONION_CNTL 0x50e7
|
||||
#define mmACP_AXI2DAGB_ONION_ERR_STATUS_WR 0x50e8
|
||||
#define mmACP_AXI2DAGB_ONION_ERR_STATUS_RD 0x50e9
|
||||
#define mmACP_DAGB_Onion_TransPerf_Counter_Control 0x50ea
|
||||
#define mmACP_DAGB_Onion_Wr_TransPerf_Counter_Current 0x50eb
|
||||
#define mmACP_DAGB_Onion_Wr_TransPerf_Counter_Peak 0x50ec
|
||||
#define mmACP_DAGB_Onion_Rd_TransPerf_Counter_Current 0x50ed
|
||||
#define mmACP_DAGB_Onion_Rd_TransPerf_Counter_Peak 0x50ee
|
||||
#define mmACP_AXI2DAGB_GARLIC_CNTL 0x50f3
|
||||
#define mmACP_AXI2DAGB_GARLIC_ERR_STATUS_WR 0x50f4
|
||||
#define mmACP_AXI2DAGB_GARLIC_ERR_STATUS_RD 0x50f5
|
||||
#define mmACP_DAGB_Garlic_TransPerf_Counter_Control 0x50f6
|
||||
#define mmACP_DAGB_Garlic_Wr_TransPerf_Counter_Current 0x50f7
|
||||
#define mmACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak 0x50f8
|
||||
#define mmACP_DAGB_Garlic_Rd_TransPerf_Counter_Current 0x50f9
|
||||
#define mmACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak 0x50fa
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_1 0x50ff
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_1 0x5100
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_2 0x5101
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_2 0x5102
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_3 0x5103
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_3 0x5104
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_4 0x5105
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_4 0x5106
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_5 0x5107
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_5 0x5108
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_6 0x5109
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_6 0x510a
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_7 0x510b
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_7 0x510c
|
||||
#define mmACP_DAGB_PAGE_SIZE_GRP_8 0x510d
|
||||
#define mmACP_DAGB_BASE_ADDR_GRP_8 0x510e
|
||||
#define mmACP_DAGB_ATU_CTRL 0x510f
|
||||
#define mmACP_CONTROL 0x5131
|
||||
#define mmACP_STATUS 0x5133
|
||||
#define mmACP_SOFT_RESET 0x5134
|
||||
#define mmACP_PwrMgmt_CNTL 0x5135
|
||||
#define mmACP_CAC_INDICATOR_CONTROL 0x5136
|
||||
#define mmACP_SMU_MAILBOX 0x5137
|
||||
#define mmACP_FUTURE_REG_SCLK_0 0x5138
|
||||
#define mmACP_FUTURE_REG_SCLK_1 0x5139
|
||||
#define mmACP_FUTURE_REG_SCLK_2 0x513a
|
||||
#define mmACP_FUTURE_REG_SCLK_3 0x513b
|
||||
#define mmACP_FUTURE_REG_SCLK_4 0x513c
|
||||
#define mmACP_DAGB_DEBUG_CNT_ENABLE 0x513d
|
||||
#define mmACP_DAGBG_WR_ASK_CNT 0x513e
|
||||
#define mmACP_DAGBG_WR_GO_CNT 0x513f
|
||||
#define mmACP_DAGBG_WR_EXP_RESP_CNT 0x5140
|
||||
#define mmACP_DAGBG_WR_ACTUAL_RESP_CNT 0x5141
|
||||
#define mmACP_DAGBG_RD_ASK_CNT 0x5142
|
||||
#define mmACP_DAGBG_RD_GO_CNT 0x5143
|
||||
#define mmACP_DAGBG_RD_EXP_RESP_CNT 0x5144
|
||||
#define mmACP_DAGBG_RD_ACTUAL_RESP_CNT 0x5145
|
||||
#define mmACP_DAGBO_WR_ASK_CNT 0x5146
|
||||
#define mmACP_DAGBO_WR_GO_CNT 0x5147
|
||||
#define mmACP_DAGBO_WR_EXP_RESP_CNT 0x5148
|
||||
#define mmACP_DAGBO_WR_ACTUAL_RESP_CNT 0x5149
|
||||
#define mmACP_DAGBO_RD_ASK_CNT 0x514a
|
||||
#define mmACP_DAGBO_RD_GO_CNT 0x514b
|
||||
#define mmACP_DAGBO_RD_EXP_RESP_CNT 0x514c
|
||||
#define mmACP_DAGBO_RD_ACTUAL_RESP_CNT 0x514d
|
||||
#define mmACP_BRB_CONTROL 0x5156
|
||||
#define mmACP_EXTERNAL_INTR_ENB 0x5157
|
||||
#define mmACP_EXTERNAL_INTR_CNTL 0x5158
|
||||
#define mmACP_ERROR_SOURCE_STS 0x5159
|
||||
#define mmACP_DSP_SW_INTR_TRIG 0x515a
|
||||
#define mmACP_DSP_SW_INTR_CNTL 0x515b
|
||||
#define mmACP_DAGBG_TIMEOUT_CNTL 0x515c
|
||||
#define mmACP_DAGBO_TIMEOUT_CNTL 0x515d
|
||||
#define mmACP_EXTERNAL_INTR_STAT 0x515e
|
||||
#define mmACP_DSP_SW_INTR_STAT 0x515f
|
||||
#define mmACP_DSP0_INTR_CNTL 0x5160
|
||||
#define mmACP_DSP0_INTR_STAT 0x5161
|
||||
#define mmACP_DSP0_TIMEOUT_CNTL 0x5162
|
||||
#define mmACP_DSP1_INTR_CNTL 0x5163
|
||||
#define mmACP_DSP1_INTR_STAT 0x5164
|
||||
#define mmACP_DSP1_TIMEOUT_CNTL 0x5165
|
||||
#define mmACP_DSP2_INTR_CNTL 0x5166
|
||||
#define mmACP_DSP2_INTR_STAT 0x5167
|
||||
#define mmACP_DSP2_TIMEOUT_CNTL 0x5168
|
||||
#define mmACP_DSP0_EXT_TIMER_CNTL 0x5169
|
||||
#define mmACP_DSP1_EXT_TIMER_CNTL 0x516a
|
||||
#define mmACP_DSP2_EXT_TIMER_CNTL 0x516b
|
||||
#define mmACP_AXI2DAGB_SEM_0 0x516c
|
||||
#define mmACP_AXI2DAGB_SEM_1 0x516d
|
||||
#define mmACP_AXI2DAGB_SEM_2 0x516e
|
||||
#define mmACP_AXI2DAGB_SEM_3 0x516f
|
||||
#define mmACP_AXI2DAGB_SEM_4 0x5170
|
||||
#define mmACP_AXI2DAGB_SEM_5 0x5171
|
||||
#define mmACP_AXI2DAGB_SEM_6 0x5172
|
||||
#define mmACP_AXI2DAGB_SEM_7 0x5173
|
||||
#define mmACP_AXI2DAGB_SEM_8 0x5174
|
||||
#define mmACP_AXI2DAGB_SEM_9 0x5175
|
||||
#define mmACP_AXI2DAGB_SEM_10 0x5176
|
||||
#define mmACP_AXI2DAGB_SEM_11 0x5177
|
||||
#define mmACP_AXI2DAGB_SEM_12 0x5178
|
||||
#define mmACP_AXI2DAGB_SEM_13 0x5179
|
||||
#define mmACP_AXI2DAGB_SEM_14 0x517a
|
||||
#define mmACP_AXI2DAGB_SEM_15 0x517b
|
||||
#define mmACP_AXI2DAGB_SEM_16 0x517c
|
||||
#define mmACP_AXI2DAGB_SEM_17 0x517d
|
||||
#define mmACP_AXI2DAGB_SEM_18 0x517e
|
||||
#define mmACP_AXI2DAGB_SEM_19 0x517f
|
||||
#define mmACP_AXI2DAGB_SEM_20 0x5180
|
||||
#define mmACP_AXI2DAGB_SEM_21 0x5181
|
||||
#define mmACP_AXI2DAGB_SEM_22 0x5182
|
||||
#define mmACP_AXI2DAGB_SEM_23 0x5183
|
||||
#define mmACP_AXI2DAGB_SEM_24 0x5184
|
||||
#define mmACP_AXI2DAGB_SEM_25 0x5185
|
||||
#define mmACP_AXI2DAGB_SEM_26 0x5186
|
||||
#define mmACP_AXI2DAGB_SEM_27 0x5187
|
||||
#define mmACP_AXI2DAGB_SEM_28 0x5188
|
||||
#define mmACP_AXI2DAGB_SEM_29 0x5189
|
||||
#define mmACP_AXI2DAGB_SEM_30 0x518a
|
||||
#define mmACP_AXI2DAGB_SEM_31 0x518b
|
||||
#define mmACP_AXI2DAGB_SEM_32 0x518c
|
||||
#define mmACP_AXI2DAGB_SEM_33 0x518d
|
||||
#define mmACP_AXI2DAGB_SEM_34 0x518e
|
||||
#define mmACP_AXI2DAGB_SEM_35 0x518f
|
||||
#define mmACP_AXI2DAGB_SEM_36 0x5190
|
||||
#define mmACP_AXI2DAGB_SEM_37 0x5191
|
||||
#define mmACP_AXI2DAGB_SEM_38 0x5192
|
||||
#define mmACP_AXI2DAGB_SEM_39 0x5193
|
||||
#define mmACP_AXI2DAGB_SEM_40 0x5194
|
||||
#define mmACP_AXI2DAGB_SEM_41 0x5195
|
||||
#define mmACP_AXI2DAGB_SEM_42 0x5196
|
||||
#define mmACP_AXI2DAGB_SEM_43 0x5197
|
||||
#define mmACP_AXI2DAGB_SEM_44 0x5198
|
||||
#define mmACP_AXI2DAGB_SEM_45 0x5199
|
||||
#define mmACP_AXI2DAGB_SEM_46 0x519a
|
||||
#define mmACP_AXI2DAGB_SEM_47 0x519b
|
||||
#define mmACP_SRBM_Client_Base_Addr 0x519c
|
||||
#define mmACP_SRBM_Client_RDDATA 0x519d
|
||||
#define mmACP_SRBM_Cycle_Sts 0x519e
|
||||
#define mmACP_SRBM_Targ_Idx_Addr 0x519f
|
||||
#define mmACP_SRBM_Targ_Idx_Data 0x51a0
|
||||
#define mmACP_SEMA_ADDR_LOW 0x51a1
|
||||
#define mmACP_SEMA_ADDR_HIGH 0x51a2
|
||||
#define mmACP_SEMA_CMD 0x51a3
|
||||
#define mmACP_SEMA_STS 0x51a4
|
||||
#define mmACP_SEMA_REQ 0x51a5
|
||||
#define mmACP_FW_STATUS 0x51a6
|
||||
#define mmACP_FUTURE_REG_ACLK_0 0x51a7
|
||||
#define mmACP_FUTURE_REG_ACLK_1 0x51a8
|
||||
#define mmACP_FUTURE_REG_ACLK_2 0x51a9
|
||||
#define mmACP_FUTURE_REG_ACLK_3 0x51aa
|
||||
#define mmACP_FUTURE_REG_ACLK_4 0x51ab
|
||||
#define mmACP_TIMER 0x51ac
|
||||
#define mmACP_TIMER_CNTL 0x51ad
|
||||
#define mmACP_DSP0_TIMER 0x51ae
|
||||
#define mmACP_DSP1_TIMER 0x51af
|
||||
#define mmACP_DSP2_TIMER 0x51b0
|
||||
#define mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH 0x51b1
|
||||
#define mmACP_I2S_TRANSMIT_BYTE_CNT_LOW 0x51b2
|
||||
#define mmACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH 0x51b3
|
||||
#define mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW 0x51b4
|
||||
#define mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH 0x51b5
|
||||
#define mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW 0x51b6
|
||||
#define mmACP_DSP0_CS_STATE 0x51b7
|
||||
#define mmACP_DSP1_CS_STATE 0x51b8
|
||||
#define mmACP_DSP2_CS_STATE 0x51b9
|
||||
#define mmACP_SCRATCH_REG_BASE_ADDR 0x51ba
|
||||
#define mmCC_ACP_EFUSE 0x51c8
|
||||
#define mmACP_PGFSM_RETAIN_REG 0x51c9
|
||||
#define mmACP_PGFSM_CONFIG_REG 0x51ca
|
||||
#define mmACP_PGFSM_WRITE_REG 0x51cb
|
||||
#define mmACP_PGFSM_READ_REG_0 0x51cc
|
||||
#define mmACP_PGFSM_READ_REG_1 0x51cd
|
||||
#define mmACP_PGFSM_READ_REG_2 0x51ce
|
||||
#define mmACP_PGFSM_READ_REG_3 0x51cf
|
||||
#define mmACP_PGFSM_READ_REG_4 0x51d0
|
||||
#define mmACP_PGFSM_READ_REG_5 0x51d1
|
||||
#define mmACP_IP_PGFSM_ENABLE 0x51d2
|
||||
#define mmACP_I2S_PIN_CONFIG 0x51d3
|
||||
#define mmACP_AZALIA_I2S_SELECT 0x51d4
|
||||
#define mmACP_CHIP_PKG_FOR_PAD_ISOLATION 0x51d5
|
||||
#define mmACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL 0x51d6
|
||||
#define mmACP_BT_UART_PAD_SEL 0x51d7
|
||||
#define mmACP_SCRATCH_REG_0 0x52c0
|
||||
#define mmACP_SCRATCH_REG_1 0x52c1
|
||||
#define mmACP_SCRATCH_REG_2 0x52c2
|
||||
#define mmACP_SCRATCH_REG_3 0x52c3
|
||||
#define mmACP_SCRATCH_REG_4 0x52c4
|
||||
#define mmACP_SCRATCH_REG_5 0x52c5
|
||||
#define mmACP_SCRATCH_REG_6 0x52c6
|
||||
#define mmACP_SCRATCH_REG_7 0x52c7
|
||||
#define mmACP_SCRATCH_REG_8 0x52c8
|
||||
#define mmACP_SCRATCH_REG_9 0x52c9
|
||||
#define mmACP_SCRATCH_REG_10 0x52ca
|
||||
#define mmACP_SCRATCH_REG_11 0x52cb
|
||||
#define mmACP_SCRATCH_REG_12 0x52cc
|
||||
#define mmACP_SCRATCH_REG_13 0x52cd
|
||||
#define mmACP_SCRATCH_REG_14 0x52ce
|
||||
#define mmACP_SCRATCH_REG_15 0x52cf
|
||||
#define mmACP_SCRATCH_REG_16 0x52d0
|
||||
#define mmACP_SCRATCH_REG_17 0x52d1
|
||||
#define mmACP_SCRATCH_REG_18 0x52d2
|
||||
#define mmACP_SCRATCH_REG_19 0x52d3
|
||||
#define mmACP_SCRATCH_REG_20 0x52d4
|
||||
#define mmACP_SCRATCH_REG_21 0x52d5
|
||||
#define mmACP_SCRATCH_REG_22 0x52d6
|
||||
#define mmACP_SCRATCH_REG_23 0x52d7
|
||||
#define mmACP_SCRATCH_REG_24 0x52d8
|
||||
#define mmACP_SCRATCH_REG_25 0x52d9
|
||||
#define mmACP_SCRATCH_REG_26 0x52da
|
||||
#define mmACP_SCRATCH_REG_27 0x52db
|
||||
#define mmACP_SCRATCH_REG_28 0x52dc
|
||||
#define mmACP_SCRATCH_REG_29 0x52dd
|
||||
#define mmACP_SCRATCH_REG_30 0x52de
|
||||
#define mmACP_SCRATCH_REG_31 0x52df
|
||||
#define mmACP_SCRATCH_REG_32 0x52e0
|
||||
#define mmACP_SCRATCH_REG_33 0x52e1
|
||||
#define mmACP_SCRATCH_REG_34 0x52e2
|
||||
#define mmACP_SCRATCH_REG_35 0x52e3
|
||||
#define mmACP_SCRATCH_REG_36 0x52e4
|
||||
#define mmACP_SCRATCH_REG_37 0x52e5
|
||||
#define mmACP_SCRATCH_REG_38 0x52e6
|
||||
#define mmACP_SCRATCH_REG_39 0x52e7
|
||||
#define mmACP_SCRATCH_REG_40 0x52e8
|
||||
#define mmACP_SCRATCH_REG_41 0x52e9
|
||||
#define mmACP_SCRATCH_REG_42 0x52ea
|
||||
#define mmACP_SCRATCH_REG_43 0x52eb
|
||||
#define mmACP_SCRATCH_REG_44 0x52ec
|
||||
#define mmACP_SCRATCH_REG_45 0x52ed
|
||||
#define mmACP_SCRATCH_REG_46 0x52ee
|
||||
#define mmACP_SCRATCH_REG_47 0x52ef
|
||||
#define mmACP_VOICE_WAKEUP_ENABLE 0x51e8
|
||||
#define mmACP_VOICE_WAKEUP_STATUS 0x51e9
|
||||
#define mmI2S_VOICE_WAKEUP_LOWER_THRESHOLD 0x51ea
|
||||
#define mmI2S_VOICE_WAKEUP_HIGHER_THRESHOLD 0x51eb
|
||||
#define mmI2S_VOICE_WAKEUP_NO_OF_SAMPLES 0x51ec
|
||||
#define mmI2S_VOICE_WAKEUP_NO_OF_PEAKS 0x51ed
|
||||
#define mmI2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS 0x51ee
|
||||
#define mmI2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION 0x51ef
|
||||
#define mmI2S_VOICE_WAKEUP_DATA_PATH_SWITCH 0x51f0
|
||||
#define mmI2S_VOICE_WAKEUP_DATA_POINTER 0x51f1
|
||||
#define mmI2S_VOICE_WAKEUP_AUTH_MATCH 0x51f2
|
||||
#define mmI2S_VOICE_WAKEUP_8KB_WRAP 0x51f3
|
||||
#define mmACP_I2S_RECEIVED_BYTE_CNT_HIGH 0x51f4
|
||||
#define mmACP_I2S_RECEIVED_BYTE_CNT_LOW 0x51f5
|
||||
#define mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH 0x51f6
|
||||
#define mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW 0x51f7
|
||||
#define mmACP_MEM_SHUT_DOWN_REQ_LO 0x51f8
|
||||
#define mmACP_MEM_SHUT_DOWN_REQ_HI 0x51f9
|
||||
#define mmACP_MEM_SHUT_DOWN_STS_LO 0x51fa
|
||||
#define mmACP_MEM_SHUT_DOWN_STS_HI 0x51fb
|
||||
#define mmACP_MEM_DEEP_SLEEP_REQ_LO 0x51fc
|
||||
#define mmACP_MEM_DEEP_SLEEP_REQ_HI 0x51fd
|
||||
#define mmACP_MEM_DEEP_SLEEP_STS_LO 0x51fe
|
||||
#define mmACP_MEM_DEEP_SLEEP_STS_HI 0x51ff
|
||||
#define mmACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO 0x5200
|
||||
#define mmACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI 0x5201
|
||||
#define mmACP_MEM_WAKEUP_FROM_SLEEP_LO 0x5202
|
||||
#define mmACP_MEM_WAKEUP_FROM_SLEEP_HI 0x5203
|
||||
#define mmACP_I2SSP_IER 0x5210
|
||||
#define mmACP_I2SSP_IRER 0x5211
|
||||
#define mmACP_I2SSP_ITER 0x5212
|
||||
#define mmACP_I2SSP_CER 0x5213
|
||||
#define mmACP_I2SSP_CCR 0x5214
|
||||
#define mmACP_I2SSP_RXFFR 0x5215
|
||||
#define mmACP_I2SSP_TXFFR 0x5216
|
||||
#define mmACP_I2SSP_LRBR0 0x5218
|
||||
#define mmACP_I2SSP_RRBR0 0x5219
|
||||
#define mmACP_I2SSP_RER0 0x521a
|
||||
#define mmACP_I2SSP_TER0 0x521b
|
||||
#define mmACP_I2SSP_RCR0 0x521c
|
||||
#define mmACP_I2SSP_TCR0 0x521d
|
||||
#define mmACP_I2SSP_ISR0 0x521e
|
||||
#define mmACP_I2SSP_IMR0 0x521f
|
||||
#define mmACP_I2SSP_ROR0 0x5220
|
||||
#define mmACP_I2SSP_TOR0 0x5221
|
||||
#define mmACP_I2SSP_RFCR0 0x5222
|
||||
#define mmACP_I2SSP_TFCR0 0x5223
|
||||
#define mmACP_I2SSP_RFF0 0x5224
|
||||
#define mmACP_I2SSP_TFF0 0x5225
|
||||
#define mmACP_I2SSP_RXDMA 0x5226
|
||||
#define mmACP_I2SSP_RRXDMA 0x5227
|
||||
#define mmACP_I2SSP_TXDMA 0x5228
|
||||
#define mmACP_I2SSP_RTXDMA 0x5229
|
||||
#define mmACP_I2SSP_COMP_PARAM_2 0x522a
|
||||
#define mmACP_I2SSP_COMP_PARAM_1 0x522b
|
||||
#define mmACP_I2SSP_COMP_VERSION 0x522c
|
||||
#define mmACP_I2SSP_COMP_TYPE 0x522d
|
||||
#define mmACP_I2SMICSP_IER 0x522e
|
||||
#define mmACP_I2SMICSP_IRER 0x522f
|
||||
#define mmACP_I2SMICSP_ITER 0x5230
|
||||
#define mmACP_I2SMICSP_CER 0x5231
|
||||
#define mmACP_I2SMICSP_CCR 0x5232
|
||||
#define mmACP_I2SMICSP_RXFFR 0x5233
|
||||
#define mmACP_I2SMICSP_TXFFR 0x5234
|
||||
#define mmACP_I2SMICSP_LRBR0 0x5236
|
||||
#define mmACP_I2SMICSP_RRBR0 0x5237
|
||||
#define mmACP_I2SMICSP_RER0 0x5238
|
||||
#define mmACP_I2SMICSP_TER0 0x5239
|
||||
#define mmACP_I2SMICSP_RCR0 0x523a
|
||||
#define mmACP_I2SMICSP_TCR0 0x523b
|
||||
#define mmACP_I2SMICSP_ISR0 0x523c
|
||||
#define mmACP_I2SMICSP_IMR0 0x523d
|
||||
#define mmACP_I2SMICSP_ROR0 0x523e
|
||||
#define mmACP_I2SMICSP_TOR0 0x523f
|
||||
#define mmACP_I2SMICSP_RFCR0 0x5240
|
||||
#define mmACP_I2SMICSP_TFCR0 0x5241
|
||||
#define mmACP_I2SMICSP_RFF0 0x5242
|
||||
#define mmACP_I2SMICSP_TFF0 0x5243
|
||||
#define mmACP_I2SMICSP_LRBR1 0x5246
|
||||
#define mmACP_I2SMICSP_RRBR1 0x5247
|
||||
#define mmACP_I2SMICSP_RER1 0x5248
|
||||
#define mmACP_I2SMICSP_TER1 0x5249
|
||||
#define mmACP_I2SMICSP_RCR1 0x524a
|
||||
#define mmACP_I2SMICSP_TCR1 0x524b
|
||||
#define mmACP_I2SMICSP_ISR1 0x524c
|
||||
#define mmACP_I2SMICSP_IMR1 0x524d
|
||||
#define mmACP_I2SMICSP_ROR1 0x524e
|
||||
#define mmACP_I2SMICSP_TOR1 0x524f
|
||||
#define mmACP_I2SMICSP_RFCR1 0x5250
|
||||
#define mmACP_I2SMICSP_TFCR1 0x5251
|
||||
#define mmACP_I2SMICSP_RFF1 0x5252
|
||||
#define mmACP_I2SMICSP_TFF1 0x5253
|
||||
#define mmACP_I2SMICSP_RXDMA 0x5254
|
||||
#define mmACP_I2SMICSP_RRXDMA 0x5255
|
||||
#define mmACP_I2SMICSP_TXDMA 0x5256
|
||||
#define mmACP_I2SMICSP_RTXDMA 0x5257
|
||||
#define mmACP_I2SMICSP_COMP_PARAM_2 0x5258
|
||||
#define mmACP_I2SMICSP_COMP_PARAM_1 0x5259
|
||||
#define mmACP_I2SMICSP_COMP_VERSION 0x525a
|
||||
#define mmACP_I2SMICSP_COMP_TYPE 0x525b
|
||||
#define mmACP_I2SBT_IER 0x525c
|
||||
#define mmACP_I2SBT_IRER 0x525d
|
||||
#define mmACP_I2SBT_ITER 0x525e
|
||||
#define mmACP_I2SBT_CER 0x525f
|
||||
#define mmACP_I2SBT_CCR 0x5260
|
||||
#define mmACP_I2SBT_RXFFR 0x5261
|
||||
#define mmACP_I2SBT_TXFFR 0x5262
|
||||
#define mmACP_I2SBT_LRBR0 0x5264
|
||||
#define mmACP_I2SBT_RRBR0 0x5265
|
||||
#define mmACP_I2SBT_RER0 0x5266
|
||||
#define mmACP_I2SBT_TER0 0x5267
|
||||
#define mmACP_I2SBT_RCR0 0x5268
|
||||
#define mmACP_I2SBT_TCR0 0x5269
|
||||
#define mmACP_I2SBT_ISR0 0x526a
|
||||
#define mmACP_I2SBT_IMR0 0x526b
|
||||
#define mmACP_I2SBT_ROR0 0x526c
|
||||
#define mmACP_I2SBT_TOR0 0x526d
|
||||
#define mmACP_I2SBT_RFCR0 0x526e
|
||||
#define mmACP_I2SBT_TFCR0 0x526f
|
||||
#define mmACP_I2SBT_RFF0 0x5270
|
||||
#define mmACP_I2SBT_TFF0 0x5271
|
||||
#define mmACP_I2SBT_LRBR1 0x5274
|
||||
#define mmACP_I2SBT_RRBR1 0x5275
|
||||
#define mmACP_I2SBT_RER1 0x5276
|
||||
#define mmACP_I2SBT_TER1 0x5277
|
||||
#define mmACP_I2SBT_RCR1 0x5278
|
||||
#define mmACP_I2SBT_TCR1 0x5279
|
||||
#define mmACP_I2SBT_ISR1 0x527a
|
||||
#define mmACP_I2SBT_IMR1 0x527b
|
||||
#define mmACP_I2SBT_ROR1 0x527c
|
||||
#define mmACP_I2SBT_TOR1 0x527d
|
||||
#define mmACP_I2SBT_RFCR1 0x527e
|
||||
#define mmACP_I2SBT_TFCR1 0x527f
|
||||
#define mmACP_I2SBT_RFF1 0x5280
|
||||
#define mmACP_I2SBT_TFF1 0x5281
|
||||
#define mmACP_I2SBT_RXDMA 0x5282
|
||||
#define mmACP_I2SBT_RRXDMA 0x5283
|
||||
#define mmACP_I2SBT_TXDMA 0x5284
|
||||
#define mmACP_I2SBT_RTXDMA 0x5285
|
||||
#define mmACP_I2SBT_COMP_PARAM_2 0x5286
|
||||
#define mmACP_I2SBT_COMP_PARAM_1 0x5287
|
||||
#define mmACP_I2SBT_COMP_VERSION 0x5288
|
||||
#define mmACP_I2SBT_COMP_TYPE 0x5289
|
||||
|
||||
#endif /* ACP_2_2_D_H */
|
1068
sound/soc/amd/include/acp_2_2_enum.h
Normal file
1068
sound/soc/amd/include/acp_2_2_enum.h
Normal file
File diff suppressed because it is too large
Load Diff
2292
sound/soc/amd/include/acp_2_2_sh_mask.h
Normal file
2292
sound/soc/amd/include/acp_2_2_sh_mask.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -31,20 +31,20 @@
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
/* Clock registers */
|
||||
#define BCM2835_CLK_PCMCTL_REG 0x00
|
||||
|
@ -87,7 +87,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_ML26124 if I2C
|
||||
select SND_SOC_NAU8825 if I2C
|
||||
select SND_SOC_PCM1681 if I2C
|
||||
select SND_SOC_PCM1792A if SPI_MASTER
|
||||
select SND_SOC_PCM179X if SPI_MASTER
|
||||
select SND_SOC_PCM3008
|
||||
select SND_SOC_PCM3168A_I2C if I2C
|
||||
select SND_SOC_PCM3168A_SPI if SPI_MASTER
|
||||
@ -526,8 +526,8 @@ config SND_SOC_PCM1681
|
||||
tristate "Texas Instruments PCM1681 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_PCM1792A
|
||||
tristate "Texas Instruments PCM1792A CODEC"
|
||||
config SND_SOC_PCM179X
|
||||
tristate "Texas Instruments PCM179X CODEC"
|
||||
depends on SPI_MASTER
|
||||
|
||||
config SND_SOC_PCM3008
|
||||
|
@ -80,7 +80,7 @@ snd-soc-mc13783-objs := mc13783.o
|
||||
snd-soc-ml26124-objs := ml26124.o
|
||||
snd-soc-nau8825-objs := nau8825.o
|
||||
snd-soc-pcm1681-objs := pcm1681.o
|
||||
snd-soc-pcm1792a-codec-objs := pcm1792a.o
|
||||
snd-soc-pcm179x-codec-objs := pcm179x.o
|
||||
snd-soc-pcm3008-objs := pcm3008.o
|
||||
snd-soc-pcm3168a-objs := pcm3168a.o
|
||||
snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o
|
||||
@ -284,7 +284,7 @@ obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
|
||||
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
|
||||
obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
|
||||
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
|
||||
obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
|
||||
obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o
|
||||
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
|
||||
obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o
|
||||
obj-$(CONFIG_SND_SOC_PCM3168A_I2C) += snd-soc-pcm3168a-i2c.o
|
||||
|
@ -1494,6 +1494,9 @@ static int arizona_startup(struct snd_pcm_substream *substream,
|
||||
const struct snd_pcm_hw_constraint_list *constraint;
|
||||
unsigned int base_rate;
|
||||
|
||||
if (!substream->runtime)
|
||||
return 0;
|
||||
|
||||
switch (dai_priv->clk) {
|
||||
case ARIZONA_CLK_SYSCLK:
|
||||
base_rate = priv->sysclk;
|
||||
|
@ -1954,17 +1954,44 @@ static int da7218_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
dai_clk_mode |= DA7218_DAI_WCLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
dai_clk_mode |= DA7218_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
dai_clk_mode |= DA7218_DAI_WCLK_POL_INV |
|
||||
DA7218_DAI_CLK_POL_INV;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
dai_clk_mode |= DA7218_DAI_WCLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
dai_clk_mode |= DA7218_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
dai_clk_mode |= DA7218_DAI_WCLK_POL_INV | DA7218_DAI_CLK_POL_INV;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
dai_clk_mode |= DA7218_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
dai_clk_mode |= DA7218_DAI_WCLK_POL_INV |
|
||||
DA7218_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
dai_clk_mode |= DA7218_DAI_WCLK_POL_INV;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -1156,18 +1156,44 @@ static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
dai_clk_mode |= DA7219_DAI_WCLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
dai_clk_mode |= DA7219_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
dai_clk_mode |= DA7219_DAI_WCLK_POL_INV |
|
||||
DA7219_DAI_CLK_POL_INV;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
dai_clk_mode |= DA7219_DAI_WCLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
dai_clk_mode |= DA7219_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
dai_clk_mode |= DA7219_DAI_WCLK_POL_INV |
|
||||
DA7219_DAI_CLK_POL_INV;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
dai_clk_mode |= DA7219_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
dai_clk_mode |= DA7219_DAI_WCLK_POL_INV |
|
||||
DA7219_DAI_CLK_POL_INV;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
dai_clk_mode |= DA7219_DAI_WCLK_POL_INV;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -1592,9 +1618,14 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec)
|
||||
}
|
||||
}
|
||||
|
||||
static struct reg_sequence da7219_rev_aa_patch[] = {
|
||||
{ DA7219_REFERENCES, 0x08 },
|
||||
};
|
||||
|
||||
static int da7219_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int rev;
|
||||
int ret;
|
||||
|
||||
mutex_init(&da7219->lock);
|
||||
@ -1604,6 +1635,26 @@ static int da7219_probe(struct snd_soc_codec *codec)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(da7219->regmap, DA7219_CHIP_REVISION, &rev);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to read chip revision: %d\n", ret);
|
||||
goto err_disable_reg;
|
||||
}
|
||||
|
||||
switch (rev & DA7219_CHIP_MINOR_MASK) {
|
||||
case 0:
|
||||
ret = regmap_register_patch(da7219->regmap, da7219_rev_aa_patch,
|
||||
ARRAY_SIZE(da7219_rev_aa_patch));
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to register AA patch: %d\n",
|
||||
ret);
|
||||
goto err_disable_reg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle DT/Platform data */
|
||||
if (codec->dev->of_node)
|
||||
da7219->pdata = da7219_of_to_pdata(codec);
|
||||
@ -1774,7 +1825,6 @@ static struct reg_default da7219_reg_defaults[] = {
|
||||
{ DA7219_MIXOUT_R_CTRL, 0x10 },
|
||||
{ DA7219_CHIP_ID1, 0x23 },
|
||||
{ DA7219_CHIP_ID2, 0x93 },
|
||||
{ DA7219_CHIP_REVISION, 0x00 },
|
||||
{ DA7219_IO_CTRL, 0x00 },
|
||||
{ DA7219_GAIN_RAMP_CTRL, 0x00 },
|
||||
{ DA7219_PC_COUNT, 0x02 },
|
||||
|
@ -43,11 +43,13 @@ struct hdac_hdmi_cvt_params {
|
||||
};
|
||||
|
||||
struct hdac_hdmi_cvt {
|
||||
struct list_head head;
|
||||
hda_nid_t nid;
|
||||
struct hdac_hdmi_cvt_params params;
|
||||
};
|
||||
|
||||
struct hdac_hdmi_pin {
|
||||
struct list_head head;
|
||||
hda_nid_t nid;
|
||||
int num_mux_nids;
|
||||
hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
|
||||
@ -55,21 +57,23 @@ struct hdac_hdmi_pin {
|
||||
|
||||
struct hdac_hdmi_dai_pin_map {
|
||||
int dai_id;
|
||||
struct hdac_hdmi_pin pin;
|
||||
struct hdac_hdmi_cvt cvt;
|
||||
struct hdac_hdmi_pin *pin;
|
||||
struct hdac_hdmi_cvt *cvt;
|
||||
};
|
||||
|
||||
struct hdac_hdmi_priv {
|
||||
hda_nid_t pin_nid[3];
|
||||
hda_nid_t cvt_nid[3];
|
||||
struct hdac_hdmi_dai_pin_map dai_map[3];
|
||||
struct list_head pin_list;
|
||||
struct list_head cvt_list;
|
||||
int num_pin;
|
||||
int num_cvt;
|
||||
};
|
||||
|
||||
static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
|
||||
{
|
||||
struct hdac_device *hdac = container_of(dev, struct hdac_device, dev);
|
||||
struct hdac_device *hdac = dev_to_hdac_dev(dev);
|
||||
|
||||
return container_of(hdac, struct hdac_ext_device, hdac);
|
||||
return to_ehdac_device(hdac);
|
||||
}
|
||||
|
||||
static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
|
||||
@ -149,13 +153,15 @@ static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
|
||||
struct hdac_hdmi_dai_pin_map *dai_map, unsigned int pwr_state)
|
||||
{
|
||||
/* Power up pin widget */
|
||||
if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin.nid, pwr_state))
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->pin.nid, 0,
|
||||
if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin->nid,
|
||||
pwr_state))
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->pin->nid, 0,
|
||||
AC_VERB_SET_POWER_STATE, pwr_state);
|
||||
|
||||
/* Power up converter */
|
||||
if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt.nid, pwr_state))
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0,
|
||||
if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt->nid,
|
||||
pwr_state))
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
|
||||
AC_VERB_SET_POWER_STATE, pwr_state);
|
||||
}
|
||||
|
||||
@ -179,13 +185,13 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
|
||||
dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n",
|
||||
dd->stream_tag, dd->format);
|
||||
|
||||
ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt.nid,
|
||||
dai_map->pin.nid);
|
||||
ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
|
||||
dai_map->pin->nid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return hdac_hdmi_setup_stream(hdac, dai_map->cvt.nid, dai_map->pin.nid,
|
||||
dd->stream_tag, dd->format);
|
||||
return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid,
|
||||
dai_map->pin->nid, dd->stream_tag, dd->format);
|
||||
}
|
||||
|
||||
static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
|
||||
@ -221,9 +227,9 @@ static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
|
||||
|
||||
dai_map = &hdmi->dai_map[dai->id];
|
||||
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0,
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
|
||||
AC_VERB_SET_CHANNEL_STREAMID, 0);
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0,
|
||||
snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
|
||||
AC_VERB_SET_STREAM_FORMAT, 0);
|
||||
|
||||
dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
|
||||
@ -249,7 +255,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
|
||||
|
||||
dai_map = &hdmi->dai_map[dai->id];
|
||||
|
||||
val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin.nid, 0,
|
||||
val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin->nid, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0);
|
||||
dev_info(&hdac->hdac.dev, "Val for AC_VERB_GET_PIN_SENSE: %x\n", val);
|
||||
|
||||
@ -260,7 +266,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
|
||||
|
||||
hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0);
|
||||
|
||||
snd_hdac_codec_write(&hdac->hdac, dai_map->pin.nid, 0,
|
||||
snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
|
||||
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
|
||||
|
||||
snd_pcm_hw_constraint_step(substream->runtime, 0,
|
||||
@ -280,7 +286,7 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
|
||||
|
||||
hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
|
||||
|
||||
snd_hdac_codec_write(&hdac->hdac, dai_map->pin.nid, 0,
|
||||
snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
|
||||
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
||||
}
|
||||
|
||||
@ -304,26 +310,6 @@ hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac,
|
||||
struct hdac_hdmi_pin *pin)
|
||||
{
|
||||
if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
|
||||
dev_warn(&hdac->hdac.dev,
|
||||
"HDMI: pin %d wcaps %#x does not support connection list\n",
|
||||
pin->nid, get_wcaps(&hdac->hdac, pin->nid));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
|
||||
pin->mux_nids, HDA_MAX_CONNECTIONS);
|
||||
if (pin->num_mux_nids == 0) {
|
||||
dev_err(&hdac->hdac.dev, "No connections found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return pin->num_mux_nids;
|
||||
}
|
||||
|
||||
static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w,
|
||||
enum snd_soc_dapm_type id,
|
||||
const char *wname, const char *stream)
|
||||
@ -366,40 +352,79 @@ static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm,
|
||||
snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route));
|
||||
}
|
||||
|
||||
static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev,
|
||||
struct hdac_hdmi_dai_pin_map *dai_map,
|
||||
hda_nid_t pin_nid, hda_nid_t cvt_nid, int dai_id)
|
||||
static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
|
||||
{
|
||||
int ret;
|
||||
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||
struct hdac_hdmi_dai_pin_map *dai_map = &hdmi->dai_map[0];
|
||||
struct hdac_hdmi_cvt *cvt;
|
||||
struct hdac_hdmi_pin *pin;
|
||||
|
||||
dai_map->dai_id = dai_id;
|
||||
dai_map->pin.nid = pin_nid;
|
||||
if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
|
||||
return -EINVAL;
|
||||
|
||||
ret = hdac_hdmi_query_pin_connlist(edev, &dai_map->pin);
|
||||
if (ret < 0) {
|
||||
dev_err(&edev->hdac.dev,
|
||||
"Error querying connection list: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* Currently on board only 1 pin and 1 converter is enabled for
|
||||
* simplification, more will be added eventually
|
||||
* So using fixed map for dai_id:pin:cvt
|
||||
*/
|
||||
cvt = list_first_entry(&hdmi->cvt_list, struct hdac_hdmi_cvt, head);
|
||||
pin = list_first_entry(&hdmi->pin_list, struct hdac_hdmi_pin, head);
|
||||
|
||||
dai_map->cvt.nid = cvt_nid;
|
||||
dai_map->dai_id = 0;
|
||||
dai_map->pin = pin;
|
||||
|
||||
dai_map->cvt = cvt;
|
||||
|
||||
/* Enable out path for this pin widget */
|
||||
snd_hdac_codec_write(&edev->hdac, pin_nid, 0,
|
||||
snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
||||
|
||||
/* Enable transmission */
|
||||
snd_hdac_codec_write(&edev->hdac, cvt_nid, 0,
|
||||
snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
|
||||
AC_VERB_SET_DIGI_CONVERT_1, 1);
|
||||
|
||||
/* Category Code (CC) to zero */
|
||||
snd_hdac_codec_write(&edev->hdac, cvt_nid, 0,
|
||||
snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
|
||||
AC_VERB_SET_DIGI_CONVERT_2, 0);
|
||||
|
||||
snd_hdac_codec_write(&edev->hdac, pin_nid, 0,
|
||||
snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
|
||||
AC_VERB_SET_CONNECT_SEL, 0);
|
||||
|
||||
return hdac_hdmi_query_cvt_params(&edev->hdac, &dai_map->cvt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
|
||||
{
|
||||
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||
struct hdac_hdmi_cvt *cvt;
|
||||
|
||||
cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
|
||||
if (!cvt)
|
||||
return -ENOMEM;
|
||||
|
||||
cvt->nid = nid;
|
||||
|
||||
list_add_tail(&cvt->head, &hdmi->cvt_list);
|
||||
hdmi->num_cvt++;
|
||||
|
||||
return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
|
||||
}
|
||||
|
||||
static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
|
||||
{
|
||||
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||
struct hdac_hdmi_pin *pin;
|
||||
|
||||
pin = kzalloc(sizeof(*pin), GFP_KERNEL);
|
||||
if (!pin)
|
||||
return -ENOMEM;
|
||||
|
||||
pin->nid = nid;
|
||||
|
||||
list_add_tail(&pin->head, &hdmi->pin_list);
|
||||
hdmi->num_pin++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -412,10 +437,10 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
|
||||
int i, num_nodes;
|
||||
struct hdac_device *hdac = &edev->hdac;
|
||||
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||
int cvt_nid = 0, pin_nid = 0;
|
||||
int ret;
|
||||
|
||||
num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
|
||||
if (!nid || num_nodes < 0) {
|
||||
if (!nid || num_nodes <= 0) {
|
||||
dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -436,29 +461,25 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
|
||||
switch (type) {
|
||||
|
||||
case AC_WID_AUD_OUT:
|
||||
hdmi->cvt_nid[cvt_nid] = nid;
|
||||
cvt_nid++;
|
||||
ret = hdac_hdmi_add_cvt(edev, nid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case AC_WID_PIN:
|
||||
hdmi->pin_nid[pin_nid] = nid;
|
||||
pin_nid++;
|
||||
ret = hdac_hdmi_add_pin(edev, nid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hdac->end_nid = nid;
|
||||
|
||||
if (!pin_nid || !cvt_nid)
|
||||
if (!hdmi->num_pin || !hdmi->num_cvt)
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* Currently on board only 1 pin and 1 converter is enabled for
|
||||
* simplification, more will be added eventually
|
||||
* So using fixed map for dai_id:pin:cvt
|
||||
*/
|
||||
return hdac_hdmi_init_dai_map(edev, &hdmi->dai_map[0], hdmi->pin_nid[0],
|
||||
hdmi->cvt_nid[0], 0);
|
||||
return hdac_hdmi_init_dai_map(edev);
|
||||
}
|
||||
|
||||
static int hdmi_codec_probe(struct snd_soc_codec *codec)
|
||||
@ -542,6 +563,9 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
|
||||
|
||||
dev_set_drvdata(&codec->dev, edev);
|
||||
|
||||
INIT_LIST_HEAD(&hdmi_priv->pin_list);
|
||||
INIT_LIST_HEAD(&hdmi_priv->cvt_list);
|
||||
|
||||
ret = hdac_hdmi_parse_and_map_nid(edev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -553,8 +577,22 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
|
||||
|
||||
static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
|
||||
{
|
||||
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||
struct hdac_hdmi_pin *pin, *pin_next;
|
||||
struct hdac_hdmi_cvt *cvt, *cvt_next;
|
||||
|
||||
snd_soc_unregister_codec(&edev->hdac.dev);
|
||||
|
||||
list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
|
||||
list_del(&cvt->head);
|
||||
kfree(cvt);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
|
||||
list_del(&pin->head);
|
||||
kfree(pin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,271 +0,0 @@
|
||||
/*
|
||||
* PCM1792A ASoC codec driver
|
||||
*
|
||||
* Copyright (c) Amarula Solutions B.V. 2013
|
||||
*
|
||||
* Michael Trimarchi <michael@amarulasolutions.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "pcm1792a.h"
|
||||
|
||||
#define PCM1792A_DAC_VOL_LEFT 0x10
|
||||
#define PCM1792A_DAC_VOL_RIGHT 0x11
|
||||
#define PCM1792A_FMT_CONTROL 0x12
|
||||
#define PCM1792A_MODE_CONTROL 0x13
|
||||
#define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL
|
||||
|
||||
#define PCM1792A_FMT_MASK 0x70
|
||||
#define PCM1792A_FMT_SHIFT 4
|
||||
#define PCM1792A_MUTE_MASK 0x01
|
||||
#define PCM1792A_MUTE_SHIFT 0
|
||||
#define PCM1792A_ATLD_ENABLE (1 << 7)
|
||||
|
||||
static const struct reg_default pcm1792a_reg_defaults[] = {
|
||||
{ 0x10, 0xff },
|
||||
{ 0x11, 0xff },
|
||||
{ 0x12, 0x50 },
|
||||
{ 0x13, 0x00 },
|
||||
{ 0x14, 0x00 },
|
||||
{ 0x15, 0x01 },
|
||||
{ 0x16, 0x00 },
|
||||
{ 0x17, 0x00 },
|
||||
};
|
||||
|
||||
static bool pcm1792a_accessible_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg >= 0x10 && reg <= 0x17;
|
||||
}
|
||||
|
||||
static bool pcm1792a_writeable_reg(struct device *dev, unsigned register reg)
|
||||
{
|
||||
bool accessible;
|
||||
|
||||
accessible = pcm1792a_accessible_reg(dev, reg);
|
||||
|
||||
return accessible && reg != 0x16 && reg != 0x17;
|
||||
}
|
||||
|
||||
struct pcm1792a_private {
|
||||
struct regmap *regmap;
|
||||
unsigned int format;
|
||||
unsigned int rate;
|
||||
};
|
||||
|
||||
static int pcm1792a_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int format)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
priv->format = format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm1792a_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM1792A_SOFT_MUTE,
|
||||
PCM1792A_MUTE_MASK, !!mute);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int val = 0, ret;
|
||||
|
||||
priv->rate = params_rate(params);
|
||||
|
||||
switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
case 32:
|
||||
val = 2;
|
||||
break;
|
||||
case 16:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
case 32:
|
||||
val = 5;
|
||||
break;
|
||||
case 16:
|
||||
val = 4;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Invalid DAI format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = val << PCM1792A_FMT_SHIFT | PCM1792A_ATLD_ENABLE;
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM1792A_FMT_CONTROL,
|
||||
PCM1792A_FMT_MASK | PCM1792A_ATLD_ENABLE, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops pcm1792a_dai_ops = {
|
||||
.set_fmt = pcm1792a_set_dai_fmt,
|
||||
.hw_params = pcm1792a_hw_params,
|
||||
.digital_mute = pcm1792a_digital_mute,
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(pcm1792a_dac_tlv, -12000, 50, 1);
|
||||
|
||||
static const struct snd_kcontrol_new pcm1792a_controls[] = {
|
||||
SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
|
||||
PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
|
||||
pcm1792a_dac_tlv),
|
||||
SOC_SINGLE("DAC Invert Output Switch", PCM1792A_MODE_CONTROL, 7, 1, 0),
|
||||
SOC_SINGLE("DAC Rolloff Filter Switch", PCM1792A_MODE_CONTROL, 1, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("IOUTL+"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTL-"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTR+"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTR-"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route pcm1792a_dapm_routes[] = {
|
||||
{ "IOUTL+", NULL, "Playback" },
|
||||
{ "IOUTL-", NULL, "Playback" },
|
||||
{ "IOUTR+", NULL, "Playback" },
|
||||
{ "IOUTR-", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver pcm1792a_dai = {
|
||||
.name = "pcm1792a-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = PCM1792A_RATES,
|
||||
.formats = PCM1792A_FORMATS, },
|
||||
.ops = &pcm1792a_dai_ops,
|
||||
};
|
||||
|
||||
static const struct of_device_id pcm1792a_of_match[] = {
|
||||
{ .compatible = "ti,pcm1792a", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcm1792a_of_match);
|
||||
|
||||
static const struct regmap_config pcm1792a_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 23,
|
||||
.reg_defaults = pcm1792a_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(pcm1792a_reg_defaults),
|
||||
.writeable_reg = pcm1792a_writeable_reg,
|
||||
.readable_reg = pcm1792a_accessible_reg,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm1792a = {
|
||||
.controls = pcm1792a_controls,
|
||||
.num_controls = ARRAY_SIZE(pcm1792a_controls),
|
||||
.dapm_widgets = pcm1792a_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(pcm1792a_dapm_widgets),
|
||||
.dapm_routes = pcm1792a_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(pcm1792a_dapm_routes),
|
||||
};
|
||||
|
||||
static int pcm1792a_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct pcm1792a_private *pcm1792a;
|
||||
int ret;
|
||||
|
||||
pcm1792a = devm_kzalloc(&spi->dev, sizeof(struct pcm1792a_private),
|
||||
GFP_KERNEL);
|
||||
if (!pcm1792a)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, pcm1792a);
|
||||
|
||||
pcm1792a->regmap = devm_regmap_init_spi(spi, &pcm1792a_regmap);
|
||||
if (IS_ERR(pcm1792a->regmap)) {
|
||||
ret = PTR_ERR(pcm1792a->regmap);
|
||||
dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_pcm1792a, &pcm1792a_dai, 1);
|
||||
}
|
||||
|
||||
static int pcm1792a_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id pcm1792a_spi_ids[] = {
|
||||
{ "pcm1792a", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, pcm1792a_spi_ids);
|
||||
|
||||
static struct spi_driver pcm1792a_codec_driver = {
|
||||
.driver = {
|
||||
.name = "pcm1792a",
|
||||
.of_match_table = of_match_ptr(pcm1792a_of_match),
|
||||
},
|
||||
.id_table = pcm1792a_spi_ids,
|
||||
.probe = pcm1792a_spi_probe,
|
||||
.remove = pcm1792a_spi_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(pcm1792a_codec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC PCM1792A driver");
|
||||
MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
|
||||
MODULE_LICENSE("GPL");
|
271
sound/soc/codecs/pcm179x.c
Normal file
271
sound/soc/codecs/pcm179x.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* PCM179X ASoC codec driver
|
||||
*
|
||||
* Copyright (c) Amarula Solutions B.V. 2013
|
||||
*
|
||||
* Michael Trimarchi <michael@amarulasolutions.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "pcm179x.h"
|
||||
|
||||
#define PCM179X_DAC_VOL_LEFT 0x10
|
||||
#define PCM179X_DAC_VOL_RIGHT 0x11
|
||||
#define PCM179X_FMT_CONTROL 0x12
|
||||
#define PCM179X_MODE_CONTROL 0x13
|
||||
#define PCM179X_SOFT_MUTE PCM179X_FMT_CONTROL
|
||||
|
||||
#define PCM179X_FMT_MASK 0x70
|
||||
#define PCM179X_FMT_SHIFT 4
|
||||
#define PCM179X_MUTE_MASK 0x01
|
||||
#define PCM179X_MUTE_SHIFT 0
|
||||
#define PCM179X_ATLD_ENABLE (1 << 7)
|
||||
|
||||
static const struct reg_default pcm179x_reg_defaults[] = {
|
||||
{ 0x10, 0xff },
|
||||
{ 0x11, 0xff },
|
||||
{ 0x12, 0x50 },
|
||||
{ 0x13, 0x00 },
|
||||
{ 0x14, 0x00 },
|
||||
{ 0x15, 0x01 },
|
||||
{ 0x16, 0x00 },
|
||||
{ 0x17, 0x00 },
|
||||
};
|
||||
|
||||
static bool pcm179x_accessible_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg >= 0x10 && reg <= 0x17;
|
||||
}
|
||||
|
||||
static bool pcm179x_writeable_reg(struct device *dev, unsigned register reg)
|
||||
{
|
||||
bool accessible;
|
||||
|
||||
accessible = pcm179x_accessible_reg(dev, reg);
|
||||
|
||||
return accessible && reg != 0x16 && reg != 0x17;
|
||||
}
|
||||
|
||||
struct pcm179x_private {
|
||||
struct regmap *regmap;
|
||||
unsigned int format;
|
||||
unsigned int rate;
|
||||
};
|
||||
|
||||
static int pcm179x_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int format)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct pcm179x_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
priv->format = format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm179x_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm179x_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM179X_SOFT_MUTE,
|
||||
PCM179X_MUTE_MASK, !!mute);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm179x_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm179x_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int val = 0, ret;
|
||||
|
||||
priv->rate = params_rate(params);
|
||||
|
||||
switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
case 32:
|
||||
val = 2;
|
||||
break;
|
||||
case 16:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
case 32:
|
||||
val = 5;
|
||||
break;
|
||||
case 16:
|
||||
val = 4;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Invalid DAI format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = val << PCM179X_FMT_SHIFT | PCM179X_ATLD_ENABLE;
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM179X_FMT_CONTROL,
|
||||
PCM179X_FMT_MASK | PCM179X_ATLD_ENABLE, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops pcm179x_dai_ops = {
|
||||
.set_fmt = pcm179x_set_dai_fmt,
|
||||
.hw_params = pcm179x_hw_params,
|
||||
.digital_mute = pcm179x_digital_mute,
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(pcm179x_dac_tlv, -12000, 50, 1);
|
||||
|
||||
static const struct snd_kcontrol_new pcm179x_controls[] = {
|
||||
SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM179X_DAC_VOL_LEFT,
|
||||
PCM179X_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
|
||||
pcm179x_dac_tlv),
|
||||
SOC_SINGLE("DAC Invert Output Switch", PCM179X_MODE_CONTROL, 7, 1, 0),
|
||||
SOC_SINGLE("DAC Rolloff Filter Switch", PCM179X_MODE_CONTROL, 1, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm179x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("IOUTL+"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTL-"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTR+"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTR-"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route pcm179x_dapm_routes[] = {
|
||||
{ "IOUTL+", NULL, "Playback" },
|
||||
{ "IOUTL-", NULL, "Playback" },
|
||||
{ "IOUTR+", NULL, "Playback" },
|
||||
{ "IOUTR-", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver pcm179x_dai = {
|
||||
.name = "pcm179x-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = PCM1792A_RATES,
|
||||
.formats = PCM1792A_FORMATS, },
|
||||
.ops = &pcm179x_dai_ops,
|
||||
};
|
||||
|
||||
static const struct of_device_id pcm179x_of_match[] = {
|
||||
{ .compatible = "ti,pcm1792a", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcm179x_of_match);
|
||||
|
||||
static const struct regmap_config pcm179x_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 23,
|
||||
.reg_defaults = pcm179x_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(pcm179x_reg_defaults),
|
||||
.writeable_reg = pcm179x_writeable_reg,
|
||||
.readable_reg = pcm179x_accessible_reg,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm179x = {
|
||||
.controls = pcm179x_controls,
|
||||
.num_controls = ARRAY_SIZE(pcm179x_controls),
|
||||
.dapm_widgets = pcm179x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(pcm179x_dapm_widgets),
|
||||
.dapm_routes = pcm179x_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes),
|
||||
};
|
||||
|
||||
static int pcm179x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct pcm179x_private *pcm179x;
|
||||
int ret;
|
||||
|
||||
pcm179x = devm_kzalloc(&spi->dev, sizeof(struct pcm179x_private),
|
||||
GFP_KERNEL);
|
||||
if (!pcm179x)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, pcm179x);
|
||||
|
||||
pcm179x->regmap = devm_regmap_init_spi(spi, &pcm179x_regmap);
|
||||
if (IS_ERR(pcm179x->regmap)) {
|
||||
ret = PTR_ERR(pcm179x->regmap);
|
||||
dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_pcm179x, &pcm179x_dai, 1);
|
||||
}
|
||||
|
||||
static int pcm179x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id pcm179x_spi_ids[] = {
|
||||
{ "pcm179x", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, pcm179x_spi_ids);
|
||||
|
||||
static struct spi_driver pcm179x_codec_driver = {
|
||||
.driver = {
|
||||
.name = "pcm179x",
|
||||
.of_match_table = of_match_ptr(pcm179x_of_match),
|
||||
},
|
||||
.id_table = pcm179x_spi_ids,
|
||||
.probe = pcm179x_spi_probe,
|
||||
.remove = pcm179x_spi_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(pcm179x_codec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC PCM179X driver");
|
||||
MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* definitions for PCM1792A
|
||||
* definitions for PCM179X
|
||||
*
|
||||
* Copyright 2013 Amarula Solutions
|
||||
*
|
||||
@ -14,8 +14,8 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __PCM1792A_H__
|
||||
#define __PCM1792A_H__
|
||||
#ifndef __PCM179X_H__
|
||||
#define __PCM179X_H__
|
||||
|
||||
#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
|
||||
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
|
@ -488,6 +488,18 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_using_asrc(struct snd_soc_dapm_widget *source,
|
||||
struct snd_soc_dapm_widget *sink)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!rt5640->asrc_en)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Digital Mixer */
|
||||
static const struct snd_kcontrol_new rt5640_sto_adc_l_mix[] = {
|
||||
SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
|
||||
@ -1059,6 +1071,20 @@ static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w,
|
||||
static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
|
||||
RT5640_PWR_PLL_BIT, 0, NULL, 0),
|
||||
|
||||
/* ASRC */
|
||||
SND_SOC_DAPM_SUPPLY_S("Stereo Filter ASRC", 1, RT5640_ASRC_1,
|
||||
15, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("I2S2 Filter ASRC", 1, RT5640_ASRC_1,
|
||||
12, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5640_ASRC_1,
|
||||
11, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("DMIC1 ASRC", 1, RT5640_ASRC_1,
|
||||
9, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("DMIC2 ASRC", 1, RT5640_ASRC_1,
|
||||
8, 0, NULL, 0),
|
||||
|
||||
|
||||
/* Input Side */
|
||||
/* micbias */
|
||||
SND_SOC_DAPM_SUPPLY("LDO2", RT5640_PWR_ANLG1,
|
||||
@ -1319,6 +1345,12 @@ static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = {
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
|
||||
{ "I2S1", NULL, "Stereo Filter ASRC", is_using_asrc },
|
||||
{ "I2S2", NULL, "I2S2 ASRC", is_using_asrc },
|
||||
{ "I2S2", NULL, "I2S2 Filter ASRC", is_using_asrc },
|
||||
{ "DMIC1", NULL, "DMIC1 ASRC", is_using_asrc },
|
||||
{ "DMIC2", NULL, "DMIC2 ASRC", is_using_asrc },
|
||||
|
||||
{"IN1P", NULL, "LDO2"},
|
||||
{"IN2P", NULL, "LDO2"},
|
||||
{"IN3P", NULL, "LDO2"},
|
||||
@ -1981,6 +2013,76 @@ int rt5640_dmic_enable(struct snd_soc_codec *codec,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_dmic_enable);
|
||||
|
||||
int rt5640_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
||||
unsigned int filter_mask, unsigned int clk_src)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int asrc2_mask = 0;
|
||||
unsigned int asrc2_value = 0;
|
||||
|
||||
switch (clk_src) {
|
||||
case RT5640_CLK_SEL_SYS:
|
||||
case RT5640_CLK_SEL_ASRC:
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!filter_mask)
|
||||
return -EINVAL;
|
||||
|
||||
if (filter_mask & RT5640_DA_STEREO_FILTER) {
|
||||
asrc2_mask |= RT5640_STO_DAC_M_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5640_STO_DAC_M_MASK)
|
||||
| (clk_src << RT5640_STO_DAC_M_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5640_DA_MONO_L_FILTER) {
|
||||
asrc2_mask |= RT5640_MDA_L_M_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5640_MDA_L_M_MASK)
|
||||
| (clk_src << RT5640_MDA_L_M_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5640_DA_MONO_R_FILTER) {
|
||||
asrc2_mask |= RT5640_MDA_R_M_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5640_MDA_R_M_MASK)
|
||||
| (clk_src << RT5640_MDA_R_M_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5640_AD_STEREO_FILTER) {
|
||||
asrc2_mask |= RT5640_ADC_M_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5640_ADC_M_MASK)
|
||||
| (clk_src << RT5640_ADC_M_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5640_AD_MONO_L_FILTER) {
|
||||
asrc2_mask |= RT5640_MAD_L_M_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5640_MAD_L_M_MASK)
|
||||
| (clk_src << RT5640_MAD_L_M_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5640_AD_MONO_R_FILTER) {
|
||||
asrc2_mask |= RT5640_MAD_R_M_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5640_MAD_R_M_MASK)
|
||||
| (clk_src << RT5640_MAD_R_M_SFT);
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, RT5640_ASRC_2,
|
||||
asrc2_mask, asrc2_value);
|
||||
|
||||
if (snd_soc_read(codec, RT5640_ASRC_2)) {
|
||||
rt5640->asrc_en = true;
|
||||
snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x3);
|
||||
} else {
|
||||
rt5640->asrc_en = false;
|
||||
snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src);
|
||||
|
||||
static int rt5640_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
@ -2175,6 +2277,7 @@ static const struct acpi_device_id rt5640_acpi_match[] = {
|
||||
{ "INT33CA", 0 },
|
||||
{ "10EC5640", 0 },
|
||||
{ "10EC5642", 0 },
|
||||
{ "INTCCFFD", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
|
||||
|
@ -1033,6 +1033,10 @@
|
||||
#define RT5640_DMIC_2_M_NOR (0x0 << 8)
|
||||
#define RT5640_DMIC_2_M_ASYN (0x1 << 8)
|
||||
|
||||
/* ASRC clock source selection (0x84) */
|
||||
#define RT5640_CLK_SEL_SYS (0x0)
|
||||
#define RT5640_CLK_SEL_ASRC (0x1)
|
||||
|
||||
/* ASRC Control 2 (0x84) */
|
||||
#define RT5640_MDA_L_M_MASK (0x1 << 15)
|
||||
#define RT5640_MDA_L_M_SFT 15
|
||||
@ -2079,6 +2083,16 @@ enum {
|
||||
RT5640_DMIC2,
|
||||
};
|
||||
|
||||
/* filter mask */
|
||||
enum {
|
||||
RT5640_DA_STEREO_FILTER = 0x1,
|
||||
RT5640_DA_MONO_L_FILTER = (0x1 << 1),
|
||||
RT5640_DA_MONO_R_FILTER = (0x1 << 2),
|
||||
RT5640_AD_STEREO_FILTER = (0x1 << 3),
|
||||
RT5640_AD_MONO_L_FILTER = (0x1 << 4),
|
||||
RT5640_AD_MONO_R_FILTER = (0x1 << 5),
|
||||
};
|
||||
|
||||
struct rt5640_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
struct rt5640_platform_data pdata;
|
||||
@ -2095,9 +2109,12 @@ struct rt5640_priv {
|
||||
int pll_out;
|
||||
|
||||
bool hp_mute;
|
||||
bool asrc_en;
|
||||
};
|
||||
|
||||
int rt5640_dmic_enable(struct snd_soc_codec *codec,
|
||||
bool dmic1_data_pin, bool dmic2_data_pin);
|
||||
int rt5640_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
||||
unsigned int filter_mask, unsigned int clk_src);
|
||||
|
||||
#endif
|
||||
|
@ -64,7 +64,6 @@ static const struct reg_sequence init_list[] = {
|
||||
{RT5645_PR_BASE + 0x21, 0x4040},
|
||||
{RT5645_PR_BASE + 0x23, 0x0004},
|
||||
};
|
||||
#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
|
||||
|
||||
static const struct reg_sequence rt5650_init_list[] = {
|
||||
{0xf6, 0x0100},
|
||||
@ -405,6 +404,7 @@ struct rt5645_priv {
|
||||
struct delayed_work jack_detect_work, rcclock_work;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
|
||||
struct rt5645_eq_param_s *eq_param;
|
||||
struct timer_list btn_check_timer;
|
||||
|
||||
int codec_type;
|
||||
int sysclk;
|
||||
@ -3066,6 +3066,7 @@ static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec,
|
||||
snd_soc_dapm_force_enable_pin(dapm, "ADC R power");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD1, 0x3, 0x3);
|
||||
snd_soc_update_bits(codec,
|
||||
RT5645_INT_IRQ_ST, 0x8, 0x8);
|
||||
snd_soc_update_bits(codec,
|
||||
@ -3134,7 +3135,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
|
||||
}
|
||||
if (rt5645->pdata.jd_invert)
|
||||
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
|
||||
RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
|
||||
RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR);
|
||||
} else { /* jack out */
|
||||
rt5645->jack_type = 0;
|
||||
|
||||
@ -3155,7 +3156,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
|
||||
snd_soc_dapm_sync(dapm);
|
||||
if (rt5645->pdata.jd_invert)
|
||||
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
|
||||
RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR);
|
||||
RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
|
||||
}
|
||||
|
||||
return rt5645->jack_type;
|
||||
@ -3279,6 +3280,12 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
||||
}
|
||||
if (btn_type == 0)/* button release */
|
||||
report = rt5645->jack_type;
|
||||
else {
|
||||
if (rt5645->pdata.jd_invert) {
|
||||
mod_timer(&rt5645->btn_check_timer,
|
||||
msecs_to_jiffies(100));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
/* jack out */
|
||||
@ -3321,6 +3328,14 @@ static irqreturn_t rt5645_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rt5645_btn_check_callback(unsigned long data)
|
||||
{
|
||||
struct rt5645_priv *rt5645 = (struct rt5645_priv *)data;
|
||||
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rt5645->jack_detect_work, msecs_to_jiffies(5));
|
||||
}
|
||||
|
||||
static int rt5645_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
@ -3510,7 +3525,7 @@ static const struct i2c_device_id rt5645_i2c_id[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static struct acpi_device_id rt5645_acpi_match[] = {
|
||||
static const struct acpi_device_id rt5645_acpi_match[] = {
|
||||
{ "10EC5645", 0 },
|
||||
{ "10EC5650", 0 },
|
||||
{},
|
||||
@ -3787,6 +3802,13 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
|
||||
}
|
||||
}
|
||||
|
||||
if (rt5645->pdata.jd_invert) {
|
||||
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
|
||||
RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
|
||||
setup_timer(&rt5645->btn_check_timer,
|
||||
rt5645_btn_check_callback, (unsigned long)rt5645);
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work);
|
||||
INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work);
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@ -1735,12 +1736,38 @@ static const struct regmap_config rt5651_regmap = {
|
||||
.num_ranges = ARRAY_SIZE(rt5651_ranges),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id rt5651_of_match[] = {
|
||||
{ .compatible = "realtek,rt5651", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rt5651_of_match);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id rt5651_acpi_match[] = {
|
||||
{ "10EC5651", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id rt5651_i2c_id[] = {
|
||||
{ "rt5651", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
|
||||
|
||||
static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
|
||||
{
|
||||
rt5651->pdata.in2_diff = of_property_read_bool(np,
|
||||
"realtek,in2-differential");
|
||||
rt5651->pdata.dmic_en = of_property_read_bool(np,
|
||||
"realtek,dmic-en");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5651_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -1757,6 +1784,8 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
if (pdata)
|
||||
rt5651->pdata = *pdata;
|
||||
else if (i2c->dev.of_node)
|
||||
rt5651_parse_dt(rt5651, i2c->dev.of_node);
|
||||
|
||||
rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
|
||||
if (IS_ERR(rt5651->regmap)) {
|
||||
@ -1806,6 +1835,8 @@ static int rt5651_i2c_remove(struct i2c_client *i2c)
|
||||
static struct i2c_driver rt5651_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rt5651",
|
||||
.acpi_match_table = ACPI_PTR(rt5651_acpi_match),
|
||||
.of_match_table = of_match_ptr(rt5651_of_match),
|
||||
},
|
||||
.probe = rt5651_i2c_probe,
|
||||
.remove = rt5651_i2c_remove,
|
||||
|
@ -1097,8 +1097,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct twl6040_data *priv;
|
||||
struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent);
|
||||
struct platform_device *pdev = container_of(codec->dev,
|
||||
struct platform_device, dev);
|
||||
struct platform_device *pdev = to_platform_device(codec->dev);
|
||||
int ret = 0;
|
||||
|
||||
priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
@ -360,15 +360,13 @@ static int wm5110_hp_ev(struct snd_soc_dapm_widget *w,
|
||||
|
||||
static int wm5110_clear_pga_volume(struct arizona *arizona, int output)
|
||||
{
|
||||
struct reg_sequence clear_pga = {
|
||||
ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80
|
||||
};
|
||||
unsigned int reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4;
|
||||
int ret;
|
||||
|
||||
ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1);
|
||||
ret = regmap_write(arizona->regmap, reg, 0x80);
|
||||
if (ret)
|
||||
dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n",
|
||||
clear_pga.reg, ret);
|
||||
reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -439,18 +437,17 @@ static int wm5110_in_pga_get(struct snd_kcontrol *kcontrol,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* PGA Volume is also used as part of the enable sequence, so
|
||||
* usage of it should be avoided whilst that is running.
|
||||
*/
|
||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
snd_soc_dapm_mutex_lock(dapm);
|
||||
|
||||
ret = snd_soc_get_volsw_range(kcontrol, ucontrol);
|
||||
|
||||
mutex_unlock(&card->dapm_mutex);
|
||||
snd_soc_dapm_mutex_unlock(dapm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -460,18 +457,17 @@ static int wm5110_in_pga_put(struct snd_kcontrol *kcontrol,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* PGA Volume is also used as part of the enable sequence, so
|
||||
* usage of it should be avoided whilst that is running.
|
||||
*/
|
||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
snd_soc_dapm_mutex_lock(dapm);
|
||||
|
||||
ret = snd_soc_put_volsw_range(kcontrol, ucontrol);
|
||||
|
||||
mutex_unlock(&card->dapm_mutex);
|
||||
snd_soc_dapm_mutex_unlock(dapm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2177,10 +2173,23 @@ static int wm5110_open(struct snd_compr_stream *stream)
|
||||
return wm_adsp_compr_open(&priv->core.adsp[n_adsp], stream);
|
||||
}
|
||||
|
||||
static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
|
||||
{
|
||||
struct wm5110_priv *florida = data;
|
||||
int ret;
|
||||
|
||||
ret = wm_adsp_compr_handle_irq(&florida->core.adsp[2]);
|
||||
if (ret == -ENODEV)
|
||||
return IRQ_NONE;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int wm5110_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->core.arizona;
|
||||
int i, ret;
|
||||
|
||||
priv->core.arizona->dapm = dapm;
|
||||
@ -2189,6 +2198,14 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
|
||||
arizona_init_gpio(codec);
|
||||
arizona_init_mono(codec);
|
||||
|
||||
ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
|
||||
"ADSP2 Compressed IRQ", wm5110_adsp2_irq,
|
||||
priv);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < WM5110_NUM_ADSP; ++i) {
|
||||
ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec);
|
||||
if (ret)
|
||||
@ -2209,12 +2226,15 @@ err_adsp2_codec_probe:
|
||||
for (--i; i >= 0; --i)
|
||||
wm_adsp2_codec_remove(&priv->core.adsp[i], codec);
|
||||
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm5110_codec_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->core.arizona;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < WM5110_NUM_ADSP; ++i)
|
||||
@ -2222,6 +2242,8 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
|
||||
|
||||
priv->core.arizona->dapm = NULL;
|
||||
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2273,6 +2295,8 @@ static struct snd_compr_ops wm5110_compr_ops = {
|
||||
.set_params = wm_adsp_compr_set_params,
|
||||
.get_caps = wm_adsp_compr_get_caps,
|
||||
.trigger = wm_adsp_compr_trigger,
|
||||
.pointer = wm_adsp_compr_pointer,
|
||||
.copy = wm_adsp_compr_copy,
|
||||
};
|
||||
|
||||
static struct snd_soc_platform_driver wm5110_compr_platform = {
|
||||
|
@ -147,6 +147,13 @@ static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
|
||||
static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
|
||||
static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
|
||||
static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
|
||||
static const char *wm8960_adc_data_output_sel[] = {
|
||||
"Left Data = Left ADC; Right Data = Right ADC",
|
||||
"Left Data = Left ADC; Right Data = Left ADC",
|
||||
"Left Data = Right ADC; Right Data = Right ADC",
|
||||
"Left Data = Right ADC; Right Data = Left ADC",
|
||||
};
|
||||
static const char *wm8960_dmonomix[] = {"Stereo", "Mono"};
|
||||
|
||||
static const struct soc_enum wm8960_enum[] = {
|
||||
SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
|
||||
@ -155,6 +162,8 @@ static const struct soc_enum wm8960_enum[] = {
|
||||
SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
|
||||
SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
|
||||
SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
|
||||
SOC_ENUM_SINGLE(WM8960_ADDCTL1, 2, 4, wm8960_adc_data_output_sel),
|
||||
SOC_ENUM_SINGLE(WM8960_ADDCTL1, 4, 2, wm8960_dmonomix),
|
||||
};
|
||||
|
||||
static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
|
||||
@ -295,6 +304,9 @@ SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
|
||||
WM8960_BYPASS2, 4, 7, 1, bypass_tlv),
|
||||
SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
|
||||
WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),
|
||||
|
||||
SOC_ENUM("ADC Data Output Select", wm8960_enum[6]),
|
||||
SOC_ENUM("DAC Mono Mix", wm8960_enum[7]),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm8960_lin_boost[] = {
|
||||
@ -401,8 +413,8 @@ static const struct snd_soc_dapm_route audio_paths[] = {
|
||||
{ "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
|
||||
{ "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
|
||||
|
||||
{ "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
|
||||
{ "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */
|
||||
{ "Left Input Mixer", "Boost Switch", "Left Boost Mixer" },
|
||||
{ "Left Input Mixer", "Boost Switch", "LINPUT1" }, /* Really Boost Switch */
|
||||
{ "Left Input Mixer", NULL, "LINPUT2" },
|
||||
{ "Left Input Mixer", NULL, "LINPUT3" },
|
||||
|
||||
@ -410,8 +422,8 @@ static const struct snd_soc_dapm_route audio_paths[] = {
|
||||
{ "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
|
||||
{ "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
|
||||
|
||||
{ "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
|
||||
{ "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */
|
||||
{ "Right Input Mixer", "Boost Switch", "Right Boost Mixer" },
|
||||
{ "Right Input Mixer", "Boost Switch", "RINPUT1" }, /* Really Boost Switch */
|
||||
{ "Right Input Mixer", NULL, "RINPUT2" },
|
||||
{ "Right Input Mixer", NULL, "RINPUT3" },
|
||||
|
||||
@ -419,11 +431,11 @@ static const struct snd_soc_dapm_route audio_paths[] = {
|
||||
{ "Right ADC", NULL, "Right Input Mixer" },
|
||||
|
||||
{ "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
|
||||
{ "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
|
||||
{ "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer" },
|
||||
{ "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
|
||||
|
||||
{ "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
|
||||
{ "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
|
||||
{ "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" },
|
||||
{ "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
|
||||
|
||||
{ "LOUT1 PGA", NULL, "Left Output Mixer" },
|
||||
|
@ -279,6 +279,11 @@ struct wm_adsp_compr_buf {
|
||||
|
||||
struct wm_adsp_buffer_region *regions;
|
||||
u32 host_buf_ptr;
|
||||
|
||||
u32 error;
|
||||
u32 irq_count;
|
||||
int read_index;
|
||||
int avail;
|
||||
};
|
||||
|
||||
struct wm_adsp_compr {
|
||||
@ -287,6 +292,9 @@ struct wm_adsp_compr {
|
||||
|
||||
struct snd_compr_stream *stream;
|
||||
struct snd_compressed_buffer size;
|
||||
|
||||
u32 *raw_buf;
|
||||
unsigned int copied_total;
|
||||
};
|
||||
|
||||
#define WM_ADSP_DATA_WORD_SIZE 3
|
||||
@ -2378,6 +2386,7 @@ int wm_adsp_compr_free(struct snd_compr_stream *stream)
|
||||
|
||||
dsp->compr = NULL;
|
||||
|
||||
kfree(compr->raw_buf);
|
||||
kfree(compr);
|
||||
|
||||
mutex_unlock(&dsp->pwr_lock);
|
||||
@ -2436,10 +2445,16 @@ static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
|
||||
{
|
||||
return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
|
||||
}
|
||||
|
||||
int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
|
||||
struct snd_compr_params *params)
|
||||
{
|
||||
struct wm_adsp_compr *compr = stream->runtime->private_data;
|
||||
unsigned int size;
|
||||
int ret;
|
||||
|
||||
ret = wm_adsp_compr_check_params(stream, params);
|
||||
@ -2451,6 +2466,11 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
|
||||
adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n",
|
||||
compr->size.fragment_size, compr->size.fragments);
|
||||
|
||||
size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
|
||||
compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
|
||||
if (!compr->raw_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
|
||||
@ -2622,6 +2642,8 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->dsp = dsp;
|
||||
buf->read_index = -1;
|
||||
buf->irq_count = 0xFFFFFFFF;
|
||||
|
||||
ret = wm_adsp_buffer_locate(buf);
|
||||
if (ret < 0) {
|
||||
@ -2705,6 +2727,16 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Trigger the IRQ at one fragment of data */
|
||||
ret = wm_adsp_buffer_write(compr->buf,
|
||||
HOST_BUFFER_FIELD(high_water_mark),
|
||||
wm_adsp_compr_frag_words(compr));
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp, "Failed to set high water mark: %d\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
break;
|
||||
@ -2719,4 +2751,298 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
|
||||
|
||||
static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
|
||||
|
||||
return buf->regions[last_region].cumulative_size;
|
||||
}
|
||||
|
||||
static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
u32 next_read_index, next_write_index;
|
||||
int write_index, read_index, avail;
|
||||
int ret;
|
||||
|
||||
/* Only sync read index if we haven't already read a valid index */
|
||||
if (buf->read_index < 0) {
|
||||
ret = wm_adsp_buffer_read(buf,
|
||||
HOST_BUFFER_FIELD(next_read_index),
|
||||
&next_read_index);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
read_index = sign_extend32(next_read_index, 23);
|
||||
|
||||
if (read_index < 0) {
|
||||
adsp_dbg(buf->dsp, "Avail check on unstarted stream\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf->read_index = read_index;
|
||||
}
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
|
||||
&next_write_index);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
write_index = sign_extend32(next_write_index, 23);
|
||||
|
||||
avail = write_index - buf->read_index;
|
||||
if (avail < 0)
|
||||
avail += wm_adsp_buffer_size(buf);
|
||||
|
||||
adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
|
||||
buf->read_index, write_index, avail);
|
||||
|
||||
buf->avail = avail;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
|
||||
{
|
||||
struct wm_adsp_compr_buf *buf = dsp->buffer;
|
||||
struct wm_adsp_compr *compr = dsp->compr;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
if (!buf) {
|
||||
adsp_err(dsp, "Spurious buffer IRQ\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
adsp_dbg(dsp, "Handling buffer IRQ\n");
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp, "Failed to check buffer error: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
if (buf->error != 0) {
|
||||
adsp_err(dsp, "Buffer error occurred: %d\n", buf->error);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
|
||||
&buf->irq_count);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp, "Failed to get irq_count: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wm_adsp_buffer_update_avail(buf);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp, "Error reading avail: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (compr->stream)
|
||||
snd_compr_fragment_elapsed(compr->stream);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dsp->pwr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
|
||||
|
||||
static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
if (buf->irq_count & 0x01)
|
||||
return 0;
|
||||
|
||||
adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n",
|
||||
buf->irq_count);
|
||||
|
||||
buf->irq_count |= 0x01;
|
||||
|
||||
return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
|
||||
buf->irq_count);
|
||||
}
|
||||
|
||||
int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
|
||||
struct snd_compr_tstamp *tstamp)
|
||||
{
|
||||
struct wm_adsp_compr *compr = stream->runtime->private_data;
|
||||
struct wm_adsp_compr_buf *buf = compr->buf;
|
||||
struct wm_adsp *dsp = compr->dsp;
|
||||
int ret = 0;
|
||||
|
||||
adsp_dbg(dsp, "Pointer request\n");
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
if (!compr->buf) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (compr->buf->error) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (buf->avail < wm_adsp_compr_frag_words(compr)) {
|
||||
ret = wm_adsp_buffer_update_avail(buf);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp, "Error reading avail: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we really have less than 1 fragment available tell the
|
||||
* DSP to inform us once a whole fragment is available.
|
||||
*/
|
||||
if (buf->avail < wm_adsp_compr_frag_words(compr)) {
|
||||
ret = wm_adsp_buffer_reenable_irq(buf);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp,
|
||||
"Failed to re-enable buffer IRQ: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tstamp->copied_total = compr->copied_total;
|
||||
tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
|
||||
|
||||
out:
|
||||
mutex_unlock(&dsp->pwr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
|
||||
|
||||
static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
|
||||
{
|
||||
struct wm_adsp_compr_buf *buf = compr->buf;
|
||||
u8 *pack_in = (u8 *)compr->raw_buf;
|
||||
u8 *pack_out = (u8 *)compr->raw_buf;
|
||||
unsigned int adsp_addr;
|
||||
int mem_type, nwords, max_read;
|
||||
int i, j, ret;
|
||||
|
||||
/* Calculate read parameters */
|
||||
for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
|
||||
if (buf->read_index < buf->regions[i].cumulative_size)
|
||||
break;
|
||||
|
||||
if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
|
||||
return -EINVAL;
|
||||
|
||||
mem_type = buf->regions[i].mem_type;
|
||||
adsp_addr = buf->regions[i].base_addr +
|
||||
(buf->read_index - buf->regions[i].offset);
|
||||
|
||||
max_read = wm_adsp_compr_frag_words(compr);
|
||||
nwords = buf->regions[i].cumulative_size - buf->read_index;
|
||||
|
||||
if (nwords > target)
|
||||
nwords = target;
|
||||
if (nwords > buf->avail)
|
||||
nwords = buf->avail;
|
||||
if (nwords > max_read)
|
||||
nwords = max_read;
|
||||
if (!nwords)
|
||||
return 0;
|
||||
|
||||
/* Read data from DSP */
|
||||
ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
|
||||
nwords, compr->raw_buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Remove the padding bytes from the data read from the DSP */
|
||||
for (i = 0; i < nwords; i++) {
|
||||
for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++)
|
||||
*pack_out++ = *pack_in++;
|
||||
|
||||
pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE;
|
||||
}
|
||||
|
||||
/* update read index to account for words read */
|
||||
buf->read_index += nwords;
|
||||
if (buf->read_index == wm_adsp_buffer_size(buf))
|
||||
buf->read_index = 0;
|
||||
|
||||
ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
|
||||
buf->read_index);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* update avail to account for words read */
|
||||
buf->avail -= nwords;
|
||||
|
||||
return nwords;
|
||||
}
|
||||
|
||||
static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
|
||||
char __user *buf, size_t count)
|
||||
{
|
||||
struct wm_adsp *dsp = compr->dsp;
|
||||
int ntotal = 0;
|
||||
int nwords, nbytes;
|
||||
|
||||
adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
|
||||
|
||||
if (!compr->buf)
|
||||
return -ENXIO;
|
||||
|
||||
if (compr->buf->error)
|
||||
return -EIO;
|
||||
|
||||
count /= WM_ADSP_DATA_WORD_SIZE;
|
||||
|
||||
do {
|
||||
nwords = wm_adsp_buffer_capture_block(compr, count);
|
||||
if (nwords < 0) {
|
||||
adsp_err(dsp, "Failed to capture block: %d\n", nwords);
|
||||
return nwords;
|
||||
}
|
||||
|
||||
nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
|
||||
|
||||
adsp_dbg(dsp, "Read %d bytes\n", nbytes);
|
||||
|
||||
if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
|
||||
adsp_err(dsp, "Failed to copy data to user: %d, %d\n",
|
||||
ntotal, nbytes);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
count -= nwords;
|
||||
ntotal += nbytes;
|
||||
} while (nwords > 0 && count > 0);
|
||||
|
||||
compr->copied_total += ntotal;
|
||||
|
||||
return ntotal;
|
||||
}
|
||||
|
||||
int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct wm_adsp_compr *compr = stream->runtime->private_data;
|
||||
struct wm_adsp *dsp = compr->dsp;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
if (stream->direction == SND_COMPRESS_CAPTURE)
|
||||
ret = wm_adsp_compr_read(compr, buf, count);
|
||||
else
|
||||
ret = -ENOTSUPP;
|
||||
|
||||
mutex_unlock(&dsp->pwr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -112,5 +112,10 @@ extern int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
|
||||
extern int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
|
||||
struct snd_compr_caps *caps);
|
||||
extern int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd);
|
||||
extern int wm_adsp_compr_handle_irq(struct wm_adsp *dsp);
|
||||
extern int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
|
||||
struct snd_compr_tstamp *tstamp);
|
||||
extern int wm_adsp_compr_copy(struct snd_compr_stream *stream,
|
||||
char __user *buf, size_t count);
|
||||
|
||||
#endif
|
||||
|
@ -500,6 +500,10 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
|
||||
u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2);
|
||||
u32 idx;
|
||||
|
||||
if (dev->capability & DWC_I2S_RECORD &&
|
||||
dev->quirks & DW_I2S_QUIRK_COMP_PARAM1)
|
||||
comp1 = comp1 & ~BIT(5);
|
||||
|
||||
if (COMP1_TX_ENABLED(comp1)) {
|
||||
dev_dbg(dev->dev, " designware: play supported\n");
|
||||
idx = COMP1_TX_WORDSIZE_0(comp1);
|
||||
|
@ -996,6 +996,9 @@ static int fsl_asrc_suspend(struct device *dev)
|
||||
{
|
||||
struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
|
||||
|
||||
regmap_read(asrc_priv->regmap, REG_ASRCFG,
|
||||
&asrc_priv->regcache_cfg);
|
||||
|
||||
regcache_cache_only(asrc_priv->regmap, true);
|
||||
regcache_mark_dirty(asrc_priv->regmap);
|
||||
|
||||
@ -1016,6 +1019,10 @@ static int fsl_asrc_resume(struct device *dev)
|
||||
regcache_cache_only(asrc_priv->regmap, false);
|
||||
regcache_sync(asrc_priv->regmap);
|
||||
|
||||
regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
|
||||
ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
|
||||
ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
|
||||
|
||||
/* Restart enabled pairs */
|
||||
regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
|
||||
ASRCTR_ASRCEi_ALL_MASK, asrctr);
|
||||
|
@ -132,10 +132,13 @@
|
||||
#define ASRCFG_INIRQi (1 << ASRCFG_INIRQi_SHIFT(i))
|
||||
#define ASRCFG_NDPRi_SHIFT(i) (18 + i)
|
||||
#define ASRCFG_NDPRi_MASK(i) (1 << ASRCFG_NDPRi_SHIFT(i))
|
||||
#define ASRCFG_NDPRi_ALL_SHIFT 18
|
||||
#define ASRCFG_NDPRi_ALL_MASK (7 << ASRCFG_NDPRi_ALL_SHIFT)
|
||||
#define ASRCFG_NDPRi (1 << ASRCFG_NDPRi_SHIFT(i))
|
||||
#define ASRCFG_POSTMODi_SHIFT(i) (8 + (i << 2))
|
||||
#define ASRCFG_POSTMODi_WIDTH 2
|
||||
#define ASRCFG_POSTMODi_MASK(i) (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i))
|
||||
#define ASRCFG_POSTMODi_ALL_MASK (ASRCFG_POSTMODi_MASK(0) | ASRCFG_POSTMODi_MASK(1) | ASRCFG_POSTMODi_MASK(2))
|
||||
#define ASRCFG_POSTMOD(i, v) ((v) << ASRCFG_POSTMODi_SHIFT(i))
|
||||
#define ASRCFG_POSTMODi_UP(i) (0 << ASRCFG_POSTMODi_SHIFT(i))
|
||||
#define ASRCFG_POSTMODi_DCON(i) (1 << ASRCFG_POSTMODi_SHIFT(i))
|
||||
@ -143,6 +146,7 @@
|
||||
#define ASRCFG_PREMODi_SHIFT(i) (6 + (i << 2))
|
||||
#define ASRCFG_PREMODi_WIDTH 2
|
||||
#define ASRCFG_PREMODi_MASK(i) (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i))
|
||||
#define ASRCFG_PREMODi_ALL_MASK (ASRCFG_PREMODi_MASK(0) | ASRCFG_PREMODi_MASK(1) | ASRCFG_PREMODi_MASK(2))
|
||||
#define ASRCFG_PREMOD(i, v) ((v) << ASRCFG_PREMODi_SHIFT(i))
|
||||
#define ASRCFG_PREMODi_UP(i) (0 << ASRCFG_PREMODi_SHIFT(i))
|
||||
#define ASRCFG_PREMODi_DCON(i) (1 << ASRCFG_PREMODi_SHIFT(i))
|
||||
@ -434,6 +438,7 @@ struct fsl_asrc_pair {
|
||||
* @channel_avail: non-occupied channel numbers
|
||||
* @asrc_rate: default sample rate for ASoC Back-Ends
|
||||
* @asrc_width: default sample width for ASoC Back-Ends
|
||||
* @regcache_cfg: store register value of REG_ASRCFG
|
||||
*/
|
||||
struct fsl_asrc {
|
||||
struct snd_dmaengine_dai_dma_data dma_params_rx;
|
||||
@ -453,6 +458,8 @@ struct fsl_asrc {
|
||||
|
||||
int asrc_rate;
|
||||
int asrc_width;
|
||||
|
||||
u32 regcache_cfg;
|
||||
};
|
||||
|
||||
extern struct snd_soc_platform_driver fsl_asrc_platform;
|
||||
|
@ -146,6 +146,7 @@ static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CCSR_SSI_SRX1:
|
||||
case CCSR_SSI_SISR:
|
||||
case CCSR_SSI_SFCSR:
|
||||
case CCSR_SSI_SACNT:
|
||||
case CCSR_SSI_SACADD:
|
||||
case CCSR_SSI_SACDAT:
|
||||
case CCSR_SSI_SATAG:
|
||||
@ -156,6 +157,21 @@ static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
|
||||
}
|
||||
}
|
||||
|
||||
static bool fsl_ssi_precious_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case CCSR_SSI_SRX0:
|
||||
case CCSR_SSI_SRX1:
|
||||
case CCSR_SSI_SISR:
|
||||
case CCSR_SSI_SACADD:
|
||||
case CCSR_SSI_SACDAT:
|
||||
case CCSR_SSI_SATAG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool fsl_ssi_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
@ -178,6 +194,7 @@ static const struct regmap_config fsl_ssi_regconfig = {
|
||||
.num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults),
|
||||
.readable_reg = fsl_ssi_readable_reg,
|
||||
.volatile_reg = fsl_ssi_volatile_reg,
|
||||
.precious_reg = fsl_ssi_precious_reg,
|
||||
.writeable_reg = fsl_ssi_writeable_reg,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
@ -239,8 +256,9 @@ struct fsl_ssi_private {
|
||||
unsigned int baudclk_streams;
|
||||
unsigned int bitclk_freq;
|
||||
|
||||
/*regcache for SFCSR*/
|
||||
/* regcache for volatile regs */
|
||||
u32 regcache_sfcsr;
|
||||
u32 regcache_sacnt;
|
||||
|
||||
/* DMA params */
|
||||
struct snd_dmaengine_dai_dma_data dma_params_tx;
|
||||
@ -1587,6 +1605,8 @@ static int fsl_ssi_suspend(struct device *dev)
|
||||
|
||||
regmap_read(regs, CCSR_SSI_SFCSR,
|
||||
&ssi_private->regcache_sfcsr);
|
||||
regmap_read(regs, CCSR_SSI_SACNT,
|
||||
&ssi_private->regcache_sacnt);
|
||||
|
||||
regcache_cache_only(regs, true);
|
||||
regcache_mark_dirty(regs);
|
||||
@ -1605,6 +1625,8 @@ static int fsl_ssi_resume(struct device *dev)
|
||||
CCSR_SSI_SFCSR_RFWM1_MASK | CCSR_SSI_SFCSR_TFWM1_MASK |
|
||||
CCSR_SSI_SFCSR_RFWM0_MASK | CCSR_SSI_SFCSR_TFWM0_MASK,
|
||||
ssi_private->regcache_sfcsr);
|
||||
regmap_write(regs, CCSR_SSI_SACNT,
|
||||
ssi_private->regcache_sacnt);
|
||||
|
||||
return regcache_sync(regs);
|
||||
}
|
||||
|
@ -189,8 +189,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = pdev->dev.parent;
|
||||
/* ssi_pdev is the platform device for the SSI node that probed us */
|
||||
struct platform_device *ssi_pdev =
|
||||
container_of(dev, struct platform_device, dev);
|
||||
struct platform_device *ssi_pdev = to_platform_device(dev);
|
||||
struct device_node *np = ssi_pdev->dev.of_node;
|
||||
struct device_node *codec_np = NULL;
|
||||
struct mpc8610_hpcd_data *machine_data;
|
||||
|
@ -199,8 +199,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = pdev->dev.parent;
|
||||
/* ssi_pdev is the platform device for the SSI node that probed us */
|
||||
struct platform_device *ssi_pdev =
|
||||
container_of(dev, struct platform_device, dev);
|
||||
struct platform_device *ssi_pdev = to_platform_device(dev);
|
||||
struct device_node *np = ssi_pdev->dev.of_node;
|
||||
struct device_node *codec_np = NULL;
|
||||
struct machine_data *mdata;
|
||||
|
@ -203,8 +203,7 @@ static int p1022_rdk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = pdev->dev.parent;
|
||||
/* ssi_pdev is the platform device for the SSI node that probed us */
|
||||
struct platform_device *ssi_pdev =
|
||||
container_of(dev, struct platform_device, dev);
|
||||
struct platform_device *ssi_pdev = to_platform_device(dev);
|
||||
struct device_node *np = ssi_pdev->dev.of_node;
|
||||
struct device_node *codec_np = NULL;
|
||||
struct machine_data *mdata;
|
||||
|
@ -103,6 +103,18 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH
|
||||
Say Y if you have such a device
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_INTEL_BYTCR_RT5651_MACH
|
||||
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec"
|
||||
depends on X86 && I2C
|
||||
select SND_SOC_RT5651
|
||||
select SND_SST_MFLD_PLATFORM
|
||||
select SND_SST_IPC_ACPI
|
||||
help
|
||||
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
|
||||
platforms with RT5651 audio codec.
|
||||
Say Y if you have such a device
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
|
||||
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec"
|
||||
depends on X86_INTEL_LPSS && I2C
|
||||
|
@ -247,16 +247,23 @@ static int sst_acpi_probe(struct platform_device *pdev)
|
||||
|
||||
dev_dbg(dev, "ACPI device id: %x\n", dev_id);
|
||||
|
||||
plat_dev = platform_device_register_data(dev, pdata->platform, -1, NULL, 0);
|
||||
plat_dev = platform_device_register_data(dev, pdata->platform, -1,
|
||||
NULL, 0);
|
||||
if (IS_ERR(plat_dev)) {
|
||||
dev_err(dev, "Failed to create machine device: %s\n", pdata->platform);
|
||||
dev_err(dev, "Failed to create machine device: %s\n",
|
||||
pdata->platform);
|
||||
return PTR_ERR(plat_dev);
|
||||
}
|
||||
|
||||
/* Create platform device for sst machine driver */
|
||||
mdev = platform_device_register_data(dev, mach->drv_name, -1, NULL, 0);
|
||||
/*
|
||||
* Create platform device for sst machine driver,
|
||||
* pass machine info as pdata
|
||||
*/
|
||||
mdev = platform_device_register_data(dev, mach->drv_name, -1,
|
||||
(const void *)mach, sizeof(*mach));
|
||||
if (IS_ERR(mdev)) {
|
||||
dev_err(dev, "Failed to create machine device: %s\n", mach->drv_name);
|
||||
dev_err(dev, "Failed to create machine device: %s\n",
|
||||
mach->drv_name);
|
||||
return PTR_ERR(mdev);
|
||||
}
|
||||
|
||||
@ -316,6 +323,12 @@ static int sst_acpi_remove(struct platform_device *pdev)
|
||||
static struct sst_acpi_mach sst_acpi_bytcr[] = {
|
||||
{"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
|
||||
&byt_rvp_platform_data },
|
||||
{"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
|
||||
&byt_rvp_platform_data },
|
||||
{"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
|
||||
&byt_rvp_platform_data },
|
||||
{"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL,
|
||||
&byt_rvp_platform_data },
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
|
||||
snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
|
||||
snd-soc-sst-broadwell-objs := broadwell.o
|
||||
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
|
||||
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
|
||||
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
|
||||
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
|
||||
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
|
||||
@ -15,6 +16,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <sound/jack.h>
|
||||
#include "../../codecs/rt5640.h"
|
||||
#include "../atom/sst-atom-controls.h"
|
||||
#include "../common/sst-acpi.h"
|
||||
|
||||
static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone", NULL),
|
||||
@ -140,6 +141,14 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
||||
.driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP |
|
||||
BYT_RT5640_DMIC_EN),
|
||||
},
|
||||
{
|
||||
.callback = byt_rt5640_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
|
||||
},
|
||||
.driver_data = (unsigned long *)BYT_RT5640_IN1_MAP,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@ -153,6 +162,11 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
|
||||
|
||||
card->dapm.idle_bias_off = true;
|
||||
|
||||
rt5640_sel_asrc_clk_src(codec,
|
||||
RT5640_DA_STEREO_FILTER |
|
||||
RT5640_AD_STEREO_FILTER,
|
||||
RT5640_CLK_SEL_ASRC);
|
||||
|
||||
ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
|
||||
ARRAY_SIZE(byt_rt5640_controls));
|
||||
if (ret) {
|
||||
@ -296,7 +310,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.no_pcm = 1,
|
||||
.codec_dai_name = "rt5640-aif1",
|
||||
.codec_name = "i2c-10EC5640:00",
|
||||
.codec_name = "i2c-10EC5640:00", /* overwritten with HID */
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBS_CFS,
|
||||
.be_hw_params_fixup = byt_rt5640_codec_fixup,
|
||||
@ -321,12 +335,21 @@ static struct snd_soc_card byt_rt5640_card = {
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static char byt_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
|
||||
|
||||
static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret_val = 0;
|
||||
struct sst_acpi_mach *mach;
|
||||
|
||||
/* register the soc card */
|
||||
byt_rt5640_card.dev = &pdev->dev;
|
||||
mach = byt_rt5640_card.dev->platform_data;
|
||||
|
||||
/* fixup codec name based on HID */
|
||||
snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
|
||||
"%s%s%s", "i2c-", mach->id, ":00");
|
||||
byt_rt5640_dais[MERR_DPCM_COMPR+1].codec_name = byt_rt5640_codec_name;
|
||||
|
||||
ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
|
||||
|
||||
|
332
sound/soc/intel/boards/bytcr_rt5651.c
Normal file
332
sound/soc/intel/boards/bytcr_rt5651.c
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
|
||||
* (derived from bytcr_rt5640.c)
|
||||
*
|
||||
* Copyright (C) 2015 Intel Corp
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/jack.h>
|
||||
#include "../../codecs/rt5651.h"
|
||||
#include "../atom/sst-atom-controls.h"
|
||||
|
||||
static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
SND_SOC_DAPM_MIC("Internal Mic", NULL),
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
|
||||
{"AIF1 Playback", NULL, "ssp2 Tx"},
|
||||
{"ssp2 Tx", NULL, "codec_out0"},
|
||||
{"ssp2 Tx", NULL, "codec_out1"},
|
||||
{"codec_in0", NULL, "ssp2 Rx"},
|
||||
{"codec_in1", NULL, "ssp2 Rx"},
|
||||
{"ssp2 Rx", NULL, "AIF1 Capture"},
|
||||
|
||||
{"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
|
||||
{"IN2P", NULL, "Headset Mic"},
|
||||
{"Headphone", NULL, "HPOL"},
|
||||
{"Headphone", NULL, "HPOR"},
|
||||
{"Speaker", NULL, "LOUTL"},
|
||||
{"Speaker", NULL, "LOUTR"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic1_map[] = {
|
||||
{"DMIC1", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic2_map[] = {
|
||||
{"DMIC2", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
|
||||
{"Internal Mic", NULL, "micbias1"},
|
||||
{"IN1P", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
enum {
|
||||
BYT_RT5651_DMIC1_MAP,
|
||||
BYT_RT5651_DMIC2_MAP,
|
||||
BYT_RT5651_IN1_MAP,
|
||||
};
|
||||
|
||||
#define BYT_RT5651_MAP(quirk) ((quirk) & 0xff)
|
||||
#define BYT_RT5651_DMIC_EN BIT(16)
|
||||
|
||||
static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC1_MAP |
|
||||
BYT_RT5651_DMIC_EN;
|
||||
|
||||
static const struct snd_kcontrol_new byt_rt5651_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Headphone"),
|
||||
SOC_DAPM_PIN_SWITCH("Headset Mic"),
|
||||
SOC_DAPM_PIN_SWITCH("Internal Mic"),
|
||||
SOC_DAPM_PIN_SWITCH("Speaker"),
|
||||
};
|
||||
|
||||
static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret;
|
||||
|
||||
snd_soc_dai_set_bclk_ratio(codec_dai, 50);
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
|
||||
params_rate(params) * 512,
|
||||
SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set codec clock %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5651_PLL1_S_BCLK1,
|
||||
params_rate(params) * 50,
|
||||
params_rate(params) * 512);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id byt_rt5651_quirk_table[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_card *card = runtime->card;
|
||||
const struct snd_soc_dapm_route *custom_map;
|
||||
int num_routes;
|
||||
|
||||
card->dapm.idle_bias_off = true;
|
||||
|
||||
dmi_check_system(byt_rt5651_quirk_table);
|
||||
switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
|
||||
case BYT_RT5651_IN1_MAP:
|
||||
custom_map = byt_rt5651_intmic_in1_map;
|
||||
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
|
||||
break;
|
||||
case BYT_RT5651_DMIC2_MAP:
|
||||
custom_map = byt_rt5651_intmic_dmic2_map;
|
||||
num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic2_map);
|
||||
break;
|
||||
default:
|
||||
custom_map = byt_rt5651_intmic_dmic1_map;
|
||||
num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic1_map);
|
||||
}
|
||||
|
||||
ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
|
||||
ARRAY_SIZE(byt_rt5651_controls));
|
||||
if (ret) {
|
||||
dev_err(card->dev, "unable to add card controls\n");
|
||||
return ret;
|
||||
}
|
||||
snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
|
||||
snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_soc_pcm_stream byt_rt5651_dai_params = {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_LE,
|
||||
.rate_min = 48000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
};
|
||||
|
||||
static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_interval *rate = hw_param_interval(params,
|
||||
SNDRV_PCM_HW_PARAM_RATE);
|
||||
struct snd_interval *channels = hw_param_interval(params,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
int ret;
|
||||
|
||||
/* The DSP will covert the FE rate to 48k, stereo, 24bits */
|
||||
rate->min = rate->max = 48000;
|
||||
channels->min = channels->max = 2;
|
||||
|
||||
/* set SSP2 to 24-bit */
|
||||
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
|
||||
|
||||
/*
|
||||
* Default mode for SSP configuration is TDM 4 slot, override config
|
||||
* with explicit setting to I2S 2ch 24-bit. The word length is set with
|
||||
* dai_set_tdm_slot() since there is no other API exposed
|
||||
*/
|
||||
ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
|
||||
SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_IF |
|
||||
SND_SOC_DAIFMT_CBS_CFS
|
||||
);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int rates_48000[] = {
|
||||
48000,
|
||||
};
|
||||
|
||||
static struct snd_pcm_hw_constraint_list constraints_48000 = {
|
||||
.count = ARRAY_SIZE(rates_48000),
|
||||
.list = rates_48000,
|
||||
};
|
||||
|
||||
static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_48000);
|
||||
}
|
||||
|
||||
static struct snd_soc_ops byt_rt5651_aif1_ops = {
|
||||
.startup = byt_rt5651_aif1_startup,
|
||||
};
|
||||
|
||||
static struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
|
||||
.hw_params = byt_rt5651_aif1_hw_params,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link byt_rt5651_dais[] = {
|
||||
[MERR_DPCM_AUDIO] = {
|
||||
.name = "Audio Port",
|
||||
.stream_name = "Audio",
|
||||
.cpu_dai_name = "media-cpu-dai",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &byt_rt5651_aif1_ops,
|
||||
},
|
||||
[MERR_DPCM_DEEP_BUFFER] = {
|
||||
.name = "Deep-Buffer Audio Port",
|
||||
.stream_name = "Deep-Buffer Audio",
|
||||
.cpu_dai_name = "deepbuffer-cpu-dai",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.ops = &byt_rt5651_aif1_ops,
|
||||
},
|
||||
[MERR_DPCM_COMPR] = {
|
||||
.name = "Compressed Port",
|
||||
.stream_name = "Compress",
|
||||
.cpu_dai_name = "compress-cpu-dai",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
},
|
||||
/* CODEC<->CODEC link */
|
||||
/* back ends */
|
||||
{
|
||||
.name = "SSP2-Codec",
|
||||
.be_id = 1,
|
||||
.cpu_dai_name = "ssp2-port",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.no_pcm = 1,
|
||||
.codec_dai_name = "rt5651-aif1",
|
||||
.codec_name = "i2c-10EC5651:00",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBS_CFS,
|
||||
.be_hw_params_fixup = byt_rt5651_codec_fixup,
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.init = byt_rt5651_init,
|
||||
.ops = &byt_rt5651_be_ssp2_ops,
|
||||
},
|
||||
};
|
||||
|
||||
/* SoC card */
|
||||
static struct snd_soc_card byt_rt5651_card = {
|
||||
.name = "bytcr-rt5651",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = byt_rt5651_dais,
|
||||
.num_links = ARRAY_SIZE(byt_rt5651_dais),
|
||||
.dapm_widgets = byt_rt5651_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
|
||||
.dapm_routes = byt_rt5651_audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret_val = 0;
|
||||
|
||||
/* register the soc card */
|
||||
byt_rt5651_card.dev = &pdev->dev;
|
||||
|
||||
ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
|
||||
|
||||
if (ret_val) {
|
||||
dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
|
||||
ret_val);
|
||||
return ret_val;
|
||||
}
|
||||
platform_set_drvdata(pdev, &byt_rt5651_card);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static struct platform_driver snd_byt_rt5651_mc_driver = {
|
||||
.driver = {
|
||||
.name = "bytcr_rt5651",
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = snd_byt_rt5651_mc_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(snd_byt_rt5651_mc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
|
||||
MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:bytcr_rt5651");
|
@ -1,5 +1,10 @@
|
||||
snd-soc-sst-dsp-objs := sst-dsp.o
|
||||
ifneq ($(CONFIG_SND_SST_IPC_ACPI),)
|
||||
snd-soc-sst-acpi-objs := sst-match-acpi.o
|
||||
else
|
||||
snd-soc-sst-acpi-objs := sst-acpi.o sst-match-acpi.o
|
||||
endif
|
||||
|
||||
snd-soc-sst-ipc-objs := sst-ipc.o
|
||||
|
||||
snd-soc-sst-dsp-$(CONFIG_DW_DMAC_CORE) += sst-firmware.o
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <sound/soc.h>
|
||||
#include "skl.h"
|
||||
#include "skl-topology.h"
|
||||
#include "skl-sst-dsp.h"
|
||||
#include "skl-sst-ipc.h"
|
||||
|
||||
#define HDA_MONO 1
|
||||
#define HDA_STEREO 2
|
||||
@ -36,6 +38,7 @@ static struct snd_pcm_hardware azx_pcm_hw = {
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_RESUME |
|
||||
SNDRV_PCM_INFO_SYNC_START |
|
||||
SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
|
||||
SNDRV_PCM_INFO_HAS_LINK_ATIME |
|
||||
@ -272,6 +275,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
|
||||
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
|
||||
struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
|
||||
struct skl_dma_params *dma_params = NULL;
|
||||
struct skl *skl = ebus_to_skl(ebus);
|
||||
|
||||
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
|
||||
|
||||
@ -285,6 +289,16 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
|
||||
snd_soc_dai_set_dma_data(dai, substream, NULL);
|
||||
skl_set_suspend_active(substream, dai, false);
|
||||
|
||||
/*
|
||||
* check if close is for "Reference Pin" and set back the
|
||||
* CGCTL.MISCBDCGE if disabled by driver
|
||||
*/
|
||||
if (!strncmp(dai->name, "Reference Pin", 13) &&
|
||||
skl->skl_sst->miscbdcg_disabled) {
|
||||
skl->skl_sst->enable_miscbdcge(dai->dev, true);
|
||||
skl->skl_sst->miscbdcg_disabled = false;
|
||||
}
|
||||
|
||||
kfree(dma_params);
|
||||
}
|
||||
|
||||
@ -380,6 +394,15 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
skl_pcm_prepare(substream, dai);
|
||||
/*
|
||||
* enable DMA Resume enable bit for the stream, set the dpib
|
||||
* & lpib position to resune before starting the DMA
|
||||
*/
|
||||
snd_hdac_ext_stream_drsm_enable(ebus, true,
|
||||
hdac_stream(stream)->index);
|
||||
snd_hdac_ext_stream_set_dpibr(ebus, stream, stream->dpib);
|
||||
snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
|
||||
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
/*
|
||||
@ -408,8 +431,17 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
return ret;
|
||||
|
||||
ret = skl_decoupled_trigger(substream, cmd);
|
||||
if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
|
||||
if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) {
|
||||
/* save the dpib and lpib positions */
|
||||
stream->dpib = readl(ebus->bus.remap_addr +
|
||||
AZX_REG_VS_SDXDPIB_XBASE +
|
||||
(AZX_REG_VS_SDXDPIB_XINTERVAL *
|
||||
hdac_stream(stream)->index));
|
||||
|
||||
stream->lpib = snd_hdac_stream_get_pos_lpib(
|
||||
hdac_stream(stream));
|
||||
snd_hdac_ext_stream_decouple(ebus, stream, false);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -465,11 +497,6 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct hdac_ext_link *link;
|
||||
|
||||
if (link_dev->link_prepared) {
|
||||
dev_dbg(dai->dev, "already stream is prepared - returning\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma_params = (struct skl_dma_params *)
|
||||
snd_soc_dai_get_dma_data(codec_dai, substream);
|
||||
if (dma_params)
|
||||
@ -477,14 +504,15 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
|
||||
dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
|
||||
hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);
|
||||
|
||||
snd_hdac_ext_link_stream_reset(link_dev);
|
||||
|
||||
snd_hdac_ext_link_stream_setup(link_dev, format_val);
|
||||
|
||||
link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
|
||||
if (!link)
|
||||
return -EINVAL;
|
||||
|
||||
snd_hdac_ext_bus_link_power_up(link);
|
||||
snd_hdac_ext_link_stream_reset(link_dev);
|
||||
|
||||
snd_hdac_ext_link_stream_setup(link_dev, format_val);
|
||||
|
||||
snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
|
||||
link_dev->link_prepared = 1;
|
||||
|
||||
@ -496,12 +524,16 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct hdac_ext_stream *link_dev =
|
||||
snd_soc_dai_get_dma_data(dai, substream);
|
||||
struct hdac_ext_bus *ebus = get_bus_ctx(substream);
|
||||
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
|
||||
|
||||
dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
skl_link_pcm_prepare(substream, dai);
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
snd_hdac_ext_stream_decouple(ebus, stream, true);
|
||||
snd_hdac_ext_link_stream_start(link_dev);
|
||||
break;
|
||||
|
||||
@ -509,6 +541,8 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
snd_hdac_ext_link_stream_clear(link_dev);
|
||||
if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
|
||||
snd_hdac_ext_stream_decouple(ebus, stream, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
#include "../common/sst-dsp.h"
|
||||
#include "../common/sst-dsp-priv.h"
|
||||
#include "skl.h"
|
||||
#include "skl-sst-dsp.h"
|
||||
#include "skl-sst-ipc.h"
|
||||
#include "sound/hdaudio_ext.h"
|
||||
|
||||
|
||||
#define IPC_IXC_STATUS_BITS 24
|
||||
@ -322,6 +324,19 @@ static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
|
||||
wake_up(&skl->boot_wait);
|
||||
break;
|
||||
|
||||
case IPC_GLB_NOTIFY_PHRASE_DETECTED:
|
||||
dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
|
||||
|
||||
/*
|
||||
* Per HW recomendation, After phrase detection,
|
||||
* clear the CGCTL.MISCBDCGE.
|
||||
*
|
||||
* This will be set back on stream closure
|
||||
*/
|
||||
skl->enable_miscbdcge(ipc->dev, false);
|
||||
skl->miscbdcg_disabled = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(ipc->dev, "ipc: Unhandled error msg=%x",
|
||||
header.primary);
|
||||
|
@ -55,6 +55,11 @@ struct skl_sst {
|
||||
|
||||
/* IPC messaging */
|
||||
struct sst_generic_ipc ipc;
|
||||
|
||||
/* callback for miscbdge */
|
||||
void (*enable_miscbdcge)(struct device *dev, bool enable);
|
||||
/*Is CGCTL.MISCBDCGE disabled*/
|
||||
bool miscbdcg_disabled;
|
||||
};
|
||||
|
||||
struct skl_ipc_init_instance_msg {
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <sound/pcm.h>
|
||||
#include "../common/sst-acpi.h"
|
||||
#include "skl.h"
|
||||
#include "skl-sst-dsp.h"
|
||||
#include "skl-sst-ipc.h"
|
||||
|
||||
/*
|
||||
* initialize the PCI registers
|
||||
@ -59,6 +61,49 @@ static void skl_init_pci(struct skl *skl)
|
||||
skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0);
|
||||
}
|
||||
|
||||
static void update_pci_dword(struct pci_dev *pci,
|
||||
unsigned int reg, u32 mask, u32 val)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
pci_read_config_dword(pci, reg, &data);
|
||||
data &= ~mask;
|
||||
data |= (val & mask);
|
||||
pci_write_config_dword(pci, reg, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits
|
||||
*
|
||||
* @dev: device pointer
|
||||
* @enable: enable/disable flag
|
||||
*/
|
||||
static void skl_enable_miscbdcge(struct device *dev, bool enable)
|
||||
{
|
||||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
u32 val;
|
||||
|
||||
val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0;
|
||||
|
||||
update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* While performing reset, controller may not come back properly causing
|
||||
* issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset
|
||||
* (init chip) and then again set CGCTL.MISCBDCGE to 1
|
||||
*/
|
||||
static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
skl_enable_miscbdcge(bus->dev, false);
|
||||
ret = snd_hdac_bus_init_chip(bus, full_reset);
|
||||
skl_enable_miscbdcge(bus->dev, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* called from IRQ */
|
||||
static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr)
|
||||
{
|
||||
@ -145,7 +190,9 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
|
||||
return ret;
|
||||
|
||||
snd_hdac_bus_stop_chip(bus);
|
||||
skl_enable_miscbdcge(bus->dev, false);
|
||||
snd_hdac_bus_enter_link_reset(bus);
|
||||
skl_enable_miscbdcge(bus->dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -156,7 +203,7 @@ static int _skl_resume(struct hdac_ext_bus *ebus)
|
||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||
|
||||
skl_init_pci(skl);
|
||||
snd_hdac_bus_init_chip(bus, true);
|
||||
skl_init_chip(bus, true);
|
||||
|
||||
return skl_resume_dsp(skl);
|
||||
}
|
||||
@ -171,12 +218,15 @@ static int skl_suspend(struct device *dev)
|
||||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
|
||||
struct skl *skl = ebus_to_skl(ebus);
|
||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||
|
||||
/*
|
||||
* Do not suspend if streams which are marked ignore suspend are
|
||||
* running, we need to save the state for these and continue
|
||||
*/
|
||||
if (skl->supend_active) {
|
||||
snd_hdac_ext_bus_link_power_down_all(ebus);
|
||||
enable_irq_wake(bus->irq);
|
||||
pci_save_state(pci);
|
||||
pci_disable_device(pci);
|
||||
return 0;
|
||||
@ -190,6 +240,7 @@ static int skl_resume(struct device *dev)
|
||||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
|
||||
struct skl *skl = ebus_to_skl(ebus);
|
||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -199,6 +250,8 @@ static int skl_resume(struct device *dev)
|
||||
if (skl->supend_active) {
|
||||
pci_restore_state(pci);
|
||||
ret = pci_enable_device(pci);
|
||||
snd_hdac_ext_bus_link_power_up_all(ebus);
|
||||
disable_irq_wake(bus->irq);
|
||||
} else {
|
||||
ret = _skl_resume(ebus);
|
||||
}
|
||||
@ -380,7 +433,7 @@ static int skl_codec_create(struct hdac_ext_bus *ebus)
|
||||
* back to the sanity state.
|
||||
*/
|
||||
snd_hdac_bus_stop_chip(bus);
|
||||
snd_hdac_bus_init_chip(bus, true);
|
||||
skl_init_chip(bus, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -490,7 +543,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
|
||||
/* initialize chip */
|
||||
skl_init_pci(skl);
|
||||
|
||||
snd_hdac_bus_init_chip(bus, true);
|
||||
skl_init_chip(bus, true);
|
||||
|
||||
/* codec detection */
|
||||
if (!bus->codec_mask) {
|
||||
@ -539,6 +592,8 @@ static int skl_probe(struct pci_dev *pci,
|
||||
dev_dbg(bus->dev, "error failed to register dsp\n");
|
||||
goto out_mach_free;
|
||||
}
|
||||
skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
|
||||
|
||||
}
|
||||
if (ebus->mlcap)
|
||||
snd_hdac_ext_bus_get_ml_capabilities(ebus);
|
||||
|
@ -48,6 +48,9 @@
|
||||
#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094
|
||||
#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20
|
||||
|
||||
#define AZX_PCIREG_CGCTL 0x48
|
||||
#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6)
|
||||
|
||||
struct skl_dsp_resource {
|
||||
u32 max_mcps;
|
||||
u32 max_mem;
|
||||
|
@ -242,6 +242,9 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
val |= I2S_TXCR_VDW(24);
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
val |= I2S_TXCR_VDW(32);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -360,7 +363,8 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
|
||||
.formats = (SNDRV_PCM_FMTBIT_S8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE),
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE),
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
@ -370,7 +374,8 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
|
||||
.formats = (SNDRV_PCM_FMTBIT_S8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE),
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE),
|
||||
},
|
||||
.ops = &rockchip_i2s_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
|
@ -403,29 +403,30 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
|
||||
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
|
||||
if (rsnd_ssi_is_parent(mod, io))
|
||||
goto rsnd_ssi_quit_end;
|
||||
if (!ssi->usrcnt) {
|
||||
dev_err(dev, "%s[%d] usrcnt error\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ssi->err > 0)
|
||||
dev_warn(dev, "%s[%d] under/over flow err = %d\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod), ssi->err);
|
||||
if (!rsnd_ssi_is_parent(mod, io)) {
|
||||
if (ssi->err > 0)
|
||||
dev_warn(dev, "%s[%d] under/over flow err = %d\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod),
|
||||
ssi->err);
|
||||
|
||||
ssi->cr_own = 0;
|
||||
ssi->err = 0;
|
||||
ssi->cr_own = 0;
|
||||
ssi->err = 0;
|
||||
|
||||
rsnd_ssi_irq_disable(mod);
|
||||
rsnd_ssi_irq_disable(mod);
|
||||
}
|
||||
|
||||
rsnd_ssi_quit_end:
|
||||
rsnd_ssi_master_clk_stop(ssi, io);
|
||||
|
||||
rsnd_mod_power_off(mod);
|
||||
|
||||
ssi->usrcnt--;
|
||||
|
||||
if (ssi->usrcnt < 0)
|
||||
dev_err(dev, "%s[%d] usrcnt error\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
|
||||
switch (multi_ssi_slaves) {
|
||||
case 0x0206: /* SSI0/1/2/9 */
|
||||
val2 = (1 << 4) | /* SSI0129 sync */
|
||||
rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1;
|
||||
(rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1);
|
||||
/* fall through */
|
||||
case 0x0006: /* SSI0/1/2 */
|
||||
val1 = rsnd_rdai_is_clk_master(rdai) ?
|
||||
|
@ -630,6 +630,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
struct snd_pcm *be_pcm;
|
||||
char new_name[64];
|
||||
int ret = 0, direction = 0;
|
||||
int playback = 0, capture = 0;
|
||||
|
||||
if (rtd->num_codecs > 1) {
|
||||
dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
|
||||
@ -641,11 +642,27 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
rtd->dai_link->stream_name, codec_dai->name, num);
|
||||
|
||||
if (codec_dai->driver->playback.channels_min)
|
||||
direction = SND_COMPRESS_PLAYBACK;
|
||||
else if (codec_dai->driver->capture.channels_min)
|
||||
direction = SND_COMPRESS_CAPTURE;
|
||||
else
|
||||
playback = 1;
|
||||
if (codec_dai->driver->capture.channels_min)
|
||||
capture = 1;
|
||||
|
||||
capture = capture && cpu_dai->driver->capture.channels_min;
|
||||
playback = playback && cpu_dai->driver->playback.channels_min;
|
||||
|
||||
/*
|
||||
* Compress devices are unidirectional so only one of the directions
|
||||
* should be set, check for that (xor)
|
||||
*/
|
||||
if (playback + capture != 1) {
|
||||
dev_err(rtd->card->dev, "Invalid direction for compress P %d, C %d\n",
|
||||
playback, capture);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(playback)
|
||||
direction = SND_COMPRESS_PLAYBACK;
|
||||
else
|
||||
direction = SND_COMPRESS_CAPTURE;
|
||||
|
||||
compr = kzalloc(sizeof(*compr), GFP_KERNEL);
|
||||
if (compr == NULL) {
|
||||
|
@ -1413,6 +1413,16 @@ static int soc_probe_component(struct snd_soc_card *card,
|
||||
component->name);
|
||||
}
|
||||
|
||||
/* machine specific init */
|
||||
if (component->init) {
|
||||
ret = component->init(component);
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev,
|
||||
"Failed to do machine specific init %d\n", ret);
|
||||
goto err_probe;
|
||||
}
|
||||
}
|
||||
|
||||
if (component->controls)
|
||||
snd_soc_add_component_controls(component, component->controls,
|
||||
component->num_controls);
|
||||
@ -1657,65 +1667,81 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
|
||||
|
||||
static int soc_bind_aux_dev(struct snd_soc_card *card, int num)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
|
||||
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
|
||||
const char *name = aux_dev->codec_name;
|
||||
struct snd_soc_component *component;
|
||||
const char *name;
|
||||
struct device_node *codec_of_node;
|
||||
|
||||
rtd->component = soc_find_component(aux_dev->codec_of_node, name);
|
||||
if (!rtd->component) {
|
||||
if (aux_dev->codec_of_node)
|
||||
name = of_node_full_name(aux_dev->codec_of_node);
|
||||
|
||||
dev_err(card->dev, "ASoC: %s not registered\n", name);
|
||||
return -EPROBE_DEFER;
|
||||
if (aux_dev->codec_of_node || aux_dev->codec_name) {
|
||||
/* codecs, usually analog devices */
|
||||
name = aux_dev->codec_name;
|
||||
codec_of_node = aux_dev->codec_of_node;
|
||||
component = soc_find_component(codec_of_node, name);
|
||||
if (!component) {
|
||||
if (codec_of_node)
|
||||
name = of_node_full_name(codec_of_node);
|
||||
goto err_defer;
|
||||
}
|
||||
} else if (aux_dev->name) {
|
||||
/* generic components */
|
||||
name = aux_dev->name;
|
||||
component = soc_find_component(NULL, name);
|
||||
if (!component)
|
||||
goto err_defer;
|
||||
} else {
|
||||
dev_err(card->dev, "ASoC: Invalid auxiliary device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some places still reference rtd->codec, so we have to keep that
|
||||
* initialized if the component is a CODEC. Once all those references
|
||||
* have been removed, this code can be removed as well.
|
||||
*/
|
||||
rtd->codec = rtd->component->codec;
|
||||
component->init = aux_dev->init;
|
||||
list_add(&component->list_aux, &card->aux_comp_list);
|
||||
return 0;
|
||||
|
||||
err_defer:
|
||||
dev_err(card->dev, "ASoC: %s not registered\n", name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
static int soc_probe_aux_devices(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_component *comp;
|
||||
int order;
|
||||
int ret;
|
||||
|
||||
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
|
||||
order++) {
|
||||
list_for_each_entry(comp, &card->aux_comp_list, list_aux) {
|
||||
if (comp->driver->probe_order == order) {
|
||||
ret = soc_probe_component(card, comp);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev,
|
||||
"ASoC: failed to probe aux component %s %d\n",
|
||||
comp->name, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
|
||||
static void soc_remove_aux_devices(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
|
||||
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
|
||||
int ret;
|
||||
struct snd_soc_component *comp, *_comp;
|
||||
int order;
|
||||
|
||||
ret = soc_probe_component(card, rtd->component);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* do machine specific initialization */
|
||||
if (aux_dev->init) {
|
||||
ret = aux_dev->init(rtd->component);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "ASoC: failed to init %s: %d\n",
|
||||
aux_dev->name, ret);
|
||||
return ret;
|
||||
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
|
||||
order++) {
|
||||
list_for_each_entry_safe(comp, _comp,
|
||||
&card->aux_comp_list, list_aux) {
|
||||
if (comp->driver->remove_order == order) {
|
||||
soc_remove_component(comp);
|
||||
/* remove it from the card's aux_comp_list */
|
||||
list_del(&comp->list_aux);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return soc_post_component_init(rtd, aux_dev->name);
|
||||
}
|
||||
|
||||
static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
|
||||
struct snd_soc_component *component = rtd->component;
|
||||
|
||||
/* unregister the rtd device */
|
||||
if (rtd->dev_registered) {
|
||||
device_unregister(rtd->dev);
|
||||
rtd->dev_registered = 0;
|
||||
}
|
||||
|
||||
if (component)
|
||||
soc_remove_component(component);
|
||||
}
|
||||
|
||||
static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
|
||||
@ -1894,6 +1920,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
|
||||
}
|
||||
}
|
||||
|
||||
/* probe auxiliary components */
|
||||
ret = soc_probe_aux_devices(card);
|
||||
if (ret < 0)
|
||||
goto probe_dai_err;
|
||||
|
||||
/* Find new DAI links added during probing components and bind them.
|
||||
* Components with topology may bring new DAIs and DAI links.
|
||||
*/
|
||||
@ -1923,16 +1954,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < card->num_aux_devs; i++) {
|
||||
ret = soc_probe_aux_dev(card, i);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev,
|
||||
"ASoC: failed to add auxiliary devices %d\n",
|
||||
ret);
|
||||
goto probe_aux_dev_err;
|
||||
}
|
||||
}
|
||||
|
||||
snd_soc_dapm_link_dai_widgets(card);
|
||||
snd_soc_dapm_connect_dai_link_widgets(card);
|
||||
|
||||
@ -1992,8 +2013,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
|
||||
return 0;
|
||||
|
||||
probe_aux_dev_err:
|
||||
for (i = 0; i < card->num_aux_devs; i++)
|
||||
soc_remove_aux_dev(card, i);
|
||||
soc_remove_aux_devices(card);
|
||||
|
||||
probe_dai_err:
|
||||
soc_remove_dai_links(card);
|
||||
@ -2039,20 +2059,18 @@ static int soc_probe(struct platform_device *pdev)
|
||||
static int soc_cleanup_card_resources(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd;
|
||||
int i;
|
||||
|
||||
/* make sure any delayed work runs */
|
||||
list_for_each_entry(rtd, &card->rtd_list, list)
|
||||
flush_delayed_work(&rtd->delayed_work);
|
||||
|
||||
/* remove auxiliary devices */
|
||||
for (i = 0; i < card->num_aux_devs; i++)
|
||||
soc_remove_aux_dev(card, i);
|
||||
|
||||
/* remove and free each DAI */
|
||||
soc_remove_dai_links(card);
|
||||
soc_remove_pcm_runtimes(card);
|
||||
|
||||
/* remove auxiliary devices */
|
||||
soc_remove_aux_devices(card);
|
||||
|
||||
soc_cleanup_card_debugfs(card);
|
||||
|
||||
/* remove the card */
|
||||
@ -2608,16 +2626,6 @@ int snd_soc_register_card(struct snd_soc_card *card)
|
||||
INIT_LIST_HEAD(&card->rtd_list);
|
||||
card->num_rtd = 0;
|
||||
|
||||
card->rtd_aux = devm_kzalloc(card->dev,
|
||||
sizeof(struct snd_soc_pcm_runtime) *
|
||||
card->num_aux_devs,
|
||||
GFP_KERNEL);
|
||||
if (card->rtd_aux == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < card->num_aux_devs; i++)
|
||||
card->rtd_aux[i].card = card;
|
||||
|
||||
INIT_LIST_HEAD(&card->dapm_dirty);
|
||||
INIT_LIST_HEAD(&card->dobj_list);
|
||||
card->instantiated = 0;
|
||||
@ -2744,6 +2752,56 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a DAI and add it to the component's DAI list */
|
||||
static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
bool legacy_dai_naming)
|
||||
{
|
||||
struct device *dev = component->dev;
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
dev_dbg(dev, "ASoC: dynamically register DAI %s\n", dev_name(dev));
|
||||
|
||||
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
|
||||
if (dai == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Back in the old days when we still had component-less DAIs,
|
||||
* instead of having a static name, component-less DAIs would
|
||||
* inherit the name of the parent device so it is possible to
|
||||
* register multiple instances of the DAI. We still need to keep
|
||||
* the same naming style even though those DAIs are not
|
||||
* component-less anymore.
|
||||
*/
|
||||
if (legacy_dai_naming &&
|
||||
(dai_drv->id == 0 || dai_drv->name == NULL)) {
|
||||
dai->name = fmt_single_name(dev, &dai->id);
|
||||
} else {
|
||||
dai->name = fmt_multiple_name(dev, dai_drv);
|
||||
if (dai_drv->id)
|
||||
dai->id = dai_drv->id;
|
||||
else
|
||||
dai->id = component->num_dai;
|
||||
}
|
||||
if (dai->name == NULL) {
|
||||
kfree(dai);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dai->component = component;
|
||||
dai->dev = dev;
|
||||
dai->driver = dai_drv;
|
||||
if (!dai->driver->ops)
|
||||
dai->driver->ops = &null_dai_ops;
|
||||
|
||||
list_add(&dai->list, &component->dai_list);
|
||||
component->num_dai++;
|
||||
|
||||
dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
|
||||
return dai;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_dais - Register a DAI with the ASoC core
|
||||
*
|
||||
@ -2765,49 +2823,15 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
|
||||
dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
|
||||
|
||||
component->dai_drv = dai_drv;
|
||||
component->num_dai = count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
|
||||
dai = soc_add_dai(component, dai_drv + i,
|
||||
count == 1 && legacy_dai_naming);
|
||||
if (dai == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Back in the old days when we still had component-less DAIs,
|
||||
* instead of having a static name, component-less DAIs would
|
||||
* inherit the name of the parent device so it is possible to
|
||||
* register multiple instances of the DAI. We still need to keep
|
||||
* the same naming style even though those DAIs are not
|
||||
* component-less anymore.
|
||||
*/
|
||||
if (count == 1 && legacy_dai_naming &&
|
||||
(dai_drv[i].id == 0 || dai_drv[i].name == NULL)) {
|
||||
dai->name = fmt_single_name(dev, &dai->id);
|
||||
} else {
|
||||
dai->name = fmt_multiple_name(dev, &dai_drv[i]);
|
||||
if (dai_drv[i].id)
|
||||
dai->id = dai_drv[i].id;
|
||||
else
|
||||
dai->id = i;
|
||||
}
|
||||
if (dai->name == NULL) {
|
||||
kfree(dai);
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dai->component = component;
|
||||
dai->dev = dev;
|
||||
dai->driver = &dai_drv[i];
|
||||
if (!dai->driver->ops)
|
||||
dai->driver->ops = &null_dai_ops;
|
||||
|
||||
list_add(&dai->list, &component->dai_list);
|
||||
|
||||
dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2818,6 +2842,48 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_register_dai - Register a DAI dynamically & create its widgets
|
||||
*
|
||||
* @component: The component the DAIs are registered for
|
||||
* @dai_drv: DAI driver to use for the DAI
|
||||
*
|
||||
* Topology can use this API to register DAIs when probing a component.
|
||||
* These DAIs's widgets will be freed in the card cleanup and the DAIs
|
||||
* will be freed in the component cleanup.
|
||||
*/
|
||||
int snd_soc_register_dai(struct snd_soc_component *component,
|
||||
struct snd_soc_dai_driver *dai_drv)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm =
|
||||
snd_soc_component_get_dapm(component);
|
||||
struct snd_soc_dai *dai;
|
||||
int ret;
|
||||
|
||||
if (dai_drv->dobj.type != SND_SOC_DOBJ_PCM) {
|
||||
dev_err(component->dev, "Invalid dai type %d\n",
|
||||
dai_drv->dobj.type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lockdep_assert_held(&client_mutex);
|
||||
dai = soc_add_dai(component, dai_drv, false);
|
||||
if (!dai)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Create the DAI widgets here. After adding DAIs, topology may
|
||||
* also add routes that need these widgets as source or sink.
|
||||
*/
|
||||
ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
|
||||
if (ret != 0) {
|
||||
dev_err(component->dev,
|
||||
"Failed to create DAI widgets %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_register_dai);
|
||||
|
||||
static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_dapm_type type, int subseq)
|
||||
{
|
||||
|
@ -599,10 +599,15 @@ platform_err:
|
||||
out:
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
|
||||
pm_runtime_put(platform->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
pm_runtime_put(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_put(cpu_dai->dev);
|
||||
pm_runtime_mark_last_busy(platform->dev);
|
||||
pm_runtime_put_autosuspend(platform->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(cpu_dai->dev);
|
||||
pm_runtime_put_autosuspend(cpu_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
if (!rtd->codec_dais[i]->active)
|
||||
pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
|
||||
@ -706,10 +711,17 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
|
||||
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
|
||||
pm_runtime_put(platform->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
pm_runtime_put(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_put(cpu_dai->dev);
|
||||
pm_runtime_mark_last_busy(platform->dev);
|
||||
pm_runtime_put_autosuspend(platform->dev);
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(cpu_dai->dev);
|
||||
pm_runtime_put_autosuspend(cpu_dai->dev);
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
if (!rtd->codec_dais[i]->active)
|
||||
pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
|
||||
|
Loading…
Reference in New Issue
Block a user