diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index a3934a5b75..008801fae7 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -25,6 +25,7 @@ #include "swrm_registers.h" #include "swr-mstr-ctrl.h" +#define SWRM_FRAME_SYNC_SEL 4000 /* 4KHz */ #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700 #define SWRM_SYS_SUSPEND_WAIT 1 @@ -43,6 +44,13 @@ #define ERR_AUTO_SUSPEND_TIMER_VAL 0x1 #define SWRM_INTERRUPT_STATUS_MASK 0x1FDFD + +#define SWRM_ROW_48 48 +#define SWRM_ROW_50 50 +#define SWRM_ROW_64 64 +#define SWRM_COL_02 02 +#define SWRM_COL_16 16 + /* pm runtime auto suspend timer in msecs */ static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000; module_param(auto_suspend_timer, int, 0664); @@ -341,6 +349,16 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, return ret; } +static int swrm_get_ssp_period(struct swr_mstr_ctrl *swrm, + int row, int col, + int frame_sync) +{ + if (!swrm || !row || !col || !frame_sync) + return 1; + + return ((swrm->bus_clk * 2) / ((row * col) * frame_sync)); +} + static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable) { int ret = 0; @@ -591,6 +609,10 @@ retry_read: if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) { /* wait 500 us before retry on fifo read failure */ usleep_range(500, 505); + if (retry_attempt == (MAX_FIFO_RD_FAIL_RETRY - 1)) { + swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1); + swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); + } retry_attempt++; goto retry_read; } else { @@ -1093,7 +1115,9 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable) { u8 bank; u32 value, n_row, n_col; + u32 row = 0, col = 0; int ret; + u8 ssp_period = 0; struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | @@ -1162,30 +1186,39 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable) if (enable) { /* set col = 16 */ n_col = SWR_MAX_COL; + col = SWRM_COL_16; } else { /* * Do not change to col = 2 if there are still active ports */ - if (!master->num_port) + if (!master->num_port) { n_col = SWR_MIN_COL; - else + col = SWRM_COL_02; + } else { n_col = SWR_MAX_COL; + col = SWRM_COL_16; + } } /* Use default 50 * x, frame shape. Change based on mclk */ if (swrm->mclk_freq == MCLK_FREQ_NATIVE) { dev_dbg(swrm->dev, "setting 64 x %d frameshape\n", n_col ? 16 : 2); n_row = SWR_ROW_64; + row = SWRM_ROW_64; } else { dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", n_col ? 16 : 2); n_row = SWR_ROW_50; + row = SWRM_ROW_50; } + ssp_period = swrm_get_ssp_period(swrm, row, col, SWRM_FRAME_SYNC_SEL); + dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period); + value = swr_master_read(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); value &= (~mask); value |= ((n_row << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | - (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); + ((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); swr_master_write(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, @@ -1726,6 +1759,7 @@ handle_irq: case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW: dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n", __func__); + swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1); break; case SWRM_INTERRUPT_STATUS_CMD_ERROR: value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS); @@ -2019,10 +2053,14 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) u32 temp = 0; int len = 0; + ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50, + SWRM_COL_02, SWRM_FRAME_SYNC_SEL); + dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period); + /* Clear Rows and Cols */ val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | - (ssp_period << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); + ((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); reg[len] = SWRM_MCP_FRAME_CTRL_BANK_ADDR(0); value[len++] = val; @@ -2303,6 +2341,7 @@ static int swrm_probe(struct platform_device *pdev) swrm->clk_ref_count = 0; swrm->swr_irq_wakeup_capable = 0; swrm->mclk_freq = MCLK_FREQ; + swrm->bus_clk = MCLK_FREQ; swrm->dev_up = true; swrm->state = SWR_MSTR_UP; swrm->ipc_wakeup = false; @@ -2882,6 +2921,7 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) usleep_range(10000, 10500); } swrm->mclk_freq = *(int *)data; + swrm->bus_clk = swrm->mclk_freq; mutex_unlock(&swrm->mlock); } break; diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index 43bf227601..b07a80db61 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -142,6 +142,7 @@ struct swr_mstr_ctrl { int wake_irq; int version; int mclk_freq; + int bus_clk; u32 num_dev; int slave_status; struct swrm_mports mport_cfg[SWR_MAX_MSTR_PORT_NUM];