lkml.org 
[lkml]   [2020]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 132/314] SoC: rsnd: add interrupt support for SSI BUSIF buffer
    Date
    From: Yongbo Zhang <giraffesnn123@gmail.com>

    [ Upstream commit 66c705d07d784fb6b4622c6e47b6acae357472db ]

    SSI BUSIF buffer is possible to overflow or underflow, especially in a
    hypervisor environment. If there is no interrupt support, it will eventually
    lead to errors in pcm data.
    This patch adds overflow and underflow interrupt support for SSI BUSIF buffer.

    Reported-by: Chen Li <licheng0822@thundersoft.com>
    Signed-off-by: Yongbo Zhang <giraffesnn123@gmail.com>
    Tested-by: Chen Li <licheng0822@thundersoft.com>
    Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
    Link: https://lore.kernel.org/r/20200512093003.28332-1-giraffesnn123@gmail.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    sound/soc/sh/rcar/gen.c | 8 +++
    sound/soc/sh/rcar/rsnd.h | 9 +++
    sound/soc/sh/rcar/ssi.c | 145 +++++++++++++++++++++++++++++++++++++++
    3 files changed, 162 insertions(+)

    diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
    index af19010b9d88f..8bd49c8a9517e 100644
    --- a/sound/soc/sh/rcar/gen.c
    +++ b/sound/soc/sh/rcar/gen.c
    @@ -224,6 +224,14 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
    RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
    RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
    RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
    + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c),
    RSND_GEN_S_REG(HDMI0_SEL, 0x9e0),
    RSND_GEN_S_REG(HDMI1_SEL, 0x9e4),

    diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
    index ea6cbaa9743ee..d47608ff5facc 100644
    --- a/sound/soc/sh/rcar/rsnd.h
    +++ b/sound/soc/sh/rcar/rsnd.h
    @@ -189,6 +189,14 @@ enum rsnd_reg {
    SSI_SYS_STATUS5,
    SSI_SYS_STATUS6,
    SSI_SYS_STATUS7,
    + SSI_SYS_INT_ENABLE0,
    + SSI_SYS_INT_ENABLE1,
    + SSI_SYS_INT_ENABLE2,
    + SSI_SYS_INT_ENABLE3,
    + SSI_SYS_INT_ENABLE4,
    + SSI_SYS_INT_ENABLE5,
    + SSI_SYS_INT_ENABLE6,
    + SSI_SYS_INT_ENABLE7,
    HDMI0_SEL,
    HDMI1_SEL,
    SSI9_BUSIF0_MODE,
    @@ -237,6 +245,7 @@ enum rsnd_reg {
    #define SSI9_BUSIF_ADINR(i) (SSI9_BUSIF0_ADINR + (i))
    #define SSI9_BUSIF_DALIGN(i) (SSI9_BUSIF0_DALIGN + (i))
    #define SSI_SYS_STATUS(i) (SSI_SYS_STATUS0 + (i))
    +#define SSI_SYS_INT_ENABLE(i) (SSI_SYS_INT_ENABLE0 + (i))


    struct rsnd_priv;
    diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
    index 4a7d3413917fc..47d5ddb526f21 100644
    --- a/sound/soc/sh/rcar/ssi.c
    +++ b/sound/soc/sh/rcar/ssi.c
    @@ -372,6 +372,9 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
    u32 wsr = ssi->wsr;
    int width;
    int is_tdm, is_tdm_split;
    + int id = rsnd_mod_id(mod);
    + int i;
    + u32 sys_int_enable = 0;

    is_tdm = rsnd_runtime_is_tdm(io);
    is_tdm_split = rsnd_runtime_is_tdm_split(io);
    @@ -447,6 +450,38 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
    cr_mode = DIEN; /* PIO : enable Data interrupt */
    }

    + /* enable busif buffer over/under run interrupt. */
    + if (is_tdm || is_tdm_split) {
    + switch (id) {
    + case 0:
    + case 1:
    + case 2:
    + case 3:
    + case 4:
    + for (i = 0; i < 4; i++) {
    + sys_int_enable = rsnd_mod_read(mod,
    + SSI_SYS_INT_ENABLE(i * 2));
    + sys_int_enable |= 0xf << (id * 4);
    + rsnd_mod_write(mod,
    + SSI_SYS_INT_ENABLE(i * 2),
    + sys_int_enable);
    + }
    +
    + break;
    + case 9:
    + for (i = 0; i < 4; i++) {
    + sys_int_enable = rsnd_mod_read(mod,
    + SSI_SYS_INT_ENABLE((i * 2) + 1));
    + sys_int_enable |= 0xf << 4;
    + rsnd_mod_write(mod,
    + SSI_SYS_INT_ENABLE((i * 2) + 1),
    + sys_int_enable);
    + }
    +
    + break;
    + }
    + }
    +
    init_end:
    ssi->cr_own = cr_own;
    ssi->cr_mode = cr_mode;
    @@ -496,6 +531,13 @@ 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);
    + int is_tdm, is_tdm_split;
    + int id = rsnd_mod_id(mod);
    + int i;
    + u32 sys_int_enable = 0;
    +
    + is_tdm = rsnd_runtime_is_tdm(io);
    + is_tdm_split = rsnd_runtime_is_tdm_split(io);

    if (!rsnd_ssi_is_run_mods(mod, io))
    return 0;
    @@ -517,6 +559,38 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
    ssi->wsr = 0;
    }

    + /* disable busif buffer over/under run interrupt. */
    + if (is_tdm || is_tdm_split) {
    + switch (id) {
    + case 0:
    + case 1:
    + case 2:
    + case 3:
    + case 4:
    + for (i = 0; i < 4; i++) {
    + sys_int_enable = rsnd_mod_read(mod,
    + SSI_SYS_INT_ENABLE(i * 2));
    + sys_int_enable &= ~(0xf << (id * 4));
    + rsnd_mod_write(mod,
    + SSI_SYS_INT_ENABLE(i * 2),
    + sys_int_enable);
    + }
    +
    + break;
    + case 9:
    + for (i = 0; i < 4; i++) {
    + sys_int_enable = rsnd_mod_read(mod,
    + SSI_SYS_INT_ENABLE((i * 2) + 1));
    + sys_int_enable &= ~(0xf << 4);
    + rsnd_mod_write(mod,
    + SSI_SYS_INT_ENABLE((i * 2) + 1),
    + sys_int_enable);
    + }
    +
    + break;
    + }
    + }
    +
    return 0;
    }

    @@ -622,6 +696,11 @@ static int rsnd_ssi_irq(struct rsnd_mod *mod,
    int enable)
    {
    u32 val = 0;
    + int is_tdm, is_tdm_split;
    + int id = rsnd_mod_id(mod);
    +
    + is_tdm = rsnd_runtime_is_tdm(io);
    + is_tdm_split = rsnd_runtime_is_tdm_split(io);

    if (rsnd_is_gen1(priv))
    return 0;
    @@ -635,6 +714,19 @@ static int rsnd_ssi_irq(struct rsnd_mod *mod,
    if (enable)
    val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000;

    + if (is_tdm || is_tdm_split) {
    + switch (id) {
    + case 0:
    + case 1:
    + case 2:
    + case 3:
    + case 4:
    + case 9:
    + val |= 0x0000ff00;
    + break;
    + }
    + }
    +
    rsnd_mod_write(mod, SSI_INT_ENABLE, val);

    return 0;
    @@ -651,6 +743,12 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
    u32 status;
    bool elapsed = false;
    bool stop = false;
    + int id = rsnd_mod_id(mod);
    + int i;
    + int is_tdm, is_tdm_split;
    +
    + is_tdm = rsnd_runtime_is_tdm(io);
    + is_tdm_split = rsnd_runtime_is_tdm_split(io);

    spin_lock(&priv->lock);

    @@ -672,6 +770,53 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
    stop = true;
    }

    + status = 0;
    +
    + if (is_tdm || is_tdm_split) {
    + switch (id) {
    + case 0:
    + case 1:
    + case 2:
    + case 3:
    + case 4:
    + for (i = 0; i < 4; i++) {
    + status = rsnd_mod_read(mod,
    + SSI_SYS_STATUS(i * 2));
    + status &= 0xf << (id * 4);
    +
    + if (status) {
    + rsnd_dbg_irq_status(dev,
    + "%s err status : 0x%08x\n",
    + rsnd_mod_name(mod), status);
    + rsnd_mod_write(mod,
    + SSI_SYS_STATUS(i * 2),
    + 0xf << (id * 4));
    + stop = true;
    + break;
    + }
    + }
    + break;
    + case 9:
    + for (i = 0; i < 4; i++) {
    + status = rsnd_mod_read(mod,
    + SSI_SYS_STATUS((i * 2) + 1));
    + status &= 0xf << 4;
    +
    + if (status) {
    + rsnd_dbg_irq_status(dev,
    + "%s err status : 0x%08x\n",
    + rsnd_mod_name(mod), status);
    + rsnd_mod_write(mod,
    + SSI_SYS_STATUS((i * 2) + 1),
    + 0xf << 4);
    + stop = true;
    + break;
    + }
    + }
    + break;
    + }
    + }
    +
    rsnd_ssi_status_clear(mod);
    rsnd_ssi_interrupt_out:
    spin_unlock(&priv->lock);
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-06-23 22:28    [W:4.260 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site