soc: soundwire: change ssp period based on frame shape

Change SSP period based on soundwire bus clock rate and frame shape
to avoid any synchronization issues.

Change-Id: I376958c6b92eca28b857c4c7c9948b1e56818657
Signed-off-by: Sudheer Papothi <spapothi@codeaurora.org>
This commit is contained in:
Sudheer Papothi
2019-10-17 05:38:40 +05:30
parent f138524159
commit ac0ae1c298
2 changed files with 45 additions and 4 deletions

View File

@@ -25,6 +25,7 @@
#include "swrm_registers.h" #include "swrm_registers.h"
#include "swr-mstr-ctrl.h" #include "swr-mstr-ctrl.h"
#define SWRM_FRAME_SYNC_SEL 4000 /* 4KHz */
#define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700 #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700
#define SWRM_SYS_SUSPEND_WAIT 1 #define SWRM_SYS_SUSPEND_WAIT 1
@@ -43,6 +44,13 @@
#define ERR_AUTO_SUSPEND_TIMER_VAL 0x1 #define ERR_AUTO_SUSPEND_TIMER_VAL 0x1
#define SWRM_INTERRUPT_STATUS_MASK 0x1FDFD #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 */ /* pm runtime auto suspend timer in msecs */
static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000; static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000;
module_param(auto_suspend_timer, int, 0664); module_param(auto_suspend_timer, int, 0664);
@@ -341,6 +349,16 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm,
return ret; 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) static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
{ {
int ret = 0; int ret = 0;
@@ -591,6 +609,10 @@ retry_read:
if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) { if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
/* wait 500 us before retry on fifo read failure */ /* wait 500 us before retry on fifo read failure */
usleep_range(500, 505); 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++; retry_attempt++;
goto retry_read; goto retry_read;
} else { } else {
@@ -1093,7 +1115,9 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
{ {
u8 bank; u8 bank;
u32 value, n_row, n_col; u32 value, n_row, n_col;
u32 row = 0, col = 0;
int ret; int ret;
u8 ssp_period = 0;
struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK |
SWRM_MCP_FRAME_CTRL_BANK_COL_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) { if (enable) {
/* set col = 16 */ /* set col = 16 */
n_col = SWR_MAX_COL; n_col = SWR_MAX_COL;
col = SWRM_COL_16;
} else { } else {
/* /*
* Do not change to col = 2 if there are still active ports * 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; n_col = SWR_MIN_COL;
else col = SWRM_COL_02;
} else {
n_col = SWR_MAX_COL; n_col = SWR_MAX_COL;
col = SWRM_COL_16;
}
} }
/* Use default 50 * x, frame shape. Change based on mclk */ /* Use default 50 * x, frame shape. Change based on mclk */
if (swrm->mclk_freq == MCLK_FREQ_NATIVE) { if (swrm->mclk_freq == MCLK_FREQ_NATIVE) {
dev_dbg(swrm->dev, "setting 64 x %d frameshape\n", dev_dbg(swrm->dev, "setting 64 x %d frameshape\n",
n_col ? 16 : 2); n_col ? 16 : 2);
n_row = SWR_ROW_64; n_row = SWR_ROW_64;
row = SWRM_ROW_64;
} else { } else {
dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", dev_dbg(swrm->dev, "setting 50 x %d frameshape\n",
n_col ? 16 : 2); n_col ? 16 : 2);
n_row = SWR_ROW_50; 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 = swr_master_read(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank));
value &= (~mask); value &= (~mask);
value |= ((n_row << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | value |= ((n_row << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
(n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_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); 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__, dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__,
@@ -1732,6 +1765,7 @@ handle_irq:
case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW: case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n", dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n",
__func__); __func__);
swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
break; break;
case SWRM_INTERRUPT_STATUS_CMD_ERROR: case SWRM_INTERRUPT_STATUS_CMD_ERROR:
value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS); value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
@@ -2024,10 +2058,14 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
u32 value[SWRM_MAX_INIT_REG]; u32 value[SWRM_MAX_INIT_REG];
int len = 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 */ /* Clear Rows and Cols */
val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
(col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_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); reg[len] = SWRM_MCP_FRAME_CTRL_BANK_ADDR(0);
value[len++] = val; value[len++] = val;
@@ -2295,6 +2333,7 @@ static int swrm_probe(struct platform_device *pdev)
swrm->clk_ref_count = 0; swrm->clk_ref_count = 0;
swrm->swr_irq_wakeup_capable = 0; swrm->swr_irq_wakeup_capable = 0;
swrm->mclk_freq = MCLK_FREQ; swrm->mclk_freq = MCLK_FREQ;
swrm->bus_clk = MCLK_FREQ;
swrm->dev_up = true; swrm->dev_up = true;
swrm->state = SWR_MSTR_UP; swrm->state = SWR_MSTR_UP;
swrm->ipc_wakeup = false; swrm->ipc_wakeup = false;
@@ -2868,6 +2907,7 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
swrm_device_suspend(&pdev->dev); swrm_device_suspend(&pdev->dev);
} }
swrm->mclk_freq = *(int *)data; swrm->mclk_freq = *(int *)data;
swrm->bus_clk = swrm->mclk_freq;
mutex_unlock(&swrm->mlock); mutex_unlock(&swrm->mlock);
} }
break; break;

View File

@@ -140,6 +140,7 @@ struct swr_mstr_ctrl {
int wake_irq; int wake_irq;
int version; int version;
int mclk_freq; int mclk_freq;
int bus_clk;
u32 num_dev; u32 num_dev;
int slave_status; int slave_status;
struct swrm_mports mport_cfg[SWR_MAX_MSTR_PORT_NUM]; struct swrm_mports mport_cfg[SWR_MAX_MSTR_PORT_NUM];