|
@@ -88,6 +88,17 @@
|
|
#define SWRM_REG_GAP_START 0x2C54
|
|
#define SWRM_REG_GAP_START 0x2C54
|
|
#define SWRM_REG_GAP_END 0x4000
|
|
#define SWRM_REG_GAP_END 0x4000
|
|
|
|
|
|
|
|
+#define SAMPLING_RATE_44P1KHZ 44100
|
|
|
|
+#define SAMPLING_RATE_88P2KHZ 88200
|
|
|
|
+#define SAMPLING_RATE_176P4KHZ 176400
|
|
|
|
+#define SAMPLING_RATE_352P8KHZ 352800
|
|
|
|
+
|
|
|
|
+#define SAMPLING_RATE_48KHZ 48000
|
|
|
|
+#define SAMPLING_RATE_96KHZ 96000
|
|
|
|
+#define SAMPLING_RATE_192KHZ 192000
|
|
|
|
+#define SAMPLING_RATE_384KHZ 384000
|
|
|
|
+
|
|
|
|
+
|
|
/* pm runtime auto suspend timer in msecs */
|
|
/* pm runtime auto suspend timer in msecs */
|
|
static int auto_suspend_timer = 500;
|
|
static int auto_suspend_timer = 500;
|
|
module_param(auto_suspend_timer, int, 0664);
|
|
module_param(auto_suspend_timer, int, 0664);
|
|
@@ -103,7 +114,9 @@ enum {
|
|
enum {
|
|
enum {
|
|
MASTER_ID_WSA = 1,
|
|
MASTER_ID_WSA = 1,
|
|
MASTER_ID_RX,
|
|
MASTER_ID_RX,
|
|
- MASTER_ID_TX
|
|
|
|
|
|
+ MASTER_ID_TX,
|
|
|
|
+ MASTER_ID_WSA2,
|
|
|
|
+ MASTER_ID_BT = 5
|
|
};
|
|
};
|
|
|
|
|
|
enum {
|
|
enum {
|
|
@@ -752,7 +765,7 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
|
|
struct port_params *params;
|
|
struct port_params *params;
|
|
u32 usecase = 0;
|
|
u32 usecase = 0;
|
|
|
|
|
|
- if (swrm->master_id == MASTER_ID_TX)
|
|
|
|
|
|
+ if (swrm->master_id == MASTER_ID_TX || swrm->master_id == MASTER_ID_BT)
|
|
return 0;
|
|
return 0;
|
|
/* TODO - Send usecase information to avoid checking for master_id */
|
|
/* TODO - Send usecase information to avoid checking for master_id */
|
|
if (swrm->mport_cfg[SWRM_DSD_PARAMS_PORT].port_en &&
|
|
if (swrm->mport_cfg[SWRM_DSD_PARAMS_PORT].port_en &&
|
|
@@ -774,11 +787,44 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool swrm_is_fractional_sample_rate(u32 sample_rate)
|
|
|
|
+{
|
|
|
|
+ switch (sample_rate) {
|
|
|
|
+ case SAMPLING_RATE_44P1KHZ:
|
|
|
|
+ case SAMPLING_RATE_88P2KHZ:
|
|
|
|
+ case SAMPLING_RATE_176P4KHZ:
|
|
|
|
+ case SAMPLING_RATE_352P8KHZ:
|
|
|
|
+ return true;
|
|
|
|
+ default:
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool swrm_is_flow_ctrl_needed(struct swrm_mports *mport, u32 bus_clk)
|
|
|
|
+{
|
|
|
|
+ struct swr_port_info *port_req = NULL;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(port_req, &mport->port_req_list, list) {
|
|
|
|
+
|
|
|
|
+ if (swrm_is_fractional_sample_rate(port_req->req_ch_rate) &&
|
|
|
|
+ (bus_clk % port_req->req_ch_rate)) {
|
|
|
|
+ pr_debug("%s: flow control needed on Master port ID %d\n",
|
|
|
|
+ __func__, port_req->master_port_id);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
static int swrm_pcm_port_config(struct swr_mstr_ctrl *swrm, u8 port_num,
|
|
static int swrm_pcm_port_config(struct swr_mstr_ctrl *swrm, u8 port_num,
|
|
- u8 stream_type, bool dir, bool enable)
|
|
|
|
|
|
+ struct swrm_mports *mport, bool enable)
|
|
{
|
|
{
|
|
u16 reg_addr = 0;
|
|
u16 reg_addr = 0;
|
|
u32 reg_val = 0;
|
|
u32 reg_val = 0;
|
|
|
|
+ u8 stream_type = mport->stream_type;
|
|
|
|
+ bool dir = mport->dir;
|
|
|
|
+ u32 flow_mode = (dir) ? SWRM_DP_PORT_CONTROL__FLOW_MODE_PULL :
|
|
|
|
+ SWRM_DP_PORT_CONTROL__FLOW_MODE_PUSH;
|
|
|
|
|
|
if (!port_num || port_num > SWR_MSTR_PORT_LEN) {
|
|
if (!port_num || port_num > SWR_MSTR_PORT_LEN) {
|
|
dev_err_ratelimited(swrm->dev, "%s: invalid port: %d\n",
|
|
dev_err_ratelimited(swrm->dev, "%s: invalid port: %d\n",
|
|
@@ -824,6 +870,37 @@ static int swrm_pcm_port_config(struct swr_mstr_ctrl *swrm, u8 port_num,
|
|
swr_master_write(swrm, SWRM_COMP_FEATURE_CFG, reg_val);
|
|
swr_master_write(swrm, SWRM_COMP_FEATURE_CFG, reg_val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ dev_dbg(swrm->dev, "%s : pcm port %s, reg_val = %d, for addr %x\n",
|
|
|
|
+ __func__, enable ? "Enabled" : "disabled", reg_val, reg_addr);
|
|
|
|
+
|
|
|
|
+ if (swrm_is_flow_ctrl_needed(mport, swrm->bus_clk) && enable) {
|
|
|
|
+ /*Flow control pull/push mode. */
|
|
|
|
+ reg_addr = SWRM_DP_PORT_CONTROL(port_num);
|
|
|
|
+ reg_val = swr_master_read(swrm, reg_addr);
|
|
|
|
+ reg_val |= flow_mode;
|
|
|
|
+ swr_master_write(swrm, reg_addr, reg_val);
|
|
|
|
+
|
|
|
|
+ /*SELF GEN SUBRATE ENABLE*/
|
|
|
|
+ reg_addr = ((dir) ? SWRM_DIN_DP_PCM_PORT_CTRL(port_num) :
|
|
|
|
+ SWRM_DOUT_DP_PCM_PORT_CTRL(port_num));
|
|
|
|
+ reg_val = swr_master_read(swrm, reg_addr);
|
|
|
|
+ reg_val |= SWRM_DOUT_DP_PCM_PORT_CTRL__SELF_GEN_SUB_RATE_EN;
|
|
|
|
+ swr_master_write(swrm, reg_addr, reg_val);
|
|
|
|
+
|
|
|
|
+ /*M VALID SAMPLE*/
|
|
|
|
+ reg_addr = SWRM_DP_FLOW_CTRL_M_VALID_SAMPLE(port_num);
|
|
|
|
+ swr_master_write(swrm, reg_addr, 147);
|
|
|
|
+ /*N REPEAT PERIOD*/
|
|
|
|
+ reg_addr = SWRM_DP_FLOW_CTRL_N_REPEAT_PERIOD(port_num);
|
|
|
|
+ swr_master_write(swrm, reg_addr, 160);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!enable) {
|
|
|
|
+ /* Reset flow control configuration registers to defaults. */
|
|
|
|
+ swr_master_write(swrm, SWRM_DP_PORT_CONTROL(port_num), 0x0);
|
|
|
|
+ swr_master_write(swrm, SWRM_DP_FLOW_CTRL_M_VALID_SAMPLE(port_num), 0x1);
|
|
|
|
+ swr_master_write(swrm, SWRM_DP_FLOW_CTRL_N_REPEAT_PERIOD(port_num), 0x1);
|
|
|
|
+ }
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -917,6 +994,7 @@ static void swrm_wait_for_fifo_avail(struct swr_mstr_ctrl *swrm, int swrm_rd_wr)
|
|
dev_err_ratelimited(swrm->dev,
|
|
dev_err_ratelimited(swrm->dev,
|
|
"%s err write overflow\n", __func__);
|
|
"%s err write overflow\n", __func__);
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
|
|
static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
|
|
@@ -1180,6 +1258,12 @@ static void swrm_switch_frame_shape(struct swr_mstr_ctrl *swrm, int mclk_freq)
|
|
n_row = SWR_ROW_64;
|
|
n_row = SWR_ROW_64;
|
|
row = SWRM_ROW_64;
|
|
row = SWRM_ROW_64;
|
|
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
|
|
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
|
|
|
|
+ } else if (mclk_freq == MCLK_FREQ_12288) {
|
|
|
|
+ n_col = SWR_MIN_COL;
|
|
|
|
+ col = SWRM_COL_02;
|
|
|
|
+ n_row = SWR_ROW_64;
|
|
|
|
+ row = SWRM_ROW_64;
|
|
|
|
+ frame_sync = SWRM_FRAME_SYNC_SEL;
|
|
} else {
|
|
} else {
|
|
n_col = SWR_MIN_COL;
|
|
n_col = SWR_MIN_COL;
|
|
col = SWRM_COL_02;
|
|
col = SWRM_COL_02;
|
|
@@ -1256,6 +1340,8 @@ int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq)
|
|
bus_clk_freq = SWR_CLK_RATE_9P6MHZ;
|
|
bus_clk_freq = SWR_CLK_RATE_9P6MHZ;
|
|
} else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ)
|
|
} else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ)
|
|
bus_clk_freq = SWR_CLK_RATE_11P2896MHZ;
|
|
bus_clk_freq = SWR_CLK_RATE_11P2896MHZ;
|
|
|
|
+ else if (mclk_freq == SWR_CLK_RATE_12P288MHZ)
|
|
|
|
+ bus_clk_freq = SWR_CLK_RATE_12P288MHZ;
|
|
|
|
|
|
return bus_clk_freq;
|
|
return bus_clk_freq;
|
|
}
|
|
}
|
|
@@ -1333,8 +1419,7 @@ static void swrm_disable_ports(struct swr_master *master,
|
|
__func__, i,
|
|
__func__, i,
|
|
(SWRM_DP_PORT_CTRL_BANK((i + 1), bank)), value);
|
|
(SWRM_DP_PORT_CTRL_BANK((i + 1), bank)), value);
|
|
if (!mport->req_ch)
|
|
if (!mport->req_ch)
|
|
- swrm_pcm_port_config(swrm, (i + 1),
|
|
|
|
- mport->stream_type, mport->dir, false);
|
|
|
|
|
|
+ swrm_pcm_port_config(swrm, (i + 1), mport, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1417,6 +1502,22 @@ static int swrm_get_uc(int bus_clk)
|
|
return SWR_UC0;
|
|
return SWR_UC0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int swrm_adjust_sample_rate(u32 sample_rate)
|
|
|
|
+{
|
|
|
|
+ switch (sample_rate) {
|
|
|
|
+ case SAMPLING_RATE_44P1KHZ:
|
|
|
|
+ return SAMPLING_RATE_48KHZ;
|
|
|
|
+ case SAMPLING_RATE_88P2KHZ:
|
|
|
|
+ return SAMPLING_RATE_96KHZ;
|
|
|
|
+ case SAMPLING_RATE_176P4KHZ:
|
|
|
|
+ return SAMPLING_RATE_192KHZ;
|
|
|
|
+ case SAMPLING_RATE_352P8KHZ:
|
|
|
|
+ return SAMPLING_RATE_384KHZ;
|
|
|
|
+ default:
|
|
|
|
+ return sample_rate;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
|
|
static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
|
|
struct swrm_mports *mport,
|
|
struct swrm_mports *mport,
|
|
struct swr_port_info *port_req)
|
|
struct swr_port_info *port_req)
|
|
@@ -1441,6 +1542,20 @@ static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
|
|
port_req->blk_pack_mode = 0xFF;
|
|
port_req->blk_pack_mode = 0xFF;
|
|
port_req->blk_grp_count = 0xFF;
|
|
port_req->blk_grp_count = 0xFF;
|
|
port_req->lane_ctrl = swrm->pp[uc][port_id_offset].lane_ctrl;
|
|
port_req->lane_ctrl = swrm->pp[uc][port_id_offset].lane_ctrl;
|
|
|
|
+ } else if (swrm->master_id == MASTER_ID_BT) {
|
|
|
|
+ port_req->sinterval =
|
|
|
|
+ ((swrm->bus_clk * 2) / port_req->ch_rate) - 1;
|
|
|
|
+ if (mport->dir == 0)
|
|
|
|
+ port_req->offset1 = 0;
|
|
|
|
+ else
|
|
|
|
+ port_req->offset1 = 0x14;
|
|
|
|
+ port_req->offset2 = 0x00;
|
|
|
|
+ port_req->hstart = 1;
|
|
|
|
+ port_req->hstop = 0xF;
|
|
|
|
+ port_req->word_length = 0xF;
|
|
|
|
+ port_req->blk_pack_mode = 0xFF;
|
|
|
|
+ port_req->blk_grp_count = 0xFF;
|
|
|
|
+ port_req->lane_ctrl = 0;
|
|
} else {
|
|
} else {
|
|
/* copy master port config to slave */
|
|
/* copy master port config to slave */
|
|
port_req->sinterval = mport->sinterval;
|
|
port_req->sinterval = mport->sinterval;
|
|
@@ -1463,6 +1578,7 @@ static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
|
|
return;
|
|
return;
|
|
port_req->offset1 = swrm->pp[uc][port_id_offset].offset1;
|
|
port_req->offset1 = swrm->pp[uc][port_id_offset].offset1;
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
|
|
static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
|
|
@@ -1495,8 +1611,8 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
|
|
if (!mport->port_en)
|
|
if (!mport->port_en)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- swrm_pcm_port_config(swrm, (i + 1),
|
|
|
|
- mport->stream_type, mport->dir, true);
|
|
|
|
|
|
+ swrm_pcm_port_config(swrm, (i + 1), mport, true);
|
|
|
|
+
|
|
j = 0;
|
|
j = 0;
|
|
lane_ctrl = 0;
|
|
lane_ctrl = 0;
|
|
sinterval = 0xFFFF;
|
|
sinterval = 0xFFFF;
|
|
@@ -1537,14 +1653,13 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
|
|
bank));
|
|
bank));
|
|
|
|
|
|
/* Only wite MSB if SI > 0xFF */
|
|
/* Only wite MSB if SI > 0xFF */
|
|
- if (port_req->sinterval > 0xFF) {
|
|
|
|
- reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
- val[len++] = SWR_REG_VAL_PACK(
|
|
|
|
- (port_req->sinterval >> 8) & 0xFF,
|
|
|
|
- port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
- SWRS_DP_SAMPLE_CONTROL_2_BANK(slv_id,
|
|
|
|
- bank));
|
|
|
|
- }
|
|
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] = SWR_REG_VAL_PACK(
|
|
|
|
+ (port_req->sinterval >> 8) & 0xFF,
|
|
|
|
+ port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
+ SWRS_DP_SAMPLE_CONTROL_2_BANK(slv_id,
|
|
|
|
+ bank));
|
|
|
|
+
|
|
if (port_req->offset1 != SWR_INVALID_PARAM) {
|
|
if (port_req->offset1 != SWR_INVALID_PARAM) {
|
|
reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
val[len++] = SWR_REG_VAL_PACK(port_req->offset1,
|
|
val[len++] = SWR_REG_VAL_PACK(port_req->offset1,
|
|
@@ -1604,12 +1719,61 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
|
|
SWRS_DP_LANE_CONTROL_BANK(
|
|
SWRS_DP_LANE_CONTROL_BANK(
|
|
slv_id, bank));
|
|
slv_id, bank));
|
|
}
|
|
}
|
|
|
|
+ if (port_req->req_ch_rate != port_req->ch_rate) {
|
|
|
|
+ dev_dbg(swrm->dev, "requested sample rate is fractional");
|
|
|
|
+ if (mport->dir == 0) {
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] =
|
|
|
|
+ SWR_REG_VAL_PACK(1,
|
|
|
|
+ port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
+ SWRS_DP_PORT_CONTROL(
|
|
|
|
+ slv_id));
|
|
|
|
+ } else if (mport->dir == 1) {
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] =
|
|
|
|
+ SWR_REG_VAL_PACK(2,
|
|
|
|
+ port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
+ SWRS_DP_PORT_CONTROL(
|
|
|
|
+ slv_id));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] = SWR_REG_VAL_PACK(4,
|
|
|
|
+ port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
+ SWRS_DPn_FEATURE_EN(port_req->slave_port_id));
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] = SWR_REG_VAL_PACK(1,
|
|
|
|
+ port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
+ SWRS_DPn_FLOW_CTRL_N_REPEAT_PERIOD(
|
|
|
|
+ port_req->slave_port_id));
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] = SWR_REG_VAL_PACK(1,
|
|
|
|
+ port_req->dev_num, get_cmd_id(swrm),
|
|
|
|
+ SWRS_DPn_FLOW_CTRL_M_VALID_SAMPLE(
|
|
|
|
+ port_req->slave_port_id));
|
|
|
|
+ } else {
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] = SWR_REG_VAL_PACK(0, port_req->dev_num,
|
|
|
|
+ get_cmd_id(swrm), SWRS_DP_PORT_CONTROL(slv_id));
|
|
|
|
+
|
|
|
|
+ reg[len] = SWRM_CMD_FIFO_WR_CMD(swrm->ee_val);
|
|
|
|
+ val[len++] = SWR_REG_VAL_PACK(0, port_req->dev_num,
|
|
|
|
+ get_cmd_id(swrm),
|
|
|
|
+ SWRS_DPn_FEATURE_EN(port_req->slave_port_id));
|
|
|
|
+ }
|
|
|
|
+
|
|
port_req->ch_en = port_req->req_ch;
|
|
port_req->ch_en = port_req->req_ch;
|
|
dev_offset[port_req->dev_num] = port_req->offset1;
|
|
dev_offset[port_req->dev_num] = port_req->offset1;
|
|
}
|
|
}
|
|
if (swrm->master_id == MASTER_ID_TX) {
|
|
if (swrm->master_id == MASTER_ID_TX) {
|
|
mport->sinterval = sinterval;
|
|
mport->sinterval = sinterval;
|
|
mport->lane_ctrl = lane_ctrl;
|
|
mport->lane_ctrl = lane_ctrl;
|
|
|
|
+ } else if (swrm->master_id == MASTER_ID_BT) {
|
|
|
|
+ mport->sinterval = sinterval;
|
|
|
|
+ mport->lane_ctrl = lane_ctrl;
|
|
|
|
+ mport->word_length = 0xF;
|
|
|
|
+ mport->hstart = 1;
|
|
|
|
+ mport->hstop = 0xF;
|
|
}
|
|
}
|
|
value = ((mport->req_ch)
|
|
value = ((mport->req_ch)
|
|
<< SWRM_DP_PORT_CTRL_EN_CHAN_SHFT);
|
|
<< SWRM_DP_PORT_CTRL_EN_CHAN_SHFT);
|
|
@@ -1789,6 +1953,11 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
|
|
n_row = SWR_ROW_64;
|
|
n_row = SWR_ROW_64;
|
|
row = SWRM_ROW_64;
|
|
row = SWRM_ROW_64;
|
|
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
|
|
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
|
|
|
|
+ } else if (swrm->mclk_freq == MCLK_FREQ_12288) {
|
|
|
|
+ dev_dbg(swrm->dev, "setting 64 x %d frameshape\n", col);
|
|
|
|
+ n_row = SWR_ROW_64;
|
|
|
|
+ row = SWRM_ROW_64;
|
|
|
|
+ frame_sync = SWRM_FRAME_SYNC_SEL;
|
|
} else {
|
|
} else {
|
|
dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", col);
|
|
dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", col);
|
|
n_row = SWR_ROW_50;
|
|
n_row = SWR_ROW_50;
|
|
@@ -1895,6 +2064,9 @@ static int swrm_connect_port(struct swr_master *master,
|
|
port_req->slave_port_id = portinfo->port_id[i];
|
|
port_req->slave_port_id = portinfo->port_id[i];
|
|
port_req->num_ch = portinfo->num_ch[i];
|
|
port_req->num_ch = portinfo->num_ch[i];
|
|
port_req->ch_rate = portinfo->ch_rate[i];
|
|
port_req->ch_rate = portinfo->ch_rate[i];
|
|
|
|
+ port_req->req_ch_rate = portinfo->ch_rate[i];
|
|
|
|
+ if (swrm_is_fractional_sample_rate(port_req->ch_rate))
|
|
|
|
+ port_req->ch_rate = swrm_adjust_sample_rate(port_req->ch_rate);
|
|
port_req->ch_en = 0;
|
|
port_req->ch_en = 0;
|
|
port_req->master_port_id = mstr_port_id;
|
|
port_req->master_port_id = mstr_port_id;
|
|
list_add(&port_req->list, &mport->port_req_list);
|
|
list_add(&port_req->list, &mport->port_req_list);
|
|
@@ -1902,10 +2074,10 @@ static int swrm_connect_port(struct swr_master *master,
|
|
port_req->req_ch |= portinfo->ch_en[i];
|
|
port_req->req_ch |= portinfo->ch_en[i];
|
|
|
|
|
|
dev_dbg(&master->dev,
|
|
dev_dbg(&master->dev,
|
|
- "%s: mstr port %d, slv port %d ch_rate %d num_ch %d\n",
|
|
|
|
|
|
+ "%s: mstr port %d, slv port %d ch_rate %d num_ch %d req_ch_rate %d\n",
|
|
__func__, port_req->master_port_id,
|
|
__func__, port_req->master_port_id,
|
|
port_req->slave_port_id, port_req->ch_rate,
|
|
port_req->slave_port_id, port_req->ch_rate,
|
|
- port_req->num_ch);
|
|
|
|
|
|
+ port_req->num_ch, port_req->req_ch_rate);
|
|
/* Put the port req on master port */
|
|
/* Put the port req on master port */
|
|
mport = &(swrm->mport_cfg[mstr_port_id]);
|
|
mport = &(swrm->mport_cfg[mstr_port_id]);
|
|
mport->port_en = true;
|
|
mport->port_en = true;
|
|
@@ -2589,6 +2761,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
|
|
u32 val;
|
|
u32 val;
|
|
u8 row_ctrl = SWR_ROW_50;
|
|
u8 row_ctrl = SWR_ROW_50;
|
|
u8 col_ctrl = SWR_MIN_COL;
|
|
u8 col_ctrl = SWR_MIN_COL;
|
|
|
|
+ u8 num_rows = SWRM_ROW_50;
|
|
u8 ssp_period = 1;
|
|
u8 ssp_period = 1;
|
|
u8 retry_cmd_num = 3;
|
|
u8 retry_cmd_num = 3;
|
|
u32 reg[SWRM_MAX_INIT_REG];
|
|
u32 reg[SWRM_MAX_INIT_REG];
|
|
@@ -2612,7 +2785,13 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
|
|
__func__, temp);
|
|
__func__, temp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50,
|
|
|
|
|
|
+
|
|
|
|
+ if (swrm->master_id == MASTER_ID_BT) {
|
|
|
|
+ row_ctrl = SWR_ROW_64;
|
|
|
|
+ num_rows = SWRM_ROW_64;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ssp_period = swrm_get_ssp_period(swrm, num_rows,
|
|
SWRM_COL_02, SWRM_FRAME_SYNC_SEL);
|
|
SWRM_COL_02, SWRM_FRAME_SYNC_SEL);
|
|
dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
|
|
dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
|
|
|
|
|
|
@@ -2644,10 +2823,12 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
|
|
reg[len] = SWRM_LINK_MANAGER_EE;
|
|
reg[len] = SWRM_LINK_MANAGER_EE;
|
|
value[len++] = swrm->ee_val;
|
|
value[len++] = swrm->ee_val;
|
|
}
|
|
}
|
|
-#ifdef CONFIG_SWRM_VER_2P0
|
|
|
|
- reg[len] = SWRM_CLK_CTRL(swrm->ee_val);
|
|
|
|
- value[len++] = 0x01;
|
|
|
|
-#endif
|
|
|
|
|
|
+
|
|
|
|
+ if (swrm->master_id == MASTER_ID_BT) {
|
|
|
|
+ /* Enable self_gen_frame_sync. */
|
|
|
|
+ reg[len] = SWRM_SELF_GENERATE_FRAME_SYNC;
|
|
|
|
+ value[len++] = 0x01;
|
|
|
|
+ }
|
|
|
|
|
|
#ifdef CONFIG_SWRM_VER_1P7
|
|
#ifdef CONFIG_SWRM_VER_1P7
|
|
reg[len] = SWRM_MCP_BUS_CTRL;
|
|
reg[len] = SWRM_MCP_BUS_CTRL;
|
|
@@ -2669,10 +2850,14 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
|
|
reg[len] = SWRM_INTERRUPT_EN(swrm->ee_val);
|
|
reg[len] = SWRM_INTERRUPT_EN(swrm->ee_val);
|
|
value[len++] = swrm->intr_mask;
|
|
value[len++] = swrm->intr_mask;
|
|
|
|
|
|
-
|
|
|
|
reg[len] = SWRM_COMP_CFG;
|
|
reg[len] = SWRM_COMP_CFG;
|
|
value[len++] = 0x03;
|
|
value[len++] = 0x03;
|
|
|
|
|
|
|
|
+#ifdef CONFIG_SWRM_VER_2P0
|
|
|
|
+ reg[len] = SWRM_CLK_CTRL(swrm->ee_val);
|
|
|
|
+ value[len++] = 0x01;
|
|
|
|
+#endif
|
|
|
|
+
|
|
swr_master_bulk_write(swrm, reg, value, len);
|
|
swr_master_bulk_write(swrm, reg, value, len);
|
|
|
|
|
|
if (!swrm_check_link_status(swrm, 0x1)) {
|
|
if (!swrm_check_link_status(swrm, 0x1)) {
|
|
@@ -2908,7 +3093,11 @@ static int swrm_probe(struct platform_device *pdev)
|
|
goto err_pdata_fail;
|
|
goto err_pdata_fail;
|
|
}
|
|
}
|
|
swrm->port_mapping[port_num][ch_iter].port_type = port_type;
|
|
swrm->port_mapping[port_num][ch_iter].port_type = port_type;
|
|
- swrm->port_mapping[port_num][ch_iter++].ch_mask = ch_mask;
|
|
|
|
|
|
+
|
|
|
|
+ if (swrm->master_id == MASTER_ID_BT)
|
|
|
|
+ swrm->port_mapping[port_num][ch_iter++].ch_mask = 1;
|
|
|
|
+ else
|
|
|
|
+ swrm->port_mapping[port_num][ch_iter++].ch_mask = ch_mask;
|
|
old_port_num = port_num;
|
|
old_port_num = port_num;
|
|
}
|
|
}
|
|
devm_kfree(&pdev->dev, temp);
|
|
devm_kfree(&pdev->dev, temp);
|
|
@@ -2942,6 +3131,10 @@ static int swrm_probe(struct platform_device *pdev)
|
|
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->bus_clk = MCLK_FREQ;
|
|
|
|
+ if (swrm->master_id == MASTER_ID_BT) {
|
|
|
|
+ swrm->mclk_freq = MCLK_FREQ_12288;
|
|
|
|
+ swrm->bus_clk = MCLK_FREQ_12288;
|
|
|
|
+ }
|
|
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;
|
|
@@ -2970,9 +3163,12 @@ static int swrm_probe(struct platform_device *pdev)
|
|
for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++) {
|
|
for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++) {
|
|
INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
|
|
INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
|
|
|
|
|
|
- if (swrm->master_id == MASTER_ID_TX) {
|
|
|
|
|
|
+ if (swrm->master_id == MASTER_ID_TX || swrm->master_id == MASTER_ID_BT) {
|
|
swrm->mport_cfg[i].sinterval = 0xFFFF;
|
|
swrm->mport_cfg[i].sinterval = 0xFFFF;
|
|
- swrm->mport_cfg[i].offset1 = 0x00;
|
|
|
|
|
|
+ if (swrm->master_id == MASTER_ID_BT && i > 3)
|
|
|
|
+ swrm->mport_cfg[i].offset1 = 0x14;
|
|
|
|
+ else
|
|
|
|
+ swrm->mport_cfg[i].offset1 = 0x00;
|
|
swrm->mport_cfg[i].offset2 = 0x00;
|
|
swrm->mport_cfg[i].offset2 = 0x00;
|
|
swrm->mport_cfg[i].hstart = 0xFF;
|
|
swrm->mport_cfg[i].hstart = 0xFF;
|
|
swrm->mport_cfg[i].hstop = 0xFF;
|
|
swrm->mport_cfg[i].hstop = 0xFF;
|
|
@@ -2980,8 +3176,12 @@ static int swrm_probe(struct platform_device *pdev)
|
|
swrm->mport_cfg[i].blk_grp_count = 0xFF;
|
|
swrm->mport_cfg[i].blk_grp_count = 0xFF;
|
|
swrm->mport_cfg[i].word_length = 0xFF;
|
|
swrm->mport_cfg[i].word_length = 0xFF;
|
|
swrm->mport_cfg[i].lane_ctrl = 0x00;
|
|
swrm->mport_cfg[i].lane_ctrl = 0x00;
|
|
- swrm->mport_cfg[i].dir = 0x00;
|
|
|
|
- swrm->mport_cfg[i].stream_type = 0x00;
|
|
|
|
|
|
+ if (swrm->master_id == MASTER_ID_BT && i > 3)
|
|
|
|
+ swrm->mport_cfg[i].dir = 0x01;
|
|
|
|
+ else
|
|
|
|
+ swrm->mport_cfg[i].dir = 0x00;
|
|
|
|
+ swrm->mport_cfg[i].stream_type =
|
|
|
|
+ (swrm->master_id == MASTER_ID_TX) ? 0x00 : 0x01;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (of_property_read_u32(pdev->dev.of_node,
|
|
if (of_property_read_u32(pdev->dev.of_node,
|
|
@@ -3456,7 +3656,7 @@ static int swrm_runtime_suspend(struct device *dev)
|
|
/* Mask bus clash interrupt */
|
|
/* Mask bus clash interrupt */
|
|
swrm->intr_mask &= ~((u32)0x08);
|
|
swrm->intr_mask &= ~((u32)0x08);
|
|
swr_master_write(swrm, SWRM_INTERRUPT_EN(swrm->ee_val),
|
|
swr_master_write(swrm, SWRM_INTERRUPT_EN(swrm->ee_val),
|
|
- swrm->intr_mask);
|
|
|
|
|
|
+ swrm->intr_mask);
|
|
mutex_unlock(&swrm->reslock);
|
|
mutex_unlock(&swrm->reslock);
|
|
/* clock stop sequence */
|
|
/* clock stop sequence */
|
|
swrm_cmd_fifo_wr_cmd(swrm, 0x2, 0xF, 0xF,
|
|
swrm_cmd_fifo_wr_cmd(swrm, 0x2, 0xF, 0xF,
|
|
@@ -4137,7 +4337,7 @@ static struct platform_driver swr_mstr_driver = {
|
|
.probe = swrm_probe,
|
|
.probe = swrm_probe,
|
|
.remove = swrm_remove,
|
|
.remove = swrm_remove,
|
|
.driver = {
|
|
.driver = {
|
|
- .name = SWR_WCD_NAME,
|
|
|
|
|
|
+ .name = SWR_NAME,
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
.pm = &swrm_dev_pm_ops,
|
|
.pm = &swrm_dev_pm_ops,
|
|
.of_match_table = swrm_dt_match,
|
|
.of_match_table = swrm_dt_match,
|