Skip to content

Commit

Permalink
ASoC: Intel: avs: Abstract IPC handling
Browse files Browse the repository at this point in the history
Servicing IPCs on CNL platforms and onward differs from the existing
one. To make room for these, enrich platform descriptor with fields
representing crucial IPC registers and utilize them throughout the code.

While cleaning up device descriptors, reduce the number of code lines by
assigning 'min_fw_version' within a single line.

Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://msgid.link/r/20240220115035.770402-5-cezary.rojewski@intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Cezary Rojewski authored and Mark Brown committed Feb 20, 2024
1 parent a8f858d commit 7576e2f
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 41 deletions.
22 changes: 19 additions & 3 deletions sound/soc/intel/avs/avs.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,23 @@ extern const struct avs_dsp_ops avs_apl_dsp_ops;
#define avs_platattr_test(adev, attr) \
((adev)->spec->attributes & AVS_PLATATTR_##attr)

struct avs_sram_spec {
const u32 base_offset;
const u32 window_size;
const u32 rom_status_offset;
};

struct avs_hipc_spec {
const u32 req_offset;
const u32 req_ext_offset;
const u32 req_busy_mask;
const u32 ack_offset;
const u32 ack_done_mask;
const u32 rsp_offset;
const u32 rsp_busy_mask;
const u32 ctl_offset;
};

/* Platform specific descriptor */
struct avs_spec {
const char *name;
Expand All @@ -82,9 +99,8 @@ struct avs_spec {

const u32 core_init_mask; /* used during DSP boot */
const u64 attributes; /* bitmask of AVS_PLATATTR_* */
const u32 sram_base_offset;
const u32 sram_window_size;
const u32 rom_status;
const struct avs_sram_spec *sram;
const struct avs_hipc_spec *hipc;
};

struct avs_fw_entry {
Expand Down
47 changes: 29 additions & 18 deletions sound/soc/intel/avs/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,36 +730,47 @@ static const struct dev_pm_ops avs_dev_pm = {
SET_RUNTIME_PM_OPS(avs_runtime_suspend, avs_runtime_resume, NULL)
};

static const struct avs_sram_spec skl_sram_spec = {
.base_offset = SKL_ADSP_SRAM_BASE_OFFSET,
.window_size = SKL_ADSP_SRAM_WINDOW_SIZE,
.rom_status_offset = SKL_ADSP_SRAM_BASE_OFFSET,
};

static const struct avs_sram_spec apl_sram_spec = {
.base_offset = APL_ADSP_SRAM_BASE_OFFSET,
.window_size = APL_ADSP_SRAM_WINDOW_SIZE,
.rom_status_offset = APL_ADSP_SRAM_BASE_OFFSET,
};

static const struct avs_hipc_spec skl_hipc_spec = {
.req_offset = SKL_ADSP_REG_HIPCI,
.req_ext_offset = SKL_ADSP_REG_HIPCIE,
.req_busy_mask = SKL_ADSP_HIPCI_BUSY,
.ack_offset = SKL_ADSP_REG_HIPCIE,
.ack_done_mask = SKL_ADSP_HIPCIE_DONE,
.rsp_offset = SKL_ADSP_REG_HIPCT,
.rsp_busy_mask = SKL_ADSP_HIPCT_BUSY,
.ctl_offset = SKL_ADSP_REG_HIPCCTL,
};

static const struct avs_spec skl_desc = {
.name = "skl",
.min_fw_version = {
.major = 9,
.minor = 21,
.hotfix = 0,
.build = 4732,
},
.min_fw_version = { 9, 21, 0, 4732 },
.dsp_ops = &avs_skl_dsp_ops,
.core_init_mask = 1,
.attributes = AVS_PLATATTR_CLDMA,
.sram_base_offset = SKL_ADSP_SRAM_BASE_OFFSET,
.sram_window_size = SKL_ADSP_SRAM_WINDOW_SIZE,
.rom_status = SKL_ADSP_SRAM_BASE_OFFSET,
.sram = &skl_sram_spec,
.hipc = &skl_hipc_spec,
};

static const struct avs_spec apl_desc = {
.name = "apl",
.min_fw_version = {
.major = 9,
.minor = 22,
.hotfix = 1,
.build = 4323,
},
.min_fw_version = { 9, 22, 1, 4323 },
.dsp_ops = &avs_apl_dsp_ops,
.core_init_mask = 3,
.attributes = AVS_PLATATTR_IMR,
.sram_base_offset = APL_ADSP_SRAM_BASE_OFFSET,
.sram_window_size = APL_ADSP_SRAM_WINDOW_SIZE,
.rom_status = APL_ADSP_SRAM_BASE_OFFSET,
.sram = &apl_sram_spec,
.hipc = &skl_hipc_spec,
};

static const struct pci_device_id avs_ids[] = {
Expand Down
36 changes: 20 additions & 16 deletions sound/soc/intel/avs/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,42 +305,43 @@ irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id)
{
struct avs_dev *adev = dev_id;
struct avs_ipc *ipc = adev->ipc;
const struct avs_spec *const spec = adev->spec;
u32 adspis, hipc_rsp, hipc_ack;
irqreturn_t ret = IRQ_NONE;

adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS);
if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC))
return ret;

hipc_ack = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCIE);
hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset);
hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);

/* DSP acked host's request */
if (hipc_ack & SKL_ADSP_HIPCIE_DONE) {
if (hipc_ack & spec->hipc->ack_done_mask) {
/*
* As an extra precaution, mask done interrupt. Code executed
* due to complete() found below does not assume any masking.
*/
snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
AVS_ADSP_HIPCCTL_DONE, 0);

complete(&ipc->done_completion);

/* tell DSP it has our attention */
snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCIE,
SKL_ADSP_HIPCIE_DONE,
SKL_ADSP_HIPCIE_DONE);
snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset,
spec->hipc->ack_done_mask,
spec->hipc->ack_done_mask);
/* unmask done interrupt */
snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
AVS_ADSP_HIPCCTL_DONE,
AVS_ADSP_HIPCCTL_DONE);
ret = IRQ_HANDLED;
}

/* DSP sent new response to process */
if (hipc_rsp & SKL_ADSP_HIPCT_BUSY) {
if (hipc_rsp & spec->hipc->rsp_busy_mask) {
/* mask busy interrupt */
snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
AVS_ADSP_HIPCCTL_BUSY, 0);

ret = IRQ_WAKE_THREAD;
Expand Down Expand Up @@ -379,10 +380,11 @@ irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id)
static bool avs_ipc_is_busy(struct avs_ipc *ipc)
{
struct avs_dev *adev = to_avs_dev(ipc->dev);
const struct avs_spec *const spec = adev->spec;
u32 hipc_rsp;

hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
return hipc_rsp & SKL_ADSP_HIPCT_BUSY;
hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
return hipc_rsp & spec->hipc->rsp_busy_mask;
}

static int avs_ipc_wait_busy_completion(struct avs_ipc *ipc, int timeout)
Expand Down Expand Up @@ -440,18 +442,19 @@ static void avs_ipc_msg_init(struct avs_ipc *ipc, struct avs_ipc_msg *reply)

static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool read_fwregs)
{
const struct avs_spec *const spec = adev->spec;
u64 reg = ULONG_MAX;

tx->header |= SKL_ADSP_HIPCI_BUSY;
tx->header |= spec->hipc->req_busy_mask;
if (read_fwregs)
reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));

trace_avs_request(tx, reg);

if (tx->size)
memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size);
snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCIE, tx->header >> 32);
snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCI, tx->header & UINT_MAX);
snd_hdac_adsp_writel(adev, spec->hipc->req_ext_offset, tx->header >> 32);
snd_hdac_adsp_writel(adev, spec->hipc->req_offset, tx->header & UINT_MAX);
}

static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request,
Expand Down Expand Up @@ -606,6 +609,7 @@ int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, cons

void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable)
{
const struct avs_spec *const spec = adev->spec;
u32 value, mask;

/*
Expand All @@ -617,7 +621,7 @@ void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable)

mask = AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY;
value = enable ? mask : 0;
snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, mask, value);
snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, mask, value);
}

int avs_ipc_init(struct avs_ipc *ipc, struct device *dev)
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/intel/avs/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ avs_hda_init_rom(struct avs_dev *adev, unsigned int dma_id, bool purge)
}

/* await ROM init */
ret = snd_hdac_adsp_readq_poll(adev, spec->rom_status, reg,
ret = snd_hdac_adsp_readq_poll(adev, spec->sram->rom_status_offset, reg,
(reg & 0xF) == AVS_ROM_INIT_DONE ||
(reg & 0xF) == APL_ROM_FW_ENTERED,
AVS_ROM_INIT_POLLING_US, APL_ROM_INIT_TIMEOUT_US);
Expand Down
6 changes: 3 additions & 3 deletions sound/soc/intel/avs/registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
#define APL_ADSP_SRAM_WINDOW_SIZE 0x20000

/* Constants used when accessing SRAM, space shared with firmware */
#define AVS_FW_REG_BASE(adev) ((adev)->spec->sram_base_offset)
#define AVS_FW_REG_BASE(adev) ((adev)->spec->sram->base_offset)
#define AVS_FW_REG_STATUS(adev) (AVS_FW_REG_BASE(adev) + 0x0)
#define AVS_FW_REG_ERROR_CODE(adev) (AVS_FW_REG_BASE(adev) + 0x4)

Expand All @@ -72,8 +72,8 @@

/* registry I/O helpers */
#define avs_sram_offset(adev, window_idx) \
((adev)->spec->sram_base_offset + \
(adev)->spec->sram_window_size * (window_idx))
((adev)->spec->sram->base_offset + \
(adev)->spec->sram->window_size * (window_idx))

#define avs_sram_addr(adev, window_idx) \
((adev)->dsp_ba + avs_sram_offset(adev, window_idx))
Expand Down

0 comments on commit 7576e2f

Please sign in to comment.